mirror of
https://github.com/tbsdtv/linux_media.git
synced 2025-07-23 12:43:29 +02:00
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:
@@ -5,7 +5,7 @@ Description: It is possible to switch the cpi setting of the mouse with the
|
|||||||
press of a button.
|
press of a button.
|
||||||
When read, this file returns the raw number of the actual cpi
|
When read, this file returns the raw number of the actual cpi
|
||||||
setting reported by the mouse. This number has to be further
|
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
|
VALUE DPI
|
||||||
1 400
|
1 400
|
||||||
|
@@ -1,5 +1,4 @@
|
|||||||
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/
|
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/asic_health
|
||||||
asic_health
|
|
||||||
|
|
||||||
Date: June 2018
|
Date: June 2018
|
||||||
KernelVersion: 4.19
|
KernelVersion: 4.19
|
||||||
@@ -9,9 +8,8 @@ Description: This file shows ASIC health status. The possible values are:
|
|||||||
|
|
||||||
The files are read only.
|
The files are read only.
|
||||||
|
|
||||||
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/
|
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/cpld1_version
|
||||||
cpld1_version
|
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/cpld2_version
|
||||||
cpld2_version
|
|
||||||
Date: June 2018
|
Date: June 2018
|
||||||
KernelVersion: 4.19
|
KernelVersion: 4.19
|
||||||
Contact: Vadim Pasternak <vadimpmellanox.com>
|
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.
|
The files are read only.
|
||||||
|
|
||||||
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/
|
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/fan_dir
|
||||||
fan_dir
|
|
||||||
|
|
||||||
Date: December 2018
|
Date: December 2018
|
||||||
KernelVersion: 5.0
|
KernelVersion: 5.0
|
||||||
@@ -32,8 +29,7 @@ Description: This file shows the system fans direction:
|
|||||||
|
|
||||||
The files are read only.
|
The files are read only.
|
||||||
|
|
||||||
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/
|
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/jtag_enable
|
||||||
jtag_enable
|
|
||||||
|
|
||||||
Date: November 2018
|
Date: November 2018
|
||||||
KernelVersion: 5.0
|
KernelVersion: 5.0
|
||||||
@@ -43,8 +39,7 @@ Description: These files show with which CPLD versions have been burned
|
|||||||
|
|
||||||
The files are read only.
|
The files are read only.
|
||||||
|
|
||||||
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/
|
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/jtag_enable
|
||||||
jtag_enable
|
|
||||||
|
|
||||||
Date: November 2018
|
Date: November 2018
|
||||||
KernelVersion: 5.0
|
KernelVersion: 5.0
|
||||||
@@ -87,16 +82,15 @@ Description: These files allow asserting system power cycling, switching
|
|||||||
|
|
||||||
The files are write only.
|
The files are write only.
|
||||||
|
|
||||||
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/
|
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/reset_aux_pwr_or_ref
|
||||||
reset_aux_pwr_or_ref
|
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/reset_asic_thermal
|
||||||
reset_asic_thermal
|
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/reset_hotswap_or_halt
|
||||||
reset_hotswap_or_halt
|
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/reset_hotswap_or_wd
|
||||||
reset_hotswap_or_wd
|
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/reset_fw_reset
|
||||||
reset_fw_reset
|
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/reset_long_pb
|
||||||
reset_long_pb
|
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/reset_main_pwr_fail
|
||||||
reset_main_pwr_fail
|
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/reset_short_pb
|
||||||
reset_short_pb
|
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/reset_sw_reset
|
||||||
reset_sw_reset
|
|
||||||
Date: June 2018
|
Date: June 2018
|
||||||
KernelVersion: 4.19
|
KernelVersion: 4.19
|
||||||
Contact: Vadim Pasternak <vadimpmellanox.com>
|
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.
|
The files are read only.
|
||||||
|
|
||||||
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/
|
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/reset_comex_pwr_fail
|
||||||
reset_comex_pwr_fail
|
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/reset_from_comex
|
||||||
reset_from_comex
|
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/reset_system
|
||||||
reset_system
|
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/reset_voltmon_upgrade_fail
|
||||||
reset_voltmon_upgrade_fail
|
|
||||||
|
|
||||||
Date: November 2018
|
Date: November 2018
|
||||||
KernelVersion: 5.0
|
KernelVersion: 5.0
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
Where: /sys/fs/pstore/... (or /dev/pstore/...)
|
What: /sys/fs/pstore/... (or /dev/pstore/...)
|
||||||
Date: March 2011
|
Date: March 2011
|
||||||
KernelVersion: 2.6.39
|
KernelVersion: 2.6.39
|
||||||
Contact: tony.luck@intel.com
|
Contact: tony.luck@intel.com
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
Where: /sys/bus/event_source/devices/<dev>/format
|
What: /sys/bus/event_source/devices/<dev>/format
|
||||||
Date: January 2012
|
Date: January 2012
|
||||||
KernelVersion: 3.3
|
KernelVersion: 3.3
|
||||||
Contact: Jiri Olsa <jolsa@redhat.com>
|
Contact: Jiri Olsa <jolsa@redhat.com>
|
||||||
|
@@ -1,18 +1,18 @@
|
|||||||
Where: /sys/bus/i2c/devices/.../heading0_input
|
What: /sys/bus/i2c/devices/.../heading0_input
|
||||||
Date: April 2010
|
Date: April 2010
|
||||||
KernelVersion: 2.6.36?
|
KernelVersion: 2.6.36?
|
||||||
Contact: alan.cox@intel.com
|
Contact: alan.cox@intel.com
|
||||||
Description: Reports the current heading from the compass as a floating
|
Description: Reports the current heading from the compass as a floating
|
||||||
point value in degrees.
|
point value in degrees.
|
||||||
|
|
||||||
Where: /sys/bus/i2c/devices/.../power_state
|
What: /sys/bus/i2c/devices/.../power_state
|
||||||
Date: April 2010
|
Date: April 2010
|
||||||
KernelVersion: 2.6.36?
|
KernelVersion: 2.6.36?
|
||||||
Contact: alan.cox@intel.com
|
Contact: alan.cox@intel.com
|
||||||
Description: Sets the power state of the device. 0 sets the device into
|
Description: Sets the power state of the device. 0 sets the device into
|
||||||
sleep mode, 1 wakes it up.
|
sleep mode, 1 wakes it up.
|
||||||
|
|
||||||
Where: /sys/bus/i2c/devices/.../calibration
|
What: /sys/bus/i2c/devices/.../calibration
|
||||||
Date: April 2010
|
Date: April 2010
|
||||||
KernelVersion: 2.6.36?
|
KernelVersion: 2.6.36?
|
||||||
Contact: alan.cox@intel.com
|
Contact: alan.cox@intel.com
|
||||||
|
@@ -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
|
Date: January 2017
|
||||||
KernelVersion: 4.11
|
KernelVersion: 4.11
|
||||||
Contact: linux-iio@vger.kernel.org
|
Contact: linux-iio@vger.kernel.org
|
||||||
@@ -6,7 +6,7 @@ Description:
|
|||||||
Show or set the gain boost of the amp, from 0-31 range.
|
Show or set the gain boost of the amp, from 0-31 range.
|
||||||
default 31
|
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
|
Date: January 2017
|
||||||
KernelVersion: 4.11
|
KernelVersion: 4.11
|
||||||
Contact: linux-iio@vger.kernel.org
|
Contact: linux-iio@vger.kernel.org
|
||||||
|
@@ -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
|
Date: March 2014
|
||||||
KernelVersion: 3.15
|
KernelVersion: 3.15
|
||||||
Contact: Matt Ranostay <matt.ranostay@konsulko.com>
|
Contact: Matt Ranostay <matt.ranostay@konsulko.com>
|
||||||
@@ -6,7 +6,7 @@ Description:
|
|||||||
Get the current distance in meters of storm (1km steps)
|
Get the current distance in meters of storm (1km steps)
|
||||||
1000-40000 = distance in meters
|
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
|
Date: March 2014
|
||||||
KernelVersion: 3.15
|
KernelVersion: 3.15
|
||||||
Contact: Matt Ranostay <matt.ranostay@konsulko.com>
|
Contact: Matt Ranostay <matt.ranostay@konsulko.com>
|
||||||
|
@@ -9,7 +9,7 @@ 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
|
problematic endpoint itself (which may report all counters as 0 as it never
|
||||||
saw any problems).
|
saw any problems).
|
||||||
|
|
||||||
Where: /sys/bus/pci/devices/<dev>/aer_dev_correctable
|
What: /sys/bus/pci/devices/<dev>/aer_dev_correctable
|
||||||
Date: July 2018
|
Date: July 2018
|
||||||
KernelVersion: 4.19.0
|
KernelVersion: 4.19.0
|
||||||
Contact: linux-pci@vger.kernel.org, rajatja@google.com
|
Contact: linux-pci@vger.kernel.org, rajatja@google.com
|
||||||
@@ -31,7 +31,7 @@ Header Log Overflow 0
|
|||||||
TOTAL_ERR_COR 2
|
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
|
Date: July 2018
|
||||||
KernelVersion: 4.19.0
|
KernelVersion: 4.19.0
|
||||||
Contact: linux-pci@vger.kernel.org, rajatja@google.com
|
Contact: linux-pci@vger.kernel.org, rajatja@google.com
|
||||||
@@ -62,7 +62,7 @@ TLP Prefix Blocked Error 0
|
|||||||
TOTAL_ERR_FATAL 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
|
Date: July 2018
|
||||||
KernelVersion: 4.19.0
|
KernelVersion: 4.19.0
|
||||||
Contact: linux-pci@vger.kernel.org, rajatja@google.com
|
Contact: linux-pci@vger.kernel.org, rajatja@google.com
|
||||||
@@ -103,19 +103,19 @@ 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
|
device, so these counters include them and are thus cumulative of all the error
|
||||||
messages on the PCI hierarchy originating at that root port.
|
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
|
Date: July 2018
|
||||||
KernelVersion: 4.19.0
|
KernelVersion: 4.19.0
|
||||||
Contact: linux-pci@vger.kernel.org, rajatja@google.com
|
Contact: linux-pci@vger.kernel.org, rajatja@google.com
|
||||||
Description: Total number of ERR_COR messages reported to rootport.
|
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
|
Date: July 2018
|
||||||
KernelVersion: 4.19.0
|
KernelVersion: 4.19.0
|
||||||
Contact: linux-pci@vger.kernel.org, rajatja@google.com
|
Contact: linux-pci@vger.kernel.org, rajatja@google.com
|
||||||
Description: Total number of ERR_FATAL messages reported to rootport.
|
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
|
Date: July 2018
|
||||||
KernelVersion: 4.19.0
|
KernelVersion: 4.19.0
|
||||||
Contact: linux-pci@vger.kernel.org, rajatja@google.com
|
Contact: linux-pci@vger.kernel.org, rajatja@google.com
|
||||||
|
@@ -1,66 +1,66 @@
|
|||||||
Where: /sys/bus/pci/devices/<dev>/ccissX/cXdY/model
|
What: /sys/bus/pci/devices/<dev>/ccissX/cXdY/model
|
||||||
Date: March 2009
|
Date: March 2009
|
||||||
KernelVersion: 2.6.30
|
KernelVersion: 2.6.30
|
||||||
Contact: iss_storagedev@hp.com
|
Contact: iss_storagedev@hp.com
|
||||||
Description: Displays the SCSI INQUIRY page 0 model for logical drive
|
Description: Displays the SCSI INQUIRY page 0 model for logical drive
|
||||||
Y of controller X.
|
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
|
Date: March 2009
|
||||||
KernelVersion: 2.6.30
|
KernelVersion: 2.6.30
|
||||||
Contact: iss_storagedev@hp.com
|
Contact: iss_storagedev@hp.com
|
||||||
Description: Displays the SCSI INQUIRY page 0 revision for logical
|
Description: Displays the SCSI INQUIRY page 0 revision for logical
|
||||||
drive Y of controller X.
|
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
|
Date: March 2009
|
||||||
KernelVersion: 2.6.30
|
KernelVersion: 2.6.30
|
||||||
Contact: iss_storagedev@hp.com
|
Contact: iss_storagedev@hp.com
|
||||||
Description: Displays the SCSI INQUIRY page 83 serial number for logical
|
Description: Displays the SCSI INQUIRY page 83 serial number for logical
|
||||||
drive Y of controller X.
|
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
|
Date: March 2009
|
||||||
KernelVersion: 2.6.30
|
KernelVersion: 2.6.30
|
||||||
Contact: iss_storagedev@hp.com
|
Contact: iss_storagedev@hp.com
|
||||||
Description: Displays the SCSI INQUIRY page 0 vendor for logical drive
|
Description: Displays the SCSI INQUIRY page 0 vendor for logical drive
|
||||||
Y of controller X.
|
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
|
Date: March 2009
|
||||||
KernelVersion: 2.6.30
|
KernelVersion: 2.6.30
|
||||||
Contact: iss_storagedev@hp.com
|
Contact: iss_storagedev@hp.com
|
||||||
Description: A symbolic link to /sys/block/cciss!cXdY
|
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
|
Date: August 2009
|
||||||
KernelVersion: 2.6.31
|
KernelVersion: 2.6.31
|
||||||
Contact: iss_storagedev@hp.com
|
Contact: iss_storagedev@hp.com
|
||||||
Description: Kicks of a rescan of the controller to discover logical
|
Description: Kicks of a rescan of the controller to discover logical
|
||||||
drive topology changes.
|
drive topology changes.
|
||||||
|
|
||||||
Where: /sys/bus/pci/devices/<dev>/ccissX/cXdY/lunid
|
What: /sys/bus/pci/devices/<dev>/ccissX/cXdY/lunid
|
||||||
Date: August 2009
|
Date: August 2009
|
||||||
KernelVersion: 2.6.31
|
KernelVersion: 2.6.31
|
||||||
Contact: iss_storagedev@hp.com
|
Contact: iss_storagedev@hp.com
|
||||||
Description: Displays the 8-byte LUN ID used to address logical
|
Description: Displays the 8-byte LUN ID used to address logical
|
||||||
drive Y of controller X.
|
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
|
Date: August 2009
|
||||||
KernelVersion: 2.6.31
|
KernelVersion: 2.6.31
|
||||||
Contact: iss_storagedev@hp.com
|
Contact: iss_storagedev@hp.com
|
||||||
Description: Displays the RAID level of logical drive Y of
|
Description: Displays the RAID level of logical drive Y of
|
||||||
controller X.
|
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
|
Date: August 2009
|
||||||
KernelVersion: 2.6.31
|
KernelVersion: 2.6.31
|
||||||
Contact: iss_storagedev@hp.com
|
Contact: iss_storagedev@hp.com
|
||||||
Description: Displays the usage count (number of opens) of logical drive Y
|
Description: Displays the usage count (number of opens) of logical drive Y
|
||||||
of controller X.
|
of controller X.
|
||||||
|
|
||||||
Where: /sys/bus/pci/devices/<dev>/ccissX/resettable
|
What: /sys/bus/pci/devices/<dev>/ccissX/resettable
|
||||||
Date: February 2011
|
Date: February 2011
|
||||||
KernelVersion: 2.6.38
|
KernelVersion: 2.6.38
|
||||||
Contact: iss_storagedev@hp.com
|
Contact: iss_storagedev@hp.com
|
||||||
@@ -71,7 +71,7 @@ Description: Value of 1 indicates the controller can honor the reset_devices
|
|||||||
a dump device, as kdump requires resetting the device in order
|
a dump device, as kdump requires resetting the device in order
|
||||||
to work reliably.
|
to work reliably.
|
||||||
|
|
||||||
Where: /sys/bus/pci/devices/<dev>/ccissX/transport_mode
|
What: /sys/bus/pci/devices/<dev>/ccissX/transport_mode
|
||||||
Date: July 2011
|
Date: July 2011
|
||||||
KernelVersion: 3.0
|
KernelVersion: 3.0
|
||||||
Contact: iss_storagedev@hp.com
|
Contact: iss_storagedev@hp.com
|
||||||
|
@@ -1,12 +1,12 @@
|
|||||||
Where: /sys/bus/usb/.../powered
|
What: /sys/bus/usb/.../powered
|
||||||
Date: August 2008
|
Date: August 2008
|
||||||
KernelVersion: 2.6.26
|
KernelVersion: 2.6.26
|
||||||
Contact: Harrison Metzger <harrisonmetz@gmail.com>
|
Contact: Harrison Metzger <harrisonmetz@gmail.com>
|
||||||
Description: Controls whether the device's display will powered.
|
Description: Controls whether the device's display will powered.
|
||||||
A value of 0 is off and a non-zero value is on.
|
A value of 0 is off and a non-zero value is on.
|
||||||
|
|
||||||
Where: /sys/bus/usb/.../mode_msb
|
What: /sys/bus/usb/.../mode_msb
|
||||||
Where: /sys/bus/usb/.../mode_lsb
|
What: /sys/bus/usb/.../mode_lsb
|
||||||
Date: August 2008
|
Date: August 2008
|
||||||
KernelVersion: 2.6.26
|
KernelVersion: 2.6.26
|
||||||
Contact: Harrison Metzger <harrisonmetz@gmail.com>
|
Contact: Harrison Metzger <harrisonmetz@gmail.com>
|
||||||
@@ -16,7 +16,7 @@ Description: Controls the devices display mode.
|
|||||||
for an 8 character display the values are
|
for an 8 character display the values are
|
||||||
MSB 0x08; LSB 0xFF.
|
MSB 0x08; LSB 0xFF.
|
||||||
|
|
||||||
Where: /sys/bus/usb/.../textmode
|
What: /sys/bus/usb/.../textmode
|
||||||
Date: August 2008
|
Date: August 2008
|
||||||
KernelVersion: 2.6.26
|
KernelVersion: 2.6.26
|
||||||
Contact: Harrison Metzger <harrisonmetz@gmail.com>
|
Contact: Harrison Metzger <harrisonmetz@gmail.com>
|
||||||
@@ -25,13 +25,13 @@ Description: Controls the way the device interprets its text buffer.
|
|||||||
hex: each character is between 0-15
|
hex: each character is between 0-15
|
||||||
ascii: each character is between '0'-'9' and 'A'-'F'.
|
ascii: each character is between '0'-'9' and 'A'-'F'.
|
||||||
|
|
||||||
Where: /sys/bus/usb/.../text
|
What: /sys/bus/usb/.../text
|
||||||
Date: August 2008
|
Date: August 2008
|
||||||
KernelVersion: 2.6.26
|
KernelVersion: 2.6.26
|
||||||
Contact: Harrison Metzger <harrisonmetz@gmail.com>
|
Contact: Harrison Metzger <harrisonmetz@gmail.com>
|
||||||
Description: The text (or data) for the device to display
|
Description: The text (or data) for the device to display
|
||||||
|
|
||||||
Where: /sys/bus/usb/.../decimals
|
What: /sys/bus/usb/.../decimals
|
||||||
Date: August 2008
|
Date: August 2008
|
||||||
KernelVersion: 2.6.26
|
KernelVersion: 2.6.26
|
||||||
Contact: Harrison Metzger <harrisonmetz@gmail.com>
|
Contact: Harrison Metzger <harrisonmetz@gmail.com>
|
||||||
|
@@ -4,7 +4,7 @@ KernelVersion: 3.5
|
|||||||
Contact: Johan Hovold <jhovold@gmail.com>
|
Contact: Johan Hovold <jhovold@gmail.com>
|
||||||
Description:
|
Description:
|
||||||
Get the ALS output channel used as input in
|
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)
|
0 - out_current0 (backlight 0)
|
||||||
1 - out_current1 (backlight 1)
|
1 - out_current1 (backlight 1)
|
||||||
@@ -28,7 +28,7 @@ Date: April 2012
|
|||||||
KernelVersion: 3.5
|
KernelVersion: 3.5
|
||||||
Contact: Johan Hovold <jhovold@gmail.com>
|
Contact: Johan Hovold <jhovold@gmail.com>
|
||||||
Description:
|
Description:
|
||||||
Set the brightness-mapping mode (0, 1), where
|
Set the brightness-mapping mode (0, 1), where:
|
||||||
|
|
||||||
0 - exponential mode
|
0 - exponential mode
|
||||||
1 - linear mode
|
1 - linear mode
|
||||||
@@ -38,7 +38,7 @@ Date: April 2012
|
|||||||
KernelVersion: 3.5
|
KernelVersion: 3.5
|
||||||
Contact: Johan Hovold <jhovold@gmail.com>
|
Contact: Johan Hovold <jhovold@gmail.com>
|
||||||
Description:
|
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 5 - PWM-input enabled in Zone 4
|
||||||
bit 4 - PWM-input enabled in Zone 3
|
bit 4 - PWM-input enabled in Zone 3
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
Note: Attributes that are shared between devices are stored in the directory
|
Please note that attributes that are shared between devices are stored in
|
||||||
pointed to by the symlink device/.
|
the directory pointed to by the symlink device/.
|
||||||
Example: The real path of the attribute /sys/class/cxl/afu0.0s/irqs_max is
|
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.
|
/sys/class/cxl/afu0.0s/device/irqs_max, i.e. /sys/class/cxl/afu0.0/irqs_max.
|
||||||
|
|
||||||
|
|
||||||
|
@@ -47,7 +47,7 @@ Description:
|
|||||||
What: /sys/class/devfreq/.../trans_stat
|
What: /sys/class/devfreq/.../trans_stat
|
||||||
Date: October 2012
|
Date: October 2012
|
||||||
Contact: MyungJoo Ham <myungjoo.ham@samsung.com>
|
Contact: MyungJoo Ham <myungjoo.ham@samsung.com>
|
||||||
Descrtiption:
|
Description:
|
||||||
This ABI shows the statistics of devfreq behavior on a
|
This ABI shows the statistics of devfreq behavior on a
|
||||||
specific device. It shows the time spent in each state and
|
specific device. It shows the time spent in each state and
|
||||||
the number of transitions between states.
|
the number of transitions between states.
|
||||||
|
@@ -4,7 +4,7 @@ KernelVersion: 3.5
|
|||||||
Contact: Johan Hovold <jhovold@gmail.com>
|
Contact: Johan Hovold <jhovold@gmail.com>
|
||||||
Description:
|
Description:
|
||||||
Set the ALS output channel to use as input in
|
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
|
1 - out_current1
|
||||||
2 - out_current2
|
2 - out_current2
|
||||||
@@ -22,7 +22,7 @@ Date: April 2012
|
|||||||
KernelVersion: 3.5
|
KernelVersion: 3.5
|
||||||
Contact: Johan Hovold <jhovold@gmail.com>
|
Contact: Johan Hovold <jhovold@gmail.com>
|
||||||
Description:
|
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
|
0 - 2048 us
|
||||||
1 - 262 ms
|
1 - 262 ms
|
||||||
@@ -45,7 +45,7 @@ Date: April 2012
|
|||||||
KernelVersion: 3.5
|
KernelVersion: 3.5
|
||||||
Contact: Johan Hovold <jhovold@gmail.com>
|
Contact: Johan Hovold <jhovold@gmail.com>
|
||||||
Description:
|
Description:
|
||||||
Set the brightness-mapping mode (0, 1), where
|
Set the brightness-mapping mode (0, 1), where:
|
||||||
|
|
||||||
0 - exponential mode
|
0 - exponential mode
|
||||||
1 - linear mode
|
1 - linear mode
|
||||||
@@ -55,7 +55,7 @@ Date: April 2012
|
|||||||
KernelVersion: 3.5
|
KernelVersion: 3.5
|
||||||
Contact: Johan Hovold <jhovold@gmail.com>
|
Contact: Johan Hovold <jhovold@gmail.com>
|
||||||
Description:
|
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 5 - PWM-input enabled in Zone 4
|
||||||
bit 4 - PWM-input enabled in Zone 3
|
bit 4 - PWM-input enabled in Zone 3
|
||||||
|
@@ -5,7 +5,7 @@ Contact: Janne Kanniainen <janne.kanniainen@gmail.com>
|
|||||||
Description:
|
Description:
|
||||||
Set the mode of LEDs. You should notice that changing the mode
|
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
|
of one LED will update the mode of its two sibling devices as
|
||||||
well.
|
well. Possible values are:
|
||||||
|
|
||||||
0 - normal
|
0 - normal
|
||||||
1 - audio
|
1 - audio
|
||||||
|
@@ -147,6 +147,6 @@ What: /sys/class/powercap/.../<power zone>/enabled
|
|||||||
Date: September 2013
|
Date: September 2013
|
||||||
KernelVersion: 3.13
|
KernelVersion: 3.13
|
||||||
Contact: linux-pm@vger.kernel.org
|
Contact: linux-pm@vger.kernel.org
|
||||||
Description
|
Description:
|
||||||
This allows to enable/disable power capping at power zone level.
|
This allows to enable/disable power capping at power zone level.
|
||||||
This applies to current power zone and its children.
|
This applies to current power zone and its children.
|
||||||
|
@@ -125,12 +125,6 @@ Description:
|
|||||||
The EUI-48 of this device in colon separated hex
|
The EUI-48 of this device in colon separated hex
|
||||||
octets.
|
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
|
What: /sys/class/uwb_rc/uwbN/<EUI-48>/IEs
|
||||||
Date: July 2008
|
Date: July 2008
|
||||||
KernelVersion: 2.6.27
|
KernelVersion: 2.6.27
|
||||||
|
@@ -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
|
What: /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
|
What: /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/class/hidraw/hidraw<num>/device/report_descriptor
|
||||||
Date: Jan 2011
|
Date: Jan 2011
|
||||||
KernelVersion: 2.0.39
|
KernelVersion: 2.0.39
|
||||||
Contact: Alan Ott <alan@signal11.us>
|
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.
|
This file cannot be written.
|
||||||
Users: HIDAPI library (http://www.signal11.us/oss/hidapi)
|
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
|
What: /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
|
What: /sys/class/bluetooth/hci<addr>/<hid-bus>:<vendor-id>:<product-id>.<num>/country
|
||||||
Symlink : /sys/class/hidraw/hidraw<num>/device/country
|
What: /sys/class/hidraw/hidraw<num>/device/country
|
||||||
Date: February 2015
|
Date: February 2015
|
||||||
KernelVersion: 3.19
|
KernelVersion: 3.19
|
||||||
Contact: Olivier Gay <ogay@logitech.com>
|
Contact: Olivier Gay <ogay@logitech.com>
|
||||||
|
@@ -5,7 +5,7 @@ Description: It is possible to switch the dpi setting of the mouse with the
|
|||||||
press of a button.
|
press of a button.
|
||||||
When read, this file returns the raw number of the actual dpi
|
When read, this file returns the raw number of the actual dpi
|
||||||
setting reported by the mouse. This number has to be further
|
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
|
VALUE DPI
|
||||||
1 800
|
1 800
|
||||||
|
@@ -2,7 +2,7 @@ What: /sys/kernel/fscaps
|
|||||||
Date: February 2011
|
Date: February 2011
|
||||||
KernelVersion: 2.6.38
|
KernelVersion: 2.6.38
|
||||||
Contact: Ludwig Nussel <ludwig.nussel@suse.de>
|
Contact: Ludwig Nussel <ludwig.nussel@suse.de>
|
||||||
Description
|
Description:
|
||||||
Shows whether file system capabilities are honored
|
Shows whether file system capabilities are honored
|
||||||
when executing a binary
|
when executing a binary
|
||||||
|
|
||||||
|
@@ -4,7 +4,7 @@ KernelVersion: 2.6.24
|
|||||||
Contact: Ken'ichi Ohmichi <oomichi@mxs.nes.nec.co.jp>
|
Contact: Ken'ichi Ohmichi <oomichi@mxs.nes.nec.co.jp>
|
||||||
Kexec Mailing List <kexec@lists.infradead.org>
|
Kexec Mailing List <kexec@lists.infradead.org>
|
||||||
Vivek Goyal <vgoyal@redhat.com>
|
Vivek Goyal <vgoyal@redhat.com>
|
||||||
Description
|
Description:
|
||||||
Shows physical address and size of vmcoreinfo ELF note.
|
Shows physical address and size of vmcoreinfo ELF note.
|
||||||
First value contains physical address of note in hex and
|
First value contains physical address of note in hex and
|
||||||
second value contains the size of note in hex. This ELF
|
second value contains the size of note in hex. This ELF
|
||||||
|
@@ -399,7 +399,7 @@ symbol:
|
|||||||
will pass the struct gpio_chip* for the chip to all IRQ callbacks, so the
|
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
|
callbacks need to embed the gpio_chip in its state container and obtain a
|
||||||
pointer to the container using container_of().
|
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,
|
- gpiochip_irqchip_add_nested(): adds a nested cascaded irqchip to a gpiochip,
|
||||||
as discussed above regarding different types of cascaded irqchips. The
|
as discussed above regarding different types of cascaded irqchips. The
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
|
==============
|
||||||
Driver Binding
|
Driver Binding
|
||||||
|
==============
|
||||||
|
|
||||||
Driver binding is the process of associating a device with a device
|
Driver binding is the process of associating a device with a device
|
||||||
driver that can control it. Bus drivers have typically handled this
|
driver that can control it. Bus drivers have typically handled this
|
||||||
@@ -95,4 +96,3 @@ 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
|
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
|
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.
|
||||||
|
|
@@ -1,5 +1,6 @@
|
|||||||
|
=========
|
||||||
Bus Types
|
Bus Types
|
||||||
|
=========
|
||||||
|
|
||||||
Definition
|
Definition
|
||||||
~~~~~~~~~~
|
~~~~~~~~~~
|
||||||
@@ -13,7 +14,7 @@ Declaration
|
|||||||
|
|
||||||
Each bus type in the kernel (PCI, USB, etc) should declare one static
|
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
|
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 = {
|
struct bus_type pci_bus_type = {
|
||||||
.name = "pci",
|
.name = "pci",
|
||||||
@@ -66,9 +67,10 @@ struct device_drivers, respectively. Bus drivers are free to use the
|
|||||||
lists as they please, but conversion to the bus-specific type may be
|
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 bus_for_each_dev(struct bus_type * bus, struct device * start,
|
||||||
|
void * data,
|
||||||
int (*fn)(struct device *, void *));
|
int (*fn)(struct device *, void *));
|
||||||
|
|
||||||
int bus_for_each_drv(struct bus_type * bus, struct device_driver * start,
|
int bus_for_each_drv(struct bus_type * bus, struct device_driver * start,
|
||||||
@@ -87,14 +89,14 @@ sysfs
|
|||||||
There is a top-level directory named 'bus'.
|
There is a top-level directory named 'bus'.
|
||||||
|
|
||||||
Each bus gets a directory in the bus directory, along with two default
|
Each bus gets a directory in the bus directory, along with two default
|
||||||
directories:
|
directories::
|
||||||
|
|
||||||
/sys/bus/pci/
|
/sys/bus/pci/
|
||||||
|-- devices
|
|-- devices
|
||||||
`-- drivers
|
`-- drivers
|
||||||
|
|
||||||
Drivers registered with the bus get a directory in the bus's drivers
|
Drivers registered with the bus get a directory in the bus's drivers
|
||||||
directory:
|
directory::
|
||||||
|
|
||||||
/sys/bus/pci/
|
/sys/bus/pci/
|
||||||
|-- devices
|
|-- devices
|
||||||
@@ -106,7 +108,7 @@ directory:
|
|||||||
|
|
||||||
Each device that is discovered on a bus of that type gets a symlink in
|
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
|
the bus's devices directory to the device's directory in the physical
|
||||||
hierarchy:
|
hierarchy::
|
||||||
|
|
||||||
/sys/bus/pci/
|
/sys/bus/pci/
|
||||||
|-- devices
|
|-- devices
|
||||||
@@ -118,6 +120,9 @@ hierarchy:
|
|||||||
|
|
||||||
Exporting Attributes
|
Exporting Attributes
|
||||||
~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
struct bus_attribute {
|
struct bus_attribute {
|
||||||
struct attribute attr;
|
struct attribute attr;
|
||||||
ssize_t (*show)(struct bus_type *, char * buf);
|
ssize_t (*show)(struct bus_type *, char * buf);
|
||||||
@@ -126,18 +131,16 @@ struct bus_attribute {
|
|||||||
|
|
||||||
Bus drivers can export attributes using the BUS_ATTR_RW macro that works
|
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
|
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
|
This can then be used to add and remove the attribute from the bus's
|
||||||
sysfs directory using:
|
sysfs directory using::
|
||||||
|
|
||||||
int bus_create_file(struct bus_type *, struct bus_attribute *);
|
int bus_create_file(struct bus_type *, struct bus_attribute *);
|
||||||
void bus_remove_file(struct bus_type *, struct bus_attribute *);
|
void bus_remove_file(struct bus_type *, struct bus_attribute *);
|
||||||
|
|
||||||
|
|
@@ -1,6 +1,6 @@
|
|||||||
|
==============
|
||||||
Device Classes
|
Device Classes
|
||||||
|
==============
|
||||||
|
|
||||||
Introduction
|
Introduction
|
||||||
~~~~~~~~~~~~
|
~~~~~~~~~~~~
|
||||||
@@ -21,7 +21,7 @@ on.
|
|||||||
|
|
||||||
Programming Interface
|
Programming Interface
|
||||||
~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~
|
||||||
The device class structure looks like:
|
The device class structure looks like::
|
||||||
|
|
||||||
|
|
||||||
typedef int (*devclass_add)(struct device *);
|
typedef int (*devclass_add)(struct device *);
|
||||||
@@ -29,7 +29,7 @@ typedef void (*devclass_remove)(struct device *);
|
|||||||
|
|
||||||
See the kerneldoc for the struct class.
|
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",
|
.name = "input",
|
||||||
@@ -40,7 +40,7 @@ struct device_class input_devclass = {
|
|||||||
Each device class structure should be exported in a header file so it
|
Each device class structure should be exported in a header file so it
|
||||||
can be used by drivers, extensions and interfaces.
|
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);
|
int devclass_register(struct device_class * cls);
|
||||||
void devclass_unregister(struct device_class * cls);
|
void devclass_unregister(struct device_class * cls);
|
||||||
@@ -81,7 +81,7 @@ 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
|
Each class gets a directory in the class directory, along with two
|
||||||
default subdirectories:
|
default subdirectories::
|
||||||
|
|
||||||
class/
|
class/
|
||||||
`-- input
|
`-- input
|
||||||
@@ -90,7 +90,7 @@ default subdirectories:
|
|||||||
|
|
||||||
|
|
||||||
Drivers registered with the class get a symlink in the drivers/ directory
|
Drivers registered with the class get a symlink in the drivers/ directory
|
||||||
that points to the driver's directory (under its bus directory):
|
that points to the driver's directory (under its bus directory)::
|
||||||
|
|
||||||
class/
|
class/
|
||||||
`-- input
|
`-- input
|
||||||
@@ -100,7 +100,7 @@ that points to the driver's directory (under its bus directory):
|
|||||||
|
|
||||||
|
|
||||||
Each device gets a symlink in the devices/ directory that points to the
|
Each device gets a symlink in the devices/ directory that points to the
|
||||||
device's directory in the physical hierarchy:
|
device's directory in the physical hierarchy::
|
||||||
|
|
||||||
class/
|
class/
|
||||||
`-- input
|
`-- input
|
||||||
@@ -111,6 +111,9 @@ device's directory in the physical hierarchy:
|
|||||||
|
|
||||||
Exporting Attributes
|
Exporting Attributes
|
||||||
~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
struct devclass_attribute {
|
struct devclass_attribute {
|
||||||
struct attribute attr;
|
struct attribute attr;
|
||||||
ssize_t (*show)(struct device_class *, char * buf, size_t count, loff_t off);
|
ssize_t (*show)(struct device_class *, char * buf, size_t count, loff_t off);
|
||||||
@@ -119,16 +122,16 @@ struct devclass_attribute {
|
|||||||
|
|
||||||
Class drivers can export attributes using the DEVCLASS_ATTR macro that works
|
Class drivers can export attributes using the DEVCLASS_ATTR macro that works
|
||||||
similarly to the DEVICE_ATTR macro for devices. For example, a definition
|
similarly to the DEVICE_ATTR macro for devices. For example, a definition
|
||||||
like this:
|
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
|
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 *);
|
int devclass_create_file(struct device_class *, struct devclass_attribute *);
|
||||||
void devclass_remove_file(struct device_class *, struct devclass_attribute *);
|
void devclass_remove_file(struct device_class *, struct devclass_attribute *);
|
||||||
@@ -144,4 +147,3 @@ particular class type. Device interfaces describe these mechanisms.
|
|||||||
|
|
||||||
When a device is added to a device class, the core attempts to add it
|
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.
|
to every interface that is registered with the device class.
|
||||||
|
|
@@ -1,6 +1,6 @@
|
|||||||
|
=============================
|
||||||
Device Driver Design Patterns
|
Device Driver Design Patterns
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
=============================
|
||||||
|
|
||||||
This document describes a few common design patterns found in device drivers.
|
This document describes a few common design patterns found in device drivers.
|
||||||
It is likely that subsystem maintainers will ask driver developers to
|
It is likely that subsystem maintainers will ask driver developers to
|
||||||
@@ -19,7 +19,7 @@ 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.
|
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
|
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 {
|
struct foo {
|
||||||
spinlock_t lock; /* Example member */
|
spinlock_t lock; /* Example member */
|
||||||
@@ -43,7 +43,7 @@ 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.
|
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
|
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)
|
static irqreturn_t foo_handler(int irq, void *arg)
|
||||||
{
|
{
|
||||||
@@ -66,7 +66,7 @@ your interrupt handler.
|
|||||||
2. container_of()
|
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 {
|
struct foo {
|
||||||
spinlock_t lock;
|
spinlock_t lock;
|
@@ -1,6 +1,6 @@
|
|||||||
|
==========================
|
||||||
The Basic Device Structure
|
The Basic Device Structure
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
==========================
|
||||||
|
|
||||||
See the kerneldoc for the struct device.
|
See the kerneldoc for the struct device.
|
||||||
|
|
||||||
@@ -8,7 +8,7 @@ See the kerneldoc for the struct device.
|
|||||||
Programming Interface
|
Programming Interface
|
||||||
~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~
|
||||||
The bus driver that discovers the device uses this to register the
|
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);
|
||||||
|
|
||||||
@@ -20,7 +20,7 @@ The bus should initialize the following fields:
|
|||||||
- bus
|
- bus
|
||||||
|
|
||||||
A device is removed from the core when its reference count goes to
|
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);
|
struct device * get_device(struct device * dev);
|
||||||
void put_device(struct device * dev);
|
void put_device(struct device * dev);
|
||||||
@@ -29,7 +29,7 @@ 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
|
if the reference is not already 0 (if it's in the process of being
|
||||||
removed already).
|
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 lock_device(struct device * dev);
|
||||||
void unlock_device(struct device * dev);
|
void unlock_device(struct device * dev);
|
||||||
@@ -37,6 +37,9 @@ void unlock_device(struct device * dev);
|
|||||||
|
|
||||||
Attributes
|
Attributes
|
||||||
~~~~~~~~~~
|
~~~~~~~~~~
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
struct device_attribute {
|
struct device_attribute {
|
||||||
struct attribute attr;
|
struct attribute attr;
|
||||||
ssize_t (*show)(struct device *dev, struct device_attribute *attr,
|
ssize_t (*show)(struct device *dev, struct device_attribute *attr,
|
||||||
@@ -54,18 +57,18 @@ As explained in Documentation/kobject.txt, device attributes must be
|
|||||||
created before the KOBJ_ADD uevent is generated. The only way to realize
|
created before the KOBJ_ADD uevent is generated. The only way to realize
|
||||||
that is by defining an attribute group.
|
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(type, 0444, show_type, NULL);
|
||||||
static DEVICE_ATTR(power, 0644, show_power, store_power);
|
static DEVICE_ATTR(power, 0644, show_power, store_power);
|
||||||
|
|
||||||
This declares two structures of type struct device_attribute with respective
|
This declares two structures of type struct device_attribute with respective
|
||||||
names 'dev_attr_type' and 'dev_attr_power'. These two attributes can be
|
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_type.attr,
|
||||||
@@ -83,7 +86,7 @@ static const struct attribute_group *dev_attr_groups[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
This array of groups can then be associated with a device by setting the
|
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;
|
dev->groups = dev_attr_groups;
|
||||||
device_register(dev);
|
device_register(dev);
|
@@ -1,3 +1,4 @@
|
|||||||
|
================================
|
||||||
Devres - Managed Device Resource
|
Devres - Managed Device Resource
|
||||||
================================
|
================================
|
||||||
|
|
||||||
@@ -5,6 +6,7 @@ Tejun Heo <teheo@suse.de>
|
|||||||
|
|
||||||
First draft 10 January 2007
|
First draft 10 January 2007
|
||||||
|
|
||||||
|
.. contents
|
||||||
|
|
||||||
1. Intro : Huh? Devres?
|
1. Intro : Huh? Devres?
|
||||||
2. Devres : Devres in a nutshell
|
2. Devres : Devres in a nutshell
|
||||||
@@ -58,7 +60,7 @@ using dma_alloc_coherent(). The managed version is called
|
|||||||
dmam_alloc_coherent(). It is identical to dma_alloc_coherent() except
|
dmam_alloc_coherent(). It is identical to dma_alloc_coherent() except
|
||||||
for the DMA memory allocated using it is managed and will be
|
for the DMA memory allocated using it is managed and will be
|
||||||
automatically released on driver detach. Implementation looks like
|
automatically released on driver detach. Implementation looks like
|
||||||
the following.
|
the following::
|
||||||
|
|
||||||
struct dma_devres {
|
struct dma_devres {
|
||||||
size_t size;
|
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
|
freed whether initialization fails half-way or the device gets
|
||||||
detached. If most resources are acquired using managed interface, a
|
detached. If most resources are acquired using managed interface, a
|
||||||
driver can have much simpler init and exit code. Init path basically
|
driver can have much simpler init and exit code. Init path basically
|
||||||
looks like the following.
|
looks like the following::
|
||||||
|
|
||||||
my_init_one()
|
my_init_one()
|
||||||
{
|
{
|
||||||
@@ -119,7 +121,7 @@ looks like the following.
|
|||||||
return register_to_upper_layer(d);
|
return register_to_upper_layer(d);
|
||||||
}
|
}
|
||||||
|
|
||||||
And exit path,
|
And exit path::
|
||||||
|
|
||||||
my_remove_one()
|
my_remove_one()
|
||||||
{
|
{
|
||||||
@@ -146,7 +148,7 @@ necessary before moving to the managed devm_* calls.
|
|||||||
Devres entries can be grouped using devres group. When a group is
|
Devres entries can be grouped using devres group. When a group is
|
||||||
released, all contained normal devres entries and properly nested
|
released, all contained normal devres entries and properly nested
|
||||||
groups are released. One usage is to rollback series of acquired
|
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))
|
if (!devres_open_group(dev, NULL, GFP_KERNEL))
|
||||||
return -ENOMEM;
|
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.
|
layer) where interface function shouldn't have side effect on failure.
|
||||||
For LLDs, just returning error code suffices in most cases.
|
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
|
specified by @id argument to devres_open_group() or automatically
|
||||||
created by passing NULL as @id as in the above example. In both
|
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
|
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
|
If NULL is given to those functions, the latest open group is
|
||||||
selected.
|
selected.
|
||||||
|
|
||||||
For example, you can do something like the following.
|
For example, you can do something like the following::
|
||||||
|
|
||||||
int my_midlayer_create_something()
|
int my_midlayer_create_something()
|
||||||
{
|
{
|
@@ -1,5 +1,6 @@
|
|||||||
|
==============
|
||||||
Device Drivers
|
Device Drivers
|
||||||
|
==============
|
||||||
|
|
||||||
See the kerneldoc for the struct device_driver.
|
See the kerneldoc for the struct device_driver.
|
||||||
|
|
||||||
@@ -26,7 +27,7 @@ Declaration
|
|||||||
As stated above, struct device_driver objects are statically
|
As stated above, struct device_driver objects are statically
|
||||||
allocated. Below is an example declaration of the eepro100
|
allocated. Below is an example declaration of the eepro100
|
||||||
driver. This declaration is hypothetical only; it relies on the driver
|
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 = {
|
static struct device_driver eepro100_driver = {
|
||||||
.name = "eepro100",
|
.name = "eepro100",
|
||||||
@@ -49,7 +50,7 @@ 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
|
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 {
|
struct pci_driver {
|
||||||
const struct pci_device_id *id_table;
|
const struct pci_device_id *id_table;
|
||||||
@@ -57,7 +58,7 @@ struct pci_driver {
|
|||||||
};
|
};
|
||||||
|
|
||||||
A definition that included bus-specific fields would look like
|
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 = {
|
static struct pci_driver eepro100_driver = {
|
||||||
.id_table = eepro100_pci_tbl,
|
.id_table = eepro100_pci_tbl,
|
||||||
@@ -77,6 +78,8 @@ even a bit ugly. So far, it's the best way we've found to do what we want...
|
|||||||
Registration
|
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
|
The driver registers the structure on startup. For drivers that have
|
||||||
@@ -113,7 +116,7 @@ Access
|
|||||||
~~~~~~
|
~~~~~~
|
||||||
|
|
||||||
Once the object has been registered, it may access the common fields of
|
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 driver_for_each_dev(struct device_driver *drv, void *data,
|
||||||
int (*callback)(struct device *dev, void *data));
|
int (*callback)(struct device *dev, void *data));
|
||||||
@@ -142,6 +145,8 @@ supports.
|
|||||||
Callbacks
|
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
|
The probe() entry is called in task context, with the bus's rwsem locked
|
||||||
@@ -162,7 +167,7 @@ the driver to that device.
|
|||||||
|
|
||||||
A driver's probe() may return a negative errno value to indicate that
|
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
|
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);
|
||||||
|
|
||||||
@@ -176,11 +181,11 @@ 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
|
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);
|
||||||
|
|
||||||
@@ -189,6 +194,9 @@ Resume is used to bring a device back from a low power state.
|
|||||||
|
|
||||||
Attributes
|
Attributes
|
||||||
~~~~~~~~~~
|
~~~~~~~~~~
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
struct driver_attribute {
|
struct driver_attribute {
|
||||||
struct attribute attr;
|
struct attribute attr;
|
||||||
ssize_t (*show)(struct device_driver *driver, char *buf);
|
ssize_t (*show)(struct device_driver *driver, char *buf);
|
||||||
@@ -200,16 +208,16 @@ 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
|
macro that works identically to the DEVICE_ATTR_RW and DEVICE_ATTR_RO
|
||||||
macros.
|
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
|
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 *);
|
int driver_create_file(struct device_driver *, const struct driver_attribute *);
|
||||||
void driver_remove_file(struct device_driver *, const struct driver_attribute *);
|
void driver_remove_file(struct device_driver *, const struct driver_attribute *);
|
26
Documentation/driver-model/index.rst
Normal file
26
Documentation/driver-model/index.rst
Normal 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`
|
@@ -1,4 +1,6 @@
|
|||||||
|
=============================
|
||||||
The Linux Kernel Device Model
|
The Linux Kernel Device Model
|
||||||
|
=============================
|
||||||
|
|
||||||
Patrick Mochel <mochel@digitalimplant.org>
|
Patrick Mochel <mochel@digitalimplant.org>
|
||||||
|
|
||||||
@@ -41,7 +43,7 @@ data structure. These fields must still be accessed by the bus layers,
|
|||||||
and sometimes by the device-specific drivers.
|
and sometimes by the device-specific drivers.
|
||||||
|
|
||||||
Other bus layers are encouraged to do what has been done for the PCI layer.
|
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 {
|
||||||
...
|
...
|
||||||
@@ -80,7 +82,7 @@ easy. This has been accomplished by implementing a special purpose virtual
|
|||||||
file system named sysfs.
|
file system named sysfs.
|
||||||
|
|
||||||
Almost all mainstream Linux distros mount this filesystem automatically; you
|
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
|
$ mount
|
||||||
...
|
...
|
||||||
@@ -89,15 +91,15 @@ none on /sys type sysfs (rw,noexec,nosuid,nodev)
|
|||||||
$
|
$
|
||||||
|
|
||||||
The auto-mounting of sysfs is typically accomplished by an entry similar to
|
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
|
||||||
|
|
||||||
@@ -120,4 +122,3 @@ device-specific data or tunable interfaces.
|
|||||||
More information about the sysfs directory layout can be found in
|
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.
|
Documentation/filesystems/sysfs.txt.
|
||||||
|
|
@@ -1,5 +1,7 @@
|
|||||||
|
============================
|
||||||
Platform Devices and Drivers
|
Platform Devices and Drivers
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
============================
|
||||||
|
|
||||||
See <linux/platform_device.h> for the driver model interface to the
|
See <linux/platform_device.h> for the driver model interface to the
|
||||||
platform bus: platform_device, and platform_driver. This pseudo-bus
|
platform bus: platform_device, and platform_driver. This pseudo-bus
|
||||||
is used to connect devices on busses with minimal infrastructure,
|
is used to connect devices on busses with minimal infrastructure,
|
||||||
@@ -19,7 +21,7 @@ be connected through a segment of some other kind of bus; but its
|
|||||||
registers will still be directly addressable.
|
registers will still be directly addressable.
|
||||||
|
|
||||||
Platform devices are given a name, used in driver binding, and a
|
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;
|
const char *name;
|
||||||
@@ -35,7 +37,7 @@ Platform drivers
|
|||||||
Platform drivers follow the standard driver model convention, where
|
Platform drivers follow the standard driver model convention, where
|
||||||
discovery/enumeration is handled outside the drivers, and drivers
|
discovery/enumeration is handled outside the drivers, and drivers
|
||||||
provide probe() and remove() methods. They support power management
|
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 (*probe)(struct platform_device *);
|
||||||
@@ -52,19 +54,19 @@ Note that probe() should in general verify that the specified device hardware
|
|||||||
actually exists; sometimes platform setup code can't be sure. The probing
|
actually exists; sometimes platform setup code can't be sure. The probing
|
||||||
can use device resources, including clocks, and device platform_data.
|
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);
|
int platform_driver_register(struct platform_driver *drv);
|
||||||
|
|
||||||
Or, in common situations where the device is known not to be hot-pluggable,
|
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
|
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 platform_driver_probe(struct platform_driver *drv,
|
||||||
int (*probe)(struct platform_device *))
|
int (*probe)(struct platform_device *))
|
||||||
|
|
||||||
Kernel modules can be composed of several platform drivers. The platform core
|
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,
|
int __platform_register_drivers(struct platform_driver * const *drivers,
|
||||||
unsigned int count, struct module *owner);
|
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
|
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
|
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)
|
#define platform_register_drivers(drivers, count)
|
||||||
|
|
||||||
@@ -81,7 +83,7 @@ macro that passes THIS_MODULE as owner parameter:
|
|||||||
Device Enumeration
|
Device Enumeration
|
||||||
~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~
|
||||||
As a rule, platform specific (and often board-specific) setup code will
|
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);
|
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.
|
were created by PNP or by platform device setup.
|
||||||
|
|
||||||
None the less, there are some APIs to support such legacy drivers. Avoid
|
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(
|
struct platform_device *platform_device_alloc(
|
||||||
const char *name, int id);
|
const char *name, int id);
|
||||||
|
|
||||||
You can use platform_device_alloc() to dynamically allocate a device, which
|
You can use platform_device_alloc() to dynamically allocate a device, which
|
||||||
you will then initialize with resources and platform_device_register().
|
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(
|
struct platform_device *platform_device_register_simple(
|
||||||
const char *name, int id,
|
const char *name, int id,
|
@@ -1,5 +1,6 @@
|
|||||||
|
=======================================
|
||||||
Porting Drivers to the New Driver Model
|
Porting Drivers to the New Driver Model
|
||||||
|
=======================================
|
||||||
|
|
||||||
Patrick Mochel
|
Patrick Mochel
|
||||||
|
|
||||||
@@ -8,7 +9,7 @@ Patrick Mochel
|
|||||||
|
|
||||||
Overview
|
Overview
|
||||||
|
|
||||||
Please refer to Documentation/driver-model/*.txt for definitions of
|
Please refer to `Documentation/driver-model/*.rst` for definitions of
|
||||||
various driver types and concepts.
|
various driver types and concepts.
|
||||||
|
|
||||||
Most of the work of porting devices drivers to the new model happens
|
Most of the work of porting devices drivers to the new model happens
|
||||||
@@ -22,7 +23,7 @@ objects can replace fields in the bus-specific objects.
|
|||||||
|
|
||||||
The generic objects must be registered with the driver model core. By
|
The generic objects must be registered with the driver model core. By
|
||||||
doing so, they will exported via the sysfs filesystem. sysfs can be
|
doing so, they will exported via the sysfs filesystem. sysfs can be
|
||||||
mounted by doing
|
mounted by doing::
|
||||||
|
|
||||||
# mount -t sysfs sysfs /sys
|
# mount -t sysfs sysfs /sys
|
||||||
|
|
||||||
@@ -35,7 +36,7 @@ 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 = {
|
struct bus_type pci_bus_type = {
|
||||||
.name = "pci",
|
.name = "pci",
|
||||||
@@ -43,8 +44,9 @@ struct bus_type pci_bus_type = {
|
|||||||
|
|
||||||
|
|
||||||
- Register the bus type.
|
- Register the bus type.
|
||||||
|
|
||||||
This should be done in the initialization function for 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)
|
static int __init pci_driver_init(void)
|
||||||
{
|
{
|
||||||
@@ -55,7 +57,7 @@ subsys_initcall(pci_driver_init);
|
|||||||
|
|
||||||
|
|
||||||
The bus type may be unregistered (if the bus driver may be compiled
|
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);
|
bus_unregister(&pci_bus_type);
|
||||||
|
|
||||||
@@ -65,19 +67,19 @@ subsys_initcall(pci_driver_init);
|
|||||||
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.
|
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
|
- 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/
|
# tree -d /sys/bus/pci/
|
||||||
/sys/bus/pci/
|
/sys/bus/pci/
|
||||||
@@ -92,7 +94,7 @@ 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 pci_dev {
|
||||||
@@ -104,7 +106,7 @@ struct pci_dev {
|
|||||||
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
|
the struct to discourage programmers from doing mindless casts
|
||||||
between the object types. Instead macros, or inline functions,
|
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)
|
||||||
@@ -163,11 +165,11 @@ static inline struct pci_dev * to_pci_dev(struct kobject * kobj)
|
|||||||
- Register the device.
|
- Register the device.
|
||||||
|
|
||||||
Once the generic device has been initialized, it can be registered
|
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);
|
device_register(&dev->dev);
|
||||||
|
|
||||||
It can later be unregistered by doing:
|
It can later be unregistered by doing::
|
||||||
|
|
||||||
device_unregister(&dev->dev);
|
device_unregister(&dev->dev);
|
||||||
|
|
||||||
@@ -181,7 +183,7 @@ static inline struct pci_dev * to_pci_dev(struct kobject * kobj)
|
|||||||
|
|
||||||
|
|
||||||
When the device is registered, a directory in sysfs is created.
|
When the device is registered, a directory in sysfs is created.
|
||||||
The PCI tree in sysfs looks like:
|
The PCI tree in sysfs looks like::
|
||||||
|
|
||||||
/sys/devices/pci0/
|
/sys/devices/pci0/
|
||||||
|-- 00:00.0
|
|-- 00:00.0
|
||||||
@@ -204,7 +206,7 @@ static inline struct pci_dev * to_pci_dev(struct kobject * kobj)
|
|||||||
`-- 00:1f.5
|
`-- 00:1f.5
|
||||||
|
|
||||||
Also, symlinks are created in the bus's 'devices' directory
|
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/
|
/sys/bus/pci/devices/
|
||||||
|-- 00:00.0 -> ../../../devices/pci0/00:00.0
|
|-- 00:00.0 -> ../../../devices/pci0/00:00.0
|
||||||
@@ -231,7 +233,7 @@ 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 pci_driver {
|
||||||
...
|
...
|
||||||
@@ -248,14 +250,14 @@ struct pci_driver {
|
|||||||
|
|
||||||
- Register the driver.
|
- Register the driver.
|
||||||
|
|
||||||
After the generic driver has been initialized, call
|
After the generic driver has been initialized, call::
|
||||||
|
|
||||||
driver_register(&drv->driver);
|
driver_register(&drv->driver);
|
||||||
|
|
||||||
to register the driver with the core.
|
to register the driver with the core.
|
||||||
|
|
||||||
When the driver is unregistered from the bus, unregister it from the
|
When the driver is unregistered from the bus, unregister it from the
|
||||||
core by doing:
|
core by doing::
|
||||||
|
|
||||||
driver_unregister(&drv->driver);
|
driver_unregister(&drv->driver);
|
||||||
|
|
||||||
@@ -266,7 +268,7 @@ struct pci_driver {
|
|||||||
- Sysfs representation.
|
- Sysfs representation.
|
||||||
|
|
||||||
Drivers are exported via sysfs in their bus's 'driver's directory.
|
Drivers are exported via sysfs in their bus's 'driver's directory.
|
||||||
For example:
|
For example::
|
||||||
|
|
||||||
/sys/bus/pci/drivers/
|
/sys/bus/pci/drivers/
|
||||||
|-- 3c59x
|
|-- 3c59x
|
||||||
@@ -286,7 +288,7 @@ parameters.
|
|||||||
It would be difficult and tedious to force every driver on a bus to
|
It would be difficult and tedious to force every driver on a bus to
|
||||||
simultaneously convert their drivers to generic format. Instead, the
|
simultaneously convert their drivers to generic format. Instead, the
|
||||||
bus driver should define single instances of the generic methods that
|
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)
|
static int pci_device_remove(struct device * dev)
|
||||||
@@ -304,7 +306,7 @@ static int pci_device_remove(struct device * dev)
|
|||||||
|
|
||||||
|
|
||||||
The generic driver should be initialized with these methods before it
|
The generic driver should be initialized with these methods before it
|
||||||
is registered.
|
is registered::
|
||||||
|
|
||||||
/* initialize common driver fields */
|
/* initialize common driver fields */
|
||||||
drv->driver.name = drv->name;
|
drv->driver.name = drv->name;
|
||||||
@@ -336,7 +338,7 @@ 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
|
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);
|
int (*match)(struct device * dev, struct device_driver * drv);
|
||||||
|
|
||||||
@@ -355,7 +357,7 @@ claimed by a driver.
|
|||||||
When a device is successfully bound to a driver, device->driver is
|
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
|
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
|
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/
|
/sys/bus/pci/drivers/
|
||||||
|-- 3c59x
|
|-- 3c59x
|
||||||
@@ -387,7 +389,7 @@ environment variables, including
|
|||||||
|
|
||||||
A bus driver may also supply additional parameters for userspace to
|
A bus driver may also supply additional parameters for userspace to
|
||||||
consume. To do this, a bus must implement the 'hotplug' method in
|
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);
|
int num_envp, char *buffer, int buffer_size);
|
||||||
@@ -407,7 +409,7 @@ 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
|
An internal list that the bus uses may be removed, in favor of using
|
||||||
this one.
|
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,
|
int bus_for_each_dev(struct bus_type * bus, struct device * start,
|
||||||
void * data, int (*fn)(struct device *, void *));
|
void * data, int (*fn)(struct device *, void *));
|
||||||
@@ -419,7 +421,7 @@ struct bus_type also contains a list of all drivers registered with
|
|||||||
it. An internal list of drivers that the bus driver maintains may
|
it. An internal list of drivers that the bus driver maintains may
|
||||||
be removed in favor of using the generic one.
|
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,
|
int bus_for_each_drv(struct bus_type * bus, struct device_driver * start,
|
||||||
void * data, int (*fn)(struct device_driver *, void *));
|
void * data, int (*fn)(struct device_driver *, void *));
|
||||||
@@ -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
|
though, that this will likely mean fixing up all the drivers that
|
||||||
reference the bus-specific fields (though those should all be 1-line
|
reference the bus-specific fields (though those should all be 1-line
|
||||||
changes).
|
changes).
|
||||||
|
|
@@ -103,7 +103,7 @@ id_table an array of NULL terminated EISA id strings,
|
|||||||
(driver_data).
|
(driver_data).
|
||||||
|
|
||||||
driver a generic driver, such as described in
|
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.
|
.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.
|
flags are EISA_CONFIG_ENABLED and EISA_CONFIG_FORCED.
|
||||||
res set of four 256 bytes I/O regions allocated to this device
|
res set of four 256 bytes I/O regions allocated to this device
|
||||||
dma_mask DMA mask set from the parent 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
|
You can get the 'struct eisa_device' from 'struct device' using the
|
||||||
|
@@ -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:
|
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,
|
struct dentry *parent,
|
||||||
u32 *array, u32 elements);
|
u32 *array, u32 elements);
|
||||||
|
|
||||||
|
@@ -89,7 +89,7 @@ increase the chances of your change being accepted.
|
|||||||
console. Excessive logging can seriously affect system performance.
|
console. Excessive logging can seriously affect system performance.
|
||||||
|
|
||||||
* Use devres functions whenever possible to allocate resources. For rationale
|
* 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 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
|
* If the driver has a detect function, make sure it is silent. Debug messages
|
||||||
|
@@ -21,13 +21,10 @@ struct ptdump_info {
|
|||||||
|
|
||||||
void ptdump_walk_pgd(struct seq_file *s, struct ptdump_info *info);
|
void ptdump_walk_pgd(struct seq_file *s, struct ptdump_info *info);
|
||||||
#ifdef CONFIG_ARM_PTDUMP_DEBUGFS
|
#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
|
#else
|
||||||
static inline int ptdump_debugfs_register(struct ptdump_info *info,
|
static inline void ptdump_debugfs_register(struct ptdump_info *info,
|
||||||
const char *name)
|
const char *name) { }
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif /* CONFIG_ARM_PTDUMP_DEBUGFS */
|
#endif /* CONFIG_ARM_PTDUMP_DEBUGFS */
|
||||||
|
|
||||||
void ptdump_check_wx(void);
|
void ptdump_check_wx(void);
|
||||||
|
@@ -987,84 +987,44 @@ static int debug_clock_show(struct seq_file *s, void *unused)
|
|||||||
|
|
||||||
DEFINE_SHOW_ATTRIBUTE(debug_clock);
|
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 dentry *d;
|
||||||
struct clk *pa = c->parent;
|
struct clk *pa = c->parent;
|
||||||
|
|
||||||
d = debugfs_create_dir(c->name, pa ? pa->dent : clk_debugfs_root);
|
d = debugfs_create_dir(c->name, pa ? pa->dent : clk_debugfs_root);
|
||||||
if (!d)
|
|
||||||
return -ENOMEM;
|
|
||||||
c->dent = d;
|
c->dent = d;
|
||||||
|
|
||||||
d = debugfs_create_u8("usecount", S_IRUGO, c->dent, &c->usecount);
|
debugfs_create_u8("usecount", S_IRUGO, c->dent, &c->usecount);
|
||||||
if (!d) {
|
debugfs_create_ulong("rate", S_IRUGO, c->dent, &c->rate);
|
||||||
err = -ENOMEM;
|
debugfs_create_x8("flags", S_IRUGO, c->dent, &c->flags);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int clk_debugfs_register(struct clk *c)
|
static void clk_debugfs_register(struct clk *c)
|
||||||
{
|
{
|
||||||
int err;
|
|
||||||
struct clk *pa = c->parent;
|
struct clk *pa = c->parent;
|
||||||
|
|
||||||
if (pa && !pa->dent) {
|
if (pa && !pa->dent)
|
||||||
err = clk_debugfs_register(pa);
|
clk_debugfs_register(pa);
|
||||||
if (err)
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!c->dent) {
|
if (!c->dent)
|
||||||
err = clk_debugfs_register_one(c);
|
clk_debugfs_register_one(c);
|
||||||
if (err)
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __init clk_debugfs_init(void)
|
static int __init clk_debugfs_init(void)
|
||||||
{
|
{
|
||||||
struct clk *c;
|
struct clk *c;
|
||||||
struct dentry *d;
|
struct dentry *d;
|
||||||
int err;
|
|
||||||
|
|
||||||
d = debugfs_create_dir("clock", NULL);
|
d = debugfs_create_dir("clock", NULL);
|
||||||
if (!d)
|
|
||||||
return -ENOMEM;
|
|
||||||
clk_debugfs_root = d;
|
clk_debugfs_root = d;
|
||||||
|
|
||||||
list_for_each_entry(c, &clocks, node) {
|
list_for_each_entry(c, &clocks, node)
|
||||||
err = clk_debugfs_register(c);
|
clk_debugfs_register(c);
|
||||||
if (err)
|
|
||||||
goto err_out;
|
|
||||||
}
|
|
||||||
|
|
||||||
d = debugfs_create_file("summary", S_IRUGO,
|
debugfs_create_file("summary", S_IRUGO, d, NULL, &debug_clock_fops);
|
||||||
d, NULL, &debug_clock_fops);
|
|
||||||
if (!d)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
err_out:
|
|
||||||
debugfs_remove_recursive(clk_debugfs_root);
|
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
late_initcall(clk_debugfs_init);
|
late_initcall(clk_debugfs_init);
|
||||||
|
|
||||||
|
@@ -539,11 +539,8 @@ static void omap_pm_init_debugfs(void)
|
|||||||
struct dentry *d;
|
struct dentry *d;
|
||||||
|
|
||||||
d = debugfs_create_dir("pm_debug", NULL);
|
d = debugfs_create_dir("pm_debug", NULL);
|
||||||
if (!d)
|
debugfs_create_file("omap_pm", S_IWUSR | S_IRUGO, d, NULL,
|
||||||
return;
|
&omap_pm_debug_fops);
|
||||||
|
|
||||||
(void) debugfs_create_file("omap_pm", S_IWUSR | S_IRUGO,
|
|
||||||
d, NULL, &omap_pm_debug_fops);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* CONFIG_DEBUG_FS */
|
#endif /* CONFIG_DEBUG_FS */
|
||||||
|
@@ -190,9 +190,8 @@ static int __init pwrdms_setup(struct powerdomain *pwrdm, void *dir)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
d = debugfs_create_dir(pwrdm->name, (struct dentry *)dir);
|
d = debugfs_create_dir(pwrdm->name, (struct dentry *)dir);
|
||||||
if (d)
|
debugfs_create_file("suspend", S_IRUGO|S_IWUSR, d, pwrdm,
|
||||||
(void) debugfs_create_file("suspend", S_IRUGO|S_IWUSR, d,
|
&pwrdm_suspend_fops);
|
||||||
(void *)pwrdm, &pwrdm_suspend_fops);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -230,15 +229,13 @@ static int __init pm_dbg_init(void)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
d = debugfs_create_dir("pm_debug", NULL);
|
d = debugfs_create_dir("pm_debug", NULL);
|
||||||
if (!d)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
(void) debugfs_create_file("count", 0444, d, NULL, &pm_dbg_counters_fops);
|
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("time", 0444, d, NULL, &pm_dbg_timers_fops);
|
||||||
|
|
||||||
pwrdm_for_each(pwrdms_setup, (void *)d);
|
pwrdm_for_each(pwrdms_setup, (void *)d);
|
||||||
|
|
||||||
(void) debugfs_create_file("enable_off_mode", S_IRUGO | S_IWUSR, d,
|
debugfs_create_file("enable_off_mode", S_IRUGO | S_IWUSR, d,
|
||||||
&enable_off_mode, &pm_dbg_option_fops);
|
&enable_off_mode, &pm_dbg_option_fops);
|
||||||
pm_dbg_init_done = 1;
|
pm_dbg_init_done = 1;
|
||||||
|
|
||||||
|
@@ -446,7 +446,7 @@ void ptdump_check_wx(void)
|
|||||||
static int ptdump_init(void)
|
static int ptdump_init(void)
|
||||||
{
|
{
|
||||||
ptdump_initialize();
|
ptdump_initialize();
|
||||||
return ptdump_debugfs_register(&kernel_ptdump_info,
|
ptdump_debugfs_register(&kernel_ptdump_info, "kernel_page_tables");
|
||||||
"kernel_page_tables");
|
return 0;
|
||||||
}
|
}
|
||||||
__initcall(ptdump_init);
|
__initcall(ptdump_init);
|
||||||
|
@@ -24,11 +24,7 @@ static const struct file_operations ptdump_fops = {
|
|||||||
.release = single_release,
|
.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;
|
debugfs_create_file(name, 0400, NULL, info, &ptdump_fops);
|
||||||
|
|
||||||
pe = debugfs_create_file(name, 0400, NULL, info, &ptdump_fops);
|
|
||||||
return pe ? 0 : -ENOMEM;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -147,13 +147,13 @@ static const struct dma_map_ops ibmebus_dma_ops = {
|
|||||||
.unmap_page = ibmebus_unmap_page,
|
.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;
|
struct device_node *dn = to_platform_device(dev)->dev.of_node;
|
||||||
return (of_find_node_by_path(data) == dn);
|
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;
|
return to_platform_device(dev)->dev.of_node == data;
|
||||||
}
|
}
|
||||||
|
@@ -9,9 +9,6 @@ EXPORT_SYMBOL(arch_debugfs_dir);
|
|||||||
static int __init arch_kdebugfs_init(void)
|
static int __init arch_kdebugfs_init(void)
|
||||||
{
|
{
|
||||||
arch_debugfs_dir = debugfs_create_dir("sh", NULL);
|
arch_debugfs_dir = debugfs_create_dir("sh", NULL);
|
||||||
if (!arch_debugfs_dir)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
arch_initcall(arch_kdebugfs_init);
|
arch_initcall(arch_kdebugfs_init);
|
||||||
|
@@ -63,13 +63,8 @@ static const struct file_operations asids_debugfs_fops = {
|
|||||||
|
|
||||||
static int __init asids_debugfs_init(void)
|
static int __init asids_debugfs_init(void)
|
||||||
{
|
{
|
||||||
struct dentry *asids_dentry;
|
debugfs_create_file("asids", S_IRUSR, arch_debugfs_dir, NULL,
|
||||||
|
&asids_debugfs_fops);
|
||||||
asids_dentry = debugfs_create_file("asids", S_IRUSR, arch_debugfs_dir,
|
return 0;
|
||||||
NULL, &asids_debugfs_fops);
|
|
||||||
if (!asids_dentry)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
return PTR_ERR_OR_ZERO(asids_dentry);
|
|
||||||
}
|
}
|
||||||
device_initcall(asids_debugfs_init);
|
device_initcall(asids_debugfs_init);
|
||||||
|
@@ -109,22 +109,10 @@ static const struct file_operations cache_debugfs_fops = {
|
|||||||
|
|
||||||
static int __init cache_debugfs_init(void)
|
static int __init cache_debugfs_init(void)
|
||||||
{
|
{
|
||||||
struct dentry *dcache_dentry, *icache_dentry;
|
debugfs_create_file("dcache", S_IRUSR, arch_debugfs_dir,
|
||||||
|
(void *)CACHE_TYPE_DCACHE, &cache_debugfs_fops);
|
||||||
dcache_dentry = debugfs_create_file("dcache", S_IRUSR, arch_debugfs_dir,
|
debugfs_create_file("icache", S_IRUSR, arch_debugfs_dir,
|
||||||
(unsigned int *)CACHE_TYPE_DCACHE,
|
(void *)CACHE_TYPE_ICACHE, &cache_debugfs_fops);
|
||||||
&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;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
module_init(cache_debugfs_init);
|
module_init(cache_debugfs_init);
|
||||||
|
@@ -861,13 +861,8 @@ static const struct file_operations pmb_debugfs_fops = {
|
|||||||
|
|
||||||
static int __init pmb_debugfs_init(void)
|
static int __init pmb_debugfs_init(void)
|
||||||
{
|
{
|
||||||
struct dentry *dentry;
|
debugfs_create_file("pmb", S_IFREG | S_IRUGO, arch_debugfs_dir, NULL,
|
||||||
|
&pmb_debugfs_fops);
|
||||||
dentry = debugfs_create_file("pmb", S_IFREG | S_IRUGO,
|
|
||||||
arch_debugfs_dir, NULL, &pmb_debugfs_fops);
|
|
||||||
if (!dentry)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
subsys_initcall(pmb_debugfs_init);
|
subsys_initcall(pmb_debugfs_init);
|
||||||
|
@@ -149,22 +149,10 @@ static const struct file_operations tlb_debugfs_fops = {
|
|||||||
|
|
||||||
static int __init tlb_debugfs_init(void)
|
static int __init tlb_debugfs_init(void)
|
||||||
{
|
{
|
||||||
struct dentry *itlb, *utlb;
|
debugfs_create_file("itlb", S_IRUSR, arch_debugfs_dir,
|
||||||
|
(void *)TLB_TYPE_ITLB, &tlb_debugfs_fops);
|
||||||
itlb = debugfs_create_file("itlb", S_IRUSR, arch_debugfs_dir,
|
debugfs_create_file("utlb", S_IRUSR, arch_debugfs_dir,
|
||||||
(unsigned int *)TLB_TYPE_ITLB,
|
(void *)TLB_TYPE_UTLB, &tlb_debugfs_fops);
|
||||||
&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;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
module_init(tlb_debugfs_init);
|
module_init(tlb_debugfs_init);
|
||||||
|
@@ -67,33 +67,18 @@ static const struct file_operations fops_setup_data = {
|
|||||||
.llseek = default_llseek,
|
.llseek = default_llseek,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int __init
|
static void __init
|
||||||
create_setup_data_node(struct dentry *parent, int no,
|
create_setup_data_node(struct dentry *parent, int no,
|
||||||
struct setup_data_node *node)
|
struct setup_data_node *node)
|
||||||
{
|
{
|
||||||
struct dentry *d, *type, *data;
|
struct dentry *d;
|
||||||
char buf[16];
|
char buf[16];
|
||||||
|
|
||||||
sprintf(buf, "%d", no);
|
sprintf(buf, "%d", no);
|
||||||
d = debugfs_create_dir(buf, parent);
|
d = debugfs_create_dir(buf, parent);
|
||||||
if (!d)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
type = debugfs_create_x32("type", S_IRUGO, d, &node->type);
|
debugfs_create_x32("type", S_IRUGO, d, &node->type);
|
||||||
if (!type)
|
debugfs_create_file("data", S_IRUGO, d, node, &fops_setup_data);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __init create_setup_data_nodes(struct dentry *parent)
|
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;
|
int no = 0;
|
||||||
|
|
||||||
d = debugfs_create_dir("setup_data", parent);
|
d = debugfs_create_dir("setup_data", parent);
|
||||||
if (!d)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
pa_data = boot_params.hdr.setup_data;
|
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->paddr = pa_data;
|
||||||
node->type = data->type;
|
node->type = data->type;
|
||||||
node->len = data->len;
|
node->len = data->len;
|
||||||
error = create_setup_data_node(d, no, node);
|
create_setup_data_node(d, no, node);
|
||||||
pa_data = data->next;
|
pa_data = data->next;
|
||||||
|
|
||||||
memunmap(data);
|
memunmap(data);
|
||||||
if (error)
|
|
||||||
goto err_dir;
|
|
||||||
no++;
|
no++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err_dir:
|
err_dir:
|
||||||
debugfs_remove(d);
|
debugfs_remove_recursive(d);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -151,35 +132,18 @@ static struct debugfs_blob_wrapper boot_params_blob = {
|
|||||||
|
|
||||||
static int __init boot_params_kdebugfs_init(void)
|
static int __init boot_params_kdebugfs_init(void)
|
||||||
{
|
{
|
||||||
struct dentry *dbp, *version, *data;
|
struct dentry *dbp;
|
||||||
int error = -ENOMEM;
|
int error;
|
||||||
|
|
||||||
dbp = debugfs_create_dir("boot_params", arch_debugfs_dir);
|
dbp = debugfs_create_dir("boot_params", arch_debugfs_dir);
|
||||||
if (!dbp)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
version = debugfs_create_x16("version", S_IRUGO, dbp,
|
debugfs_create_x16("version", S_IRUGO, dbp, &boot_params.hdr.version);
|
||||||
&boot_params.hdr.version);
|
debugfs_create_blob("data", S_IRUGO, dbp, &boot_params_blob);
|
||||||
if (!version)
|
|
||||||
goto err_dir;
|
|
||||||
|
|
||||||
data = debugfs_create_blob("data", S_IRUGO, dbp,
|
|
||||||
&boot_params_blob);
|
|
||||||
if (!data)
|
|
||||||
goto err_version;
|
|
||||||
|
|
||||||
error = create_setup_data_nodes(dbp);
|
error = create_setup_data_nodes(dbp);
|
||||||
if (error)
|
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;
|
return error;
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_DEBUG_BOOT_PARAMS */
|
#endif /* CONFIG_DEBUG_BOOT_PARAMS */
|
||||||
@@ -189,8 +153,6 @@ static int __init arch_kdebugfs_init(void)
|
|||||||
int error = 0;
|
int error = 0;
|
||||||
|
|
||||||
arch_debugfs_dir = debugfs_create_dir("x86", NULL);
|
arch_debugfs_dir = debugfs_create_dir("x86", NULL);
|
||||||
if (!arch_debugfs_dir)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
#ifdef CONFIG_DEBUG_BOOT_PARAMS
|
#ifdef CONFIG_DEBUG_BOOT_PARAMS
|
||||||
error = boot_params_kdebugfs_init();
|
error = boot_params_kdebugfs_init();
|
||||||
|
@@ -26,8 +26,6 @@ static int ptdump_curknl_show(struct seq_file *m, void *v)
|
|||||||
DEFINE_SHOW_ATTRIBUTE(ptdump_curknl);
|
DEFINE_SHOW_ATTRIBUTE(ptdump_curknl);
|
||||||
|
|
||||||
#ifdef CONFIG_PAGE_TABLE_ISOLATION
|
#ifdef CONFIG_PAGE_TABLE_ISOLATION
|
||||||
static struct dentry *pe_curusr;
|
|
||||||
|
|
||||||
static int ptdump_curusr_show(struct seq_file *m, void *v)
|
static int ptdump_curusr_show(struct seq_file *m, void *v)
|
||||||
{
|
{
|
||||||
if (current->mm->pgd) {
|
if (current->mm->pgd) {
|
||||||
@@ -42,8 +40,6 @@ DEFINE_SHOW_ATTRIBUTE(ptdump_curusr);
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(CONFIG_EFI) && defined(CONFIG_X86_64)
|
#if defined(CONFIG_EFI) && defined(CONFIG_X86_64)
|
||||||
static struct dentry *pe_efi;
|
|
||||||
|
|
||||||
static int ptdump_efi_show(struct seq_file *m, void *v)
|
static int ptdump_efi_show(struct seq_file *m, void *v)
|
||||||
{
|
{
|
||||||
if (efi_mm.pgd)
|
if (efi_mm.pgd)
|
||||||
@@ -54,41 +50,24 @@ static int ptdump_efi_show(struct seq_file *m, void *v)
|
|||||||
DEFINE_SHOW_ATTRIBUTE(ptdump_efi);
|
DEFINE_SHOW_ATTRIBUTE(ptdump_efi);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static struct dentry *dir, *pe_knl, *pe_curknl;
|
static struct dentry *dir;
|
||||||
|
|
||||||
static int __init pt_dump_debug_init(void)
|
static int __init pt_dump_debug_init(void)
|
||||||
{
|
{
|
||||||
dir = debugfs_create_dir("page_tables", NULL);
|
dir = debugfs_create_dir("page_tables", NULL);
|
||||||
if (!dir)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
pe_knl = debugfs_create_file("kernel", 0400, dir, NULL,
|
debugfs_create_file("kernel", 0400, dir, NULL, &ptdump_fops);
|
||||||
&ptdump_fops);
|
debugfs_create_file("current_kernel", 0400, dir, NULL,
|
||||||
if (!pe_knl)
|
&ptdump_curknl_fops);
|
||||||
goto err;
|
|
||||||
|
|
||||||
pe_curknl = debugfs_create_file("current_kernel", 0400,
|
|
||||||
dir, NULL, &ptdump_curknl_fops);
|
|
||||||
if (!pe_curknl)
|
|
||||||
goto err;
|
|
||||||
|
|
||||||
#ifdef CONFIG_PAGE_TABLE_ISOLATION
|
#ifdef CONFIG_PAGE_TABLE_ISOLATION
|
||||||
pe_curusr = debugfs_create_file("current_user", 0400,
|
debugfs_create_file("current_user", 0400, dir, NULL,
|
||||||
dir, NULL, &ptdump_curusr_fops);
|
&ptdump_curusr_fops);
|
||||||
if (!pe_curusr)
|
|
||||||
goto err;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(CONFIG_EFI) && defined(CONFIG_X86_64)
|
#if defined(CONFIG_EFI) && defined(CONFIG_X86_64)
|
||||||
pe_efi = debugfs_create_file("efi", 0400, dir, NULL, &ptdump_efi_fops);
|
debugfs_create_file("efi", 0400, dir, NULL, &ptdump_efi_fops);
|
||||||
if (!pe_efi)
|
|
||||||
goto err;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
err:
|
|
||||||
debugfs_remove_recursive(dir);
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __exit pt_dump_debug_exit(void)
|
static void __exit pt_dump_debug_exit(void)
|
||||||
|
@@ -104,24 +104,12 @@ DEFINE_SHOW_ATTRIBUTE(punit_dev_state);
|
|||||||
|
|
||||||
static struct dentry *punit_dbg_file;
|
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);
|
punit_dbg_file = debugfs_create_dir("punit_atom", NULL);
|
||||||
if (!punit_dbg_file)
|
|
||||||
return -ENXIO;
|
|
||||||
|
|
||||||
dev_state = debugfs_create_file("dev_power_state", 0444,
|
debugfs_create_file("dev_power_state", 0444, punit_dbg_file,
|
||||||
punit_dbg_file, punit_device,
|
punit_device, &punit_dev_state_fops);
|
||||||
&punit_dev_state_fops);
|
|
||||||
if (!dev_state) {
|
|
||||||
pr_err("punit_dev_state register failed\n");
|
|
||||||
debugfs_remove(punit_dbg_file);
|
|
||||||
return -ENXIO;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void punit_dbgfs_unregister(void)
|
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)
|
static int __init punit_atom_debug_init(void)
|
||||||
{
|
{
|
||||||
const struct x86_cpu_id *id;
|
const struct x86_cpu_id *id;
|
||||||
int ret;
|
|
||||||
|
|
||||||
id = x86_match_cpu(intel_punit_cpu_ids);
|
id = x86_match_cpu(intel_punit_cpu_ids);
|
||||||
if (!id)
|
if (!id)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
ret = punit_dbgfs_register((struct punit_device *)id->driver_data);
|
punit_dbgfs_register((struct punit_device *)id->driver_data);
|
||||||
if (ret < 0)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@@ -35,7 +35,6 @@
|
|||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
|
|
||||||
struct imr_device {
|
struct imr_device {
|
||||||
struct dentry *file;
|
|
||||||
bool init;
|
bool init;
|
||||||
struct mutex lock;
|
struct mutex lock;
|
||||||
int max_imr;
|
int max_imr;
|
||||||
@@ -231,13 +230,11 @@ DEFINE_SHOW_ATTRIBUTE(imr_dbgfs_state);
|
|||||||
* imr_debugfs_register - register debugfs hooks.
|
* imr_debugfs_register - register debugfs hooks.
|
||||||
*
|
*
|
||||||
* @idev: pointer to imr_device structure.
|
* @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,
|
debugfs_create_file("imr_state", 0444, NULL, idev,
|
||||||
&imr_dbgfs_state_fops);
|
&imr_dbgfs_state_fops);
|
||||||
return PTR_ERR_OR_ZERO(idev->file);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -582,7 +579,6 @@ static const struct x86_cpu_id imr_ids[] __initconst = {
|
|||||||
static int __init imr_init(void)
|
static int __init imr_init(void)
|
||||||
{
|
{
|
||||||
struct imr_device *idev = &imr_dev;
|
struct imr_device *idev = &imr_dev;
|
||||||
int ret;
|
|
||||||
|
|
||||||
if (!x86_match_cpu(imr_ids) || !iosf_mbi_available())
|
if (!x86_match_cpu(imr_ids) || !iosf_mbi_available())
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
@@ -592,9 +588,7 @@ static int __init imr_init(void)
|
|||||||
idev->init = true;
|
idev->init = true;
|
||||||
|
|
||||||
mutex_init(&idev->lock);
|
mutex_init(&idev->lock);
|
||||||
ret = imr_debugfs_register(idev);
|
imr_debugfs_register(idev);
|
||||||
if (ret != 0)
|
|
||||||
pr_warn("debugfs register failed!\n");
|
|
||||||
imr_fixup_memmap(idev);
|
imr_fixup_memmap(idev);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@@ -461,31 +461,16 @@ static struct dentry *iosf_dbg;
|
|||||||
|
|
||||||
static void iosf_sideband_debug_init(void)
|
static void iosf_sideband_debug_init(void)
|
||||||
{
|
{
|
||||||
struct dentry *d;
|
|
||||||
|
|
||||||
iosf_dbg = debugfs_create_dir("iosf_sb", NULL);
|
iosf_dbg = debugfs_create_dir("iosf_sb", NULL);
|
||||||
if (IS_ERR_OR_NULL(iosf_dbg))
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* mdr */
|
/* mdr */
|
||||||
d = debugfs_create_x32("mdr", 0660, iosf_dbg, &dbg_mdr);
|
debugfs_create_x32("mdr", 0660, iosf_dbg, &dbg_mdr);
|
||||||
if (!d)
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
/* mcrx */
|
/* mcrx */
|
||||||
d = debugfs_create_x32("mcrx", 0660, iosf_dbg, &dbg_mcrx);
|
debugfs_create_x32("mcrx", 0660, iosf_dbg, &dbg_mcrx);
|
||||||
if (!d)
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
/* mcr - initiates mailbox tranaction */
|
/* mcr - initiates mailbox tranaction */
|
||||||
d = debugfs_create_file("mcr", 0660, iosf_dbg, &dbg_mcr, &iosf_mcr_fops);
|
debugfs_create_file("mcr", 0660, iosf_dbg, &dbg_mcr, &iosf_mcr_fops);
|
||||||
if (!d)
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
return;
|
|
||||||
|
|
||||||
cleanup:
|
|
||||||
debugfs_remove_recursive(d);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void iosf_debugfs_init(void)
|
static void iosf_debugfs_init(void)
|
||||||
|
@@ -66,7 +66,6 @@ static struct tunables tunables[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static struct dentry *tunables_dir;
|
static struct dentry *tunables_dir;
|
||||||
static struct dentry *tunables_file;
|
|
||||||
|
|
||||||
/* these correspond to the statistics printed by ptc_seq_show() */
|
/* these correspond to the statistics printed by ptc_seq_show() */
|
||||||
static char *stat_description[] = {
|
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);
|
tunables_dir = debugfs_create_dir(UV_BAU_TUNABLES_DIR, NULL);
|
||||||
if (!tunables_dir) {
|
debugfs_create_file(UV_BAU_TUNABLES_FILE, 0600, tunables_dir, NULL,
|
||||||
pr_err("unable to create debugfs directory %s\n",
|
&tunables_fops);
|
||||||
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;
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -9,13 +9,8 @@ static struct dentry *d_xen_debug;
|
|||||||
|
|
||||||
struct dentry * __init xen_init_debugfs(void)
|
struct dentry * __init xen_init_debugfs(void)
|
||||||
{
|
{
|
||||||
if (!d_xen_debug) {
|
|
||||||
d_xen_debug = debugfs_create_dir("xen", NULL);
|
|
||||||
|
|
||||||
if (!d_xen_debug)
|
if (!d_xen_debug)
|
||||||
pr_warning("Could not create 'xen' debugfs directory\n");
|
d_xen_debug = debugfs_create_dir("xen", NULL);
|
||||||
}
|
|
||||||
|
|
||||||
return d_xen_debug;
|
return d_xen_debug;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -817,9 +817,6 @@ static int __init xen_p2m_debugfs(void)
|
|||||||
{
|
{
|
||||||
struct dentry *d_xen = xen_init_debugfs();
|
struct dentry *d_xen = xen_init_debugfs();
|
||||||
|
|
||||||
if (d_xen == NULL)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
d_mmu_debug = debugfs_create_dir("mmu", d_xen);
|
d_mmu_debug = debugfs_create_dir("mmu", d_xen);
|
||||||
|
|
||||||
debugfs_create_file("p2m", 0600, d_mmu_debug, NULL, &p2m_dump_fops);
|
debugfs_create_file("p2m", 0600, d_mmu_debug, NULL, &p2m_dump_fops);
|
||||||
|
@@ -508,10 +508,10 @@ struct hid_uid {
|
|||||||
const char *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 acpi_device *adev = ACPI_COMPANION(dev);
|
||||||
struct hid_uid *id = data;
|
const struct hid_uid *id = data;
|
||||||
|
|
||||||
if (!adev)
|
if (!adev)
|
||||||
return 0;
|
return 0;
|
||||||
|
@@ -725,17 +725,15 @@ bool acpi_dev_found(const char *hid)
|
|||||||
EXPORT_SYMBOL(acpi_dev_found);
|
EXPORT_SYMBOL(acpi_dev_found);
|
||||||
|
|
||||||
struct acpi_dev_match_info {
|
struct acpi_dev_match_info {
|
||||||
const char *dev_name;
|
|
||||||
struct acpi_device *adev;
|
|
||||||
struct acpi_device_id hid[2];
|
struct acpi_device_id hid[2];
|
||||||
const char *uid;
|
const char *uid;
|
||||||
s64 hrv;
|
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_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;
|
unsigned long long hrv;
|
||||||
acpi_status status;
|
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)))
|
strcmp(adev->pnp.unique_id, match->uid)))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
match->dev_name = acpi_dev_name(adev);
|
|
||||||
match->adev = adev;
|
|
||||||
|
|
||||||
if (match->hrv == -1)
|
if (match->hrv == -1)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
@@ -818,7 +813,7 @@ acpi_dev_get_first_match_dev(const char *hid, const char *uid, s64 hrv)
|
|||||||
match.hrv = hrv;
|
match.hrv = hrv;
|
||||||
|
|
||||||
dev = bus_find_device(&acpi_bus_type, NULL, &match, acpi_dev_match_cb);
|
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);
|
EXPORT_SYMBOL(acpi_dev_get_first_match_dev);
|
||||||
|
|
||||||
|
@@ -134,10 +134,10 @@ static inline void gizmo_writel(struct tegra_ahb *ahb, u32 value, u32 offset)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_TEGRA_IOMMU_SMMU
|
#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 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;
|
return (ahb->dev->of_node == dn) ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
@@ -137,7 +137,6 @@ bool __init topology_parse_cpu_capacity(struct device_node *cpu_node, int cpu)
|
|||||||
sizeof(*raw_capacity),
|
sizeof(*raw_capacity),
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
if (!raw_capacity) {
|
if (!raw_capacity) {
|
||||||
pr_err("cpu_capacity: failed to allocate memory for raw capacities\n");
|
|
||||||
cap_parsing_failed = true;
|
cap_parsing_failed = true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -217,10 +216,8 @@ static int __init register_cpufreq_notifier(void)
|
|||||||
if (!acpi_disabled || !raw_capacity)
|
if (!acpi_disabled || !raw_capacity)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (!alloc_cpumask_var(&cpus_to_visit, GFP_KERNEL)) {
|
if (!alloc_cpumask_var(&cpus_to_visit, GFP_KERNEL))
|
||||||
pr_err("cpu_capacity: failed to allocate memory for cpus_to_visit\n");
|
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
|
||||||
|
|
||||||
cpumask_copy(cpus_to_visit, cpu_possible_mask);
|
cpumask_copy(cpus_to_visit, cpu_possible_mask);
|
||||||
|
|
||||||
|
@@ -323,8 +323,8 @@ EXPORT_SYMBOL_GPL(bus_for_each_dev);
|
|||||||
* return to the caller and not iterate over any more devices.
|
* return to the caller and not iterate over any more devices.
|
||||||
*/
|
*/
|
||||||
struct device *bus_find_device(struct bus_type *bus,
|
struct device *bus_find_device(struct bus_type *bus,
|
||||||
struct device *start, void *data,
|
struct device *start, const void *data,
|
||||||
int (*match)(struct device *dev, void *data))
|
int (*match)(struct device *dev, const void *data))
|
||||||
{
|
{
|
||||||
struct klist_iter i;
|
struct klist_iter i;
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
@@ -342,7 +342,7 @@ struct device *bus_find_device(struct bus_type *bus,
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(bus_find_device);
|
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;
|
const char *name = data;
|
||||||
|
|
||||||
|
@@ -660,7 +660,8 @@ static int cacheinfo_cpu_pre_down(unsigned int cpu)
|
|||||||
|
|
||||||
static int __init cacheinfo_sysfs_init(void)
|
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);
|
cacheinfo_cpu_online, cacheinfo_cpu_pre_down);
|
||||||
}
|
}
|
||||||
device_initcall(cacheinfo_sysfs_init);
|
device_initcall(cacheinfo_sysfs_init);
|
||||||
|
@@ -3356,3 +3356,9 @@ void device_set_of_node_from_dev(struct device *dev, const struct device *dev2)
|
|||||||
dev->of_node_reused = true;
|
dev->of_node_reused = true;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(device_set_of_node_from_dev);
|
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);
|
||||||
|
@@ -235,6 +235,19 @@ static int __init deferred_probe_timeout_setup(char *str)
|
|||||||
}
|
}
|
||||||
__setup("deferred_probe_timeout=", deferred_probe_timeout_setup);
|
__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
|
* driver_deferred_probe_check_state() - Check deferred probe state
|
||||||
* @dev: device to check
|
* @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)
|
int driver_deferred_probe_check_state(struct device *dev)
|
||||||
{
|
{
|
||||||
if (initcalls_done) {
|
int ret;
|
||||||
if (!deferred_probe_timeout) {
|
|
||||||
dev_WARN(dev, "deferred probe timeout, ignoring dependency");
|
ret = __driver_deferred_probe_check_state(dev);
|
||||||
return -ETIMEDOUT;
|
if (ret < 0)
|
||||||
}
|
return ret;
|
||||||
|
|
||||||
dev_warn(dev, "ignoring dependency for device, assuming no driver");
|
dev_warn(dev, "ignoring dependency for device, assuming no driver");
|
||||||
|
|
||||||
return -ENODEV;
|
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;
|
return -EPROBE_DEFER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -133,7 +133,7 @@ static struct bus_type *generic_match_buses[] = {
|
|||||||
NULL,
|
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;
|
return dev_fwnode(dev) == fwnode;
|
||||||
}
|
}
|
||||||
|
@@ -73,8 +73,8 @@ EXPORT_SYMBOL_GPL(driver_for_each_device);
|
|||||||
* return to the caller and not iterate over any more devices.
|
* return to the caller and not iterate over any more devices.
|
||||||
*/
|
*/
|
||||||
struct device *driver_find_device(struct device_driver *drv,
|
struct device *driver_find_device(struct device_driver *drv,
|
||||||
struct device *start, void *data,
|
struct device *start, const void *data,
|
||||||
int (*match)(struct device *dev, void *data))
|
int (*match)(struct device *dev, const void *data))
|
||||||
{
|
{
|
||||||
struct klist_iter i;
|
struct klist_iter i;
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
|
@@ -26,6 +26,9 @@ config FW_LOADER
|
|||||||
|
|
||||||
if FW_LOADER
|
if FW_LOADER
|
||||||
|
|
||||||
|
config FW_LOADER_PAGED_BUF
|
||||||
|
bool
|
||||||
|
|
||||||
config EXTRA_FIRMWARE
|
config EXTRA_FIRMWARE
|
||||||
string "Build named firmware blobs into the kernel binary"
|
string "Build named firmware blobs into the kernel binary"
|
||||||
help
|
help
|
||||||
@@ -67,6 +70,7 @@ config EXTRA_FIRMWARE_DIR
|
|||||||
|
|
||||||
config FW_LOADER_USER_HELPER
|
config FW_LOADER_USER_HELPER
|
||||||
bool "Enable the firmware sysfs fallback mechanism"
|
bool "Enable the firmware sysfs fallback mechanism"
|
||||||
|
select FW_LOADER_PAGED_BUF
|
||||||
help
|
help
|
||||||
This option enables a sysfs loading facility to enable firmware
|
This option enables a sysfs loading facility to enable firmware
|
||||||
loading to the kernel through userspace as a fallback mechanism
|
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.
|
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
|
endif # FW_LOADER
|
||||||
endmenu
|
endmenu
|
||||||
|
@@ -219,20 +219,6 @@ static ssize_t firmware_loading_show(struct device *dev,
|
|||||||
return sprintf(buf, "%d\n", loading);
|
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
|
* firmware_loading_store() - set value in the 'loading' control file
|
||||||
* @dev: device pointer
|
* @dev: device pointer
|
||||||
@@ -254,7 +240,6 @@ static ssize_t firmware_loading_store(struct device *dev,
|
|||||||
struct fw_priv *fw_priv;
|
struct fw_priv *fw_priv;
|
||||||
ssize_t written = count;
|
ssize_t written = count;
|
||||||
int loading = simple_strtol(buf, NULL, 10);
|
int loading = simple_strtol(buf, NULL, 10);
|
||||||
int i;
|
|
||||||
|
|
||||||
mutex_lock(&fw_lock);
|
mutex_lock(&fw_lock);
|
||||||
fw_priv = fw_sysfs->fw_priv;
|
fw_priv = fw_sysfs->fw_priv;
|
||||||
@@ -265,12 +250,7 @@ static ssize_t firmware_loading_store(struct device *dev,
|
|||||||
case 1:
|
case 1:
|
||||||
/* discarding any previous partial load */
|
/* discarding any previous partial load */
|
||||||
if (!fw_sysfs_done(fw_priv)) {
|
if (!fw_sysfs_done(fw_priv)) {
|
||||||
for (i = 0; i < fw_priv->nr_pages; i++)
|
fw_free_paged_buf(fw_priv);
|
||||||
__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_state_start(fw_priv);
|
fw_state_start(fw_priv);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -284,7 +264,7 @@ static ssize_t firmware_loading_store(struct device *dev,
|
|||||||
* see the mapped 'buf->data' once the loading
|
* see the mapped 'buf->data' once the loading
|
||||||
* is completed.
|
* is completed.
|
||||||
* */
|
* */
|
||||||
rc = map_fw_priv_pages(fw_priv);
|
rc = fw_map_paged_buf(fw_priv);
|
||||||
if (rc)
|
if (rc)
|
||||||
dev_err(dev, "%s: map pages failed\n",
|
dev_err(dev, "%s: map pages failed\n",
|
||||||
__func__);
|
__func__);
|
||||||
@@ -389,40 +369,13 @@ out:
|
|||||||
|
|
||||||
static int fw_realloc_pages(struct fw_sysfs *fw_sysfs, int min_size)
|
static int fw_realloc_pages(struct fw_sysfs *fw_sysfs, int min_size)
|
||||||
{
|
{
|
||||||
struct fw_priv *fw_priv= fw_sysfs->fw_priv;
|
int err;
|
||||||
int pages_needed = PAGE_ALIGN(min_size) >> PAGE_SHIFT;
|
|
||||||
|
|
||||||
/* If the array of pages is too small, grow it... */
|
err = fw_grow_paged_buf(fw_sysfs->fw_priv,
|
||||||
if (fw_priv->page_array_size < pages_needed) {
|
PAGE_ALIGN(min_size) >> PAGE_SHIFT);
|
||||||
int new_array_size = max(pages_needed,
|
if (err)
|
||||||
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);
|
fw_load_abort(fw_sysfs);
|
||||||
return -ENOMEM;
|
return err;
|
||||||
}
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -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 */
|
/* Also permit LSMs and IMA to fail firmware sysfs fallback */
|
||||||
ret = security_kernel_load_data(LOADING_FIRMWARE);
|
ret = security_kernel_load_data(LOADING_FIRMWARE);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return false;
|
||||||
|
|
||||||
return fw_force_sysfs_fallback(opt_flags);
|
return fw_force_sysfs_fallback(opt_flags);
|
||||||
}
|
}
|
||||||
|
@@ -64,12 +64,14 @@ struct fw_priv {
|
|||||||
void *data;
|
void *data;
|
||||||
size_t size;
|
size_t size;
|
||||||
size_t allocated_size;
|
size_t allocated_size;
|
||||||
#ifdef CONFIG_FW_LOADER_USER_HELPER
|
#ifdef CONFIG_FW_LOADER_PAGED_BUF
|
||||||
bool is_paged_buf;
|
bool is_paged_buf;
|
||||||
bool need_uevent;
|
|
||||||
struct page **pages;
|
struct page **pages;
|
||||||
int nr_pages;
|
int nr_pages;
|
||||||
int page_array_size;
|
int page_array_size;
|
||||||
|
#endif
|
||||||
|
#ifdef CONFIG_FW_LOADER_USER_HELPER
|
||||||
|
bool need_uevent;
|
||||||
struct list_head pending_list;
|
struct list_head pending_list;
|
||||||
#endif
|
#endif
|
||||||
const char *fw_name;
|
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,
|
int assign_fw(struct firmware *fw, struct device *device,
|
||||||
enum fw_opt opt_flags);
|
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 */
|
#endif /* __FIRMWARE_LOADER_H */
|
||||||
|
@@ -33,6 +33,7 @@
|
|||||||
#include <linux/syscore_ops.h>
|
#include <linux/syscore_ops.h>
|
||||||
#include <linux/reboot.h>
|
#include <linux/reboot.h>
|
||||||
#include <linux/security.h>
|
#include <linux/security.h>
|
||||||
|
#include <linux/xz.h>
|
||||||
|
|
||||||
#include <generated/utsrelease.h>
|
#include <generated/utsrelease.h>
|
||||||
|
|
||||||
@@ -251,15 +252,7 @@ static void __free_fw_priv(struct kref *ref)
|
|||||||
list_del(&fw_priv->list);
|
list_del(&fw_priv->list);
|
||||||
spin_unlock(&fwc->lock);
|
spin_unlock(&fwc->lock);
|
||||||
|
|
||||||
#ifdef CONFIG_FW_LOADER_USER_HELPER
|
fw_free_paged_buf(fw_priv); /* free leftover pages */
|
||||||
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
|
|
||||||
if (!fw_priv->allocated_size)
|
if (!fw_priv->allocated_size)
|
||||||
vfree(fw_priv->data);
|
vfree(fw_priv->data);
|
||||||
kfree_const(fw_priv->fw_name);
|
kfree_const(fw_priv->fw_name);
|
||||||
@@ -274,6 +267,174 @@ static void free_fw_priv(struct fw_priv *fw_priv)
|
|||||||
spin_unlock(&fwc->lock);
|
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 */
|
/* direct firmware loading support */
|
||||||
static char fw_path_para[256];
|
static char fw_path_para[256];
|
||||||
static const char * const fw_path[] = {
|
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");
|
MODULE_PARM_DESC(path, "customized firmware image search path with a higher priority than default path");
|
||||||
|
|
||||||
static int
|
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;
|
loff_t size;
|
||||||
int i, len;
|
int i, len;
|
||||||
@@ -301,9 +467,11 @@ fw_get_filesystem_firmware(struct device *device, struct fw_priv *fw_priv)
|
|||||||
char *path;
|
char *path;
|
||||||
enum kernel_read_file_id id = READING_FIRMWARE;
|
enum kernel_read_file_id id = READING_FIRMWARE;
|
||||||
size_t msize = INT_MAX;
|
size_t msize = INT_MAX;
|
||||||
|
void *buffer = NULL;
|
||||||
|
|
||||||
/* Already populated data member means we're loading into a buffer */
|
/* 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;
|
id = READING_FIRMWARE_PREALLOC_BUFFER;
|
||||||
msize = fw_priv->allocated_size;
|
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])
|
if (!fw_path[i][0])
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
len = snprintf(path, PATH_MAX, "%s/%s",
|
len = snprintf(path, PATH_MAX, "%s/%s%s",
|
||||||
fw_path[i], fw_priv->fw_name);
|
fw_path[i], fw_priv->fw_name, suffix);
|
||||||
if (len >= PATH_MAX) {
|
if (len >= PATH_MAX) {
|
||||||
rc = -ENAMETOOLONG;
|
rc = -ENAMETOOLONG;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
fw_priv->size = 0;
|
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);
|
msize, id);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
if (rc != -ENOENT)
|
if (rc != -ENOENT)
|
||||||
@@ -336,8 +504,24 @@ fw_get_filesystem_firmware(struct device *device, struct fw_priv *fw_priv)
|
|||||||
path);
|
path);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
dev_dbg(device, "direct-loading %s\n", fw_priv->fw_name);
|
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_priv->size = size;
|
||||||
|
}
|
||||||
fw_state_done(fw_priv);
|
fw_state_done(fw_priv);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -584,7 +768,13 @@ _request_firmware(const struct firmware **firmware_p, const char *name,
|
|||||||
if (ret <= 0) /* error or already assigned */
|
if (ret <= 0) /* error or already assigned */
|
||||||
goto out;
|
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 (ret) {
|
||||||
if (!(opt_flags & FW_OPT_NO_WARN))
|
if (!(opt_flags & FW_OPT_NO_WARN))
|
||||||
dev_warn(device,
|
dev_warn(device,
|
||||||
|
@@ -66,6 +66,7 @@ static DEVICE_ATTR(cpulist, S_IRUGO, node_read_cpulist, NULL);
|
|||||||
* @dev: Device for this memory access class
|
* @dev: Device for this memory access class
|
||||||
* @list_node: List element in the node's access list
|
* @list_node: List element in the node's access list
|
||||||
* @access: The access class rank
|
* @access: The access class rank
|
||||||
|
* @hmem_attrs: Heterogeneous memory performance attributes
|
||||||
*/
|
*/
|
||||||
struct node_access_nodes {
|
struct node_access_nodes {
|
||||||
struct device dev;
|
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
|
* register_memory_node_under_compute_node - link memory node to its compute
|
||||||
* node for a given access class.
|
* node for a given access class.
|
||||||
* @mem_node: Memory node number
|
* @mem_nid: Memory node number
|
||||||
* @cpu_node: Cpu node number
|
* @cpu_nid: Cpu node number
|
||||||
* @access: Access class to register
|
* @access: Access class to register
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
|
@@ -5,7 +5,7 @@
|
|||||||
* Copyright (c) 2002-3 Patrick Mochel
|
* Copyright (c) 2002-3 Patrick Mochel
|
||||||
* Copyright (c) 2002-3 Open Source Development Labs
|
* 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.
|
* information.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@@ -2819,9 +2819,9 @@ static const struct device_type bmc_device_type = {
|
|||||||
.groups = bmc_dev_attr_groups,
|
.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;
|
struct bmc_device *bmc;
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
@@ -2857,9 +2857,9 @@ struct prod_dev_id {
|
|||||||
unsigned char device_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;
|
struct bmc_device *bmc;
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
|
@@ -426,7 +426,7 @@ static int ipmi_remove(struct platform_device *pdev)
|
|||||||
return ipmi_si_remove_by_dev(&pdev->dev);
|
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);
|
struct platform_device *pdev = to_platform_device(dev);
|
||||||
const char *name = data;
|
const char *name = data;
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
/*
|
/*
|
||||||
* System Control and Management Interface (SCMI) Message Protocol
|
* System Control and Management Interface (SCMI) Message Protocol
|
||||||
* driver common header file containing some definitions, structures
|
* driver common header file containing some definitions, structures
|
||||||
|
@@ -17,9 +17,9 @@ struct acpi_hid_uid {
|
|||||||
char uid[11]; /* UINT_MAX + null byte */
|
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);
|
struct acpi_device *adev = to_acpi_device(dev);
|
||||||
|
|
||||||
if (acpi_match_device_ids(adev, hid_uid.hid))
|
if (acpi_match_device_ids(adev, hid_uid.hid))
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
// SPDX-License-Identifier: BSD-3-Clause
|
/* SPDX-License-Identifier: BSD-3-Clause */
|
||||||
/*
|
/*
|
||||||
* Texas Instruments System Control Interface (TISCI) Protocol
|
* Texas Instruments System Control Interface (TISCI) Protocol
|
||||||
*
|
*
|
||||||
|
@@ -22,11 +22,6 @@ static const struct of_device_id fpga_region_of_match[] = {
|
|||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(of, 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
|
* of_fpga_region_find - find FPGA region
|
||||||
* @np: device node of 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)
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -41,7 +41,7 @@ MODULE_PARM_DESC(mask, "GPIO channel mask.");
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* FIXME: convert this singleton driver to use the state container
|
* 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 {
|
static struct cs5535_gpio_chip {
|
||||||
struct gpio_chip chip;
|
struct gpio_chip chip;
|
||||||
|
@@ -93,7 +93,7 @@ static struct bus_type mipi_dsi_bus_type = {
|
|||||||
.pm = &mipi_dsi_device_pm_ops,
|
.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;
|
return dev->of_node == data;
|
||||||
}
|
}
|
||||||
|
@@ -2372,10 +2372,10 @@ static int tegra_dc_parse_dt(struct tegra_dc *dc)
|
|||||||
return 0;
|
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);
|
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;
|
return dc->pipe == pipe;
|
||||||
}
|
}
|
||||||
|
@@ -525,23 +525,12 @@ static const struct file_operations debug_func_knob_fops = {
|
|||||||
|
|
||||||
static int debug_func_init(void)
|
static int debug_func_init(void)
|
||||||
{
|
{
|
||||||
struct dentry *file;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/* Create debugfs node */
|
/* Create debugfs node */
|
||||||
debug_debugfs_dir = debugfs_create_dir("coresight_cpu_debug", NULL);
|
debug_debugfs_dir = debugfs_create_dir("coresight_cpu_debug", NULL);
|
||||||
if (!debug_debugfs_dir) {
|
debugfs_create_file("enable", 0644, debug_debugfs_dir, NULL,
|
||||||
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);
|
&debug_func_knob_fops);
|
||||||
if (!file) {
|
|
||||||
pr_err("%s: unable to create enable knob file\n", __func__);
|
|
||||||
ret = -ENOMEM;
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Register function to be called for panic */
|
/* Register function to be called for panic */
|
||||||
ret = atomic_notifier_chain_register(&panic_notifier_list,
|
ret = atomic_notifier_chain_register(&panic_notifier_list,
|
||||||
|
@@ -37,7 +37,7 @@ static int coresight_alloc_conns(struct device *dev,
|
|||||||
return 0;
|
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;
|
return dev_fwnode(dev) == fwnode;
|
||||||
}
|
}
|
||||||
|
@@ -498,9 +498,9 @@ struct coresight_device *coresight_get_sink(struct list_head *path)
|
|||||||
return csdev;
|
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);
|
struct coresight_device *csdev = to_coresight_device(dev);
|
||||||
|
|
||||||
if ((csdev->type == CORESIGHT_DEV_TYPE_SINK ||
|
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;
|
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);
|
struct coresight_device *csdev = to_coresight_device(dev);
|
||||||
unsigned long hash;
|
unsigned long hash;
|
||||||
|
@@ -789,10 +789,9 @@ static int intel_th_populate(struct intel_th *th)
|
|||||||
return 0;
|
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;
|
return dev->devt == devt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -457,7 +457,7 @@ static struct pci_driver amd_mp2_pci_driver = {
|
|||||||
};
|
};
|
||||||
module_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;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@@ -320,7 +320,7 @@ u32 i2c_acpi_find_bus_speed(struct device *dev)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(i2c_acpi_find_bus_speed);
|
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);
|
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;
|
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;
|
return ACPI_COMPANION(dev) == data;
|
||||||
}
|
}
|
||||||
|
@@ -112,12 +112,12 @@ void of_i2c_register_devices(struct i2c_adapter *adap)
|
|||||||
of_node_put(bus);
|
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;
|
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)
|
if (dev->of_node == data)
|
||||||
return 1;
|
return 1;
|
||||||
|
@@ -90,7 +90,7 @@ static const struct iio_chan_spec
|
|||||||
|
|
||||||
#ifdef CONFIG_OF
|
#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;
|
return dev->of_node == data && dev->type == &iio_device_type;
|
||||||
}
|
}
|
||||||
|
@@ -4498,7 +4498,7 @@ static const struct acpi_device_id hns_roce_acpi_match[] = {
|
|||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(acpi, 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;
|
return dev->fwnode == fwnode;
|
||||||
}
|
}
|
||||||
|
@@ -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 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;
|
return dev->fwnode == data;
|
||||||
}
|
}
|
||||||
|
@@ -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;
|
return dev->fwnode == data;
|
||||||
}
|
}
|
||||||
|
@@ -296,8 +296,6 @@ struct flexrm_mbox {
|
|||||||
struct dma_pool *bd_pool;
|
struct dma_pool *bd_pool;
|
||||||
struct dma_pool *cmpl_pool;
|
struct dma_pool *cmpl_pool;
|
||||||
struct dentry *root;
|
struct dentry *root;
|
||||||
struct dentry *config;
|
|
||||||
struct dentry *stats;
|
|
||||||
struct mbox_controller controller;
|
struct mbox_controller controller;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1603,7 +1601,6 @@ static int flexrm_mbox_probe(struct platform_device *pdev)
|
|||||||
1 << RING_CMPL_ALIGN_ORDER, 0);
|
1 << RING_CMPL_ALIGN_ORDER, 0);
|
||||||
if (!mbox->cmpl_pool) {
|
if (!mbox->cmpl_pool) {
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
goto fail_destroy_bd_pool;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Allocate platform MSIs for each ring */
|
/* Allocate platform MSIs for each ring */
|
||||||
@@ -1624,28 +1621,15 @@ static int flexrm_mbox_probe(struct platform_device *pdev)
|
|||||||
|
|
||||||
/* Create debugfs root entry */
|
/* Create debugfs root entry */
|
||||||
mbox->root = debugfs_create_dir(dev_name(mbox->dev), NULL);
|
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 */
|
/* Create debugfs config entry */
|
||||||
mbox->config = debugfs_create_devm_seqfile(mbox->dev,
|
debugfs_create_devm_seqfile(mbox->dev, "config", mbox->root,
|
||||||
"config", mbox->root,
|
|
||||||
flexrm_debugfs_conf_show);
|
flexrm_debugfs_conf_show);
|
||||||
if (IS_ERR_OR_NULL(mbox->config)) {
|
|
||||||
ret = PTR_ERR_OR_ZERO(mbox->config);
|
|
||||||
goto fail_free_debugfs_root;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Create debugfs stats entry */
|
/* Create debugfs stats entry */
|
||||||
mbox->stats = debugfs_create_devm_seqfile(mbox->dev,
|
debugfs_create_devm_seqfile(mbox->dev, "stats", mbox->root,
|
||||||
"stats", mbox->root,
|
|
||||||
flexrm_debugfs_stats_show);
|
flexrm_debugfs_stats_show);
|
||||||
if (IS_ERR_OR_NULL(mbox->stats)) {
|
|
||||||
ret = PTR_ERR_OR_ZERO(mbox->stats);
|
|
||||||
goto fail_free_debugfs_root;
|
|
||||||
}
|
|
||||||
skip_debugfs:
|
skip_debugfs:
|
||||||
|
|
||||||
/* Initialize mailbox controller */
|
/* Initialize mailbox controller */
|
||||||
@@ -1676,11 +1660,9 @@ skip_debugfs:
|
|||||||
|
|
||||||
fail_free_debugfs_root:
|
fail_free_debugfs_root:
|
||||||
debugfs_remove_recursive(mbox->root);
|
debugfs_remove_recursive(mbox->root);
|
||||||
fail_free_msis:
|
|
||||||
platform_msi_domain_free_irqs(dev);
|
platform_msi_domain_free_irqs(dev);
|
||||||
fail_destroy_cmpl_pool:
|
fail_destroy_cmpl_pool:
|
||||||
dma_pool_destroy(mbox->cmpl_pool);
|
dma_pool_destroy(mbox->cmpl_pool);
|
||||||
fail_destroy_bd_pool:
|
|
||||||
dma_pool_destroy(mbox->bd_pool);
|
dma_pool_destroy(mbox->bd_pool);
|
||||||
fail:
|
fail:
|
||||||
return ret;
|
return ret;
|
||||||
|
@@ -395,8 +395,6 @@ struct pdc_state {
|
|||||||
*/
|
*/
|
||||||
struct scatterlist *src_sg[PDC_RING_ENTRIES];
|
struct scatterlist *src_sg[PDC_RING_ENTRIES];
|
||||||
|
|
||||||
struct dentry *debugfs_stats; /* debug FS stats file for this PDC */
|
|
||||||
|
|
||||||
/* counters */
|
/* counters */
|
||||||
u32 pdc_requests; /* number of request messages submitted */
|
u32 pdc_requests; /* number of request messages submitted */
|
||||||
u32 pdc_replies; /* number of reply messages received */
|
u32 pdc_replies; /* number of reply messages received */
|
||||||
@@ -501,8 +499,7 @@ static void pdc_setup_debugfs(struct pdc_state *pdcs)
|
|||||||
debugfs_dir = debugfs_create_dir(KBUILD_MODNAME, NULL);
|
debugfs_dir = debugfs_create_dir(KBUILD_MODNAME, NULL);
|
||||||
|
|
||||||
/* S_IRUSR == 0400 */
|
/* S_IRUSR == 0400 */
|
||||||
pdcs->debugfs_stats = debugfs_create_file(spu_stats_name, 0400,
|
debugfs_create_file(spu_stats_name, 0400, debugfs_dir, pdcs,
|
||||||
debugfs_dir, pdcs,
|
|
||||||
&pdc_debugfs_stats);
|
&pdc_debugfs_stats);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1603,7 +1600,6 @@ static int pdc_probe(struct platform_device *pdev)
|
|||||||
if (err)
|
if (err)
|
||||||
goto cleanup_buf_pool;
|
goto cleanup_buf_pool;
|
||||||
|
|
||||||
pdcs->debugfs_stats = NULL;
|
|
||||||
pdc_setup_debugfs(pdcs);
|
pdc_setup_debugfs(pdcs);
|
||||||
|
|
||||||
dev_dbg(dev, "pdc_probe() successful");
|
dev_dbg(dev, "pdc_probe() successful");
|
||||||
|
@@ -92,9 +92,9 @@ static struct regmap_config altr_sysmgr_regmap_cfg = {
|
|||||||
* Matching function used by driver_find_device().
|
* Matching function used by driver_find_device().
|
||||||
* Return: True if match is found, otherwise false.
|
* 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -190,27 +190,6 @@ struct regmap *syscon_regmap_lookup_by_compatible(const char *s)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(syscon_regmap_lookup_by_compatible);
|
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,
|
struct regmap *syscon_regmap_lookup_by_phandle(struct device_node *np,
|
||||||
const char *property)
|
const char *property)
|
||||||
{
|
{
|
||||||
|
@@ -908,11 +908,11 @@ void cxl_update_dedicated_ivtes_psl8(struct cxl_context *ctx);
|
|||||||
|
|
||||||
#ifdef CONFIG_DEBUG_FS
|
#ifdef CONFIG_DEBUG_FS
|
||||||
|
|
||||||
int cxl_debugfs_init(void);
|
void cxl_debugfs_init(void);
|
||||||
void cxl_debugfs_exit(void);
|
void cxl_debugfs_exit(void);
|
||||||
int cxl_debugfs_adapter_add(struct cxl *adapter);
|
void cxl_debugfs_adapter_add(struct cxl *adapter);
|
||||||
void cxl_debugfs_adapter_remove(struct cxl *adapter);
|
void cxl_debugfs_adapter_remove(struct cxl *adapter);
|
||||||
int cxl_debugfs_afu_add(struct cxl_afu *afu);
|
void cxl_debugfs_afu_add(struct cxl_afu *afu);
|
||||||
void cxl_debugfs_afu_remove(struct cxl_afu *afu);
|
void cxl_debugfs_afu_remove(struct cxl_afu *afu);
|
||||||
void cxl_debugfs_add_adapter_regs_psl9(struct cxl *adapter, struct dentry *dir);
|
void cxl_debugfs_add_adapter_regs_psl9(struct cxl *adapter, struct dentry *dir);
|
||||||
void cxl_debugfs_add_adapter_regs_psl8(struct cxl *adapter, struct dentry *dir);
|
void cxl_debugfs_add_adapter_regs_psl8(struct cxl *adapter, struct dentry *dir);
|
||||||
@@ -921,27 +921,24 @@ void cxl_debugfs_add_afu_regs_psl8(struct cxl_afu *afu, struct dentry *dir);
|
|||||||
|
|
||||||
#else /* CONFIG_DEBUG_FS */
|
#else /* CONFIG_DEBUG_FS */
|
||||||
|
|
||||||
static inline int __init cxl_debugfs_init(void)
|
static inline void __init cxl_debugfs_init(void)
|
||||||
{
|
{
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void cxl_debugfs_exit(void)
|
static inline void cxl_debugfs_exit(void)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int cxl_debugfs_adapter_add(struct cxl *adapter)
|
static inline void cxl_debugfs_adapter_add(struct cxl *adapter)
|
||||||
{
|
{
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void cxl_debugfs_adapter_remove(struct cxl *adapter)
|
static inline void cxl_debugfs_adapter_remove(struct cxl *adapter)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int cxl_debugfs_afu_add(struct cxl_afu *afu)
|
static inline void cxl_debugfs_afu_add(struct cxl_afu *afu)
|
||||||
{
|
{
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void cxl_debugfs_afu_remove(struct cxl_afu *afu)
|
static inline void cxl_debugfs_afu_remove(struct cxl_afu *afu)
|
||||||
|
@@ -26,11 +26,11 @@ static int debugfs_io_u64_set(void *data, u64 val)
|
|||||||
DEFINE_DEBUGFS_ATTRIBUTE(fops_io_x64, debugfs_io_u64_get, debugfs_io_u64_set,
|
DEFINE_DEBUGFS_ATTRIBUTE(fops_io_x64, debugfs_io_u64_get, debugfs_io_u64_set,
|
||||||
"0x%016llx\n");
|
"0x%016llx\n");
|
||||||
|
|
||||||
static struct dentry *debugfs_create_io_x64(const char *name, umode_t mode,
|
static void debugfs_create_io_x64(const char *name, umode_t mode,
|
||||||
struct dentry *parent, u64 __iomem *value)
|
struct dentry *parent, u64 __iomem *value)
|
||||||
{
|
{
|
||||||
return debugfs_create_file_unsafe(name, mode, parent,
|
debugfs_create_file_unsafe(name, mode, parent, (void __force *)value,
|
||||||
(void __force *)value, &fops_io_x64);
|
&fops_io_x64);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cxl_debugfs_add_adapter_regs_psl9(struct cxl *adapter, struct dentry *dir)
|
void cxl_debugfs_add_adapter_regs_psl9(struct cxl *adapter, struct dentry *dir)
|
||||||
@@ -54,25 +54,22 @@ void cxl_debugfs_add_adapter_regs_psl8(struct cxl *adapter, struct dentry *dir)
|
|||||||
debugfs_create_io_x64("trace", S_IRUSR | S_IWUSR, dir, _cxl_p1_addr(adapter, CXL_PSL_TRACE));
|
debugfs_create_io_x64("trace", S_IRUSR | S_IWUSR, dir, _cxl_p1_addr(adapter, CXL_PSL_TRACE));
|
||||||
}
|
}
|
||||||
|
|
||||||
int cxl_debugfs_adapter_add(struct cxl *adapter)
|
void cxl_debugfs_adapter_add(struct cxl *adapter)
|
||||||
{
|
{
|
||||||
struct dentry *dir;
|
struct dentry *dir;
|
||||||
char buf[32];
|
char buf[32];
|
||||||
|
|
||||||
if (!cxl_debugfs)
|
if (!cxl_debugfs)
|
||||||
return -ENODEV;
|
return;
|
||||||
|
|
||||||
snprintf(buf, 32, "card%i", adapter->adapter_num);
|
snprintf(buf, 32, "card%i", adapter->adapter_num);
|
||||||
dir = debugfs_create_dir(buf, cxl_debugfs);
|
dir = debugfs_create_dir(buf, cxl_debugfs);
|
||||||
if (IS_ERR(dir))
|
|
||||||
return PTR_ERR(dir);
|
|
||||||
adapter->debugfs = dir;
|
adapter->debugfs = dir;
|
||||||
|
|
||||||
debugfs_create_io_x64("err_ivte", S_IRUSR, dir, _cxl_p1_addr(adapter, CXL_PSL_ErrIVTE));
|
debugfs_create_io_x64("err_ivte", S_IRUSR, dir, _cxl_p1_addr(adapter, CXL_PSL_ErrIVTE));
|
||||||
|
|
||||||
if (adapter->native->sl_ops->debugfs_add_adapter_regs)
|
if (adapter->native->sl_ops->debugfs_add_adapter_regs)
|
||||||
adapter->native->sl_ops->debugfs_add_adapter_regs(adapter, dir);
|
adapter->native->sl_ops->debugfs_add_adapter_regs(adapter, dir);
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void cxl_debugfs_adapter_remove(struct cxl *adapter)
|
void cxl_debugfs_adapter_remove(struct cxl *adapter)
|
||||||
@@ -96,18 +93,16 @@ void cxl_debugfs_add_afu_regs_psl8(struct cxl_afu *afu, struct dentry *dir)
|
|||||||
debugfs_create_io_x64("trace", S_IRUSR | S_IWUSR, dir, _cxl_p1n_addr(afu, CXL_PSL_SLICE_TRACE));
|
debugfs_create_io_x64("trace", S_IRUSR | S_IWUSR, dir, _cxl_p1n_addr(afu, CXL_PSL_SLICE_TRACE));
|
||||||
}
|
}
|
||||||
|
|
||||||
int cxl_debugfs_afu_add(struct cxl_afu *afu)
|
void cxl_debugfs_afu_add(struct cxl_afu *afu)
|
||||||
{
|
{
|
||||||
struct dentry *dir;
|
struct dentry *dir;
|
||||||
char buf[32];
|
char buf[32];
|
||||||
|
|
||||||
if (!afu->adapter->debugfs)
|
if (!afu->adapter->debugfs)
|
||||||
return -ENODEV;
|
return;
|
||||||
|
|
||||||
snprintf(buf, 32, "psl%i.%i", afu->adapter->adapter_num, afu->slice);
|
snprintf(buf, 32, "psl%i.%i", afu->adapter->adapter_num, afu->slice);
|
||||||
dir = debugfs_create_dir(buf, afu->adapter->debugfs);
|
dir = debugfs_create_dir(buf, afu->adapter->debugfs);
|
||||||
if (IS_ERR(dir))
|
|
||||||
return PTR_ERR(dir);
|
|
||||||
afu->debugfs = dir;
|
afu->debugfs = dir;
|
||||||
|
|
||||||
debugfs_create_io_x64("sr", S_IRUSR, dir, _cxl_p1n_addr(afu, CXL_PSL_SR_An));
|
debugfs_create_io_x64("sr", S_IRUSR, dir, _cxl_p1n_addr(afu, CXL_PSL_SR_An));
|
||||||
@@ -118,8 +113,6 @@ int cxl_debugfs_afu_add(struct cxl_afu *afu)
|
|||||||
|
|
||||||
if (afu->adapter->native->sl_ops->debugfs_add_afu_regs)
|
if (afu->adapter->native->sl_ops->debugfs_add_afu_regs)
|
||||||
afu->adapter->native->sl_ops->debugfs_add_afu_regs(afu, dir);
|
afu->adapter->native->sl_ops->debugfs_add_afu_regs(afu, dir);
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void cxl_debugfs_afu_remove(struct cxl_afu *afu)
|
void cxl_debugfs_afu_remove(struct cxl_afu *afu)
|
||||||
@@ -127,19 +120,12 @@ void cxl_debugfs_afu_remove(struct cxl_afu *afu)
|
|||||||
debugfs_remove_recursive(afu->debugfs);
|
debugfs_remove_recursive(afu->debugfs);
|
||||||
}
|
}
|
||||||
|
|
||||||
int __init cxl_debugfs_init(void)
|
void __init cxl_debugfs_init(void)
|
||||||
{
|
{
|
||||||
struct dentry *ent;
|
|
||||||
|
|
||||||
if (!cpu_has_feature(CPU_FTR_HVMODE))
|
if (!cpu_has_feature(CPU_FTR_HVMODE))
|
||||||
return 0;
|
return;
|
||||||
|
|
||||||
ent = debugfs_create_dir("cxl", NULL);
|
cxl_debugfs = debugfs_create_dir("cxl", NULL);
|
||||||
if (IS_ERR(ent))
|
|
||||||
return PTR_ERR(ent);
|
|
||||||
cxl_debugfs = ent;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void cxl_debugfs_exit(void)
|
void cxl_debugfs_exit(void)
|
||||||
|
@@ -1369,10 +1369,6 @@ static int __init genwqe_init_module(void)
|
|||||||
class_genwqe->devnode = genwqe_devnode;
|
class_genwqe->devnode = genwqe_devnode;
|
||||||
|
|
||||||
debugfs_genwqe = debugfs_create_dir(GENWQE_DEVNAME, NULL);
|
debugfs_genwqe = debugfs_create_dir(GENWQE_DEVNAME, NULL);
|
||||||
if (!debugfs_genwqe) {
|
|
||||||
rc = -ENOMEM;
|
|
||||||
goto err_out;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = pci_register_driver(&genwqe_driver);
|
rc = pci_register_driver(&genwqe_driver);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
@@ -1384,7 +1380,6 @@ static int __init genwqe_init_module(void)
|
|||||||
|
|
||||||
err_out0:
|
err_out0:
|
||||||
debugfs_remove(debugfs_genwqe);
|
debugfs_remove(debugfs_genwqe);
|
||||||
err_out:
|
|
||||||
class_destroy(class_genwqe);
|
class_destroy(class_genwqe);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@@ -437,7 +437,7 @@ int genwqe_device_create(struct genwqe_dev *cd);
|
|||||||
int genwqe_device_remove(struct genwqe_dev *cd);
|
int genwqe_device_remove(struct genwqe_dev *cd);
|
||||||
|
|
||||||
/* debugfs */
|
/* debugfs */
|
||||||
int genwqe_init_debugfs(struct genwqe_dev *cd);
|
void genwqe_init_debugfs(struct genwqe_dev *cd);
|
||||||
void genqwe_exit_debugfs(struct genwqe_dev *cd);
|
void genqwe_exit_debugfs(struct genwqe_dev *cd);
|
||||||
|
|
||||||
int genwqe_read_softreset(struct genwqe_dev *cd);
|
int genwqe_read_softreset(struct genwqe_dev *cd);
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user