Merge remote-tracking branch 'linus/master'
diff --git a/.gitignore b/.gitignore index 5937c74..f2f63e4 100644 --- a/.gitignore +++ b/.gitignore
@@ -65,6 +65,7 @@ /vmlinux.32 /vmlinux.map /vmlinux.symvers +/vmlinux.unstripped /vmlinux-gdb.py /vmlinuz /System.map
diff --git a/.mailmap b/.mailmap index c85576e..4f7cd8e 100644 --- a/.mailmap +++ b/.mailmap
@@ -549,6 +549,8 @@ Nicolas Pitre <nico@fluxnic.net> <nico@linaro.org> Nicolas Saenz Julienne <nsaenz@kernel.org> <nsaenzjulienne@suse.de> Nicolas Saenz Julienne <nsaenz@kernel.org> <nsaenzjulienne@suse.com> +Nicolas Schier <nicolas.schier@linux.dev> <n.schier@avm.de> +Nicolas Schier <nicolas.schier@linux.dev> <nicolas@fjasle.eu> Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se> Nikolay Aleksandrov <razor@blackwall.org> <naleksan@redhat.com> Nikolay Aleksandrov <razor@blackwall.org> <nikolay@redhat.com>
diff --git a/CREDITS b/CREDITS index 660d5e6..1b77fba 100644 --- a/CREDITS +++ b/CREDITS
@@ -317,6 +317,10 @@ S: Greenbelt, Maryland 20771 S: USA +N: Joel Becker +E: jlbec@evilplan.org +D: configfs + N: Adam Belay E: ambx1@neo.rr.com D: Linux Plug and Play Support @@ -3666,6 +3670,10 @@ S: Kingston, Ontario S: Canada K7L 2P4 +N: Pravin B Shelar +E: pshelar@ovn.org +D: Open vSwitch maintenance and contributions + N: John Shifflett E: john@geolog.com E: jshiffle@netcom.com
diff --git a/Documentation/ABI/obsolete/sysfs-class-cxl b/Documentation/ABI/removed/sysfs-class-cxl similarity index 87% rename from Documentation/ABI/obsolete/sysfs-class-cxl rename to Documentation/ABI/removed/sysfs-class-cxl index 8cba1b6..266c413 100644 --- a/Documentation/ABI/obsolete/sysfs-class-cxl +++ b/Documentation/ABI/removed/sysfs-class-cxl
@@ -1,5 +1,4 @@ -The cxl driver is no longer maintained, and will be removed from the kernel in -the near future. +The cxl driver was removed in 6.15. Please note that attributes that are shared between devices are stored in the directory pointed to by the symlink device/. @@ -10,7 +9,7 @@ Slave contexts (eg. /sys/class/cxl/afu0.0s): What: /sys/class/cxl/<afu>/afu_err_buf -Date: September 2014 +Date: September 2014, removed February 2025 Contact: linuxppc-dev@lists.ozlabs.org Description: read only AFU Error Buffer contents. The contents of this file are @@ -21,7 +20,7 @@ What: /sys/class/cxl/<afu>/irqs_max -Date: September 2014 +Date: September 2014, removed February 2025 Contact: linuxppc-dev@lists.ozlabs.org Description: read/write Decimal value of maximum number of interrupts that can be @@ -32,7 +31,7 @@ Users: https://github.com/ibm-capi/libcxl What: /sys/class/cxl/<afu>/irqs_min -Date: September 2014 +Date: September 2014, removed February 2025 Contact: linuxppc-dev@lists.ozlabs.org Description: read only Decimal value of the minimum number of interrupts that @@ -42,7 +41,7 @@ Users: https://github.com/ibm-capi/libcxl What: /sys/class/cxl/<afu>/mmio_size -Date: September 2014 +Date: September 2014, removed February 2025 Contact: linuxppc-dev@lists.ozlabs.org Description: read only Decimal value of the size of the MMIO space that may be mmapped @@ -50,7 +49,7 @@ Users: https://github.com/ibm-capi/libcxl What: /sys/class/cxl/<afu>/modes_supported -Date: September 2014 +Date: September 2014, removed February 2025 Contact: linuxppc-dev@lists.ozlabs.org Description: read only List of the modes this AFU supports. One per line. @@ -58,7 +57,7 @@ Users: https://github.com/ibm-capi/libcxl What: /sys/class/cxl/<afu>/mode -Date: September 2014 +Date: September 2014, removed February 2025 Contact: linuxppc-dev@lists.ozlabs.org Description: read/write The current mode the AFU is using. Will be one of the modes @@ -68,7 +67,7 @@ What: /sys/class/cxl/<afu>/prefault_mode -Date: September 2014 +Date: September 2014, removed February 2025 Contact: linuxppc-dev@lists.ozlabs.org Description: read/write Set the mode for prefaulting in segments into the segment table @@ -88,7 +87,7 @@ Users: https://github.com/ibm-capi/libcxl What: /sys/class/cxl/<afu>/reset -Date: September 2014 +Date: September 2014, removed February 2025 Contact: linuxppc-dev@lists.ozlabs.org Description: write only Writing 1 here will reset the AFU provided there are not @@ -96,14 +95,14 @@ Users: https://github.com/ibm-capi/libcxl What: /sys/class/cxl/<afu>/api_version -Date: September 2014 +Date: September 2014, removed February 2025 Contact: linuxppc-dev@lists.ozlabs.org Description: read only Decimal value of the current version of the kernel/user API. Users: https://github.com/ibm-capi/libcxl What: /sys/class/cxl/<afu>/api_version_compatible -Date: September 2014 +Date: September 2014, removed February 2025 Contact: linuxppc-dev@lists.ozlabs.org Description: read only Decimal value of the lowest version of the userspace API @@ -117,7 +116,7 @@ as AFU configuration records, which will show up here (if present). What: /sys/class/cxl/<afu>/cr<config num>/vendor -Date: February 2015 +Date: February 2015, removed February 2025 Contact: linuxppc-dev@lists.ozlabs.org Description: read only Hexadecimal value of the vendor ID found in this AFU @@ -125,7 +124,7 @@ Users: https://github.com/ibm-capi/libcxl What: /sys/class/cxl/<afu>/cr<config num>/device -Date: February 2015 +Date: February 2015, removed February 2025 Contact: linuxppc-dev@lists.ozlabs.org Description: read only Hexadecimal value of the device ID found in this AFU @@ -133,7 +132,7 @@ Users: https://github.com/ibm-capi/libcxl What: /sys/class/cxl/<afu>/cr<config num>/class -Date: February 2015 +Date: February 2015, removed February 2025 Contact: linuxppc-dev@lists.ozlabs.org Description: read only Hexadecimal value of the class code found in this AFU @@ -141,7 +140,7 @@ Users: https://github.com/ibm-capi/libcxl What: /sys/class/cxl/<afu>/cr<config num>/config -Date: February 2015 +Date: February 2015, removed February 2025 Contact: linuxppc-dev@lists.ozlabs.org Description: read only This binary file provides raw access to the AFU configuration @@ -155,7 +154,7 @@ Master contexts (eg. /sys/class/cxl/afu0.0m) What: /sys/class/cxl/<afu>m/mmio_size -Date: September 2014 +Date: September 2014, removed February 2025 Contact: linuxppc-dev@lists.ozlabs.org Description: read only Decimal value of the size of the MMIO space that may be mmapped @@ -163,14 +162,14 @@ Users: https://github.com/ibm-capi/libcxl What: /sys/class/cxl/<afu>m/pp_mmio_len -Date: September 2014 +Date: September 2014, removed February 2025 Contact: linuxppc-dev@lists.ozlabs.org Description: read only Decimal value of the Per Process MMIO space length. Users: https://github.com/ibm-capi/libcxl What: /sys/class/cxl/<afu>m/pp_mmio_off -Date: September 2014 +Date: September 2014, removed February 2025 Contact: linuxppc-dev@lists.ozlabs.org Description: read only (not in a guest) @@ -181,21 +180,21 @@ Card info (eg. /sys/class/cxl/card0) What: /sys/class/cxl/<card>/caia_version -Date: September 2014 +Date: September 2014, removed February 2025 Contact: linuxppc-dev@lists.ozlabs.org Description: read only Identifies the CAIA Version the card implements. Users: https://github.com/ibm-capi/libcxl What: /sys/class/cxl/<card>/psl_revision -Date: September 2014 +Date: September 2014, removed February 2025 Contact: linuxppc-dev@lists.ozlabs.org Description: read only Identifies the revision level of the PSL. Users: https://github.com/ibm-capi/libcxl What: /sys/class/cxl/<card>/base_image -Date: September 2014 +Date: September 2014, removed February 2025 Contact: linuxppc-dev@lists.ozlabs.org Description: read only (not in a guest) @@ -206,7 +205,7 @@ Users: https://github.com/ibm-capi/libcxl What: /sys/class/cxl/<card>/image_loaded -Date: September 2014 +Date: September 2014, removed February 2025 Contact: linuxppc-dev@lists.ozlabs.org Description: read only (not in a guest) @@ -215,7 +214,7 @@ Users: https://github.com/ibm-capi/libcxl What: /sys/class/cxl/<card>/load_image_on_perst -Date: December 2014 +Date: December 2014, removed February 2025 Contact: linuxppc-dev@lists.ozlabs.org Description: read/write (not in a guest) @@ -232,7 +231,7 @@ Users: https://github.com/ibm-capi/libcxl What: /sys/class/cxl/<card>/reset -Date: October 2014 +Date: October 2014, removed February 2025 Contact: linuxppc-dev@lists.ozlabs.org Description: write only Writing 1 will issue a PERST to card provided there are no @@ -243,7 +242,7 @@ Users: https://github.com/ibm-capi/libcxl What: /sys/class/cxl/<card>/perst_reloads_same_image -Date: July 2015 +Date: July 2015, removed February 2025 Contact: linuxppc-dev@lists.ozlabs.org Description: read/write (not in a guest) @@ -257,7 +256,7 @@ Users: https://github.com/ibm-capi/libcxl What: /sys/class/cxl/<card>/psl_timebase_synced -Date: March 2016 +Date: March 2016, removed February 2025 Contact: linuxppc-dev@lists.ozlabs.org Description: read only Returns 1 if the psl timebase register is synchronized @@ -265,7 +264,7 @@ Users: https://github.com/ibm-capi/libcxl What: /sys/class/cxl/<card>/tunneled_ops_supported -Date: May 2018 +Date: May 2018, removed February 2025 Contact: linuxppc-dev@lists.ozlabs.org Description: read only Returns 1 if tunneled operations are supported in capi mode,
diff --git a/Documentation/ABI/stable/sysfs-devices-node b/Documentation/ABI/stable/sysfs-devices-node index 402af4b..a02707c 100644 --- a/Documentation/ABI/stable/sysfs-devices-node +++ b/Documentation/ABI/stable/sysfs-devices-node
@@ -177,6 +177,12 @@ The cache write policy: 0 for write-back, 1 for write-through, other or unknown. +What: /sys/devices/system/node/nodeX/memory_side_cache/indexY/address_mode +Date: March 2025 +Contact: Dave Jiang <dave.jiang@intel.com> +Description: + The address mode: 0 for reserved, 1 for extended-linear. + What: /sys/devices/system/node/nodeX/x86/sgx_total_bytes Date: November 2021 Contact: Jarkko Sakkinen <jarkko@kernel.org>
diff --git a/Documentation/ABI/testing/sysfs-bus-cxl b/Documentation/ABI/testing/sysfs-bus-cxl index 3f5627a..99bb3fa 100644 --- a/Documentation/ABI/testing/sysfs-bus-cxl +++ b/Documentation/ABI/testing/sysfs-bus-cxl
@@ -1,5 +1,5 @@ What: /sys/bus/cxl/flush -Date: Januarry, 2022 +Date: January, 2022 KernelVersion: v5.18 Contact: linux-cxl@vger.kernel.org Description: @@ -18,6 +18,24 @@ specification. +What: /sys/bus/cxl/devices/memX/payload_max +Date: December, 2020 +KernelVersion: v5.12 +Contact: linux-cxl@vger.kernel.org +Description: + (RO) Maximum size (in bytes) of the mailbox command payload + registers. Linux caps this at 1MB if the device reports a + larger size. + + +What: /sys/bus/cxl/devices/memX/label_storage_size +Date: May, 2021 +KernelVersion: v5.13 +Contact: linux-cxl@vger.kernel.org +Description: + (RO) Size (in bytes) of the Label Storage Area (LSA). + + What: /sys/bus/cxl/devices/memX/ram/size Date: December, 2020 KernelVersion: v5.12 @@ -33,7 +51,7 @@ KernelVersion: v6.8 Contact: linux-cxl@vger.kernel.org Description: - (RO) For CXL host platforms that support "QoS Telemmetry" + (RO) For CXL host platforms that support "QoS Telemetry" this attribute conveys a comma delimited list of platform specific cookies that identifies a QoS performance class for the volatile partition of the CXL mem device. These @@ -60,7 +78,7 @@ KernelVersion: v6.8 Contact: linux-cxl@vger.kernel.org Description: - (RO) For CXL host platforms that support "QoS Telemmetry" + (RO) For CXL host platforms that support "QoS Telemetry" this attribute conveys a comma delimited list of platform specific cookies that identifies a QoS performance class for the persistent partition of the CXL mem device. These @@ -321,14 +339,13 @@ Contact: linux-cxl@vger.kernel.org Description: (RW) When a CXL decoder is of devtype "cxl_decoder_endpoint" it - translates from a host physical address range, to a device local - address range. Device-local address ranges are further split - into a 'ram' (volatile memory) range and 'pmem' (persistent - memory) range. The 'mode' attribute emits one of 'ram', 'pmem', - 'mixed', or 'none'. The 'mixed' indication is for error cases - when a decoder straddles the volatile/persistent partition - boundary, and 'none' indicates the decoder is not actively - decoding, or no DPA allocation policy has been set. + translates from a host physical address range, to a device + local address range. Device-local address ranges are further + split into a 'ram' (volatile memory) range and 'pmem' + (persistent memory) range. The 'mode' attribute emits one of + 'ram', 'pmem', or 'none'. The 'none' indicates the decoder is + not actively decoding, or no DPA allocation policy has been + set. 'mode' can be written, when the decoder is in the 'disabled' state, with either 'ram' or 'pmem' to set the boundaries for the @@ -423,7 +440,7 @@ KernelVersion: v6.5 Contact: linux-cxl@vger.kernel.org Description: - (RO) For CXL host platforms that support "QoS Telemmetry" this + (RO) For CXL host platforms that support "QoS Telemetry" this root-decoder-only attribute conveys a platform specific cookie that identifies a QoS performance class for the CXL Window. This class-id can be compared against a similar "qos_class" @@ -586,3 +603,15 @@ See Documentation/ABI/stable/sysfs-devices-node. access0 provides the number to the closest initiator and access1 provides the number to the closest CPU. + + +What: /sys/bus/cxl/devices/nvdimm-bridge0/ndbusX/nmemY/cxl/dirty_shutdown +Date: Feb, 2025 +KernelVersion: v6.15 +Contact: linux-cxl@vger.kernel.org +Description: + (RO) The device dirty shutdown count value, which is the number + of times the device could have incurred in potential data loss. + The count is persistent across power loss and wraps back to 0 + upon overflow. If this file is not present, the device does not + have the necessary support for dirty tracking.
diff --git a/Documentation/admin-guide/device-mapper/dm-crypt.rst b/Documentation/admin-guide/device-mapper/dm-crypt.rst index 9f8139f..4467f6d4 100644 --- a/Documentation/admin-guide/device-mapper/dm-crypt.rst +++ b/Documentation/admin-guide/device-mapper/dm-crypt.rst
@@ -146,6 +146,11 @@ integrity for the encrypted device. The additional space is then used for storing authentication tag (and persistent IV if needed). +integrity_key_size:<bytes> + Optionally set the integrity key size if it differs from the digest size. + It allows the use of wrapped key algorithms where the key size is + independent of the cryptographic key size. + sector_size:<bytes> Use <bytes> as the encryption unit instead of 512 bytes sectors. This option can be in range 512 - 4096 bytes and must be power of two.
diff --git a/Documentation/admin-guide/device-mapper/dm-integrity.rst b/Documentation/admin-guide/device-mapper/dm-integrity.rst index d8a5f14..c2e18ec 100644 --- a/Documentation/admin-guide/device-mapper/dm-integrity.rst +++ b/Documentation/admin-guide/device-mapper/dm-integrity.rst
@@ -92,6 +92,11 @@ allowed. This mode is useful for data recovery if the device cannot be activated in any of the other standard modes. + I - inline mode - in this mode, dm-integrity will store integrity + data directly in the underlying device sectors. + The underlying device must have an integrity profile that + allows storing user integrity data and provides enough + space for the selected integrity tag. 5. the number of additional arguments
diff --git a/Documentation/admin-guide/device-mapper/verity.rst b/Documentation/admin-guide/device-mapper/verity.rst index a65c160..8c3f1f9 100644 --- a/Documentation/admin-guide/device-mapper/verity.rst +++ b/Documentation/admin-guide/device-mapper/verity.rst
@@ -87,6 +87,15 @@ Panic the device when a corrupted block is discovered. This option is not compatible with ignore_corruption and restart_on_corruption. +restart_on_error + Restart the system when an I/O error is detected. + This option can be combined with the restart_on_corruption option. + +panic_on_error + Panic the device when an I/O error is detected. This option is + not compatible with the restart_on_error option but can be combined + with the panic_on_corruption option. + ignore_zero_blocks Do not verify blocks that are expected to contain zeroes and always return zeroes instead. This may be useful if the partition contains unused blocks @@ -142,8 +151,15 @@ already in the secondary trusted keyring. try_verify_in_tasklet - If verity hashes are in cache, verify data blocks in kernel tasklet instead - of workqueue. This option can reduce IO latency. + If verity hashes are in cache and the IO size does not exceed the limit, + verify data blocks in bottom half instead of workqueue. This option can + reduce IO latency. The size limits can be configured via + /sys/module/dm_verity/parameters/use_bh_bytes. The four parameters + correspond to limits for IOPRIO_CLASS_NONE, IOPRIO_CLASS_RT, + IOPRIO_CLASS_BE and IOPRIO_CLASS_IDLE in turn. + For example: + <none>,<rt>,<be>,<idle> + 4096,4096,4096,4096 Theory of operation ===================
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index 3f35d5b..76e538c 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -4265,10 +4265,10 @@ nosmp [SMP,EARLY] Tells an SMP kernel to act as a UP kernel, and disable the IO APIC. legacy for "maxcpus=0". - nosmt [KNL,MIPS,PPC,S390,EARLY] Disable symmetric multithreading (SMT). + nosmt [KNL,MIPS,PPC,EARLY] Disable symmetric multithreading (SMT). Equivalent to smt=1. - [KNL,X86,PPC] Disable symmetric multithreading (SMT). + [KNL,X86,PPC,S390] Disable symmetric multithreading (SMT). nosmt=force: Force disable SMT, cannot be undone via the sysfs control file. @@ -7288,6 +7288,8 @@ This is just one of many ways that can clear memory. Make sure your system keeps the content of memory across reboots before relying on this option. + NB: Both the mapped address and size must be page aligned for the architecture. + See also Documentation/trace/debugging.rst @@ -7533,6 +7535,22 @@ Note that genuine overcurrent events won't be reported either. + unaligned_scalar_speed= + [RISCV] + Format: {slow | fast | unsupported} + Allow skipping scalar unaligned access speed tests. This + is useful for testing alternative code paths and to skip + the tests in environments where they run too slowly. All + CPUs must have the same scalar unaligned access speed. + + unaligned_vector_speed= + [RISCV] + Format: {slow | fast | unsupported} + Allow skipping vector unaligned access speed tests. This + is useful for testing alternative code paths and to skip + the tests in environments where they run too slowly. All + CPUs must have the same vector unaligned access speed. + unknown_nmi_panic [X86] Cause panic on unknown NMI.
diff --git a/Documentation/admin-guide/sysctl/fs.rst b/Documentation/admin-guide/sysctl/fs.rst index 08e89e0..6c54718 100644 --- a/Documentation/admin-guide/sysctl/fs.rst +++ b/Documentation/admin-guide/sysctl/fs.rst
@@ -347,3 +347,28 @@ ``/proc/sys/fs/fuse/max_pages_limit`` is a read/write file for setting/getting the maximum number of pages that can be used for servicing requests in FUSE. + +``/proc/sys/fs/fuse/default_request_timeout`` is a read/write file for +setting/getting the default timeout (in seconds) for a fuse server to +reply to a kernel-issued request in the event where the server did not +specify a timeout at mount. If the server set a timeout, +then default_request_timeout will be ignored. The default +"default_request_timeout" is set to 0. 0 indicates no default timeout. +The maximum value that can be set is 65535. + +``/proc/sys/fs/fuse/max_request_timeout`` is a read/write file for +setting/getting the maximum timeout (in seconds) for a fuse server to +reply to a kernel-issued request. A value greater than 0 automatically opts +the server into a timeout that will be set to at most "max_request_timeout", +even if the server did not specify a timeout and default_request_timeout is +set to 0. If max_request_timeout is greater than 0 and the server set a timeout +greater than max_request_timeout or default_request_timeout is set to a value +greater than max_request_timeout, the system will use max_request_timeout as the +timeout. 0 indicates no max request timeout. The maximum value that can be set +is 65535. + +For timeouts, if the server does not respond to the request by the time +the set timeout elapses, then the connection to the fuse server will be aborted. +Please note that the timeouts are not 100% precise (eg you may set 60 seconds but +the timeout may kick in after 70 seconds). The upper margin of error for the +timeout is roughly FUSE_TIMEOUT_TIMER_FREQ seconds.
diff --git a/Documentation/arch/powerpc/cxl.rst b/Documentation/arch/powerpc/cxl.rst deleted file mode 100644 index 778adda..0000000 --- a/Documentation/arch/powerpc/cxl.rst +++ /dev/null
@@ -1,470 +0,0 @@ -==================================== -Coherent Accelerator Interface (CXL) -==================================== - -Introduction -============ - - The coherent accelerator interface is designed to allow the - coherent connection of accelerators (FPGAs and other devices) to a - POWER system. These devices need to adhere to the Coherent - Accelerator Interface Architecture (CAIA). - - IBM refers to this as the Coherent Accelerator Processor Interface - or CAPI. In the kernel it's referred to by the name CXL to avoid - confusion with the ISDN CAPI subsystem. - - Coherent in this context means that the accelerator and CPUs can - both access system memory directly and with the same effective - addresses. - - **This driver is deprecated and will be removed in a future release.** - -Hardware overview -================= - - :: - - POWER8/9 FPGA - +----------+ +---------+ - | | | | - | CPU | | AFU | - | | | | - | | | | - | | | | - +----------+ +---------+ - | PHB | | | - | +------+ | PSL | - | | CAPP |<------>| | - +---+------+ PCIE +---------+ - - The POWER8/9 chip has a Coherently Attached Processor Proxy (CAPP) - unit which is part of the PCIe Host Bridge (PHB). This is managed - by Linux by calls into OPAL. Linux doesn't directly program the - CAPP. - - The FPGA (or coherently attached device) consists of two parts. - The POWER Service Layer (PSL) and the Accelerator Function Unit - (AFU). The AFU is used to implement specific functionality behind - the PSL. The PSL, among other things, provides memory address - translation services to allow each AFU direct access to userspace - memory. - - The AFU is the core part of the accelerator (eg. the compression, - crypto etc function). The kernel has no knowledge of the function - of the AFU. Only userspace interacts directly with the AFU. - - The PSL provides the translation and interrupt services that the - AFU needs. This is what the kernel interacts with. For example, if - the AFU needs to read a particular effective address, it sends - that address to the PSL, the PSL then translates it, fetches the - data from memory and returns it to the AFU. If the PSL has a - translation miss, it interrupts the kernel and the kernel services - the fault. The context to which this fault is serviced is based on - who owns that acceleration function. - - - POWER8 and PSL Version 8 are compliant to the CAIA Version 1.0. - - POWER9 and PSL Version 9 are compliant to the CAIA Version 2.0. - - This PSL Version 9 provides new features such as: - - * Interaction with the nest MMU on the P9 chip. - * Native DMA support. - * Supports sending ASB_Notify messages for host thread wakeup. - * Supports Atomic operations. - * etc. - - Cards with a PSL9 won't work on a POWER8 system and cards with a - PSL8 won't work on a POWER9 system. - -AFU Modes -========= - - There are two programming modes supported by the AFU. Dedicated - and AFU directed. AFU may support one or both modes. - - When using dedicated mode only one MMU context is supported. In - this mode, only one userspace process can use the accelerator at - time. - - When using AFU directed mode, up to 16K simultaneous contexts can - be supported. This means up to 16K simultaneous userspace - applications may use the accelerator (although specific AFUs may - support fewer). In this mode, the AFU sends a 16 bit context ID - with each of its requests. This tells the PSL which context is - associated with each operation. If the PSL can't translate an - operation, the ID can also be accessed by the kernel so it can - determine the userspace context associated with an operation. - - -MMIO space -========== - - A portion of the accelerator MMIO space can be directly mapped - from the AFU to userspace. Either the whole space can be mapped or - just a per context portion. The hardware is self describing, hence - the kernel can determine the offset and size of the per context - portion. - - -Interrupts -========== - - AFUs may generate interrupts that are destined for userspace. These - are received by the kernel as hardware interrupts and passed onto - userspace by a read syscall documented below. - - Data storage faults and error interrupts are handled by the kernel - driver. - - -Work Element Descriptor (WED) -============================= - - The WED is a 64-bit parameter passed to the AFU when a context is - started. Its format is up to the AFU hence the kernel has no - knowledge of what it represents. Typically it will be the - effective address of a work queue or status block where the AFU - and userspace can share control and status information. - - - - -User API -======== - -1. AFU character devices -^^^^^^^^^^^^^^^^^^^^^^^^ - - For AFUs operating in AFU directed mode, two character device - files will be created. /dev/cxl/afu0.0m will correspond to a - master context and /dev/cxl/afu0.0s will correspond to a slave - context. Master contexts have access to the full MMIO space an - AFU provides. Slave contexts have access to only the per process - MMIO space an AFU provides. - - For AFUs operating in dedicated process mode, the driver will - only create a single character device per AFU called - /dev/cxl/afu0.0d. This will have access to the entire MMIO space - that the AFU provides (like master contexts in AFU directed). - - The types described below are defined in include/uapi/misc/cxl.h - - The following file operations are supported on both slave and - master devices. - - A userspace library libcxl is available here: - - https://github.com/ibm-capi/libcxl - - This provides a C interface to this kernel API. - -open ----- - - Opens the device and allocates a file descriptor to be used with - the rest of the API. - - A dedicated mode AFU only has one context and only allows the - device to be opened once. - - An AFU directed mode AFU can have many contexts, the device can be - opened once for each context that is available. - - When all available contexts are allocated the open call will fail - and return -ENOSPC. - - Note: - IRQs need to be allocated for each context, which may limit - the number of contexts that can be created, and therefore - how many times the device can be opened. The POWER8 CAPP - supports 2040 IRQs and 3 are used by the kernel, so 2037 are - left. If 1 IRQ is needed per context, then only 2037 - contexts can be allocated. If 4 IRQs are needed per context, - then only 2037/4 = 509 contexts can be allocated. - - -ioctl ------ - - CXL_IOCTL_START_WORK: - Starts the AFU context and associates it with the current - process. Once this ioctl is successfully executed, all memory - mapped into this process is accessible to this AFU context - using the same effective addresses. No additional calls are - required to map/unmap memory. The AFU memory context will be - updated as userspace allocates and frees memory. This ioctl - returns once the AFU context is started. - - Takes a pointer to a struct cxl_ioctl_start_work - - :: - - struct cxl_ioctl_start_work { - __u64 flags; - __u64 work_element_descriptor; - __u64 amr; - __s16 num_interrupts; - __s16 reserved1; - __s32 reserved2; - __u64 reserved3; - __u64 reserved4; - __u64 reserved5; - __u64 reserved6; - }; - - flags: - Indicates which optional fields in the structure are - valid. - - work_element_descriptor: - The Work Element Descriptor (WED) is a 64-bit argument - defined by the AFU. Typically this is an effective - address pointing to an AFU specific structure - describing what work to perform. - - amr: - Authority Mask Register (AMR), same as the powerpc - AMR. This field is only used by the kernel when the - corresponding CXL_START_WORK_AMR value is specified in - flags. If not specified the kernel will use a default - value of 0. - - num_interrupts: - Number of userspace interrupts to request. This field - is only used by the kernel when the corresponding - CXL_START_WORK_NUM_IRQS value is specified in flags. - If not specified the minimum number required by the - AFU will be allocated. The min and max number can be - obtained from sysfs. - - reserved fields: - For ABI padding and future extensions - - CXL_IOCTL_GET_PROCESS_ELEMENT: - Get the current context id, also known as the process element. - The value is returned from the kernel as a __u32. - - -mmap ----- - - An AFU may have an MMIO space to facilitate communication with the - AFU. If it does, the MMIO space can be accessed via mmap. The size - and contents of this area are specific to the particular AFU. The - size can be discovered via sysfs. - - In AFU directed mode, master contexts are allowed to map all of - the MMIO space and slave contexts are allowed to only map the per - process MMIO space associated with the context. In dedicated - process mode the entire MMIO space can always be mapped. - - This mmap call must be done after the START_WORK ioctl. - - Care should be taken when accessing MMIO space. Only 32 and 64-bit - accesses are supported by POWER8. Also, the AFU will be designed - with a specific endianness, so all MMIO accesses should consider - endianness (recommend endian(3) variants like: le64toh(), - be64toh() etc). These endian issues equally apply to shared memory - queues the WED may describe. - - -read ----- - - Reads events from the AFU. Blocks if no events are pending - (unless O_NONBLOCK is supplied). Returns -EIO in the case of an - unrecoverable error or if the card is removed. - - read() will always return an integral number of events. - - The buffer passed to read() must be at least 4K bytes. - - The result of the read will be a buffer of one or more events, - each event is of type struct cxl_event, of varying size:: - - struct cxl_event { - struct cxl_event_header header; - union { - struct cxl_event_afu_interrupt irq; - struct cxl_event_data_storage fault; - struct cxl_event_afu_error afu_error; - }; - }; - - The struct cxl_event_header is defined as - - :: - - struct cxl_event_header { - __u16 type; - __u16 size; - __u16 process_element; - __u16 reserved1; - }; - - type: - This defines the type of event. The type determines how - the rest of the event is structured. These types are - described below and defined by enum cxl_event_type. - - size: - This is the size of the event in bytes including the - struct cxl_event_header. The start of the next event can - be found at this offset from the start of the current - event. - - process_element: - Context ID of the event. - - reserved field: - For future extensions and padding. - - If the event type is CXL_EVENT_AFU_INTERRUPT then the event - structure is defined as - - :: - - struct cxl_event_afu_interrupt { - __u16 flags; - __u16 irq; /* Raised AFU interrupt number */ - __u32 reserved1; - }; - - flags: - These flags indicate which optional fields are present - in this struct. Currently all fields are mandatory. - - irq: - The IRQ number sent by the AFU. - - reserved field: - For future extensions and padding. - - If the event type is CXL_EVENT_DATA_STORAGE then the event - structure is defined as - - :: - - struct cxl_event_data_storage { - __u16 flags; - __u16 reserved1; - __u32 reserved2; - __u64 addr; - __u64 dsisr; - __u64 reserved3; - }; - - flags: - These flags indicate which optional fields are present in - this struct. Currently all fields are mandatory. - - address: - The address that the AFU unsuccessfully attempted to - access. Valid accesses will be handled transparently by the - kernel but invalid accesses will generate this event. - - dsisr: - This field gives information on the type of fault. It is a - copy of the DSISR from the PSL hardware when the address - fault occurred. The form of the DSISR is as defined in the - CAIA. - - reserved fields: - For future extensions - - If the event type is CXL_EVENT_AFU_ERROR then the event structure - is defined as - - :: - - struct cxl_event_afu_error { - __u16 flags; - __u16 reserved1; - __u32 reserved2; - __u64 error; - }; - - flags: - These flags indicate which optional fields are present in - this struct. Currently all fields are Mandatory. - - error: - Error status from the AFU. Defined by the AFU. - - reserved fields: - For future extensions and padding - - -2. Card character device (powerVM guest only) -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - In a powerVM guest, an extra character device is created for the - card. The device is only used to write (flash) a new image on the - FPGA accelerator. Once the image is written and verified, the - device tree is updated and the card is reset to reload the updated - image. - -open ----- - - Opens the device and allocates a file descriptor to be used with - the rest of the API. The device can only be opened once. - -ioctl ------ - -CXL_IOCTL_DOWNLOAD_IMAGE / CXL_IOCTL_VALIDATE_IMAGE: - Starts and controls flashing a new FPGA image. Partial - reconfiguration is not supported (yet), so the image must contain - a copy of the PSL and AFU(s). Since an image can be quite large, - the caller may have to iterate, splitting the image in smaller - chunks. - - Takes a pointer to a struct cxl_adapter_image:: - - struct cxl_adapter_image { - __u64 flags; - __u64 data; - __u64 len_data; - __u64 len_image; - __u64 reserved1; - __u64 reserved2; - __u64 reserved3; - __u64 reserved4; - }; - - flags: - These flags indicate which optional fields are present in - this struct. Currently all fields are mandatory. - - data: - Pointer to a buffer with part of the image to write to the - card. - - len_data: - Size of the buffer pointed to by data. - - len_image: - Full size of the image. - - -Sysfs Class -=========== - - A cxl sysfs class is added under /sys/class/cxl to facilitate - enumeration and tuning of the accelerators. Its layout is - described in Documentation/ABI/obsolete/sysfs-class-cxl - - -Udev rules -========== - - The following udev rules could be used to create a symlink to the - most logical chardev to use in any programming mode (afuX.Yd for - dedicated, afuX.Ys for afu directed), since the API is virtually - identical for each:: - - SUBSYSTEM=="cxl", ATTRS{mode}=="dedicated_process", SYMLINK="cxl/%b" - SUBSYSTEM=="cxl", ATTRS{mode}=="afu_directed", \ - KERNEL=="afu[0-9]*.[0-9]*s", SYMLINK="cxl/%b"
diff --git a/Documentation/arch/powerpc/index.rst b/Documentation/arch/powerpc/index.rst index 9952685..0560cba 100644 --- a/Documentation/arch/powerpc/index.rst +++ b/Documentation/arch/powerpc/index.rst
@@ -12,7 +12,6 @@ bootwrapper cpu_families cpu_features - cxl dawr-power9 dexcr dscr
diff --git a/Documentation/arch/riscv/hwprobe.rst b/Documentation/arch/riscv/hwprobe.rst index f273ea1..53607d9 100644 --- a/Documentation/arch/riscv/hwprobe.rst +++ b/Documentation/arch/riscv/hwprobe.rst
@@ -183,6 +183,9 @@ defined in the Atomic Compare-and-Swap (CAS) instructions manual starting from commit 5059e0ca641c ("update to ratified"). + * :c:macro:`RISCV_HWPROBE_EXT_ZICNTR`: The Zicntr extension version 2.0 + is supported as defined in the RISC-V ISA manual. + * :c:macro:`RISCV_HWPROBE_EXT_ZICOND`: The Zicond extension is supported as defined in the RISC-V Integer Conditional (Zicond) operations extension manual starting from commit 95cf1f9 ("Add changes requested by Ved @@ -192,6 +195,9 @@ supported as defined in the RISC-V ISA manual starting from commit d8ab5c78c207 ("Zihintpause is ratified"). + * :c:macro:`RISCV_HWPROBE_EXT_ZIHPM`: The Zihpm extension version 2.0 + is supported as defined in the RISC-V ISA manual. + * :c:macro:`RISCV_HWPROBE_EXT_ZVE32X`: The Vector sub-extension Zve32x is supported, as defined by version 1.0 of the RISC-V Vector extension manual. @@ -239,9 +245,32 @@ ratified in commit 98918c844281 ("Merge pull request #1217 from riscv/zawrs") of riscv-isa-manual. + * :c:macro:`RISCV_HWPROBE_EXT_ZAAMO`: The Zaamo extension is supported as + defined in the in the RISC-V ISA manual starting from commit e87412e621f1 + ("integrate Zaamo and Zalrsc text (#1304)"). + + * :c:macro:`RISCV_HWPROBE_EXT_ZALRSC`: The Zalrsc extension is supported as + defined in the in the RISC-V ISA manual starting from commit e87412e621f1 + ("integrate Zaamo and Zalrsc text (#1304)"). + * :c:macro:`RISCV_HWPROBE_EXT_SUPM`: The Supm extension is supported as defined in version 1.0 of the RISC-V Pointer Masking extensions. + * :c:macro:`RISCV_HWPROBE_EXT_ZFBFMIN`: The Zfbfmin extension is supported as + defined in the RISC-V ISA manual starting from commit 4dc23d6229de + ("Added Chapter title to BF16"). + + * :c:macro:`RISCV_HWPROBE_EXT_ZVFBFMIN`: The Zvfbfmin extension is supported as + defined in the RISC-V ISA manual starting from commit 4dc23d6229de + ("Added Chapter title to BF16"). + + * :c:macro:`RISCV_HWPROBE_EXT_ZVFBFWMA`: The Zvfbfwma extension is supported as + defined in the RISC-V ISA manual starting from commit 4dc23d6229de + ("Added Chapter title to BF16"). + + * :c:macro:`RISCV_HWPROBE_EXT_ZICBOM`: The Zicbom extension is supported, as + ratified in commit 3dd606f ("Create cmobase-v1.0.pdf") of riscv-CMOs. + * :c:macro:`RISCV_HWPROBE_KEY_CPUPERF_0`: Deprecated. Returns similar values to :c:macro:`RISCV_HWPROBE_KEY_MISALIGNED_SCALAR_PERF`, but the key was mistakenly classified as a bitmask rather than a value. @@ -303,3 +332,6 @@ * :c:macro:`RISCV_HWPROBE_VENDOR_EXT_XTHEADVECTOR`: The xtheadvector vendor extension is supported in the T-Head ISA extensions spec starting from commit a18c801634 ("Add T-Head VECTOR vendor extension. "). + +* :c:macro:`RISCV_HWPROBE_KEY_ZICBOM_BLOCK_SIZE`: An unsigned int which + represents the size of the Zicbom block in bytes.
diff --git a/Documentation/block/ublk.rst b/Documentation/block/ublk.rst index 1e0e735..854f823 100644 --- a/Documentation/block/ublk.rst +++ b/Documentation/block/ublk.rst
@@ -309,18 +309,35 @@ ``UBLK_IO_COMMIT_AND_FETCH_REQ`` to the server, ublkdrv needs to copy the server buffer (pages) read to the IO request pages. -Future development -================== - Zero copy --------- -Zero copy is a generic requirement for nbd, fuse or similar drivers. A -problem [#xiaoguang]_ Xiaoguang mentioned is that pages mapped to userspace -can't be remapped any more in kernel with existing mm interfaces. This can -occurs when destining direct IO to ``/dev/ublkb*``. Also, he reported that -big requests (IO size >= 256 KB) may benefit a lot from zero copy. +ublk zero copy relies on io_uring's fixed kernel buffer, which provides +two APIs: `io_buffer_register_bvec()` and `io_buffer_unregister_bvec`. +ublk adds IO command of `UBLK_IO_REGISTER_IO_BUF` to call +`io_buffer_register_bvec()` for ublk server to register client request +buffer into io_uring buffer table, then ublk server can submit io_uring +IOs with the registered buffer index. IO command of `UBLK_IO_UNREGISTER_IO_BUF` +calls `io_buffer_unregister_bvec()` to unregister the buffer, which is +guaranteed to be live between calling `io_buffer_register_bvec()` and +`io_buffer_unregister_bvec()`. Any io_uring operation which supports this +kind of kernel buffer will grab one reference of the buffer until the +operation is completed. + +ublk server implementing zero copy or user copy has to be CAP_SYS_ADMIN and +be trusted, because it is ublk server's responsibility to make sure IO buffer +filled with data for handling read command, and ublk server has to return +correct result to ublk driver when handling READ command, and the result +has to match with how many bytes filled to the IO buffer. Otherwise, +uninitialized kernel IO buffer will be exposed to client application. + +ublk server needs to align the parameter of `struct ublk_param_dma_align` +with backend for zero copy to work correctly. + +For reaching best IO performance, ublk server should align its segment +parameter of `struct ublk_param_segment` with backend for avoiding +unnecessary IO split, which usually hurts io_uring performance. References ========== @@ -332,5 +349,3 @@ .. [#userspace_nbdublk] https://gitlab.com/rwmjones/libnbd/-/tree/nbdublk .. [#userspace_readme] https://github.com/ming1/ubdsrv/blob/master/README - -.. [#xiaoguang] https://lore.kernel.org/linux-block/YoOr6jBfgVm8GvWg@stefanha-x1.localdomain/
diff --git a/Documentation/dev-tools/checkpatch.rst b/Documentation/dev-tools/checkpatch.rst index abb3ff6..76bd0dd 100644 --- a/Documentation/dev-tools/checkpatch.rst +++ b/Documentation/dev-tools/checkpatch.rst
@@ -342,24 +342,6 @@ See: https://www.kernel.org/doc/html/latest/RCU/whatisRCU.html#full-list-of-rcu-apis - **DEPRECATED_VARIABLE** - EXTRA_{A,C,CPP,LD}FLAGS are deprecated and should be replaced by the new - flags added via commit f77bf01425b1 ("kbuild: introduce ccflags-y, - asflags-y and ldflags-y"). - - The following conversion scheme maybe used:: - - EXTRA_AFLAGS -> asflags-y - EXTRA_CFLAGS -> ccflags-y - EXTRA_CPPFLAGS -> cppflags-y - EXTRA_LDFLAGS -> ldflags-y - - See: - - 1. https://lore.kernel.org/lkml/20070930191054.GA15876@uranus.ravnborg.org/ - 2. https://lore.kernel.org/lkml/1313384834-24433-12-git-send-email-lacombar@gmail.com/ - 3. https://www.kernel.org/doc/html/latest/kbuild/makefiles.html#compilation-flags - **DEVICE_ATTR_FUNCTIONS** The function names used in DEVICE_ATTR is unusual. Typically, the store and show functions are used with <attr>_store and
diff --git a/Documentation/devicetree/bindings/input/gpio-matrix-keypad.txt b/Documentation/devicetree/bindings/input/gpio-matrix-keypad.txt deleted file mode 100644 index 570dc10..0000000 --- a/Documentation/devicetree/bindings/input/gpio-matrix-keypad.txt +++ /dev/null
@@ -1,49 +0,0 @@ -* GPIO driven matrix keypad device tree bindings - -GPIO driven matrix keypad is used to interface a SoC with a matrix keypad. -The matrix keypad supports multiple row and column lines, a key can be -placed at each intersection of a unique row and a unique column. The matrix -keypad can sense a key-press and key-release by means of GPIO lines and -report the event using GPIO interrupts to the cpu. - -Required Properties: -- compatible: Should be "gpio-matrix-keypad" -- row-gpios: List of gpios used as row lines. The gpio specifier - for this property depends on the gpio controller to - which these row lines are connected. -- col-gpios: List of gpios used as column lines. The gpio specifier - for this property depends on the gpio controller to - which these column lines are connected. -- linux,keymap: The definition can be found at - bindings/input/matrix-keymap.txt - -Optional Properties: -- linux,no-autorepeat: do no enable autorepeat feature. -- wakeup-source: use any event on keypad as wakeup event. - (Legacy property supported: "linux,wakeup") -- debounce-delay-ms: debounce interval in milliseconds -- col-scan-delay-us: delay, measured in microseconds, that is needed - before we can scan keypad after activating column gpio -- drive-inactive-cols: drive inactive columns during scan, - default is to turn inactive columns into inputs. - -Example: - matrix-keypad { - compatible = "gpio-matrix-keypad"; - debounce-delay-ms = <5>; - col-scan-delay-us = <2>; - - row-gpios = <&gpio2 25 0 - &gpio2 26 0 - &gpio2 27 0>; - - col-gpios = <&gpio2 21 0 - &gpio2 22 0>; - - linux,keymap = <0x0000008B - 0x0100009E - 0x02000069 - 0x0001006A - 0x0101001C - 0x0201006C>; - };
diff --git a/Documentation/devicetree/bindings/input/gpio-matrix-keypad.yaml b/Documentation/devicetree/bindings/input/gpio-matrix-keypad.yaml new file mode 100644 index 0000000..ebfff9e --- /dev/null +++ b/Documentation/devicetree/bindings/input/gpio-matrix-keypad.yaml
@@ -0,0 +1,103 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- + +$id: http://devicetree.org/schemas/input/gpio-matrix-keypad.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: GPIO matrix keypad + +maintainers: + - Marek Vasut <marek.vasut@gmail.com> + +description: + GPIO driven matrix keypad is used to interface a SoC with a matrix keypad. + The matrix keypad supports multiple row and column lines, a key can be + placed at each intersection of a unique row and a unique column. The matrix + keypad can sense a key-press and key-release by means of GPIO lines and + report the event using GPIO interrupts to the cpu. + +allOf: + - $ref: /schemas/input/matrix-keymap.yaml# + +properties: + compatible: + const: gpio-matrix-keypad + + row-gpios: + description: + List of GPIOs used as row lines. The gpio specifier for this property + depends on the gpio controller to which these row lines are connected. + + col-gpios: + description: + List of GPIOs used as column lines. The gpio specifier for this property + depends on the gpio controller to which these column lines are connected. + + linux,keymap: true + + linux,no-autorepeat: + type: boolean + description: Do not enable autorepeat feature. + + gpio-activelow: + type: boolean + description: + Force GPIO polarity to active low. + In the absence of this property GPIOs are treated as active high. + + debounce-delay-ms: + description: Debounce interval in milliseconds. + default: 0 + + col-scan-delay-us: + description: + Delay, measured in microseconds, that is needed + before we can scan keypad after activating column gpio. + default: 0 + + all-cols-on-delay-us: + description: + Delay, measured in microseconds, that is needed + after activating all column gpios. + default: 0 + + drive-inactive-cols: + type: boolean + description: + Drive inactive columns during scan, + default is to turn inactive columns into inputs. + + wakeup-source: true + +required: + - compatible + - row-gpios + - col-gpios + - linux,keymap + +additionalProperties: false + +examples: + - | + matrix-keypad { + compatible = "gpio-matrix-keypad"; + debounce-delay-ms = <5>; + col-scan-delay-us = <2>; + + row-gpios = <&gpio2 25 0 + &gpio2 26 0 + &gpio2 27 0>; + + col-gpios = <&gpio2 21 0 + &gpio2 22 0>; + + linux,keymap = <0x0000008B + 0x0100009E + 0x02000069 + 0x0001006A + 0x0101001C + 0x0201006C>; + + wakeup-source; + };
diff --git a/Documentation/devicetree/bindings/input/qcom,pm8921-keypad.yaml b/Documentation/devicetree/bindings/input/qcom,pm8921-keypad.yaml index 88764ad..e03611e 100644 --- a/Documentation/devicetree/bindings/input/qcom,pm8921-keypad.yaml +++ b/Documentation/devicetree/bindings/input/qcom,pm8921-keypad.yaml
@@ -62,28 +62,28 @@ examples: - | - #include <dt-bindings/input/input.h> - #include <dt-bindings/interrupt-controller/irq.h> - pmic { - #address-cells = <1>; - #size-cells = <0>; + #include <dt-bindings/input/input.h> + #include <dt-bindings/interrupt-controller/irq.h> + pmic { + #address-cells = <1>; + #size-cells = <0>; - keypad@148 { - compatible = "qcom,pm8921-keypad"; - reg = <0x148>; - interrupt-parent = <&pmicintc>; - interrupts = <74 IRQ_TYPE_EDGE_RISING>, <75 IRQ_TYPE_EDGE_RISING>; - linux,keymap = < - MATRIX_KEY(0, 0, KEY_VOLUMEUP) - MATRIX_KEY(0, 1, KEY_VOLUMEDOWN) - MATRIX_KEY(0, 2, KEY_CAMERA_FOCUS) - MATRIX_KEY(0, 3, KEY_CAMERA) - >; - keypad,num-rows = <1>; - keypad,num-columns = <5>; - debounce = <15>; - scan-delay = <32>; - row-hold = <91500>; - }; - }; + keypad@148 { + compatible = "qcom,pm8921-keypad"; + reg = <0x148>; + interrupt-parent = <&pmicintc>; + interrupts = <74 IRQ_TYPE_EDGE_RISING>, <75 IRQ_TYPE_EDGE_RISING>; + linux,keymap = < + MATRIX_KEY(0, 0, KEY_VOLUMEUP) + MATRIX_KEY(0, 1, KEY_VOLUMEDOWN) + MATRIX_KEY(0, 2, KEY_CAMERA_FOCUS) + MATRIX_KEY(0, 3, KEY_CAMERA) + >; + keypad,num-rows = <1>; + keypad,num-columns = <5>; + debounce = <15>; + scan-delay = <32>; + row-hold = <91500>; + }; + }; ...
diff --git a/Documentation/devicetree/bindings/input/qcom,pm8921-pwrkey.yaml b/Documentation/devicetree/bindings/input/qcom,pm8921-pwrkey.yaml index 12c74c0..6459089 100644 --- a/Documentation/devicetree/bindings/input/qcom,pm8921-pwrkey.yaml +++ b/Documentation/devicetree/bindings/input/qcom,pm8921-pwrkey.yaml
@@ -52,24 +52,24 @@ examples: - | - #include <dt-bindings/interrupt-controller/irq.h> - ssbi { - #address-cells = <1>; - #size-cells = <0>; + #include <dt-bindings/interrupt-controller/irq.h> + ssbi { + #address-cells = <1>; + #size-cells = <0>; - pmic@0 { - reg = <0x0>; - #address-cells = <1>; - #size-cells = <0>; + pmic@0 { + reg = <0x0>; + #address-cells = <1>; + #size-cells = <0>; - pwrkey@1c { - compatible = "qcom,pm8921-pwrkey"; - reg = <0x1c>; - interrupt-parent = <&pmicint>; - interrupts = <50 IRQ_TYPE_EDGE_RISING>, <51 IRQ_TYPE_EDGE_RISING>; - debounce = <15625>; - pull-up; - }; - }; - }; + pwrkey@1c { + compatible = "qcom,pm8921-pwrkey"; + reg = <0x1c>; + interrupt-parent = <&pmicint>; + interrupts = <50 IRQ_TYPE_EDGE_RISING>, <51 IRQ_TYPE_EDGE_RISING>; + debounce = <15625>; + pull-up; + }; + }; + }; ...
diff --git a/Documentation/devicetree/bindings/input/touchscreen/apple,z2-multitouch.yaml b/Documentation/devicetree/bindings/input/touchscreen/apple,z2-multitouch.yaml new file mode 100644 index 0000000..402ca6b --- /dev/null +++ b/Documentation/devicetree/bindings/input/touchscreen/apple,z2-multitouch.yaml
@@ -0,0 +1,70 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/input/touchscreen/apple,z2-multitouch.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Apple touchscreens attached using the Z2 protocol + +maintainers: + - Sasha Finkelstein <fnkl.kernel@gmail.com> + +description: A series of touschscreen controllers used in Apple products + +allOf: + - $ref: touchscreen.yaml# + - $ref: /schemas/spi/spi-peripheral-props.yaml# + +properties: + compatible: + enum: + - apple,j293-touchbar + - apple,j493-touchbar + + interrupts: + maxItems: 1 + + reset-gpios: + maxItems: 1 + + firmware-name: + maxItems: 1 + + apple,z2-cal-blob: + $ref: /schemas/types.yaml#/definitions/uint8-array + maxItems: 4096 + description: + Calibration blob supplied by the bootloader + +required: + - compatible + - interrupts + - reset-gpios + - firmware-name + - touchscreen-size-x + - touchscreen-size-y + +unevaluatedProperties: false + +examples: + - | + #include <dt-bindings/gpio/gpio.h> + #include <dt-bindings/interrupt-controller/irq.h> + + spi { + #address-cells = <1>; + #size-cells = <0>; + + touchscreen@0 { + compatible = "apple,j293-touchbar"; + reg = <0>; + spi-max-frequency = <11500000>; + reset-gpios = <&pinctrl_ap 139 GPIO_ACTIVE_LOW>; + interrupts-extended = <&pinctrl_ap 194 IRQ_TYPE_EDGE_FALLING>; + firmware-name = "apple/dfrmtfw-j293.bin"; + touchscreen-size-x = <23045>; + touchscreen-size-y = <640>; + }; + }; + +...
diff --git a/Documentation/devicetree/bindings/input/touchscreen/goodix,gt9916.yaml b/Documentation/devicetree/bindings/input/touchscreen/goodix,gt9916.yaml index d90f045..c40d92b 100644 --- a/Documentation/devicetree/bindings/input/touchscreen/goodix,gt9916.yaml +++ b/Documentation/devicetree/bindings/input/touchscreen/goodix,gt9916.yaml
@@ -19,6 +19,7 @@ properties: compatible: enum: + - goodix,gt9897 - goodix,gt9916 reg:
diff --git a/Documentation/devicetree/bindings/input/touchscreen/ti,ads7843.yaml b/Documentation/devicetree/bindings/input/touchscreen/ti,ads7843.yaml index 6049217..8f6335d 100644 --- a/Documentation/devicetree/bindings/input/touchscreen/ti,ads7843.yaml +++ b/Documentation/devicetree/bindings/input/touchscreen/ti,ads7843.yaml
@@ -164,20 +164,20 @@ #size-cells = <0>; touchscreen@0 { - compatible = "ti,tsc2046"; - reg = <0>; /* CS0 */ - interrupt-parent = <&gpio1>; - interrupts = <8 0>; /* BOOT6 / GPIO 8 */ - pendown-gpio = <&gpio1 8 0>; - spi-max-frequency = <1000000>; - vcc-supply = <®_vcc3>; - wakeup-source; + compatible = "ti,tsc2046"; + reg = <0>; /* CS0 */ + interrupt-parent = <&gpio1>; + interrupts = <8 0>; /* BOOT6 / GPIO 8 */ + pendown-gpio = <&gpio1 8 0>; + spi-max-frequency = <1000000>; + vcc-supply = <®_vcc3>; + wakeup-source; - ti,pressure-max = /bits/ 16 <255>; - ti,x-max = /bits/ 16 <8000>; - ti,x-min = /bits/ 16 <0>; - ti,x-plate-ohms = /bits/ 16 <40>; - ti,y-max = /bits/ 16 <4800>; - ti,y-min = /bits/ 16 <0>; - }; + ti,pressure-max = /bits/ 16 <255>; + ti,x-max = /bits/ 16 <8000>; + ti,x-min = /bits/ 16 <0>; + ti,x-plate-ohms = /bits/ 16 <40>; + ti,y-max = /bits/ 16 <4800>; + ti,y-min = /bits/ 16 <0>; + }; };
diff --git a/Documentation/devicetree/bindings/mfd/aspeed-lpc.yaml b/Documentation/devicetree/bindings/mfd/aspeed-lpc.yaml index 5dfe77a..d88854e 100644 --- a/Documentation/devicetree/bindings/mfd/aspeed-lpc.yaml +++ b/Documentation/devicetree/bindings/mfd/aspeed-lpc.yaml
@@ -1,5 +1,5 @@ # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) -# # Copyright (c) 2021 Aspeed Tehchnology Inc. +# # Copyright (c) 2021 Aspeed Technology Inc. %YAML 1.2 --- $id: http://devicetree.org/schemas/mfd/aspeed-lpc.yaml#
diff --git a/Documentation/devicetree/bindings/power/wakeup-source.txt b/Documentation/devicetree/bindings/power/wakeup-source.txt index 27f1797..66bb016 100644 --- a/Documentation/devicetree/bindings/power/wakeup-source.txt +++ b/Documentation/devicetree/bindings/power/wakeup-source.txt
@@ -23,7 +23,7 @@ 1. "gpio-key,wakeup" Documentation/devicetree/bindings/input/gpio-keys{,-polled}.txt 2. "has-tpo" Documentation/devicetree/bindings/rtc/rtc-opal.txt -3. "linux,wakeup" Documentation/devicetree/bindings/input/gpio-matrix-keypad.txt +3. "linux,wakeup" Documentation/devicetree/bindings/input/gpio-matrix-keypad.yaml Documentation/devicetree/bindings/mfd/tc3589x.txt Documentation/devicetree/bindings/input/touchscreen/ti,ads7843.yaml 4. "linux,keypad-wakeup" Documentation/devicetree/bindings/input/qcom,pm8921-keypad.yaml
diff --git a/Documentation/devicetree/bindings/riscv/extensions.yaml b/Documentation/devicetree/bindings/riscv/extensions.yaml index a63b994..bcab59e 100644 --- a/Documentation/devicetree/bindings/riscv/extensions.yaml +++ b/Documentation/devicetree/bindings/riscv/extensions.yaml
@@ -224,6 +224,12 @@ as ratified at commit 4a69197e5617 ("Update to ratified state") of riscv-svvptc. + - const: zaamo + description: | + The standard Zaamo extension for atomic memory operations as + ratified at commit e87412e621f1 ("integrate Zaamo and Zalrsc text + (#1304)") of the unprivileged ISA specification. + - const: zabha description: | The Zabha extension for Byte and Halfword Atomic Memory Operations @@ -236,6 +242,12 @@ is supported as ratified at commit 5059e0ca641c ("update to ratified") of the riscv-zacas. + - const: zalrsc + description: | + The standard Zalrsc extension for load-reserved/store-conditional as + ratified at commit e87412e621f1 ("integrate Zaamo and Zalrsc text + (#1304)") of the unprivileged ISA specification. + - const: zawrs description: | The Zawrs extension for entering a low-power state or for trapping @@ -329,6 +341,12 @@ instructions, as ratified in commit 056b6ff ("Zfa is ratified") of riscv-isa-manual. + - const: zfbfmin + description: + The standard Zfbfmin extension which provides minimal support for + 16-bit half-precision brain floating-point instructions, as ratified + in commit 4dc23d62 ("Added Chapter title to BF16") of riscv-isa-manual. + - const: zfh description: The standard Zfh extension for 16-bit half-precision binary @@ -525,6 +543,18 @@ in commit 6f702a2 ("Vector extensions are now ratified") of riscv-v-spec. + - const: zvfbfmin + description: + The standard Zvfbfmin extension for minimal support for vectored + 16-bit half-precision brain floating-point instructions, as ratified + in commit 4dc23d62 ("Added Chapter title to BF16") of riscv-isa-manual. + + - const: zvfbfwma + description: + The standard Zvfbfwma extension for vectored half-precision brain + floating-point widening multiply-accumulate instructions, as ratified + in commit 4dc23d62 ("Added Chapter title to BF16") of riscv-isa-manual. + - const: zvfh description: The standard Zvfh extension for vectored half-precision @@ -639,6 +669,12 @@ https://github.com/T-head-Semi/thead-extension-spec/blob/95358cb2cca9489361c61d335e03d3134b14133f/xtheadvector.adoc. allOf: + - if: + contains: + const: d + then: + contains: + const: f # Zcb depends on Zca - if: contains: @@ -673,6 +709,119 @@ then: contains: const: zca + # Zfbfmin depends on F + - if: + contains: + const: zfbfmin + then: + contains: + const: f + # Zvfbfmin depends on V or Zve32f + - if: + contains: + const: zvfbfmin + then: + oneOf: + - contains: + const: v + - contains: + const: zve32f + # Zvfbfwma depends on Zfbfmin and Zvfbfmin + - if: + contains: + const: zvfbfwma + then: + allOf: + - contains: + const: zfbfmin + - contains: + const: zvfbfmin + # Zacas depends on Zaamo + - if: + contains: + const: zacas + then: + contains: + const: zaamo + + - if: + contains: + const: zve32x + then: + contains: + const: zicsr + + - if: + contains: + const: zve32f + then: + allOf: + - contains: + const: f + - contains: + const: zve32x + + - if: + contains: + const: zve64x + then: + contains: + const: zve32x + + - if: + contains: + const: zve64f + then: + allOf: + - contains: + const: f + - contains: + const: zve32f + - contains: + const: zve64x + + - if: + contains: + const: zve64d + then: + allOf: + - contains: + const: d + - contains: + const: zve64f + + - if: + contains: + anyOf: + - const: zvbc + - const: zvkn + - const: zvknc + - const: zvkng + - const: zvknhb + - const: zvksc + then: + contains: + anyOf: + - const: v + - const: zve64x + + - if: + contains: + anyOf: + - const: zvbb + - const: zvkb + - const: zvkg + - const: zvkned + - const: zvknha + - const: zvksed + - const: zvksh + - const: zvks + - const: zvkt + then: + contains: + anyOf: + - const: v + - const: zve32x allOf: # Zcf extension does not exist on rv64
diff --git a/Documentation/devicetree/bindings/rtc/adi,max31335.yaml b/Documentation/devicetree/bindings/rtc/adi,max31335.yaml index 0125cf6..bce7558 100644 --- a/Documentation/devicetree/bindings/rtc/adi,max31335.yaml +++ b/Documentation/devicetree/bindings/rtc/adi,max31335.yaml
@@ -18,7 +18,9 @@ properties: compatible: - const: adi,max31335 + enum: + - adi,max31331 + - adi,max31335 reg: maxItems: 1
diff --git a/Documentation/devicetree/bindings/rtc/nxp,pcf2127.yaml b/Documentation/devicetree/bindings/rtc/nxp,pcf2127.yaml index 2d9fe5a..11fcf0c 100644 --- a/Documentation/devicetree/bindings/rtc/nxp,pcf2127.yaml +++ b/Documentation/devicetree/bindings/rtc/nxp,pcf2127.yaml
@@ -8,6 +8,7 @@ allOf: - $ref: rtc.yaml# + - $ref: /schemas/spi/spi-peripheral-props.yaml# maintainers: - Alexandre Belloni <alexandre.belloni@bootlin.com> @@ -34,7 +35,7 @@ - compatible - reg -additionalProperties: false +unevaluatedProperties: false examples: - |
diff --git a/Documentation/devicetree/bindings/rtc/qcom-pm8xxx-rtc.yaml b/Documentation/devicetree/bindings/rtc/qcom-pm8xxx-rtc.yaml index d274bb7..68ef320 100644 --- a/Documentation/devicetree/bindings/rtc/qcom-pm8xxx-rtc.yaml +++ b/Documentation/devicetree/bindings/rtc/qcom-pm8xxx-rtc.yaml
@@ -50,6 +50,11 @@ items: - const: offset + qcom,no-alarm: + type: boolean + description: + RTC alarm is not owned by the OS + wakeup-source: true required:
diff --git a/Documentation/devicetree/bindings/serial/8250.yaml b/Documentation/devicetree/bindings/serial/8250.yaml index 0bde237..dc0d529 100644 --- a/Documentation/devicetree/bindings/serial/8250.yaml +++ b/Documentation/devicetree/bindings/serial/8250.yaml
@@ -77,7 +77,6 @@ - altr,16550-FIFO64 - altr,16550-FIFO128 - fsl,16550-FIFO64 - - fsl,ns16550 - andestech,uart16550 - nxp,lpc1850-uart - opencores,uart16550-rtlsvn105 @@ -86,6 +85,7 @@ - items: - enum: - ns16750 + - fsl,ns16550 - cavium,octeon-3860-uart - xlnx,xps-uart16550-2.00.b - ralink,rt2880-uart
diff --git a/Documentation/devicetree/bindings/serial/fsl-lpuart.yaml b/Documentation/devicetree/bindings/serial/fsl-lpuart.yaml index 3f9ace8..c42261b 100644 --- a/Documentation/devicetree/bindings/serial/fsl-lpuart.yaml +++ b/Documentation/devicetree/bindings/serial/fsl-lpuart.yaml
@@ -30,6 +30,7 @@ - items: - enum: - fsl,imx93-lpuart + - fsl,imx94-lpuart - fsl,imx95-lpuart - const: fsl,imx8ulp-lpuart - const: fsl,imx7ulp-lpuart
diff --git a/Documentation/devicetree/bindings/serial/nvidia,tegra264-utc.yaml b/Documentation/devicetree/bindings/serial/nvidia,tegra264-utc.yaml new file mode 100644 index 0000000..572cc57 --- /dev/null +++ b/Documentation/devicetree/bindings/serial/nvidia,tegra264-utc.yaml
@@ -0,0 +1,73 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/serial/nvidia,tegra264-utc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: NVIDIA Tegra UTC (UART Trace Controller) client + +maintainers: + - Kartik Rajput <kkartik@nvidia.com> + - Thierry Reding <thierry.reding@gmail.com> + - Jonathan Hunter <jonathanh@nvidia.com> + +description: + Represents a client interface of the Tegra UTC (UART Trace Controller). The + Tegra UTC allows multiple clients within the Tegra SoC to share a physical + UART interface. It supports up to 16 clients. Each client operates as an + independent UART endpoint with a dedicated interrupt and 128-character TX/RX + FIFOs. + + The Tegra UTC clients use 8-N-1 configuration and operates on a baudrate + configured by the bootloader at the controller level. + +allOf: + - $ref: serial.yaml# + +properties: + compatible: + const: nvidia,tegra264-utc + + reg: + items: + - description: TX region. + - description: RX region. + + reg-names: + items: + - const: tx + - const: rx + + interrupts: + maxItems: 1 + + tx-threshold: + minimum: 1 + maximum: 128 + + rx-threshold: + minimum: 1 + maximum: 128 + +required: + - compatible + - reg + - reg-names + - interrupts + - tx-threshold + - rx-threshold + +additionalProperties: false + +examples: + - | + #include <dt-bindings/interrupt-controller/arm-gic.h> + + tegra_utc: serial@c4e0000 { + compatible = "nvidia,tegra264-utc"; + reg = <0xc4e0000 0x8000>, <0xc4e8000 0x8000>; + reg-names = "tx", "rx"; + interrupts = <GIC_SPI 514 IRQ_TYPE_LEVEL_HIGH>; + tx-threshold = <4>; + rx-threshold = <4>; + };
diff --git a/Documentation/devicetree/bindings/serial/pl011.yaml b/Documentation/devicetree/bindings/serial/pl011.yaml index 95710410..3fcf2d0 100644 --- a/Documentation/devicetree/bindings/serial/pl011.yaml +++ b/Documentation/devicetree/bindings/serial/pl011.yaml
@@ -92,6 +92,9 @@ 3000ms. default: 3000 + power-domains: + maxItems: 1 + resets: maxItems: 1
diff --git a/Documentation/devicetree/bindings/serial/samsung_uart.yaml b/Documentation/devicetree/bindings/serial/samsung_uart.yaml index 070eba9..83d9986 100644 --- a/Documentation/devicetree/bindings/serial/samsung_uart.yaml +++ b/Documentation/devicetree/bindings/serial/samsung_uart.yaml
@@ -42,6 +42,10 @@ - samsung,exynosautov9-uart - samsung,exynosautov920-uart - const: samsung,exynos850-uart + - items: + - enum: + - samsung,exynos7870-uart + - const: samsung,exynos8895-uart reg: maxItems: 1
diff --git a/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.yaml b/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.yaml index 1c163cb..1aa3480 100644 --- a/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.yaml +++ b/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.yaml
@@ -16,6 +16,20 @@ - if: properties: compatible: + items: + - enum: + - renesas,r9a06g032-uart + - renesas,r9a06g033-uart + - const: renesas,rzn1-uart + - const: snps,dw-apb-uart + then: + properties: + dmas: false + dma-names: false + + - if: + properties: + compatible: contains: const: starfive,jh7110-uart then: @@ -35,6 +49,12 @@ - renesas,r9a06g032-uart - renesas,r9a06g033-uart - const: renesas,rzn1-uart + - const: snps,dw-apb-uart + - items: + - enum: + - renesas,r9a06g032-uart + - renesas,r9a06g033-uart + - const: renesas,rzn1-uart - items: - enum: - brcm,bcm11351-dw-apb-uart @@ -51,6 +71,7 @@ - rockchip,rk3368-uart - rockchip,rk3399-uart - rockchip,rk3528-uart + - rockchip,rk3562-uart - rockchip,rk3568-uart - rockchip,rk3576-uart - rockchip,rk3588-uart
diff --git a/Documentation/devicetree/bindings/serial/sprd-uart.yaml b/Documentation/devicetree/bindings/serial/sprd-uart.yaml index a2a5056..5bf2656 100644 --- a/Documentation/devicetree/bindings/serial/sprd-uart.yaml +++ b/Documentation/devicetree/bindings/serial/sprd-uart.yaml
@@ -17,13 +17,18 @@ oneOf: - items: - enum: - - sprd,sc9632-uart + - sprd,ums9632-uart + - const: sprd,sc9632-uart + - items: + - enum: - sprd,sc9860-uart - sprd,sc9863a-uart - sprd,ums512-uart - sprd,ums9620-uart - const: sprd,sc9836-uart - - const: sprd,sc9836-uart + - enum: + - sprd,sc9632-uart + - sprd,sc9836-uart reg: maxItems: 1
diff --git a/Documentation/devicetree/bindings/usb/generic-xhci.yaml b/Documentation/devicetree/bindings/usb/generic-xhci.yaml index 6ceafa4..a2b94a1 100644 --- a/Documentation/devicetree/bindings/usb/generic-xhci.yaml +++ b/Documentation/devicetree/bindings/usb/generic-xhci.yaml
@@ -51,6 +51,8 @@ - const: core - const: reg + dma-coherent: true + power-domains: maxItems: 1
diff --git a/Documentation/devicetree/bindings/usb/microchip,usb2514.yaml b/Documentation/devicetree/bindings/usb/microchip,usb2514.yaml index b14e6f3..4e3901e 100644 --- a/Documentation/devicetree/bindings/usb/microchip,usb2514.yaml +++ b/Documentation/devicetree/bindings/usb/microchip,usb2514.yaml
@@ -9,16 +9,19 @@ maintainers: - Fabio Estevam <festevam@gmail.com> -allOf: - - $ref: usb-device.yaml# - properties: compatible: - enum: - - usb424,2412 - - usb424,2417 - - usb424,2514 - - usb424,2517 + oneOf: + - enum: + - usb424,2412 + - usb424,2417 + - usb424,2514 + - usb424,2517 + - items: + - enum: + - usb424,2512 + - usb424,2513 + - const: usb424,2514 reg: true @@ -28,6 +31,9 @@ vdd-supply: description: 3.3V power supply. + vdda-supply: + description: 3.3V analog power supply. + clocks: description: External 24MHz clock connected to the CLKIN pin. maxItems: 1 @@ -43,6 +49,18 @@ $ref: /schemas/usb/usb-device.yaml additionalProperties: true +allOf: + - $ref: usb-device.yaml# + - if: + not: + properties: + compatible: + contains: + const: usb424,2514 + then: + properties: + vdda-supply: false + unevaluatedProperties: false examples: @@ -60,6 +78,7 @@ clocks = <&clks IMX6QDL_CLK_CKO>; reset-gpios = <&gpio7 12 GPIO_ACTIVE_LOW>; vdd-supply = <®_3v3_hub>; + vdda-supply = <®_3v3a_hub>; #address-cells = <1>; #size-cells = <0>;
diff --git a/Documentation/devicetree/bindings/usb/parade,ps8830.yaml b/Documentation/devicetree/bindings/usb/parade,ps8830.yaml new file mode 100644 index 0000000..935d57f --- /dev/null +++ b/Documentation/devicetree/bindings/usb/parade,ps8830.yaml
@@ -0,0 +1,140 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/usb/parade,ps8830.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Parade PS883x USB and DisplayPort Retimer + +maintainers: + - Abel Vesa <abel.vesa@linaro.org> + +properties: + compatible: + enum: + - parade,ps8830 + + reg: + maxItems: 1 + + clocks: + items: + - description: XO Clock + + reset-gpios: + maxItems: 1 + + vdd-supply: + description: power supply (1.07V) + + vdd33-supply: + description: power supply (3.3V) + + vdd33-cap-supply: + description: power supply (3.3V) + + vddar-supply: + description: power supply (1.07V) + + vddat-supply: + description: power supply (1.07V) + + vddio-supply: + description: power supply (1.2V or 1.8V) + + orientation-switch: true + retimer-switch: true + + ports: + $ref: /schemas/graph.yaml#/properties/ports + properties: + port@0: + $ref: /schemas/graph.yaml#/properties/port + description: Super Speed (SS) Output endpoint to the Type-C connector + + port@1: + $ref: /schemas/graph.yaml#/$defs/port-base + description: Super Speed (SS) Input endpoint from the Super-Speed PHY + unevaluatedProperties: false + + port@2: + $ref: /schemas/graph.yaml#/properties/port + description: + Sideband Use (SBU) AUX lines endpoint to the Type-C connector for the purpose of + handling altmode muxing and orientation switching. + +required: + - compatible + - reg + - clocks + - reset-gpios + - vdd-supply + - vdd33-supply + - vdd33-cap-supply + - vddat-supply + - vddio-supply + - orientation-switch + - retimer-switch + +allOf: + - $ref: usb-switch.yaml# + +additionalProperties: false + +examples: + - | + #include <dt-bindings/gpio/gpio.h> + + i2c { + #address-cells = <1>; + #size-cells = <0>; + + typec-mux@8 { + compatible = "parade,ps8830"; + reg = <0x8>; + + clocks = <&clk_rtmr_xo>; + + vdd-supply = <&vreg_rtmr_1p15>; + vdd33-supply = <&vreg_rtmr_3p3>; + vdd33-cap-supply = <&vreg_rtmr_3p3>; + vddar-supply = <&vreg_rtmr_1p15>; + vddat-supply = <&vreg_rtmr_1p15>; + vddio-supply = <&vreg_rtmr_1p8>; + + reset-gpios = <&tlmm 10 GPIO_ACTIVE_LOW>; + + retimer-switch; + orientation-switch; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + endpoint { + remote-endpoint = <&typec_con_ss>; + }; + }; + + port@1 { + reg = <1>; + + endpoint { + remote-endpoint = <&usb_phy_ss>; + }; + }; + + port@2 { + reg = <2>; + + endpoint { + remote-endpoint = <&typec_dp_aux>; + }; + }; + }; + }; + }; +...
diff --git a/Documentation/devicetree/bindings/usb/qcom,dwc3.yaml b/Documentation/devicetree/bindings/usb/qcom,dwc3.yaml index a2b3cf6..64137c1 100644 --- a/Documentation/devicetree/bindings/usb/qcom,dwc3.yaml +++ b/Documentation/devicetree/bindings/usb/qcom,dwc3.yaml
@@ -404,6 +404,7 @@ minItems: 2 maxItems: 3 interrupt-names: + minItems: 2 items: - const: pwr_event - const: qusb2_phy @@ -425,6 +426,7 @@ minItems: 3 maxItems: 4 interrupt-names: + minItems: 3 items: - const: pwr_event - const: qusb2_phy
diff --git a/Documentation/devicetree/bindings/usb/richtek,rt1711h.yaml b/Documentation/devicetree/bindings/usb/richtek,rt1711h.yaml index 8da4d2a..ae611f7 100644 --- a/Documentation/devicetree/bindings/usb/richtek,rt1711h.yaml +++ b/Documentation/devicetree/bindings/usb/richtek,rt1711h.yaml
@@ -30,6 +30,9 @@ interrupts: maxItems: 1 + vbus-supply: + description: VBUS power supply + wakeup-source: type: boolean
diff --git a/Documentation/devicetree/bindings/usb/rockchip,dwc3.yaml b/Documentation/devicetree/bindings/usb/rockchip,dwc3.yaml index a21cc09..fba2cb0 100644 --- a/Documentation/devicetree/bindings/usb/rockchip,dwc3.yaml +++ b/Documentation/devicetree/bindings/usb/rockchip,dwc3.yaml
@@ -26,6 +26,7 @@ contains: enum: - rockchip,rk3328-dwc3 + - rockchip,rk3562-dwc3 - rockchip,rk3568-dwc3 - rockchip,rk3576-dwc3 - rockchip,rk3588-dwc3 @@ -37,6 +38,7 @@ items: - enum: - rockchip,rk3328-dwc3 + - rockchip,rk3562-dwc3 - rockchip,rk3568-dwc3 - rockchip,rk3576-dwc3 - rockchip,rk3588-dwc3 @@ -72,6 +74,7 @@ - enum: - grf_clk - utmi + - pipe - const: pipe power-domains: @@ -115,6 +118,22 @@ properties: compatible: contains: + const: rockchip,rk3562-dwc3 + then: + properties: + clocks: + minItems: 4 + maxItems: 4 + clock-names: + items: + - const: ref_clk + - const: suspend_clk + - const: bus_clk + - const: pipe + - if: + properties: + compatible: + contains: enum: - rockchip,rk3568-dwc3 - rockchip,rk3576-dwc3
diff --git a/Documentation/devicetree/bindings/usb/samsung,exynos-dwc3.yaml b/Documentation/devicetree/bindings/usb/samsung,exynos-dwc3.yaml index 2b3430c..256bee2 100644 --- a/Documentation/devicetree/bindings/usb/samsung,exynos-dwc3.yaml +++ b/Documentation/devicetree/bindings/usb/samsung,exynos-dwc3.yaml
@@ -11,12 +11,17 @@ properties: compatible: - enum: - - google,gs101-dwusb3 - - samsung,exynos5250-dwusb3 - - samsung,exynos5433-dwusb3 - - samsung,exynos7-dwusb3 - - samsung,exynos850-dwusb3 + oneOf: + - enum: + - google,gs101-dwusb3 + - samsung,exynos5250-dwusb3 + - samsung,exynos5433-dwusb3 + - samsung,exynos7-dwusb3 + - samsung,exynos7870-dwusb3 + - samsung,exynos850-dwusb3 + - items: + - const: samsung,exynos990-dwusb3 + - const: samsung,exynos850-dwusb3 '#address-cells': const: 1 @@ -52,7 +57,6 @@ - clock-names - ranges - '#size-cells' - - vdd10-supply - vdd33-supply allOf: @@ -72,6 +76,8 @@ - const: susp_clk - const: link_aclk - const: link_pclk + required: + - vdd10-supply - if: properties: @@ -86,6 +92,8 @@ clock-names: items: - const: usbdrd30 + required: + - vdd10-supply - if: properties: @@ -103,6 +111,8 @@ - const: susp_clk - const: phyclk - const: pipe_pclk + required: + - vdd10-supply - if: properties: @@ -119,6 +129,24 @@ - const: usbdrd30 - const: usbdrd30_susp_clk - const: usbdrd30_axius_clk + required: + - vdd10-supply + + - if: + properties: + compatible: + contains: + const: samsung,exynos7870-dwusb3 + then: + properties: + clocks: + minItems: 3 + maxItems: 3 + clock-names: + items: + - const: bus_early + - const: ref + - const: ctrl - if: properties: @@ -134,6 +162,8 @@ items: - const: bus_early - const: ref + required: + - vdd10-supply additionalProperties: false
diff --git a/Documentation/devicetree/bindings/usb/snps,dwc3-common.yaml b/Documentation/devicetree/bindings/usb/snps,dwc3-common.yaml index c956053..71249b6 100644 --- a/Documentation/devicetree/bindings/usb/snps,dwc3-common.yaml +++ b/Documentation/devicetree/bindings/usb/snps,dwc3-common.yaml
@@ -65,6 +65,17 @@ mode. type: boolean + snps,reserved-endpoints: + description: + Reserve endpoints for other needs, e.g, for tracing control and output. + When set, the driver will avoid using them for the regular USB transfers. + $ref: /schemas/types.yaml#/definitions/uint8-array + minItems: 1 + maxItems: 30 + items: + minimum: 2 + maximum: 31 + snps,dis-start-transfer-quirk: description: When set, disable isoc START TRANSFER command failure SW work-around
diff --git a/Documentation/devicetree/bindings/usb/usb-device.yaml b/Documentation/devicetree/bindings/usb/usb-device.yaml index da890ee..c676956 100644 --- a/Documentation/devicetree/bindings/usb/usb-device.yaml +++ b/Documentation/devicetree/bindings/usb/usb-device.yaml
@@ -39,8 +39,10 @@ reg: description: the number of the USB hub port or the USB host-controller - port to which this device is attached. The range is 1-255. - maxItems: 1 + port to which this device is attached. + items: + - minimum: 1 + maximum: 255 "#address-cells": description: should be 1 for hub nodes with device nodes,
diff --git a/Documentation/driver-api/cxl/maturity-map.rst b/Documentation/driver-api/cxl/maturity-map.rst index df8e2ac..a2288f9 100644 --- a/Documentation/driver-api/cxl/maturity-map.rst +++ b/Documentation/driver-api/cxl/maturity-map.rst
@@ -130,7 +130,7 @@ * [0] Switch CCI * [3] Timestamp * [1] PMEM labels -* [0] PMEM GPF / Dirty Shutdown +* [3] PMEM GPF / Dirty Shutdown * [0] Scan Media PMU
diff --git a/Documentation/driver-api/serial/driver.rst b/Documentation/driver-api/serial/driver.rst index 84b4306..fa1ebfc 100644 --- a/Documentation/driver-api/serial/driver.rst +++ b/Documentation/driver-api/serial/driver.rst
@@ -101,6 +101,6 @@ Some helpers are provided in order to set/get modem control lines via GPIO. .. kernel-doc:: drivers/tty/serial/serial_mctrl_gpio.c - :identifiers: mctrl_gpio_init mctrl_gpio_free mctrl_gpio_to_gpiod + :identifiers: mctrl_gpio_init mctrl_gpio_to_gpiod mctrl_gpio_set mctrl_gpio_get mctrl_gpio_enable_ms - mctrl_gpio_disable_ms + mctrl_gpio_disable_ms_sync mctrl_gpio_disable_ms_no_sync
diff --git a/Documentation/driver-api/tty/tty_driver.rst b/Documentation/driver-api/tty/tty_driver.rst index cc529f8..7138222 100644 --- a/Documentation/driver-api/tty/tty_driver.rst +++ b/Documentation/driver-api/tty/tty_driver.rst
@@ -25,6 +25,8 @@ For reference, both allocation and deallocation functions are explained here in detail: +.. kernel-doc:: include/linux/tty_driver.h + :identifiers: tty_alloc_driver .. kernel-doc:: drivers/tty/tty_io.c :identifiers: __tty_alloc_driver tty_driver_kref_put @@ -35,7 +37,7 @@ __tty_alloc_driver()): .. kernel-doc:: include/linux/tty_driver.h - :doc: TTY Driver Flags + :identifiers: tty_driver_flag ----
diff --git a/Documentation/driver-api/tty/tty_struct.rst b/Documentation/driver-api/tty/tty_struct.rst index c72f5a4..29caf1c 100644 --- a/Documentation/driver-api/tty/tty_struct.rst +++ b/Documentation/driver-api/tty/tty_struct.rst
@@ -72,7 +72,7 @@ ================ .. kernel-doc:: include/linux/tty.h - :doc: TTY Struct Flags + :identifiers: tty_struct_flags TTY Struct Reference ====================
diff --git a/Documentation/driver-api/usb/writing_musb_glue_layer.rst b/Documentation/driver-api/usb/writing_musb_glue_layer.rst index e755c85..0bb96ec 100644 --- a/Documentation/driver-api/usb/writing_musb_glue_layer.rst +++ b/Documentation/driver-api/usb/writing_musb_glue_layer.rst
@@ -613,7 +613,7 @@ to bypass reading the configuration from silicon, and rely on a hard-coded table that describes the endpoints configuration instead:: - static struct musb_fifo_cfg jz4740_musb_fifo_cfg[] = { + static const struct musb_fifo_cfg jz4740_musb_fifo_cfg[] = { { .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, }, { .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, }, { .hw_ep_num = 2, .style = FIFO_TX, .maxpacket = 64, },
diff --git a/Documentation/features/core/mseal_sys_mappings/arch-support.txt b/Documentation/features/core/mseal_sys_mappings/arch-support.txt new file mode 100644 index 0000000..c6cab976 --- /dev/null +++ b/Documentation/features/core/mseal_sys_mappings/arch-support.txt
@@ -0,0 +1,30 @@ +# +# Feature name: mseal-system-mappings +# Kconfig: ARCH_SUPPORTS_MSEAL_SYSTEM_MAPPINGS +# description: arch supports mseal system mappings +# + ----------------------- + | arch |status| + ----------------------- + | alpha: | TODO | + | arc: | N/A | + | arm: | N/A | + | arm64: | ok | + | csky: | N/A | + | hexagon: | N/A | + | loongarch: | TODO | + | m68k: | N/A | + | microblaze: | N/A | + | mips: | TODO | + | nios2: | N/A | + | openrisc: | N/A | + | parisc: | TODO | + | powerpc: | TODO | + | riscv: | TODO | + | s390: | ok | + | sh: | N/A | + | sparc: | TODO | + | um: | TODO | + | x86: | ok | + | xtensa: | N/A | + -----------------------
diff --git a/Documentation/filesystems/9p.rst b/Documentation/filesystems/9p.rst index 3078f3c..be3504c 100644 --- a/Documentation/filesystems/9p.rst +++ b/Documentation/filesystems/9p.rst
@@ -40,7 +40,7 @@ mount -t 9p 10.10.1.2 /mnt/9 -For Plan 9 From User Space applications (http://swtch.com/plan9):: +For Plan 9 From User Space applications (https://9fans.github.io/plan9port/):: mount -t 9p `namespace`/acme /mnt/9 -o trans=unix,uname=$USER @@ -165,8 +165,8 @@ do not necessarily validate cached values on the server. In other words changes on the server are not guaranteed to be reflected on the client system. Only use this mode of operation if you - have an exclusive mount and the server will modify the filesystem - underneath you. + have an exclusive mount and the server will not modify the + filesystem underneath you. debug=n specifies debug level. The debug level is a bitmask.
diff --git a/Documentation/kbuild/bash-completion.rst b/Documentation/kbuild/bash-completion.rst new file mode 100644 index 0000000..2b52dbc --- /dev/null +++ b/Documentation/kbuild/bash-completion.rst
@@ -0,0 +1,65 @@ +.. SPDX-License-Identifier: GPL-2.0-only + +========================== +Bash completion for Kbuild +========================== + +The kernel build system is written using Makefiles, and Bash completion +for the `make` command is available through the `bash-completion`_ project. + +However, the Makefiles for the kernel build are complex. The generic completion +rules for the `make` command do not provide meaningful suggestions for the +kernel build system, except for the options of the `make` command itself. + +To enhance completion for various variables and targets, the kernel source +includes its own completion script at `scripts/bash-completion/make`. + +This script provides additional completions when working within the kernel tree. +Outside the kernel tree, it defaults to the generic completion rules for the +`make` command. + +Prerequisites +============= + +The script relies on helper functions provided by `bash-completion`_ project. +Please ensure it is installed on your system. On most distributions, you can +install the `bash-completion` package through the standard package manager. + +How to use +========== + +You can source the script directly:: + + $ source scripts/bash-completion/make + +Or, you can copy it into the search path for Bash completion scripts. +For example:: + + $ mkdir -p ~/.local/share/bash-completion/completions + $ cp scripts/bash-completion/make ~/.local/share/bash-completion/completions/ + +Details +======= + +The additional completion for Kbuild is enabled in the following cases: + + - You are in the root directory of the kernel source. + - You are in the top-level build directory created by the O= option + (checked via the `source` symlink pointing to the kernel source). + - The -C make option specifies the kernel source or build directory. + - The -f make option specifies a file in the kernel source or build directory. + +If none of the above are met, it falls back to the generic completion rules. + +The completion supports: + + - Commonly used targets, such as `all`, `menuconfig`, `dtbs`, etc. + - Make (or environment) variables, such as `ARCH`, `LLVM`, etc. + - Single-target builds (`foo/bar/baz.o`) + - Configuration files (`*_defconfig` and `*.config`) + +Some variables offer intelligent behavior. For instance, `CROSS_COMPILE=` +followed by a TAB displays installed toolchains. The list of defconfig files +shown depends on the value of the `ARCH=` variable. + +.. _bash-completion: https://github.com/scop/bash-completion/
diff --git a/Documentation/kbuild/index.rst b/Documentation/kbuild/index.rst index e82af05..3731ab2 100644 --- a/Documentation/kbuild/index.rst +++ b/Documentation/kbuild/index.rst
@@ -23,6 +23,8 @@ llvm gendwarfksyms + bash-completion + .. only:: subproject and html Indices
diff --git a/Documentation/kbuild/kconfig-language.rst b/Documentation/kbuild/kconfig-language.rst index 2619fdf..a91abb8 100644 --- a/Documentation/kbuild/kconfig-language.rst +++ b/Documentation/kbuild/kconfig-language.rst
@@ -194,16 +194,6 @@ ability to hook into a secondary subsystem while allowing the user to configure that subsystem out without also having to unset these drivers. - Note: If the combination of FOO=y and BAZ=m causes a link error, - you can guard the function call with IS_REACHABLE():: - - foo_init() - { - if (IS_REACHABLE(CONFIG_BAZ)) - baz_register(&foo); - ... - } - Note: If the feature provided by BAZ is highly desirable for FOO, FOO should imply not only BAZ, but also its dependency BAR:: @@ -588,7 +578,9 @@ depends on BAR || !BAR This means that there is either a dependency on BAR that disallows -the combination of FOO=y with BAR=m, or BAR is completely disabled. +the combination of FOO=y with BAR=m, or BAR is completely disabled. The BAR +module must provide all the stubs for !BAR case. + For a more formalized approach if there are multiple drivers that have the same dependency, a helper symbol can be used, like:: @@ -599,6 +591,21 @@ config BAR_OPTIONAL def_tristate BAR || !BAR +Much less favorable way to express optional dependency is IS_REACHABLE() within +the module code, useful for example when the module BAR does not provide +!BAR stubs:: + + foo_init() + { + if (IS_REACHABLE(CONFIG_BAR)) + bar_register(&foo); + ... + } + +IS_REACHABLE() is generally discouraged, because the code will be silently +discarded, when CONFIG_BAR=m and this code is built-in. This is not what users +usually expect when enabling BAR as module. + Kconfig recursive dependency limitations ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/Documentation/kbuild/makefiles.rst b/Documentation/kbuild/makefiles.rst index d36519f..3b9a8bc 100644 --- a/Documentation/kbuild/makefiles.rst +++ b/Documentation/kbuild/makefiles.rst
@@ -318,9 +318,6 @@ These three flags apply only to the kbuild makefile in which they are assigned. They are used for all the normal cc, as and ld invocations happening during a recursive build. - Note: Flags with the same behaviour were previously named: - EXTRA_CFLAGS, EXTRA_AFLAGS and EXTRA_LDFLAGS. - They are still supported but their usage is deprecated. ccflags-y specifies options for compiling with $(CC). @@ -670,6 +667,20 @@ endif endif +$(RUSTC) support functions +-------------------------- + +rustc-min-version + rustc-min-version tests if the value of $(CONFIG_RUSTC_VERSION) is greater + than or equal to the provided value and evaluates to y if so. + + Example:: + + rustflags-$(call rustc-min-version, 108500) := -Cfoo + + In this example, rustflags-y will be assigned the value -Cfoo if + $(CONFIG_RUSTC_VERSION) is >= 1.85.0. + $(LD) support functions -----------------------
diff --git a/Documentation/kbuild/modules.rst b/Documentation/kbuild/modules.rst index a42f00d..d070360 100644 --- a/Documentation/kbuild/modules.rst +++ b/Documentation/kbuild/modules.rst
@@ -318,7 +318,7 @@ | |__ include | |__ hardwareif.h |__ include - |__ complex.h + |__ complex.h To build the module complex.ko, we then need the following kbuild file::
diff --git a/Documentation/kbuild/reproducible-builds.rst b/Documentation/kbuild/reproducible-builds.rst index f2dcc39..a776248 100644 --- a/Documentation/kbuild/reproducible-builds.rst +++ b/Documentation/kbuild/reproducible-builds.rst
@@ -46,21 +46,6 @@ `KBUILD_BUILD_USER and KBUILD_BUILD_HOST`_ variables. If you are building from a git commit, you could use its committer address. -Absolute filenames ------------------- - -When the kernel is built out-of-tree, debug information may include -absolute filenames for the source files. This must be overridden by -including the ``-fdebug-prefix-map`` option in the `KCFLAGS`_ variable. - -Depending on the compiler used, the ``__FILE__`` macro may also expand -to an absolute filename in an out-of-tree build. Kbuild automatically -uses the ``-fmacro-prefix-map`` option to prevent this, if it is -supported. - -The Reproducible Builds web site has more information about these -`prefix-map options`_. - Generated files in source packages ---------------------------------- @@ -131,7 +116,5 @@ .. _KBUILD_BUILD_TIMESTAMP: kbuild.html#kbuild-build-timestamp .. _KBUILD_BUILD_USER and KBUILD_BUILD_HOST: kbuild.html#kbuild-build-user-kbuild-build-host -.. _KCFLAGS: kbuild.html#kcflags -.. _prefix-map options: https://reproducible-builds.org/docs/build-path/ .. _Reproducible Builds project: https://reproducible-builds.org/ .. _SOURCE_DATE_EPOCH: https://reproducible-builds.org/docs/source-date-epoch/
diff --git a/Documentation/netlink/specs/rt_addr.yaml b/Documentation/netlink/specs/rt_addr.yaml index 5dd5469..df6b23f 100644 --- a/Documentation/netlink/specs/rt_addr.yaml +++ b/Documentation/netlink/specs/rt_addr.yaml
@@ -78,45 +78,46 @@ attribute-sets: - name: addr-attrs + name-prefix: ifa- attributes: - - name: ifa-address + name: address type: binary display-hint: ipv4 - - name: ifa-local + name: local type: binary display-hint: ipv4 - - name: ifa-label + name: label type: string - - name: ifa-broadcast + name: broadcast type: binary display-hint: ipv4 - - name: ifa-anycast + name: anycast type: binary - - name: ifa-cacheinfo + name: cacheinfo type: binary struct: ifa-cacheinfo - - name: ifa-multicast + name: multicast type: binary - - name: ifa-flags + name: flags type: u32 enum: ifa-flags enum-as-flags: true - - name: ifa-rt-priority + name: rt-priority type: u32 - - name: ifa-target-netnsid + name: target-netnsid type: binary - - name: ifa-proto + name: proto type: u8 @@ -137,10 +138,10 @@ - ifa-prefixlen - ifa-scope - ifa-index - - ifa-address - - ifa-label - - ifa-local - - ifa-cacheinfo + - address + - label + - local + - cacheinfo - name: deladdr doc: Remove address @@ -154,8 +155,8 @@ - ifa-prefixlen - ifa-scope - ifa-index - - ifa-address - - ifa-local + - address + - local - name: getaddr doc: Dump address information. @@ -169,7 +170,7 @@ value: 20 attributes: *ifaddr-all - - name: getmaddrs + name: getmulticast doc: Get / dump IPv4/IPv6 multicast addresses. attribute-set: addr-attrs fixed-header: ifaddrmsg @@ -182,11 +183,12 @@ reply: value: 58 attributes: &mcaddr-attrs - - ifa-multicast - - ifa-cacheinfo + - multicast + - cacheinfo dump: request: value: 58 + attributes: - ifa-family reply: value: 58
diff --git a/Documentation/netlink/specs/rt_route.yaml b/Documentation/netlink/specs/rt_route.yaml index a674103..292469c 100644 --- a/Documentation/netlink/specs/rt_route.yaml +++ b/Documentation/netlink/specs/rt_route.yaml
@@ -80,165 +80,167 @@ attribute-sets: - name: route-attrs + name-prefix: rta- attributes: - - name: rta-dst + name: dst type: binary display-hint: ipv4 - - name: rta-src + name: src type: binary display-hint: ipv4 - - name: rta-iif + name: iif type: u32 - - name: rta-oif + name: oif type: u32 - - name: rta-gateway + name: gateway type: binary display-hint: ipv4 - - name: rta-priority + name: priority type: u32 - - name: rta-prefsrc + name: prefsrc type: binary display-hint: ipv4 - - name: rta-metrics + name: metrics type: nest - nested-attributes: rta-metrics + nested-attributes: metrics - - name: rta-multipath + name: multipath type: binary - - name: rta-protoinfo # not used + name: protoinfo # not used type: binary - - name: rta-flow + name: flow type: u32 - - name: rta-cacheinfo + name: cacheinfo type: binary struct: rta-cacheinfo - - name: rta-session # not used + name: session # not used type: binary - - name: rta-mp-algo # not used + name: mp-algo # not used type: binary - - name: rta-table + name: table type: u32 - - name: rta-mark + name: mark type: u32 - - name: rta-mfc-stats + name: mfc-stats type: binary - - name: rta-via + name: via type: binary - - name: rta-newdst + name: newdst type: binary - - name: rta-pref + name: pref type: u8 - - name: rta-encap-type + name: encap-type type: u16 - - name: rta-encap + name: encap type: binary # tunnel specific nest - - name: rta-expires + name: expires type: u32 - - name: rta-pad + name: pad type: binary - - name: rta-uid + name: uid type: u32 - - name: rta-ttl-propagate + name: ttl-propagate type: u8 - - name: rta-ip-proto + name: ip-proto type: u8 - - name: rta-sport + name: sport type: u16 - - name: rta-dport + name: dport type: u16 - - name: rta-nh-id + name: nh-id type: u32 - - name: rta-flowlabel + name: flowlabel type: u32 byte-order: big-endian display-hint: hex - - name: rta-metrics + name: metrics + name-prefix: rtax- attributes: - - name: rtax-unspec + name: unspec type: unused value: 0 - - name: rtax-lock + name: lock type: u32 - - name: rtax-mtu + name: mtu type: u32 - - name: rtax-window + name: window type: u32 - - name: rtax-rtt + name: rtt type: u32 - - name: rtax-rttvar + name: rttvar type: u32 - - name: rtax-ssthresh + name: ssthresh type: u32 - - name: rtax-cwnd + name: cwnd type: u32 - - name: rtax-advmss + name: advmss type: u32 - - name: rtax-reordering + name: reordering type: u32 - - name: rtax-hoplimit + name: hoplimit type: u32 - - name: rtax-initcwnd + name: initcwnd type: u32 - - name: rtax-features + name: features type: u32 - - name: rtax-rto-min + name: rto-min type: u32 - - name: rtax-initrwnd + name: initrwnd type: u32 - - name: rtax-quickack + name: quickack type: u32 - - name: rtax-cc-algo + name: cc-algo type: string - - name: rtax-fastopen-no-cookie + name: fastopen-no-cookie type: u32 operations: @@ -254,18 +256,18 @@ value: 26 attributes: - rtm-family - - rta-src + - src - rtm-src-len - - rta-dst + - dst - rtm-dst-len - - rta-iif - - rta-oif - - rta-ip-proto - - rta-sport - - rta-dport - - rta-mark - - rta-uid - - rta-flowlabel + - iif + - oif + - ip-proto + - sport + - dport + - mark + - uid + - flowlabel reply: value: 24 attributes: &all-route-attrs @@ -278,34 +280,34 @@ - rtm-scope - rtm-type - rtm-flags - - rta-dst - - rta-src - - rta-iif - - rta-oif - - rta-gateway - - rta-priority - - rta-prefsrc - - rta-metrics - - rta-multipath - - rta-flow - - rta-cacheinfo - - rta-table - - rta-mark - - rta-mfc-stats - - rta-via - - rta-newdst - - rta-pref - - rta-encap-type - - rta-encap - - rta-expires - - rta-pad - - rta-uid - - rta-ttl-propagate - - rta-ip-proto - - rta-sport - - rta-dport - - rta-nh-id - - rta-flowlabel + - dst + - src + - iif + - oif + - gateway + - priority + - prefsrc + - metrics + - multipath + - flow + - cacheinfo + - table + - mark + - mfc-stats + - via + - newdst + - pref + - encap-type + - encap + - expires + - pad + - uid + - ttl-propagate + - ip-proto + - sport + - dport + - nh-id + - flowlabel dump: request: value: 26
diff --git a/Documentation/networking/netdevices.rst b/Documentation/networking/netdevices.rst index ebb868f..6c2d894 100644 --- a/Documentation/networking/netdevices.rst +++ b/Documentation/networking/netdevices.rst
@@ -343,6 +343,29 @@ acquiring the instance lock themselves, while the ``netif_xxx`` functions assume that the driver has already acquired the instance lock. +Notifiers and netdev instance lock +================================== + +For device drivers that implement shaping or queue management APIs, +some of the notifiers (``enum netdev_cmd``) are running under the netdev +instance lock. + +For devices with locked ops, currently only the following notifiers are +running under the lock: +* ``NETDEV_REGISTER`` +* ``NETDEV_UP`` + +The following notifiers are running without the lock: +* ``NETDEV_UNREGISTER`` + +There are no clear expectations for the remaining notifiers. Notifiers not on +the list may run with or without the instance lock, potentially even invoking +the same notifier type with and without the lock from different code paths. +The goal is to eventually ensure that all (or most, with a few documented +exceptions) notifiers run under the instance lock. Please extend this +documentation whenever you make explicit assumption about lock being held +from a notifier. + NETDEV_INTERNAL symbol namespace ================================
diff --git a/Documentation/rust/arch-support.rst b/Documentation/rust/arch-support.rst index 54be7dd..6e6a515 100644 --- a/Documentation/rust/arch-support.rst +++ b/Documentation/rust/arch-support.rst
@@ -15,6 +15,7 @@ ============= ================ ============================================== Architecture Level of support Constraints ============= ================ ============================================== +``arm`` Maintained ARMv7 Little Endian only. ``arm64`` Maintained Little Endian only. ``loongarch`` Maintained \- ``riscv`` Maintained ``riscv64`` and LLVM/Clang only.
diff --git a/Documentation/trace/debugging.rst b/Documentation/trace/debugging.rst index 54fb162..d54bc50 100644 --- a/Documentation/trace/debugging.rst +++ b/Documentation/trace/debugging.rst
@@ -136,6 +136,8 @@ preserved. Switching to a different kernel version may find a different layout and mark the buffer as invalid. +NB: Both the mapped address and size must be page aligned for the architecture. + Using trace_printk() in the boot instance ----------------------------------------- By default, the content of trace_printk() goes into the top level tracing
diff --git a/Documentation/trace/ftrace.rst b/Documentation/trace/ftrace.rst index 2b74f96..c9e88bf 100644 --- a/Documentation/trace/ftrace.rst +++ b/Documentation/trace/ftrace.rst
@@ -3077,7 +3077,7 @@ # cat set_ftrace_filter hrtimer_run_queues hrtimer_run_pending - hrtimer_init + hrtimer_setup hrtimer_cancel hrtimer_try_to_cancel hrtimer_forward @@ -3115,7 +3115,7 @@ # cat set_ftrace_filter hrtimer_run_queues hrtimer_run_pending - hrtimer_init + hrtimer_setup hrtimer_cancel hrtimer_try_to_cancel hrtimer_forward
diff --git a/Documentation/usb/CREDITS b/Documentation/usb/CREDITS index 81ea3eb..ce6450a 100644 --- a/Documentation/usb/CREDITS +++ b/Documentation/usb/CREDITS
@@ -161,7 +161,7 @@ - The people at the linux-usb mailing list, for reading so many messages :) Ok, no more kidding; for all your advises! - - All the people at the USB Implementors Forum for their + - All the people at the USB Implementers Forum for their help and assistance. - Nathan Myers <ncm@cantrip.org>, for his advice! (hope you
diff --git a/Documentation/userspace-api/ioctl/ioctl-number.rst b/Documentation/userspace-api/ioctl/ioctl-number.rst index 3d1cd7a..7a1409ec 100644 --- a/Documentation/userspace-api/ioctl/ioctl-number.rst +++ b/Documentation/userspace-api/ioctl/ioctl-number.rst
@@ -376,9 +376,9 @@ 0xB8 all uapi/linux/mshv.h Microsoft Hyper-V /dev/mshv driver <mailto:linux-hyperv@vger.kernel.org> 0xC0 00-0F linux/usb/iowarrior.h -0xCA 00-0F uapi/misc/cxl.h +0xCA 00-0F uapi/misc/cxl.h Dead since 6.15 0xCA 10-2F uapi/misc/ocxl.h -0xCA 80-BF uapi/scsi/cxlflash_ioctl.h Dead since 6.14 +0xCA 80-BF uapi/scsi/cxlflash_ioctl.h Dead since 6.15 0xCB 00-1F CBM serial IEC bus in development: <mailto:michael.klein@puffin.lb.shuttle.de> 0xCC 00-0F drivers/misc/ibmvmc.h pseries VMC driver
diff --git a/Documentation/userspace-api/mseal.rst b/Documentation/userspace-api/mseal.rst index 41102f7..1dabfc2 100644 --- a/Documentation/userspace-api/mseal.rst +++ b/Documentation/userspace-api/mseal.rst
@@ -130,6 +130,27 @@ - Chrome browser: protect some security sensitive data structures. +- System mappings: + The system mappings are created by the kernel and includes vdso, vvar, + vvar_vclock, vectors (arm compat-mode), sigpage (arm compat-mode), uprobes. + + Those system mappings are readonly only or execute only, memory sealing can + protect them from ever changing to writable or unmmap/remapped as different + attributes. This is useful to mitigate memory corruption issues where a + corrupted pointer is passed to a memory management system. + + If supported by an architecture (CONFIG_ARCH_SUPPORTS_MSEAL_SYSTEM_MAPPINGS), + the CONFIG_MSEAL_SYSTEM_MAPPINGS seals all system mappings of this + architecture. + + The following architectures currently support this feature: x86-64, arm64, + and s390. + + WARNING: This feature breaks programs which rely on relocating + or unmapping system mappings. Known broken software at the time + of writing includes CHECKPOINT_RESTORE, UML, gVisor, rr. Therefore + this config can't be enabled universally. + When not to use mseal ===================== Applications can apply sealing to any virtual memory region from userspace,
diff --git a/MAINTAINERS b/MAINTAINERS index db55bd4..96b8270 100644 --- a/MAINTAINERS +++ b/MAINTAINERS
@@ -2268,6 +2268,7 @@ F: Documentation/devicetree/bindings/cpufreq/apple,cluster-cpufreq.yaml F: Documentation/devicetree/bindings/dma/apple,admac.yaml F: Documentation/devicetree/bindings/i2c/apple,i2c.yaml +F: Documentation/devicetree/bindings/input/touchscreen/apple,z2-multitouch.yaml F: Documentation/devicetree/bindings/interrupt-controller/apple,* F: Documentation/devicetree/bindings/iommu/apple,dart.yaml F: Documentation/devicetree/bindings/iommu/apple,sart.yaml @@ -2290,6 +2291,7 @@ F: drivers/pmdomain/apple/ F: drivers/i2c/busses/i2c-pasemi-core.c F: drivers/i2c/busses/i2c-pasemi-platform.c +F: drivers/input/touchscreen/apple_z2.c F: drivers/iommu/apple-dart.c F: drivers/iommu/io-pgtable-dart.c F: drivers/irqchip/irq-apple-aic.c @@ -5544,12 +5546,12 @@ F: sound/soc/codecs/cros_ec_codec.* CHROMEOS EC CHARGE CONTROL -M: Thomas Weißschuh <thomas@weissschuh.net> +M: Thomas Weißschuh <linux@weissschuh.net> S: Maintained F: drivers/power/supply/cros_charge-control.c CHROMEOS EC HARDWARE MONITORING -M: Thomas Weißschuh <thomas@weissschuh.net> +M: Thomas Weißschuh <linux@weissschuh.net> L: chrome-platform@lists.linux.dev L: linux-hwmon@vger.kernel.org S: Maintained @@ -5557,7 +5559,7 @@ F: drivers/hwmon/cros_ec_hwmon.c CHROMEOS EC LED DRIVER -M: Thomas Weißschuh <thomas@weissschuh.net> +M: Thomas Weißschuh <linux@weissschuh.net> S: Maintained F: drivers/leds/leds-cros_ec.c @@ -5967,9 +5969,10 @@ F: Documentation/security/snp-tdx-threat-model.rst CONFIGFS -M: Joel Becker <jlbec@evilplan.org> +M: Andreas Hindborg <a.hindborg@kernel.org> +R: Breno Leitao <leitao@debian.org> S: Supported -T: git git://git.infradead.org/users/hch/configfs.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/a.hindborg/linux.git configfs-next F: fs/configfs/ F: include/linux/configfs.h F: samples/configfs/ @@ -6435,18 +6438,6 @@ W: http://www.chelsio.com F: drivers/net/ethernet/chelsio/cxgb4vf/ -CXL (IBM Coherent Accelerator Processor Interface CAPI) DRIVER -M: Frederic Barrat <fbarrat@linux.ibm.com> -M: Andrew Donnellan <ajd@linux.ibm.com> -L: linuxppc-dev@lists.ozlabs.org -S: Obsolete -F: Documentation/ABI/obsolete/sysfs-class-cxl -F: Documentation/arch/powerpc/cxl.rst -F: arch/powerpc/platforms/powernv/pci-cxl.c -F: drivers/misc/cxl/ -F: include/misc/cxl* -F: include/uapi/misc/cxl.h - CYBERPRO FB DRIVER M: Russell King <linux@armlinux.org.uk> L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) @@ -9118,7 +9109,7 @@ FILESYSTEMS [NETFS LIBRARY] M: David Howells <dhowells@redhat.com> -R: Jeff Layton <jlayton@kernel.org> +M: Paulo Alcantara <pc@manguebit.com> L: netfs@lists.linux.dev L: linux-fsdevel@vger.kernel.org S: Supported @@ -10032,7 +10023,7 @@ F: drivers/hwmon/gigabyte_waterforce.c GIGABYTE WMI DRIVER -M: Thomas Weißschuh <thomas@weissschuh.net> +M: Thomas Weißschuh <linux@weissschuh.net> L: platform-driver-x86@vger.kernel.org S: Maintained F: drivers/platform/x86/gigabyte-wmi.c @@ -12859,6 +12850,7 @@ F: scripts/*vmlinux* F: scripts/Kbuild* F: scripts/Makefile* +F: scripts/bash-completion/ F: scripts/basic/ F: scripts/clang-tools/ F: scripts/dummy-tools/ @@ -15498,6 +15490,45 @@ F: tools/testing/selftests/mm/ N: include/linux/page[-_]* +MEMORY MANAGEMENT - EXECMEM +M: Andrew Morton <akpm@linux-foundation.org> +M: Mike Rapoport <rppt@kernel.org> +L: linux-mm@kvack.org +S: Maintained +F: include/linux/execmem.h +F: mm/execmem.c + +MEMORY MANAGEMENT - NUMA MEMBLOCKS AND NUMA EMULATION +M: Andrew Morton <akpm@linux-foundation.org> +M: Mike Rapoport <rppt@kernel.org> +L: linux-mm@kvack.org +S: Maintained +F: include/linux/numa_memblks.h +F: mm/numa.c +F: mm/numa_emulation.c +F: mm/numa_memblks.c + +MEMORY MANAGEMENT - SECRETMEM +M: Andrew Morton <akpm@linux-foundation.org> +M: Mike Rapoport <rppt@kernel.org> +L: linux-mm@kvack.org +S: Maintained +F: include/linux/secretmem.h +F: mm/secretmem.c + +MEMORY MANAGEMENT - USERFAULTFD +M: Andrew Morton <akpm@linux-foundation.org> +R: Peter Xu <peterx@redhat.com> +L: linux-mm@kvack.org +S: Maintained +F: Documentation/admin-guide/mm/userfaultfd.rst +F: fs/userfaultfd.c +F: include/asm-generic/pgtable_uffd.h +F: include/linux/userfaultfd_k.h +F: include/uapi/linux/userfaultfd.h +F: mm/userfaultfd.c +F: tools/testing/selftests/mm/uffd-*.[ch] + MEMORY MAPPING M: Andrew Morton <akpm@linux-foundation.org> M: Liam R. Howlett <Liam.Howlett@oracle.com> @@ -16561,6 +16592,12 @@ F: drivers/mtd/nand/ F: include/linux/mtd/*nand*.h +NATIONAL INSTRUMENTS SERIAL DRIVER +M: Chaitanya Vadrevu <chaitanya.vadrevu@emerson.com> +L: linux-serial@vger.kernel.org +S: Maintained +F: drivers/tty/serial/8250/8250_ni.c + NATIVE INSTRUMENTS USB SOUND INTERFACE DRIVER M: Daniel Mack <zonque@gmail.com> L: linux-sound@vger.kernel.org @@ -16806,6 +16843,13 @@ F: tools/testing/selftests/drivers/net/hw/ethtool_mm.sh K: ethtool_mm +NETWORKING [ETHTOOL PHY TOPOLOGY] +M: Maxime Chevallier <maxime.chevallier@bootlin.com> +F: Documentation/networking/phy-link-topology.rst +F: drivers/net/phy/phy_link_topology.c +F: include/linux/phy_link_topology.h +F: net/ethtool/phy.c + NETWORKING [GENERAL] M: "David S. Miller" <davem@davemloft.net> M: Eric Dumazet <edumazet@google.com> @@ -17203,7 +17247,6 @@ F: scripts/nsdeps NTB AMD DRIVER -M: Sanjay R Mehta <sanju.mehta@amd.com> M: Shyam Sundar S K <Shyam-sundar.S-k@amd.com> L: ntb@lists.linux.dev S: Supported @@ -18090,7 +18133,9 @@ F: drivers/irqchip/irq-or1k-* OPENVSWITCH -M: Pravin B Shelar <pshelar@ovn.org> +M: Aaron Conole <aconole@redhat.com> +M: Eelco Chaudron <echaudro@redhat.com> +M: Ilya Maximets <i.maximets@ovn.org> L: netdev@vger.kernel.org L: dev@openvswitch.org S: Maintained @@ -19682,12 +19727,12 @@ F: include/linux/qnx6_fs.h QORIQ DPAA2 FSL-MC BUS DRIVER -M: Stuart Yoder <stuyoder@gmail.com> -M: Laurentiu Tudor <laurentiu.tudor@nxp.com> +M: Ioana Ciornei <ioana.ciornei@nxp.com> +L: linuxppc-dev@lists.ozlabs.org L: linux-kernel@vger.kernel.org S: Maintained F: Documentation/ABI/stable/sysfs-bus-fsl-mc -F: Documentation/devicetree/bindings/misc/fsl,qoriq-mc.txt +F: Documentation/devicetree/bindings/misc/fsl,qoriq-mc.yaml F: Documentation/networking/device_drivers/ethernet/freescale/dpaa2/overview.rst F: drivers/bus/fsl-mc/ F: include/uapi/linux/fsl_mc.h @@ -19862,7 +19907,7 @@ F: drivers/i2c/busses/i2c-qcom-geni.c QUALCOMM I2C CCI DRIVER -M: Loic Poulain <loic.poulain@linaro.org> +M: Loic Poulain <loic.poulain@oss.qualcomm.com> M: Robert Foss <rfoss@kernel.org> L: linux-i2c@vger.kernel.org L: linux-arm-msm@vger.kernel.org @@ -19995,7 +20040,7 @@ F: drivers/media/platform/qcom/venus/ QUALCOMM WCN36XX WIRELESS DRIVER -M: Loic Poulain <loic.poulain@linaro.org> +M: Loic Poulain <loic.poulain@oss.qualcomm.com> L: wcn36xx@lists.infradead.org S: Supported W: https://wireless.wiki.kernel.org/en/users/Drivers/wcn36xx @@ -24021,7 +24066,7 @@ THUNDERBOLT DRIVER M: Andreas Noever <andreas.noever@gmail.com> M: Michael Jamet <michael.jamet@intel.com> -M: Mika Westerberg <mika.westerberg@linux.intel.com> +M: Mika Westerberg <westeri@kernel.org> M: Yehezkel Bernat <YehezkelShB@gmail.com> L: linux-usb@vger.kernel.org S: Maintained @@ -24032,7 +24077,7 @@ THUNDERBOLT NETWORK DRIVER M: Michael Jamet <michael.jamet@intel.com> -M: Mika Westerberg <mika.westerberg@linux.intel.com> +M: Mika Westerberg <westeri@kernel.org> M: Yehezkel Bernat <YehezkelShB@gmail.com> L: netdev@vger.kernel.org S: Maintained @@ -26034,7 +26079,7 @@ F: kernel/workqueue_internal.h WWAN DRIVERS -M: Loic Poulain <loic.poulain@linaro.org> +M: Loic Poulain <loic.poulain@oss.qualcomm.com> M: Sergey Ryazanov <ryazanov.s.a@gmail.com> R: Johannes Berg <johannes@sipsolutions.net> L: netdev@vger.kernel.org
diff --git a/Makefile b/Makefile index d138b17..f424185 100644 --- a/Makefile +++ b/Makefile
@@ -1,8 +1,8 @@ # SPDX-License-Identifier: GPL-2.0 VERSION = 6 -PATCHLEVEL = 14 +PATCHLEVEL = 15 SUBLEVEL = 0 -EXTRAVERSION = +EXTRAVERSION = -rc1 NAME = Baby Opossum Posse # *DOCUMENTATION* @@ -151,9 +151,6 @@ export KBUILD_EXTMOD -# backward compatibility -KBUILD_EXTRA_WARN ?= $(KBUILD_ENABLE_EXTRA_GCC_CHECKS) - ifeq ("$(origin W)", "command line") KBUILD_EXTRA_WARN := $(W) endif @@ -928,6 +925,9 @@ endif endif +# Explicitly clear padding bits during variable initialization +KBUILD_CFLAGS += $(call cc-option,-fzero-init-padding-bits=all) + # While VLAs have been removed, GCC produces unreachable stack probes # for the randomize_kstack_offset feature. Disable it for all compilers. KBUILD_CFLAGS += $(call cc-option, -fno-stack-clash-protection) @@ -1068,9 +1068,13 @@ KBUILD_CFLAGS += -fconserve-stack endif +# Ensure compilers do not transform certain loops into calls to wcslen() +KBUILD_CFLAGS += -fno-builtin-wcslen + # change __FILE__ to the relative path to the source directory ifdef building_out_of_srctree -KBUILD_CPPFLAGS += $(call cc-option,-fmacro-prefix-map=$(srcroot)/=) +KBUILD_CPPFLAGS += $(call cc-option,-ffile-prefix-map=$(srcroot)/=) +KBUILD_RUSTFLAGS += --remap-path-prefix=$(srcroot)/= endif # include additional Makefiles when needed @@ -1122,6 +1126,10 @@ LDFLAGS_vmlinux += --orphan-handling=$(CONFIG_LD_ORPHAN_WARN_LEVEL) endif +ifneq ($(CONFIG_ARCH_VMLINUX_NEEDS_RELOCS),) +LDFLAGS_vmlinux += --emit-relocs --discard-none +endif + # Align the bit size of userspace programs with the kernel KBUILD_USERCFLAGS += $(filter -m32 -m64 --target=%, $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS)) KBUILD_USERLDFLAGS += $(filter -m32 -m64 --target=%, $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS)) @@ -1364,9 +1372,12 @@ PHONY += headers headers: $(version_h) scripts_unifdef uapi-asm-generic archheaders archscripts - $(if $(filter um, $(SRCARCH)), $(error Headers not exportable for UML)) +ifdef HEADER_ARCH + $(Q)$(MAKE) -f $(srctree)/Makefile HEADER_ARCH= SRCARCH=$(HEADER_ARCH) headers +else $(Q)$(MAKE) $(hdr-inst)=include/uapi $(Q)$(MAKE) $(hdr-inst)=arch/$(SRCARCH)/include/uapi +endif ifdef CONFIG_HEADERS_INSTALL prepare: headers @@ -1564,7 +1575,7 @@ # Directories & files removed with 'make clean' CLEAN_FILES += vmlinux.symvers modules-only.symvers \ modules.builtin modules.builtin.modinfo modules.nsdeps \ - modules.builtin.ranges vmlinux.o.map \ + modules.builtin.ranges vmlinux.o.map vmlinux.unstripped \ compile_commands.json rust/test \ rust-project.json .vmlinux.objs .vmlinux.export.c \ .builtin-dtbs-list .builtin-dtb.S @@ -1667,7 +1678,8 @@ @echo ' kernelrelease - Output the release version string (use with make -s)' @echo ' kernelversion - Output the version stored in Makefile (use with make -s)' @echo ' image_name - Output the image name (use with make -s)' - @echo ' headers_install - Install sanitised kernel headers to INSTALL_HDR_PATH'; \ + @echo ' headers - Build ready-to-install UAPI headers in usr/include' + @echo ' headers_install - Install sanitised kernel UAPI headers to INSTALL_HDR_PATH'; \ echo ' (default: $(INSTALL_HDR_PATH))'; \ echo '' @echo 'Static analysers:'
diff --git a/arch/Kconfig b/arch/Kconfig index 9f6eb09..b0adb66 100644 --- a/arch/Kconfig +++ b/arch/Kconfig
@@ -1699,6 +1699,13 @@ Architectures that select this option can run floating-point code in the kernel, as described in Documentation/core-api/floating-point.rst. +config ARCH_VMLINUX_NEEDS_RELOCS + bool + help + Whether the architecture needs vmlinux to be built with static + relocations preserved. This is used by some architectures to + construct bespoke relocation tables for KASLR. + source "kernel/gcov/Kconfig" source "scripts/gcc-plugins/Kconfig"
diff --git a/arch/alpha/kernel/srmcons.c b/arch/alpha/kernel/srmcons.c index 3e61073..a89ce84 100644 --- a/arch/alpha/kernel/srmcons.c +++ b/arch/alpha/kernel/srmcons.c
@@ -177,7 +177,7 @@ srmcons_close(struct tty_struct *tty, struct file *filp) if (tty->count == 1) { port->tty = NULL; - del_timer(&srmconsp->timer); + timer_delete(&srmconsp->timer); } spin_unlock_irqrestore(&port->lock, flags); @@ -196,40 +196,44 @@ static const struct tty_operations srmcons_ops = { static int __init srmcons_init(void) { + struct tty_driver *driver; + int err; + timer_setup(&srmcons_singleton.timer, srmcons_receive_chars, 0); - if (srm_is_registered_console) { - struct tty_driver *driver; - int err; - driver = tty_alloc_driver(MAX_SRM_CONSOLE_DEVICES, 0); - if (IS_ERR(driver)) - return PTR_ERR(driver); + if (!srm_is_registered_console) + return -ENODEV; - tty_port_init(&srmcons_singleton.port); + driver = tty_alloc_driver(MAX_SRM_CONSOLE_DEVICES, 0); + if (IS_ERR(driver)) + return PTR_ERR(driver); - driver->driver_name = "srm"; - driver->name = "srm"; - driver->major = 0; /* dynamic */ - driver->minor_start = 0; - driver->type = TTY_DRIVER_TYPE_SYSTEM; - driver->subtype = SYSTEM_TYPE_SYSCONS; - driver->init_termios = tty_std_termios; - tty_set_operations(driver, &srmcons_ops); - tty_port_link_device(&srmcons_singleton.port, driver, 0); - err = tty_register_driver(driver); - if (err) { - tty_driver_kref_put(driver); - tty_port_destroy(&srmcons_singleton.port); - return err; - } - srmcons_driver = driver; - } + tty_port_init(&srmcons_singleton.port); - return -ENODEV; + driver->driver_name = "srm"; + driver->name = "srm"; + driver->major = 0; /* dynamic */ + driver->minor_start = 0; + driver->type = TTY_DRIVER_TYPE_SYSTEM; + driver->subtype = SYSTEM_TYPE_SYSCONS; + driver->init_termios = tty_std_termios; + tty_set_operations(driver, &srmcons_ops); + tty_port_link_device(&srmcons_singleton.port, driver, 0); + err = tty_register_driver(driver); + if (err) + goto err_free_drv; + + srmcons_driver = driver; + + return 0; +err_free_drv: + tty_driver_kref_put(driver); + tty_port_destroy(&srmcons_singleton.port); + + return err; } device_initcall(srmcons_init); - /* * The console driver */
diff --git a/arch/arc/kernel/intc-arcv2.c b/arch/arc/kernel/intc-arcv2.c index f324f0e..fea29d9 100644 --- a/arch/arc/kernel/intc-arcv2.c +++ b/arch/arc/kernel/intc-arcv2.c
@@ -178,7 +178,7 @@ init_onchip_IRQ(struct device_node *intc, struct device_node *parent) * Needed for primary domain lookup to succeed * This is a primary irqchip, and can never have a parent */ - irq_set_default_host(root_domain); + irq_set_default_domain(root_domain); #ifdef CONFIG_SMP irq_create_mapping(root_domain, IPI_IRQ);
diff --git a/arch/arc/kernel/intc-compact.c b/arch/arc/kernel/intc-compact.c index 6885e42..1d2ff1c 100644 --- a/arch/arc/kernel/intc-compact.c +++ b/arch/arc/kernel/intc-compact.c
@@ -121,7 +121,7 @@ init_onchip_IRQ(struct device_node *intc, struct device_node *parent) * Needed for primary domain lookup to succeed * This is a primary irqchip, and can never have a parent */ - irq_set_default_host(root_domain); + irq_set_default_domain(root_domain); return 0; }
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 835b5f1..25ed6f1 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig
@@ -121,7 +121,7 @@ select HAVE_KERNEL_XZ select HAVE_KPROBES if !XIP_KERNEL && !CPU_ENDIAN_BE32 && !CPU_V7M select HAVE_KRETPROBES if HAVE_KPROBES - select HAVE_LD_DEAD_CODE_DATA_ELIMINATION if (LD_VERSION >= 23600 || LD_IS_LLD) + select HAVE_LD_DEAD_CODE_DATA_ELIMINATION if (LD_VERSION >= 23600 || LD_CAN_USE_KEEP_IN_OVERLAY) select HAVE_MOD_ARCH_SPECIFIC select HAVE_NMI select HAVE_OPTPROBES if !THUMB2_KERNEL @@ -133,6 +133,7 @@ select MMU_GATHER_RCU_TABLE_FREE if SMP && ARM_LPAE select HAVE_REGS_AND_STACK_ACCESS_API select HAVE_RSEQ + select HAVE_RUST if CPU_LITTLE_ENDIAN && CPU_32v7 select HAVE_STACKPROTECTOR select HAVE_SYSCALL_TRACEPOINTS select HAVE_UID16
diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 00ca788..4808d3e 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile
@@ -150,6 +150,7 @@ KBUILD_CPPFLAGS +=$(cpp-y) KBUILD_CFLAGS +=$(CFLAGS_ABI) $(CFLAGS_ISA) $(arch-y) $(tune-y) $(call cc-option,-mshort-load-bytes,$(call cc-option,-malignment-traps,)) -msoft-float -Uarm KBUILD_AFLAGS +=$(CFLAGS_ABI) $(AFLAGS_ISA) -Wa,$(arch-y) $(tune-y) -include asm/unified.h -msoft-float +KBUILD_RUSTFLAGS += --target=arm-unknown-linux-gnueabi CHECKFLAGS += -D__arm__
diff --git a/arch/arm/configs/at91_dt_defconfig b/arch/arm/configs/at91_dt_defconfig index f2596a1..ff13e1e 100644 --- a/arch/arm/configs/at91_dt_defconfig +++ b/arch/arm/configs/at91_dt_defconfig
@@ -232,7 +232,6 @@ CONFIG_CRYPTO_DEV_ATMEL_AES=y CONFIG_CRYPTO_DEV_ATMEL_TDES=y CONFIG_CRYPTO_DEV_ATMEL_SHA=y -CONFIG_CRC_CCITT=y CONFIG_FONTS=y CONFIG_FONT_8x8=y CONFIG_FONT_ACORN_8x8=y
diff --git a/arch/arm/configs/collie_defconfig b/arch/arm/configs/collie_defconfig index 42cb1c8..578c6a4 100644 --- a/arch/arm/configs/collie_defconfig +++ b/arch/arm/configs/collie_defconfig
@@ -78,7 +78,6 @@ CONFIG_NLS_DEFAULT="cp437" CONFIG_NLS_CODEPAGE_437=y CONFIG_NLS_ISO8859_1=y -CONFIG_CRC_CCITT=y CONFIG_FONTS=y CONFIG_FONT_MINI_4x6=y # CONFIG_DEBUG_BUGVERBOSE is not set
diff --git a/arch/arm/configs/davinci_all_defconfig b/arch/arm/configs/davinci_all_defconfig index 3474e47..70b8c78 100644 --- a/arch/arm/configs/davinci_all_defconfig +++ b/arch/arm/configs/davinci_all_defconfig
@@ -249,7 +249,6 @@ CONFIG_NLS_ISO8859_1=y CONFIG_NLS_UTF8=m # CONFIG_CRYPTO_HW is not set -CONFIG_CRC_T10DIF=m CONFIG_DMA_CMA=y CONFIG_DEBUG_FS=y CONFIG_DEBUG_RT_MUTEXES=y
diff --git a/arch/arm/configs/dove_defconfig b/arch/arm/configs/dove_defconfig index b382a2e..d76eb12 100644 --- a/arch/arm/configs/dove_defconfig +++ b/arch/arm/configs/dove_defconfig
@@ -128,7 +128,6 @@ CONFIG_CRYPTO_LZO=y # CONFIG_CRYPTO_ANSI_CPRNG is not set CONFIG_CRYPTO_DEV_MARVELL_CESA=y -CONFIG_CRC_CCITT=y CONFIG_PRINTK_TIME=y # CONFIG_DEBUG_BUGVERBOSE is not set CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
diff --git a/arch/arm/configs/exynos_defconfig b/arch/arm/configs/exynos_defconfig index 7ad48fd..e81a5d6 100644 --- a/arch/arm/configs/exynos_defconfig +++ b/arch/arm/configs/exynos_defconfig
@@ -370,7 +370,6 @@ CONFIG_CRYPTO_CHACHA20_NEON=m CONFIG_CRYPTO_DEV_EXYNOS_RNG=y CONFIG_CRYPTO_DEV_S5P=y -CONFIG_CRC_CCITT=y CONFIG_DMA_CMA=y CONFIG_CMA_SIZE_MBYTES=96 CONFIG_FONTS=y
diff --git a/arch/arm/configs/imx_v6_v7_defconfig b/arch/arm/configs/imx_v6_v7_defconfig index 297c6a7b..062c1eb 100644 --- a/arch/arm/configs/imx_v6_v7_defconfig +++ b/arch/arm/configs/imx_v6_v7_defconfig
@@ -481,8 +481,6 @@ CONFIG_CRYPTO_DEV_FSL_CAAM=y CONFIG_CRYPTO_DEV_SAHARA=y CONFIG_CRYPTO_DEV_MXS_DCP=y -CONFIG_CRC_CCITT=m -CONFIG_CRC_T10DIF=y CONFIG_CMA_SIZE_MBYTES=64 CONFIG_FONTS=y CONFIG_FONT_8x8=y
diff --git a/arch/arm/configs/lpc18xx_defconfig b/arch/arm/configs/lpc18xx_defconfig index 2aa2ac8..2d48918 100644 --- a/arch/arm/configs/lpc18xx_defconfig +++ b/arch/arm/configs/lpc18xx_defconfig
@@ -147,7 +147,6 @@ # CONFIG_INOTIFY_USER is not set CONFIG_JFFS2_FS=y # CONFIG_NETWORK_FILESYSTEMS is not set -CONFIG_CRC_ITU_T=y CONFIG_PRINTK_TIME=y # CONFIG_ENABLE_MUST_CHECK is not set # CONFIG_DEBUG_BUGVERBOSE is not set
diff --git a/arch/arm/configs/lpc32xx_defconfig b/arch/arm/configs/lpc32xx_defconfig index 98e2672..9afccd7 100644 --- a/arch/arm/configs/lpc32xx_defconfig +++ b/arch/arm/configs/lpc32xx_defconfig
@@ -179,7 +179,6 @@ CONFIG_NLS_UTF8=y CONFIG_CRYPTO_ANSI_CPRNG=y # CONFIG_CRYPTO_HW is not set -CONFIG_CRC_CCITT=y CONFIG_PRINTK_TIME=y CONFIG_DYNAMIC_DEBUG=y CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
diff --git a/arch/arm/configs/milbeaut_m10v_defconfig b/arch/arm/configs/milbeaut_m10v_defconfig index acd1620..275ddf7 100644 --- a/arch/arm/configs/milbeaut_m10v_defconfig +++ b/arch/arm/configs/milbeaut_m10v_defconfig
@@ -108,8 +108,6 @@ CONFIG_CRYPTO_AES_ARM_CE=m CONFIG_CRYPTO_CHACHA20_NEON=m # CONFIG_CRYPTO_HW is not set -CONFIG_CRC_CCITT=m -CONFIG_CRC_ITU_T=m CONFIG_DMA_CMA=y CONFIG_CMA_SIZE_MBYTES=64 CONFIG_PRINTK_TIME=y
diff --git a/arch/arm/configs/mmp2_defconfig b/arch/arm/configs/mmp2_defconfig index f6f9e13..842a989 100644 --- a/arch/arm/configs/mmp2_defconfig +++ b/arch/arm/configs/mmp2_defconfig
@@ -67,7 +67,6 @@ CONFIG_NFS_V3_ACL=y CONFIG_NFS_V4=y CONFIG_ROOT_NFS=y -CONFIG_CRC_CCITT=y CONFIG_PRINTK_TIME=y CONFIG_DEBUG_KERNEL=y CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
diff --git a/arch/arm/configs/multi_v4t_defconfig b/arch/arm/configs/multi_v4t_defconfig index 27d6506..1a86dc3 100644 --- a/arch/arm/configs/multi_v4t_defconfig +++ b/arch/arm/configs/multi_v4t_defconfig
@@ -91,6 +91,5 @@ CONFIG_VFAT_FS=y CONFIG_CRAMFS=y CONFIG_MINIX_FS=y -CONFIG_CRC_CCITT=y # CONFIG_FTRACE is not set CONFIG_DEBUG_USER=y
diff --git a/arch/arm/configs/multi_v5_defconfig b/arch/arm/configs/multi_v5_defconfig index db81862..cf6180b 100644 --- a/arch/arm/configs/multi_v5_defconfig +++ b/arch/arm/configs/multi_v5_defconfig
@@ -289,7 +289,6 @@ CONFIG_CRYPTO_CBC=m CONFIG_CRYPTO_PCBC=m CONFIG_CRYPTO_DEV_MARVELL_CESA=y -CONFIG_CRC_CCITT=y CONFIG_DEBUG_KERNEL=y CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y CONFIG_MAGIC_SYSRQ=y
diff --git a/arch/arm/configs/mvebu_v5_defconfig b/arch/arm/configs/mvebu_v5_defconfig index a518d4a..23dbb80 100644 --- a/arch/arm/configs/mvebu_v5_defconfig +++ b/arch/arm/configs/mvebu_v5_defconfig
@@ -187,7 +187,6 @@ CONFIG_CRYPTO_CBC=m CONFIG_CRYPTO_PCBC=m CONFIG_CRYPTO_DEV_MARVELL_CESA=y -CONFIG_CRC_CCITT=y CONFIG_DEBUG_KERNEL=y CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y CONFIG_MAGIC_SYSRQ=y
diff --git a/arch/arm/configs/mxs_defconfig b/arch/arm/configs/mxs_defconfig index d8a6e43..c76d661 100644 --- a/arch/arm/configs/mxs_defconfig +++ b/arch/arm/configs/mxs_defconfig
@@ -160,7 +160,6 @@ CONFIG_NLS_ISO8859_1=y CONFIG_NLS_ISO8859_15=y CONFIG_CRYPTO_DEV_MXS_DCP=y -CONFIG_CRC_ITU_T=m CONFIG_FONTS=y CONFIG_PRINTK_TIME=y CONFIG_DEBUG_KERNEL=y
diff --git a/arch/arm/configs/omap2plus_defconfig b/arch/arm/configs/omap2plus_defconfig index 113d6df..75b326b 100644 --- a/arch/arm/configs/omap2plus_defconfig +++ b/arch/arm/configs/omap2plus_defconfig
@@ -706,9 +706,6 @@ CONFIG_CRYPTO_DEV_OMAP_SHAM=m CONFIG_CRYPTO_DEV_OMAP_AES=m CONFIG_CRYPTO_DEV_OMAP_DES=m -CONFIG_CRC_CCITT=y -CONFIG_CRC_T10DIF=y -CONFIG_CRC_ITU_T=y CONFIG_DMA_CMA=y CONFIG_FONTS=y CONFIG_FONT_8x8=y
diff --git a/arch/arm/configs/orion5x_defconfig b/arch/arm/configs/orion5x_defconfig index 0629b08..62b9c61 100644 --- a/arch/arm/configs/orion5x_defconfig +++ b/arch/arm/configs/orion5x_defconfig
@@ -136,7 +136,6 @@ CONFIG_CRYPTO_ECB=m CONFIG_CRYPTO_PCBC=m CONFIG_CRYPTO_DEV_MARVELL_CESA=y -CONFIG_CRC_T10DIF=y # CONFIG_DEBUG_BUGVERBOSE is not set CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y CONFIG_MAGIC_SYSRQ=y
diff --git a/arch/arm/configs/pxa168_defconfig b/arch/arm/configs/pxa168_defconfig index ce10fe2..4748c7d 100644 --- a/arch/arm/configs/pxa168_defconfig +++ b/arch/arm/configs/pxa168_defconfig
@@ -41,7 +41,6 @@ CONFIG_NFS_V3_ACL=y CONFIG_NFS_V4=y CONFIG_ROOT_NFS=y -CONFIG_CRC_CCITT=y CONFIG_PRINTK_TIME=y CONFIG_DEBUG_KERNEL=y CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
diff --git a/arch/arm/configs/pxa910_defconfig b/arch/arm/configs/pxa910_defconfig index 1f28aea..49b59c6 100644 --- a/arch/arm/configs/pxa910_defconfig +++ b/arch/arm/configs/pxa910_defconfig
@@ -50,7 +50,6 @@ CONFIG_NFS_V3_ACL=y CONFIG_NFS_V4=y CONFIG_ROOT_NFS=y -CONFIG_CRC_CCITT=y CONFIG_PRINTK_TIME=y CONFIG_DEBUG_KERNEL=y CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
diff --git a/arch/arm/configs/pxa_defconfig b/arch/arm/configs/pxa_defconfig index de0ac8f..24fca86 100644 --- a/arch/arm/configs/pxa_defconfig +++ b/arch/arm/configs/pxa_defconfig
@@ -663,8 +663,6 @@ CONFIG_CRYPTO_SHA256_ARM=m CONFIG_CRYPTO_SHA512_ARM=m CONFIG_CRYPTO_AES_ARM=m -CONFIG_CRC_CCITT=y -CONFIG_CRC_T10DIF=m CONFIG_FONTS=y CONFIG_FONT_8x8=y CONFIG_FONT_8x16=y
diff --git a/arch/arm/configs/s5pv210_defconfig b/arch/arm/configs/s5pv210_defconfig index 5dbe85c..02121ee 100644 --- a/arch/arm/configs/s5pv210_defconfig +++ b/arch/arm/configs/s5pv210_defconfig
@@ -113,7 +113,6 @@ CONFIG_NLS_ASCII=y CONFIG_NLS_ISO8859_1=y CONFIG_NLS_UTF8=y -CONFIG_CRC_CCITT=y CONFIG_DEBUG_KERNEL=y CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y CONFIG_MAGIC_SYSRQ=y
diff --git a/arch/arm/configs/sama7_defconfig b/arch/arm/configs/sama7_defconfig index ea7ddf6..e14720a 100644 --- a/arch/arm/configs/sama7_defconfig +++ b/arch/arm/configs/sama7_defconfig
@@ -227,8 +227,6 @@ CONFIG_CRYPTO_DEV_ATMEL_AES=y CONFIG_CRYPTO_DEV_ATMEL_TDES=y CONFIG_CRYPTO_DEV_ATMEL_SHA=y -CONFIG_CRC_CCITT=y -CONFIG_CRC_ITU_T=y CONFIG_DMA_CMA=y CONFIG_CMA_SIZE_MBYTES=32 CONFIG_CMA_ALIGNMENT=9
diff --git a/arch/arm/configs/spitz_defconfig b/arch/arm/configs/spitz_defconfig index ac5b7a5..ffec59e 100644 --- a/arch/arm/configs/spitz_defconfig +++ b/arch/arm/configs/spitz_defconfig
@@ -234,7 +234,6 @@ CONFIG_CRYPTO_MICHAEL_MIC=m CONFIG_CRYPTO_SHA512=m CONFIG_CRYPTO_WP512=m -CONFIG_CRC_CCITT=y CONFIG_FONTS=y CONFIG_FONT_8x8=y CONFIG_FONT_8x16=y
diff --git a/arch/arm/configs/stm32_defconfig b/arch/arm/configs/stm32_defconfig index 423bb41..dcd9c316 100644 --- a/arch/arm/configs/stm32_defconfig +++ b/arch/arm/configs/stm32_defconfig
@@ -74,7 +74,6 @@ # CONFIG_DNOTIFY is not set # CONFIG_INOTIFY_USER is not set CONFIG_NLS=y -CONFIG_CRC_ITU_T=y CONFIG_PRINTK_TIME=y # CONFIG_DEBUG_BUGVERBOSE is not set CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
diff --git a/arch/arm/configs/wpcm450_defconfig b/arch/arm/configs/wpcm450_defconfig index 5e4397f..cd4b3e7 100644 --- a/arch/arm/configs/wpcm450_defconfig +++ b/arch/arm/configs/wpcm450_defconfig
@@ -191,8 +191,6 @@ CONFIG_X509_CERTIFICATE_PARSER=y CONFIG_PKCS7_MESSAGE_PARSER=y CONFIG_SYSTEM_TRUSTED_KEYRING=y -CONFIG_CRC_CCITT=y -CONFIG_CRC_ITU_T=m CONFIG_PRINTK_TIME=y CONFIG_DEBUG_KERNEL=y CONFIG_MAGIC_SYSRQ=y
diff --git a/arch/arm/include/asm/vmlinux.lds.h b/arch/arm/include/asm/vmlinux.lds.h index d60f6e8..0341973 100644 --- a/arch/arm/include/asm/vmlinux.lds.h +++ b/arch/arm/include/asm/vmlinux.lds.h
@@ -19,7 +19,7 @@ #endif #ifdef CONFIG_MMU -#define ARM_MMU_KEEP(x) x +#define ARM_MMU_KEEP(x) KEEP(x) #define ARM_MMU_DISCARD(x) #else #define ARM_MMU_KEEP(x) @@ -34,6 +34,12 @@ #define NOCROSSREFS #endif +#ifdef CONFIG_LD_CAN_USE_KEEP_IN_OVERLAY +#define OVERLAY_KEEP(x) KEEP(x) +#else +#define OVERLAY_KEEP(x) x +#endif + /* Set start/end symbol names to the LMA for the section */ #define ARM_LMA(sym, section) \ sym##_start = LOADADDR(section); \ @@ -125,13 +131,13 @@ __vectors_lma = .; \ OVERLAY 0xffff0000 : NOCROSSREFS AT(__vectors_lma) { \ .vectors { \ - *(.vectors) \ + OVERLAY_KEEP(*(.vectors)) \ } \ .vectors.bhb.loop8 { \ - *(.vectors.bhb.loop8) \ + OVERLAY_KEEP(*(.vectors.bhb.loop8)) \ } \ .vectors.bhb.bpiall { \ - *(.vectors.bhb.bpiall) \ + OVERLAY_KEEP(*(.vectors.bhb.bpiall)) \ } \ } \ ARM_LMA(__vectors, .vectors); \
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index 3431c05..5099988 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c
@@ -551,7 +551,8 @@ void show_ipi_list(struct seq_file *p, int prec) if (!ipi_desc[i]) continue; - seq_printf(p, "%*s%u: ", prec - 1, "IPI", i); + seq_printf(p, "%*s%u:%s", prec - 1, "IPI", i, + prec >= 4 ? " " : ""); for_each_online_cpu(cpu) seq_printf(p, "%10u ", irq_desc_kstat_cpu(ipi_desc[i], cpu));
diff --git a/arch/arm/kernel/vmlinux-xip.lds.S b/arch/arm/kernel/vmlinux-xip.lds.S index 5eddb75..f2e8d4f 100644 --- a/arch/arm/kernel/vmlinux-xip.lds.S +++ b/arch/arm/kernel/vmlinux-xip.lds.S
@@ -63,7 +63,7 @@ . = ALIGN(4); __ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET) { __start___ex_table = .; - ARM_MMU_KEEP(KEEP(*(__ex_table))) + ARM_MMU_KEEP(*(__ex_table)) __stop___ex_table = .; }
diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S index de373c6..d592a20 100644 --- a/arch/arm/kernel/vmlinux.lds.S +++ b/arch/arm/kernel/vmlinux.lds.S
@@ -74,7 +74,7 @@ . = ALIGN(4); __ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET) { __start___ex_table = .; - ARM_MMU_KEEP(KEEP(*(__ex_table))) + ARM_MMU_KEEP(*(__ex_table)) __stop___ex_table = .; }
diff --git a/arch/arm/mach-footbridge/dc21285.c b/arch/arm/mach-footbridge/dc21285.c index f8920d0..6521ab3 100644 --- a/arch/arm/mach-footbridge/dc21285.c +++ b/arch/arm/mach-footbridge/dc21285.c
@@ -135,7 +135,7 @@ static struct timer_list perr_timer; static void dc21285_enable_error(struct timer_list *timer) { - del_timer(timer); + timer_delete(timer); if (timer == &serr_timer) enable_irq(IRQ_PCI_SERR);
diff --git a/arch/arm/mach-pxa/irq.c b/arch/arm/mach-pxa/irq.c index a9ef710..d9cadd9 100644 --- a/arch/arm/mach-pxa/irq.c +++ b/arch/arm/mach-pxa/irq.c
@@ -152,7 +152,7 @@ pxa_init_irq_common(struct device_node *node, int irq_nr, &pxa_irq_ops, NULL); if (!pxa_irq_domain) panic("Unable to add PXA IRQ domain\n"); - irq_set_default_host(pxa_irq_domain); + irq_set_default_domain(pxa_irq_domain); for (n = 0; n < irq_nr; n += 32) { void __iomem *base = irq_base(n >> 5);
diff --git a/arch/arm/mach-pxa/sharpsl_pm.c b/arch/arm/mach-pxa/sharpsl_pm.c index dd930e3..71b282b 100644 --- a/arch/arm/mach-pxa/sharpsl_pm.c +++ b/arch/arm/mach-pxa/sharpsl_pm.c
@@ -913,8 +913,8 @@ static void sharpsl_pm_remove(struct platform_device *pdev) if (sharpsl_pm.machinfo->exit) sharpsl_pm.machinfo->exit(); - del_timer_sync(&sharpsl_pm.chrg_full_timer); - del_timer_sync(&sharpsl_pm.ac_timer); + timer_delete_sync(&sharpsl_pm.chrg_full_timer); + timer_delete_sync(&sharpsl_pm.ac_timer); } static struct platform_driver sharpsl_pm_driver = {
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 748c34d..a182295 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig
@@ -38,6 +38,7 @@ select ARCH_HAS_KEEPINITRD select ARCH_HAS_MEMBARRIER_SYNC_CORE select ARCH_HAS_MEM_ENCRYPT + select ARCH_SUPPORTS_MSEAL_SYSTEM_MAPPINGS select ARCH_HAS_NMI_SAFE_THIS_CPU_OPS select ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE select ARCH_HAS_NONLEAF_PMD_YOUNG if ARM64_HAFT
diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile index 2b25d67..1d5dfcd 100644 --- a/arch/arm64/Makefile +++ b/arch/arm64/Makefile
@@ -48,7 +48,7 @@ KBUILD_CFLAGS += $(call cc-disable-warning, psabi) KBUILD_AFLAGS += $(compat_vdso) -ifeq ($(call test-ge, $(CONFIG_RUSTC_VERSION), 108500),y) +ifeq ($(call rustc-min-version, 108500),y) KBUILD_RUSTFLAGS += --target=aarch64-unknown-none-softfloat else KBUILD_RUSTFLAGS += --target=aarch64-unknown-none -Ctarget-feature="-neon"
diff --git a/arch/arm64/include/asm/cputype.h b/arch/arm64/include/asm/cputype.h index c607e0b..d1cc057 100644 --- a/arch/arm64/include/asm/cputype.h +++ b/arch/arm64/include/asm/cputype.h
@@ -132,6 +132,7 @@ #define FUJITSU_CPU_PART_A64FX 0x001 #define HISI_CPU_PART_TSV110 0xD01 +#define HISI_CPU_PART_HIP09 0xD02 #define APPLE_CPU_PART_M1_ICESTORM 0x022 #define APPLE_CPU_PART_M1_FIRESTORM 0x023 @@ -218,6 +219,7 @@ #define MIDR_NVIDIA_CARMEL MIDR_CPU_MODEL(ARM_CPU_IMP_NVIDIA, NVIDIA_CPU_PART_CARMEL) #define MIDR_FUJITSU_A64FX MIDR_CPU_MODEL(ARM_CPU_IMP_FUJITSU, FUJITSU_CPU_PART_A64FX) #define MIDR_HISI_TSV110 MIDR_CPU_MODEL(ARM_CPU_IMP_HISI, HISI_CPU_PART_TSV110) +#define MIDR_HISI_HIP09 MIDR_CPU_MODEL(ARM_CPU_IMP_HISI, HISI_CPU_PART_HIP09) #define MIDR_APPLE_M1_ICESTORM MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_ICESTORM) #define MIDR_APPLE_M1_FIRESTORM MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_FIRESTORM) #define MIDR_APPLE_M1_ICESTORM_PRO MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_ICESTORM_PRO)
diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h index 84f05f78..d3b538b 100644 --- a/arch/arm64/include/asm/pgtable.h +++ b/arch/arm64/include/asm/pgtable.h
@@ -633,11 +633,6 @@ static inline pud_t pud_mkhuge(pud_t pud) #define pud_pfn(pud) ((__pud_to_phys(pud) & PUD_MASK) >> PAGE_SHIFT) #define pfn_pud(pfn,prot) __pud(__phys_to_pud_val((phys_addr_t)(pfn) << PAGE_SHIFT) | pgprot_val(prot)) -#ifdef CONFIG_ARCH_SUPPORTS_PUD_PFNMAP -#define pud_special(pte) pte_special(pud_pte(pud)) -#define pud_mkspecial(pte) pte_pud(pte_mkspecial(pud_pte(pud))) -#endif - #define pmd_pgprot pmd_pgprot static inline pgprot_t pmd_pgprot(pmd_t pmd) {
diff --git a/arch/arm64/include/asm/traps.h b/arch/arm64/include/asm/traps.h index d780d1b..82cf1f8 100644 --- a/arch/arm64/include/asm/traps.h +++ b/arch/arm64/include/asm/traps.h
@@ -109,10 +109,9 @@ static inline void arm64_mops_reset_regs(struct user_pt_regs *regs, unsigned lon int dstreg = ESR_ELx_MOPS_ISS_DESTREG(esr); int srcreg = ESR_ELx_MOPS_ISS_SRCREG(esr); int sizereg = ESR_ELx_MOPS_ISS_SIZEREG(esr); - unsigned long dst, src, size; + unsigned long dst, size; dst = regs->regs[dstreg]; - src = regs->regs[srcreg]; size = regs->regs[sizereg]; /* @@ -129,6 +128,7 @@ static inline void arm64_mops_reset_regs(struct user_pt_regs *regs, unsigned lon } } else { /* CPY* instruction */ + unsigned long src = regs->regs[srcreg]; if (!(option_a ^ wrong_option)) { /* Format is from Option B */ if (regs->pstate & PSR_N_BIT) {
diff --git a/arch/arm64/kernel/compat_alignment.c b/arch/arm64/kernel/compat_alignment.c index deff21b..b68e1d3 100644 --- a/arch/arm64/kernel/compat_alignment.c +++ b/arch/arm64/kernel/compat_alignment.c
@@ -368,6 +368,8 @@ int do_compat_alignment_fixup(unsigned long addr, struct pt_regs *regs) return 1; } + if (!handler) + return 1; type = handler(addr, instr, regs); if (type == TYPE_ERROR || type == TYPE_FAULT)
diff --git a/arch/arm64/kernel/proton-pack.c b/arch/arm64/kernel/proton-pack.c index d5d11fd..b198dde 100644 --- a/arch/arm64/kernel/proton-pack.c +++ b/arch/arm64/kernel/proton-pack.c
@@ -901,6 +901,7 @@ static u8 spectre_bhb_loop_affected(void) MIDR_ALL_VERSIONS(MIDR_CORTEX_A77), MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N1), MIDR_ALL_VERSIONS(MIDR_QCOM_KRYO_4XX_GOLD), + MIDR_ALL_VERSIONS(MIDR_HISI_HIP09), {}, }; static const struct midr_range spectre_bhb_k11_list[] = {
diff --git a/arch/arm64/kernel/vdso.c b/arch/arm64/kernel/vdso.c index 887ac0b..78ddf6b 100644 --- a/arch/arm64/kernel/vdso.c +++ b/arch/arm64/kernel/vdso.c
@@ -130,7 +130,8 @@ static int __setup_additional_pages(enum vdso_abi abi, mm->context.vdso = (void *)vdso_base; ret = _install_special_mapping(mm, vdso_base, vdso_text_len, VM_READ|VM_EXEC|gp_flags| - VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC, + VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC| + VM_SEALED_SYSMAP, vdso_info[abi].cm); if (IS_ERR(ret)) goto up_fail; @@ -256,7 +257,8 @@ static int aarch32_kuser_helpers_setup(struct mm_struct *mm) */ ret = _install_special_mapping(mm, AARCH32_VECTORS_BASE, PAGE_SIZE, VM_READ | VM_EXEC | - VM_MAYREAD | VM_MAYEXEC, + VM_MAYREAD | VM_MAYEXEC | + VM_SEALED_SYSMAP, &aarch32_vdso_maps[AA32_MAP_VECTORS]); return PTR_ERR_OR_ZERO(ret); @@ -279,7 +281,8 @@ static int aarch32_sigreturn_setup(struct mm_struct *mm) */ ret = _install_special_mapping(mm, addr, PAGE_SIZE, VM_READ | VM_EXEC | VM_MAYREAD | - VM_MAYWRITE | VM_MAYEXEC, + VM_MAYWRITE | VM_MAYEXEC | + VM_SEALED_SYSMAP, &aarch32_vdso_maps[AA32_MAP_SIGPAGE]); if (IS_ERR(ret)) goto out;
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c index b98f894..ea6695d 100644 --- a/arch/arm64/mm/mmu.c +++ b/arch/arm64/mm/mmu.c
@@ -1361,7 +1361,8 @@ int arch_add_memory(int nid, u64 start, u64 size, __remove_pgd_mapping(swapper_pg_dir, __phys_to_virt(start), size); else { - max_pfn = PFN_UP(start + size); + /* Address of hotplugged memory can be smaller */ + max_pfn = max(max_pfn, PFN_UP(start + size)); max_low_pfn = max_pfn; }
diff --git a/arch/csky/include/asm/pgalloc.h b/arch/csky/include/asm/pgalloc.h index bf8400c..11055c5 100644 --- a/arch/csky/include/asm/pgalloc.h +++ b/arch/csky/include/asm/pgalloc.h
@@ -61,11 +61,8 @@ static inline pgd_t *pgd_alloc(struct mm_struct *mm) return ret; } -#define __pte_free_tlb(tlb, pte, address) \ -do { \ - pagetable_dtor(page_ptdesc(pte)); \ - tlb_remove_page_ptdesc(tlb, page_ptdesc(pte)); \ -} while (0) +#define __pte_free_tlb(tlb, pte, address) \ + tlb_remove_ptdesc((tlb), page_ptdesc(pte)) extern void pagetable_init(void); extern void mmu_init(unsigned long min_pfn, unsigned long max_pfn);
diff --git a/arch/hexagon/configs/comet_defconfig b/arch/hexagon/configs/comet_defconfig index 469c025..c6108f0 100644 --- a/arch/hexagon/configs/comet_defconfig +++ b/arch/hexagon/configs/comet_defconfig
@@ -72,9 +72,6 @@ CONFIG_CRYPTO_MD5=y # CONFIG_CRYPTO_ANSI_CPRNG is not set # CONFIG_CRYPTO_HW is not set -CONFIG_CRC_CCITT=y -CONFIG_CRC16=y -CONFIG_CRC_T10DIF=y CONFIG_FRAME_WARN=0 CONFIG_MAGIC_SYSRQ=y CONFIG_DEBUG_FS=y
diff --git a/arch/hexagon/include/asm/pgalloc.h b/arch/hexagon/include/asm/pgalloc.h index 1ee5f5f..937a11e 100644 --- a/arch/hexagon/include/asm/pgalloc.h +++ b/arch/hexagon/include/asm/pgalloc.h
@@ -87,10 +87,7 @@ static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd, max_kernel_seg = pmdindex; } -#define __pte_free_tlb(tlb, pte, addr) \ -do { \ - pagetable_dtor((page_ptdesc(pte))); \ - tlb_remove_page_ptdesc((tlb), (page_ptdesc(pte))); \ -} while (0) +#define __pte_free_tlb(tlb, pte, addr) \ + tlb_remove_ptdesc((tlb), page_ptdesc(pte)) #endif
diff --git a/arch/loongarch/Kconfig b/arch/loongarch/Kconfig index 6875029..067c0b9 100644 --- a/arch/loongarch/Kconfig +++ b/arch/loongarch/Kconfig
@@ -30,6 +30,7 @@ select ARCH_HAS_SET_MEMORY select ARCH_HAS_SET_DIRECT_MAP select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST + select ARCH_HAS_UBSAN select ARCH_HAS_VDSO_ARCH_DATA select ARCH_INLINE_READ_LOCK if !PREEMPTION select ARCH_INLINE_READ_LOCK_BH if !PREEMPTION @@ -177,7 +178,7 @@ select HAVE_STACKPROTECTOR select HAVE_SYSCALL_TRACEPOINTS select HAVE_TIF_NOHZ - select HAVE_VIRT_CPU_ACCOUNTING_GEN if !SMP + select HAVE_VIRT_CPU_ACCOUNTING_GEN select IRQ_FORCED_THREADING select IRQ_LOONGARCH_CPU select LOCK_MM_AND_FIND_VMA @@ -387,8 +388,8 @@ config CMDLINE_EXTEND bool "Use built-in to extend bootloader kernel arguments" help - The command-line arguments provided during boot will be - appended to the built-in command line. This is useful in + The built-in command line will be appended to the command- + line arguments provided during boot. This is useful in cases where the provided arguments are insufficient and you don't want to or cannot modify them.
diff --git a/arch/loongarch/configs/loongson3_defconfig b/arch/loongarch/configs/loongson3_defconfig index c9f564e..90f21df 100644 --- a/arch/loongarch/configs/loongson3_defconfig +++ b/arch/loongarch/configs/loongson3_defconfig
@@ -24,9 +24,9 @@ CONFIG_MEMCG=y CONFIG_BLK_CGROUP=y CONFIG_CFS_BANDWIDTH=y -CONFIG_RT_GROUP_SCHED=y CONFIG_CGROUP_PIDS=y CONFIG_CGROUP_RDMA=y +CONFIG_CGROUP_DMEM=y CONFIG_CGROUP_FREEZER=y CONFIG_CGROUP_HUGETLB=y CONFIG_CPUSETS=y @@ -665,6 +665,10 @@ CONFIG_RTW88_8723DU=m CONFIG_RTW88_8821CE=m CONFIG_RTW88_8821CU=m +CONFIG_RTW88_8821AU=m +CONFIG_RTW88_8812AU=m +CONFIG_RTW88_8814AE=m +CONFIG_RTW88_8814AU=m CONFIG_RTW89=m CONFIG_RTW89_8851BE=m CONFIG_RTW89_8852AE=m @@ -748,6 +752,7 @@ CONFIG_VIDEO_BT848=m CONFIG_DVB_BT8XX=m CONFIG_DRM=y +CONFIG_DRM_LOAD_EDID_FIRMWARE=y CONFIG_DRM_RADEON=m CONFIG_DRM_RADEON_USERPTR=y CONFIG_DRM_AMDGPU=m @@ -761,6 +766,7 @@ CONFIG_FB=y CONFIG_FB_EFI=y CONFIG_FB_RADEON=y +CONFIG_FIRMWARE_EDID=y CONFIG_LCD_CLASS_DEVICE=y CONFIG_LCD_PLATFORM=m # CONFIG_VGA_CONSOLE is not set @@ -843,6 +849,9 @@ CONFIG_TYPEC_UCSI=m CONFIG_UCSI_ACPI=m CONFIG_INFINIBAND=m +CONFIG_EDAC=y +# CONFIG_EDAC_LEGACY_SYSFS is not set +CONFIG_EDAC_LOONGSON=y CONFIG_RTC_CLASS=y CONFIG_RTC_DRV_EFI=y CONFIG_RTC_DRV_LOONGSON=y
diff --git a/arch/loongarch/include/asm/cache.h b/arch/loongarch/include/asm/cache.h index 1b6d096..aa622c7 100644 --- a/arch/loongarch/include/asm/cache.h +++ b/arch/loongarch/include/asm/cache.h
@@ -8,6 +8,8 @@ #define L1_CACHE_SHIFT CONFIG_L1_CACHE_SHIFT #define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT) +#define ARCH_DMA_MINALIGN (16) + #define __read_mostly __section(".data..read_mostly") #endif /* _ASM_CACHE_H */
diff --git a/arch/loongarch/include/asm/irq.h b/arch/loongarch/include/asm/irq.h index a0ca84d..12bd155 100644 --- a/arch/loongarch/include/asm/irq.h +++ b/arch/loongarch/include/asm/irq.h
@@ -53,7 +53,7 @@ void spurious_interrupt(void); #define arch_trigger_cpumask_backtrace arch_trigger_cpumask_backtrace void arch_trigger_cpumask_backtrace(const struct cpumask *mask, int exclude_cpu); -#define MAX_IO_PICS 2 +#define MAX_IO_PICS 8 #define NR_IRQS (64 + NR_VECTORS * (NR_CPUS + MAX_IO_PICS)) struct acpi_vector_group {
diff --git a/arch/loongarch/include/asm/pgalloc.h b/arch/loongarch/include/asm/pgalloc.h index 7211dff..b58f587 100644 --- a/arch/loongarch/include/asm/pgalloc.h +++ b/arch/loongarch/include/asm/pgalloc.h
@@ -55,11 +55,8 @@ static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm) return pte; } -#define __pte_free_tlb(tlb, pte, address) \ -do { \ - pagetable_dtor(page_ptdesc(pte)); \ - tlb_remove_page_ptdesc((tlb), page_ptdesc(pte)); \ -} while (0) +#define __pte_free_tlb(tlb, pte, address) \ + tlb_remove_ptdesc((tlb), page_ptdesc(pte)) #ifndef __PAGETABLE_PMD_FOLDED
diff --git a/arch/loongarch/include/asm/stacktrace.h b/arch/loongarch/include/asm/stacktrace.h index f23adb1..fc8b647 100644 --- a/arch/loongarch/include/asm/stacktrace.h +++ b/arch/loongarch/include/asm/stacktrace.h
@@ -8,6 +8,7 @@ #include <asm/asm.h> #include <asm/ptrace.h> #include <asm/loongarch.h> +#include <asm/unwind_hints.h> #include <linux/stringify.h> enum stack_type { @@ -43,6 +44,7 @@ int get_stack_info(unsigned long stack, struct task_struct *task, struct stack_i static __always_inline void prepare_frametrace(struct pt_regs *regs) { __asm__ __volatile__( + UNWIND_HINT_SAVE /* Save $ra */ STORE_ONE_REG(1) /* Use $ra to save PC */ @@ -80,6 +82,7 @@ static __always_inline void prepare_frametrace(struct pt_regs *regs) STORE_ONE_REG(29) STORE_ONE_REG(30) STORE_ONE_REG(31) + UNWIND_HINT_RESTORE : "=m" (regs->csr_era) : "r" (regs->regs) : "memory");
diff --git a/arch/loongarch/include/asm/unwind_hints.h b/arch/loongarch/include/asm/unwind_hints.h index a01086a..2c68bc727 100644 --- a/arch/loongarch/include/asm/unwind_hints.h +++ b/arch/loongarch/include/asm/unwind_hints.h
@@ -23,6 +23,14 @@ UNWIND_HINT sp_reg=ORC_REG_SP type=UNWIND_HINT_TYPE_CALL .endm -#endif /* __ASSEMBLY__ */ +#else /* !__ASSEMBLY__ */ + +#define UNWIND_HINT_SAVE \ + UNWIND_HINT(UNWIND_HINT_TYPE_SAVE, 0, 0, 0) + +#define UNWIND_HINT_RESTORE \ + UNWIND_HINT(UNWIND_HINT_TYPE_RESTORE, 0, 0, 0) + +#endif /* !__ASSEMBLY__ */ #endif /* _ASM_LOONGARCH_UNWIND_HINTS_H */
diff --git a/arch/loongarch/kernel/env.c b/arch/loongarch/kernel/env.c index 2f1f5b0..27144de 100644 --- a/arch/loongarch/kernel/env.c +++ b/arch/loongarch/kernel/env.c
@@ -68,6 +68,8 @@ static int __init fdt_cpu_clk_init(void) return -ENODEV; clk = of_clk_get(np, 0); + of_node_put(np); + if (IS_ERR(clk)) return -ENODEV;
diff --git a/arch/loongarch/kernel/kgdb.c b/arch/loongarch/kernel/kgdb.c index 445c452..7be5b4c 100644 --- a/arch/loongarch/kernel/kgdb.c +++ b/arch/loongarch/kernel/kgdb.c
@@ -8,6 +8,7 @@ #include <linux/hw_breakpoint.h> #include <linux/kdebug.h> #include <linux/kgdb.h> +#include <linux/objtool.h> #include <linux/processor.h> #include <linux/ptrace.h> #include <linux/sched.h> @@ -224,13 +225,13 @@ void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long pc) regs->csr_era = pc; } -void arch_kgdb_breakpoint(void) +noinline void arch_kgdb_breakpoint(void) { __asm__ __volatile__ ( \ ".globl kgdb_breakinst\n\t" \ - "nop\n" \ "kgdb_breakinst:\tbreak 2\n\t"); /* BRK_KDB = 2 */ } +STACK_FRAME_NON_STANDARD(arch_kgdb_breakpoint); /* * Calls linux_debug_hook before the kernel dies. If KGDB is enabled,
diff --git a/arch/loongarch/net/bpf_jit.c b/arch/loongarch/net/bpf_jit.c index ea357a3..fa1500d 100644 --- a/arch/loongarch/net/bpf_jit.c +++ b/arch/loongarch/net/bpf_jit.c
@@ -142,6 +142,8 @@ static void build_prologue(struct jit_ctx *ctx) */ if (seen_tail_call(ctx) && seen_call(ctx)) move_reg(ctx, TCC_SAVED, REG_TCC); + else + emit_insn(ctx, nop); ctx->stack_size = stack_adjust; } @@ -905,7 +907,10 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx, bool ext move_addr(ctx, t1, func_addr); emit_insn(ctx, jirl, LOONGARCH_GPR_RA, t1, 0); - move_reg(ctx, regmap[BPF_REG_0], LOONGARCH_GPR_A0); + + if (insn->src_reg != BPF_PSEUDO_CALL) + move_reg(ctx, regmap[BPF_REG_0], LOONGARCH_GPR_A0); + break; /* tail call */ @@ -930,7 +935,10 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx, bool ext { const u64 imm64 = (u64)(insn + 1)->imm << 32 | (u32)insn->imm; - move_imm(ctx, dst, imm64, is32); + if (bpf_pseudo_func(insn)) + move_addr(ctx, dst, imm64); + else + move_imm(ctx, dst, imm64, is32); return 1; }
diff --git a/arch/loongarch/net/bpf_jit.h b/arch/loongarch/net/bpf_jit.h index 6858633..f9c569f 100644 --- a/arch/loongarch/net/bpf_jit.h +++ b/arch/loongarch/net/bpf_jit.h
@@ -27,6 +27,11 @@ struct jit_data { struct jit_ctx ctx; }; +static inline void emit_nop(union loongarch_instruction *insn) +{ + insn->word = INSN_NOP; +} + #define emit_insn(ctx, func, ...) \ do { \ if (ctx->image != NULL) { \
diff --git a/arch/loongarch/vdso/Makefile b/arch/loongarch/vdso/Makefile index 1c26147..ccd2c5e 100644 --- a/arch/loongarch/vdso/Makefile +++ b/arch/loongarch/vdso/Makefile
@@ -36,8 +36,7 @@ # VDSO linker flags. ldflags-y := -Bsymbolic --no-undefined -soname=linux-vdso.so.1 \ - $(filter -E%,$(KBUILD_CFLAGS)) -nostdlib -shared \ - --hash-style=sysv --build-id -T + $(filter -E%,$(KBUILD_CFLAGS)) -nostdlib -shared --build-id -T # # Shared build commands.
diff --git a/arch/loongarch/vdso/vgetrandom-chacha.S b/arch/loongarch/vdso/vgetrandom-chacha.S index c2733e6..c4dd2ba 100644 --- a/arch/loongarch/vdso/vgetrandom-chacha.S +++ b/arch/loongarch/vdso/vgetrandom-chacha.S
@@ -58,9 +58,7 @@ #define copy0 t5 #define copy1 t6 #define copy2 t7 - -/* Reuse i as copy3 */ -#define copy3 i +#define copy3 t8 /* Packs to be used with OP_4REG */ #define line0 state0, state1, state2, state3 @@ -99,6 +97,7 @@ li.w copy0, 0x61707865 li.w copy1, 0x3320646e li.w copy2, 0x79622d32 + li.w copy3, 0x6b206574 ld.w cnt_lo, counter, 0 ld.w cnt_hi, counter, 4 @@ -108,7 +107,7 @@ move state0, copy0 move state1, copy1 move state2, copy2 - li.w state3, 0x6b206574 + move state3, copy3 /* state[4,5,..,11] = key */ ld.w state4, key, 0 @@ -167,12 +166,6 @@ addi.w i, i, -1 bnez i, .Lpermute - /* - * copy[3] = "expa", materialize it here because copy[3] shares the - * same register with i which just became dead. - */ - li.w copy3, 0x6b206574 - /* output[0,1,2,3] = copy[0,1,2,3] + state[0,1,2,3] */ OP_4REG add.w line0, copy st.w state0, output, 0
diff --git a/arch/m68k/amiga/amisound.c b/arch/m68k/amiga/amisound.c index 714fe8e..5fd93df 100644 --- a/arch/m68k/amiga/amisound.c +++ b/arch/m68k/amiga/amisound.c
@@ -78,7 +78,7 @@ void amiga_mksound( unsigned int hz, unsigned int ticks ) return; local_irq_save(flags); - del_timer( &sound_timer ); + timer_delete(&sound_timer); if (hz > 20 && hz < 32767) { unsigned long period = (clock_constant / hz);
diff --git a/arch/m68k/configs/amcore_defconfig b/arch/m68k/configs/amcore_defconfig index 67a0d15..110279a 100644 --- a/arch/m68k/configs/amcore_defconfig +++ b/arch/m68k/configs/amcore_defconfig
@@ -89,4 +89,3 @@ # CONFIG_CRYPTO_ECHAINIV is not set CONFIG_CRYPTO_ANSI_CPRNG=y # CONFIG_CRYPTO_HW is not set -CONFIG_CRC16=y
diff --git a/arch/m68k/include/asm/sun3_pgalloc.h b/arch/m68k/include/asm/sun3_pgalloc.h index 80afc3a..1e21c75 100644 --- a/arch/m68k/include/asm/sun3_pgalloc.h +++ b/arch/m68k/include/asm/sun3_pgalloc.h
@@ -17,11 +17,8 @@ extern const char bad_pmd_string[]; -#define __pte_free_tlb(tlb, pte, addr) \ -do { \ - pagetable_dtor(page_ptdesc(pte)); \ - tlb_remove_page_ptdesc((tlb), page_ptdesc(pte)); \ -} while (0) +#define __pte_free_tlb(tlb, pte, addr) \ + tlb_remove_ptdesc((tlb), page_ptdesc(pte)) static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd, pte_t *pte) {
diff --git a/arch/m68k/mac/macboing.c b/arch/m68k/mac/macboing.c index faea226..6312d5b 100644 --- a/arch/m68k/mac/macboing.c +++ b/arch/m68k/mac/macboing.c
@@ -183,7 +183,7 @@ void mac_mksound( unsigned int freq, unsigned int length ) local_irq_save(flags); - del_timer( &mac_sound_timer ); + timer_delete(&mac_sound_timer); for ( i = 0; i < 0x800; i++ ) mac_asc_regs[ i ] = 0; @@ -277,7 +277,7 @@ static void mac_quadra_ring_bell(struct timer_list *unused) local_irq_save(flags); - del_timer( &mac_sound_timer ); + timer_delete(&mac_sound_timer); if ( mac_bell_duration-- > 0 ) {
diff --git a/arch/microblaze/mm/init.c b/arch/microblaze/mm/init.c index 65f0d1f..31d475c 100644 --- a/arch/microblaze/mm/init.c +++ b/arch/microblaze/mm/init.c
@@ -118,7 +118,7 @@ int page_is_ram(unsigned long pfn) /* * Check for command-line options that affect what MMU_init will do. */ -static void mm_cmdline_setup(void) +static void __init mm_cmdline_setup(void) { unsigned long maxmem = 0; char *p = cmd_line;
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 8592826..fc0772c 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig
@@ -2618,6 +2618,7 @@ CPU_MIPS32_R6 || CPU_MIPS64_R6 || \ CPU_P5600 || CAVIUM_OCTEON_SOC || \ CPU_LOONGSON64 + select ARCH_VMLINUX_NEEDS_RELOCS help This builds a kernel image that retains relocation information so it can be loaded someplace besides the default 1MB.
diff --git a/arch/mips/Makefile b/arch/mips/Makefile index be8cb44..d9057e2 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile
@@ -100,10 +100,6 @@ KBUILD_AFLAGS_MODULE += -mlong-calls KBUILD_CFLAGS_MODULE += -mlong-calls -ifeq ($(CONFIG_RELOCATABLE),y) -LDFLAGS_vmlinux += --emit-relocs -endif - cflags-y += -ffreestanding cflags-$(CONFIG_CPU_BIG_ENDIAN) += -EB
diff --git a/arch/mips/Makefile.postlink b/arch/mips/Makefile.postlink index 6cfdc14..ea0add7 100644 --- a/arch/mips/Makefile.postlink +++ b/arch/mips/Makefile.postlink
@@ -22,7 +22,7 @@ # `@true` prevents complaint when there is nothing to be done -vmlinux: FORCE +vmlinux vmlinux.unstripped: FORCE @true ifeq ($(CONFIG_CPU_LOONGSON3_WORKAROUNDS),y) $(call if_changed,ls3_llsc)
diff --git a/arch/mips/cavium-octeon/octeon-irq.c b/arch/mips/cavium-octeon/octeon-irq.c index 8425a6b..e6b4d9c 100644 --- a/arch/mips/cavium-octeon/octeon-irq.c +++ b/arch/mips/cavium-octeon/octeon-irq.c
@@ -1505,7 +1505,7 @@ static int __init octeon_irq_init_ciu( ciu_domain = irq_domain_add_tree( ciu_node, &octeon_irq_domain_ciu_ops, dd); - irq_set_default_host(ciu_domain); + irq_set_default_domain(ciu_domain); /* CIU_0 */ for (i = 0; i < 16; i++) { @@ -2076,7 +2076,7 @@ static int __init octeon_irq_init_ciu2( ciu_domain = irq_domain_add_tree( ciu_node, &octeon_irq_domain_ciu2_ops, NULL); - irq_set_default_host(ciu_domain); + irq_set_default_domain(ciu_domain); /* CUI2 */ for (i = 0; i < 64; i++) { @@ -2929,7 +2929,7 @@ static int __init octeon_irq_init_ciu3(struct device_node *ciu_node, /* Only do per CPU things if it is the CIU of the boot node. */ octeon_irq_ciu3_alloc_resources(ciu3_info); if (node == 0) - irq_set_default_host(domain); + irq_set_default_domain(domain); octeon_irq_use_ip4 = false; /* Enable the CIU lines */
diff --git a/arch/mips/configs/ath79_defconfig b/arch/mips/configs/ath79_defconfig index 8caa03a..cba0b85 100644 --- a/arch/mips/configs/ath79_defconfig +++ b/arch/mips/configs/ath79_defconfig
@@ -82,7 +82,6 @@ # CONFIG_IOMMU_SUPPORT is not set # CONFIG_DNOTIFY is not set # CONFIG_PROC_PAGE_MONITOR is not set -CONFIG_CRC_ITU_T=m CONFIG_STRIP_ASM_SYMS=y CONFIG_DEBUG_FS=y # CONFIG_SCHED_DEBUG is not set
diff --git a/arch/mips/configs/bigsur_defconfig b/arch/mips/configs/bigsur_defconfig index fe28263..8f7c368 100644 --- a/arch/mips/configs/bigsur_defconfig +++ b/arch/mips/configs/bigsur_defconfig
@@ -238,7 +238,6 @@ CONFIG_CRYPTO_TEA=m CONFIG_CRYPTO_TWOFISH=m CONFIG_CRYPTO_LZO=m -CONFIG_CRC_T10DIF=m CONFIG_MAGIC_SYSRQ=y CONFIG_DEBUG_MEMORY_INIT=y CONFIG_DETECT_HUNG_TASK=y
diff --git a/arch/mips/configs/fuloong2e_defconfig b/arch/mips/configs/fuloong2e_defconfig index 5ab149c..114fcd6 100644 --- a/arch/mips/configs/fuloong2e_defconfig +++ b/arch/mips/configs/fuloong2e_defconfig
@@ -218,4 +218,3 @@ CONFIG_CRYPTO_DEFLATE=m CONFIG_CRYPTO_LZO=m # CONFIG_CRYPTO_HW is not set -CONFIG_CRC_CCITT=y
diff --git a/arch/mips/configs/ip22_defconfig b/arch/mips/configs/ip22_defconfig index 31ca93d..f1a8ccf 100644 --- a/arch/mips/configs/ip22_defconfig +++ b/arch/mips/configs/ip22_defconfig
@@ -326,5 +326,4 @@ CONFIG_CRYPTO_TWOFISH=m CONFIG_CRYPTO_LZO=m # CONFIG_CRYPTO_HW is not set -CONFIG_CRC_T10DIF=m CONFIG_DEBUG_MEMORY_INIT=y
diff --git a/arch/mips/configs/ip27_defconfig b/arch/mips/configs/ip27_defconfig index b8907b3..5d07994 100644 --- a/arch/mips/configs/ip27_defconfig +++ b/arch/mips/configs/ip27_defconfig
@@ -317,4 +317,3 @@ CONFIG_CRYPTO_TEA=m CONFIG_CRYPTO_TWOFISH=m CONFIG_CRYPTO_LZO=m -CONFIG_CRC_T10DIF=m
diff --git a/arch/mips/configs/ip30_defconfig b/arch/mips/configs/ip30_defconfig index 270181a..a4524e7 100644 --- a/arch/mips/configs/ip30_defconfig +++ b/arch/mips/configs/ip30_defconfig
@@ -179,4 +179,3 @@ CONFIG_CRYPTO_WP512=m CONFIG_CRYPTO_XCBC=m CONFIG_CRYPTO_LZO=m -CONFIG_CRC_T10DIF=m
diff --git a/arch/mips/configs/ip32_defconfig b/arch/mips/configs/ip32_defconfig index 121e7e4..d8ac114 100644 --- a/arch/mips/configs/ip32_defconfig +++ b/arch/mips/configs/ip32_defconfig
@@ -177,7 +177,6 @@ CONFIG_CRYPTO_TEA=y CONFIG_CRYPTO_TWOFISH=y CONFIG_CRYPTO_DEFLATE=y -CONFIG_CRC_T10DIF=y CONFIG_FONTS=y CONFIG_FONT_8x8=y CONFIG_FONT_8x16=y
diff --git a/arch/mips/configs/omega2p_defconfig b/arch/mips/configs/omega2p_defconfig index 128f9ab..e2bcdfd 100644 --- a/arch/mips/configs/omega2p_defconfig +++ b/arch/mips/configs/omega2p_defconfig
@@ -111,7 +111,6 @@ CONFIG_NLS_UTF8=y CONFIG_CRYPTO_DEFLATE=y CONFIG_CRYPTO_LZO=y -CONFIG_CRC16=y CONFIG_XZ_DEC=y CONFIG_PRINTK_TIME=y CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
diff --git a/arch/mips/configs/rb532_defconfig b/arch/mips/configs/rb532_defconfig index 0261969..42b161d 100644 --- a/arch/mips/configs/rb532_defconfig +++ b/arch/mips/configs/rb532_defconfig
@@ -155,5 +155,4 @@ CONFIG_SQUASHFS=y CONFIG_CRYPTO_TEST=m # CONFIG_CRYPTO_HW is not set -CONFIG_CRC16=m CONFIG_STRIP_ASM_SYMS=y
diff --git a/arch/mips/configs/rt305x_defconfig b/arch/mips/configs/rt305x_defconfig index 8404e0a..8f9701e 100644 --- a/arch/mips/configs/rt305x_defconfig +++ b/arch/mips/configs/rt305x_defconfig
@@ -128,7 +128,6 @@ # CONFIG_SQUASHFS_ZLIB is not set CONFIG_SQUASHFS_XZ=y CONFIG_CRYPTO_ARC4=m -CONFIG_CRC_ITU_T=m # CONFIG_XZ_DEC_X86 is not set # CONFIG_XZ_DEC_POWERPC is not set # CONFIG_XZ_DEC_IA64 is not set
diff --git a/arch/mips/configs/sb1250_swarm_defconfig b/arch/mips/configs/sb1250_swarm_defconfig index ce855b6..ae2afff 100644 --- a/arch/mips/configs/sb1250_swarm_defconfig +++ b/arch/mips/configs/sb1250_swarm_defconfig
@@ -99,4 +99,3 @@ CONFIG_CRYPTO_DEFLATE=m CONFIG_CRYPTO_LZO=m # CONFIG_CRYPTO_HW is not set -CONFIG_CRC16=m
diff --git a/arch/mips/configs/vocore2_defconfig b/arch/mips/configs/vocore2_defconfig index 917967f..2a9a9b1 100644 --- a/arch/mips/configs/vocore2_defconfig +++ b/arch/mips/configs/vocore2_defconfig
@@ -111,7 +111,6 @@ CONFIG_NLS_UTF8=y CONFIG_CRYPTO_DEFLATE=y CONFIG_CRYPTO_LZO=y -CONFIG_CRC16=y CONFIG_XZ_DEC=y CONFIG_PRINTK_TIME=y CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
diff --git a/arch/mips/configs/xway_defconfig b/arch/mips/configs/xway_defconfig index 7b91edf..aae8497 100644 --- a/arch/mips/configs/xway_defconfig +++ b/arch/mips/configs/xway_defconfig
@@ -140,7 +140,6 @@ # CONFIG_SQUASHFS_ZLIB is not set CONFIG_SQUASHFS_XZ=y CONFIG_CRYPTO_ARC4=m -CONFIG_CRC_ITU_T=m CONFIG_PRINTK_TIME=y CONFIG_STRIP_ASM_SYMS=y CONFIG_DEBUG_FS=y
diff --git a/arch/mips/include/asm/pgalloc.h b/arch/mips/include/asm/pgalloc.h index 26c7a6e..bbca420 100644 --- a/arch/mips/include/asm/pgalloc.h +++ b/arch/mips/include/asm/pgalloc.h
@@ -48,11 +48,8 @@ static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd) extern void pgd_init(void *addr); extern pgd_t *pgd_alloc(struct mm_struct *mm); -#define __pte_free_tlb(tlb, pte, address) \ -do { \ - pagetable_dtor(page_ptdesc(pte)); \ - tlb_remove_page_ptdesc((tlb), page_ptdesc(pte)); \ -} while (0) +#define __pte_free_tlb(tlb, pte, address) \ + tlb_remove_ptdesc((tlb), page_ptdesc(pte)) #ifndef __PAGETABLE_PMD_FOLDED
diff --git a/arch/mips/pci/pci-xtalk-bridge.c b/arch/mips/pci/pci-xtalk-bridge.c index dae856f..e00c386 100644 --- a/arch/mips/pci/pci-xtalk-bridge.c +++ b/arch/mips/pci/pci-xtalk-bridge.c
@@ -620,7 +620,7 @@ static int bridge_probe(struct platform_device *pdev) if (bridge_get_partnum(virt_to_phys((void *)bd->bridge_addr), partnum)) return -EPROBE_DEFER; /* not available yet */ - parent = irq_get_default_host(); + parent = irq_get_default_domain(); if (!parent) return -ENODEV; fn = irq_domain_alloc_named_fwnode("BRIDGE");
diff --git a/arch/mips/sgi-ip22/ip22-reset.c b/arch/mips/sgi-ip22/ip22-reset.c index 8f0861c..8539f56 100644 --- a/arch/mips/sgi-ip22/ip22-reset.c +++ b/arch/mips/sgi-ip22/ip22-reset.c
@@ -98,7 +98,7 @@ static void blink_timeout(struct timer_list *unused) static void debounce(struct timer_list *unused) { - del_timer(&debounce_timer); + timer_delete(&debounce_timer); if (sgint->istat1 & SGINT_ISTAT1_PWR) { /* Interrupt still being sent. */ debounce_timer.expires = jiffies + (HZ / 20); /* 0.05s */
diff --git a/arch/mips/sgi-ip27/ip27-irq.c b/arch/mips/sgi-ip27/ip27-irq.c index 00e63e9..288d4d1 100644 --- a/arch/mips/sgi-ip27/ip27-irq.c +++ b/arch/mips/sgi-ip27/ip27-irq.c
@@ -297,7 +297,7 @@ void __init arch_init_irq(void) if (WARN_ON(domain == NULL)) return; - irq_set_default_host(domain); + irq_set_default_domain(domain); irq_set_percpu_devid(IP27_HUB_PEND0_IRQ); irq_set_chained_handler_and_data(IP27_HUB_PEND0_IRQ, ip27_do_irq_mask0,
diff --git a/arch/mips/sgi-ip30/ip30-irq.c b/arch/mips/sgi-ip30/ip30-irq.c index 423c32c..9fb905e 100644 --- a/arch/mips/sgi-ip30/ip30-irq.c +++ b/arch/mips/sgi-ip30/ip30-irq.c
@@ -313,7 +313,7 @@ void __init arch_init_irq(void) if (!domain) return; - irq_set_default_host(domain); + irq_set_default_domain(domain); irq_set_percpu_devid(IP30_HEART_L0_IRQ); irq_set_chained_handler_and_data(IP30_HEART_L0_IRQ, ip30_normal_irq,
diff --git a/arch/nios2/Kbuild b/arch/nios2/Kbuild index fc2952e..fa64c59 100644 --- a/arch/nios2/Kbuild +++ b/arch/nios2/Kbuild
@@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-only -obj-y += kernel/ mm/ platform/ boot/dts/ +obj-y += kernel/ mm/ platform/ # for cleaning subdir- += boot
diff --git a/arch/nios2/boot/dts/Makefile b/arch/nios2/boot/dts/Makefile index 1a2e899..1b8f41c 100644 --- a/arch/nios2/boot/dts/Makefile +++ b/arch/nios2/boot/dts/Makefile
@@ -1,5 +1,5 @@ # SPDX-License-Identifier: GPL-2.0 -obj-y := $(patsubst %.dts,%.dtb.o,$(CONFIG_NIOS2_DTB_SOURCE)) +dtb-y := $(addsuffix .dtb, $(CONFIG_BUILTIN_DTB_NAME)) -dtb-$(CONFIG_OF_ALL_DTBS) := $(patsubst $(src)/%.dts,%.dtb, $(wildcard $(src)/*.dts)) +dtb-$(CONFIG_OF_ALL_DTBS) += $(patsubst $(src)/%.dts,%.dtb, $(wildcard $(src)/*.dts))
diff --git a/arch/nios2/include/asm/pgalloc.h b/arch/nios2/include/asm/pgalloc.h index 12a536b..db122b0 100644 --- a/arch/nios2/include/asm/pgalloc.h +++ b/arch/nios2/include/asm/pgalloc.h
@@ -28,10 +28,7 @@ static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd, extern pgd_t *pgd_alloc(struct mm_struct *mm); -#define __pte_free_tlb(tlb, pte, addr) \ - do { \ - pagetable_dtor(page_ptdesc(pte)); \ - tlb_remove_page_ptdesc((tlb), (page_ptdesc(pte))); \ - } while (0) +#define __pte_free_tlb(tlb, pte, addr) \ + tlb_remove_ptdesc((tlb), page_ptdesc(pte)) #endif /* _ASM_NIOS2_PGALLOC_H */
diff --git a/arch/nios2/kernel/irq.c b/arch/nios2/kernel/irq.c index 6b7890e..8fa2806 100644 --- a/arch/nios2/kernel/irq.c +++ b/arch/nios2/kernel/irq.c
@@ -72,7 +72,7 @@ void __init init_IRQ(void) domain = irq_domain_add_linear(node, NIOS2_CPU_NR_IRQS, &irq_ops, NULL); BUG_ON(!domain); - irq_set_default_host(domain); + irq_set_default_domain(domain); of_node_put(node); /* Load the initial ienable value */ ienable = RDCTL(CTL_IENABLE);
diff --git a/arch/nios2/kernel/prom.c b/arch/nios2/kernel/prom.c index db04924..4f8c14d 100644 --- a/arch/nios2/kernel/prom.c +++ b/arch/nios2/kernel/prom.c
@@ -32,7 +32,7 @@ void __init early_init_devtree(void *params) } #endif -#ifdef CONFIG_NIOS2_DTB_SOURCE_BOOL +#ifdef CONFIG_BUILTIN_DTB if (be32_to_cpu((__be32) *dtb) == OF_DT_HEADER) params = (void *)__dtb_start; #endif
diff --git a/arch/nios2/platform/Kconfig.platform b/arch/nios2/platform/Kconfig.platform index e849daf..c75cadd 100644 --- a/arch/nios2/platform/Kconfig.platform +++ b/arch/nios2/platform/Kconfig.platform
@@ -35,19 +35,20 @@ help Physical address of a dtb blob. -config NIOS2_DTB_SOURCE_BOOL +config BUILTIN_DTB bool "Compile and link device tree into kernel image" depends on !COMPILE_TEST + select GENERIC_BUILTIN_DTB help This allows you to specify a dts (device tree source) file which will be compiled and linked into the kernel image. -config NIOS2_DTB_SOURCE - string "Device tree source file" - depends on NIOS2_DTB_SOURCE_BOOL +config BUILTIN_DTB_NAME + string "Built-in device tree name" + depends on BUILTIN_DTB default "" help - Absolute path to the device tree source (dts) file describing your + Relative path to the device tree without suffix describing your system. comment "Nios II instructions"
diff --git a/arch/openrisc/include/asm/pgalloc.h b/arch/openrisc/include/asm/pgalloc.h index 3372f4e..3f11093 100644 --- a/arch/openrisc/include/asm/pgalloc.h +++ b/arch/openrisc/include/asm/pgalloc.h
@@ -64,10 +64,7 @@ extern inline pgd_t *pgd_alloc(struct mm_struct *mm) extern pte_t *pte_alloc_one_kernel(struct mm_struct *mm); -#define __pte_free_tlb(tlb, pte, addr) \ -do { \ - pagetable_dtor(page_ptdesc(pte)); \ - tlb_remove_page_ptdesc((tlb), (page_ptdesc(pte))); \ -} while (0) +#define __pte_free_tlb(tlb, pte, addr) \ + tlb_remove_ptdesc((tlb), page_ptdesc(pte)) #endif
diff --git a/arch/parisc/configs/generic-32bit_defconfig b/arch/parisc/configs/generic-32bit_defconfig index f5fffc2..5b65c98 100644 --- a/arch/parisc/configs/generic-32bit_defconfig +++ b/arch/parisc/configs/generic-32bit_defconfig
@@ -264,8 +264,6 @@ CONFIG_CRYPTO_SHA1=y CONFIG_CRYPTO_WP512=m CONFIG_CRYPTO_DEFLATE=y -CONFIG_CRC_CCITT=m -CONFIG_CRC_T10DIF=y CONFIG_FONTS=y CONFIG_PRINTK_TIME=y CONFIG_MAGIC_SYSRQ=y
diff --git a/arch/parisc/configs/generic-64bit_defconfig b/arch/parisc/configs/generic-64bit_defconfig index 2487765..ecc9ffc 100644 --- a/arch/parisc/configs/generic-64bit_defconfig +++ b/arch/parisc/configs/generic-64bit_defconfig
@@ -292,7 +292,6 @@ CONFIG_CRYPTO_MICHAEL_MIC=m CONFIG_CRYPTO_DEFLATE=m # CONFIG_CRYPTO_HW is not set -CONFIG_CRC_CCITT=m CONFIG_PRINTK_TIME=y CONFIG_DEBUG_KERNEL=y CONFIG_STRIP_ASM_SYMS=y
diff --git a/arch/powerpc/configs/44x/sam440ep_defconfig b/arch/powerpc/configs/44x/sam440ep_defconfig index 2479ab6..98221bd 100644 --- a/arch/powerpc/configs/44x/sam440ep_defconfig +++ b/arch/powerpc/configs/44x/sam440ep_defconfig
@@ -91,5 +91,4 @@ # CONFIG_NETWORK_FILESYSTEMS is not set CONFIG_NLS_CODEPAGE_437=y CONFIG_NLS_ISO8859_1=y -CONFIG_CRC_T10DIF=y CONFIG_MAGIC_SYSRQ=y
diff --git a/arch/powerpc/configs/44x/warp_defconfig b/arch/powerpc/configs/44x/warp_defconfig index 20891c4..5757625 100644 --- a/arch/powerpc/configs/44x/warp_defconfig +++ b/arch/powerpc/configs/44x/warp_defconfig
@@ -85,8 +85,6 @@ CONFIG_NLS_ISO8859_1=y CONFIG_NLS_ISO8859_15=y CONFIG_NLS_UTF8=y -CONFIG_CRC_CCITT=y -CONFIG_CRC_T10DIF=y CONFIG_PRINTK_TIME=y CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y CONFIG_DEBUG_FS=y
diff --git a/arch/powerpc/configs/83xx/mpc832x_rdb_defconfig b/arch/powerpc/configs/83xx/mpc832x_rdb_defconfig index 1715ff5..b99caba 100644 --- a/arch/powerpc/configs/83xx/mpc832x_rdb_defconfig +++ b/arch/powerpc/configs/83xx/mpc832x_rdb_defconfig
@@ -73,6 +73,5 @@ CONFIG_NLS_CODEPAGE_932=y CONFIG_NLS_ISO8859_8=y CONFIG_NLS_ISO8859_1=y -CONFIG_CRC_T10DIF=y CONFIG_CRYPTO_ECB=m CONFIG_CRYPTO_PCBC=m
diff --git a/arch/powerpc/configs/83xx/mpc834x_itx_defconfig b/arch/powerpc/configs/83xx/mpc834x_itx_defconfig index e65c0057..1116305 100644 --- a/arch/powerpc/configs/83xx/mpc834x_itx_defconfig +++ b/arch/powerpc/configs/83xx/mpc834x_itx_defconfig
@@ -80,5 +80,4 @@ CONFIG_NFS_FS=y CONFIG_NFS_V4=y CONFIG_ROOT_NFS=y -CONFIG_CRC_T10DIF=y CONFIG_CRYPTO_PCBC=m
diff --git a/arch/powerpc/configs/83xx/mpc834x_itxgp_defconfig b/arch/powerpc/configs/83xx/mpc834x_itxgp_defconfig index 17714bf..312d39e 100644 --- a/arch/powerpc/configs/83xx/mpc834x_itxgp_defconfig +++ b/arch/powerpc/configs/83xx/mpc834x_itxgp_defconfig
@@ -72,5 +72,4 @@ CONFIG_NFS_FS=y CONFIG_NFS_V4=y CONFIG_ROOT_NFS=y -CONFIG_CRC_T10DIF=y CONFIG_CRYPTO_PCBC=m
diff --git a/arch/powerpc/configs/83xx/mpc837x_rdb_defconfig b/arch/powerpc/configs/83xx/mpc837x_rdb_defconfig index 58fae51..ac27f99 100644 --- a/arch/powerpc/configs/83xx/mpc837x_rdb_defconfig +++ b/arch/powerpc/configs/83xx/mpc837x_rdb_defconfig
@@ -75,6 +75,5 @@ CONFIG_NFS_FS=y CONFIG_NFS_V4=y CONFIG_ROOT_NFS=y -CONFIG_CRC_T10DIF=y CONFIG_CRYPTO_ECB=m CONFIG_CRYPTO_PCBC=m
diff --git a/arch/powerpc/configs/85xx/ge_imp3a_defconfig b/arch/powerpc/configs/85xx/ge_imp3a_defconfig index 6f58ee1..7beb36a 100644 --- a/arch/powerpc/configs/85xx/ge_imp3a_defconfig +++ b/arch/powerpc/configs/85xx/ge_imp3a_defconfig
@@ -221,8 +221,6 @@ CONFIG_NLS_KOI8_R=m CONFIG_NLS_KOI8_U=m CONFIG_NLS_UTF8=y -CONFIG_CRC_CCITT=y -CONFIG_CRC_T10DIF=y CONFIG_MAGIC_SYSRQ=y CONFIG_CRYPTO_CBC=y CONFIG_CRYPTO_MD5=y
diff --git a/arch/powerpc/configs/85xx/stx_gp3_defconfig b/arch/powerpc/configs/85xx/stx_gp3_defconfig index e708049..0a42072 100644 --- a/arch/powerpc/configs/85xx/stx_gp3_defconfig +++ b/arch/powerpc/configs/85xx/stx_gp3_defconfig
@@ -60,8 +60,6 @@ CONFIG_NFS_FS=y CONFIG_ROOT_NFS=y CONFIG_NLS=y -CONFIG_CRC_CCITT=y -CONFIG_CRC_T10DIF=m CONFIG_DETECT_HUNG_TASK=y # CONFIG_DEBUG_BUGVERBOSE is not set CONFIG_BDI_SWITCH=y
diff --git a/arch/powerpc/configs/85xx/xes_mpc85xx_defconfig b/arch/powerpc/configs/85xx/xes_mpc85xx_defconfig index 3a6381a..488d03a 100644 --- a/arch/powerpc/configs/85xx/xes_mpc85xx_defconfig +++ b/arch/powerpc/configs/85xx/xes_mpc85xx_defconfig
@@ -132,7 +132,6 @@ CONFIG_NFSD=y CONFIG_NLS_CODEPAGE_437=y CONFIG_NLS_ISO8859_1=y -CONFIG_CRC_T10DIF=y CONFIG_DETECT_HUNG_TASK=y # CONFIG_DEBUG_BUGVERBOSE is not set CONFIG_CRYPTO_HMAC=y
diff --git a/arch/powerpc/configs/86xx-hw.config b/arch/powerpc/configs/86xx-hw.config index 0cb24b3..e7bd265 100644 --- a/arch/powerpc/configs/86xx-hw.config +++ b/arch/powerpc/configs/86xx-hw.config
@@ -5,7 +5,6 @@ # CONFIG_CARDBUS is not set CONFIG_CHR_DEV_SG=y CONFIG_CHR_DEV_ST=y -CONFIG_CRC_T10DIF=y CONFIG_CRYPTO_HMAC=y CONFIG_DS1682=y CONFIG_EEPROM_LEGACY=y
diff --git a/arch/powerpc/configs/amigaone_defconfig b/arch/powerpc/configs/amigaone_defconfig index 200bb1e..69ef3dc 100644 --- a/arch/powerpc/configs/amigaone_defconfig +++ b/arch/powerpc/configs/amigaone_defconfig
@@ -106,7 +106,6 @@ CONFIG_AFFS_FS=m CONFIG_NLS_ASCII=y CONFIG_NLS_ISO8859_1=m -CONFIG_CRC_T10DIF=y CONFIG_MAGIC_SYSRQ=y CONFIG_DEBUG_KERNEL=y CONFIG_DEBUG_MUTEXES=y
diff --git a/arch/powerpc/configs/chrp32_defconfig b/arch/powerpc/configs/chrp32_defconfig index fb314f7..b799c95 100644 --- a/arch/powerpc/configs/chrp32_defconfig +++ b/arch/powerpc/configs/chrp32_defconfig
@@ -110,7 +110,6 @@ CONFIG_TMPFS=y CONFIG_NLS_ASCII=y CONFIG_NLS_ISO8859_1=m -CONFIG_CRC_T10DIF=y CONFIG_MAGIC_SYSRQ=y CONFIG_DEBUG_KERNEL=y CONFIG_DEBUG_MUTEXES=y
diff --git a/arch/powerpc/configs/fsl-emb-nonhw.config b/arch/powerpc/configs/fsl-emb-nonhw.config index d6d2a45..2f81bc2 100644 --- a/arch/powerpc/configs/fsl-emb-nonhw.config +++ b/arch/powerpc/configs/fsl-emb-nonhw.config
@@ -15,7 +15,6 @@ CONFIG_CGROUP_SCHED=y CONFIG_CGROUPS=y # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set -CONFIG_CRC_T10DIF=y CONFIG_CPUSETS=y CONFIG_CRAMFS=y CONFIG_CRYPTO_MD4=y
diff --git a/arch/powerpc/configs/g5_defconfig b/arch/powerpc/configs/g5_defconfig index 9215bed..7e58f3e 100644 --- a/arch/powerpc/configs/g5_defconfig +++ b/arch/powerpc/configs/g5_defconfig
@@ -231,7 +231,6 @@ CONFIG_NLS_ISO8859_1=y CONFIG_NLS_ISO8859_15=y CONFIG_NLS_UTF8=y -CONFIG_CRC_T10DIF=y CONFIG_MAGIC_SYSRQ=y CONFIG_DEBUG_KERNEL=y CONFIG_DEBUG_MUTEXES=y
diff --git a/arch/powerpc/configs/gamecube_defconfig b/arch/powerpc/configs/gamecube_defconfig index d77eeb5..cdd9965 100644 --- a/arch/powerpc/configs/gamecube_defconfig +++ b/arch/powerpc/configs/gamecube_defconfig
@@ -82,7 +82,6 @@ CONFIG_CIFS=y CONFIG_NLS_CODEPAGE_437=y CONFIG_NLS_ISO8859_1=y -CONFIG_CRC_CCITT=y CONFIG_PRINTK_TIME=y CONFIG_DEBUG_SPINLOCK=y CONFIG_DEBUG_MUTEXES=y
diff --git a/arch/powerpc/configs/linkstation_defconfig b/arch/powerpc/configs/linkstation_defconfig index fa707de..b564f9e 100644 --- a/arch/powerpc/configs/linkstation_defconfig +++ b/arch/powerpc/configs/linkstation_defconfig
@@ -125,8 +125,6 @@ CONFIG_NLS_CODEPAGE_932=m CONFIG_NLS_ISO8859_1=m CONFIG_NLS_UTF8=m -CONFIG_CRC_CCITT=m -CONFIG_CRC_T10DIF=y CONFIG_MAGIC_SYSRQ=y CONFIG_DEBUG_KERNEL=y CONFIG_DETECT_HUNG_TASK=y
diff --git a/arch/powerpc/configs/mpc83xx_defconfig b/arch/powerpc/configs/mpc83xx_defconfig index 83c4710..a815d9e 100644 --- a/arch/powerpc/configs/mpc83xx_defconfig +++ b/arch/powerpc/configs/mpc83xx_defconfig
@@ -97,7 +97,6 @@ CONFIG_NFS_FS=y CONFIG_NFS_V4=y CONFIG_ROOT_NFS=y -CONFIG_CRC_T10DIF=y CONFIG_CRYPTO_ECB=m CONFIG_CRYPTO_PCBC=m CONFIG_CRYPTO_SHA512=y
diff --git a/arch/powerpc/configs/mpc866_ads_defconfig b/arch/powerpc/configs/mpc866_ads_defconfig index a0d27c5..dfbdd5e 100644 --- a/arch/powerpc/configs/mpc866_ads_defconfig +++ b/arch/powerpc/configs/mpc866_ads_defconfig
@@ -38,4 +38,3 @@ CONFIG_CRAMFS=y CONFIG_NFS_FS=y CONFIG_ROOT_NFS=y -CONFIG_CRC_CCITT=y
diff --git a/arch/powerpc/configs/mvme5100_defconfig b/arch/powerpc/configs/mvme5100_defconfig index d1c7fd5..fa2b3b9 100644 --- a/arch/powerpc/configs/mvme5100_defconfig +++ b/arch/powerpc/configs/mvme5100_defconfig
@@ -107,8 +107,6 @@ CONFIG_NLS_CODEPAGE_932=m CONFIG_NLS_ISO8859_1=m CONFIG_NLS_UTF8=m -CONFIG_CRC_CCITT=m -CONFIG_CRC_T10DIF=y CONFIG_XZ_DEC=y CONFIG_MAGIC_SYSRQ=y CONFIG_DEBUG_KERNEL=y
diff --git a/arch/powerpc/configs/pasemi_defconfig b/arch/powerpc/configs/pasemi_defconfig index 6199394..8bbf51b3 100644 --- a/arch/powerpc/configs/pasemi_defconfig +++ b/arch/powerpc/configs/pasemi_defconfig
@@ -159,7 +159,6 @@ CONFIG_NFSD_V4=y CONFIG_NLS_CODEPAGE_437=y CONFIG_NLS_ISO8859_1=y -CONFIG_CRC_CCITT=y CONFIG_PRINTK_TIME=y CONFIG_MAGIC_SYSRQ=y CONFIG_DEBUG_KERNEL=y
diff --git a/arch/powerpc/configs/pmac32_defconfig b/arch/powerpc/configs/pmac32_defconfig index e8b3f67..1bc3466 100644 --- a/arch/powerpc/configs/pmac32_defconfig +++ b/arch/powerpc/configs/pmac32_defconfig
@@ -276,7 +276,6 @@ CONFIG_NFSD_V4=y CONFIG_NLS_CODEPAGE_437=m CONFIG_NLS_ISO8859_1=m -CONFIG_CRC_T10DIF=y CONFIG_MAGIC_SYSRQ=y CONFIG_DEBUG_KERNEL=y CONFIG_DETECT_HUNG_TASK=y
diff --git a/arch/powerpc/configs/ppc44x_defconfig b/arch/powerpc/configs/ppc44x_defconfig index 8b595f6..41c930f 100644 --- a/arch/powerpc/configs/ppc44x_defconfig +++ b/arch/powerpc/configs/ppc44x_defconfig
@@ -90,7 +90,6 @@ CONFIG_ROOT_NFS=y CONFIG_NLS_CODEPAGE_437=m CONFIG_NLS_ISO8859_1=m -CONFIG_CRC_T10DIF=m CONFIG_MAGIC_SYSRQ=y CONFIG_DETECT_HUNG_TASK=y CONFIG_CRYPTO_ECB=y
diff --git a/arch/powerpc/configs/ppc64e_defconfig b/arch/powerpc/configs/ppc64e_defconfig index 4c05f4e..d2e659a 100644 --- a/arch/powerpc/configs/ppc64e_defconfig +++ b/arch/powerpc/configs/ppc64e_defconfig
@@ -207,7 +207,6 @@ CONFIG_NLS_ASCII=y CONFIG_NLS_ISO8859_1=y CONFIG_NLS_UTF8=y -CONFIG_CRC_T10DIF=y CONFIG_MAGIC_SYSRQ=y CONFIG_DEBUG_KERNEL=y CONFIG_DEBUG_STACK_USAGE=y
diff --git a/arch/powerpc/configs/ps3_defconfig b/arch/powerpc/configs/ps3_defconfig index 2b175dd..0b48d2b 100644 --- a/arch/powerpc/configs/ps3_defconfig +++ b/arch/powerpc/configs/ps3_defconfig
@@ -148,8 +148,6 @@ CONFIG_CRYPTO_PCBC=m CONFIG_CRYPTO_MICHAEL_MIC=m CONFIG_CRYPTO_LZO=m -CONFIG_CRC_CCITT=m -CONFIG_CRC_T10DIF=y CONFIG_PRINTK_TIME=y CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y CONFIG_MAGIC_SYSRQ=y
diff --git a/arch/powerpc/configs/skiroot_defconfig b/arch/powerpc/configs/skiroot_defconfig index 1eb4464..2b71a6d 100644 --- a/arch/powerpc/configs/skiroot_defconfig +++ b/arch/powerpc/configs/skiroot_defconfig
@@ -78,7 +78,6 @@ CONFIG_BLK_DEV_NVME=m CONFIG_NVME_MULTIPATH=y CONFIG_EEPROM_AT24=m -# CONFIG_CXL is not set # CONFIG_OCXL is not set CONFIG_BLK_DEV_SD=m CONFIG_BLK_DEV_SR=m @@ -279,8 +278,6 @@ # CONFIG_INTEGRITY is not set CONFIG_LSM="yama,loadpin,safesetid,integrity" # CONFIG_CRYPTO_HW is not set -CONFIG_CRC16=y -CONFIG_CRC_ITU_T=y # CONFIG_XZ_DEC_X86 is not set # CONFIG_XZ_DEC_IA64 is not set # CONFIG_XZ_DEC_ARM is not set
diff --git a/arch/powerpc/configs/storcenter_defconfig b/arch/powerpc/configs/storcenter_defconfig index 7a978d3..e415222 100644 --- a/arch/powerpc/configs/storcenter_defconfig +++ b/arch/powerpc/configs/storcenter_defconfig
@@ -75,4 +75,3 @@ CONFIG_NLS_CODEPAGE_437=y CONFIG_NLS_ISO8859_1=y CONFIG_NLS_UTF8=y -CONFIG_CRC_T10DIF=y
diff --git a/arch/powerpc/configs/wii_defconfig b/arch/powerpc/configs/wii_defconfig index 5017a69..7c714a1 100644 --- a/arch/powerpc/configs/wii_defconfig +++ b/arch/powerpc/configs/wii_defconfig
@@ -114,7 +114,6 @@ CONFIG_CIFS=m CONFIG_NLS_CODEPAGE_437=y CONFIG_NLS_ISO8859_1=y -CONFIG_CRC_CCITT=y CONFIG_PRINTK_TIME=y CONFIG_MAGIC_SYSRQ=y CONFIG_DEBUG_SPINLOCK=y
diff --git a/arch/powerpc/include/asm/copro.h b/arch/powerpc/include/asm/copro.h index fd2e166..81bd176 100644 --- a/arch/powerpc/include/asm/copro.h +++ b/arch/powerpc/include/asm/copro.h
@@ -18,10 +18,4 @@ int copro_handle_mm_fault(struct mm_struct *mm, unsigned long ea, int copro_calculate_slb(struct mm_struct *mm, u64 ea, struct copro_slb *slb); - -#ifdef CONFIG_PPC_COPRO_BASE -void copro_flush_all_slbs(struct mm_struct *mm); -#else -static inline void copro_flush_all_slbs(struct mm_struct *mm) {} -#endif #endif /* _ASM_POWERPC_COPRO_H */
diff --git a/arch/powerpc/include/asm/device.h b/arch/powerpc/include/asm/device.h index 47ed639..a4dc276 100644 --- a/arch/powerpc/include/asm/device.h +++ b/arch/powerpc/include/asm/device.h
@@ -38,9 +38,6 @@ struct dev_archdata { #ifdef CONFIG_FAIL_IOMMU int fail_iommu; #endif -#ifdef CONFIG_CXL_BASE - struct cxl_context *cxl_ctx; -#endif #ifdef CONFIG_PCI_IOV void *iov_data; #endif
diff --git a/arch/powerpc/include/asm/pnv-pci.h b/arch/powerpc/include/asm/pnv-pci.h index 8afc928..7e9a479 100644 --- a/arch/powerpc/include/asm/pnv-pci.h +++ b/arch/powerpc/include/asm/pnv-pci.h
@@ -10,7 +10,6 @@ #include <linux/pci_hotplug.h> #include <linux/irq.h> #include <linux/of.h> -#include <misc/cxl-base.h> #include <asm/opal-api.h> #define PCI_SLOT_ID_PREFIX (1UL << 63) @@ -25,25 +24,9 @@ extern int pnv_pci_get_power_state(uint64_t id, uint8_t *state); extern int pnv_pci_set_power_state(uint64_t id, uint8_t state, struct opal_msg *msg); -extern int pnv_pci_set_tunnel_bar(struct pci_dev *dev, uint64_t addr, - int enable); -int pnv_phb_to_cxl_mode(struct pci_dev *dev, uint64_t mode); -int pnv_cxl_ioda_msi_setup(struct pci_dev *dev, unsigned int hwirq, - unsigned int virq); -int pnv_cxl_alloc_hwirqs(struct pci_dev *dev, int num); -void pnv_cxl_release_hwirqs(struct pci_dev *dev, int hwirq, int num); -int pnv_cxl_get_irq_count(struct pci_dev *dev); -struct device_node *pnv_pci_get_phb_node(struct pci_dev *dev); int64_t pnv_opal_pci_msi_eoi(struct irq_data *d); bool is_pnv_opal_msi(struct irq_chip *chip); -#ifdef CONFIG_CXL_BASE -int pnv_cxl_alloc_hwirq_ranges(struct cxl_irq_ranges *irqs, - struct pci_dev *dev, int num); -void pnv_cxl_release_hwirq_ranges(struct cxl_irq_ranges *irqs, - struct pci_dev *dev); -#endif - struct pnv_php_slot { struct hotplug_slot slot; uint64_t id;
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c index 86bff15..19f4d29 100644 --- a/arch/powerpc/kvm/book3s_hv.c +++ b/arch/powerpc/kvm/book3s_hv.c
@@ -6041,7 +6041,7 @@ static int kvmppc_set_passthru_irq(struct kvm *kvm, int host_irq, int guest_gsi) * the underlying calls, which will EOI the interrupt in real * mode, need an HW IRQ number mapped in the XICS IRQ domain. */ - host_data = irq_domain_get_irq_data(irq_get_default_host(), host_irq); + host_data = irq_domain_get_irq_data(irq_get_default_domain(), host_irq); irq_map->r_hwirq = (unsigned int)irqd_to_hwirq(host_data); if (i == pimap->n_mapped)
diff --git a/arch/powerpc/kvm/book3s_xive.c b/arch/powerpc/kvm/book3s_xive.c index 1362c67..1302b5a 100644 --- a/arch/powerpc/kvm/book3s_xive.c +++ b/arch/powerpc/kvm/book3s_xive.c
@@ -1555,7 +1555,7 @@ int kvmppc_xive_set_mapped(struct kvm *kvm, unsigned long guest_irq, struct kvmppc_xive_src_block *sb; struct kvmppc_xive_irq_state *state; struct irq_data *host_data = - irq_domain_get_irq_data(irq_get_default_host(), host_irq); + irq_domain_get_irq_data(irq_get_default_domain(), host_irq); unsigned int hw_irq = (unsigned int)irqd_to_hwirq(host_data); u16 idx; u8 prio;
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c index 6a5be02..6a48059 100644 --- a/arch/powerpc/kvm/booke.c +++ b/arch/powerpc/kvm/booke.c
@@ -622,7 +622,7 @@ static void arm_next_watchdog(struct kvm_vcpu *vcpu) if (nr_jiffies < NEXT_TIMER_MAX_DELTA) mod_timer(&vcpu->arch.wdt_timer, jiffies + nr_jiffies); else - del_timer(&vcpu->arch.wdt_timer); + timer_delete(&vcpu->arch.wdt_timer); spin_unlock_irqrestore(&vcpu->arch.wdt_lock, flags); } @@ -1441,7 +1441,7 @@ int kvmppc_subarch_vcpu_init(struct kvm_vcpu *vcpu) void kvmppc_subarch_vcpu_uninit(struct kvm_vcpu *vcpu) { - del_timer_sync(&vcpu->arch.wdt_timer); + timer_delete_sync(&vcpu->arch.wdt_timer); } int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
diff --git a/arch/powerpc/mm/book3s64/hash_native.c b/arch/powerpc/mm/book3s64/hash_native.c index 430d1d9..e9e2dd7 100644 --- a/arch/powerpc/mm/book3s64/hash_native.c +++ b/arch/powerpc/mm/book3s64/hash_native.c
@@ -27,8 +27,6 @@ #include <asm/ppc-opcode.h> #include <asm/feature-fixups.h> -#include <misc/cxl-base.h> - #ifdef DEBUG_LOW #define DBG_LOW(fmt...) udbg_printf(fmt) #else @@ -217,11 +215,9 @@ static inline void __tlbiel(unsigned long vpn, int psize, int apsize, int ssize) static inline void tlbie(unsigned long vpn, int psize, int apsize, int ssize, int local) { - unsigned int use_local; + unsigned int use_local = local && mmu_has_feature(MMU_FTR_TLBIEL); int lock_tlbie = !mmu_has_feature(MMU_FTR_LOCKLESS_TLBIE); - use_local = local && mmu_has_feature(MMU_FTR_TLBIEL) && !cxl_ctx_in_use(); - if (use_local) use_local = mmu_psize_defs[psize].tlbiel; if (lock_tlbie && !use_local) @@ -789,10 +785,6 @@ static void native_flush_hash_range(unsigned long number, int local) unsigned long psize = batch->psize; int ssize = batch->ssize; int i; - unsigned int use_local; - - use_local = local && mmu_has_feature(MMU_FTR_TLBIEL) && - mmu_psize_defs[psize].tlbiel && !cxl_ctx_in_use(); local_irq_save(flags); @@ -827,7 +819,8 @@ static void native_flush_hash_range(unsigned long number, int local) } pte_iterate_hashed_end(); } - if (use_local) { + if (mmu_has_feature(MMU_FTR_TLBIEL) && + mmu_psize_defs[psize].tlbiel && local) { asm volatile("ptesync":::"memory"); for (i = 0; i < number; i++) { vpn = batch->vpn[i];
diff --git a/arch/powerpc/mm/book3s64/hash_utils.c b/arch/powerpc/mm/book3s64/hash_utils.c index 7346100..5158aef 100644 --- a/arch/powerpc/mm/book3s64/hash_utils.c +++ b/arch/powerpc/mm/book3s64/hash_utils.c
@@ -56,7 +56,7 @@ #include <asm/cacheflush.h> #include <asm/cputable.h> #include <asm/sections.h> -#include <asm/copro.h> +#include <asm/spu.h> #include <asm/udbg.h> #include <asm/text-patching.h> #include <asm/fadump.h> @@ -1600,7 +1600,9 @@ void demote_segment_4k(struct mm_struct *mm, unsigned long addr) if (get_slice_psize(mm, addr) == MMU_PAGE_4K) return; slice_set_range_psize(mm, addr, 1, MMU_PAGE_4K); - copro_flush_all_slbs(mm); +#ifdef CONFIG_SPU_BASE + spu_flush_all_slbs(mm); +#endif if ((get_paca_psize(addr) != MMU_PAGE_4K) && (current->mm == mm)) { copy_mm_to_paca(mm); @@ -1869,7 +1871,9 @@ int hash_page_mm(struct mm_struct *mm, unsigned long ea, "to 4kB pages because of " "non-cacheable mapping\n"); psize = mmu_vmalloc_psize = MMU_PAGE_4K; - copro_flush_all_slbs(mm); +#ifdef CONFIG_SPU_BASE + spu_flush_all_slbs(mm); +#endif } }
diff --git a/arch/powerpc/mm/book3s64/pgtable.c b/arch/powerpc/mm/book3s64/pgtable.c index c0c45d0..8f7d41c 100644 --- a/arch/powerpc/mm/book3s64/pgtable.c +++ b/arch/powerpc/mm/book3s64/pgtable.c
@@ -10,7 +10,6 @@ #include <linux/pkeys.h> #include <linux/debugfs.h> #include <linux/proc_fs.h> -#include <misc/cxl-base.h> #include <asm/pgalloc.h> #include <asm/tlb.h>
diff --git a/arch/powerpc/mm/book3s64/slice.c b/arch/powerpc/mm/book3s64/slice.c index bc9a398..28bec5b 100644 --- a/arch/powerpc/mm/book3s64/slice.c +++ b/arch/powerpc/mm/book3s64/slice.c
@@ -22,7 +22,7 @@ #include <linux/security.h> #include <asm/mman.h> #include <asm/mmu.h> -#include <asm/copro.h> +#include <asm/spu.h> #include <asm/hugetlb.h> #include <asm/mmu_context.h> @@ -248,7 +248,9 @@ static void slice_convert(struct mm_struct *mm, spin_unlock_irqrestore(&slice_convert_lock, flags); - copro_flush_all_slbs(mm); +#ifdef CONFIG_SPU_BASE + spu_flush_all_slbs(mm); +#endif } /*
diff --git a/arch/powerpc/mm/copro_fault.c b/arch/powerpc/mm/copro_fault.c index f49fd87..f5f8692 100644 --- a/arch/powerpc/mm/copro_fault.c +++ b/arch/powerpc/mm/copro_fault.c
@@ -12,8 +12,6 @@ #include <linux/export.h> #include <asm/reg.h> #include <asm/copro.h> -#include <asm/spu.h> -#include <misc/cxl-base.h> /* * This ought to be kept in sync with the powerpc specific do_page_fault @@ -135,13 +133,4 @@ int copro_calculate_slb(struct mm_struct *mm, u64 ea, struct copro_slb *slb) return 0; } EXPORT_SYMBOL_GPL(copro_calculate_slb); - -void copro_flush_all_slbs(struct mm_struct *mm) -{ -#ifdef CONFIG_SPU_BASE - spu_flush_all_slbs(mm); -#endif - cxl_slbia(mm); -} -EXPORT_SYMBOL_GPL(copro_flush_all_slbs); #endif
diff --git a/arch/powerpc/platforms/44x/uic.c b/arch/powerpc/platforms/44x/uic.c index 8b03ae4..31f760c 100644 --- a/arch/powerpc/platforms/44x/uic.c +++ b/arch/powerpc/platforms/44x/uic.c
@@ -291,7 +291,7 @@ void __init uic_init_tree(void) if (!primary_uic) panic("Unable to initialize primary UIC %pOF\n", np); - irq_set_default_host(primary_uic->irqhost); + irq_set_default_domain(primary_uic->irqhost); of_node_put(np); /* The scan again for cascaded UICs */
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pic.c b/arch/powerpc/platforms/52xx/mpc52xx_pic.c index 1e0a5e9..43c881d 100644 --- a/arch/powerpc/platforms/52xx/mpc52xx_pic.c +++ b/arch/powerpc/platforms/52xx/mpc52xx_pic.c
@@ -453,7 +453,7 @@ void __init mpc52xx_init_irq(void) if (!mpc52xx_irqhost) panic(__FILE__ ": Cannot allocate the IRQ host\n"); - irq_set_default_host(mpc52xx_irqhost); + irq_set_default_domain(mpc52xx_irqhost); pr_info("MPC52xx PIC is up and running!\n"); }
diff --git a/arch/powerpc/platforms/amigaone/setup.c b/arch/powerpc/platforms/amigaone/setup.c index 2c8dc08..33f852a 100644 --- a/arch/powerpc/platforms/amigaone/setup.c +++ b/arch/powerpc/platforms/amigaone/setup.c
@@ -109,7 +109,7 @@ static void __init amigaone_init_IRQ(void) i8259_init(pic, int_ack); ppc_md.get_irq = i8259_irq; - irq_set_default_host(i8259_get_host()); + irq_set_default_domain(i8259_get_host()); } static int __init request_isa_regions(void)
diff --git a/arch/powerpc/platforms/cell/spufs/gang.c b/arch/powerpc/platforms/cell/spufs/gang.c index 827d338..2c2999de 100644 --- a/arch/powerpc/platforms/cell/spufs/gang.c +++ b/arch/powerpc/platforms/cell/spufs/gang.c
@@ -25,6 +25,7 @@ struct spu_gang *alloc_spu_gang(void) mutex_init(&gang->aff_mutex); INIT_LIST_HEAD(&gang->list); INIT_LIST_HEAD(&gang->aff_list_head); + gang->alive = 1; out: return gang;
diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c index 70236d1..9f9e4b8 100644 --- a/arch/powerpc/platforms/cell/spufs/inode.c +++ b/arch/powerpc/platforms/cell/spufs/inode.c
@@ -192,13 +192,32 @@ static int spufs_fill_dir(struct dentry *dir, return -ENOMEM; ret = spufs_new_file(dir->d_sb, dentry, files->ops, files->mode & mode, files->size, ctx); - if (ret) + if (ret) { + dput(dentry); return ret; + } files++; } return 0; } +static void unuse_gang(struct dentry *dir) +{ + struct inode *inode = dir->d_inode; + struct spu_gang *gang = SPUFS_I(inode)->i_gang; + + if (gang) { + bool dead; + + inode_lock(inode); // exclusion with spufs_create_context() + dead = !--gang->alive; + inode_unlock(inode); + + if (dead) + simple_recursive_removal(dir, NULL); + } +} + static int spufs_dir_close(struct inode *inode, struct file *file) { struct inode *parent; @@ -213,6 +232,7 @@ static int spufs_dir_close(struct inode *inode, struct file *file) inode_unlock(parent); WARN_ON(ret); + unuse_gang(dir->d_parent); return dcache_dir_close(inode, file); } @@ -405,7 +425,7 @@ spufs_create_context(struct inode *inode, struct dentry *dentry, { int ret; int affinity; - struct spu_gang *gang; + struct spu_gang *gang = SPUFS_I(inode)->i_gang; struct spu_context *neighbor; struct path path = {.mnt = mnt, .dentry = dentry}; @@ -420,11 +440,15 @@ spufs_create_context(struct inode *inode, struct dentry *dentry, if ((flags & SPU_CREATE_ISOLATE) && !isolated_loader) return -ENODEV; - gang = NULL; + if (gang) { + if (!gang->alive) + return -ENOENT; + gang->alive++; + } + neighbor = NULL; affinity = flags & (SPU_CREATE_AFFINITY_MEM | SPU_CREATE_AFFINITY_SPU); if (affinity) { - gang = SPUFS_I(inode)->i_gang; if (!gang) return -EINVAL; mutex_lock(&gang->aff_mutex); @@ -436,8 +460,11 @@ spufs_create_context(struct inode *inode, struct dentry *dentry, } ret = spufs_mkdir(inode, dentry, flags, mode & 0777); - if (ret) + if (ret) { + if (neighbor) + put_spu_context(neighbor); goto out_aff_unlock; + } if (affinity) { spufs_set_affinity(flags, SPUFS_I(d_inode(dentry))->i_ctx, @@ -453,6 +480,8 @@ spufs_create_context(struct inode *inode, struct dentry *dentry, out_aff_unlock: if (affinity) mutex_unlock(&gang->aff_mutex); + if (ret && gang) + gang->alive--; // can't reach 0 return ret; } @@ -482,6 +511,7 @@ spufs_mkgang(struct inode *dir, struct dentry *dentry, umode_t mode) inode->i_fop = &simple_dir_operations; d_instantiate(dentry, inode); + dget(dentry); inc_nlink(dir); inc_nlink(d_inode(dentry)); return ret; @@ -492,6 +522,21 @@ spufs_mkgang(struct inode *dir, struct dentry *dentry, umode_t mode) return ret; } +static int spufs_gang_close(struct inode *inode, struct file *file) +{ + unuse_gang(file->f_path.dentry); + return dcache_dir_close(inode, file); +} + +static const struct file_operations spufs_gang_fops = { + .open = dcache_dir_open, + .release = spufs_gang_close, + .llseek = dcache_dir_lseek, + .read = generic_read_dir, + .iterate_shared = dcache_readdir, + .fsync = noop_fsync, +}; + static int spufs_gang_open(const struct path *path) { int ret; @@ -511,7 +556,7 @@ static int spufs_gang_open(const struct path *path) return PTR_ERR(filp); } - filp->f_op = &simple_dir_operations; + filp->f_op = &spufs_gang_fops; fd_install(ret, filp); return ret; } @@ -526,10 +571,8 @@ static int spufs_create_gang(struct inode *inode, ret = spufs_mkgang(inode, dentry, mode & 0777); if (!ret) { ret = spufs_gang_open(&path); - if (ret < 0) { - int err = simple_rmdir(inode, dentry); - WARN_ON(err); - } + if (ret < 0) + unuse_gang(dentry); } return ret; }
diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c index 610ca85..8e7ed010 100644 --- a/arch/powerpc/platforms/cell/spufs/sched.c +++ b/arch/powerpc/platforms/cell/spufs/sched.c
@@ -508,7 +508,7 @@ static void __spu_del_from_rq(struct spu_context *ctx) if (!list_empty(&ctx->rq)) { if (!--spu_prio->nr_waiting) - del_timer(&spusched_timer); + timer_delete(&spusched_timer); list_del_init(&ctx->rq); if (list_empty(&spu_prio->runq[prio])) @@ -1126,8 +1126,8 @@ void spu_sched_exit(void) remove_proc_entry("spu_loadavg", NULL); - del_timer_sync(&spusched_timer); - del_timer_sync(&spuloadavg_timer); + timer_delete_sync(&spusched_timer); + timer_delete_sync(&spuloadavg_timer); kthread_stop(spusched_task); for (node = 0; node < MAX_NUMNODES; node++) {
diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h index 8495848..d33787c5 100644 --- a/arch/powerpc/platforms/cell/spufs/spufs.h +++ b/arch/powerpc/platforms/cell/spufs/spufs.h
@@ -151,6 +151,8 @@ struct spu_gang { int aff_flags; struct spu *aff_ref_spu; atomic_t aff_sched_count; + + int alive; }; /* Flag bits for spu_gang aff_flags */
diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c index 36ee3a5..c1bfa4c 100644 --- a/arch/powerpc/platforms/chrp/setup.c +++ b/arch/powerpc/platforms/chrp/setup.c
@@ -486,7 +486,7 @@ static void __init chrp_find_8259(void) i8259_init(pic, chrp_int_ack); if (ppc_md.get_irq == NULL) { ppc_md.get_irq = i8259_irq; - irq_set_default_host(i8259_get_host()); + irq_set_default_domain(i8259_get_host()); } if (chrp_mpic != NULL) { cascade_irq = irq_of_parse_and_map(pic, 0);
diff --git a/arch/powerpc/platforms/embedded6xx/flipper-pic.c b/arch/powerpc/platforms/embedded6xx/flipper-pic.c index 4d9200b..013d663 100644 --- a/arch/powerpc/platforms/embedded6xx/flipper-pic.c +++ b/arch/powerpc/platforms/embedded6xx/flipper-pic.c
@@ -190,7 +190,7 @@ void __init flipper_pic_probe(void) flipper_irq_host = flipper_pic_init(np); BUG_ON(!flipper_irq_host); - irq_set_default_host(flipper_irq_host); + irq_set_default_domain(flipper_irq_host); of_node_put(np); }
diff --git a/arch/powerpc/platforms/pasemi/setup.c b/arch/powerpc/platforms/pasemi/setup.c index 0761d98..d03b413 100644 --- a/arch/powerpc/platforms/pasemi/setup.c +++ b/arch/powerpc/platforms/pasemi/setup.c
@@ -228,7 +228,7 @@ static void __init nemo_init_IRQ(struct mpic *mpic) irq_set_chained_handler(gpio_virq, sb600_8259_cascade); mpic_unmask_irq(irq_get_irq_data(gpio_virq)); - irq_set_default_host(mpic->irqhost); + irq_set_default_domain(mpic->irqhost); } #else
diff --git a/arch/powerpc/platforms/powermac/low_i2c.c b/arch/powerpc/platforms/powermac/low_i2c.c index c097d59..a0ae5863 100644 --- a/arch/powerpc/platforms/powermac/low_i2c.c +++ b/arch/powerpc/platforms/powermac/low_i2c.c
@@ -347,7 +347,7 @@ static irqreturn_t kw_i2c_irq(int irq, void *dev_id) unsigned long flags; spin_lock_irqsave(&host->lock, flags); - del_timer(&host->timeout_timer); + timer_delete(&host->timeout_timer); kw_i2c_handle_interrupt(host, kw_read_reg(reg_isr)); if (host->state != state_idle) { host->timeout_timer.expires = jiffies + KW_POLL_TIMEOUT;
diff --git a/arch/powerpc/platforms/powermac/pic.c b/arch/powerpc/platforms/powermac/pic.c index 2202bf7..03a7c51 100644 --- a/arch/powerpc/platforms/powermac/pic.c +++ b/arch/powerpc/platforms/powermac/pic.c
@@ -330,7 +330,7 @@ static void __init pmac_pic_probe_oldstyle(void) pmac_pic_host = irq_domain_add_linear(master, max_irqs, &pmac_pic_host_ops, NULL); BUG_ON(pmac_pic_host == NULL); - irq_set_default_host(pmac_pic_host); + irq_set_default_domain(pmac_pic_host); /* Get addresses of first controller if we have a node for it */ BUG_ON(of_address_to_resource(master, 0, &r));
diff --git a/arch/powerpc/platforms/powernv/Makefile b/arch/powerpc/platforms/powernv/Makefile index 19f0fc5..9e5d0c8 100644 --- a/arch/powerpc/platforms/powernv/Makefile +++ b/arch/powerpc/platforms/powernv/Makefile
@@ -21,7 +21,6 @@ obj-$(CONFIG_OPAL_CORE) += opal-core.o obj-$(CONFIG_PCI) += pci.o pci-ioda.o pci-ioda-tce.o obj-$(CONFIG_PCI_IOV) += pci-sriov.o -obj-$(CONFIG_CXL_BASE) += pci-cxl.o obj-$(CONFIG_EEH) += eeh-powernv.o obj-$(CONFIG_MEMORY_FAILURE) += opal-memory-errors.o obj-$(CONFIG_OPAL_PRD) += opal-prd.o
diff --git a/arch/powerpc/platforms/powernv/pci-cxl.c b/arch/powerpc/platforms/powernv/pci-cxl.c deleted file mode 100644 index 7e419de..0000000 --- a/arch/powerpc/platforms/powernv/pci-cxl.c +++ /dev/null
@@ -1,153 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Copyright 2014-2016 IBM Corp. - */ - -#include <linux/module.h> -#include <misc/cxl-base.h> -#include <asm/pnv-pci.h> -#include <asm/opal.h> - -#include "pci.h" - -int pnv_phb_to_cxl_mode(struct pci_dev *dev, uint64_t mode) -{ - struct pci_controller *hose = pci_bus_to_host(dev->bus); - struct pnv_phb *phb = hose->private_data; - struct pnv_ioda_pe *pe; - int rc; - - pe = pnv_ioda_get_pe(dev); - if (!pe) - return -ENODEV; - - pe_info(pe, "Switching PHB to CXL\n"); - - rc = opal_pci_set_phb_cxl_mode(phb->opal_id, mode, pe->pe_number); - if (rc == OPAL_UNSUPPORTED) - dev_err(&dev->dev, "Required cxl mode not supported by firmware - update skiboot\n"); - else if (rc) - dev_err(&dev->dev, "opal_pci_set_phb_cxl_mode failed: %i\n", rc); - - return rc; -} -EXPORT_SYMBOL(pnv_phb_to_cxl_mode); - -/* Find PHB for cxl dev and allocate MSI hwirqs? - * Returns the absolute hardware IRQ number - */ -int pnv_cxl_alloc_hwirqs(struct pci_dev *dev, int num) -{ - struct pci_controller *hose = pci_bus_to_host(dev->bus); - struct pnv_phb *phb = hose->private_data; - int hwirq = msi_bitmap_alloc_hwirqs(&phb->msi_bmp, num); - - if (hwirq < 0) { - dev_warn(&dev->dev, "Failed to find a free MSI\n"); - return -ENOSPC; - } - - return phb->msi_base + hwirq; -} -EXPORT_SYMBOL(pnv_cxl_alloc_hwirqs); - -void pnv_cxl_release_hwirqs(struct pci_dev *dev, int hwirq, int num) -{ - struct pci_controller *hose = pci_bus_to_host(dev->bus); - struct pnv_phb *phb = hose->private_data; - - msi_bitmap_free_hwirqs(&phb->msi_bmp, hwirq - phb->msi_base, num); -} -EXPORT_SYMBOL(pnv_cxl_release_hwirqs); - -void pnv_cxl_release_hwirq_ranges(struct cxl_irq_ranges *irqs, - struct pci_dev *dev) -{ - struct pci_controller *hose = pci_bus_to_host(dev->bus); - struct pnv_phb *phb = hose->private_data; - int i, hwirq; - - for (i = 1; i < CXL_IRQ_RANGES; i++) { - if (!irqs->range[i]) - continue; - pr_devel("cxl release irq range 0x%x: offset: 0x%lx limit: %ld\n", - i, irqs->offset[i], - irqs->range[i]); - hwirq = irqs->offset[i] - phb->msi_base; - msi_bitmap_free_hwirqs(&phb->msi_bmp, hwirq, - irqs->range[i]); - } -} -EXPORT_SYMBOL(pnv_cxl_release_hwirq_ranges); - -int pnv_cxl_alloc_hwirq_ranges(struct cxl_irq_ranges *irqs, - struct pci_dev *dev, int num) -{ - struct pci_controller *hose = pci_bus_to_host(dev->bus); - struct pnv_phb *phb = hose->private_data; - int i, hwirq, try; - - memset(irqs, 0, sizeof(struct cxl_irq_ranges)); - - /* 0 is reserved for the multiplexed PSL DSI interrupt */ - for (i = 1; i < CXL_IRQ_RANGES && num; i++) { - try = num; - while (try) { - hwirq = msi_bitmap_alloc_hwirqs(&phb->msi_bmp, try); - if (hwirq >= 0) - break; - try /= 2; - } - if (!try) - goto fail; - - irqs->offset[i] = phb->msi_base + hwirq; - irqs->range[i] = try; - pr_devel("cxl alloc irq range 0x%x: offset: 0x%lx limit: %li\n", - i, irqs->offset[i], irqs->range[i]); - num -= try; - } - if (num) - goto fail; - - return 0; -fail: - pnv_cxl_release_hwirq_ranges(irqs, dev); - return -ENOSPC; -} -EXPORT_SYMBOL(pnv_cxl_alloc_hwirq_ranges); - -int pnv_cxl_get_irq_count(struct pci_dev *dev) -{ - struct pci_controller *hose = pci_bus_to_host(dev->bus); - struct pnv_phb *phb = hose->private_data; - - return phb->msi_bmp.irq_count; -} -EXPORT_SYMBOL(pnv_cxl_get_irq_count); - -int pnv_cxl_ioda_msi_setup(struct pci_dev *dev, unsigned int hwirq, - unsigned int virq) -{ - struct pci_controller *hose = pci_bus_to_host(dev->bus); - struct pnv_phb *phb = hose->private_data; - unsigned int xive_num = hwirq - phb->msi_base; - struct pnv_ioda_pe *pe; - int rc; - - if (!(pe = pnv_ioda_get_pe(dev))) - return -ENODEV; - - /* Assign XIVE to PE */ - rc = opal_pci_set_xive_pe(phb->opal_id, pe->pe_number, xive_num); - if (rc) { - pe_warn(pe, "%s: OPAL error %d setting msi_base 0x%x " - "hwirq 0x%x XIVE 0x%x PE\n", - pci_name(dev), rc, phb->msi_base, hwirq, xive_num); - return -EIO; - } - pnv_set_msi_irq_chip(phb, virq); - - return 0; -} -EXPORT_SYMBOL(pnv_cxl_ioda_msi_setup);
diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index b0a14e4..ae4b549 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c
@@ -39,8 +39,6 @@ #include <asm/mmzone.h> #include <asm/xive.h> -#include <misc/cxl-base.h> - #include "powernv.h" #include "pci.h" #include "../../../../drivers/pci/pci.h" @@ -1636,47 +1634,6 @@ int64_t pnv_opal_pci_msi_eoi(struct irq_data *d) return opal_pci_msi_eoi(phb->opal_id, d->parent_data->hwirq); } -/* - * The IRQ data is mapped in the XICS domain, with OPAL HW IRQ numbers - */ -static void pnv_ioda2_msi_eoi(struct irq_data *d) -{ - int64_t rc; - unsigned int hw_irq = (unsigned int)irqd_to_hwirq(d); - struct pci_controller *hose = irq_data_get_irq_chip_data(d); - struct pnv_phb *phb = hose->private_data; - - rc = opal_pci_msi_eoi(phb->opal_id, hw_irq); - WARN_ON_ONCE(rc); - - icp_native_eoi(d); -} - -/* P8/CXL only */ -void pnv_set_msi_irq_chip(struct pnv_phb *phb, unsigned int virq) -{ - struct irq_data *idata; - struct irq_chip *ichip; - - /* The MSI EOI OPAL call is only needed on PHB3 */ - if (phb->model != PNV_PHB_MODEL_PHB3) - return; - - if (!phb->ioda.irq_chip_init) { - /* - * First time we setup an MSI IRQ, we need to setup the - * corresponding IRQ chip to route correctly. - */ - idata = irq_get_irq_data(virq); - ichip = irq_data_get_irq_chip(idata); - phb->ioda.irq_chip_init = 1; - phb->ioda.irq_chip = *ichip; - phb->ioda.irq_chip.irq_eoi = pnv_ioda2_msi_eoi; - } - irq_set_chip(virq, &phb->ioda.irq_chip); - irq_set_chip_data(virq, phb->hose); -} - static struct irq_chip pnv_pci_msi_irq_chip; /* @@ -1924,7 +1881,7 @@ static const struct irq_domain_ops pnv_irq_domain_ops = { static int __init pnv_msi_allocate_domains(struct pci_controller *hose, unsigned int count) { struct pnv_phb *phb = hose->private_data; - struct irq_domain *parent = irq_get_default_host(); + struct irq_domain *parent = irq_get_default_domain(); hose->fwnode = irq_domain_alloc_named_id_fwnode("PNV-MSI", phb->opal_id); if (!hose->fwnode)
diff --git a/arch/powerpc/platforms/powernv/pci.c b/arch/powerpc/platforms/powernv/pci.c index 35f566a..b2c1da0 100644 --- a/arch/powerpc/platforms/powernv/pci.c +++ b/arch/powerpc/platforms/powernv/pci.c
@@ -14,7 +14,6 @@ #include <linux/io.h> #include <linux/msi.h> #include <linux/iommu.h> -#include <linux/sched/mm.h> #include <asm/sections.h> #include <asm/io.h> @@ -33,8 +32,6 @@ #include "powernv.h" #include "pci.h" -static DEFINE_MUTEX(tunnel_mutex); - int pnv_pci_get_slot_id(struct device_node *np, uint64_t *id) { struct device_node *node = np; @@ -744,64 +741,6 @@ struct iommu_table *pnv_pci_table_alloc(int nid) return tbl; } -struct device_node *pnv_pci_get_phb_node(struct pci_dev *dev) -{ - struct pci_controller *hose = pci_bus_to_host(dev->bus); - - return of_node_get(hose->dn); -} -EXPORT_SYMBOL(pnv_pci_get_phb_node); - -int pnv_pci_set_tunnel_bar(struct pci_dev *dev, u64 addr, int enable) -{ - struct pnv_phb *phb = pci_bus_to_pnvhb(dev->bus); - u64 tunnel_bar; - __be64 val; - int rc; - - if (!opal_check_token(OPAL_PCI_GET_PBCQ_TUNNEL_BAR)) - return -ENXIO; - if (!opal_check_token(OPAL_PCI_SET_PBCQ_TUNNEL_BAR)) - return -ENXIO; - - mutex_lock(&tunnel_mutex); - rc = opal_pci_get_pbcq_tunnel_bar(phb->opal_id, &val); - if (rc != OPAL_SUCCESS) { - rc = -EIO; - goto out; - } - tunnel_bar = be64_to_cpu(val); - if (enable) { - /* - * Only one device per PHB can use atomics. - * Our policy is first-come, first-served. - */ - if (tunnel_bar) { - if (tunnel_bar != addr) - rc = -EBUSY; - else - rc = 0; /* Setting same address twice is ok */ - goto out; - } - } else { - /* - * The device that owns atomics and wants to release - * them must pass the same address with enable == 0. - */ - if (tunnel_bar != addr) { - rc = -EPERM; - goto out; - } - addr = 0x0ULL; - } - rc = opal_pci_set_pbcq_tunnel_bar(phb->opal_id, addr); - rc = opal_error_code(rc); -out: - mutex_unlock(&tunnel_mutex); - return rc; -} -EXPORT_SYMBOL_GPL(pnv_pci_set_tunnel_bar); - void pnv_pci_shutdown(void) { struct pci_controller *hose;
diff --git a/arch/powerpc/platforms/powernv/pci.h b/arch/powerpc/platforms/powernv/pci.h index 93fba1f..4207550 100644 --- a/arch/powerpc/platforms/powernv/pci.h +++ b/arch/powerpc/platforms/powernv/pci.h
@@ -163,7 +163,6 @@ struct pnv_phb { unsigned int *io_segmap; /* IRQ chip */ - int irq_chip_init; struct irq_chip irq_chip; /* Sorted list of used PE's based @@ -281,7 +280,6 @@ extern int pnv_eeh_phb_reset(struct pci_controller *hose, int option); extern struct pnv_ioda_pe *pnv_pci_bdfn_to_pe(struct pnv_phb *phb, u16 bdfn); extern struct pnv_ioda_pe *pnv_ioda_get_pe(struct pci_dev *dev); -extern void pnv_set_msi_irq_chip(struct pnv_phb *phb, unsigned int virq); extern unsigned long pnv_pci_ioda2_get_table_size(__u32 page_shift, __u64 window_size, __u32 levels); extern int pnv_eeh_post_init(void);
diff --git a/arch/powerpc/platforms/ps3/interrupt.c b/arch/powerpc/platforms/ps3/interrupt.c index af3fe9f0..95e96bd 100644 --- a/arch/powerpc/platforms/ps3/interrupt.c +++ b/arch/powerpc/platforms/ps3/interrupt.c
@@ -744,7 +744,7 @@ void __init ps3_init_IRQ(void) struct irq_domain *host; host = irq_domain_add_nomap(NULL, PS3_PLUG_MAX + 1, &ps3_host_ops, NULL); - irq_set_default_host(host); + irq_set_default_domain(host); for_each_possible_cpu(cpu) { struct ps3_private *pd = &per_cpu(ps3_private, cpu);
diff --git a/arch/powerpc/platforms/pseries/msi.c b/arch/powerpc/platforms/pseries/msi.c index fdc2f7f..f9d8011 100644 --- a/arch/powerpc/platforms/pseries/msi.c +++ b/arch/powerpc/platforms/pseries/msi.c
@@ -611,7 +611,7 @@ static const struct irq_domain_ops pseries_irq_domain_ops = { static int __pseries_msi_allocate_domains(struct pci_controller *phb, unsigned int count) { - struct irq_domain *parent = irq_get_default_host(); + struct irq_domain *parent = irq_get_default_domain(); phb->fwnode = irq_domain_alloc_named_id_fwnode("pSeries-MSI", phb->global_number);
diff --git a/arch/powerpc/sysdev/ehv_pic.c b/arch/powerpc/sysdev/ehv_pic.c index 0408276..fb502b7 100644 --- a/arch/powerpc/sysdev/ehv_pic.c +++ b/arch/powerpc/sysdev/ehv_pic.c
@@ -291,5 +291,5 @@ void __init ehv_pic_init(void) ehv_pic->coreint_flag = of_property_read_bool(np, "has-external-proxy"); global_ehv_pic = ehv_pic; - irq_set_default_host(global_ehv_pic->irqhost); + irq_set_default_domain(global_ehv_pic->irqhost); }
diff --git a/arch/powerpc/sysdev/ipic.c b/arch/powerpc/sysdev/ipic.c index 037b04b..a35be02 100644 --- a/arch/powerpc/sysdev/ipic.c +++ b/arch/powerpc/sysdev/ipic.c
@@ -757,7 +757,7 @@ struct ipic * __init ipic_init(struct device_node *node, unsigned int flags) ipic_write(ipic->regs, IPIC_SEMSR, temp); primary_ipic = ipic; - irq_set_default_host(primary_ipic->irqhost); + irq_set_default_domain(primary_ipic->irqhost); ipic_write(ipic->regs, IPIC_SIMSR_H, 0); ipic_write(ipic->regs, IPIC_SIMSR_L, 0);
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c index d94cf36..4afbab8 100644 --- a/arch/powerpc/sysdev/mpic.c +++ b/arch/powerpc/sysdev/mpic.c
@@ -1520,7 +1520,7 @@ struct mpic * __init mpic_alloc(struct device_node *node, if (!(mpic->flags & MPIC_SECONDARY)) { mpic_primary = mpic; - irq_set_default_host(mpic->irqhost); + irq_set_default_domain(mpic->irqhost); } return mpic;
diff --git a/arch/powerpc/sysdev/xics/xics-common.c b/arch/powerpc/sysdev/xics/xics-common.c index d3a4156..c3fa539 100644 --- a/arch/powerpc/sysdev/xics/xics-common.c +++ b/arch/powerpc/sysdev/xics/xics-common.c
@@ -472,7 +472,7 @@ static int __init xics_allocate_domain(void) return -ENOMEM; } - irq_set_default_host(xics_host); + irq_set_default_domain(xics_host); return 0; }
diff --git a/arch/powerpc/sysdev/xive/common.c b/arch/powerpc/sysdev/xive/common.c index a6c388b..dc2e618 100644 --- a/arch/powerpc/sysdev/xive/common.c +++ b/arch/powerpc/sysdev/xive/common.c
@@ -1467,7 +1467,7 @@ static void __init xive_init_host(struct device_node *np) xive_irq_domain = irq_domain_add_tree(np, &xive_irq_domain_ops, NULL); if (WARN_ON(xive_irq_domain == NULL)) return; - irq_set_default_host(xive_irq_domain); + irq_set_default_domain(xive_irq_domain); } static void xive_cleanup_cpu_queues(unsigned int cpu, struct xive_cpu *xc)
diff --git a/arch/riscv/Kbuild b/arch/riscv/Kbuild index 2c585f7..126fb73 100644 --- a/arch/riscv/Kbuild +++ b/arch/riscv/Kbuild
@@ -1,7 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-only obj-y += kernel/ mm/ net/ -obj-$(CONFIG_BUILTIN_DTB) += boot/dts/ obj-$(CONFIG_CRYPTO) += crypto/ obj-y += errata/ obj-$(CONFIG_KVM) += kvm/
diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig index e776fb3..bbec87b 100644 --- a/arch/riscv/Kconfig +++ b/arch/riscv/Kconfig
@@ -65,6 +65,7 @@ select ARCH_SUPPORTS_ATOMIC_RMW select ARCH_SUPPORTS_CFI_CLANG select ARCH_SUPPORTS_DEBUG_PAGEALLOC if MMU + select ARCH_SUPPORTS_HUGE_PFNMAP if TRANSPARENT_HUGEPAGE select ARCH_SUPPORTS_HUGETLBFS if MMU # LLD >= 14: https://github.com/llvm/llvm-project/issues/50505 select ARCH_SUPPORTS_LTO_CLANG if LLD_VERSION >= 140000 @@ -153,7 +154,7 @@ select HAVE_DYNAMIC_FTRACE_WITH_ARGS if HAVE_DYNAMIC_FTRACE select HAVE_FTRACE_GRAPH_FUNC select HAVE_FTRACE_MCOUNT_RECORD if !XIP_KERNEL - select HAVE_FUNCTION_GRAPH_TRACER + select HAVE_FUNCTION_GRAPH_TRACER if HAVE_DYNAMIC_FTRACE_WITH_ARGS select HAVE_FUNCTION_GRAPH_FREGS select HAVE_FUNCTION_TRACER if !XIP_KERNEL && !PREEMPTION select HAVE_EBPF_JIT if MMU @@ -205,6 +206,7 @@ select PCI_DOMAINS_GENERIC if PCI select PCI_ECAM if (ACPI && PCI) select PCI_MSI if PCI + select RELOCATABLE if !MMU && !PHYS_RAM_BASE_FIXED select RISCV_ALTERNATIVE if !XIP_KERNEL select RISCV_APLIC select RISCV_IMSIC @@ -292,13 +294,6 @@ Select if you want MMU-based virtualised addressing space support by paged memory management. If unsure, say 'Y'. -config PAGE_OFFSET - hex - default 0x80000000 if !MMU && RISCV_M_MODE - default 0x80200000 if !MMU - default 0xc0000000 if 32BIT - default 0xff60000000000000 if 64BIT - config KASAN_SHADOW_OFFSET hex depends on KASAN_GENERIC @@ -570,7 +565,8 @@ help Adds "C" to the ISA subsets that the toolchain is allowed to emit when building Linux, which results in compressed instructions in the - Linux binary. + Linux binary. This option produces a kernel that will not run on + systems that do not support compressed instructions. If you don't know what to do here, say Y. @@ -591,8 +587,8 @@ depends on RISCV_ALTERNATIVE default y help - Allow kernel to detect the Svnapot ISA-extension dynamically at boot - time and enable its usage. + Enable support for the Svnapot ISA-extension when it is detected + at boot. The Svnapot extension is used to mark contiguous PTEs as a range of contiguous virtual-to-physical translations for a naturally @@ -610,9 +606,8 @@ depends on RISCV_ALTERNATIVE default y help - Adds support to dynamically detect the presence of the Svpbmt - ISA-extension (Supervisor-mode: page-based memory types) and - enable its usage. + Add support for the Svpbmt ISA-extension (Supervisor-mode: + page-based memory types) in the kernel when it is detected at boot. The memory type for a page contains a combination of attributes that indicate the cacheability, idempotency, and ordering @@ -631,14 +626,15 @@ depends on AS_HAS_OPTION_ARCH config RISCV_ISA_V - bool "VECTOR extension support" + bool "Vector extension support" depends on TOOLCHAIN_HAS_V depends on FPU select DYNAMIC_SIGFRAME default y help - Say N here if you want to disable all vector related procedure - in the kernel. + Add support for the Vector extension when it is detected at boot. + When this option is disabled, neither the kernel nor userspace may + use vector procedures. If you don't know what to do here, say Y. @@ -737,6 +733,14 @@ def_bool $(as-instr, .option arch$(comma) +v$(comma) +zvkb) depends on AS_HAS_OPTION_ARCH +config TOOLCHAIN_HAS_ZBA + bool + default y + depends on !64BIT || $(cc-option,-mabi=lp64 -march=rv64ima_zba) + depends on !32BIT || $(cc-option,-mabi=ilp32 -march=rv32ima_zba) + depends on LLD_VERSION >= 150000 || LD_VERSION >= 23900 + depends on AS_HAS_OPTION_ARCH + config RISCV_ISA_ZBA bool "Zba extension support for bit manipulation instructions" default y @@ -751,12 +755,12 @@ config RISCV_ISA_ZBB bool "Zbb extension support for bit manipulation instructions" - depends on TOOLCHAIN_HAS_ZBB depends on RISCV_ALTERNATIVE default y help - Adds support to dynamically detect the presence of the ZBB - extension (basic bit manipulation) and enable its usage. + Add support for enabling optimisations in the kernel when the + Zbb extension is detected at boot. Some optimisations may + additionally depend on toolchain support for Zbb. The Zbb extension provides instructions to accelerate a number of bit-specific operations (count bit population, sign extending, @@ -787,6 +791,28 @@ If you don't know what to do here, say Y. +config TOOLCHAIN_HAS_ZBKB + bool + default y + depends on !64BIT || $(cc-option,-mabi=lp64 -march=rv64ima_zbkb) + depends on !32BIT || $(cc-option,-mabi=ilp32 -march=rv32ima_zbkb) + depends on LLD_VERSION >= 150000 || LD_VERSION >= 23900 + depends on AS_HAS_OPTION_ARCH + +config RISCV_ISA_ZBKB + bool "Zbkb extension support for bit manipulation instructions" + depends on TOOLCHAIN_HAS_ZBKB + depends on RISCV_ALTERNATIVE + default y + help + Adds support to dynamically detect the presence of the ZBKB + extension (bit manipulation for cryptography) and enable its usage. + + The Zbkb extension provides instructions to accelerate a number + of common cryptography operations (pack, zip, etc). + + If you don't know what to do here, say Y. + config RISCV_ISA_ZICBOM bool "Zicbom extension support for non-coherent DMA operation" depends on MMU @@ -795,9 +821,9 @@ select RISCV_DMA_NONCOHERENT select DMA_DIRECT_REMAP help - Adds support to dynamically detect the presence of the ZICBOM - extension (Cache Block Management Operations) and enable its - usage. + Add support for the Zicbom extension (Cache Block Management + Operations) and enable its use in the kernel when it is detected + at boot. The Zicbom extension can be used to handle for example non-coherent DMA support on devices that need it. @@ -810,7 +836,7 @@ default y help Enable the use of the Zicboz extension (cbo.zero instruction) - when available. + in the kernel when it is detected at boot. The Zicboz extension is used for faster zeroing of memory. @@ -848,8 +874,9 @@ bool "FPU support" default y help - Say N here if you want to disable all floating-point related procedure - in the kernel. + Add support for floating point operations when an FPU is detected at + boot. When this option is disabled, neither the kernel nor userspace + may use the floating point unit. If you don't know what to do here, say Y. @@ -1079,8 +1106,9 @@ config RELOCATABLE bool "Build a relocatable kernel" - depends on MMU && 64BIT && !XIP_KERNEL + depends on !XIP_KERNEL select MODULE_SECTIONS if MODULES + select ARCH_VMLINUX_NEEDS_RELOCS help This builds a kernel as a Position Independent Executable (PIE), which retains all relocation metadata required to relocate the @@ -1273,13 +1301,14 @@ config BUILTIN_DTB bool "Built-in device tree" depends on OF && NONPORTABLE + select GENERIC_BUILTIN_DTB help Build a device tree into the Linux image. This option should be selected if no bootloader is being used. If unsure, say N. -config BUILTIN_DTB_SOURCE +config BUILTIN_DTB_NAME string "Built-in device tree source" depends on BUILTIN_DTB help
diff --git a/arch/riscv/Kconfig.socs b/arch/riscv/Kconfig.socs index 1760694..8b503e5 100644 --- a/arch/riscv/Kconfig.socs +++ b/arch/riscv/Kconfig.socs
@@ -59,7 +59,6 @@ config ARCH_VIRT bool "QEMU Virt Machine" - select CLINT_TIMER if RISCV_M_MODE select POWER_RESET select POWER_RESET_SYSCON select POWER_RESET_SYSCON_POWEROFF @@ -79,7 +78,6 @@ config SOC_CANAAN_K210 bool "Canaan Kendryte K210 SoC" depends on !MMU && ARCH_CANAAN - select CLINT_TIMER if RISCV_M_MODE select ARCH_HAS_RESET_CONTROLLER select PINCTRL select COMMON_CLK
diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile index 13fbc0f..539d2ae 100644 --- a/arch/riscv/Makefile +++ b/arch/riscv/Makefile
@@ -8,7 +8,7 @@ LDFLAGS_vmlinux := -z norelro ifeq ($(CONFIG_RELOCATABLE),y) - LDFLAGS_vmlinux += -shared -Bsymbolic -z notext --emit-relocs + LDFLAGS_vmlinux += -shared -Bsymbolic -z notext KBUILD_CFLAGS += -fPIE endif ifeq ($(CONFIG_DYNAMIC_FTRACE),y) @@ -98,7 +98,6 @@ CC_FLAGS_FPU := -march=$(shell echo $(riscv-march-y) | sed -E 's/(rv32ima|rv64ima)([^v_]*)v?/\1\2/') KBUILD_CFLAGS += -mno-save-restore -KBUILD_CFLAGS += -DCONFIG_PAGE_OFFSET=$(CONFIG_PAGE_OFFSET) ifeq ($(CONFIG_CMODEL_MEDLOW),y) KBUILD_CFLAGS += -mcmodel=medlow
diff --git a/arch/riscv/Makefile.postlink b/arch/riscv/Makefile.postlink index 6b05809..0e4cf8a 100644 --- a/arch/riscv/Makefile.postlink +++ b/arch/riscv/Makefile.postlink
@@ -10,26 +10,17 @@ -include include/config/auto.conf include $(srctree)/scripts/Kbuild.include -include $(srctree)/scripts/Makefile.lib quiet_cmd_relocs_check = CHKREL $@ cmd_relocs_check = \ $(CONFIG_SHELL) $(srctree)/arch/riscv/tools/relocs_check.sh "$(OBJDUMP)" "$(NM)" "$@" -ifdef CONFIG_RELOCATABLE -quiet_cmd_cp_vmlinux_relocs = CPREL vmlinux.relocs -cmd_cp_vmlinux_relocs = cp vmlinux vmlinux.relocs - -endif - # `@true` prevents complaint when there is nothing to be done -vmlinux: FORCE +vmlinux vmlinux.unstripped: FORCE @true ifdef CONFIG_RELOCATABLE $(call if_changed,relocs_check) - $(call if_changed,cp_vmlinux_relocs) - $(call if_changed,strip_relocs) endif clean:
diff --git a/arch/riscv/boot/Makefile b/arch/riscv/boot/Makefile index b25d524..bfc3d0b 100644 --- a/arch/riscv/boot/Makefile +++ b/arch/riscv/boot/Makefile
@@ -32,10 +32,7 @@ endif ifdef CONFIG_RELOCATABLE -vmlinux.relocs: vmlinux - @ (! [ -f vmlinux.relocs ] && echo "vmlinux.relocs can't be found, please remove vmlinux and try again") || true - -$(obj)/Image: vmlinux.relocs FORCE +$(obj)/Image: vmlinux.unstripped FORCE else $(obj)/Image: vmlinux FORCE endif
diff --git a/arch/riscv/boot/dts/Makefile b/arch/riscv/boot/dts/Makefile index bff887d..64a898d 100644 --- a/arch/riscv/boot/dts/Makefile +++ b/arch/riscv/boot/dts/Makefile
@@ -8,5 +8,3 @@ subdir-y += spacemit subdir-y += starfive subdir-y += thead - -obj-$(CONFIG_BUILTIN_DTB) := $(addsuffix .dtb.o, $(CONFIG_BUILTIN_DTB_SOURCE))
diff --git a/arch/riscv/configs/defconfig b/arch/riscv/configs/defconfig index 0f7dcbe..3c8e16d 100644 --- a/arch/riscv/configs/defconfig +++ b/arch/riscv/configs/defconfig
@@ -26,7 +26,6 @@ # CONFIG_SYSFS_SYSCALL is not set CONFIG_PROFILING=y CONFIG_ARCH_MICROCHIP=y -CONFIG_ARCH_RENESAS=y CONFIG_ARCH_SIFIVE=y CONFIG_ARCH_SOPHGO=y CONFIG_ARCH_SPACEMIT=y @@ -202,7 +201,6 @@ CONFIG_USB_OTG=y CONFIG_USB_XHCI_HCD=y CONFIG_USB_XHCI_PLATFORM=y -# CONFIG_USB_XHCI_RCAR is not set CONFIG_USB_EHCI_HCD=y CONFIG_USB_EHCI_HCD_PLATFORM=y CONFIG_USB_OHCI_HCD=y
diff --git a/arch/riscv/configs/nommu_k210_defconfig b/arch/riscv/configs/nommu_k210_defconfig index 87ff5a1..ee18d1e 100644 --- a/arch/riscv/configs/nommu_k210_defconfig +++ b/arch/riscv/configs/nommu_k210_defconfig
@@ -35,7 +35,7 @@ CONFIG_CMDLINE="earlycon console=ttySIF0" CONFIG_CMDLINE_FORCE=y CONFIG_BUILTIN_DTB=y -CONFIG_BUILTIN_DTB_SOURCE="canaan/k210_generic" +CONFIG_BUILTIN_DTB_NAME="canaan/k210_generic" # CONFIG_SECCOMP is not set # CONFIG_STACKPROTECTOR is not set # CONFIG_GCC_PLUGINS is not set
diff --git a/arch/riscv/configs/nommu_k210_sdcard_defconfig b/arch/riscv/configs/nommu_k210_sdcard_defconfig index 95cbd57..e770d81 100644 --- a/arch/riscv/configs/nommu_k210_sdcard_defconfig +++ b/arch/riscv/configs/nommu_k210_sdcard_defconfig
@@ -27,7 +27,7 @@ CONFIG_CMDLINE="earlycon console=ttySIF0 root=/dev/mmcblk0p1 rootwait ro" CONFIG_CMDLINE_FORCE=y CONFIG_BUILTIN_DTB=y -CONFIG_BUILTIN_DTB_SOURCE="canaan/k210_generic" +CONFIG_BUILTIN_DTB_NAME="canaan/k210_generic" # CONFIG_SECCOMP is not set # CONFIG_STACKPROTECTOR is not set # CONFIG_GCC_PLUGINS is not set
diff --git a/arch/riscv/errata/Makefile b/arch/riscv/errata/Makefile index f0da9d7..bc6c77b 100644 --- a/arch/riscv/errata/Makefile +++ b/arch/riscv/errata/Makefile
@@ -1,5 +1,9 @@ ifdef CONFIG_RELOCATABLE -KBUILD_CFLAGS += -fno-pie +# We can't use PIC/PIE when handling early-boot errata parsing, as the kernel +# doesn't have a GOT setup at that point. So instead just use medany: it's +# usually position-independent, so it should be good enough for the errata +# handling. +KBUILD_CFLAGS += -fno-pie -mcmodel=medany endif ifdef CONFIG_RISCV_ALTERNATIVE_EARLY
diff --git a/arch/riscv/include/asm/arch_hweight.h b/arch/riscv/include/asm/arch_hweight.h index 613769b..0e7cdbb 100644 --- a/arch/riscv/include/asm/arch_hweight.h +++ b/arch/riscv/include/asm/arch_hweight.h
@@ -19,7 +19,7 @@ static __always_inline unsigned int __arch_hweight32(unsigned int w) { -#ifdef CONFIG_RISCV_ISA_ZBB +#if defined(CONFIG_RISCV_ISA_ZBB) && defined(CONFIG_TOOLCHAIN_HAS_ZBB) asm goto(ALTERNATIVE("j %l[legacy]", "nop", 0, RISCV_ISA_EXT_ZBB, 1) : : : : legacy); @@ -50,7 +50,7 @@ static inline unsigned int __arch_hweight8(unsigned int w) #if BITS_PER_LONG == 64 static __always_inline unsigned long __arch_hweight64(__u64 w) { -# ifdef CONFIG_RISCV_ISA_ZBB +#if defined(CONFIG_RISCV_ISA_ZBB) && defined(CONFIG_TOOLCHAIN_HAS_ZBB) asm goto(ALTERNATIVE("j %l[legacy]", "nop", 0, RISCV_ISA_EXT_ZBB, 1) : : : : legacy); @@ -64,7 +64,7 @@ static __always_inline unsigned long __arch_hweight64(__u64 w) return w; legacy: -# endif +#endif return __sw_hweight64(w); } #else /* BITS_PER_LONG == 64 */
diff --git a/arch/riscv/include/asm/asm.h b/arch/riscv/include/asm/asm.h index 7763548..a8a2af6 100644 --- a/arch/riscv/include/asm/asm.h +++ b/arch/riscv/include/asm/asm.h
@@ -27,6 +27,7 @@ #define REG_ASM __REG_SEL(.dword, .word) #define SZREG __REG_SEL(8, 4) #define LGREG __REG_SEL(3, 2) +#define SRLI __REG_SEL(srliw, srli) #if __SIZEOF_POINTER__ == 8 #ifdef __ASSEMBLY__
diff --git a/arch/riscv/include/asm/bitops.h b/arch/riscv/include/asm/bitops.h index 49a0f48d..d59310f 100644 --- a/arch/riscv/include/asm/bitops.h +++ b/arch/riscv/include/asm/bitops.h
@@ -15,7 +15,7 @@ #include <asm/barrier.h> #include <asm/bitsperlong.h> -#if !defined(CONFIG_RISCV_ISA_ZBB) || defined(NO_ALTERNATIVE) +#if !(defined(CONFIG_RISCV_ISA_ZBB) && defined(CONFIG_TOOLCHAIN_HAS_ZBB)) || defined(NO_ALTERNATIVE) #include <asm-generic/bitops/__ffs.h> #include <asm-generic/bitops/__fls.h> #include <asm-generic/bitops/ffs.h> @@ -175,7 +175,7 @@ static __always_inline int variable_fls(unsigned int x) variable_fls(x_); \ }) -#endif /* !defined(CONFIG_RISCV_ISA_ZBB) || defined(NO_ALTERNATIVE) */ +#endif /* !(defined(CONFIG_RISCV_ISA_ZBB) && defined(CONFIG_TOOLCHAIN_HAS_ZBB)) || defined(NO_ALTERNATIVE) */ #include <asm-generic/bitops/ffz.h> #include <asm-generic/bitops/fls64.h>
diff --git a/arch/riscv/include/asm/checksum.h b/arch/riscv/include/asm/checksum.h index 88e6f14..da37885 100644 --- a/arch/riscv/include/asm/checksum.h +++ b/arch/riscv/include/asm/checksum.h
@@ -49,8 +49,7 @@ static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl) * ZBB only saves three instructions on 32-bit and five on 64-bit so not * worth checking if supported without Alternatives. */ - if (IS_ENABLED(CONFIG_RISCV_ISA_ZBB) && - IS_ENABLED(CONFIG_RISCV_ALTERNATIVE)) { + if (IS_ENABLED(CONFIG_RISCV_ISA_ZBB) && IS_ENABLED(CONFIG_TOOLCHAIN_HAS_ZBB)) { unsigned long fold_temp; asm goto(ALTERNATIVE("j %l[no_zbb]", "nop", 0,
diff --git a/arch/riscv/include/asm/cmpxchg.h b/arch/riscv/include/asm/cmpxchg.h index 427c41d..2ec119e 100644 --- a/arch/riscv/include/asm/cmpxchg.h +++ b/arch/riscv/include/asm/cmpxchg.h
@@ -365,16 +365,48 @@ static __always_inline void __cmpwait(volatile void *ptr, { unsigned long tmp; + u32 *__ptr32b; + ulong __s, __val, __mask; + asm goto(ALTERNATIVE("j %l[no_zawrs]", "nop", 0, RISCV_ISA_EXT_ZAWRS, 1) : : : : no_zawrs); switch (size) { case 1: - fallthrough; + __ptr32b = (u32 *)((ulong)(ptr) & ~0x3); + __s = ((ulong)(ptr) & 0x3) * BITS_PER_BYTE; + __val = val << __s; + __mask = 0xff << __s; + + asm volatile( + " lr.w %0, %1\n" + " and %0, %0, %3\n" + " xor %0, %0, %2\n" + " bnez %0, 1f\n" + ZAWRS_WRS_NTO "\n" + "1:" + : "=&r" (tmp), "+A" (*(__ptr32b)) + : "r" (__val), "r" (__mask) + : "memory"); + break; case 2: - /* RISC-V doesn't have lr instructions on byte and half-word. */ - goto no_zawrs; + __ptr32b = (u32 *)((ulong)(ptr) & ~0x3); + __s = ((ulong)(ptr) & 0x2) * BITS_PER_BYTE; + __val = val << __s; + __mask = 0xffff << __s; + + asm volatile( + " lr.w %0, %1\n" + " and %0, %0, %3\n" + " xor %0, %0, %2\n" + " bnez %0, 1f\n" + ZAWRS_WRS_NTO "\n" + "1:" + : "=&r" (tmp), "+A" (*(__ptr32b)) + : "r" (__val), "r" (__mask) + : "memory"); + break; case 4: asm volatile( " lr.w %0, %1\n"
diff --git a/arch/riscv/include/asm/cpufeature.h b/arch/riscv/include/asm/cpufeature.h index 569140d..f56b409 100644 --- a/arch/riscv/include/asm/cpufeature.h +++ b/arch/riscv/include/asm/cpufeature.h
@@ -56,6 +56,9 @@ void __init riscv_user_isa_enable(void); #define __RISCV_ISA_EXT_BUNDLE(_name, _bundled_exts) \ _RISCV_ISA_EXT_DATA(_name, RISCV_ISA_EXT_INVALID, _bundled_exts, \ ARRAY_SIZE(_bundled_exts), NULL) +#define __RISCV_ISA_EXT_BUNDLE_VALIDATE(_name, _bundled_exts, _validate) \ + _RISCV_ISA_EXT_DATA(_name, RISCV_ISA_EXT_INVALID, _bundled_exts, \ + ARRAY_SIZE(_bundled_exts), _validate) /* Used to declare extensions that are a superset of other extensions (Zvbb for instance) */ #define __RISCV_ISA_EXT_SUPERSET(_name, _id, _sub_exts) \ @@ -63,7 +66,7 @@ void __init riscv_user_isa_enable(void); #define __RISCV_ISA_EXT_SUPERSET_VALIDATE(_name, _id, _sub_exts, _validate) \ _RISCV_ISA_EXT_DATA(_name, _id, _sub_exts, ARRAY_SIZE(_sub_exts), _validate) -bool check_unaligned_access_emulated_all_cpus(void); +bool __init check_unaligned_access_emulated_all_cpus(void); #if defined(CONFIG_RISCV_SCALAR_MISALIGNED) void check_unaligned_access_emulated(struct work_struct *work __always_unused); void unaligned_emulation_finish(void); @@ -76,7 +79,7 @@ static inline bool unaligned_ctl_available(void) } #endif -bool check_vector_unaligned_access_emulated_all_cpus(void); +bool __init check_vector_unaligned_access_emulated_all_cpus(void); #if defined(CONFIG_RISCV_VECTOR_MISALIGNED) void check_vector_unaligned_access_emulated(struct work_struct *work __always_unused); DECLARE_PER_CPU(long, vector_misaligned_access);
diff --git a/arch/riscv/include/asm/ftrace.h b/arch/riscv/include/asm/ftrace.h index c4721ce..d627f63 100644 --- a/arch/riscv/include/asm/ftrace.h +++ b/arch/riscv/include/asm/ftrace.h
@@ -79,7 +79,6 @@ struct dyn_arch_ftrace { #define AUIPC_RA (0x00000097) #define JALR_T0 (0x000282e7) #define AUIPC_T0 (0x00000297) -#define NOP4 (0x00000013) #define to_jalr_t0(offset) \ (((offset & JALR_OFFSET_MASK) << JALR_SHIFT) | JALR_T0) @@ -92,7 +91,7 @@ struct dyn_arch_ftrace { #define make_call_t0(caller, callee, call) \ do { \ unsigned int offset = \ - (unsigned long) callee - (unsigned long) caller; \ + (unsigned long) (callee) - (unsigned long) (caller); \ call[0] = to_auipc_t0(offset); \ call[1] = to_jalr_t0(offset); \ } while (0) @@ -108,7 +107,7 @@ do { \ #define make_call_ra(caller, callee, call) \ do { \ unsigned int offset = \ - (unsigned long) callee - (unsigned long) caller; \ + (unsigned long) (callee) - (unsigned long) (caller); \ call[0] = to_auipc_ra(offset); \ call[1] = to_jalr_ra(offset); \ } while (0) @@ -207,7 +206,7 @@ ftrace_partial_regs(const struct ftrace_regs *fregs, struct pt_regs *regs) { struct __arch_ftrace_regs *afregs = arch_ftrace_regs(fregs); - memcpy(®s->a0, afregs->args, sizeof(afregs->args)); + memcpy(®s->a_regs, afregs->args, sizeof(afregs->args)); regs->epc = afregs->epc; regs->ra = afregs->ra; regs->sp = afregs->sp;
diff --git a/arch/riscv/include/asm/hwcap.h b/arch/riscv/include/asm/hwcap.h index 869da08..e3cbf20 100644 --- a/arch/riscv/include/asm/hwcap.h +++ b/arch/riscv/include/asm/hwcap.h
@@ -100,6 +100,11 @@ #define RISCV_ISA_EXT_ZICCRSE 91 #define RISCV_ISA_EXT_SVADE 92 #define RISCV_ISA_EXT_SVADU 93 +#define RISCV_ISA_EXT_ZFBFMIN 94 +#define RISCV_ISA_EXT_ZVFBFMIN 95 +#define RISCV_ISA_EXT_ZVFBFWMA 96 +#define RISCV_ISA_EXT_ZAAMO 97 +#define RISCV_ISA_EXT_ZALRSC 98 #define RISCV_ISA_EXT_XLINUXENVCFG 127
diff --git a/arch/riscv/include/asm/hwprobe.h b/arch/riscv/include/asm/hwprobe.h index dd62452..1f690fe 100644 --- a/arch/riscv/include/asm/hwprobe.h +++ b/arch/riscv/include/asm/hwprobe.h
@@ -8,7 +8,7 @@ #include <uapi/asm/hwprobe.h> -#define RISCV_HWPROBE_MAX_KEY 11 +#define RISCV_HWPROBE_MAX_KEY 12 static inline bool riscv_hwprobe_key_is_valid(__s64 key) {
diff --git a/arch/riscv/include/asm/insn-def.h b/arch/riscv/include/asm/insn-def.h index 9a91301..71060a2 100644 --- a/arch/riscv/include/asm/insn-def.h +++ b/arch/riscv/include/asm/insn-def.h
@@ -199,5 +199,8 @@ #define RISCV_PAUSE ".4byte 0x100000f" #define ZAWRS_WRS_NTO ".4byte 0x00d00073" #define ZAWRS_WRS_STO ".4byte 0x01d00073" +#define RISCV_NOP4 ".4byte 0x00000013" + +#define RISCV_INSN_NOP4 _AC(0x00000013, U) #endif /* __ASM_INSN_DEF_H */
diff --git a/arch/riscv/include/asm/page.h b/arch/riscv/include/asm/page.h index 125f5ec..572a141 100644 --- a/arch/riscv/include/asm/page.h +++ b/arch/riscv/include/asm/page.h
@@ -24,21 +24,22 @@ * When not using MMU this corresponds to the first free page in * physical memory (aligned on a page boundary). */ -#ifdef CONFIG_64BIT #ifdef CONFIG_MMU -#define PAGE_OFFSET kernel_map.page_offset -#else -#define PAGE_OFFSET _AC(CONFIG_PAGE_OFFSET, UL) -#endif -/* - * By default, CONFIG_PAGE_OFFSET value corresponds to SV57 address space so - * define the PAGE_OFFSET value for SV48 and SV39. - */ +#ifdef CONFIG_64BIT +#define PAGE_OFFSET_L5 _AC(0xff60000000000000, UL) #define PAGE_OFFSET_L4 _AC(0xffffaf8000000000, UL) #define PAGE_OFFSET_L3 _AC(0xffffffd600000000, UL) +#ifdef CONFIG_XIP_KERNEL +#define PAGE_OFFSET PAGE_OFFSET_L3 #else -#define PAGE_OFFSET _AC(CONFIG_PAGE_OFFSET, UL) +#define PAGE_OFFSET kernel_map.page_offset +#endif /* CONFIG_XIP_KERNEL */ +#else +#define PAGE_OFFSET _AC(0xc0000000, UL) #endif /* CONFIG_64BIT */ +#else +#define PAGE_OFFSET ((unsigned long)phys_ram_base) +#endif /* CONFIG_MMU */ #ifndef __ASSEMBLY__ @@ -95,14 +96,9 @@ typedef struct page *pgtable_t; #define MIN_MEMBLOCK_ADDR 0 #endif -#ifdef CONFIG_MMU #define ARCH_PFN_OFFSET (PFN_DOWN((unsigned long)phys_ram_base)) -#else -#define ARCH_PFN_OFFSET (PAGE_OFFSET >> PAGE_SHIFT) -#endif /* CONFIG_MMU */ struct kernel_mapping { - unsigned long page_offset; unsigned long virt_addr; unsigned long virt_offset; uintptr_t phys_addr; @@ -116,6 +112,7 @@ struct kernel_mapping { uintptr_t xiprom; uintptr_t xiprom_sz; #else + unsigned long page_offset; unsigned long va_kernel_pa_offset; #endif };
diff --git a/arch/riscv/include/asm/pgalloc.h b/arch/riscv/include/asm/pgalloc.h index 3e2aebe..770ce18 100644 --- a/arch/riscv/include/asm/pgalloc.h +++ b/arch/riscv/include/asm/pgalloc.h
@@ -15,24 +15,6 @@ #define __HAVE_ARCH_PUD_FREE #include <asm-generic/pgalloc.h> -/* - * While riscv platforms with riscv_ipi_for_rfence as true require an IPI to - * perform TLB shootdown, some platforms with riscv_ipi_for_rfence as false use - * SBI to perform TLB shootdown. To keep software pagetable walkers safe in this - * case we switch to RCU based table free (MMU_GATHER_RCU_TABLE_FREE). See the - * comment below 'ifdef CONFIG_MMU_GATHER_RCU_TABLE_FREE' in include/asm-generic/tlb.h - * for more details. - */ -static inline void riscv_tlb_remove_ptdesc(struct mmu_gather *tlb, void *pt) -{ - if (riscv_use_sbi_for_rfence()) { - tlb_remove_ptdesc(tlb, pt); - } else { - pagetable_dtor(pt); - tlb_remove_page_ptdesc(tlb, pt); - } -} - static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd, pte_t *pte) { @@ -108,14 +90,14 @@ static inline void __pud_free_tlb(struct mmu_gather *tlb, pud_t *pud, unsigned long addr) { if (pgtable_l4_enabled) - riscv_tlb_remove_ptdesc(tlb, virt_to_ptdesc(pud)); + tlb_remove_ptdesc(tlb, virt_to_ptdesc(pud)); } static inline void __p4d_free_tlb(struct mmu_gather *tlb, p4d_t *p4d, unsigned long addr) { if (pgtable_l5_enabled) - riscv_tlb_remove_ptdesc(tlb, virt_to_ptdesc(p4d)); + tlb_remove_ptdesc(tlb, virt_to_ptdesc(p4d)); } #endif /* __PAGETABLE_PMD_FOLDED */ @@ -143,7 +125,7 @@ static inline pgd_t *pgd_alloc(struct mm_struct *mm) static inline void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd, unsigned long addr) { - riscv_tlb_remove_ptdesc(tlb, virt_to_ptdesc(pmd)); + tlb_remove_ptdesc(tlb, virt_to_ptdesc(pmd)); } #endif /* __PAGETABLE_PMD_FOLDED */ @@ -151,7 +133,7 @@ static inline void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd, static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte, unsigned long addr) { - riscv_tlb_remove_ptdesc(tlb, page_ptdesc(pte)); + tlb_remove_ptdesc(tlb, page_ptdesc(pte)); } #endif /* CONFIG_MMU */
diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h index 050fdc4..428e48e 100644 --- a/arch/riscv/include/asm/pgtable.h +++ b/arch/riscv/include/asm/pgtable.h
@@ -12,7 +12,11 @@ #include <asm/pgtable-bits.h> #ifndef CONFIG_MMU -#define KERNEL_LINK_ADDR PAGE_OFFSET +#ifdef CONFIG_RELOCATABLE +#define KERNEL_LINK_ADDR UL(0) +#else +#define KERNEL_LINK_ADDR _AC(CONFIG_PHYS_RAM_BASE, UL) +#endif #define KERN_VIRT_SIZE (UL(-1)) #else @@ -341,6 +345,14 @@ static inline pte_t pfn_pte(unsigned long pfn, pgprot_t prot) #define mk_pte(page, prot) pfn_pte(page_to_pfn(page), prot) +#define pte_pgprot pte_pgprot +static inline pgprot_t pte_pgprot(pte_t pte) +{ + unsigned long pfn = pte_pfn(pte); + + return __pgprot(pte_val(pfn_pte(pfn, __pgprot(0))) ^ pte_val(pte)); +} + static inline int pte_present(pte_t pte) { return (pte_val(pte) & (_PAGE_PRESENT | _PAGE_PROT_NONE)); @@ -674,6 +686,11 @@ static inline pmd_t pte_pmd(pte_t pte) return __pmd(pte_val(pte)); } +static inline pud_t pte_pud(pte_t pte) +{ + return __pud(pte_val(pte)); +} + static inline pmd_t pmd_mkhuge(pmd_t pmd) { return pmd; @@ -699,6 +716,18 @@ static inline unsigned long pud_pfn(pud_t pud) return ((__pud_to_phys(pud) & PUD_MASK) >> PAGE_SHIFT); } +#define pmd_pgprot pmd_pgprot +static inline pgprot_t pmd_pgprot(pmd_t pmd) +{ + return pte_pgprot(pmd_pte(pmd)); +} + +#define pud_pgprot pud_pgprot +static inline pgprot_t pud_pgprot(pud_t pud) +{ + return pte_pgprot(pud_pte(pud)); +} + static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot) { return pte_pmd(pte_modify(pmd_pte(pmd), newprot)); @@ -768,6 +797,30 @@ static inline pmd_t pmd_mkdevmap(pmd_t pmd) return pte_pmd(pte_mkdevmap(pmd_pte(pmd))); } +#ifdef CONFIG_ARCH_SUPPORTS_PMD_PFNMAP +static inline bool pmd_special(pmd_t pmd) +{ + return pte_special(pmd_pte(pmd)); +} + +static inline pmd_t pmd_mkspecial(pmd_t pmd) +{ + return pte_pmd(pte_mkspecial(pmd_pte(pmd))); +} +#endif + +#ifdef CONFIG_ARCH_SUPPORTS_PUD_PFNMAP +static inline bool pud_special(pud_t pud) +{ + return pte_special(pud_pte(pud)); +} + +static inline pud_t pud_mkspecial(pud_t pud) +{ + return pte_pud(pte_mkspecial(pud_pte(pud))); +} +#endif + static inline void set_pmd_at(struct mm_struct *mm, unsigned long addr, pmd_t *pmdp, pmd_t pmd) {
diff --git a/arch/riscv/include/asm/ptrace.h b/arch/riscv/include/asm/ptrace.h index b5b0adc..2910231 100644 --- a/arch/riscv/include/asm/ptrace.h +++ b/arch/riscv/include/asm/ptrace.h
@@ -23,14 +23,16 @@ struct pt_regs { unsigned long t2; unsigned long s0; unsigned long s1; - unsigned long a0; - unsigned long a1; - unsigned long a2; - unsigned long a3; - unsigned long a4; - unsigned long a5; - unsigned long a6; - unsigned long a7; + struct_group(a_regs, + unsigned long a0; + unsigned long a1; + unsigned long a2; + unsigned long a3; + unsigned long a4; + unsigned long a5; + unsigned long a6; + unsigned long a7; + ); unsigned long s2; unsigned long s3; unsigned long s4;
diff --git a/arch/riscv/include/asm/runtime-const.h b/arch/riscv/include/asm/runtime-const.h new file mode 100644 index 0000000..451fd76 --- /dev/null +++ b/arch/riscv/include/asm/runtime-const.h
@@ -0,0 +1,268 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_RISCV_RUNTIME_CONST_H +#define _ASM_RISCV_RUNTIME_CONST_H + +#include <asm/asm.h> +#include <asm/alternative.h> +#include <asm/cacheflush.h> +#include <asm/insn-def.h> +#include <linux/memory.h> +#include <asm/text-patching.h> + +#include <linux/uaccess.h> + +#ifdef CONFIG_32BIT +#define runtime_const_ptr(sym) \ +({ \ + typeof(sym) __ret; \ + asm_inline(".option push\n\t" \ + ".option norvc\n\t" \ + "1:\t" \ + "lui %[__ret],0x89abd\n\t" \ + "addi %[__ret],%[__ret],-0x211\n\t" \ + ".option pop\n\t" \ + ".pushsection runtime_ptr_" #sym ",\"a\"\n\t" \ + ".long 1b - .\n\t" \ + ".popsection" \ + : [__ret] "=r" (__ret)); \ + __ret; \ +}) +#else +/* + * Loading 64-bit constants into a register from immediates is a non-trivial + * task on riscv64. To get it somewhat performant, load 32 bits into two + * different registers and then combine the results. + * + * If the processor supports the Zbkb extension, we can combine the final + * "slli,slli,srli,add" into the single "pack" instruction. If the processor + * doesn't support Zbkb but does support the Zbb extension, we can + * combine the final "slli,srli,add" into one instruction "add.uw". + */ +#define RISCV_RUNTIME_CONST_64_PREAMBLE \ + ".option push\n\t" \ + ".option norvc\n\t" \ + "1:\t" \ + "lui %[__ret],0x89abd\n\t" \ + "lui %[__tmp],0x1234\n\t" \ + "addiw %[__ret],%[__ret],-0x211\n\t" \ + "addiw %[__tmp],%[__tmp],0x567\n\t" \ + +#define RISCV_RUNTIME_CONST_64_BASE \ + "slli %[__tmp],%[__tmp],32\n\t" \ + "slli %[__ret],%[__ret],32\n\t" \ + "srli %[__ret],%[__ret],32\n\t" \ + "add %[__ret],%[__ret],%[__tmp]\n\t" \ + +#define RISCV_RUNTIME_CONST_64_ZBA \ + ".option push\n\t" \ + ".option arch,+zba\n\t" \ + ".option norvc\n\t" \ + "slli %[__tmp],%[__tmp],32\n\t" \ + "add.uw %[__ret],%[__ret],%[__tmp]\n\t" \ + "nop\n\t" \ + "nop\n\t" \ + ".option pop\n\t" \ + +#define RISCV_RUNTIME_CONST_64_ZBKB \ + ".option push\n\t" \ + ".option arch,+zbkb\n\t" \ + ".option norvc\n\t" \ + "pack %[__ret],%[__ret],%[__tmp]\n\t" \ + "nop\n\t" \ + "nop\n\t" \ + "nop\n\t" \ + ".option pop\n\t" \ + +#define RISCV_RUNTIME_CONST_64_POSTAMBLE(sym) \ + ".option pop\n\t" \ + ".pushsection runtime_ptr_" #sym ",\"a\"\n\t" \ + ".long 1b - .\n\t" \ + ".popsection" \ + +#if defined(CONFIG_RISCV_ISA_ZBA) && defined(CONFIG_TOOLCHAIN_HAS_ZBA) \ + && defined(CONFIG_RISCV_ISA_ZBKB) +#define runtime_const_ptr(sym) \ +({ \ + typeof(sym) __ret, __tmp; \ + asm_inline(RISCV_RUNTIME_CONST_64_PREAMBLE \ + ALTERNATIVE_2( \ + RISCV_RUNTIME_CONST_64_BASE, \ + RISCV_RUNTIME_CONST_64_ZBA, \ + 0, RISCV_ISA_EXT_ZBA, 1, \ + RISCV_RUNTIME_CONST_64_ZBKB, \ + 0, RISCV_ISA_EXT_ZBKB, 1 \ + ) \ + RISCV_RUNTIME_CONST_64_POSTAMBLE(sym) \ + : [__ret] "=r" (__ret), [__tmp] "=r" (__tmp)); \ + __ret; \ +}) +#elif defined(CONFIG_RISCV_ISA_ZBA) && defined(CONFIG_TOOLCHAIN_HAS_ZBA) +#define runtime_const_ptr(sym) \ +({ \ + typeof(sym) __ret, __tmp; \ + asm_inline(RISCV_RUNTIME_CONST_64_PREAMBLE \ + ALTERNATIVE( \ + RISCV_RUNTIME_CONST_64_BASE, \ + RISCV_RUNTIME_CONST_64_ZBA, \ + 0, RISCV_ISA_EXT_ZBA, 1 \ + ) \ + RISCV_RUNTIME_CONST_64_POSTAMBLE(sym) \ + : [__ret] "=r" (__ret), [__tmp] "=r" (__tmp)); \ + __ret; \ +}) +#elif defined(CONFIG_RISCV_ISA_ZBKB) +#define runtime_const_ptr(sym) \ +({ \ + typeof(sym) __ret, __tmp; \ + asm_inline(RISCV_RUNTIME_CONST_64_PREAMBLE \ + ALTERNATIVE( \ + RISCV_RUNTIME_CONST_64_BASE, \ + RISCV_RUNTIME_CONST_64_ZBKB, \ + 0, RISCV_ISA_EXT_ZBKB, 1 \ + ) \ + RISCV_RUNTIME_CONST_64_POSTAMBLE(sym) \ + : [__ret] "=r" (__ret), [__tmp] "=r" (__tmp)); \ + __ret; \ +}) +#else +#define runtime_const_ptr(sym) \ +({ \ + typeof(sym) __ret, __tmp; \ + asm_inline(RISCV_RUNTIME_CONST_64_PREAMBLE \ + RISCV_RUNTIME_CONST_64_BASE \ + RISCV_RUNTIME_CONST_64_POSTAMBLE(sym) \ + : [__ret] "=r" (__ret), [__tmp] "=r" (__tmp)); \ + __ret; \ +}) +#endif +#endif + +#define runtime_const_shift_right_32(val, sym) \ +({ \ + u32 __ret; \ + asm_inline(".option push\n\t" \ + ".option norvc\n\t" \ + "1:\t" \ + SRLI " %[__ret],%[__val],12\n\t" \ + ".option pop\n\t" \ + ".pushsection runtime_shift_" #sym ",\"a\"\n\t" \ + ".long 1b - .\n\t" \ + ".popsection" \ + : [__ret] "=r" (__ret) \ + : [__val] "r" (val)); \ + __ret; \ +}) + +#define runtime_const_init(type, sym) do { \ + extern s32 __start_runtime_##type##_##sym[]; \ + extern s32 __stop_runtime_##type##_##sym[]; \ + \ + runtime_const_fixup(__runtime_fixup_##type, \ + (unsigned long)(sym), \ + __start_runtime_##type##_##sym, \ + __stop_runtime_##type##_##sym); \ +} while (0) + +static inline void __runtime_fixup_caches(void *where, unsigned int insns) +{ + /* On riscv there are currently only cache-wide flushes so va is ignored. */ + __always_unused uintptr_t va = (uintptr_t)where; + + flush_icache_range(va, va + 4 * insns); +} + +/* + * The 32-bit immediate is stored in a lui+addi pairing. + * lui holds the upper 20 bits of the immediate in the first 20 bits of the instruction. + * addi holds the lower 12 bits of the immediate in the first 12 bits of the instruction. + */ +static inline void __runtime_fixup_32(__le16 *lui_parcel, __le16 *addi_parcel, unsigned int val) +{ + unsigned int lower_immediate, upper_immediate; + u32 lui_insn, addi_insn, addi_insn_mask; + __le32 lui_res, addi_res; + + /* Mask out upper 12 bit of addi */ + addi_insn_mask = 0x000fffff; + + lui_insn = (u32)le16_to_cpu(lui_parcel[0]) | (u32)le16_to_cpu(lui_parcel[1]) << 16; + addi_insn = (u32)le16_to_cpu(addi_parcel[0]) | (u32)le16_to_cpu(addi_parcel[1]) << 16; + + lower_immediate = sign_extend32(val, 11); + upper_immediate = (val - lower_immediate); + + if (upper_immediate & 0xfffff000) { + /* replace upper 20 bits of lui with upper immediate */ + lui_insn &= 0x00000fff; + lui_insn |= upper_immediate & 0xfffff000; + } else { + /* replace lui with nop if immediate is small enough to fit in addi */ + lui_insn = RISCV_INSN_NOP4; + /* + * lui is being skipped, so do a load instead of an add. A load + * is performed by adding with the x0 register. Setting rs to + * zero with the following mask will accomplish this goal. + */ + addi_insn_mask &= 0x07fff; + } + + if (lower_immediate & 0x00000fff) { + /* replace upper 12 bits of addi with lower 12 bits of val */ + addi_insn &= addi_insn_mask; + addi_insn |= (lower_immediate & 0x00000fff) << 20; + } else { + /* replace addi with nop if lower_immediate is empty */ + addi_insn = RISCV_INSN_NOP4; + } + + addi_res = cpu_to_le32(addi_insn); + lui_res = cpu_to_le32(lui_insn); + mutex_lock(&text_mutex); + patch_insn_write(addi_parcel, &addi_res, sizeof(addi_res)); + patch_insn_write(lui_parcel, &lui_res, sizeof(lui_res)); + mutex_unlock(&text_mutex); +} + +static inline void __runtime_fixup_ptr(void *where, unsigned long val) +{ +#ifdef CONFIG_32BIT + __runtime_fixup_32(where, where + 4, val); + __runtime_fixup_caches(where, 2); +#else + __runtime_fixup_32(where, where + 8, val); + __runtime_fixup_32(where + 4, where + 12, val >> 32); + __runtime_fixup_caches(where, 4); +#endif +} + +/* + * Replace the least significant 5 bits of the srli/srliw immediate that is + * located at bits 20-24 + */ +static inline void __runtime_fixup_shift(void *where, unsigned long val) +{ + __le16 *parcel = where; + __le32 res; + u32 insn; + + insn = (u32)le16_to_cpu(parcel[0]) | (u32)le16_to_cpu(parcel[1]) << 16; + + insn &= 0xfe0fffff; + insn |= (val & 0b11111) << 20; + + res = cpu_to_le32(insn); + mutex_lock(&text_mutex); + patch_text_nosync(where, &res, sizeof(insn)); + mutex_unlock(&text_mutex); +} + +static inline void runtime_const_fixup(void (*fn)(void *, unsigned long), + unsigned long val, s32 *start, s32 *end) +{ + while (start < end) { + fn(*start + (void *)start, val); + start++; + } +} + +#endif /* _ASM_RISCV_RUNTIME_CONST_H */
diff --git a/arch/riscv/include/asm/suspend.h b/arch/riscv/include/asm/suspend.h index 4ffb022..dc5782b 100644 --- a/arch/riscv/include/asm/suspend.h +++ b/arch/riscv/include/asm/suspend.h
@@ -18,6 +18,10 @@ struct suspend_context { unsigned long ie; #ifdef CONFIG_MMU unsigned long satp; + unsigned long stimecmp; +#if __riscv_xlen < 64 + unsigned long stimecmph; +#endif #endif };
diff --git a/arch/riscv/include/uapi/asm/hwprobe.h b/arch/riscv/include/uapi/asm/hwprobe.h index c3c1cc9..3c2fce9 100644 --- a/arch/riscv/include/uapi/asm/hwprobe.h +++ b/arch/riscv/include/uapi/asm/hwprobe.h
@@ -73,6 +73,14 @@ struct riscv_hwprobe { #define RISCV_HWPROBE_EXT_ZCMOP (1ULL << 47) #define RISCV_HWPROBE_EXT_ZAWRS (1ULL << 48) #define RISCV_HWPROBE_EXT_SUPM (1ULL << 49) +#define RISCV_HWPROBE_EXT_ZICNTR (1ULL << 50) +#define RISCV_HWPROBE_EXT_ZIHPM (1ULL << 51) +#define RISCV_HWPROBE_EXT_ZFBFMIN (1ULL << 52) +#define RISCV_HWPROBE_EXT_ZVFBFMIN (1ULL << 53) +#define RISCV_HWPROBE_EXT_ZVFBFWMA (1ULL << 54) +#define RISCV_HWPROBE_EXT_ZICBOM (1ULL << 55) +#define RISCV_HWPROBE_EXT_ZAAMO (1ULL << 56) +#define RISCV_HWPROBE_EXT_ZALRSC (1ULL << 57) #define RISCV_HWPROBE_KEY_CPUPERF_0 5 #define RISCV_HWPROBE_MISALIGNED_UNKNOWN (0 << 0) #define RISCV_HWPROBE_MISALIGNED_EMULATED (1 << 0) @@ -95,6 +103,7 @@ struct riscv_hwprobe { #define RISCV_HWPROBE_MISALIGNED_VECTOR_FAST 3 #define RISCV_HWPROBE_MISALIGNED_VECTOR_UNSUPPORTED 4 #define RISCV_HWPROBE_KEY_VENDOR_EXT_THEAD_0 11 +#define RISCV_HWPROBE_KEY_ZICBOM_BLOCK_SIZE 12 /* Increase RISCV_HWPROBE_MAX_KEY when adding items. */ /* Flags */
diff --git a/arch/riscv/include/uapi/asm/kvm.h b/arch/riscv/include/uapi/asm/kvm.h index f06bc5e..5f59fd2 100644 --- a/arch/riscv/include/uapi/asm/kvm.h +++ b/arch/riscv/include/uapi/asm/kvm.h
@@ -182,6 +182,8 @@ enum KVM_RISCV_ISA_EXT_ID { KVM_RISCV_ISA_EXT_SVVPTC, KVM_RISCV_ISA_EXT_ZABHA, KVM_RISCV_ISA_EXT_ZICCRSE, + KVM_RISCV_ISA_EXT_ZAAMO, + KVM_RISCV_ISA_EXT_ZALRSC, KVM_RISCV_ISA_EXT_MAX, };
diff --git a/arch/riscv/kernel/asm-offsets.c b/arch/riscv/kernel/asm-offsets.c index e89455a..1649075 100644 --- a/arch/riscv/kernel/asm-offsets.c +++ b/arch/riscv/kernel/asm-offsets.c
@@ -36,7 +36,6 @@ void asm_offsets(void) OFFSET(TASK_THREAD_S11, task_struct, thread.s[11]); OFFSET(TASK_TI_CPU, task_struct, thread_info.cpu); - OFFSET(TASK_TI_FLAGS, task_struct, thread_info.flags); OFFSET(TASK_TI_PREEMPT_COUNT, task_struct, thread_info.preempt_count); OFFSET(TASK_TI_KERNEL_SP, task_struct, thread_info.kernel_sp); OFFSET(TASK_TI_USER_SP, task_struct, thread_info.user_sp);
diff --git a/arch/riscv/kernel/cpufeature.c b/arch/riscv/kernel/cpufeature.c index 40ac72e..2054f6c 100644 --- a/arch/riscv/kernel/cpufeature.c +++ b/arch/riscv/kernel/cpufeature.c
@@ -32,6 +32,7 @@ #define NUM_ALPHA_EXTS ('z' - 'a' + 1) static bool any_cpu_has_zicboz; +static bool any_cpu_has_zicbom; unsigned long elf_hwcap __read_mostly; @@ -53,9 +54,7 @@ u32 thead_vlenb_of; */ unsigned long riscv_isa_extension_base(const unsigned long *isa_bitmap) { - if (!isa_bitmap) - return riscv_isa[0]; - return isa_bitmap[0]; + return !isa_bitmap ? riscv_isa[0] : isa_bitmap[0]; } EXPORT_SYMBOL_GPL(riscv_isa_extension_base); @@ -76,10 +75,19 @@ bool __riscv_isa_extension_available(const unsigned long *isa_bitmap, unsigned i if (bit >= RISCV_ISA_EXT_MAX) return false; - return test_bit(bit, bmap) ? true : false; + return test_bit(bit, bmap); } EXPORT_SYMBOL_GPL(__riscv_isa_extension_available); +static int riscv_ext_f_depends(const struct riscv_isa_ext_data *data, + const unsigned long *isa_bitmap) +{ + if (__riscv_isa_extension_available(isa_bitmap, RISCV_ISA_EXT_f)) + return 0; + + return -EPROBE_DEFER; +} + static int riscv_ext_zicbom_validate(const struct riscv_isa_ext_data *data, const unsigned long *isa_bitmap) { @@ -91,6 +99,8 @@ static int riscv_ext_zicbom_validate(const struct riscv_isa_ext_data *data, pr_err("Zicbom disabled as cbom-block-size present, but is not a power-of-2\n"); return -EINVAL; } + + any_cpu_has_zicbom = true; return 0; } @@ -109,6 +119,82 @@ static int riscv_ext_zicboz_validate(const struct riscv_isa_ext_data *data, return 0; } +static int riscv_ext_f_validate(const struct riscv_isa_ext_data *data, + const unsigned long *isa_bitmap) +{ + if (!IS_ENABLED(CONFIG_FPU)) + return -EINVAL; + + /* + * Due to extension ordering, d is checked before f, so no deferral + * is required. + */ + if (!__riscv_isa_extension_available(isa_bitmap, RISCV_ISA_EXT_d)) { + pr_warn_once("This kernel does not support systems with F but not D\n"); + return -EINVAL; + } + + return 0; +} + +static int riscv_ext_d_validate(const struct riscv_isa_ext_data *data, + const unsigned long *isa_bitmap) +{ + if (!IS_ENABLED(CONFIG_FPU)) + return -EINVAL; + + return 0; +} + +static int riscv_ext_vector_x_validate(const struct riscv_isa_ext_data *data, + const unsigned long *isa_bitmap) +{ + if (!IS_ENABLED(CONFIG_RISCV_ISA_V)) + return -EINVAL; + + return 0; +} + +static int riscv_ext_vector_float_validate(const struct riscv_isa_ext_data *data, + const unsigned long *isa_bitmap) +{ + if (!IS_ENABLED(CONFIG_RISCV_ISA_V)) + return -EINVAL; + + if (!IS_ENABLED(CONFIG_FPU)) + return -EINVAL; + + /* + * The kernel doesn't support systems that don't implement both of + * F and D, so if any of the vector extensions that do floating point + * are to be usable, both floating point extensions need to be usable. + * + * Since this function validates vector only, and v/Zve* are probed + * after f/d, there's no need for a deferral here. + */ + if (!__riscv_isa_extension_available(isa_bitmap, RISCV_ISA_EXT_d)) + return -EINVAL; + + return 0; +} + +static int riscv_ext_vector_crypto_validate(const struct riscv_isa_ext_data *data, + const unsigned long *isa_bitmap) +{ + if (!IS_ENABLED(CONFIG_RISCV_ISA_V)) + return -EINVAL; + + /* + * It isn't the kernel's job to check that the binding is correct, so + * it should be enough to check that any of the vector extensions are + * enabled, which in-turn means that vector is usable in this kernel + */ + if (!__riscv_isa_extension_available(isa_bitmap, RISCV_ISA_EXT_ZVE32X)) + return -EPROBE_DEFER; + + return 0; +} + static int riscv_ext_zca_depends(const struct riscv_isa_ext_data *data, const unsigned long *isa_bitmap) { @@ -140,6 +226,28 @@ static int riscv_ext_zcf_validate(const struct riscv_isa_ext_data *data, return -EPROBE_DEFER; } +static int riscv_vector_f_validate(const struct riscv_isa_ext_data *data, + const unsigned long *isa_bitmap) +{ + if (!IS_ENABLED(CONFIG_RISCV_ISA_V)) + return -EINVAL; + + if (__riscv_isa_extension_available(isa_bitmap, RISCV_ISA_EXT_ZVE32F)) + return 0; + + return -EPROBE_DEFER; +} + +static int riscv_ext_zvfbfwma_validate(const struct riscv_isa_ext_data *data, + const unsigned long *isa_bitmap) +{ + if (__riscv_isa_extension_available(isa_bitmap, RISCV_ISA_EXT_ZFBFMIN) && + __riscv_isa_extension_available(isa_bitmap, RISCV_ISA_EXT_ZVFBFMIN)) + return 0; + + return -EPROBE_DEFER; +} + static int riscv_ext_svadu_validate(const struct riscv_isa_ext_data *data, const unsigned long *isa_bitmap) { @@ -150,6 +258,11 @@ static int riscv_ext_svadu_validate(const struct riscv_isa_ext_data *data, return 0; } +static const unsigned int riscv_a_exts[] = { + RISCV_ISA_EXT_ZAAMO, + RISCV_ISA_EXT_ZALRSC, +}; + static const unsigned int riscv_zk_bundled_exts[] = { RISCV_ISA_EXT_ZBKB, RISCV_ISA_EXT_ZBKC, @@ -321,17 +434,15 @@ static const unsigned int riscv_c_exts[] = { const struct riscv_isa_ext_data riscv_isa_ext[] = { __RISCV_ISA_EXT_DATA(i, RISCV_ISA_EXT_i), __RISCV_ISA_EXT_DATA(m, RISCV_ISA_EXT_m), - __RISCV_ISA_EXT_DATA(a, RISCV_ISA_EXT_a), - __RISCV_ISA_EXT_DATA(f, RISCV_ISA_EXT_f), - __RISCV_ISA_EXT_DATA(d, RISCV_ISA_EXT_d), + __RISCV_ISA_EXT_SUPERSET(a, RISCV_ISA_EXT_a, riscv_a_exts), + __RISCV_ISA_EXT_DATA_VALIDATE(f, RISCV_ISA_EXT_f, riscv_ext_f_validate), + __RISCV_ISA_EXT_DATA_VALIDATE(d, RISCV_ISA_EXT_d, riscv_ext_d_validate), __RISCV_ISA_EXT_DATA(q, RISCV_ISA_EXT_q), __RISCV_ISA_EXT_SUPERSET(c, RISCV_ISA_EXT_c, riscv_c_exts), - __RISCV_ISA_EXT_SUPERSET(v, RISCV_ISA_EXT_v, riscv_v_exts), + __RISCV_ISA_EXT_SUPERSET_VALIDATE(v, RISCV_ISA_EXT_v, riscv_v_exts, riscv_ext_vector_float_validate), __RISCV_ISA_EXT_DATA(h, RISCV_ISA_EXT_h), - __RISCV_ISA_EXT_SUPERSET_VALIDATE(zicbom, RISCV_ISA_EXT_ZICBOM, riscv_xlinuxenvcfg_exts, - riscv_ext_zicbom_validate), - __RISCV_ISA_EXT_SUPERSET_VALIDATE(zicboz, RISCV_ISA_EXT_ZICBOZ, riscv_xlinuxenvcfg_exts, - riscv_ext_zicboz_validate), + __RISCV_ISA_EXT_SUPERSET_VALIDATE(zicbom, RISCV_ISA_EXT_ZICBOM, riscv_xlinuxenvcfg_exts, riscv_ext_zicbom_validate), + __RISCV_ISA_EXT_SUPERSET_VALIDATE(zicboz, RISCV_ISA_EXT_ZICBOZ, riscv_xlinuxenvcfg_exts, riscv_ext_zicboz_validate), __RISCV_ISA_EXT_DATA(ziccrse, RISCV_ISA_EXT_ZICCRSE), __RISCV_ISA_EXT_DATA(zicntr, RISCV_ISA_EXT_ZICNTR), __RISCV_ISA_EXT_DATA(zicond, RISCV_ISA_EXT_ZICOND), @@ -341,10 +452,13 @@ const struct riscv_isa_ext_data riscv_isa_ext[] = { __RISCV_ISA_EXT_DATA(zihintpause, RISCV_ISA_EXT_ZIHINTPAUSE), __RISCV_ISA_EXT_DATA(zihpm, RISCV_ISA_EXT_ZIHPM), __RISCV_ISA_EXT_DATA(zimop, RISCV_ISA_EXT_ZIMOP), + __RISCV_ISA_EXT_DATA(zaamo, RISCV_ISA_EXT_ZAAMO), __RISCV_ISA_EXT_DATA(zabha, RISCV_ISA_EXT_ZABHA), __RISCV_ISA_EXT_DATA(zacas, RISCV_ISA_EXT_ZACAS), + __RISCV_ISA_EXT_DATA(zalrsc, RISCV_ISA_EXT_ZALRSC), __RISCV_ISA_EXT_DATA(zawrs, RISCV_ISA_EXT_ZAWRS), __RISCV_ISA_EXT_DATA(zfa, RISCV_ISA_EXT_ZFA), + __RISCV_ISA_EXT_DATA_VALIDATE(zfbfmin, RISCV_ISA_EXT_ZFBFMIN, riscv_ext_f_depends), __RISCV_ISA_EXT_DATA(zfh, RISCV_ISA_EXT_ZFH), __RISCV_ISA_EXT_DATA(zfhmin, RISCV_ISA_EXT_ZFHMIN), __RISCV_ISA_EXT_DATA(zca, RISCV_ISA_EXT_ZCA), @@ -370,29 +484,31 @@ const struct riscv_isa_ext_data riscv_isa_ext[] = { __RISCV_ISA_EXT_DATA(zksed, RISCV_ISA_EXT_ZKSED), __RISCV_ISA_EXT_DATA(zksh, RISCV_ISA_EXT_ZKSH), __RISCV_ISA_EXT_DATA(ztso, RISCV_ISA_EXT_ZTSO), - __RISCV_ISA_EXT_SUPERSET(zvbb, RISCV_ISA_EXT_ZVBB, riscv_zvbb_exts), - __RISCV_ISA_EXT_DATA(zvbc, RISCV_ISA_EXT_ZVBC), - __RISCV_ISA_EXT_SUPERSET(zve32f, RISCV_ISA_EXT_ZVE32F, riscv_zve32f_exts), - __RISCV_ISA_EXT_DATA(zve32x, RISCV_ISA_EXT_ZVE32X), - __RISCV_ISA_EXT_SUPERSET(zve64d, RISCV_ISA_EXT_ZVE64D, riscv_zve64d_exts), - __RISCV_ISA_EXT_SUPERSET(zve64f, RISCV_ISA_EXT_ZVE64F, riscv_zve64f_exts), - __RISCV_ISA_EXT_SUPERSET(zve64x, RISCV_ISA_EXT_ZVE64X, riscv_zve64x_exts), + __RISCV_ISA_EXT_SUPERSET_VALIDATE(zvbb, RISCV_ISA_EXT_ZVBB, riscv_zvbb_exts, riscv_ext_vector_crypto_validate), + __RISCV_ISA_EXT_DATA_VALIDATE(zvbc, RISCV_ISA_EXT_ZVBC, riscv_ext_vector_crypto_validate), + __RISCV_ISA_EXT_SUPERSET_VALIDATE(zve32f, RISCV_ISA_EXT_ZVE32F, riscv_zve32f_exts, riscv_ext_vector_float_validate), + __RISCV_ISA_EXT_DATA_VALIDATE(zve32x, RISCV_ISA_EXT_ZVE32X, riscv_ext_vector_x_validate), + __RISCV_ISA_EXT_SUPERSET_VALIDATE(zve64d, RISCV_ISA_EXT_ZVE64D, riscv_zve64d_exts, riscv_ext_vector_float_validate), + __RISCV_ISA_EXT_SUPERSET_VALIDATE(zve64f, RISCV_ISA_EXT_ZVE64F, riscv_zve64f_exts, riscv_ext_vector_float_validate), + __RISCV_ISA_EXT_SUPERSET_VALIDATE(zve64x, RISCV_ISA_EXT_ZVE64X, riscv_zve64x_exts, riscv_ext_vector_x_validate), + __RISCV_ISA_EXT_DATA_VALIDATE(zvfbfmin, RISCV_ISA_EXT_ZVFBFMIN, riscv_vector_f_validate), + __RISCV_ISA_EXT_DATA_VALIDATE(zvfbfwma, RISCV_ISA_EXT_ZVFBFWMA, riscv_ext_zvfbfwma_validate), __RISCV_ISA_EXT_DATA(zvfh, RISCV_ISA_EXT_ZVFH), __RISCV_ISA_EXT_DATA(zvfhmin, RISCV_ISA_EXT_ZVFHMIN), - __RISCV_ISA_EXT_DATA(zvkb, RISCV_ISA_EXT_ZVKB), - __RISCV_ISA_EXT_DATA(zvkg, RISCV_ISA_EXT_ZVKG), - __RISCV_ISA_EXT_BUNDLE(zvkn, riscv_zvkn_bundled_exts), - __RISCV_ISA_EXT_BUNDLE(zvknc, riscv_zvknc_bundled_exts), - __RISCV_ISA_EXT_DATA(zvkned, RISCV_ISA_EXT_ZVKNED), - __RISCV_ISA_EXT_BUNDLE(zvkng, riscv_zvkng_bundled_exts), - __RISCV_ISA_EXT_DATA(zvknha, RISCV_ISA_EXT_ZVKNHA), - __RISCV_ISA_EXT_DATA(zvknhb, RISCV_ISA_EXT_ZVKNHB), - __RISCV_ISA_EXT_BUNDLE(zvks, riscv_zvks_bundled_exts), - __RISCV_ISA_EXT_BUNDLE(zvksc, riscv_zvksc_bundled_exts), - __RISCV_ISA_EXT_DATA(zvksed, RISCV_ISA_EXT_ZVKSED), - __RISCV_ISA_EXT_DATA(zvksh, RISCV_ISA_EXT_ZVKSH), - __RISCV_ISA_EXT_BUNDLE(zvksg, riscv_zvksg_bundled_exts), - __RISCV_ISA_EXT_DATA(zvkt, RISCV_ISA_EXT_ZVKT), + __RISCV_ISA_EXT_DATA_VALIDATE(zvkb, RISCV_ISA_EXT_ZVKB, riscv_ext_vector_crypto_validate), + __RISCV_ISA_EXT_DATA_VALIDATE(zvkg, RISCV_ISA_EXT_ZVKG, riscv_ext_vector_crypto_validate), + __RISCV_ISA_EXT_BUNDLE_VALIDATE(zvkn, riscv_zvkn_bundled_exts, riscv_ext_vector_crypto_validate), + __RISCV_ISA_EXT_BUNDLE_VALIDATE(zvknc, riscv_zvknc_bundled_exts, riscv_ext_vector_crypto_validate), + __RISCV_ISA_EXT_DATA_VALIDATE(zvkned, RISCV_ISA_EXT_ZVKNED, riscv_ext_vector_crypto_validate), + __RISCV_ISA_EXT_BUNDLE_VALIDATE(zvkng, riscv_zvkng_bundled_exts, riscv_ext_vector_crypto_validate), + __RISCV_ISA_EXT_DATA_VALIDATE(zvknha, RISCV_ISA_EXT_ZVKNHA, riscv_ext_vector_crypto_validate), + __RISCV_ISA_EXT_DATA_VALIDATE(zvknhb, RISCV_ISA_EXT_ZVKNHB, riscv_ext_vector_crypto_validate), + __RISCV_ISA_EXT_BUNDLE_VALIDATE(zvks, riscv_zvks_bundled_exts, riscv_ext_vector_crypto_validate), + __RISCV_ISA_EXT_BUNDLE_VALIDATE(zvksc, riscv_zvksc_bundled_exts, riscv_ext_vector_crypto_validate), + __RISCV_ISA_EXT_DATA_VALIDATE(zvksed, RISCV_ISA_EXT_ZVKSED, riscv_ext_vector_crypto_validate), + __RISCV_ISA_EXT_DATA_VALIDATE(zvksh, RISCV_ISA_EXT_ZVKSH, riscv_ext_vector_crypto_validate), + __RISCV_ISA_EXT_BUNDLE_VALIDATE(zvksg, riscv_zvksg_bundled_exts, riscv_ext_vector_crypto_validate), + __RISCV_ISA_EXT_DATA_VALIDATE(zvkt, RISCV_ISA_EXT_ZVKT, riscv_ext_vector_crypto_validate), __RISCV_ISA_EXT_DATA(smaia, RISCV_ISA_EXT_SMAIA), __RISCV_ISA_EXT_DATA(smmpm, RISCV_ISA_EXT_SMMPM), __RISCV_ISA_EXT_SUPERSET(smnpm, RISCV_ISA_EXT_SMNPM, riscv_xlinuxenvcfg_exts), @@ -960,16 +1076,6 @@ void __init riscv_fill_hwcap(void) riscv_v_setup_vsize(); } - if (elf_hwcap & COMPAT_HWCAP_ISA_V) { - /* - * ISA string in device tree might have 'v' flag, but - * CONFIG_RISCV_ISA_V is disabled in kernel. - * Clear V flag in elf_hwcap if CONFIG_RISCV_ISA_V is disabled. - */ - if (!IS_ENABLED(CONFIG_RISCV_ISA_V)) - elf_hwcap &= ~COMPAT_HWCAP_ISA_V; - } - memset(print_str, 0, sizeof(print_str)); for (i = 0, j = 0; i < NUM_ALPHA_EXTS; i++) if (riscv_isa[0] & BIT_MASK(i)) @@ -1001,6 +1107,11 @@ void __init riscv_user_isa_enable(void) current->thread.envcfg |= ENVCFG_CBZE; else if (any_cpu_has_zicboz) pr_warn("Zicboz disabled as it is unavailable on some harts\n"); + + if (riscv_has_extension_unlikely(RISCV_ISA_EXT_ZICBOM)) + current->thread.envcfg |= ENVCFG_CBCFE; + else if (any_cpu_has_zicbom) + pr_warn("Zicbom disabled as it is unavailable on some harts\n"); } #ifdef CONFIG_RISCV_ALTERNATIVE
diff --git a/arch/riscv/kernel/elf_kexec.c b/arch/riscv/kernel/elf_kexec.c index 3c37661..e783a72 100644 --- a/arch/riscv/kernel/elf_kexec.c +++ b/arch/riscv/kernel/elf_kexec.c
@@ -468,6 +468,9 @@ int arch_kexec_apply_relocations_add(struct purgatory_info *pi, case R_RISCV_ALIGN: case R_RISCV_RELAX: break; + case R_RISCV_64: + *(u64 *)loc = val; + break; default: pr_err("Unknown rela relocation: %d\n", r_type); return -ENOEXEC;
diff --git a/arch/riscv/kernel/ftrace.c b/arch/riscv/kernel/ftrace.c index 3524db5..674dcdf 100644 --- a/arch/riscv/kernel/ftrace.c +++ b/arch/riscv/kernel/ftrace.c
@@ -36,7 +36,7 @@ static int ftrace_check_current_call(unsigned long hook_pos, unsigned int *expected) { unsigned int replaced[2]; - unsigned int nops[2] = {NOP4, NOP4}; + unsigned int nops[2] = {RISCV_INSN_NOP4, RISCV_INSN_NOP4}; /* we expect nops at the hook position */ if (!expected) @@ -68,7 +68,7 @@ static int __ftrace_modify_call(unsigned long hook_pos, unsigned long target, bool enable, bool ra) { unsigned int call[2]; - unsigned int nops[2] = {NOP4, NOP4}; + unsigned int nops[2] = {RISCV_INSN_NOP4, RISCV_INSN_NOP4}; if (ra) make_call_ra(hook_pos, target, call); @@ -97,7 +97,7 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) int ftrace_make_nop(struct module *mod, struct dyn_ftrace *rec, unsigned long addr) { - unsigned int nops[2] = {NOP4, NOP4}; + unsigned int nops[2] = {RISCV_INSN_NOP4, RISCV_INSN_NOP4}; if (patch_insn_write((void *)rec->ip, nops, MCOUNT_INSN_SIZE)) return -EPERM;
diff --git a/arch/riscv/kernel/jump_label.c b/arch/riscv/kernel/jump_label.c index 654ed15..b4c1a6a3 100644 --- a/arch/riscv/kernel/jump_label.c +++ b/arch/riscv/kernel/jump_label.c
@@ -11,8 +11,8 @@ #include <asm/bug.h> #include <asm/cacheflush.h> #include <asm/text-patching.h> +#include <asm/insn-def.h> -#define RISCV_INSN_NOP 0x00000013U #define RISCV_INSN_JAL 0x0000006fU bool arch_jump_label_transform_queue(struct jump_entry *entry, @@ -33,7 +33,7 @@ bool arch_jump_label_transform_queue(struct jump_entry *entry, (((u32)offset & GENMASK(10, 1)) << (21 - 1)) | (((u32)offset & GENMASK(20, 20)) << (31 - 20)); } else { - insn = RISCV_INSN_NOP; + insn = RISCV_INSN_NOP4; } if (early_boot_irqs_disabled) {
diff --git a/arch/riscv/kernel/mcount.S b/arch/riscv/kernel/mcount.S index 0681680..da4a400 100644 --- a/arch/riscv/kernel/mcount.S +++ b/arch/riscv/kernel/mcount.S
@@ -12,8 +12,6 @@ #include <asm/asm-offsets.h> #include <asm/ftrace.h> -#define ABI_SIZE_ON_STACK 80 - .text .macro SAVE_ABI_STATE @@ -28,12 +26,12 @@ * register if a0 was not saved. */ .macro SAVE_RET_ABI_STATE - addi sp, sp, -ABI_SIZE_ON_STACK - REG_S ra, 1*SZREG(sp) - REG_S s0, 8*SZREG(sp) - REG_S a0, 10*SZREG(sp) - REG_S a1, 11*SZREG(sp) - addi s0, sp, ABI_SIZE_ON_STACK + addi sp, sp, -FREGS_SIZE_ON_STACK + REG_S ra, FREGS_RA(sp) + REG_S s0, FREGS_S0(sp) + REG_S a0, FREGS_A0(sp) + REG_S a1, FREGS_A1(sp) + addi s0, sp, FREGS_SIZE_ON_STACK .endm .macro RESTORE_ABI_STATE @@ -43,11 +41,11 @@ .endm .macro RESTORE_RET_ABI_STATE - REG_L ra, 1*SZREG(sp) - REG_L s0, 8*SZREG(sp) - REG_L a0, 10*SZREG(sp) - REG_L a1, 11*SZREG(sp) - addi sp, sp, ABI_SIZE_ON_STACK + REG_L ra, FREGS_RA(sp) + REG_L s0, FREGS_S0(sp) + REG_L a0, FREGS_A0(sp) + REG_L a1, FREGS_A1(sp) + addi sp, sp, FREGS_SIZE_ON_STACK .endm SYM_TYPED_FUNC_START(ftrace_stub)
diff --git a/arch/riscv/kernel/setup.c b/arch/riscv/kernel/setup.c index 4fe45da..c174544 100644 --- a/arch/riscv/kernel/setup.c +++ b/arch/riscv/kernel/setup.c
@@ -235,11 +235,6 @@ static void __init parse_dtb(void) } else { pr_err("No DTB passed to the kernel\n"); } - -#ifdef CONFIG_CMDLINE_FORCE - strscpy(boot_command_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE); - pr_info("Forcing kernel command line to: %s\n", boot_command_line); -#endif } #if defined(CONFIG_RISCV_COMBO_SPINLOCKS)
diff --git a/arch/riscv/kernel/smp.c b/arch/riscv/kernel/smp.c index d58b5e7..e650dec 100644 --- a/arch/riscv/kernel/smp.c +++ b/arch/riscv/kernel/smp.c
@@ -48,6 +48,8 @@ EXPORT_SYMBOL_GPL(__cpuid_to_hartid_map); void __init smp_setup_processor_id(void) { cpuid_to_hartid_map(0) = boot_cpu_hartid; + + pr_info("Booting Linux on hartid %lu\n", boot_cpu_hartid); } static DEFINE_PER_CPU_READ_MOSTLY(int, ipi_dummy_dev);
diff --git a/arch/riscv/kernel/smpboot.c b/arch/riscv/kernel/smpboot.c index e36d202..601a321 100644 --- a/arch/riscv/kernel/smpboot.c +++ b/arch/riscv/kernel/smpboot.c
@@ -231,6 +231,10 @@ asmlinkage __visible void smp_callin(void) riscv_ipi_enable(); numa_add_cpu(curr_cpuid); + + pr_debug("CPU%u: Booted secondary hartid %lu\n", curr_cpuid, + cpuid_to_hartid_map(curr_cpuid)); + set_cpu_online(curr_cpuid, true); /*
diff --git a/arch/riscv/kernel/stacktrace.c b/arch/riscv/kernel/stacktrace.c index d4355c7..3fe9e6e 100644 --- a/arch/riscv/kernel/stacktrace.c +++ b/arch/riscv/kernel/stacktrace.c
@@ -74,7 +74,7 @@ void notrace walk_stackframe(struct task_struct *task, struct pt_regs *regs, &frame->ra); if (pc >= (unsigned long)handle_exception && pc < (unsigned long)&ret_from_exception_end) { - if (unlikely(!__kernel_text_address(pc) || !fn(arg, pc))) + if (unlikely(!fn(arg, pc))) break; pc = ((struct pt_regs *)sp)->epc;
diff --git a/arch/riscv/kernel/suspend.c b/arch/riscv/kernel/suspend.c index 9a8a0dc..24b3f57 100644 --- a/arch/riscv/kernel/suspend.c +++ b/arch/riscv/kernel/suspend.c
@@ -30,6 +30,13 @@ void suspend_save_csrs(struct suspend_context *context) */ #ifdef CONFIG_MMU + if (riscv_has_extension_unlikely(RISCV_ISA_EXT_SSTC)) { + context->stimecmp = csr_read(CSR_STIMECMP); +#if __riscv_xlen < 64 + context->stimecmph = csr_read(CSR_STIMECMPH); +#endif + } + context->satp = csr_read(CSR_SATP); #endif } @@ -43,6 +50,13 @@ void suspend_restore_csrs(struct suspend_context *context) csr_write(CSR_IE, context->ie); #ifdef CONFIG_MMU + if (riscv_has_extension_unlikely(RISCV_ISA_EXT_SSTC)) { + csr_write(CSR_STIMECMP, context->stimecmp); +#if __riscv_xlen < 64 + csr_write(CSR_STIMECMPH, context->stimecmph); +#endif + } + csr_write(CSR_SATP, context->satp); #endif }
diff --git a/arch/riscv/kernel/sys_hwprobe.c b/arch/riscv/kernel/sys_hwprobe.c index 04a4e54..249aec8 100644 --- a/arch/riscv/kernel/sys_hwprobe.c +++ b/arch/riscv/kernel/sys_hwprobe.c
@@ -95,7 +95,9 @@ static void hwprobe_isa_ext0(struct riscv_hwprobe *pair, * regardless of the kernel's configuration, as no other checks, besides * presence in the hart_isa bitmap, are made. */ + EXT_KEY(ZAAMO); EXT_KEY(ZACAS); + EXT_KEY(ZALRSC); EXT_KEY(ZAWRS); EXT_KEY(ZBA); EXT_KEY(ZBB); @@ -107,10 +109,13 @@ static void hwprobe_isa_ext0(struct riscv_hwprobe *pair, EXT_KEY(ZCA); EXT_KEY(ZCB); EXT_KEY(ZCMOP); + EXT_KEY(ZICBOM); EXT_KEY(ZICBOZ); + EXT_KEY(ZICNTR); EXT_KEY(ZICOND); EXT_KEY(ZIHINTNTL); EXT_KEY(ZIHINTPAUSE); + EXT_KEY(ZIHPM); EXT_KEY(ZIMOP); EXT_KEY(ZKND); EXT_KEY(ZKNE); @@ -132,6 +137,8 @@ static void hwprobe_isa_ext0(struct riscv_hwprobe *pair, EXT_KEY(ZVE64D); EXT_KEY(ZVE64F); EXT_KEY(ZVE64X); + EXT_KEY(ZVFBFMIN); + EXT_KEY(ZVFBFWMA); EXT_KEY(ZVFH); EXT_KEY(ZVFHMIN); EXT_KEY(ZVKB); @@ -148,6 +155,7 @@ static void hwprobe_isa_ext0(struct riscv_hwprobe *pair, EXT_KEY(ZCD); EXT_KEY(ZCF); EXT_KEY(ZFA); + EXT_KEY(ZFBFMIN); EXT_KEY(ZFH); EXT_KEY(ZFHMIN); } @@ -161,7 +169,7 @@ static void hwprobe_isa_ext0(struct riscv_hwprobe *pair, pair->value &= ~missing; } -static bool hwprobe_ext0_has(const struct cpumask *cpus, unsigned long ext) +static bool hwprobe_ext0_has(const struct cpumask *cpus, u64 ext) { struct riscv_hwprobe pair; @@ -279,6 +287,11 @@ static void hwprobe_one_pair(struct riscv_hwprobe *pair, if (hwprobe_ext0_has(cpus, RISCV_HWPROBE_EXT_ZICBOZ)) pair->value = riscv_cboz_block_size; break; + case RISCV_HWPROBE_KEY_ZICBOM_BLOCK_SIZE: + pair->value = 0; + if (hwprobe_ext0_has(cpus, RISCV_HWPROBE_EXT_ZICBOM)) + pair->value = riscv_cbom_block_size; + break; case RISCV_HWPROBE_KEY_HIGHEST_VIRT_ADDRESS: pair->value = user_max_virt_addr(); break;
diff --git a/arch/riscv/kernel/traps_misaligned.c b/arch/riscv/kernel/traps_misaligned.c index 7cc108a..4354c87 100644 --- a/arch/riscv/kernel/traps_misaligned.c +++ b/arch/riscv/kernel/traps_misaligned.c
@@ -605,16 +605,10 @@ void check_vector_unaligned_access_emulated(struct work_struct *work __always_un kernel_vector_end(); } -bool check_vector_unaligned_access_emulated_all_cpus(void) +bool __init check_vector_unaligned_access_emulated_all_cpus(void) { int cpu; - if (!has_vector()) { - for_each_online_cpu(cpu) - per_cpu(vector_misaligned_access, cpu) = RISCV_HWPROBE_MISALIGNED_VECTOR_UNSUPPORTED; - return false; - } - schedule_on_each_cpu(check_vector_unaligned_access_emulated); for_each_online_cpu(cpu) @@ -625,7 +619,7 @@ bool check_vector_unaligned_access_emulated_all_cpus(void) return true; } #else -bool check_vector_unaligned_access_emulated_all_cpus(void) +bool __init check_vector_unaligned_access_emulated_all_cpus(void) { return false; } @@ -659,7 +653,7 @@ void check_unaligned_access_emulated(struct work_struct *work __always_unused) } } -bool check_unaligned_access_emulated_all_cpus(void) +bool __init check_unaligned_access_emulated_all_cpus(void) { int cpu; @@ -684,7 +678,7 @@ bool unaligned_ctl_available(void) return unaligned_ctl; } #else -bool check_unaligned_access_emulated_all_cpus(void) +bool __init check_unaligned_access_emulated_all_cpus(void) { return false; }
diff --git a/arch/riscv/kernel/unaligned_access_speed.c b/arch/riscv/kernel/unaligned_access_speed.c index 91f189c..585d2dc 100644 --- a/arch/riscv/kernel/unaligned_access_speed.c +++ b/arch/riscv/kernel/unaligned_access_speed.c
@@ -24,8 +24,12 @@ DEFINE_PER_CPU(long, misaligned_access_speed) = RISCV_HWPROBE_MISALIGNED_SCALAR_UNKNOWN; DEFINE_PER_CPU(long, vector_misaligned_access) = RISCV_HWPROBE_MISALIGNED_VECTOR_UNSUPPORTED; -#ifdef CONFIG_RISCV_PROBE_UNALIGNED_ACCESS +static long unaligned_scalar_speed_param = RISCV_HWPROBE_MISALIGNED_SCALAR_UNKNOWN; +static long unaligned_vector_speed_param = RISCV_HWPROBE_MISALIGNED_VECTOR_UNKNOWN; + static cpumask_t fast_misaligned_access; + +#ifdef CONFIG_RISCV_PROBE_UNALIGNED_ACCESS static int check_unaligned_access(void *param) { int cpu = smp_processor_id(); @@ -121,7 +125,7 @@ static int check_unaligned_access(void *param) return 0; } -static void check_unaligned_access_nonboot_cpu(void *param) +static void __init check_unaligned_access_nonboot_cpu(void *param) { unsigned int cpu = smp_processor_id(); struct page **pages = param; @@ -130,6 +134,50 @@ static void check_unaligned_access_nonboot_cpu(void *param) check_unaligned_access(pages[cpu]); } +/* Measure unaligned access speed on all CPUs present at boot in parallel. */ +static void __init check_unaligned_access_speed_all_cpus(void) +{ + unsigned int cpu; + unsigned int cpu_count = num_possible_cpus(); + struct page **bufs = kcalloc(cpu_count, sizeof(*bufs), GFP_KERNEL); + + if (!bufs) { + pr_warn("Allocation failure, not measuring misaligned performance\n"); + return; + } + + /* + * Allocate separate buffers for each CPU so there's no fighting over + * cache lines. + */ + for_each_cpu(cpu, cpu_online_mask) { + bufs[cpu] = alloc_pages(GFP_KERNEL, MISALIGNED_BUFFER_ORDER); + if (!bufs[cpu]) { + pr_warn("Allocation failure, not measuring misaligned performance\n"); + goto out; + } + } + + /* Check everybody except 0, who stays behind to tend jiffies. */ + on_each_cpu(check_unaligned_access_nonboot_cpu, bufs, 1); + + /* Check core 0. */ + smp_call_on_cpu(0, check_unaligned_access, bufs[0], true); + +out: + for_each_cpu(cpu, cpu_online_mask) { + if (bufs[cpu]) + __free_pages(bufs[cpu], MISALIGNED_BUFFER_ORDER); + } + + kfree(bufs); +} +#else /* CONFIG_RISCV_PROBE_UNALIGNED_ACCESS */ +static void __init check_unaligned_access_speed_all_cpus(void) +{ +} +#endif + DEFINE_STATIC_KEY_FALSE(fast_unaligned_access_speed_key); static void modify_unaligned_access_branches(cpumask_t *mask, int weight) @@ -175,7 +223,7 @@ static void set_unaligned_access_static_branches(void) modify_unaligned_access_branches(&fast_and_online, num_online_cpus()); } -static int lock_and_set_unaligned_access_static_branch(void) +static int __init lock_and_set_unaligned_access_static_branch(void) { cpus_read_lock(); set_unaligned_access_static_branches(); @@ -188,21 +236,29 @@ arch_initcall_sync(lock_and_set_unaligned_access_static_branch); static int riscv_online_cpu(unsigned int cpu) { - static struct page *buf; - /* We are already set since the last check */ - if (per_cpu(misaligned_access_speed, cpu) != RISCV_HWPROBE_MISALIGNED_SCALAR_UNKNOWN) + if (per_cpu(misaligned_access_speed, cpu) != RISCV_HWPROBE_MISALIGNED_SCALAR_UNKNOWN) { goto exit; - - check_unaligned_access_emulated(NULL); - buf = alloc_pages(GFP_KERNEL, MISALIGNED_BUFFER_ORDER); - if (!buf) { - pr_warn("Allocation failure, not measuring misaligned performance\n"); - return -ENOMEM; + } else if (unaligned_scalar_speed_param != RISCV_HWPROBE_MISALIGNED_SCALAR_UNKNOWN) { + per_cpu(misaligned_access_speed, cpu) = unaligned_scalar_speed_param; + goto exit; } - check_unaligned_access(buf); - __free_pages(buf, MISALIGNED_BUFFER_ORDER); +#ifdef CONFIG_RISCV_PROBE_UNALIGNED_ACCESS + { + static struct page *buf; + + check_unaligned_access_emulated(NULL); + buf = alloc_pages(GFP_KERNEL, MISALIGNED_BUFFER_ORDER); + if (!buf) { + pr_warn("Allocation failure, not measuring misaligned performance\n"); + return -ENOMEM; + } + + check_unaligned_access(buf); + __free_pages(buf, MISALIGNED_BUFFER_ORDER); + } +#endif exit: set_unaligned_access_static_branches(); @@ -217,59 +273,6 @@ static int riscv_offline_cpu(unsigned int cpu) return 0; } -/* Measure unaligned access speed on all CPUs present at boot in parallel. */ -static int check_unaligned_access_speed_all_cpus(void) -{ - unsigned int cpu; - unsigned int cpu_count = num_possible_cpus(); - struct page **bufs = kcalloc(cpu_count, sizeof(*bufs), GFP_KERNEL); - - if (!bufs) { - pr_warn("Allocation failure, not measuring misaligned performance\n"); - return 0; - } - - /* - * Allocate separate buffers for each CPU so there's no fighting over - * cache lines. - */ - for_each_cpu(cpu, cpu_online_mask) { - bufs[cpu] = alloc_pages(GFP_KERNEL, MISALIGNED_BUFFER_ORDER); - if (!bufs[cpu]) { - pr_warn("Allocation failure, not measuring misaligned performance\n"); - goto out; - } - } - - /* Check everybody except 0, who stays behind to tend jiffies. */ - on_each_cpu(check_unaligned_access_nonboot_cpu, bufs, 1); - - /* Check core 0. */ - smp_call_on_cpu(0, check_unaligned_access, bufs[0], true); - - /* - * Setup hotplug callbacks for any new CPUs that come online or go - * offline. - */ - cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN, "riscv:online", - riscv_online_cpu, riscv_offline_cpu); - -out: - for_each_cpu(cpu, cpu_online_mask) { - if (bufs[cpu]) - __free_pages(bufs[cpu], MISALIGNED_BUFFER_ORDER); - } - - kfree(bufs); - return 0; -} -#else /* CONFIG_RISCV_PROBE_UNALIGNED_ACCESS */ -static int check_unaligned_access_speed_all_cpus(void) -{ - return 0; -} -#endif - #ifdef CONFIG_RISCV_PROBE_VECTOR_UNALIGNED_ACCESS static void check_vector_unaligned_access(struct work_struct *work __always_unused) { @@ -349,7 +352,7 @@ static void check_vector_unaligned_access(struct work_struct *work __always_unus pr_warn("cpu%d: rdtime lacks granularity needed to measure unaligned vector access speed\n", cpu); - return; + goto free; } if (word_cycles < byte_cycles) @@ -363,59 +366,114 @@ static void check_vector_unaligned_access(struct work_struct *work __always_unus (speed == RISCV_HWPROBE_MISALIGNED_VECTOR_FAST) ? "fast" : "slow"); per_cpu(vector_misaligned_access, cpu) = speed; + +free: + __free_pages(page, MISALIGNED_BUFFER_ORDER); } +/* Measure unaligned access speed on all CPUs present at boot in parallel. */ +static int __init vec_check_unaligned_access_speed_all_cpus(void *unused __always_unused) +{ + schedule_on_each_cpu(check_vector_unaligned_access); + + return 0; +} +#else /* CONFIG_RISCV_PROBE_VECTOR_UNALIGNED_ACCESS */ +static int __init vec_check_unaligned_access_speed_all_cpus(void *unused __always_unused) +{ + return 0; +} +#endif + static int riscv_online_cpu_vec(unsigned int cpu) { - if (!has_vector()) + if (unaligned_vector_speed_param != RISCV_HWPROBE_MISALIGNED_VECTOR_UNKNOWN) { + per_cpu(vector_misaligned_access, cpu) = unaligned_vector_speed_param; return 0; + } - if (per_cpu(vector_misaligned_access, cpu) != RISCV_HWPROBE_MISALIGNED_VECTOR_UNSUPPORTED) +#ifdef CONFIG_RISCV_PROBE_VECTOR_UNALIGNED_ACCESS + if (per_cpu(vector_misaligned_access, cpu) != RISCV_HWPROBE_MISALIGNED_VECTOR_UNKNOWN) return 0; check_vector_unaligned_access_emulated(NULL); check_vector_unaligned_access(NULL); +#endif + return 0; } -/* Measure unaligned access speed on all CPUs present at boot in parallel. */ -static int vec_check_unaligned_access_speed_all_cpus(void *unused __always_unused) +static const char * const speed_str[] __initconst = { NULL, NULL, "slow", "fast", "unsupported" }; + +static int __init set_unaligned_scalar_speed_param(char *str) { - schedule_on_each_cpu(check_vector_unaligned_access); + if (!strcmp(str, speed_str[RISCV_HWPROBE_MISALIGNED_SCALAR_SLOW])) + unaligned_scalar_speed_param = RISCV_HWPROBE_MISALIGNED_SCALAR_SLOW; + else if (!strcmp(str, speed_str[RISCV_HWPROBE_MISALIGNED_SCALAR_FAST])) + unaligned_scalar_speed_param = RISCV_HWPROBE_MISALIGNED_SCALAR_FAST; + else if (!strcmp(str, speed_str[RISCV_HWPROBE_MISALIGNED_SCALAR_UNSUPPORTED])) + unaligned_scalar_speed_param = RISCV_HWPROBE_MISALIGNED_SCALAR_UNSUPPORTED; + else + return -EINVAL; + + return 1; +} +__setup("unaligned_scalar_speed=", set_unaligned_scalar_speed_param); + +static int __init set_unaligned_vector_speed_param(char *str) +{ + if (!strcmp(str, speed_str[RISCV_HWPROBE_MISALIGNED_VECTOR_SLOW])) + unaligned_vector_speed_param = RISCV_HWPROBE_MISALIGNED_VECTOR_SLOW; + else if (!strcmp(str, speed_str[RISCV_HWPROBE_MISALIGNED_VECTOR_FAST])) + unaligned_vector_speed_param = RISCV_HWPROBE_MISALIGNED_VECTOR_FAST; + else if (!strcmp(str, speed_str[RISCV_HWPROBE_MISALIGNED_VECTOR_UNSUPPORTED])) + unaligned_vector_speed_param = RISCV_HWPROBE_MISALIGNED_VECTOR_UNSUPPORTED; + else + return -EINVAL; + + return 1; +} +__setup("unaligned_vector_speed=", set_unaligned_vector_speed_param); + +static int __init check_unaligned_access_all_cpus(void) +{ + int cpu; + + if (unaligned_scalar_speed_param == RISCV_HWPROBE_MISALIGNED_SCALAR_UNKNOWN && + !check_unaligned_access_emulated_all_cpus()) { + check_unaligned_access_speed_all_cpus(); + } else { + pr_info("scalar unaligned access speed set to '%s' by command line\n", + speed_str[unaligned_scalar_speed_param]); + for_each_online_cpu(cpu) + per_cpu(misaligned_access_speed, cpu) = unaligned_scalar_speed_param; + } + + if (!has_vector()) + unaligned_vector_speed_param = RISCV_HWPROBE_MISALIGNED_VECTOR_UNSUPPORTED; + + if (unaligned_vector_speed_param == RISCV_HWPROBE_MISALIGNED_VECTOR_UNKNOWN && + !check_vector_unaligned_access_emulated_all_cpus() && + IS_ENABLED(CONFIG_RISCV_PROBE_VECTOR_UNALIGNED_ACCESS)) { + kthread_run(vec_check_unaligned_access_speed_all_cpus, + NULL, "vec_check_unaligned_access_speed_all_cpus"); + } else { + pr_info("vector unaligned access speed set to '%s' by command line\n", + speed_str[unaligned_vector_speed_param]); + for_each_online_cpu(cpu) + per_cpu(vector_misaligned_access, cpu) = unaligned_vector_speed_param; + } /* * Setup hotplug callbacks for any new CPUs that come online or go * offline. */ cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN, "riscv:online", + riscv_online_cpu, riscv_offline_cpu); + cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN, "riscv:online", riscv_online_cpu_vec, NULL); return 0; } -#else /* CONFIG_RISCV_PROBE_VECTOR_UNALIGNED_ACCESS */ -static int vec_check_unaligned_access_speed_all_cpus(void *unused __always_unused) -{ - return 0; -} -#endif - -static int check_unaligned_access_all_cpus(void) -{ - bool all_cpus_emulated, all_cpus_vec_unsupported; - - all_cpus_emulated = check_unaligned_access_emulated_all_cpus(); - all_cpus_vec_unsupported = check_vector_unaligned_access_emulated_all_cpus(); - - if (!all_cpus_vec_unsupported && - IS_ENABLED(CONFIG_RISCV_PROBE_VECTOR_UNALIGNED_ACCESS)) { - kthread_run(vec_check_unaligned_access_speed_all_cpus, - NULL, "vec_check_unaligned_access_speed_all_cpus"); - } - - if (!all_cpus_emulated) - return check_unaligned_access_speed_all_cpus(); - - return 0; -} arch_initcall(check_unaligned_access_all_cpus);
diff --git a/arch/riscv/kernel/vec-copy-unaligned.S b/arch/riscv/kernel/vec-copy-unaligned.S index d16f19f..7ce4de6 100644 --- a/arch/riscv/kernel/vec-copy-unaligned.S +++ b/arch/riscv/kernel/vec-copy-unaligned.S
@@ -11,7 +11,7 @@ #define WORD_SEW CONCATENATE(e, WORD_EEW) #define VEC_L CONCATENATE(vle, WORD_EEW).v -#define VEC_S CONCATENATE(vle, WORD_EEW).v +#define VEC_S CONCATENATE(vse, WORD_EEW).v /* void __riscv_copy_vec_words_unaligned(void *, const void *, size_t) */ /* Performs a memcpy without aligning buffers, using word loads and stores. */
diff --git a/arch/riscv/kernel/vendor_extensions.c b/arch/riscv/kernel/vendor_extensions.c index a31ff84..9feb7f6 100644 --- a/arch/riscv/kernel/vendor_extensions.c +++ b/arch/riscv/kernel/vendor_extensions.c
@@ -61,6 +61,6 @@ bool __riscv_isa_vendor_extension_available(int cpu, unsigned long vendor, unsig if (bit >= RISCV_ISA_VENDOR_EXT_MAX) return false; - return test_bit(bit, bmap->isa) ? true : false; + return test_bit(bit, bmap->isa); } EXPORT_SYMBOL_GPL(__riscv_isa_vendor_extension_available);
diff --git a/arch/riscv/kernel/vmlinux.lds.S b/arch/riscv/kernel/vmlinux.lds.S index 002ca58..61bd5ba 100644 --- a/arch/riscv/kernel/vmlinux.lds.S +++ b/arch/riscv/kernel/vmlinux.lds.S
@@ -97,6 +97,9 @@ { EXIT_DATA } + + RUNTIME_CONST_VARIABLES + PERCPU_SECTION(L1_CACHE_BYTES) .rel.dyn : {
diff --git a/arch/riscv/kvm/vcpu_onereg.c b/arch/riscv/kvm/vcpu_onereg.c index 43ee8e3..2e1b646 100644 --- a/arch/riscv/kvm/vcpu_onereg.c +++ b/arch/riscv/kvm/vcpu_onereg.c
@@ -47,8 +47,10 @@ static const unsigned long kvm_isa_ext_arr[] = { KVM_ISA_EXT_ARR(SVNAPOT), KVM_ISA_EXT_ARR(SVPBMT), KVM_ISA_EXT_ARR(SVVPTC), + KVM_ISA_EXT_ARR(ZAAMO), KVM_ISA_EXT_ARR(ZABHA), KVM_ISA_EXT_ARR(ZACAS), + KVM_ISA_EXT_ARR(ZALRSC), KVM_ISA_EXT_ARR(ZAWRS), KVM_ISA_EXT_ARR(ZBA), KVM_ISA_EXT_ARR(ZBB), @@ -149,8 +151,10 @@ static bool kvm_riscv_vcpu_isa_disable_allowed(unsigned long ext) case KVM_RISCV_ISA_EXT_SVINVAL: case KVM_RISCV_ISA_EXT_SVNAPOT: case KVM_RISCV_ISA_EXT_SVVPTC: + case KVM_RISCV_ISA_EXT_ZAAMO: case KVM_RISCV_ISA_EXT_ZABHA: case KVM_RISCV_ISA_EXT_ZACAS: + case KVM_RISCV_ISA_EXT_ZALRSC: case KVM_RISCV_ISA_EXT_ZAWRS: case KVM_RISCV_ISA_EXT_ZBA: case KVM_RISCV_ISA_EXT_ZBB:
diff --git a/arch/riscv/lib/csum.c b/arch/riscv/lib/csum.c index 7fb12c5..9408f50 100644 --- a/arch/riscv/lib/csum.c +++ b/arch/riscv/lib/csum.c
@@ -40,12 +40,7 @@ __sum16 csum_ipv6_magic(const struct in6_addr *saddr, uproto = (__force unsigned int)htonl(proto); sum += uproto; - /* - * Zbb support saves 4 instructions, so not worth checking without - * alternatives if supported - */ - if (IS_ENABLED(CONFIG_RISCV_ISA_ZBB) && - IS_ENABLED(CONFIG_RISCV_ALTERNATIVE)) { + if (IS_ENABLED(CONFIG_RISCV_ISA_ZBB) && IS_ENABLED(CONFIG_TOOLCHAIN_HAS_ZBB)) { unsigned long fold_temp; /* @@ -157,12 +152,7 @@ do_csum_with_alignment(const unsigned char *buff, int len) csum = do_csum_common(ptr, end, data); #ifdef CC_HAS_ASM_GOTO_TIED_OUTPUT - /* - * Zbb support saves 6 instructions, so not worth checking without - * alternatives if supported - */ - if (IS_ENABLED(CONFIG_RISCV_ISA_ZBB) && - IS_ENABLED(CONFIG_RISCV_ALTERNATIVE)) { + if (IS_ENABLED(CONFIG_RISCV_ISA_ZBB) && IS_ENABLED(CONFIG_TOOLCHAIN_HAS_ZBB)) { unsigned long fold_temp; /* @@ -244,12 +234,7 @@ do_csum_no_alignment(const unsigned char *buff, int len) end = (const unsigned long *)(buff + len); csum = do_csum_common(ptr, end, data); - /* - * Zbb support saves 6 instructions, so not worth checking without - * alternatives if supported - */ - if (IS_ENABLED(CONFIG_RISCV_ISA_ZBB) && - IS_ENABLED(CONFIG_RISCV_ALTERNATIVE)) { + if (IS_ENABLED(CONFIG_RISCV_ISA_ZBB) && IS_ENABLED(CONFIG_TOOLCHAIN_HAS_ZBB)) { unsigned long fold_temp; /*
diff --git a/arch/riscv/lib/strcmp.S b/arch/riscv/lib/strcmp.S index 57a5c00..65027e7 100644 --- a/arch/riscv/lib/strcmp.S +++ b/arch/riscv/lib/strcmp.S
@@ -8,7 +8,8 @@ /* int strcmp(const char *cs, const char *ct) */ SYM_FUNC_START(strcmp) - ALTERNATIVE("nop", "j strcmp_zbb", 0, RISCV_ISA_EXT_ZBB, CONFIG_RISCV_ISA_ZBB) + __ALTERNATIVE_CFG("nop", "j strcmp_zbb", 0, RISCV_ISA_EXT_ZBB, + IS_ENABLED(CONFIG_RISCV_ISA_ZBB) && IS_ENABLED(CONFIG_TOOLCHAIN_HAS_ZBB)) /* * Returns @@ -43,7 +44,7 @@ * The code was published as part of the bitmanip manual * in Appendix A. */ -#ifdef CONFIG_RISCV_ISA_ZBB +#if defined(CONFIG_RISCV_ISA_ZBB) && defined(CONFIG_TOOLCHAIN_HAS_ZBB) strcmp_zbb: .option push
diff --git a/arch/riscv/lib/strlen.S b/arch/riscv/lib/strlen.S index 962983b..eb4d2b7 100644 --- a/arch/riscv/lib/strlen.S +++ b/arch/riscv/lib/strlen.S
@@ -8,7 +8,8 @@ /* int strlen(const char *s) */ SYM_FUNC_START(strlen) - ALTERNATIVE("nop", "j strlen_zbb", 0, RISCV_ISA_EXT_ZBB, CONFIG_RISCV_ISA_ZBB) + __ALTERNATIVE_CFG("nop", "j strlen_zbb", 0, RISCV_ISA_EXT_ZBB, + IS_ENABLED(CONFIG_RISCV_ISA_ZBB) && IS_ENABLED(CONFIG_TOOLCHAIN_HAS_ZBB)) /* * Returns @@ -33,7 +34,7 @@ /* * Variant of strlen using the ZBB extension if available */ -#ifdef CONFIG_RISCV_ISA_ZBB +#if defined(CONFIG_RISCV_ISA_ZBB) && defined(CONFIG_TOOLCHAIN_HAS_ZBB) strlen_zbb: #ifdef CONFIG_CPU_BIG_ENDIAN
diff --git a/arch/riscv/lib/strncmp.S b/arch/riscv/lib/strncmp.S index 7b2d0ff..062000c 100644 --- a/arch/riscv/lib/strncmp.S +++ b/arch/riscv/lib/strncmp.S
@@ -8,7 +8,8 @@ /* int strncmp(const char *cs, const char *ct, size_t count) */ SYM_FUNC_START(strncmp) - ALTERNATIVE("nop", "j strncmp_zbb", 0, RISCV_ISA_EXT_ZBB, CONFIG_RISCV_ISA_ZBB) + __ALTERNATIVE_CFG("nop", "j strncmp_zbb", 0, RISCV_ISA_EXT_ZBB, + IS_ENABLED(CONFIG_RISCV_ISA_ZBB) && IS_ENABLED(CONFIG_TOOLCHAIN_HAS_ZBB)) /* * Returns @@ -46,7 +47,7 @@ /* * Variant of strncmp using the ZBB extension if available */ -#ifdef CONFIG_RISCV_ISA_ZBB +#if defined(CONFIG_RISCV_ISA_ZBB) && defined(CONFIG_TOOLCHAIN_HAS_ZBB) strncmp_zbb: .option push
diff --git a/arch/riscv/mm/context.c b/arch/riscv/mm/context.c index 4abe3de..55c20ad 100644 --- a/arch/riscv/mm/context.c +++ b/arch/riscv/mm/context.c
@@ -158,7 +158,7 @@ static void set_mm_asid(struct mm_struct *mm, unsigned int cpu) * * - We get a zero back from the cmpxchg and end up waiting on the * lock. Taking the lock synchronises with the rollover and so - * we are forced to see the updated verion. + * we are forced to see the updated version. * * - We get a valid context back from the cmpxchg then we continue * using old ASID because __flush_context() would have marked ASID
diff --git a/arch/riscv/mm/hugetlbpage.c b/arch/riscv/mm/hugetlbpage.c index b4a78a4..375dd96 100644 --- a/arch/riscv/mm/hugetlbpage.c +++ b/arch/riscv/mm/hugetlbpage.c
@@ -148,22 +148,25 @@ unsigned long hugetlb_mask_last_page(struct hstate *h) static pte_t get_clear_contig(struct mm_struct *mm, unsigned long addr, pte_t *ptep, - unsigned long pte_num) + unsigned long ncontig) { - pte_t orig_pte = ptep_get(ptep); - unsigned long i; + pte_t pte, tmp_pte; + bool present; - for (i = 0; i < pte_num; i++, addr += PAGE_SIZE, ptep++) { - pte_t pte = ptep_get_and_clear(mm, addr, ptep); - - if (pte_dirty(pte)) - orig_pte = pte_mkdirty(orig_pte); - - if (pte_young(pte)) - orig_pte = pte_mkyoung(orig_pte); + pte = ptep_get_and_clear(mm, addr, ptep); + present = pte_present(pte); + while (--ncontig) { + ptep++; + addr += PAGE_SIZE; + tmp_pte = ptep_get_and_clear(mm, addr, ptep); + if (present) { + if (pte_dirty(tmp_pte)) + pte = pte_mkdirty(pte); + if (pte_young(tmp_pte)) + pte = pte_mkyoung(pte); + } } - - return orig_pte; + return pte; } static pte_t get_clear_contig_flush(struct mm_struct *mm, @@ -212,6 +215,26 @@ static void clear_flush(struct mm_struct *mm, flush_tlb_range(&vma, saddr, addr); } +static int num_contig_ptes_from_size(unsigned long sz, size_t *pgsize) +{ + unsigned long hugepage_shift; + + if (sz >= PGDIR_SIZE) + hugepage_shift = PGDIR_SHIFT; + else if (sz >= P4D_SIZE) + hugepage_shift = P4D_SHIFT; + else if (sz >= PUD_SIZE) + hugepage_shift = PUD_SHIFT; + else if (sz >= PMD_SIZE) + hugepage_shift = PMD_SHIFT; + else + hugepage_shift = PAGE_SHIFT; + + *pgsize = 1 << hugepage_shift; + + return sz >> hugepage_shift; +} + /* * When dealing with NAPOT mappings, the privileged specification indicates that * "if an update needs to be made, the OS generally should first mark all of the @@ -226,22 +249,10 @@ void set_huge_pte_at(struct mm_struct *mm, pte_t pte, unsigned long sz) { - unsigned long hugepage_shift, pgsize; + size_t pgsize; int i, pte_num; - if (sz >= PGDIR_SIZE) - hugepage_shift = PGDIR_SHIFT; - else if (sz >= P4D_SIZE) - hugepage_shift = P4D_SHIFT; - else if (sz >= PUD_SIZE) - hugepage_shift = PUD_SHIFT; - else if (sz >= PMD_SIZE) - hugepage_shift = PMD_SHIFT; - else - hugepage_shift = PAGE_SHIFT; - - pte_num = sz >> hugepage_shift; - pgsize = 1 << hugepage_shift; + pte_num = num_contig_ptes_from_size(sz, &pgsize); if (!pte_present(pte)) { for (i = 0; i < pte_num; i++, ptep++, addr += pgsize) @@ -295,13 +306,14 @@ pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep, unsigned long sz) { + size_t pgsize; pte_t orig_pte = ptep_get(ptep); int pte_num; if (!pte_napot(orig_pte)) return ptep_get_and_clear(mm, addr, ptep); - pte_num = napot_pte_num(napot_cont_order(orig_pte)); + pte_num = num_contig_ptes_from_size(sz, &pgsize); return get_clear_contig(mm, addr, ptep, pte_num); } @@ -351,6 +363,7 @@ void huge_pte_clear(struct mm_struct *mm, pte_t *ptep, unsigned long sz) { + size_t pgsize; pte_t pte = ptep_get(ptep); int i, pte_num; @@ -359,8 +372,9 @@ void huge_pte_clear(struct mm_struct *mm, return; } - pte_num = napot_pte_num(napot_cont_order(pte)); - for (i = 0; i < pte_num; i++, addr += PAGE_SIZE, ptep++) + pte_num = num_contig_ptes_from_size(sz, &pgsize); + + for (i = 0; i < pte_num; i++, addr += pgsize, ptep++) pte_clear(mm, addr, ptep); }
diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c index 66ee5ee..ab475ec 100644 --- a/arch/riscv/mm/init.c +++ b/arch/riscv/mm/init.c
@@ -20,15 +20,13 @@ #include <linux/dma-map-ops.h> #include <linux/crash_dump.h> #include <linux/hugetlb.h> -#ifdef CONFIG_RELOCATABLE -#include <linux/elf.h> -#endif #include <linux/kfence.h> #include <linux/execmem.h> #include <asm/fixmap.h> #include <asm/io.h> #include <asm/kasan.h> +#include <asm/module.h> #include <asm/numa.h> #include <asm/pgtable.h> #include <asm/sections.h> @@ -320,6 +318,44 @@ static void __init setup_bootmem(void) hugetlb_cma_reserve(PUD_SHIFT - PAGE_SHIFT); } +#ifdef CONFIG_RELOCATABLE +extern unsigned long __rela_dyn_start, __rela_dyn_end; + +static void __init relocate_kernel(void) +{ + Elf_Rela *rela = (Elf_Rela *)&__rela_dyn_start; + /* + * This holds the offset between the linked virtual address and the + * relocated virtual address. + */ + uintptr_t reloc_offset = kernel_map.virt_addr - KERNEL_LINK_ADDR; + /* + * This holds the offset between kernel linked virtual address and + * physical address. + */ + uintptr_t va_kernel_link_pa_offset = KERNEL_LINK_ADDR - kernel_map.phys_addr; + + for ( ; rela < (Elf_Rela *)&__rela_dyn_end; rela++) { + Elf_Addr addr = (rela->r_offset - va_kernel_link_pa_offset); + Elf_Addr relocated_addr = rela->r_addend; + + if (rela->r_info != R_RISCV_RELATIVE) + continue; + + /* + * Make sure to not relocate vdso symbols like rt_sigreturn + * which are linked from the address 0 in vmlinux since + * vdso symbol addresses are actually used as an offset from + * mm->context.vdso in VDSO_OFFSET macro. + */ + if (relocated_addr >= KERNEL_LINK_ADDR) + relocated_addr += reloc_offset; + + *(Elf_Addr *)addr = relocated_addr; + } +} +#endif /* CONFIG_RELOCATABLE */ + #ifdef CONFIG_MMU struct pt_alloc_ops pt_ops __meminitdata; @@ -820,6 +856,8 @@ static __init void set_satp_mode(uintptr_t dtb_pa) uintptr_t set_satp_mode_pmd = ((unsigned long)set_satp_mode) & PMD_MASK; u64 satp_mode_cmdline = __pi_set_satp_mode_from_cmdline(dtb_pa); + kernel_map.page_offset = PAGE_OFFSET_L5; + if (satp_mode_cmdline == SATP_MODE_57) { disable_pgtable_l5(); } else if (satp_mode_cmdline == SATP_MODE_48) { @@ -890,44 +928,6 @@ static __init void set_satp_mode(uintptr_t dtb_pa) #error "setup_vm() is called from head.S before relocate so it should not use absolute addressing." #endif -#ifdef CONFIG_RELOCATABLE -extern unsigned long __rela_dyn_start, __rela_dyn_end; - -static void __init relocate_kernel(void) -{ - Elf64_Rela *rela = (Elf64_Rela *)&__rela_dyn_start; - /* - * This holds the offset between the linked virtual address and the - * relocated virtual address. - */ - uintptr_t reloc_offset = kernel_map.virt_addr - KERNEL_LINK_ADDR; - /* - * This holds the offset between kernel linked virtual address and - * physical address. - */ - uintptr_t va_kernel_link_pa_offset = KERNEL_LINK_ADDR - kernel_map.phys_addr; - - for ( ; rela < (Elf64_Rela *)&__rela_dyn_end; rela++) { - Elf64_Addr addr = (rela->r_offset - va_kernel_link_pa_offset); - Elf64_Addr relocated_addr = rela->r_addend; - - if (rela->r_info != R_RISCV_RELATIVE) - continue; - - /* - * Make sure to not relocate vdso symbols like rt_sigreturn - * which are linked from the address 0 in vmlinux since - * vdso symbol addresses are actually used as an offset from - * mm->context.vdso in VDSO_OFFSET macro. - */ - if (relocated_addr >= KERNEL_LINK_ADDR) - relocated_addr += reloc_offset; - - *(Elf64_Addr *)addr = relocated_addr; - } -} -#endif /* CONFIG_RELOCATABLE */ - #ifdef CONFIG_XIP_KERNEL static void __init create_kernel_page_table(pgd_t *pgdir, __always_unused bool early) @@ -1105,11 +1105,6 @@ asmlinkage void __init setup_vm(uintptr_t dtb_pa) kernel_map.virt_addr = KERNEL_LINK_ADDR + kernel_map.virt_offset; #ifdef CONFIG_XIP_KERNEL -#ifdef CONFIG_64BIT - kernel_map.page_offset = PAGE_OFFSET_L3; -#else - kernel_map.page_offset = _AC(CONFIG_PAGE_OFFSET, UL); -#endif kernel_map.xiprom = (uintptr_t)CONFIG_XIP_PHYS_ADDR; kernel_map.xiprom_sz = (uintptr_t)(&_exiprom) - (uintptr_t)(&_xiprom); @@ -1124,7 +1119,6 @@ asmlinkage void __init setup_vm(uintptr_t dtb_pa) kernel_map.va_kernel_xip_data_pa_offset = kernel_map.virt_addr - kernel_map.phys_addr + (uintptr_t)&_sdata - (uintptr_t)&_start; #else - kernel_map.page_offset = _AC(CONFIG_PAGE_OFFSET, UL); kernel_map.phys_addr = (uintptr_t)(&_start); kernel_map.size = (uintptr_t)(&_end) - kernel_map.phys_addr; kernel_map.va_kernel_pa_offset = kernel_map.virt_addr - kernel_map.phys_addr; @@ -1171,7 +1165,8 @@ asmlinkage void __init setup_vm(uintptr_t dtb_pa) * makes the kernel cross over a PUD_SIZE boundary, raise a bug * since a part of the kernel would not get mapped. */ - BUG_ON(PUD_SIZE - (kernel_map.virt_addr & (PUD_SIZE - 1)) < kernel_map.size); + if (IS_ENABLED(CONFIG_64BIT)) + BUG_ON(PUD_SIZE - (kernel_map.virt_addr & (PUD_SIZE - 1)) < kernel_map.size); relocate_kernel(); #endif @@ -1375,6 +1370,12 @@ asmlinkage void __init setup_vm(uintptr_t dtb_pa) { dtb_early_va = (void *)dtb_pa; dtb_early_pa = dtb_pa; + +#ifdef CONFIG_RELOCATABLE + kernel_map.virt_addr = (uintptr_t)_start; + kernel_map.phys_addr = (uintptr_t)_start; + relocate_kernel(); +#endif } static inline void setup_vm_final(void)
diff --git a/arch/riscv/mm/physaddr.c b/arch/riscv/mm/physaddr.c index 18706f4..559d291 100644 --- a/arch/riscv/mm/physaddr.c +++ b/arch/riscv/mm/physaddr.c
@@ -12,7 +12,7 @@ phys_addr_t __virt_to_phys(unsigned long x) * Boundary checking aginst the kernel linear mapping space. */ WARN(!is_linear_mapping(x) && !is_kernel_mapping(x), - "virt_to_phys used for non-linear address: %pK (%pS)\n", + "virt_to_phys used for non-linear address: %p (%pS)\n", (void *)x, (void *)x); return __va_to_pa_nodebug(x);
diff --git a/arch/riscv/mm/tlbflush.c b/arch/riscv/mm/tlbflush.c index 74dd930..f9e27ba 100644 --- a/arch/riscv/mm/tlbflush.c +++ b/arch/riscv/mm/tlbflush.c
@@ -4,6 +4,7 @@ #include <linux/smp.h> #include <linux/sched.h> #include <linux/hugetlb.h> +#include <linux/mmu_notifier.h> #include <asm/sbi.h> #include <asm/mmu_context.h> @@ -78,10 +79,17 @@ static void __ipi_flush_tlb_range_asid(void *info) local_flush_tlb_range_asid(d->start, d->size, d->stride, d->asid); } -static void __flush_tlb_range(const struct cpumask *cmask, unsigned long asid, +static inline unsigned long get_mm_asid(struct mm_struct *mm) +{ + return mm ? cntx2asid(atomic_long_read(&mm->context.id)) : FLUSH_TLB_NO_ASID; +} + +static void __flush_tlb_range(struct mm_struct *mm, + const struct cpumask *cmask, unsigned long start, unsigned long size, unsigned long stride) { + unsigned long asid = get_mm_asid(mm); unsigned int cpu; if (cpumask_empty(cmask)) @@ -105,30 +113,26 @@ static void __flush_tlb_range(const struct cpumask *cmask, unsigned long asid, } put_cpu(); -} -static inline unsigned long get_mm_asid(struct mm_struct *mm) -{ - return cntx2asid(atomic_long_read(&mm->context.id)); + if (mm) + mmu_notifier_arch_invalidate_secondary_tlbs(mm, start, start + size); } void flush_tlb_mm(struct mm_struct *mm) { - __flush_tlb_range(mm_cpumask(mm), get_mm_asid(mm), - 0, FLUSH_TLB_MAX_SIZE, PAGE_SIZE); + __flush_tlb_range(mm, mm_cpumask(mm), 0, FLUSH_TLB_MAX_SIZE, PAGE_SIZE); } void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start, unsigned long end, unsigned int page_size) { - __flush_tlb_range(mm_cpumask(mm), get_mm_asid(mm), - start, end - start, page_size); + __flush_tlb_range(mm, mm_cpumask(mm), start, end - start, page_size); } void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr) { - __flush_tlb_range(mm_cpumask(vma->vm_mm), get_mm_asid(vma->vm_mm), + __flush_tlb_range(vma->vm_mm, mm_cpumask(vma->vm_mm), addr, PAGE_SIZE, PAGE_SIZE); } @@ -161,13 +165,13 @@ void flush_tlb_range(struct vm_area_struct *vma, unsigned long start, } } - __flush_tlb_range(mm_cpumask(vma->vm_mm), get_mm_asid(vma->vm_mm), + __flush_tlb_range(vma->vm_mm, mm_cpumask(vma->vm_mm), start, end - start, stride_size); } void flush_tlb_kernel_range(unsigned long start, unsigned long end) { - __flush_tlb_range(cpu_online_mask, FLUSH_TLB_NO_ASID, + __flush_tlb_range(NULL, cpu_online_mask, start, end - start, PAGE_SIZE); } @@ -175,7 +179,7 @@ void flush_tlb_kernel_range(unsigned long start, unsigned long end) void flush_pmd_tlb_range(struct vm_area_struct *vma, unsigned long start, unsigned long end) { - __flush_tlb_range(mm_cpumask(vma->vm_mm), get_mm_asid(vma->vm_mm), + __flush_tlb_range(vma->vm_mm, mm_cpumask(vma->vm_mm), start, end - start, PMD_SIZE); } #endif @@ -189,6 +193,7 @@ void arch_tlbbatch_add_pending(struct arch_tlbflush_unmap_batch *batch, struct mm_struct *mm, unsigned long start, unsigned long end) { cpumask_or(&batch->cpumask, &batch->cpumask, mm_cpumask(mm)); + mmu_notifier_arch_invalidate_secondary_tlbs(mm, start, end); } void arch_flush_tlb_batched_pending(struct mm_struct *mm) @@ -198,7 +203,7 @@ void arch_flush_tlb_batched_pending(struct mm_struct *mm) void arch_tlbbatch_flush(struct arch_tlbflush_unmap_batch *batch) { - __flush_tlb_range(&batch->cpumask, FLUSH_TLB_NO_ASID, 0, - FLUSH_TLB_MAX_SIZE, PAGE_SIZE); + __flush_tlb_range(NULL, &batch->cpumask, + 0, FLUSH_TLB_MAX_SIZE, PAGE_SIZE); cpumask_clear(&batch->cpumask); }
diff --git a/arch/riscv/purgatory/entry.S b/arch/riscv/purgatory/entry.S index 0e6ca6d..c5db2f0 100644 --- a/arch/riscv/purgatory/entry.S +++ b/arch/riscv/purgatory/entry.S
@@ -12,6 +12,7 @@ .text +.align 2 SYM_CODE_START(purgatory_start) lla sp, .Lstack
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index c809c48..db8161e 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig
@@ -137,6 +137,7 @@ select ARCH_SUPPORTS_DEBUG_PAGEALLOC select ARCH_SUPPORTS_HUGETLBFS select ARCH_SUPPORTS_INT128 if CC_HAS_INT128 && CC_IS_CLANG + select ARCH_SUPPORTS_MSEAL_SYSTEM_MAPPINGS select ARCH_SUPPORTS_NUMA_BALANCING select ARCH_SUPPORTS_PER_VMA_LOCK select ARCH_USE_BUILTIN_BSWAP @@ -239,6 +240,7 @@ select HAVE_SYSCALL_TRACEPOINTS select HAVE_VIRT_CPU_ACCOUNTING select HAVE_VIRT_CPU_ACCOUNTING_IDLE + select HOTPLUG_SMT select IOMMU_HELPER if PCI select IOMMU_SUPPORT if PCI select KASAN_VMALLOC if KASAN @@ -629,6 +631,7 @@ config RELOCATABLE def_bool y + select ARCH_VMLINUX_NEEDS_RELOCS help This builds a kernel image that retains relocation information so it can be loaded at an arbitrary address.
diff --git a/arch/s390/Makefile b/arch/s390/Makefile index 5fae311..b06dc53 100644 --- a/arch/s390/Makefile +++ b/arch/s390/Makefile
@@ -15,7 +15,7 @@ KBUILD_AFLAGS += -m64 KBUILD_CFLAGS += -m64 KBUILD_CFLAGS += -fPIC -LDFLAGS_vmlinux := -no-pie --emit-relocs --discard-none +LDFLAGS_vmlinux := $(call ld-option,-no-pie) extra_tools := relocs aflags_dwarf := -Wa,-gdwarf-2 KBUILD_AFLAGS_DECOMPRESSOR := $(CLANG_FLAGS) -m64 -D__ASSEMBLY__
diff --git a/arch/s390/Makefile.postlink b/arch/s390/Makefile.postlink index 1ae5478..c2b7375 100644 --- a/arch/s390/Makefile.postlink +++ b/arch/s390/Makefile.postlink
@@ -11,7 +11,6 @@ -include include/config/auto.conf include $(srctree)/scripts/Kbuild.include -include $(srctree)/scripts/Makefile.lib CMD_RELOCS=arch/s390/tools/relocs OUT_RELOCS = arch/s390/boot @@ -20,9 +19,8 @@ mkdir -p $(OUT_RELOCS); \ $(CMD_RELOCS) $@ > $(OUT_RELOCS)/relocs.S -vmlinux: FORCE +vmlinux.unstripped: FORCE $(call cmd,relocs) - $(call cmd,strip_relocs) clean: @rm -f $(OUT_RELOCS)/relocs.S
diff --git a/arch/s390/hypfs/hypfs_diag_fs.c b/arch/s390/hypfs/hypfs_diag_fs.c index 1e17e28..ede951d 100644 --- a/arch/s390/hypfs/hypfs_diag_fs.c +++ b/arch/s390/hypfs/hypfs_diag_fs.c
@@ -209,6 +209,8 @@ static int hypfs_create_cpu_files(struct dentry *cpus_dir, void *cpu_info) snprintf(buffer, TMP_SIZE, "%d", cpu_info__cpu_addr(diag204_get_info_type(), cpu_info)); cpu_dir = hypfs_mkdir(cpus_dir, buffer); + if (IS_ERR(cpu_dir)) + return PTR_ERR(cpu_dir); rc = hypfs_create_u64(cpu_dir, "mgmtime", cpu_info__acc_time(diag204_get_info_type(), cpu_info) - cpu_info__lp_time(diag204_get_info_type(), cpu_info));
diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h index 424f899..cb89e54 100644 --- a/arch/s390/include/asm/kvm_host.h +++ b/arch/s390/include/asm/kvm_host.h
@@ -20,14 +20,13 @@ #include <linux/module.h> #include <linux/pci.h> #include <linux/mmu_notifier.h> +#include <asm/kvm_host_types.h> #include <asm/debug.h> #include <asm/cpu.h> #include <asm/fpu.h> #include <asm/isc.h> #include <asm/guarded_storage.h> -#define KVM_S390_BSCA_CPU_SLOTS 64 -#define KVM_S390_ESCA_CPU_SLOTS 248 #define KVM_MAX_VCPUS 255 #define KVM_INTERNAL_MEM_SLOTS 1 @@ -51,342 +50,6 @@ #define KVM_REQ_REFRESH_GUEST_PREFIX \ KVM_ARCH_REQ_FLAGS(6, KVM_REQUEST_WAIT | KVM_REQUEST_NO_WAKEUP) -#define SIGP_CTRL_C 0x80 -#define SIGP_CTRL_SCN_MASK 0x3f - -union bsca_sigp_ctrl { - __u8 value; - struct { - __u8 c : 1; - __u8 r : 1; - __u8 scn : 6; - }; -}; - -union esca_sigp_ctrl { - __u16 value; - struct { - __u8 c : 1; - __u8 reserved: 7; - __u8 scn; - }; -}; - -struct esca_entry { - union esca_sigp_ctrl sigp_ctrl; - __u16 reserved1[3]; - __u64 sda; - __u64 reserved2[6]; -}; - -struct bsca_entry { - __u8 reserved0; - union bsca_sigp_ctrl sigp_ctrl; - __u16 reserved[3]; - __u64 sda; - __u64 reserved2[2]; -}; - -union ipte_control { - unsigned long val; - struct { - unsigned long k : 1; - unsigned long kh : 31; - unsigned long kg : 32; - }; -}; - -/* - * Utility is defined as two bytes but having it four bytes wide - * generates more efficient code. Since the following bytes are - * reserved this makes no functional difference. - */ -union sca_utility { - __u32 val; - struct { - __u32 mtcr : 1; - __u32 : 31; - }; -}; - -struct bsca_block { - union ipte_control ipte_control; - __u64 reserved[5]; - __u64 mcn; - union sca_utility utility; - __u8 reserved2[4]; - struct bsca_entry cpu[KVM_S390_BSCA_CPU_SLOTS]; -}; - -struct esca_block { - union ipte_control ipte_control; - __u64 reserved1[6]; - union sca_utility utility; - __u8 reserved2[4]; - __u64 mcn[4]; - __u64 reserved3[20]; - struct esca_entry cpu[KVM_S390_ESCA_CPU_SLOTS]; -}; - -/* - * This struct is used to store some machine check info from lowcore - * for machine checks that happen while the guest is running. - * This info in host's lowcore might be overwritten by a second machine - * check from host when host is in the machine check's high-level handling. - * The size is 24 bytes. - */ -struct mcck_volatile_info { - __u64 mcic; - __u64 failing_storage_address; - __u32 ext_damage_code; - __u32 reserved; -}; - -#define CR0_INITIAL_MASK (CR0_UNUSED_56 | CR0_INTERRUPT_KEY_SUBMASK | \ - CR0_MEASUREMENT_ALERT_SUBMASK) -#define CR14_INITIAL_MASK (CR14_UNUSED_32 | CR14_UNUSED_33 | \ - CR14_EXTERNAL_DAMAGE_SUBMASK) - -#define SIDAD_SIZE_MASK 0xff -#define sida_addr(sie_block) phys_to_virt((sie_block)->sidad & PAGE_MASK) -#define sida_size(sie_block) \ - ((((sie_block)->sidad & SIDAD_SIZE_MASK) + 1) * PAGE_SIZE) - -#define CPUSTAT_STOPPED 0x80000000 -#define CPUSTAT_WAIT 0x10000000 -#define CPUSTAT_ECALL_PEND 0x08000000 -#define CPUSTAT_STOP_INT 0x04000000 -#define CPUSTAT_IO_INT 0x02000000 -#define CPUSTAT_EXT_INT 0x01000000 -#define CPUSTAT_RUNNING 0x00800000 -#define CPUSTAT_RETAINED 0x00400000 -#define CPUSTAT_TIMING_SUB 0x00020000 -#define CPUSTAT_SIE_SUB 0x00010000 -#define CPUSTAT_RRF 0x00008000 -#define CPUSTAT_SLSV 0x00004000 -#define CPUSTAT_SLSR 0x00002000 -#define CPUSTAT_ZARCH 0x00000800 -#define CPUSTAT_MCDS 0x00000100 -#define CPUSTAT_KSS 0x00000200 -#define CPUSTAT_SM 0x00000080 -#define CPUSTAT_IBS 0x00000040 -#define CPUSTAT_GED2 0x00000010 -#define CPUSTAT_G 0x00000008 -#define CPUSTAT_GED 0x00000004 -#define CPUSTAT_J 0x00000002 -#define CPUSTAT_P 0x00000001 - -struct kvm_s390_sie_block { - atomic_t cpuflags; /* 0x0000 */ - __u32 : 1; /* 0x0004 */ - __u32 prefix : 18; - __u32 : 1; - __u32 ibc : 12; - __u8 reserved08[4]; /* 0x0008 */ -#define PROG_IN_SIE (1<<0) - __u32 prog0c; /* 0x000c */ - union { - __u8 reserved10[16]; /* 0x0010 */ - struct { - __u64 pv_handle_cpu; - __u64 pv_handle_config; - }; - }; -#define PROG_BLOCK_SIE (1<<0) -#define PROG_REQUEST (1<<1) - atomic_t prog20; /* 0x0020 */ - __u8 reserved24[4]; /* 0x0024 */ - __u64 cputm; /* 0x0028 */ - __u64 ckc; /* 0x0030 */ - __u64 epoch; /* 0x0038 */ - __u32 svcc; /* 0x0040 */ -#define LCTL_CR0 0x8000 -#define LCTL_CR6 0x0200 -#define LCTL_CR9 0x0040 -#define LCTL_CR10 0x0020 -#define LCTL_CR11 0x0010 -#define LCTL_CR14 0x0002 - __u16 lctl; /* 0x0044 */ - __s16 icpua; /* 0x0046 */ -#define ICTL_OPEREXC 0x80000000 -#define ICTL_PINT 0x20000000 -#define ICTL_LPSW 0x00400000 -#define ICTL_STCTL 0x00040000 -#define ICTL_ISKE 0x00004000 -#define ICTL_SSKE 0x00002000 -#define ICTL_RRBE 0x00001000 -#define ICTL_TPROT 0x00000200 - __u32 ictl; /* 0x0048 */ -#define ECA_CEI 0x80000000 -#define ECA_IB 0x40000000 -#define ECA_SIGPI 0x10000000 -#define ECA_MVPGI 0x01000000 -#define ECA_AIV 0x00200000 -#define ECA_VX 0x00020000 -#define ECA_PROTEXCI 0x00002000 -#define ECA_APIE 0x00000008 -#define ECA_SII 0x00000001 - __u32 eca; /* 0x004c */ -#define ICPT_INST 0x04 -#define ICPT_PROGI 0x08 -#define ICPT_INSTPROGI 0x0C -#define ICPT_EXTREQ 0x10 -#define ICPT_EXTINT 0x14 -#define ICPT_IOREQ 0x18 -#define ICPT_WAIT 0x1c -#define ICPT_VALIDITY 0x20 -#define ICPT_STOP 0x28 -#define ICPT_OPEREXC 0x2C -#define ICPT_PARTEXEC 0x38 -#define ICPT_IOINST 0x40 -#define ICPT_KSS 0x5c -#define ICPT_MCHKREQ 0x60 -#define ICPT_INT_ENABLE 0x64 -#define ICPT_PV_INSTR 0x68 -#define ICPT_PV_NOTIFY 0x6c -#define ICPT_PV_PREF 0x70 - __u8 icptcode; /* 0x0050 */ - __u8 icptstatus; /* 0x0051 */ - __u16 ihcpu; /* 0x0052 */ - __u8 reserved54; /* 0x0054 */ -#define IICTL_CODE_NONE 0x00 -#define IICTL_CODE_MCHK 0x01 -#define IICTL_CODE_EXT 0x02 -#define IICTL_CODE_IO 0x03 -#define IICTL_CODE_RESTART 0x04 -#define IICTL_CODE_SPECIFICATION 0x10 -#define IICTL_CODE_OPERAND 0x11 - __u8 iictl; /* 0x0055 */ - __u16 ipa; /* 0x0056 */ - __u32 ipb; /* 0x0058 */ - __u32 scaoh; /* 0x005c */ -#define FPF_BPBC 0x20 - __u8 fpf; /* 0x0060 */ -#define ECB_GS 0x40 -#define ECB_TE 0x10 -#define ECB_SPECI 0x08 -#define ECB_SRSI 0x04 -#define ECB_HOSTPROTINT 0x02 -#define ECB_PTF 0x01 - __u8 ecb; /* 0x0061 */ -#define ECB2_CMMA 0x80 -#define ECB2_IEP 0x20 -#define ECB2_PFMFI 0x08 -#define ECB2_ESCA 0x04 -#define ECB2_ZPCI_LSI 0x02 - __u8 ecb2; /* 0x0062 */ -#define ECB3_AISI 0x20 -#define ECB3_AISII 0x10 -#define ECB3_DEA 0x08 -#define ECB3_AES 0x04 -#define ECB3_RI 0x01 - __u8 ecb3; /* 0x0063 */ -#define ESCA_SCAOL_MASK ~0x3fU - __u32 scaol; /* 0x0064 */ - __u8 sdf; /* 0x0068 */ - __u8 epdx; /* 0x0069 */ - __u8 cpnc; /* 0x006a */ - __u8 reserved6b; /* 0x006b */ - __u32 todpr; /* 0x006c */ -#define GISA_FORMAT1 0x00000001 - __u32 gd; /* 0x0070 */ - __u8 reserved74[12]; /* 0x0074 */ - __u64 mso; /* 0x0080 */ - __u64 msl; /* 0x0088 */ - psw_t gpsw; /* 0x0090 */ - __u64 gg14; /* 0x00a0 */ - __u64 gg15; /* 0x00a8 */ - __u8 reservedb0[8]; /* 0x00b0 */ -#define HPID_KVM 0x4 -#define HPID_VSIE 0x5 - __u8 hpid; /* 0x00b8 */ - __u8 reservedb9[7]; /* 0x00b9 */ - union { - struct { - __u32 eiparams; /* 0x00c0 */ - __u16 extcpuaddr; /* 0x00c4 */ - __u16 eic; /* 0x00c6 */ - }; - __u64 mcic; /* 0x00c0 */ - } __packed; - __u32 reservedc8; /* 0x00c8 */ - union { - struct { - __u16 pgmilc; /* 0x00cc */ - __u16 iprcc; /* 0x00ce */ - }; - __u32 edc; /* 0x00cc */ - } __packed; - union { - struct { - __u32 dxc; /* 0x00d0 */ - __u16 mcn; /* 0x00d4 */ - __u8 perc; /* 0x00d6 */ - __u8 peratmid; /* 0x00d7 */ - }; - __u64 faddr; /* 0x00d0 */ - } __packed; - __u64 peraddr; /* 0x00d8 */ - __u8 eai; /* 0x00e0 */ - __u8 peraid; /* 0x00e1 */ - __u8 oai; /* 0x00e2 */ - __u8 armid; /* 0x00e3 */ - __u8 reservede4[4]; /* 0x00e4 */ - union { - __u64 tecmc; /* 0x00e8 */ - struct { - __u16 subchannel_id; /* 0x00e8 */ - __u16 subchannel_nr; /* 0x00ea */ - __u32 io_int_parm; /* 0x00ec */ - __u32 io_int_word; /* 0x00f0 */ - }; - } __packed; - __u8 reservedf4[8]; /* 0x00f4 */ -#define CRYCB_FORMAT_MASK 0x00000003 -#define CRYCB_FORMAT0 0x00000000 -#define CRYCB_FORMAT1 0x00000001 -#define CRYCB_FORMAT2 0x00000003 - __u32 crycbd; /* 0x00fc */ - __u64 gcr[16]; /* 0x0100 */ - union { - __u64 gbea; /* 0x0180 */ - __u64 sidad; - }; - __u8 reserved188[8]; /* 0x0188 */ - __u64 sdnxo; /* 0x0190 */ - __u8 reserved198[8]; /* 0x0198 */ - __u32 fac; /* 0x01a0 */ - __u8 reserved1a4[20]; /* 0x01a4 */ - __u64 cbrlo; /* 0x01b8 */ - __u8 reserved1c0[8]; /* 0x01c0 */ -#define ECD_HOSTREGMGMT 0x20000000 -#define ECD_MEF 0x08000000 -#define ECD_ETOKENF 0x02000000 -#define ECD_ECC 0x00200000 -#define ECD_HMAC 0x00004000 - __u32 ecd; /* 0x01c8 */ - __u8 reserved1cc[18]; /* 0x01cc */ - __u64 pp; /* 0x01de */ - __u8 reserved1e6[2]; /* 0x01e6 */ - __u64 itdba; /* 0x01e8 */ - __u64 riccbd; /* 0x01f0 */ - __u64 gvrd; /* 0x01f8 */ -} __packed __aligned(512); - -struct kvm_s390_itdb { - __u8 data[256]; -}; - -struct sie_page { - struct kvm_s390_sie_block sie_block; - struct mcck_volatile_info mcck_info; /* 0x0200 */ - __u8 reserved218[360]; /* 0x0218 */ - __u64 pv_grregs[16]; /* 0x0380 */ - __u8 reserved400[512]; /* 0x0400 */ - struct kvm_s390_itdb itdb; /* 0x0600 */ - __u8 reserved700[2304]; /* 0x0700 */ -}; - struct kvm_vcpu_stat { struct kvm_vcpu_stat_generic generic; u64 exit_userspace;
diff --git a/arch/s390/include/asm/kvm_host_types.h b/arch/s390/include/asm/kvm_host_types.h new file mode 100644 index 0000000..1394d3f --- /dev/null +++ b/arch/s390/include/asm/kvm_host_types.h
@@ -0,0 +1,348 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef _ASM_KVM_HOST_TYPES_H +#define _ASM_KVM_HOST_TYPES_H + +#include <linux/atomic.h> +#include <linux/types.h> + +#define KVM_S390_BSCA_CPU_SLOTS 64 +#define KVM_S390_ESCA_CPU_SLOTS 248 + +#define SIGP_CTRL_C 0x80 +#define SIGP_CTRL_SCN_MASK 0x3f + +union bsca_sigp_ctrl { + __u8 value; + struct { + __u8 c : 1; + __u8 r : 1; + __u8 scn : 6; + }; +}; + +union esca_sigp_ctrl { + __u16 value; + struct { + __u8 c : 1; + __u8 reserved: 7; + __u8 scn; + }; +}; + +struct esca_entry { + union esca_sigp_ctrl sigp_ctrl; + __u16 reserved1[3]; + __u64 sda; + __u64 reserved2[6]; +}; + +struct bsca_entry { + __u8 reserved0; + union bsca_sigp_ctrl sigp_ctrl; + __u16 reserved[3]; + __u64 sda; + __u64 reserved2[2]; +}; + +union ipte_control { + unsigned long val; + struct { + unsigned long k : 1; + unsigned long kh : 31; + unsigned long kg : 32; + }; +}; + +/* + * Utility is defined as two bytes but having it four bytes wide + * generates more efficient code. Since the following bytes are + * reserved this makes no functional difference. + */ +union sca_utility { + __u32 val; + struct { + __u32 mtcr : 1; + __u32 : 31; + }; +}; + +struct bsca_block { + union ipte_control ipte_control; + __u64 reserved[5]; + __u64 mcn; + union sca_utility utility; + __u8 reserved2[4]; + struct bsca_entry cpu[KVM_S390_BSCA_CPU_SLOTS]; +}; + +struct esca_block { + union ipte_control ipte_control; + __u64 reserved1[6]; + union sca_utility utility; + __u8 reserved2[4]; + __u64 mcn[4]; + __u64 reserved3[20]; + struct esca_entry cpu[KVM_S390_ESCA_CPU_SLOTS]; +}; + +/* + * This struct is used to store some machine check info from lowcore + * for machine checks that happen while the guest is running. + * This info in host's lowcore might be overwritten by a second machine + * check from host when host is in the machine check's high-level handling. + * The size is 24 bytes. + */ +struct mcck_volatile_info { + __u64 mcic; + __u64 failing_storage_address; + __u32 ext_damage_code; + __u32 reserved; +}; + +#define CR0_INITIAL_MASK (CR0_UNUSED_56 | CR0_INTERRUPT_KEY_SUBMASK | \ + CR0_MEASUREMENT_ALERT_SUBMASK) +#define CR14_INITIAL_MASK (CR14_UNUSED_32 | CR14_UNUSED_33 | \ + CR14_EXTERNAL_DAMAGE_SUBMASK) + +#define SIDAD_SIZE_MASK 0xff +#define sida_addr(sie_block) phys_to_virt((sie_block)->sidad & PAGE_MASK) +#define sida_size(sie_block) \ + ((((sie_block)->sidad & SIDAD_SIZE_MASK) + 1) * PAGE_SIZE) + +#define CPUSTAT_STOPPED 0x80000000 +#define CPUSTAT_WAIT 0x10000000 +#define CPUSTAT_ECALL_PEND 0x08000000 +#define CPUSTAT_STOP_INT 0x04000000 +#define CPUSTAT_IO_INT 0x02000000 +#define CPUSTAT_EXT_INT 0x01000000 +#define CPUSTAT_RUNNING 0x00800000 +#define CPUSTAT_RETAINED 0x00400000 +#define CPUSTAT_TIMING_SUB 0x00020000 +#define CPUSTAT_SIE_SUB 0x00010000 +#define CPUSTAT_RRF 0x00008000 +#define CPUSTAT_SLSV 0x00004000 +#define CPUSTAT_SLSR 0x00002000 +#define CPUSTAT_ZARCH 0x00000800 +#define CPUSTAT_MCDS 0x00000100 +#define CPUSTAT_KSS 0x00000200 +#define CPUSTAT_SM 0x00000080 +#define CPUSTAT_IBS 0x00000040 +#define CPUSTAT_GED2 0x00000010 +#define CPUSTAT_G 0x00000008 +#define CPUSTAT_GED 0x00000004 +#define CPUSTAT_J 0x00000002 +#define CPUSTAT_P 0x00000001 + +struct kvm_s390_sie_block { + atomic_t cpuflags; /* 0x0000 */ + __u32 : 1; /* 0x0004 */ + __u32 prefix : 18; + __u32 : 1; + __u32 ibc : 12; + __u8 reserved08[4]; /* 0x0008 */ +#define PROG_IN_SIE (1<<0) + __u32 prog0c; /* 0x000c */ + union { + __u8 reserved10[16]; /* 0x0010 */ + struct { + __u64 pv_handle_cpu; + __u64 pv_handle_config; + }; + }; +#define PROG_BLOCK_SIE (1<<0) +#define PROG_REQUEST (1<<1) + atomic_t prog20; /* 0x0020 */ + __u8 reserved24[4]; /* 0x0024 */ + __u64 cputm; /* 0x0028 */ + __u64 ckc; /* 0x0030 */ + __u64 epoch; /* 0x0038 */ + __u32 svcc; /* 0x0040 */ +#define LCTL_CR0 0x8000 +#define LCTL_CR6 0x0200 +#define LCTL_CR9 0x0040 +#define LCTL_CR10 0x0020 +#define LCTL_CR11 0x0010 +#define LCTL_CR14 0x0002 + __u16 lctl; /* 0x0044 */ + __s16 icpua; /* 0x0046 */ +#define ICTL_OPEREXC 0x80000000 +#define ICTL_PINT 0x20000000 +#define ICTL_LPSW 0x00400000 +#define ICTL_STCTL 0x00040000 +#define ICTL_ISKE 0x00004000 +#define ICTL_SSKE 0x00002000 +#define ICTL_RRBE 0x00001000 +#define ICTL_TPROT 0x00000200 + __u32 ictl; /* 0x0048 */ +#define ECA_CEI 0x80000000 +#define ECA_IB 0x40000000 +#define ECA_SIGPI 0x10000000 +#define ECA_MVPGI 0x01000000 +#define ECA_AIV 0x00200000 +#define ECA_VX 0x00020000 +#define ECA_PROTEXCI 0x00002000 +#define ECA_APIE 0x00000008 +#define ECA_SII 0x00000001 + __u32 eca; /* 0x004c */ +#define ICPT_INST 0x04 +#define ICPT_PROGI 0x08 +#define ICPT_INSTPROGI 0x0C +#define ICPT_EXTREQ 0x10 +#define ICPT_EXTINT 0x14 +#define ICPT_IOREQ 0x18 +#define ICPT_WAIT 0x1c +#define ICPT_VALIDITY 0x20 +#define ICPT_STOP 0x28 +#define ICPT_OPEREXC 0x2C +#define ICPT_PARTEXEC 0x38 +#define ICPT_IOINST 0x40 +#define ICPT_KSS 0x5c +#define ICPT_MCHKREQ 0x60 +#define ICPT_INT_ENABLE 0x64 +#define ICPT_PV_INSTR 0x68 +#define ICPT_PV_NOTIFY 0x6c +#define ICPT_PV_PREF 0x70 + __u8 icptcode; /* 0x0050 */ + __u8 icptstatus; /* 0x0051 */ + __u16 ihcpu; /* 0x0052 */ + __u8 reserved54; /* 0x0054 */ +#define IICTL_CODE_NONE 0x00 +#define IICTL_CODE_MCHK 0x01 +#define IICTL_CODE_EXT 0x02 +#define IICTL_CODE_IO 0x03 +#define IICTL_CODE_RESTART 0x04 +#define IICTL_CODE_SPECIFICATION 0x10 +#define IICTL_CODE_OPERAND 0x11 + __u8 iictl; /* 0x0055 */ + __u16 ipa; /* 0x0056 */ + __u32 ipb; /* 0x0058 */ + __u32 scaoh; /* 0x005c */ +#define FPF_BPBC 0x20 + __u8 fpf; /* 0x0060 */ +#define ECB_GS 0x40 +#define ECB_TE 0x10 +#define ECB_SPECI 0x08 +#define ECB_SRSI 0x04 +#define ECB_HOSTPROTINT 0x02 +#define ECB_PTF 0x01 + __u8 ecb; /* 0x0061 */ +#define ECB2_CMMA 0x80 +#define ECB2_IEP 0x20 +#define ECB2_PFMFI 0x08 +#define ECB2_ESCA 0x04 +#define ECB2_ZPCI_LSI 0x02 + __u8 ecb2; /* 0x0062 */ +#define ECB3_AISI 0x20 +#define ECB3_AISII 0x10 +#define ECB3_DEA 0x08 +#define ECB3_AES 0x04 +#define ECB3_RI 0x01 + __u8 ecb3; /* 0x0063 */ +#define ESCA_SCAOL_MASK ~0x3fU + __u32 scaol; /* 0x0064 */ + __u8 sdf; /* 0x0068 */ + __u8 epdx; /* 0x0069 */ + __u8 cpnc; /* 0x006a */ + __u8 reserved6b; /* 0x006b */ + __u32 todpr; /* 0x006c */ +#define GISA_FORMAT1 0x00000001 + __u32 gd; /* 0x0070 */ + __u8 reserved74[12]; /* 0x0074 */ + __u64 mso; /* 0x0080 */ + __u64 msl; /* 0x0088 */ + psw_t gpsw; /* 0x0090 */ + __u64 gg14; /* 0x00a0 */ + __u64 gg15; /* 0x00a8 */ + __u8 reservedb0[8]; /* 0x00b0 */ +#define HPID_KVM 0x4 +#define HPID_VSIE 0x5 + __u8 hpid; /* 0x00b8 */ + __u8 reservedb9[7]; /* 0x00b9 */ + union { + struct { + __u32 eiparams; /* 0x00c0 */ + __u16 extcpuaddr; /* 0x00c4 */ + __u16 eic; /* 0x00c6 */ + }; + __u64 mcic; /* 0x00c0 */ + } __packed; + __u32 reservedc8; /* 0x00c8 */ + union { + struct { + __u16 pgmilc; /* 0x00cc */ + __u16 iprcc; /* 0x00ce */ + }; + __u32 edc; /* 0x00cc */ + } __packed; + union { + struct { + __u32 dxc; /* 0x00d0 */ + __u16 mcn; /* 0x00d4 */ + __u8 perc; /* 0x00d6 */ + __u8 peratmid; /* 0x00d7 */ + }; + __u64 faddr; /* 0x00d0 */ + } __packed; + __u64 peraddr; /* 0x00d8 */ + __u8 eai; /* 0x00e0 */ + __u8 peraid; /* 0x00e1 */ + __u8 oai; /* 0x00e2 */ + __u8 armid; /* 0x00e3 */ + __u8 reservede4[4]; /* 0x00e4 */ + union { + __u64 tecmc; /* 0x00e8 */ + struct { + __u16 subchannel_id; /* 0x00e8 */ + __u16 subchannel_nr; /* 0x00ea */ + __u32 io_int_parm; /* 0x00ec */ + __u32 io_int_word; /* 0x00f0 */ + }; + } __packed; + __u8 reservedf4[8]; /* 0x00f4 */ +#define CRYCB_FORMAT_MASK 0x00000003 +#define CRYCB_FORMAT0 0x00000000 +#define CRYCB_FORMAT1 0x00000001 +#define CRYCB_FORMAT2 0x00000003 + __u32 crycbd; /* 0x00fc */ + __u64 gcr[16]; /* 0x0100 */ + union { + __u64 gbea; /* 0x0180 */ + __u64 sidad; + }; + __u8 reserved188[8]; /* 0x0188 */ + __u64 sdnxo; /* 0x0190 */ + __u8 reserved198[8]; /* 0x0198 */ + __u32 fac; /* 0x01a0 */ + __u8 reserved1a4[20]; /* 0x01a4 */ + __u64 cbrlo; /* 0x01b8 */ + __u8 reserved1c0[8]; /* 0x01c0 */ +#define ECD_HOSTREGMGMT 0x20000000 +#define ECD_MEF 0x08000000 +#define ECD_ETOKENF 0x02000000 +#define ECD_ECC 0x00200000 +#define ECD_HMAC 0x00004000 + __u32 ecd; /* 0x01c8 */ + __u8 reserved1cc[18]; /* 0x01cc */ + __u64 pp; /* 0x01de */ + __u8 reserved1e6[2]; /* 0x01e6 */ + __u64 itdba; /* 0x01e8 */ + __u64 riccbd; /* 0x01f0 */ + __u64 gvrd; /* 0x01f8 */ +} __packed __aligned(512); + +struct kvm_s390_itdb { + __u8 data[256]; +}; + +struct sie_page { + struct kvm_s390_sie_block sie_block; + struct mcck_volatile_info mcck_info; /* 0x0200 */ + __u8 reserved218[360]; /* 0x0218 */ + __u64 pv_grregs[16]; /* 0x0380 */ + __u8 reserved400[512]; /* 0x0400 */ + struct kvm_s390_itdb itdb; /* 0x0600 */ + __u8 reserved700[2304]; /* 0x0700 */ +}; + +#endif /* _ASM_KVM_HOST_TYPES_H */
diff --git a/arch/s390/include/asm/lowcore.h b/arch/s390/include/asm/lowcore.h index 1a31f1f..e99e9c8 100644 --- a/arch/s390/include/asm/lowcore.h +++ b/arch/s390/include/asm/lowcore.h
@@ -164,9 +164,7 @@ struct lowcore { __u32 spinlock_index; /* 0x03b0 */ __u8 pad_0x03b4[0x03b8-0x03b4]; /* 0x03b4 */ __u64 percpu_offset; /* 0x03b8 */ - __u8 pad_0x03c0[0x03c8-0x03c0]; /* 0x03c0 */ - __u64 machine_flags; /* 0x03c8 */ - __u8 pad_0x03d0[0x0400-0x03d0]; /* 0x03d0 */ + __u8 pad_0x03c0[0x0400-0x03c0]; /* 0x03c0 */ __u32 return_lpswe; /* 0x0400 */ __u32 return_mcck_lpswe; /* 0x0404 */
diff --git a/arch/s390/include/asm/processor.h b/arch/s390/include/asm/processor.h index d09a92d..6c8063c 100644 --- a/arch/s390/include/asm/processor.h +++ b/arch/s390/include/asm/processor.h
@@ -31,6 +31,7 @@ #include <linux/cpumask.h> #include <linux/linkage.h> #include <linux/irqflags.h> +#include <linux/bitops.h> #include <asm/fpu-types.h> #include <asm/cpu.h> #include <asm/page.h> @@ -62,33 +63,27 @@ static __always_inline struct pcpu *this_pcpu(void) static __always_inline void set_cpu_flag(int flag) { - this_pcpu()->flags |= (1UL << flag); + set_bit(flag, &this_pcpu()->flags); } static __always_inline void clear_cpu_flag(int flag) { - this_pcpu()->flags &= ~(1UL << flag); + clear_bit(flag, &this_pcpu()->flags); } static __always_inline bool test_cpu_flag(int flag) { - return this_pcpu()->flags & (1UL << flag); + return test_bit(flag, &this_pcpu()->flags); } static __always_inline bool test_and_set_cpu_flag(int flag) { - if (test_cpu_flag(flag)) - return true; - set_cpu_flag(flag); - return false; + return test_and_set_bit(flag, &this_pcpu()->flags); } static __always_inline bool test_and_clear_cpu_flag(int flag) { - if (!test_cpu_flag(flag)) - return false; - clear_cpu_flag(flag); - return true; + return test_and_clear_bit(flag, &this_pcpu()->flags); } /* @@ -97,7 +92,7 @@ static __always_inline bool test_and_clear_cpu_flag(int flag) */ static __always_inline bool test_cpu_flag_of(int flag, int cpu) { - return per_cpu(pcpu_devices, cpu).flags & (1UL << flag); + return test_bit(flag, &per_cpu(pcpu_devices, cpu).flags); } #define arch_needs_cpu() test_cpu_flag(CIF_NOHZ_DELAY)
diff --git a/arch/s390/include/asm/thread_info.h b/arch/s390/include/asm/thread_info.h index 1ad5e82..91f569c 100644 --- a/arch/s390/include/asm/thread_info.h +++ b/arch/s390/include/asm/thread_info.h
@@ -9,9 +9,6 @@ #define _ASM_THREAD_INFO_H #include <linux/bits.h> -#ifndef ASM_OFFSETS_C -#include <asm/asm-offsets.h> -#endif /* * General size of kernel stacks
diff --git a/arch/s390/include/asm/topology.h b/arch/s390/include/asm/topology.h index cef06bf..4411084 100644 --- a/arch/s390/include/asm/topology.h +++ b/arch/s390/include/asm/topology.h
@@ -61,6 +61,12 @@ static inline void topology_expect_change(void) { } #endif /* CONFIG_SCHED_TOPOLOGY */ +static inline bool topology_is_primary_thread(unsigned int cpu) +{ + return smp_get_base_cpu(cpu) == cpu; +} +#define topology_is_primary_thread topology_is_primary_thread + #define POLARIZATION_UNKNOWN (-1) #define POLARIZATION_HRZ (0) #define POLARIZATION_VL (1)
diff --git a/arch/s390/kernel/asm-offsets.c b/arch/s390/kernel/asm-offsets.c index 49bb197..841e05f 100644 --- a/arch/s390/kernel/asm-offsets.c +++ b/arch/s390/kernel/asm-offsets.c
@@ -5,15 +5,14 @@ * and format the required data. */ -#define ASM_OFFSETS_C - #include <linux/kbuild.h> -#include <linux/kvm_host.h> #include <linux/sched.h> #include <linux/purgatory.h> #include <linux/pgtable.h> -#include <linux/ftrace.h> +#include <linux/ftrace_regs.h> +#include <asm/kvm_host_types.h> #include <asm/stacktrace.h> +#include <asm/ptrace.h> int main(void) {
diff --git a/arch/s390/kernel/dumpstack.c b/arch/s390/kernel/dumpstack.c index 911b95c..dd41096 100644 --- a/arch/s390/kernel/dumpstack.c +++ b/arch/s390/kernel/dumpstack.c
@@ -17,6 +17,7 @@ #include <linux/sched.h> #include <linux/sched/debug.h> #include <linux/sched/task_stack.h> +#include <asm/asm-offsets.h> #include <asm/processor.h> #include <asm/debug.h> #include <asm/dis.h>
diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c index b6d3c7a..54cf092 100644 --- a/arch/s390/kernel/early.c +++ b/arch/s390/kernel/early.c
@@ -22,6 +22,7 @@ #include <asm/asm-extable.h> #include <linux/memblock.h> #include <asm/access-regs.h> +#include <asm/asm-offsets.h> #include <asm/machine.h> #include <asm/diag.h> #include <asm/ebcdic.h>
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index b0c2356..dd291c9 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S
@@ -468,7 +468,7 @@ clgrjl %r9,%r14, 4f larl %r14,.Lsie_leave clgrjhe %r9,%r14, 4f - lg %r10,__LC_PCPU + lg %r10,__LC_PCPU(%r13) oi __PCPU_FLAGS+7(%r10), _CIF_MCCK_GUEST 4: BPENTER __SF_SIE_FLAGS(%r15),_TIF_ISOLATE_BP_GUEST SIEEXIT __SF_SIE_CONTROL(%r15),%r13
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index b6686d6..f244c55 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c
@@ -414,7 +414,6 @@ static void __init setup_lowcore(void) lc->clock_comparator = clock_comparator_max; lc->current_task = (unsigned long)&init_task; lc->lpp = LPP_MAGIC; - lc->machine_flags = get_lowcore()->machine_flags; lc->preempt_count = get_lowcore()->preempt_count; nmi_alloc_mcesa_early(&lc->mcesad); lc->sys_enter_timer = get_lowcore()->sys_enter_timer;
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index f2f05c5..63f41df 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c
@@ -99,13 +99,6 @@ __vector128 __initdata boot_cpu_vector_save_area[__NUM_VXRS]; static unsigned int smp_max_threads __initdata = -1U; cpumask_t cpu_setup_mask; -static int __init early_nosmt(char *s) -{ - smp_max_threads = 1; - return 0; -} -early_param("nosmt", early_nosmt); - static int __init early_smt(char *s) { get_option(&s, &smp_max_threads); @@ -265,7 +258,6 @@ static void pcpu_prepare_secondary(struct pcpu *pcpu, int cpu) lc->percpu_offset = __per_cpu_offset[cpu]; lc->kernel_asce = get_lowcore()->kernel_asce; lc->user_asce = s390_invalid_asce; - lc->machine_flags = get_lowcore()->machine_flags; lc->user_timer = lc->system_timer = lc->steal_timer = lc->avg_steal_timer = 0; abs_lc = get_abs_lowcore(); @@ -809,6 +801,7 @@ void __init smp_detect_cpus(void) mtid = boot_core_type ? sclp.mtid : sclp.mtid_cp; mtid = (mtid < smp_max_threads) ? mtid : smp_max_threads - 1; pcpu_set_smt(mtid); + cpu_smt_set_num_threads(smp_cpu_mtid + 1, smp_cpu_mtid + 1); /* Print number of CPUs */ c_cpus = s_cpus = 0;
diff --git a/arch/s390/kernel/stacktrace.c b/arch/s390/kernel/stacktrace.c index 40edfde..b153a39 100644 --- a/arch/s390/kernel/stacktrace.c +++ b/arch/s390/kernel/stacktrace.c
@@ -9,6 +9,7 @@ #include <linux/stacktrace.h> #include <linux/uaccess.h> #include <linux/compat.h> +#include <asm/asm-offsets.h> #include <asm/stacktrace.h> #include <asm/unwind.h> #include <asm/kprobes.h>
diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c index c900ded..fed17d4 100644 --- a/arch/s390/kernel/time.c +++ b/arch/s390/kernel/time.c
@@ -680,7 +680,7 @@ static void stp_work_fn(struct work_struct *work) if (!stp_online) { chsc_sstpc(stp_page, STP_OP_CTRL, 0x0000, NULL); - del_timer_sync(&stp_timer); + timer_delete_sync(&stp_timer); goto out_unlock; }
diff --git a/arch/s390/kernel/vdso.c b/arch/s390/kernel/vdso.c index 70c8f9a..430feb1 100644 --- a/arch/s390/kernel/vdso.c +++ b/arch/s390/kernel/vdso.c
@@ -80,7 +80,7 @@ static int map_vdso(unsigned long addr, unsigned long vdso_mapping_len) vdso_text_start = vvar_start + VDSO_NR_PAGES * PAGE_SIZE; /* VM_MAYWRITE for COW so gdb can set breakpoints */ vma = _install_special_mapping(mm, vdso_text_start, vdso_text_len, - VM_READ|VM_EXEC| + VM_READ|VM_EXEC|VM_SEALED_SYSMAP| VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC, vdso_mapping); if (IS_ERR(vma)) {
diff --git a/arch/s390/mm/cmm.c b/arch/s390/mm/cmm.c index 39f44b6..e2a6eb9 100644 --- a/arch/s390/mm/cmm.c +++ b/arch/s390/mm/cmm.c
@@ -201,7 +201,7 @@ static void cmm_set_timer(void) { if (cmm_timed_pages_target <= 0 || cmm_timeout_seconds <= 0) { if (timer_pending(&cmm_timer)) - del_timer(&cmm_timer); + timer_delete(&cmm_timer); return; } mod_timer(&cmm_timer, jiffies + secs_to_jiffies(cmm_timeout_seconds)); @@ -424,7 +424,7 @@ static int __init cmm_init(void) #endif unregister_sysctl_table(cmm_sysctl_header); out_sysctl: - del_timer_sync(&cmm_timer); + timer_delete_sync(&cmm_timer); return rc; } module_init(cmm_init); @@ -437,7 +437,7 @@ static void __exit cmm_exit(void) #endif unregister_oom_notifier(&cmm_oom_nb); kthread_stop(cmm_thread_ptr); - del_timer_sync(&cmm_timer); + timer_delete_sync(&cmm_timer); cmm_free_pages(cmm_pages, &cmm_pages, &cmm_page_list); cmm_free_pages(cmm_timed_pages, &cmm_timed_pages, &cmm_timed_page_list); }
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c index 31a763e..da84ff6 100644 --- a/arch/s390/mm/fault.c +++ b/arch/s390/mm/fault.c
@@ -376,6 +376,7 @@ void do_protection_exception(struct pt_regs *regs) if (unlikely(!teid.b61)) { if (user_mode(regs)) { /* Low-address protection in user mode: cannot happen */ + dump_fault_info(regs); die(regs, "Low-address protection"); } /*
diff --git a/arch/s390/mm/pfault.c b/arch/s390/mm/pfault.c index b01e73f..e6175d7 100644 --- a/arch/s390/mm/pfault.c +++ b/arch/s390/mm/pfault.c
@@ -9,6 +9,7 @@ #include <linux/init.h> #include <linux/irq.h> #include <asm/asm-extable.h> +#include <asm/asm-offsets.h> #include <asm/pfault.h> #include <asm/diag.h>
diff --git a/arch/s390/pci/pci_bus.c b/arch/s390/pci/pci_bus.c index 0e72503..81bdb54 100644 --- a/arch/s390/pci/pci_bus.c +++ b/arch/s390/pci/pci_bus.c
@@ -287,23 +287,21 @@ static struct zpci_bus *zpci_bus_alloc(int topo, bool topo_is_tid) static void pci_dma_range_setup(struct pci_dev *pdev) { struct zpci_dev *zdev = to_zpci(pdev); - struct bus_dma_region *map; - u64 aligned_end; + u64 aligned_end, size; + dma_addr_t dma_start; + int ret; - map = kzalloc(sizeof(*map), GFP_KERNEL); - if (!map) - return; - - map->cpu_start = 0; - map->dma_start = PAGE_ALIGN(zdev->start_dma); + dma_start = PAGE_ALIGN(zdev->start_dma); aligned_end = PAGE_ALIGN_DOWN(zdev->end_dma + 1); - if (aligned_end >= map->dma_start) - map->size = aligned_end - map->dma_start; + if (aligned_end >= dma_start) + size = aligned_end - dma_start; else - map->size = 0; - WARN_ON_ONCE(map->size == 0); + size = 0; + WARN_ON_ONCE(size == 0); - pdev->dev.dma_range_map = map; + ret = dma_direct_set_offset(&pdev->dev, 0, dma_start, size); + if (ret) + pr_err("Failed to allocate DMA range map for %s\n", pci_name(pdev)); } void pcibios_bus_add_device(struct pci_dev *pdev) @@ -360,6 +358,9 @@ static bool zpci_bus_is_isolated_vf(struct zpci_bus *zbus, struct zpci_dev *zdev { struct pci_dev *pdev; + if (!zdev->vfn) + return false; + pdev = zpci_iov_find_parent_pf(zbus, zdev); if (!pdev) return true;
diff --git a/arch/sh/configs/ap325rxa_defconfig b/arch/sh/configs/ap325rxa_defconfig index 4464a2a..b6f36c9 100644 --- a/arch/sh/configs/ap325rxa_defconfig +++ b/arch/sh/configs/ap325rxa_defconfig
@@ -99,4 +99,3 @@ CONFIG_CRYPTO=y CONFIG_CRYPTO_CBC=y # CONFIG_CRYPTO_ANSI_CPRNG is not set -CONFIG_CRC_T10DIF=y
diff --git a/arch/sh/configs/ecovec24_defconfig b/arch/sh/configs/ecovec24_defconfig index ee1b366..e76694a 100644 --- a/arch/sh/configs/ecovec24_defconfig +++ b/arch/sh/configs/ecovec24_defconfig
@@ -128,4 +128,3 @@ CONFIG_CRYPTO=y CONFIG_CRYPTO_CBC=y # CONFIG_CRYPTO_ANSI_CPRNG is not set -CONFIG_CRC_T10DIF=y
diff --git a/arch/sh/configs/edosk7705_defconfig b/arch/sh/configs/edosk7705_defconfig index 296ed76..ee3f6db 100644 --- a/arch/sh/configs/edosk7705_defconfig +++ b/arch/sh/configs/edosk7705_defconfig
@@ -33,4 +33,3 @@ # CONFIG_PROC_FS is not set # CONFIG_SYSFS is not set # CONFIG_ENABLE_MUST_CHECK is not set -# CONFIG_CRC32 is not set
diff --git a/arch/sh/configs/espt_defconfig b/arch/sh/configs/espt_defconfig index 67716a4..da176f1 100644 --- a/arch/sh/configs/espt_defconfig +++ b/arch/sh/configs/espt_defconfig
@@ -110,4 +110,3 @@ # CONFIG_ENABLE_MUST_CHECK is not set CONFIG_DEBUG_FS=y # CONFIG_CRYPTO_ANSI_CPRNG is not set -CONFIG_CRC_T10DIF=y
diff --git a/arch/sh/configs/hp6xx_defconfig b/arch/sh/configs/hp6xx_defconfig index 77e3185..3582af1 100644 --- a/arch/sh/configs/hp6xx_defconfig +++ b/arch/sh/configs/hp6xx_defconfig
@@ -56,5 +56,3 @@ CONFIG_CRYPTO_MD5=y # CONFIG_CRYPTO_ANSI_CPRNG is not set # CONFIG_CRYPTO_HW is not set -CONFIG_CRC16=y -CONFIG_CRC_T10DIF=y
diff --git a/arch/sh/configs/kfr2r09-romimage_defconfig b/arch/sh/configs/kfr2r09-romimage_defconfig index 42bf341..88fbb65 100644 --- a/arch/sh/configs/kfr2r09-romimage_defconfig +++ b/arch/sh/configs/kfr2r09-romimage_defconfig
@@ -49,4 +49,3 @@ # CONFIG_NETWORK_FILESYSTEMS is not set # CONFIG_ENABLE_MUST_CHECK is not set CONFIG_DEBUG_FS=y -# CONFIG_CRC32 is not set
diff --git a/arch/sh/configs/landisk_defconfig b/arch/sh/configs/landisk_defconfig index d871623..924bb32 100644 --- a/arch/sh/configs/landisk_defconfig +++ b/arch/sh/configs/landisk_defconfig
@@ -111,4 +111,3 @@ CONFIG_NLS_CODEPAGE_932=y CONFIG_SH_STANDARD_BIOS=y # CONFIG_CRYPTO_ANSI_CPRNG is not set -CONFIG_CRC_T10DIF=y
diff --git a/arch/sh/configs/lboxre2_defconfig b/arch/sh/configs/lboxre2_defconfig index 6a23476..0307bb2 100644 --- a/arch/sh/configs/lboxre2_defconfig +++ b/arch/sh/configs/lboxre2_defconfig
@@ -58,4 +58,3 @@ CONFIG_NLS_CODEPAGE_437=y CONFIG_SH_STANDARD_BIOS=y # CONFIG_CRYPTO_ANSI_CPRNG is not set -CONFIG_CRC_T10DIF=y
diff --git a/arch/sh/configs/magicpanelr2_defconfig b/arch/sh/configs/magicpanelr2_defconfig index 8d44374..93b9aa3 100644 --- a/arch/sh/configs/magicpanelr2_defconfig +++ b/arch/sh/configs/magicpanelr2_defconfig
@@ -86,5 +86,3 @@ CONFIG_DEBUG_KOBJECT=y CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y CONFIG_FRAME_POINTER=y -CONFIG_CRC_CCITT=m -CONFIG_CRC16=m
diff --git a/arch/sh/configs/migor_defconfig b/arch/sh/configs/migor_defconfig index 2d1e65c..fc2010c 100644 --- a/arch/sh/configs/migor_defconfig +++ b/arch/sh/configs/migor_defconfig
@@ -90,4 +90,3 @@ CONFIG_CRYPTO_MANAGER=y # CONFIG_CRYPTO_ANSI_CPRNG is not set # CONFIG_CRYPTO_HW is not set -CONFIG_CRC_T10DIF=y
diff --git a/arch/sh/configs/r7780mp_defconfig b/arch/sh/configs/r7780mp_defconfig index 6bd6c0a..f28b8c4 100644 --- a/arch/sh/configs/r7780mp_defconfig +++ b/arch/sh/configs/r7780mp_defconfig
@@ -105,4 +105,3 @@ CONFIG_CRYPTO_PCBC=m CONFIG_CRYPTO_HMAC=y # CONFIG_CRYPTO_ANSI_CPRNG is not set -CONFIG_CRC_T10DIF=y
diff --git a/arch/sh/configs/r7785rp_defconfig b/arch/sh/configs/r7785rp_defconfig index cde6685..3a4239f2 100644 --- a/arch/sh/configs/r7785rp_defconfig +++ b/arch/sh/configs/r7785rp_defconfig
@@ -103,4 +103,3 @@ CONFIG_CRYPTO_PCBC=m CONFIG_CRYPTO_HMAC=y # CONFIG_CRYPTO_ANSI_CPRNG is not set -CONFIG_CRC_T10DIF=y
diff --git a/arch/sh/configs/rts7751r2d1_defconfig b/arch/sh/configs/rts7751r2d1_defconfig index c863a11..69568cc 100644 --- a/arch/sh/configs/rts7751r2d1_defconfig +++ b/arch/sh/configs/rts7751r2d1_defconfig
@@ -87,4 +87,3 @@ CONFIG_NLS_CODEPAGE_932=y CONFIG_DEBUG_FS=y # CONFIG_CRYPTO_ANSI_CPRNG is not set -CONFIG_CRC_T10DIF=y
diff --git a/arch/sh/configs/rts7751r2dplus_defconfig b/arch/sh/configs/rts7751r2dplus_defconfig index 7e4f710..ecb4bdb 100644 --- a/arch/sh/configs/rts7751r2dplus_defconfig +++ b/arch/sh/configs/rts7751r2dplus_defconfig
@@ -92,4 +92,3 @@ CONFIG_NLS_CODEPAGE_932=y CONFIG_DEBUG_FS=y # CONFIG_CRYPTO_ANSI_CPRNG is not set -CONFIG_CRC_T10DIF=y
diff --git a/arch/sh/configs/sdk7780_defconfig b/arch/sh/configs/sdk7780_defconfig index cd24cf0..9870d16 100644 --- a/arch/sh/configs/sdk7780_defconfig +++ b/arch/sh/configs/sdk7780_defconfig
@@ -136,4 +136,3 @@ CONFIG_CRYPTO_MD5=y CONFIG_CRYPTO_DES=y # CONFIG_CRYPTO_ANSI_CPRNG is not set -CONFIG_CRC_T10DIF=y
diff --git a/arch/sh/configs/se7206_defconfig b/arch/sh/configs/se7206_defconfig index 472fdf3..64f9308 100644 --- a/arch/sh/configs/se7206_defconfig +++ b/arch/sh/configs/se7206_defconfig
@@ -101,6 +101,3 @@ CONFIG_CRYPTO_LZO=y # CONFIG_CRYPTO_ANSI_CPRNG is not set # CONFIG_CRYPTO_HW is not set -CONFIG_CRC_CCITT=y -CONFIG_CRC16=y -CONFIG_CRC_ITU_T=y
diff --git a/arch/sh/configs/se7712_defconfig b/arch/sh/configs/se7712_defconfig index 20f07ae..8770a72 100644 --- a/arch/sh/configs/se7712_defconfig +++ b/arch/sh/configs/se7712_defconfig
@@ -57,7 +57,6 @@ CONFIG_NET_SCH_GRED=y CONFIG_NET_SCH_DSMARK=y CONFIG_NET_SCH_NETEM=y -CONFIG_NET_CLS_TCINDEX=y CONFIG_NET_CLS_ROUTE4=y CONFIG_NET_CLS_FW=y CONFIG_MTD=y @@ -97,4 +96,3 @@ CONFIG_CRYPTO_ECB=m CONFIG_CRYPTO_PCBC=m # CONFIG_CRYPTO_ANSI_CPRNG is not set -CONFIG_CRC_CCITT=y
diff --git a/arch/sh/configs/se7721_defconfig b/arch/sh/configs/se7721_defconfig index 00862d3..b15c640 100644 --- a/arch/sh/configs/se7721_defconfig +++ b/arch/sh/configs/se7721_defconfig
@@ -56,7 +56,6 @@ CONFIG_NET_SCH_GRED=y CONFIG_NET_SCH_DSMARK=y CONFIG_NET_SCH_NETEM=y -CONFIG_NET_CLS_TCINDEX=y CONFIG_NET_CLS_ROUTE4=y CONFIG_NET_CLS_FW=y CONFIG_MTD=y @@ -123,4 +122,3 @@ CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y CONFIG_FRAME_POINTER=y # CONFIG_CRYPTO_ANSI_CPRNG is not set -CONFIG_CRC_CCITT=y
diff --git a/arch/sh/configs/se7724_defconfig b/arch/sh/configs/se7724_defconfig index 9652127..9501e69 100644 --- a/arch/sh/configs/se7724_defconfig +++ b/arch/sh/configs/se7724_defconfig
@@ -128,4 +128,3 @@ CONFIG_CRYPTO=y CONFIG_CRYPTO_CBC=y # CONFIG_CRYPTO_ANSI_CPRNG is not set -CONFIG_CRC_T10DIF=y
diff --git a/arch/sh/configs/sh03_defconfig b/arch/sh/configs/sh03_defconfig index 48f38ec..4d75c92 100644 --- a/arch/sh/configs/sh03_defconfig +++ b/arch/sh/configs/sh03_defconfig
@@ -120,6 +120,5 @@ CONFIG_CRYPTO_SHA1=y CONFIG_CRYPTO_DEFLATE=y # CONFIG_CRYPTO_ANSI_CPRNG is not set -CONFIG_CRC_CCITT=y CONFIG_RTC_CLASS=y CONFIG_RTC_DRV_GENERIC=y
diff --git a/arch/sh/configs/sh2007_defconfig b/arch/sh/configs/sh2007_defconfig index 1b1174a..cc6292b 100644 --- a/arch/sh/configs/sh2007_defconfig +++ b/arch/sh/configs/sh2007_defconfig
@@ -193,5 +193,3 @@ CONFIG_CRYPTO_LZO=y # CONFIG_CRYPTO_ANSI_CPRNG is not set # CONFIG_CRYPTO_HW is not set -CONFIG_CRC_CCITT=y -CONFIG_CRC16=y
diff --git a/arch/sh/configs/sh7710voipgw_defconfig b/arch/sh/configs/sh7710voipgw_defconfig index 99a5d07..5b151bb2 100644 --- a/arch/sh/configs/sh7710voipgw_defconfig +++ b/arch/sh/configs/sh7710voipgw_defconfig
@@ -27,7 +27,6 @@ CONFIG_NET_SCHED=y CONFIG_NET_SCH_CBQ=y CONFIG_NET_CLS_BASIC=y -CONFIG_NET_CLS_TCINDEX=y CONFIG_NET_CLS_ROUTE4=y CONFIG_NET_CLS_U32=y CONFIG_MTD=y
diff --git a/arch/sh/configs/sh7724_generic_defconfig b/arch/sh/configs/sh7724_generic_defconfig index 5440bd0..e6298f2 100644 --- a/arch/sh/configs/sh7724_generic_defconfig +++ b/arch/sh/configs/sh7724_generic_defconfig
@@ -39,4 +39,3 @@ # CONFIG_SYSFS is not set # CONFIG_MISC_FILESYSTEMS is not set # CONFIG_ENABLE_MUST_CHECK is not set -# CONFIG_CRC32 is not set
diff --git a/arch/sh/configs/sh7763rdp_defconfig b/arch/sh/configs/sh7763rdp_defconfig index 57923c3..b77b331 100644 --- a/arch/sh/configs/sh7763rdp_defconfig +++ b/arch/sh/configs/sh7763rdp_defconfig
@@ -112,4 +112,3 @@ # CONFIG_ENABLE_MUST_CHECK is not set CONFIG_DEBUG_FS=y # CONFIG_CRYPTO_ANSI_CPRNG is not set -CONFIG_CRC_T10DIF=y
diff --git a/arch/sh/configs/sh7770_generic_defconfig b/arch/sh/configs/sh7770_generic_defconfig index 4338af8..2e2b4698 100644 --- a/arch/sh/configs/sh7770_generic_defconfig +++ b/arch/sh/configs/sh7770_generic_defconfig
@@ -41,4 +41,3 @@ # CONFIG_SYSFS is not set # CONFIG_MISC_FILESYSTEMS is not set # CONFIG_ENABLE_MUST_CHECK is not set -# CONFIG_CRC32 is not set
diff --git a/arch/sh/configs/titan_defconfig b/arch/sh/configs/titan_defconfig index 11ff5fd..f022ada 100644 --- a/arch/sh/configs/titan_defconfig +++ b/arch/sh/configs/titan_defconfig
@@ -119,7 +119,6 @@ CONFIG_NET_SCH_NETEM=m CONFIG_NET_SCH_INGRESS=m CONFIG_NET_CLS_BASIC=m -CONFIG_NET_CLS_TCINDEX=m CONFIG_NET_CLS_ROUTE4=m CONFIG_NET_CLS_FW=m CONFIG_NET_CLS_U32=m @@ -265,4 +264,3 @@ CONFIG_CRYPTO_TEA=m CONFIG_CRYPTO_TWOFISH=m # CONFIG_CRYPTO_ANSI_CPRNG is not set -CONFIG_CRC16=m
diff --git a/arch/sh/drivers/pci/common.c b/arch/sh/drivers/pci/common.c index ab9e791..5442475d 100644 --- a/arch/sh/drivers/pci/common.c +++ b/arch/sh/drivers/pci/common.c
@@ -90,7 +90,7 @@ static void pcibios_enable_err(struct timer_list *t) { struct pci_channel *hose = from_timer(hose, t, err_timer); - del_timer(&hose->err_timer); + timer_delete(&hose->err_timer); printk(KERN_DEBUG "PCI: re-enabling error IRQ.\n"); enable_irq(hose->err_irq); } @@ -99,7 +99,7 @@ static void pcibios_enable_serr(struct timer_list *t) { struct pci_channel *hose = from_timer(hose, t, serr_timer); - del_timer(&hose->serr_timer); + timer_delete(&hose->serr_timer); printk(KERN_DEBUG "PCI: re-enabling system error IRQ.\n"); enable_irq(hose->serr_irq); }
diff --git a/arch/sh/include/asm/pgalloc.h b/arch/sh/include/asm/pgalloc.h index 96d938f..6fe7123 100644 --- a/arch/sh/include/asm/pgalloc.h +++ b/arch/sh/include/asm/pgalloc.h
@@ -32,10 +32,7 @@ static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd, set_pmd(pmd, __pmd((unsigned long)page_address(pte))); } -#define __pte_free_tlb(tlb, pte, addr) \ -do { \ - pagetable_dtor(page_ptdesc(pte)); \ - tlb_remove_page_ptdesc((tlb), (page_ptdesc(pte))); \ -} while (0) +#define __pte_free_tlb(tlb, pte, addr) \ + tlb_remove_ptdesc((tlb), page_ptdesc(pte)) #endif /* __ASM_SH_PGALLOC_H */
diff --git a/arch/sh/kernel/vmlinux.lds.S b/arch/sh/kernel/vmlinux.lds.S index 9644fe1..008c302 100644 --- a/arch/sh/kernel/vmlinux.lds.S +++ b/arch/sh/kernel/vmlinux.lds.S
@@ -71,7 +71,20 @@ . = ALIGN(PAGE_SIZE); __init_end = .; - BSS_SECTION(0, PAGE_SIZE, 4) + __bss_start = .; + SBSS(0) + . = ALIGN(PAGE_SIZE); + .bss : AT(ADDR(.bss) - LOAD_OFFSET) { + BSS_FIRST_SECTIONS + . = ALIGN(PAGE_SIZE); + *(.bss..page_aligned) + . = ALIGN(PAGE_SIZE); + *(.dynbss) + *(BSS_MAIN) + *(COMMON) + . = ALIGN(8); + } + __bss_stop = .; _end = . ; STABS_DEBUG
diff --git a/arch/sparc/configs/sparc64_defconfig b/arch/sparc/configs/sparc64_defconfig index 01b2bdf..f1ba0fe 100644 --- a/arch/sparc/configs/sparc64_defconfig +++ b/arch/sparc/configs/sparc64_defconfig
@@ -229,7 +229,6 @@ CONFIG_CRYPTO_TEA=m CONFIG_CRYPTO_TWOFISH=m # CONFIG_CRYPTO_ANSI_CPRNG is not set -CONFIG_CRC16=m CONFIG_VCC=m CONFIG_PATA_CMD64X=y CONFIG_IP_PNP=y
diff --git a/arch/sparc/kernel/led.c b/arch/sparc/kernel/led.c index ab657b3..f4fb82b 100644 --- a/arch/sparc/kernel/led.c +++ b/arch/sparc/kernel/led.c
@@ -84,7 +84,7 @@ static ssize_t led_proc_write(struct file *file, const char __user *buffer, /* before we change anything we want to stop any running timers, * otherwise calls such as on will have no persistent effect */ - del_timer_sync(&led_blink_timer); + timer_delete_sync(&led_blink_timer); if (!strcmp(buf, "on")) { auxio_set_led(AUXIO_LED_ON); @@ -134,7 +134,7 @@ static int __init led_init(void) static void __exit led_exit(void) { remove_proc_entry("led", NULL); - del_timer_sync(&led_blink_timer); + timer_delete_sync(&led_blink_timer); } module_init(led_init);
diff --git a/arch/um/Kconfig b/arch/um/Kconfig index 18051b1..79509c7 100644 --- a/arch/um/Kconfig +++ b/arch/um/Kconfig
@@ -12,6 +12,7 @@ select ARCH_HAS_KCOV select ARCH_HAS_STRNCPY_FROM_USER select ARCH_HAS_STRNLEN_USER + select ARCH_HAS_STRICT_KERNEL_RWX select HAVE_ARCH_AUDITSYSCALL select HAVE_ARCH_KASAN if X86_64 select HAVE_ARCH_KASAN_VMALLOC if HAVE_ARCH_KASAN
diff --git a/arch/um/drivers/Kconfig b/arch/um/drivers/Kconfig index ede40a1..9cb1960 100644 --- a/arch/um/drivers/Kconfig +++ b/arch/um/drivers/Kconfig
@@ -345,16 +345,20 @@ by providing a fake RTC clock that causes a wakeup at the right time. -config UML_PCI_OVER_VIRTIO - bool "Enable PCI over VIRTIO device simulation" - # in theory, just VIRTIO is enough, but that causes recursion - depends on VIRTIO_UML +config UML_PCI + bool select FORCE_PCI select UML_IOMEM_EMULATION select UML_DMA_EMULATION select PCI_MSI select PCI_LOCKLESS_CONFIG +config UML_PCI_OVER_VIRTIO + bool "Enable PCI over VIRTIO device simulation" + # in theory, just VIRTIO is enough, but that causes recursion + depends on VIRTIO_UML + select UML_PCI + config UML_PCI_OVER_VIRTIO_DEVICE_ID int "set the virtio device ID for PCI emulation" default -1
diff --git a/arch/um/drivers/Makefile b/arch/um/drivers/Makefile index 57882e6..0a58203 100644 --- a/arch/um/drivers/Makefile +++ b/arch/um/drivers/Makefile
@@ -60,7 +60,8 @@ obj-$(CONFIG_UML_RANDOM) += random.o obj-$(CONFIG_VIRTIO_UML) += virtio_uml.o obj-$(CONFIG_UML_RTC) += rtc.o -obj-$(CONFIG_UML_PCI_OVER_VIRTIO) += virt-pci.o +obj-$(CONFIG_UML_PCI) += virt-pci.o +obj-$(CONFIG_UML_PCI_OVER_VIRTIO) += virtio_pcidev.o # pcap_user.o must be added explicitly. USER_OBJS := fd.o null.o pty.o tty.o xterm.o slip_common.o vde_user.o vector_user.o
diff --git a/arch/um/drivers/random.c b/arch/um/drivers/random.c index da985e0d..ca08c91 100644 --- a/arch/um/drivers/random.c +++ b/arch/um/drivers/random.c
@@ -79,7 +79,7 @@ static int __init rng_init (void) if (err < 0) goto err_out_cleanup_hw; - sigio_broken(random_fd); + sigio_broken(); hwrng.name = RNG_MODULE_NAME; hwrng.read = rng_dev_read;
diff --git a/arch/um/drivers/rtc_user.c b/arch/um/drivers/rtc_user.c index 7c3cec4..51e79f3 100644 --- a/arch/um/drivers/rtc_user.c +++ b/arch/um/drivers/rtc_user.c
@@ -39,7 +39,7 @@ int uml_rtc_start(bool timetravel) } /* apparently timerfd won't send SIGIO, use workaround */ - sigio_broken(uml_rtc_irq_fds[0]); + sigio_broken(); err = add_sigio_fd(uml_rtc_irq_fds[0]); if (err < 0) { close(uml_rtc_irq_fds[0]);
diff --git a/arch/um/drivers/ubd.h b/arch/um/drivers/ubd.h index f016fe1..2985c14 100644 --- a/arch/um/drivers/ubd.h +++ b/arch/um/drivers/ubd.h
@@ -7,8 +7,10 @@ #ifndef __UM_UBD_USER_H #define __UM_UBD_USER_H -extern int start_io_thread(unsigned long sp, int *fds_out); -extern int io_thread(void *arg); +#include <os.h> + +int start_io_thread(struct os_helper_thread **td_out, int *fd_out); +void *io_thread(void *arg); extern int kernel_fd; extern int ubd_read_poll(int timeout);
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c index 0b1e61f..4de6613 100644 --- a/arch/um/drivers/ubd_kern.c +++ b/arch/um/drivers/ubd_kern.c
@@ -474,12 +474,12 @@ static irqreturn_t ubd_intr(int irq, void *dev) } /* Only changed by ubd_init, which is an initcall. */ -static int io_pid = -1; +static struct os_helper_thread *io_td; static void kill_io_thread(void) { - if(io_pid != -1) - os_kill_process(io_pid, 1); + if (io_td) + os_kill_helper_thread(io_td); } __uml_exitcall(kill_io_thread); @@ -1104,8 +1104,8 @@ static int __init ubd_init(void) late_initcall(ubd_init); -static int __init ubd_driver_init(void){ - unsigned long stack; +static int __init ubd_driver_init(void) +{ int err; /* Set by CONFIG_BLK_DEV_UBD_SYNC or ubd=sync.*/ @@ -1114,13 +1114,11 @@ static int __init ubd_driver_init(void){ /* Letting ubd=sync be like using ubd#s= instead of ubd#= is * enough. So use anyway the io thread. */ } - stack = alloc_stack(0, 0); - io_pid = start_io_thread(stack + PAGE_SIZE, &thread_fd); - if(io_pid < 0){ + err = start_io_thread(&io_td, &thread_fd); + if (err < 0) { printk(KERN_ERR "ubd : Failed to start I/O thread (errno = %d) - " - "falling back to synchronous I/O\n", -io_pid); - io_pid = -1; + "falling back to synchronous I/O\n", -err); return 0; } err = um_request_irq(UBD_IRQ, thread_fd, IRQ_READ, ubd_intr, @@ -1496,12 +1494,11 @@ int kernel_fd = -1; /* Only changed by the io thread. XXX: currently unused. */ static int io_count; -int io_thread(void *arg) +void *io_thread(void *arg) { int n, count, written, res; - os_set_pdeathsig(); - os_fix_helper_signals(); + os_fix_helper_thread_signals(); while(1){ n = bulk_req_safe_read( @@ -1543,5 +1540,5 @@ int io_thread(void *arg) } while (written < n); } - return 0; + return NULL; }
diff --git a/arch/um/drivers/ubd_user.c b/arch/um/drivers/ubd_user.c index b4f8b8e6..c5e6545 100644 --- a/arch/um/drivers/ubd_user.c +++ b/arch/um/drivers/ubd_user.c
@@ -25,9 +25,9 @@ static struct pollfd kernel_pollfd; -int start_io_thread(unsigned long sp, int *fd_out) +int start_io_thread(struct os_helper_thread **td_out, int *fd_out) { - int pid, fds[2], err; + int fds[2], err; err = os_pipe(fds, 1, 1); if(err < 0){ @@ -47,14 +47,14 @@ int start_io_thread(unsigned long sp, int *fd_out) goto out_close; } - pid = clone(io_thread, (void *) sp, CLONE_FILES | CLONE_VM, NULL); - if(pid < 0){ - err = -errno; - printk("start_io_thread - clone failed : errno = %d\n", errno); + err = os_run_helper_thread(td_out, io_thread, NULL); + if (err < 0) { + printk("%s - failed to run helper thread, err = %d\n", + __func__, -err); goto out_close; } - return(pid); + return 0; out_close: os_close_file(fds[0]);
diff --git a/arch/um/drivers/vector_kern.c b/arch/um/drivers/vector_kern.c index 85b129e..b97bb52 100644 --- a/arch/um/drivers/vector_kern.c +++ b/arch/um/drivers/vector_kern.c
@@ -1112,7 +1112,7 @@ static int vector_net_close(struct net_device *dev) struct vector_private *vp = netdev_priv(dev); netif_stop_queue(dev); - del_timer(&vp->tl); + timer_delete(&vp->tl); vp->opened = false;
diff --git a/arch/um/drivers/virt-pci.c b/arch/um/drivers/virt-pci.c index dd5580f..b83b5a7 100644 --- a/arch/um/drivers/virt-pci.c +++ b/arch/um/drivers/virt-pci.c
@@ -5,52 +5,19 @@ */ #include <linux/module.h> #include <linux/pci.h> -#include <linux/virtio.h> -#include <linux/virtio_config.h> #include <linux/logic_iomem.h> #include <linux/of_platform.h> #include <linux/irqdomain.h> -#include <linux/virtio_pcidev.h> -#include <linux/virtio-uml.h> -#include <linux/delay.h> #include <linux/msi.h> #include <linux/unaligned.h> #include <irq_kern.h> +#include "virt-pci.h" + #define MAX_DEVICES 8 #define MAX_MSI_VECTORS 32 #define CFG_SPACE_SIZE 4096 -/* for MSI-X we have a 32-bit payload */ -#define MAX_IRQ_MSG_SIZE (sizeof(struct virtio_pcidev_msg) + sizeof(u32)) -#define NUM_IRQ_MSGS 10 - -struct um_pci_message_buffer { - struct virtio_pcidev_msg hdr; - u8 data[8]; -}; - -struct um_pci_device { - struct virtio_device *vdev; - - /* for now just standard BARs */ - u8 resptr[PCI_STD_NUM_BARS]; - - struct virtqueue *cmd_vq, *irq_vq; - -#define UM_PCI_WRITE_BUFS 20 - struct um_pci_message_buffer bufs[UM_PCI_WRITE_BUFS + 1]; - void *extra_ptrs[UM_PCI_WRITE_BUFS + 1]; - DECLARE_BITMAP(used_bufs, UM_PCI_WRITE_BUFS); - -#define UM_PCI_STAT_WAITING 0 - unsigned long status; - - int irq; - - bool platform; -}; - struct um_pci_device_reg { struct um_pci_device *dev; void __iomem *iomem; @@ -65,179 +32,15 @@ static struct irq_domain *um_pci_inner_domain; static struct irq_domain *um_pci_msi_domain; static unsigned long um_pci_msi_used[BITS_TO_LONGS(MAX_MSI_VECTORS)]; -static unsigned int um_pci_max_delay_us = 40000; -module_param_named(max_delay_us, um_pci_max_delay_us, uint, 0644); - -static int um_pci_get_buf(struct um_pci_device *dev, bool *posted) -{ - int i; - - for (i = 0; i < UM_PCI_WRITE_BUFS; i++) { - if (!test_and_set_bit(i, dev->used_bufs)) - return i; - } - - *posted = false; - return UM_PCI_WRITE_BUFS; -} - -static void um_pci_free_buf(struct um_pci_device *dev, void *buf) -{ - int i; - - if (buf == &dev->bufs[UM_PCI_WRITE_BUFS]) { - kfree(dev->extra_ptrs[UM_PCI_WRITE_BUFS]); - dev->extra_ptrs[UM_PCI_WRITE_BUFS] = NULL; - return; - } - - for (i = 0; i < UM_PCI_WRITE_BUFS; i++) { - if (buf == &dev->bufs[i]) { - kfree(dev->extra_ptrs[i]); - dev->extra_ptrs[i] = NULL; - WARN_ON(!test_and_clear_bit(i, dev->used_bufs)); - return; - } - } - - WARN_ON(1); -} - -static int um_pci_send_cmd(struct um_pci_device *dev, - struct virtio_pcidev_msg *cmd, - unsigned int cmd_size, - const void *extra, unsigned int extra_size, - void *out, unsigned int out_size) -{ - struct scatterlist out_sg, extra_sg, in_sg; - struct scatterlist *sgs_list[] = { - [0] = &out_sg, - [1] = extra ? &extra_sg : &in_sg, - [2] = extra ? &in_sg : NULL, - }; - struct um_pci_message_buffer *buf; - int delay_count = 0; - bool bounce_out; - int ret, len; - int buf_idx; - bool posted; - - if (WARN_ON(cmd_size < sizeof(*cmd) || cmd_size > sizeof(*buf))) - return -EINVAL; - - switch (cmd->op) { - case VIRTIO_PCIDEV_OP_CFG_WRITE: - case VIRTIO_PCIDEV_OP_MMIO_WRITE: - case VIRTIO_PCIDEV_OP_MMIO_MEMSET: - /* in PCI, writes are posted, so don't wait */ - posted = !out; - WARN_ON(!posted); - break; - default: - posted = false; - break; - } - - bounce_out = !posted && cmd_size <= sizeof(*cmd) && - out && out_size <= sizeof(buf->data); - - buf_idx = um_pci_get_buf(dev, &posted); - buf = &dev->bufs[buf_idx]; - memcpy(buf, cmd, cmd_size); - - if (posted && extra && extra_size > sizeof(buf) - cmd_size) { - dev->extra_ptrs[buf_idx] = kmemdup(extra, extra_size, - GFP_ATOMIC); - - if (!dev->extra_ptrs[buf_idx]) { - um_pci_free_buf(dev, buf); - return -ENOMEM; - } - extra = dev->extra_ptrs[buf_idx]; - } else if (extra && extra_size <= sizeof(buf) - cmd_size) { - memcpy((u8 *)buf + cmd_size, extra, extra_size); - cmd_size += extra_size; - extra_size = 0; - extra = NULL; - cmd = (void *)buf; - } else { - cmd = (void *)buf; - } - - sg_init_one(&out_sg, cmd, cmd_size); - if (extra) - sg_init_one(&extra_sg, extra, extra_size); - /* allow stack for small buffers */ - if (bounce_out) - sg_init_one(&in_sg, buf->data, out_size); - else if (out) - sg_init_one(&in_sg, out, out_size); - - /* add to internal virtio queue */ - ret = virtqueue_add_sgs(dev->cmd_vq, sgs_list, - extra ? 2 : 1, - out ? 1 : 0, - cmd, GFP_ATOMIC); - if (ret) { - um_pci_free_buf(dev, buf); - return ret; - } - - if (posted) { - virtqueue_kick(dev->cmd_vq); - return 0; - } - - /* kick and poll for getting a response on the queue */ - set_bit(UM_PCI_STAT_WAITING, &dev->status); - virtqueue_kick(dev->cmd_vq); - ret = 0; - - while (1) { - void *completed = virtqueue_get_buf(dev->cmd_vq, &len); - - if (completed == buf) - break; - - if (completed) - um_pci_free_buf(dev, completed); - - if (WARN_ONCE(virtqueue_is_broken(dev->cmd_vq) || - ++delay_count > um_pci_max_delay_us, - "um virt-pci delay: %d", delay_count)) { - ret = -EIO; - break; - } - udelay(1); - } - clear_bit(UM_PCI_STAT_WAITING, &dev->status); - - if (bounce_out) - memcpy(out, buf->data, out_size); - - um_pci_free_buf(dev, buf); - - return ret; -} - static unsigned long um_pci_cfgspace_read(void *priv, unsigned int offset, int size) { struct um_pci_device_reg *reg = priv; struct um_pci_device *dev = reg->dev; - struct virtio_pcidev_msg hdr = { - .op = VIRTIO_PCIDEV_OP_CFG_READ, - .size = size, - .addr = offset, - }; - /* max 8, we might not use it all */ - u8 data[8]; if (!dev) return ULONG_MAX; - memset(data, 0xff, sizeof(data)); - switch (size) { case 1: case 2: @@ -251,23 +54,7 @@ static unsigned long um_pci_cfgspace_read(void *priv, unsigned int offset, return ULONG_MAX; } - if (um_pci_send_cmd(dev, &hdr, sizeof(hdr), NULL, 0, data, size)) - return ULONG_MAX; - - switch (size) { - case 1: - return data[0]; - case 2: - return le16_to_cpup((void *)data); - case 4: - return le32_to_cpup((void *)data); -#ifdef CONFIG_64BIT - case 8: - return le64_to_cpup((void *)data); -#endif - default: - return ULONG_MAX; - } + return dev->ops->cfgspace_read(dev, offset, size); } static void um_pci_cfgspace_write(void *priv, unsigned int offset, int size, @@ -275,42 +62,24 @@ static void um_pci_cfgspace_write(void *priv, unsigned int offset, int size, { struct um_pci_device_reg *reg = priv; struct um_pci_device *dev = reg->dev; - struct { - struct virtio_pcidev_msg hdr; - /* maximum size - we may only use parts of it */ - u8 data[8]; - } msg = { - .hdr = { - .op = VIRTIO_PCIDEV_OP_CFG_WRITE, - .size = size, - .addr = offset, - }, - }; if (!dev) return; switch (size) { case 1: - msg.data[0] = (u8)val; - break; case 2: - put_unaligned_le16(val, (void *)msg.data); - break; case 4: - put_unaligned_le32(val, (void *)msg.data); - break; #ifdef CONFIG_64BIT case 8: - put_unaligned_le64(val, (void *)msg.data); - break; #endif + break; default: WARN(1, "invalid config space write size %d\n", size); return; } - WARN_ON(um_pci_send_cmd(dev, &msg.hdr, sizeof(msg), NULL, 0, NULL, 0)); + dev->ops->cfgspace_write(dev, offset, size, val); } static const struct logic_iomem_ops um_pci_device_cfgspace_ops = { @@ -318,6 +87,56 @@ static const struct logic_iomem_ops um_pci_device_cfgspace_ops = { .write = um_pci_cfgspace_write, }; +static unsigned long um_pci_bar_read(void *priv, unsigned int offset, + int size) +{ + u8 *resptr = priv; + struct um_pci_device *dev = container_of(resptr - *resptr, + struct um_pci_device, + resptr[0]); + u8 bar = *resptr; + + switch (size) { + case 1: + case 2: + case 4: +#ifdef CONFIG_64BIT + case 8: +#endif + break; + default: + WARN(1, "invalid bar read size %d\n", size); + return ULONG_MAX; + } + + return dev->ops->bar_read(dev, bar, offset, size); +} + +static void um_pci_bar_write(void *priv, unsigned int offset, int size, + unsigned long val) +{ + u8 *resptr = priv; + struct um_pci_device *dev = container_of(resptr - *resptr, + struct um_pci_device, + resptr[0]); + u8 bar = *resptr; + + switch (size) { + case 1: + case 2: + case 4: +#ifdef CONFIG_64BIT + case 8: +#endif + break; + default: + WARN(1, "invalid bar write size %d\n", size); + return; + } + + dev->ops->bar_write(dev, bar, offset, size, val); +} + static void um_pci_bar_copy_from(void *priv, void *buffer, unsigned int offset, int size) { @@ -325,53 +144,9 @@ static void um_pci_bar_copy_from(void *priv, void *buffer, struct um_pci_device *dev = container_of(resptr - *resptr, struct um_pci_device, resptr[0]); - struct virtio_pcidev_msg hdr = { - .op = VIRTIO_PCIDEV_OP_MMIO_READ, - .bar = *resptr, - .size = size, - .addr = offset, - }; + u8 bar = *resptr; - memset(buffer, 0xff, size); - - um_pci_send_cmd(dev, &hdr, sizeof(hdr), NULL, 0, buffer, size); -} - -static unsigned long um_pci_bar_read(void *priv, unsigned int offset, - int size) -{ - /* 8 is maximum size - we may only use parts of it */ - u8 data[8]; - - switch (size) { - case 1: - case 2: - case 4: -#ifdef CONFIG_64BIT - case 8: -#endif - break; - default: - WARN(1, "invalid config space read size %d\n", size); - return ULONG_MAX; - } - - um_pci_bar_copy_from(priv, data, offset, size); - - switch (size) { - case 1: - return data[0]; - case 2: - return le16_to_cpup((void *)data); - case 4: - return le32_to_cpup((void *)data); -#ifdef CONFIG_64BIT - case 8: - return le64_to_cpup((void *)data); -#endif - default: - return ULONG_MAX; - } + dev->ops->bar_copy_from(dev, bar, buffer, offset, size); } static void um_pci_bar_copy_to(void *priv, unsigned int offset, @@ -381,43 +156,9 @@ static void um_pci_bar_copy_to(void *priv, unsigned int offset, struct um_pci_device *dev = container_of(resptr - *resptr, struct um_pci_device, resptr[0]); - struct virtio_pcidev_msg hdr = { - .op = VIRTIO_PCIDEV_OP_MMIO_WRITE, - .bar = *resptr, - .size = size, - .addr = offset, - }; + u8 bar = *resptr; - um_pci_send_cmd(dev, &hdr, sizeof(hdr), buffer, size, NULL, 0); -} - -static void um_pci_bar_write(void *priv, unsigned int offset, int size, - unsigned long val) -{ - /* maximum size - we may only use parts of it */ - u8 data[8]; - - switch (size) { - case 1: - data[0] = (u8)val; - break; - case 2: - put_unaligned_le16(val, (void *)data); - break; - case 4: - put_unaligned_le32(val, (void *)data); - break; -#ifdef CONFIG_64BIT - case 8: - put_unaligned_le64(val, (void *)data); - break; -#endif - default: - WARN(1, "invalid config space write size %d\n", size); - return; - } - - um_pci_bar_copy_to(priv, offset, data, size); + dev->ops->bar_copy_to(dev, bar, offset, buffer, size); } static void um_pci_bar_set(void *priv, unsigned int offset, u8 value, int size) @@ -426,20 +167,9 @@ static void um_pci_bar_set(void *priv, unsigned int offset, u8 value, int size) struct um_pci_device *dev = container_of(resptr - *resptr, struct um_pci_device, resptr[0]); - struct { - struct virtio_pcidev_msg hdr; - u8 data; - } msg = { - .hdr = { - .op = VIRTIO_PCIDEV_OP_CFG_WRITE, - .bar = *resptr, - .size = size, - .addr = offset, - }, - .data = value, - }; + u8 bar = *resptr; - um_pci_send_cmd(dev, &msg.hdr, sizeof(msg), NULL, 0, NULL, 0); + dev->ops->bar_set(dev, bar, offset, value, size); } static const struct logic_iomem_ops um_pci_device_bar_ops = { @@ -486,76 +216,6 @@ static void um_pci_rescan(void) pci_unlock_rescan_remove(); } -static void um_pci_irq_vq_addbuf(struct virtqueue *vq, void *buf, bool kick) -{ - struct scatterlist sg[1]; - - sg_init_one(sg, buf, MAX_IRQ_MSG_SIZE); - if (virtqueue_add_inbuf(vq, sg, 1, buf, GFP_ATOMIC)) - kfree(buf); - else if (kick) - virtqueue_kick(vq); -} - -static void um_pci_handle_irq_message(struct virtqueue *vq, - struct virtio_pcidev_msg *msg) -{ - struct virtio_device *vdev = vq->vdev; - struct um_pci_device *dev = vdev->priv; - - if (!dev->irq) - return; - - /* we should properly chain interrupts, but on ARCH=um we don't care */ - - switch (msg->op) { - case VIRTIO_PCIDEV_OP_INT: - generic_handle_irq(dev->irq); - break; - case VIRTIO_PCIDEV_OP_MSI: - /* our MSI message is just the interrupt number */ - if (msg->size == sizeof(u32)) - generic_handle_irq(le32_to_cpup((void *)msg->data)); - else - generic_handle_irq(le16_to_cpup((void *)msg->data)); - break; - case VIRTIO_PCIDEV_OP_PME: - /* nothing to do - we already woke up due to the message */ - break; - default: - dev_err(&vdev->dev, "unexpected virt-pci message %d\n", msg->op); - break; - } -} - -static void um_pci_cmd_vq_cb(struct virtqueue *vq) -{ - struct virtio_device *vdev = vq->vdev; - struct um_pci_device *dev = vdev->priv; - void *cmd; - int len; - - if (test_bit(UM_PCI_STAT_WAITING, &dev->status)) - return; - - while ((cmd = virtqueue_get_buf(vq, &len))) - um_pci_free_buf(dev, cmd); -} - -static void um_pci_irq_vq_cb(struct virtqueue *vq) -{ - struct virtio_pcidev_msg *msg; - int len; - - while ((msg = virtqueue_get_buf(vq, &len))) { - if (len >= sizeof(*msg)) - um_pci_handle_irq_message(vq, msg); - - /* recycle the message buffer */ - um_pci_irq_vq_addbuf(vq, msg, true); - } -} - #ifdef CONFIG_OF /* Copied from arch/x86/kernel/devicetree.c */ struct device_node *pcibios_get_phb_of_node(struct pci_bus *bus) @@ -577,200 +237,6 @@ struct device_node *pcibios_get_phb_of_node(struct pci_bus *bus) } #endif -static int um_pci_init_vqs(struct um_pci_device *dev) -{ - struct virtqueue_info vqs_info[] = { - { "cmd", um_pci_cmd_vq_cb }, - { "irq", um_pci_irq_vq_cb }, - }; - struct virtqueue *vqs[2]; - int err, i; - - err = virtio_find_vqs(dev->vdev, 2, vqs, vqs_info, NULL); - if (err) - return err; - - dev->cmd_vq = vqs[0]; - dev->irq_vq = vqs[1]; - - virtio_device_ready(dev->vdev); - - for (i = 0; i < NUM_IRQ_MSGS; i++) { - void *msg = kzalloc(MAX_IRQ_MSG_SIZE, GFP_KERNEL); - - if (msg) - um_pci_irq_vq_addbuf(dev->irq_vq, msg, false); - } - - virtqueue_kick(dev->irq_vq); - - return 0; -} - -static void __um_pci_virtio_platform_remove(struct virtio_device *vdev, - struct um_pci_device *dev) -{ - virtio_reset_device(vdev); - vdev->config->del_vqs(vdev); - - mutex_lock(&um_pci_mtx); - um_pci_platform_device = NULL; - mutex_unlock(&um_pci_mtx); - - kfree(dev); -} - -static int um_pci_virtio_platform_probe(struct virtio_device *vdev, - struct um_pci_device *dev) -{ - int ret; - - dev->platform = true; - - mutex_lock(&um_pci_mtx); - - if (um_pci_platform_device) { - mutex_unlock(&um_pci_mtx); - ret = -EBUSY; - goto out_free; - } - - ret = um_pci_init_vqs(dev); - if (ret) { - mutex_unlock(&um_pci_mtx); - goto out_free; - } - - um_pci_platform_device = dev; - - mutex_unlock(&um_pci_mtx); - - ret = of_platform_default_populate(vdev->dev.of_node, NULL, &vdev->dev); - if (ret) - __um_pci_virtio_platform_remove(vdev, dev); - - return ret; - -out_free: - kfree(dev); - return ret; -} - -static int um_pci_virtio_probe(struct virtio_device *vdev) -{ - struct um_pci_device *dev; - int i, free = -1; - int err = -ENOSPC; - - dev = kzalloc(sizeof(*dev), GFP_KERNEL); - if (!dev) - return -ENOMEM; - - dev->vdev = vdev; - vdev->priv = dev; - - if (of_device_is_compatible(vdev->dev.of_node, "simple-bus")) - return um_pci_virtio_platform_probe(vdev, dev); - - mutex_lock(&um_pci_mtx); - for (i = 0; i < MAX_DEVICES; i++) { - if (um_pci_devices[i].dev) - continue; - free = i; - break; - } - - if (free < 0) - goto error; - - err = um_pci_init_vqs(dev); - if (err) - goto error; - - dev->irq = irq_alloc_desc(numa_node_id()); - if (dev->irq < 0) { - err = dev->irq; - goto err_reset; - } - um_pci_devices[free].dev = dev; - vdev->priv = dev; - - mutex_unlock(&um_pci_mtx); - - device_set_wakeup_enable(&vdev->dev, true); - - /* - * In order to do suspend-resume properly, don't allow VQs - * to be suspended. - */ - virtio_uml_set_no_vq_suspend(vdev, true); - - um_pci_rescan(); - return 0; -err_reset: - virtio_reset_device(vdev); - vdev->config->del_vqs(vdev); -error: - mutex_unlock(&um_pci_mtx); - kfree(dev); - return err; -} - -static void um_pci_virtio_remove(struct virtio_device *vdev) -{ - struct um_pci_device *dev = vdev->priv; - int i; - - if (dev->platform) { - of_platform_depopulate(&vdev->dev); - __um_pci_virtio_platform_remove(vdev, dev); - return; - } - - device_set_wakeup_enable(&vdev->dev, false); - - mutex_lock(&um_pci_mtx); - for (i = 0; i < MAX_DEVICES; i++) { - if (um_pci_devices[i].dev != dev) - continue; - - um_pci_devices[i].dev = NULL; - irq_free_desc(dev->irq); - - break; - } - mutex_unlock(&um_pci_mtx); - - if (i < MAX_DEVICES) { - struct pci_dev *pci_dev; - - pci_dev = pci_get_slot(bridge->bus, i); - if (pci_dev) - pci_stop_and_remove_bus_device_locked(pci_dev); - } - - /* Stop all virtqueues */ - virtio_reset_device(vdev); - dev->cmd_vq = NULL; - dev->irq_vq = NULL; - vdev->config->del_vqs(vdev); - - kfree(dev); -} - -static struct virtio_device_id id_table[] = { - { CONFIG_UML_PCI_OVER_VIRTIO_DEVICE_ID, VIRTIO_DEV_ANY_ID }, - { 0 }, -}; -MODULE_DEVICE_TABLE(virtio, id_table); - -static struct virtio_driver um_pci_virtio_driver = { - .driver.name = "virtio-pci", - .id_table = id_table, - .probe = um_pci_virtio_probe, - .remove = um_pci_virtio_remove, -}; - static struct resource virt_cfgspace_resource = { .name = "PCI config space", .start = 0xf0000000 - MAX_DEVICES * CFG_SPACE_SIZE, @@ -889,7 +355,7 @@ static void um_pci_compose_msi_msg(struct irq_data *data, struct msi_msg *msg) } static struct irq_chip um_pci_msi_bottom_irq_chip = { - .name = "UM virtio MSI", + .name = "UM virtual MSI", .irq_compose_msi_msg = um_pci_compose_msi_msg, }; @@ -939,7 +405,7 @@ static const struct irq_domain_ops um_pci_inner_domain_ops = { }; static struct irq_chip um_pci_msi_irq_chip = { - .name = "UM virtio PCIe MSI", + .name = "UM virtual PCIe MSI", .irq_mask = pci_msi_mask_irq, .irq_unmask = pci_msi_unmask_irq, }; @@ -998,6 +464,78 @@ static struct resource virt_platform_resource = { .flags = IORESOURCE_MEM, }; +int um_pci_device_register(struct um_pci_device *dev) +{ + int i, free = -1; + int err = 0; + + mutex_lock(&um_pci_mtx); + for (i = 0; i < MAX_DEVICES; i++) { + if (um_pci_devices[i].dev) + continue; + free = i; + break; + } + + if (free < 0) { + err = -ENOSPC; + goto out; + } + + dev->irq = irq_alloc_desc(numa_node_id()); + if (dev->irq < 0) { + err = dev->irq; + goto out; + } + + um_pci_devices[free].dev = dev; + +out: + mutex_unlock(&um_pci_mtx); + if (!err) + um_pci_rescan(); + return err; +} + +void um_pci_device_unregister(struct um_pci_device *dev) +{ + int i; + + mutex_lock(&um_pci_mtx); + for (i = 0; i < MAX_DEVICES; i++) { + if (um_pci_devices[i].dev != dev) + continue; + um_pci_devices[i].dev = NULL; + irq_free_desc(dev->irq); + break; + } + mutex_unlock(&um_pci_mtx); + + if (i < MAX_DEVICES) { + struct pci_dev *pci_dev; + + pci_dev = pci_get_slot(bridge->bus, i); + if (pci_dev) + pci_stop_and_remove_bus_device_locked(pci_dev); + } +} + +int um_pci_platform_device_register(struct um_pci_device *dev) +{ + guard(mutex)(&um_pci_mtx); + if (um_pci_platform_device) + return -EBUSY; + um_pci_platform_device = dev; + return 0; +} + +void um_pci_platform_device_unregister(struct um_pci_device *dev) +{ + guard(mutex)(&um_pci_mtx); + if (um_pci_platform_device == dev) + um_pci_platform_device = NULL; +} + static int __init um_pci_init(void) { struct irq_domain_info inner_domain_info = { @@ -1014,10 +552,6 @@ static int __init um_pci_init(void) WARN_ON(logic_iomem_add_region(&virt_platform_resource, &um_pci_platform_ops)); - if (WARN(CONFIG_UML_PCI_OVER_VIRTIO_DEVICE_ID < 0, - "No virtio device ID configured for PCI - no PCI support\n")) - return 0; - bridge = pci_alloc_host_bridge(0); if (!bridge) { err = -ENOMEM; @@ -1065,10 +599,8 @@ static int __init um_pci_init(void) if (err) goto free; - err = register_virtio_driver(&um_pci_virtio_driver); - if (err) - goto free; return 0; + free: if (!IS_ERR_OR_NULL(um_pci_inner_domain)) irq_domain_remove(um_pci_inner_domain); @@ -1080,11 +612,10 @@ static int __init um_pci_init(void) } return err; } -module_init(um_pci_init); +device_initcall(um_pci_init); static void __exit um_pci_exit(void) { - unregister_virtio_driver(&um_pci_virtio_driver); irq_domain_remove(um_pci_msi_domain); irq_domain_remove(um_pci_inner_domain); pci_free_resource_list(&bridge->windows);
diff --git a/arch/um/drivers/virt-pci.h b/arch/um/drivers/virt-pci.h new file mode 100644 index 0000000..b20d147 --- /dev/null +++ b/arch/um/drivers/virt-pci.h
@@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __UM_VIRT_PCI_H +#define __UM_VIRT_PCI_H + +#include <linux/pci.h> + +struct um_pci_device { + const struct um_pci_ops *ops; + + /* for now just standard BARs */ + u8 resptr[PCI_STD_NUM_BARS]; + + int irq; +}; + +struct um_pci_ops { + unsigned long (*cfgspace_read)(struct um_pci_device *dev, + unsigned int offset, int size); + void (*cfgspace_write)(struct um_pci_device *dev, unsigned int offset, + int size, unsigned long val); + + unsigned long (*bar_read)(struct um_pci_device *dev, int bar, + unsigned int offset, int size); + void (*bar_write)(struct um_pci_device *dev, int bar, + unsigned int offset, int size, unsigned long val); + + void (*bar_copy_from)(struct um_pci_device *dev, int bar, void *buffer, + unsigned int offset, int size); + void (*bar_copy_to)(struct um_pci_device *dev, int bar, + unsigned int offset, const void *buffer, int size); + void (*bar_set)(struct um_pci_device *dev, int bar, + unsigned int offset, u8 value, int size); +}; + +int um_pci_device_register(struct um_pci_device *dev); +void um_pci_device_unregister(struct um_pci_device *dev); + +int um_pci_platform_device_register(struct um_pci_device *dev); +void um_pci_platform_device_unregister(struct um_pci_device *dev); + +#endif /* __UM_VIRT_PCI_H */
diff --git a/arch/um/drivers/virtio_pcidev.c b/arch/um/drivers/virtio_pcidev.c new file mode 100644 index 0000000..3c4c4c9 --- /dev/null +++ b/arch/um/drivers/virtio_pcidev.c
@@ -0,0 +1,628 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2020 Intel Corporation + * Author: Johannes Berg <johannes@sipsolutions.net> + */ +#include <linux/module.h> +#include <linux/pci.h> +#include <linux/virtio.h> +#include <linux/virtio_config.h> +#include <linux/logic_iomem.h> +#include <linux/of_platform.h> +#include <linux/irqdomain.h> +#include <linux/virtio_pcidev.h> +#include <linux/virtio-uml.h> +#include <linux/delay.h> +#include <linux/msi.h> +#include <linux/unaligned.h> +#include <irq_kern.h> + +#include "virt-pci.h" + +#define to_virtio_pcidev(_pdev) \ + container_of(_pdev, struct virtio_pcidev_device, pdev) + +/* for MSI-X we have a 32-bit payload */ +#define MAX_IRQ_MSG_SIZE (sizeof(struct virtio_pcidev_msg) + sizeof(u32)) +#define NUM_IRQ_MSGS 10 + +struct virtio_pcidev_message_buffer { + struct virtio_pcidev_msg hdr; + u8 data[8]; +}; + +struct virtio_pcidev_device { + struct um_pci_device pdev; + struct virtio_device *vdev; + + struct virtqueue *cmd_vq, *irq_vq; + +#define VIRTIO_PCIDEV_WRITE_BUFS 20 + struct virtio_pcidev_message_buffer bufs[VIRTIO_PCIDEV_WRITE_BUFS + 1]; + void *extra_ptrs[VIRTIO_PCIDEV_WRITE_BUFS + 1]; + DECLARE_BITMAP(used_bufs, VIRTIO_PCIDEV_WRITE_BUFS); + +#define UM_PCI_STAT_WAITING 0 + unsigned long status; + + bool platform; +}; + +static unsigned int virtio_pcidev_max_delay_us = 40000; +module_param_named(max_delay_us, virtio_pcidev_max_delay_us, uint, 0644); + +static int virtio_pcidev_get_buf(struct virtio_pcidev_device *dev, bool *posted) +{ + int i; + + for (i = 0; i < VIRTIO_PCIDEV_WRITE_BUFS; i++) { + if (!test_and_set_bit(i, dev->used_bufs)) + return i; + } + + *posted = false; + return VIRTIO_PCIDEV_WRITE_BUFS; +} + +static void virtio_pcidev_free_buf(struct virtio_pcidev_device *dev, void *buf) +{ + int i; + + if (buf == &dev->bufs[VIRTIO_PCIDEV_WRITE_BUFS]) { + kfree(dev->extra_ptrs[VIRTIO_PCIDEV_WRITE_BUFS]); + dev->extra_ptrs[VIRTIO_PCIDEV_WRITE_BUFS] = NULL; + return; + } + + for (i = 0; i < VIRTIO_PCIDEV_WRITE_BUFS; i++) { + if (buf == &dev->bufs[i]) { + kfree(dev->extra_ptrs[i]); + dev->extra_ptrs[i] = NULL; + WARN_ON(!test_and_clear_bit(i, dev->used_bufs)); + return; + } + } + + WARN_ON(1); +} + +static int virtio_pcidev_send_cmd(struct virtio_pcidev_device *dev, + struct virtio_pcidev_msg *cmd, + unsigned int cmd_size, + const void *extra, unsigned int extra_size, + void *out, unsigned int out_size) +{ + struct scatterlist out_sg, extra_sg, in_sg; + struct scatterlist *sgs_list[] = { + [0] = &out_sg, + [1] = extra ? &extra_sg : &in_sg, + [2] = extra ? &in_sg : NULL, + }; + struct virtio_pcidev_message_buffer *buf; + int delay_count = 0; + bool bounce_out; + int ret, len; + int buf_idx; + bool posted; + + if (WARN_ON(cmd_size < sizeof(*cmd) || cmd_size > sizeof(*buf))) + return -EINVAL; + + switch (cmd->op) { + case VIRTIO_PCIDEV_OP_CFG_WRITE: + case VIRTIO_PCIDEV_OP_MMIO_WRITE: + case VIRTIO_PCIDEV_OP_MMIO_MEMSET: + /* in PCI, writes are posted, so don't wait */ + posted = !out; + WARN_ON(!posted); + break; + default: + posted = false; + break; + } + + bounce_out = !posted && cmd_size <= sizeof(*cmd) && + out && out_size <= sizeof(buf->data); + + buf_idx = virtio_pcidev_get_buf(dev, &posted); + buf = &dev->bufs[buf_idx]; + memcpy(buf, cmd, cmd_size); + + if (posted && extra && extra_size > sizeof(buf) - cmd_size) { + dev->extra_ptrs[buf_idx] = kmemdup(extra, extra_size, + GFP_ATOMIC); + + if (!dev->extra_ptrs[buf_idx]) { + virtio_pcidev_free_buf(dev, buf); + return -ENOMEM; + } + extra = dev->extra_ptrs[buf_idx]; + } else if (extra && extra_size <= sizeof(buf) - cmd_size) { + memcpy((u8 *)buf + cmd_size, extra, extra_size); + cmd_size += extra_size; + extra_size = 0; + extra = NULL; + cmd = (void *)buf; + } else { + cmd = (void *)buf; + } + + sg_init_one(&out_sg, cmd, cmd_size); + if (extra) + sg_init_one(&extra_sg, extra, extra_size); + /* allow stack for small buffers */ + if (bounce_out) + sg_init_one(&in_sg, buf->data, out_size); + else if (out) + sg_init_one(&in_sg, out, out_size); + + /* add to internal virtio queue */ + ret = virtqueue_add_sgs(dev->cmd_vq, sgs_list, + extra ? 2 : 1, + out ? 1 : 0, + cmd, GFP_ATOMIC); + if (ret) { + virtio_pcidev_free_buf(dev, buf); + return ret; + } + + if (posted) { + virtqueue_kick(dev->cmd_vq); + return 0; + } + + /* kick and poll for getting a response on the queue */ + set_bit(UM_PCI_STAT_WAITING, &dev->status); + virtqueue_kick(dev->cmd_vq); + ret = 0; + + while (1) { + void *completed = virtqueue_get_buf(dev->cmd_vq, &len); + + if (completed == buf) + break; + + if (completed) + virtio_pcidev_free_buf(dev, completed); + + if (WARN_ONCE(virtqueue_is_broken(dev->cmd_vq) || + ++delay_count > virtio_pcidev_max_delay_us, + "um virt-pci delay: %d", delay_count)) { + ret = -EIO; + break; + } + udelay(1); + } + clear_bit(UM_PCI_STAT_WAITING, &dev->status); + + if (bounce_out) + memcpy(out, buf->data, out_size); + + virtio_pcidev_free_buf(dev, buf); + + return ret; +} + +static unsigned long virtio_pcidev_cfgspace_read(struct um_pci_device *pdev, + unsigned int offset, int size) +{ + struct virtio_pcidev_device *dev = to_virtio_pcidev(pdev); + struct virtio_pcidev_msg hdr = { + .op = VIRTIO_PCIDEV_OP_CFG_READ, + .size = size, + .addr = offset, + }; + /* max 8, we might not use it all */ + u8 data[8]; + + memset(data, 0xff, sizeof(data)); + + /* size has been checked in um_pci_cfgspace_read() */ + if (virtio_pcidev_send_cmd(dev, &hdr, sizeof(hdr), NULL, 0, data, size)) + return ULONG_MAX; + + switch (size) { + case 1: + return data[0]; + case 2: + return le16_to_cpup((void *)data); + case 4: + return le32_to_cpup((void *)data); +#ifdef CONFIG_64BIT + case 8: + return le64_to_cpup((void *)data); +#endif + default: + return ULONG_MAX; + } +} + +static void virtio_pcidev_cfgspace_write(struct um_pci_device *pdev, + unsigned int offset, int size, + unsigned long val) +{ + struct virtio_pcidev_device *dev = to_virtio_pcidev(pdev); + struct { + struct virtio_pcidev_msg hdr; + /* maximum size - we may only use parts of it */ + u8 data[8]; + } msg = { + .hdr = { + .op = VIRTIO_PCIDEV_OP_CFG_WRITE, + .size = size, + .addr = offset, + }, + }; + + /* size has been checked in um_pci_cfgspace_write() */ + switch (size) { + case 1: + msg.data[0] = (u8)val; + break; + case 2: + put_unaligned_le16(val, (void *)msg.data); + break; + case 4: + put_unaligned_le32(val, (void *)msg.data); + break; +#ifdef CONFIG_64BIT + case 8: + put_unaligned_le64(val, (void *)msg.data); + break; +#endif + } + + WARN_ON(virtio_pcidev_send_cmd(dev, &msg.hdr, sizeof(msg), NULL, 0, NULL, 0)); +} + +static void virtio_pcidev_bar_copy_from(struct um_pci_device *pdev, + int bar, void *buffer, + unsigned int offset, int size) +{ + struct virtio_pcidev_device *dev = to_virtio_pcidev(pdev); + struct virtio_pcidev_msg hdr = { + .op = VIRTIO_PCIDEV_OP_MMIO_READ, + .bar = bar, + .size = size, + .addr = offset, + }; + + memset(buffer, 0xff, size); + + virtio_pcidev_send_cmd(dev, &hdr, sizeof(hdr), NULL, 0, buffer, size); +} + +static unsigned long virtio_pcidev_bar_read(struct um_pci_device *pdev, int bar, + unsigned int offset, int size) +{ + /* 8 is maximum size - we may only use parts of it */ + u8 data[8]; + + /* size has been checked in um_pci_bar_read() */ + virtio_pcidev_bar_copy_from(pdev, bar, data, offset, size); + + switch (size) { + case 1: + return data[0]; + case 2: + return le16_to_cpup((void *)data); + case 4: + return le32_to_cpup((void *)data); +#ifdef CONFIG_64BIT + case 8: + return le64_to_cpup((void *)data); +#endif + default: + return ULONG_MAX; + } +} + +static void virtio_pcidev_bar_copy_to(struct um_pci_device *pdev, + int bar, unsigned int offset, + const void *buffer, int size) +{ + struct virtio_pcidev_device *dev = to_virtio_pcidev(pdev); + struct virtio_pcidev_msg hdr = { + .op = VIRTIO_PCIDEV_OP_MMIO_WRITE, + .bar = bar, + .size = size, + .addr = offset, + }; + + virtio_pcidev_send_cmd(dev, &hdr, sizeof(hdr), buffer, size, NULL, 0); +} + +static void virtio_pcidev_bar_write(struct um_pci_device *pdev, int bar, + unsigned int offset, int size, + unsigned long val) +{ + /* maximum size - we may only use parts of it */ + u8 data[8]; + + /* size has been checked in um_pci_bar_write() */ + switch (size) { + case 1: + data[0] = (u8)val; + break; + case 2: + put_unaligned_le16(val, (void *)data); + break; + case 4: + put_unaligned_le32(val, (void *)data); + break; +#ifdef CONFIG_64BIT + case 8: + put_unaligned_le64(val, (void *)data); + break; +#endif + } + + virtio_pcidev_bar_copy_to(pdev, bar, offset, data, size); +} + +static void virtio_pcidev_bar_set(struct um_pci_device *pdev, int bar, + unsigned int offset, u8 value, int size) +{ + struct virtio_pcidev_device *dev = to_virtio_pcidev(pdev); + struct { + struct virtio_pcidev_msg hdr; + u8 data; + } msg = { + .hdr = { + .op = VIRTIO_PCIDEV_OP_CFG_WRITE, + .bar = bar, + .size = size, + .addr = offset, + }, + .data = value, + }; + + virtio_pcidev_send_cmd(dev, &msg.hdr, sizeof(msg), NULL, 0, NULL, 0); +} + +static const struct um_pci_ops virtio_pcidev_um_pci_ops = { + .cfgspace_read = virtio_pcidev_cfgspace_read, + .cfgspace_write = virtio_pcidev_cfgspace_write, + .bar_read = virtio_pcidev_bar_read, + .bar_write = virtio_pcidev_bar_write, + .bar_copy_from = virtio_pcidev_bar_copy_from, + .bar_copy_to = virtio_pcidev_bar_copy_to, + .bar_set = virtio_pcidev_bar_set, +}; + +static void virtio_pcidev_irq_vq_addbuf(struct virtqueue *vq, void *buf, bool kick) +{ + struct scatterlist sg[1]; + + sg_init_one(sg, buf, MAX_IRQ_MSG_SIZE); + if (virtqueue_add_inbuf(vq, sg, 1, buf, GFP_ATOMIC)) + kfree(buf); + else if (kick) + virtqueue_kick(vq); +} + +static void virtio_pcidev_handle_irq_message(struct virtqueue *vq, + struct virtio_pcidev_msg *msg) +{ + struct virtio_device *vdev = vq->vdev; + struct virtio_pcidev_device *dev = vdev->priv; + + if (!dev->pdev.irq) + return; + + /* we should properly chain interrupts, but on ARCH=um we don't care */ + + switch (msg->op) { + case VIRTIO_PCIDEV_OP_INT: + generic_handle_irq(dev->pdev.irq); + break; + case VIRTIO_PCIDEV_OP_MSI: + /* our MSI message is just the interrupt number */ + if (msg->size == sizeof(u32)) + generic_handle_irq(le32_to_cpup((void *)msg->data)); + else + generic_handle_irq(le16_to_cpup((void *)msg->data)); + break; + case VIRTIO_PCIDEV_OP_PME: + /* nothing to do - we already woke up due to the message */ + break; + default: + dev_err(&vdev->dev, "unexpected virt-pci message %d\n", msg->op); + break; + } +} + +static void virtio_pcidev_cmd_vq_cb(struct virtqueue *vq) +{ + struct virtio_device *vdev = vq->vdev; + struct virtio_pcidev_device *dev = vdev->priv; + void *cmd; + int len; + + if (test_bit(UM_PCI_STAT_WAITING, &dev->status)) + return; + + while ((cmd = virtqueue_get_buf(vq, &len))) + virtio_pcidev_free_buf(dev, cmd); +} + +static void virtio_pcidev_irq_vq_cb(struct virtqueue *vq) +{ + struct virtio_pcidev_msg *msg; + int len; + + while ((msg = virtqueue_get_buf(vq, &len))) { + if (len >= sizeof(*msg)) + virtio_pcidev_handle_irq_message(vq, msg); + + /* recycle the message buffer */ + virtio_pcidev_irq_vq_addbuf(vq, msg, true); + } +} + +static int virtio_pcidev_init_vqs(struct virtio_pcidev_device *dev) +{ + struct virtqueue_info vqs_info[] = { + { "cmd", virtio_pcidev_cmd_vq_cb }, + { "irq", virtio_pcidev_irq_vq_cb }, + }; + struct virtqueue *vqs[2]; + int err, i; + + err = virtio_find_vqs(dev->vdev, 2, vqs, vqs_info, NULL); + if (err) + return err; + + dev->cmd_vq = vqs[0]; + dev->irq_vq = vqs[1]; + + virtio_device_ready(dev->vdev); + + for (i = 0; i < NUM_IRQ_MSGS; i++) { + void *msg = kzalloc(MAX_IRQ_MSG_SIZE, GFP_KERNEL); + + if (msg) + virtio_pcidev_irq_vq_addbuf(dev->irq_vq, msg, false); + } + + virtqueue_kick(dev->irq_vq); + + return 0; +} + +static void __virtio_pcidev_virtio_platform_remove(struct virtio_device *vdev, + struct virtio_pcidev_device *dev) +{ + um_pci_platform_device_unregister(&dev->pdev); + + virtio_reset_device(vdev); + vdev->config->del_vqs(vdev); + + kfree(dev); +} + +static int virtio_pcidev_virtio_platform_probe(struct virtio_device *vdev, + struct virtio_pcidev_device *dev) +{ + int err; + + dev->platform = true; + + err = virtio_pcidev_init_vqs(dev); + if (err) + goto err_free; + + err = um_pci_platform_device_register(&dev->pdev); + if (err) + goto err_reset; + + err = of_platform_default_populate(vdev->dev.of_node, NULL, &vdev->dev); + if (err) + goto err_unregister; + + return 0; + +err_unregister: + um_pci_platform_device_unregister(&dev->pdev); +err_reset: + virtio_reset_device(vdev); + vdev->config->del_vqs(vdev); +err_free: + kfree(dev); + return err; +} + +static int virtio_pcidev_virtio_probe(struct virtio_device *vdev) +{ + struct virtio_pcidev_device *dev; + int err; + + dev = kzalloc(sizeof(*dev), GFP_KERNEL); + if (!dev) + return -ENOMEM; + + dev->vdev = vdev; + vdev->priv = dev; + + dev->pdev.ops = &virtio_pcidev_um_pci_ops; + + if (of_device_is_compatible(vdev->dev.of_node, "simple-bus")) + return virtio_pcidev_virtio_platform_probe(vdev, dev); + + err = virtio_pcidev_init_vqs(dev); + if (err) + goto err_free; + + err = um_pci_device_register(&dev->pdev); + if (err) + goto err_reset; + + device_set_wakeup_enable(&vdev->dev, true); + + /* + * In order to do suspend-resume properly, don't allow VQs + * to be suspended. + */ + virtio_uml_set_no_vq_suspend(vdev, true); + + return 0; + +err_reset: + virtio_reset_device(vdev); + vdev->config->del_vqs(vdev); +err_free: + kfree(dev); + return err; +} + +static void virtio_pcidev_virtio_remove(struct virtio_device *vdev) +{ + struct virtio_pcidev_device *dev = vdev->priv; + + if (dev->platform) { + of_platform_depopulate(&vdev->dev); + __virtio_pcidev_virtio_platform_remove(vdev, dev); + return; + } + + device_set_wakeup_enable(&vdev->dev, false); + + um_pci_device_unregister(&dev->pdev); + + /* Stop all virtqueues */ + virtio_reset_device(vdev); + dev->cmd_vq = NULL; + dev->irq_vq = NULL; + vdev->config->del_vqs(vdev); + + kfree(dev); +} + +static struct virtio_device_id id_table[] = { + { CONFIG_UML_PCI_OVER_VIRTIO_DEVICE_ID, VIRTIO_DEV_ANY_ID }, + { 0 }, +}; +MODULE_DEVICE_TABLE(virtio, id_table); + +static struct virtio_driver virtio_pcidev_virtio_driver = { + .driver.name = "virtio-pci", + .id_table = id_table, + .probe = virtio_pcidev_virtio_probe, + .remove = virtio_pcidev_virtio_remove, +}; + +static int __init virtio_pcidev_init(void) +{ + if (WARN(CONFIG_UML_PCI_OVER_VIRTIO_DEVICE_ID < 0, + "No virtio device ID configured for PCI - no PCI support\n")) + return 0; + + return register_virtio_driver(&virtio_pcidev_virtio_driver); +} +late_initcall(virtio_pcidev_init); + +static void __exit virtio_pcidev_exit(void) +{ + unregister_virtio_driver(&virtio_pcidev_virtio_driver); +} +module_exit(virtio_pcidev_exit);
diff --git a/arch/um/include/asm/Kbuild b/arch/um/include/asm/Kbuild index 428f2c5..04ab3b6 100644 --- a/arch/um/include/asm/Kbuild +++ b/arch/um/include/asm/Kbuild
@@ -13,6 +13,7 @@ generic-y += kdebug.h generic-y += mcs_spinlock.h generic-y += mmiowb.h +generic-y += module.h generic-y += module.lds.h generic-y += param.h generic-y += parport.h
diff --git a/arch/um/include/asm/pgalloc.h b/arch/um/include/asm/pgalloc.h index f0af23c3..826ec44 100644 --- a/arch/um/include/asm/pgalloc.h +++ b/arch/um/include/asm/pgalloc.h
@@ -25,27 +25,18 @@ */ extern pgd_t *pgd_alloc(struct mm_struct *); -#define __pte_free_tlb(tlb, pte, address) \ -do { \ - pagetable_dtor(page_ptdesc(pte)); \ - tlb_remove_page_ptdesc((tlb), (page_ptdesc(pte))); \ -} while (0) +#define __pte_free_tlb(tlb, pte, address) \ + tlb_remove_ptdesc((tlb), page_ptdesc(pte)) #if CONFIG_PGTABLE_LEVELS > 2 -#define __pmd_free_tlb(tlb, pmd, address) \ -do { \ - pagetable_dtor(virt_to_ptdesc(pmd)); \ - tlb_remove_page_ptdesc((tlb), virt_to_ptdesc(pmd)); \ -} while (0) +#define __pmd_free_tlb(tlb, pmd, address) \ + tlb_remove_ptdesc((tlb), virt_to_ptdesc(pmd)) #if CONFIG_PGTABLE_LEVELS > 3 -#define __pud_free_tlb(tlb, pud, address) \ -do { \ - pagetable_dtor(virt_to_ptdesc(pud)); \ - tlb_remove_page_ptdesc((tlb), virt_to_ptdesc(pud)); \ -} while (0) +#define __pud_free_tlb(tlb, pud, address) \ + tlb_remove_ptdesc((tlb), virt_to_ptdesc(pud)) #endif #endif
diff --git a/arch/um/include/asm/processor-generic.h b/arch/um/include/asm/processor-generic.h index 5d6356e..8a789c1 100644 --- a/arch/um/include/asm/processor-generic.h +++ b/arch/um/include/asm/processor-generic.h
@@ -31,6 +31,8 @@ struct thread_struct { } thread; } request; + void *segv_continue; + /* Contains variable sized FP registers */ struct pt_regs regs; };
diff --git a/arch/um/include/asm/uaccess.h b/arch/um/include/asm/uaccess.h index 1d4b6bb..3a08f90 100644 --- a/arch/um/include/asm/uaccess.h +++ b/arch/um/include/asm/uaccess.h
@@ -9,6 +9,7 @@ #include <asm/elf.h> #include <linux/unaligned.h> +#include <sysdep/faultinfo.h> #define __under_task_size(addr, size) \ (((unsigned long) (addr) < TASK_SIZE) && \ @@ -44,19 +45,28 @@ static inline int __access_ok(const void __user *ptr, unsigned long size) __access_ok_vsyscall(addr, size)); } -/* no pagefaults for kernel addresses in um */ #define __get_kernel_nofault(dst, src, type, err_label) \ do { \ - *((type *)dst) = get_unaligned((type *)(src)); \ - if (0) /* make sure the label looks used to the compiler */ \ + int __faulted; \ + \ + ___backtrack_faulted(__faulted); \ + if (__faulted) { \ + *((type *)dst) = (type) 0; \ goto err_label; \ + } \ + *((type *)dst) = get_unaligned((type *)(src)); \ + current->thread.segv_continue = NULL; \ } while (0) #define __put_kernel_nofault(dst, src, type, err_label) \ do { \ - put_unaligned(*((type *)src), (type *)(dst)); \ - if (0) /* make sure the label looks used to the compiler */ \ + int __faulted; \ + \ + ___backtrack_faulted(__faulted); \ + if (__faulted) \ goto err_label; \ + put_unaligned(*((type *)src), (type *)(dst)); \ + current->thread.segv_continue = NULL; \ } while (0) #endif
diff --git a/arch/um/include/linux/time-internal.h b/arch/um/include/linux/time-internal.h index b222266..138908b 100644 --- a/arch/um/include/linux/time-internal.h +++ b/arch/um/include/linux/time-internal.h
@@ -83,6 +83,8 @@ extern void time_travel_not_configured(void); #define time_travel_del_event(...) time_travel_not_configured() #endif /* CONFIG_UML_TIME_TRAVEL_SUPPORT */ +extern unsigned long tt_extra_sched_jiffies; + /* * Without CONFIG_UML_TIME_TRAVEL_SUPPORT this is a linker error if used, * which is intentional since we really shouldn't link it in that case.
diff --git a/arch/um/include/shared/arch.h b/arch/um/include/shared/arch.h index 880ee42..cc398a2 100644 --- a/arch/um/include/shared/arch.h +++ b/arch/um/include/shared/arch.h
@@ -12,4 +12,6 @@ extern void arch_check_bugs(void); extern int arch_fixup(unsigned long address, struct uml_pt_regs *regs); extern void arch_examine_signal(int sig, struct uml_pt_regs *regs); +void mc_set_rip(void *_mc, void *target); + #endif
diff --git a/arch/um/include/shared/as-layout.h b/arch/um/include/shared/as-layout.h index ea65f15..4f44dcc 100644 --- a/arch/um/include/shared/as-layout.h +++ b/arch/um/include/shared/as-layout.h
@@ -50,7 +50,7 @@ extern int linux_main(int argc, char **argv, char **envp); extern void uml_finishsetup(void); struct siginfo; -extern void (*sig_info[])(int, struct siginfo *si, struct uml_pt_regs *); +extern void (*sig_info[])(int, struct siginfo *si, struct uml_pt_regs *, void *); #endif
diff --git a/arch/um/include/shared/irq_user.h b/arch/um/include/shared/irq_user.h index da0f6ee..88835b5 100644 --- a/arch/um/include/shared/irq_user.h +++ b/arch/um/include/shared/irq_user.h
@@ -15,7 +15,8 @@ enum um_irq_type { }; struct siginfo; -extern void sigio_handler(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs); +extern void sigio_handler(int sig, struct siginfo *unused_si, + struct uml_pt_regs *regs, void *mc); void sigio_run_timetravel_handlers(void); extern void free_irq_by_fd(int fd); extern void deactivate_fd(int fd, int irqnum);
diff --git a/arch/um/include/shared/kern_util.h b/arch/um/include/shared/kern_util.h index f21dc85..00ca3e1 100644 --- a/arch/um/include/shared/kern_util.h +++ b/arch/um/include/shared/kern_util.h
@@ -24,10 +24,12 @@ extern void free_stack(unsigned long stack, int order); struct pt_regs; extern void do_signal(struct pt_regs *regs); extern void interrupt_end(void); -extern void relay_signal(int sig, struct siginfo *si, struct uml_pt_regs *regs); +extern void relay_signal(int sig, struct siginfo *si, struct uml_pt_regs *regs, + void *mc); extern unsigned long segv(struct faultinfo fi, unsigned long ip, - int is_user, struct uml_pt_regs *regs); + int is_user, struct uml_pt_regs *regs, + void *mc); extern int handle_page_fault(unsigned long address, unsigned long ip, int is_write, int is_user, int *code_out); @@ -59,8 +61,10 @@ extern unsigned long from_irq_stack(int nested); extern int singlestepping(void); -extern void segv_handler(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs); -extern void winch(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs); +extern void segv_handler(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs, + void *mc); +extern void winch(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs, + void *mc); extern void fatal_sigsegv(void) __attribute__ ((noreturn)); void um_idle_sleep(void);
diff --git a/arch/um/include/shared/os.h b/arch/um/include/shared/os.h index 5babad8..152a600 100644 --- a/arch/um/include/shared/os.h +++ b/arch/um/include/shared/os.h
@@ -213,7 +213,6 @@ extern int os_protect_memory(void *addr, unsigned long len, extern int os_unmap_memory(void *addr, int len); extern int os_drop_memory(void *addr, int length); extern int can_drop_memory(void); -extern int os_mincore(void *addr, unsigned long len); void os_set_pdeathsig(void); @@ -225,6 +224,11 @@ extern int run_helper_thread(int (*proc)(void *), void *arg, unsigned int flags, unsigned long *stack_out); extern int helper_wait(int pid); +struct os_helper_thread; +int os_run_helper_thread(struct os_helper_thread **td_out, + void *(*routine)(void *), void *arg); +void os_kill_helper_thread(struct os_helper_thread *td); +void os_fix_helper_thread_signals(void); /* umid.c */ extern int umid_file_name(char *name, char *buf, int len); @@ -310,7 +314,7 @@ extern void um_irqs_resume(void); extern int add_sigio_fd(int fd); extern int ignore_sigio_fd(int fd); extern void maybe_sigio_broken(int fd); -extern void sigio_broken(int fd); +extern void sigio_broken(void); /* * unlocked versions for IRQ controller code. *
diff --git a/arch/um/include/shared/sigio.h b/arch/um/include/shared/sigio.h index e60c8b2..c6c2edc 100644 --- a/arch/um/include/shared/sigio.h +++ b/arch/um/include/shared/sigio.h
@@ -6,7 +6,6 @@ #ifndef __SIGIO_H__ #define __SIGIO_H__ -extern int write_sigio_irq(int fd); extern void sigio_lock(void); extern void sigio_unlock(void);
diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile index f8567b9..4df1cd0 100644 --- a/arch/um/kernel/Makefile +++ b/arch/um/kernel/Makefile
@@ -17,7 +17,7 @@ obj-y = config.o exec.o exitcode.o irq.o ksyms.o mem.o \ physmem.o process.o ptrace.o reboot.o sigio.o \ signal.o sysrq.o time.o tlb.o trap.o \ - um_arch.o umid.o maccess.o kmsg_dump.o capflags.o skas/ + um_arch.o umid.o kmsg_dump.o capflags.o skas/ obj-y += load_file.o obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o
diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c index a499174..abe8f30 100644 --- a/arch/um/kernel/irq.c +++ b/arch/um/kernel/irq.c
@@ -236,7 +236,8 @@ static void _sigio_handler(struct uml_pt_regs *regs, free_irqs(); } -void sigio_handler(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs) +void sigio_handler(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs, + void *mc) { preempt_disable(); _sigio_handler(regs, irqs_suspended);
diff --git a/arch/um/kernel/maccess.c b/arch/um/kernel/maccess.c deleted file mode 100644 index 8ccd568..0000000 --- a/arch/um/kernel/maccess.c +++ /dev/null
@@ -1,19 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (C) 2013 Richard Weinberger <richrd@nod.at> - */ - -#include <linux/uaccess.h> -#include <linux/kernel.h> -#include <os.h> - -bool copy_from_kernel_nofault_allowed(const void *src, size_t size) -{ - void *psrc = (void *)rounddown((unsigned long)src, PAGE_SIZE); - - if ((unsigned long)src < PAGE_SIZE || size <= 0) - return false; - if (os_mincore(psrc, size + src - psrc) <= 0) - return false; - return true; -}
diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c index 379f33a..76bec7d 100644 --- a/arch/um/kernel/mem.c +++ b/arch/um/kernel/mem.c
@@ -9,6 +9,8 @@ #include <linux/mm.h> #include <linux/swap.h> #include <linux/slab.h> +#include <linux/init.h> +#include <asm/sections.h> #include <asm/page.h> #include <asm/pgalloc.h> #include <as-layout.h> @@ -66,6 +68,7 @@ void __init arch_mm_preinit(void) map_memory(brk_end, __pa(brk_end), uml_reserved - brk_end, 1, 1, 0); memblock_free((void *)brk_end, uml_reserved - brk_end); uml_reserved = brk_end; + min_low_pfn = PFN_UP(__pa(uml_reserved)); max_pfn = max_low_pfn; } @@ -242,3 +245,11 @@ static const pgprot_t protection_map[16] = { [VM_SHARED | VM_EXEC | VM_WRITE | VM_READ] = PAGE_SHARED }; DECLARE_VM_GET_PAGE_PROT + +void mark_rodata_ro(void) +{ + unsigned long rodata_start = PFN_ALIGN(__start_rodata); + unsigned long rodata_end = PFN_ALIGN(__end_rodata); + + os_protect_memory((void *)rodata_start, rodata_end - rodata_start, 1, 0, 0); +}
diff --git a/arch/um/kernel/sigio.c b/arch/um/kernel/sigio.c index 5085a50..4fc0474 100644 --- a/arch/um/kernel/sigio.c +++ b/arch/um/kernel/sigio.c
@@ -8,32 +8,6 @@ #include <os.h> #include <sigio.h> -/* Protected by sigio_lock() called from write_sigio_workaround */ -static int sigio_irq_fd = -1; - -static irqreturn_t sigio_interrupt(int irq, void *data) -{ - char c; - - os_read_file(sigio_irq_fd, &c, sizeof(c)); - return IRQ_HANDLED; -} - -int write_sigio_irq(int fd) -{ - int err; - - err = um_request_irq(SIGIO_WRITE_IRQ, fd, IRQ_READ, sigio_interrupt, - 0, "write sigio", NULL); - if (err < 0) { - printk(KERN_ERR "write_sigio_irq : um_request_irq failed, " - "err = %d\n", err); - return -1; - } - sigio_irq_fd = fd; - return 0; -} - /* These are called from os-Linux/sigio.c to protect its pollfds arrays. */ static DEFINE_MUTEX(sigio_mutex);
diff --git a/arch/um/kernel/skas/syscall.c b/arch/um/kernel/skas/syscall.c index b09e852..a5beaea 100644 --- a/arch/um/kernel/skas/syscall.c +++ b/arch/um/kernel/skas/syscall.c
@@ -31,6 +31,17 @@ void handle_syscall(struct uml_pt_regs *r) goto out; syscall = UPT_SYSCALL_NR(r); + + /* + * If no time passes, then sched_yield may not actually yield, causing + * broken spinlock implementations in userspace (ASAN) to hang for long + * periods of time. + */ + if ((time_travel_mode == TT_MODE_INFCPU || + time_travel_mode == TT_MODE_EXTERNAL) && + syscall == __NR_sched_yield) + tt_extra_sched_jiffies += 1; + if (syscall >= 0 && syscall < __NR_syscalls) { unsigned long ret = EXECUTE_SYSCALL(syscall, regs);
diff --git a/arch/um/kernel/trap.c b/arch/um/kernel/trap.c index cdaee3e..ce07315 100644 --- a/arch/um/kernel/trap.c +++ b/arch/um/kernel/trap.c
@@ -16,6 +16,7 @@ #include <kern_util.h> #include <os.h> #include <skas.h> +#include <arch.h> /* * Note this is constrained to return 0, -EFAULT, -EACCES, -ENOMEM by @@ -175,12 +176,14 @@ void fatal_sigsegv(void) * @sig: the signal number * @unused_si: the signal info struct; unused in this handler * @regs: the ptrace register information + * @mc: the mcontext of the signal * * The handler first extracts the faultinfo from the UML ptrace regs struct. * If the userfault did not happen in an UML userspace process, bad_segv is called. * Otherwise the signal did happen in a cloned userspace process, handle it. */ -void segv_handler(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs) +void segv_handler(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs, + void *mc) { struct faultinfo * fi = UPT_FAULTINFO(regs); @@ -189,7 +192,7 @@ void segv_handler(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs) bad_segv(*fi, UPT_IP(regs)); return; } - segv(*fi, UPT_IP(regs), UPT_IS_USER(regs), regs); + segv(*fi, UPT_IP(regs), UPT_IS_USER(regs), regs, mc); } /* @@ -199,7 +202,7 @@ void segv_handler(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs) * give us bad data! */ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, - struct uml_pt_regs *regs) + struct uml_pt_regs *regs, void *mc) { int si_code; int err; @@ -223,6 +226,19 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, goto out; } else if (current->mm == NULL) { + if (current->pagefault_disabled) { + if (!mc) { + show_regs(container_of(regs, struct pt_regs, regs)); + panic("Segfault with pagefaults disabled but no mcontext"); + } + if (!current->thread.segv_continue) { + show_regs(container_of(regs, struct pt_regs, regs)); + panic("Segfault without recovery target"); + } + mc_set_rip(mc, current->thread.segv_continue); + current->thread.segv_continue = NULL; + goto out; + } show_regs(container_of(regs, struct pt_regs, regs)); panic("Segfault with no mm"); } @@ -274,7 +290,8 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, return 0; } -void relay_signal(int sig, struct siginfo *si, struct uml_pt_regs *regs) +void relay_signal(int sig, struct siginfo *si, struct uml_pt_regs *regs, + void *mc) { int code, err; if (!UPT_IS_USER(regs)) { @@ -302,7 +319,8 @@ void relay_signal(int sig, struct siginfo *si, struct uml_pt_regs *regs) } } -void winch(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs) +void winch(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs, + void *mc) { do_IRQ(WINCH_IRQ, regs); }
diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c index 0502798..d4b3b67 100644 --- a/arch/um/kernel/um_arch.c +++ b/arch/um/kernel/um_arch.c
@@ -12,6 +12,7 @@ #include <linux/panic_notifier.h> #include <linux/seq_file.h> #include <linux/string.h> +#include <linux/string_choices.h> #include <linux/utsname.h> #include <linux/sched.h> #include <linux/sched/task.h> @@ -78,7 +79,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) seq_printf(m, "model name\t: UML\n"); seq_printf(m, "mode\t\t: skas\n"); seq_printf(m, "host\t\t: %s\n", host_info); - seq_printf(m, "fpu\t\t: %s\n", cpu_has(&boot_cpu_data, X86_FEATURE_FPU) ? "yes" : "no"); + seq_printf(m, "fpu\t\t: %s\n", str_yes_no(cpu_has(&boot_cpu_data, X86_FEATURE_FPU))); seq_printf(m, "flags\t\t:"); for (i = 0; i < 32*NCAPINTS; i++) if (cpu_has(&boot_cpu_data, i) && (x86_cap_flags[i] != NULL))
diff --git a/arch/um/os-Linux/helper.c b/arch/um/os-Linux/helper.c index 3cb8ac6..89c2ad2 100644 --- a/arch/um/os-Linux/helper.c +++ b/arch/um/os-Linux/helper.c
@@ -8,6 +8,7 @@ #include <unistd.h> #include <errno.h> #include <sched.h> +#include <pthread.h> #include <linux/limits.h> #include <sys/socket.h> #include <sys/wait.h> @@ -121,6 +122,10 @@ int run_helper_thread(int (*proc)(void *), void *arg, unsigned int flags, unsigned long stack, sp; int pid, status, err; + /* To share memory space, use os_run_helper_thread() instead. */ + if (flags & CLONE_VM) + return -EINVAL; + stack = alloc_stack(0, __uml_cant_sleep()); if (stack == 0) return -ENOMEM; @@ -167,3 +172,65 @@ int helper_wait(int pid) } else return 0; } + +struct os_helper_thread { + pthread_t handle; +}; + +int os_run_helper_thread(struct os_helper_thread **td_out, + void *(*routine)(void *), void *arg) +{ + struct os_helper_thread *td; + sigset_t sigset, oset; + int err, flags; + + flags = __uml_cant_sleep() ? UM_GFP_ATOMIC : UM_GFP_KERNEL; + td = uml_kmalloc(sizeof(*td), flags); + if (!td) + return -ENOMEM; + + sigfillset(&sigset); + if (sigprocmask(SIG_SETMASK, &sigset, &oset) < 0) { + err = -errno; + kfree(td); + return err; + } + + err = pthread_create(&td->handle, NULL, routine, arg); + + if (sigprocmask(SIG_SETMASK, &oset, NULL) < 0) + panic("Failed to restore the signal mask: %d", errno); + + if (err != 0) + kfree(td); + else + *td_out = td; + + return -err; +} + +void os_kill_helper_thread(struct os_helper_thread *td) +{ + pthread_cancel(td->handle); + pthread_join(td->handle, NULL); + kfree(td); +} + +void os_fix_helper_thread_signals(void) +{ + sigset_t sigset; + + sigemptyset(&sigset); + + sigaddset(&sigset, SIGWINCH); + sigaddset(&sigset, SIGPIPE); + sigaddset(&sigset, SIGPROF); + sigaddset(&sigset, SIGINT); + sigaddset(&sigset, SIGTERM); + sigaddset(&sigset, SIGCHLD); + sigaddset(&sigset, SIGALRM); + sigaddset(&sigset, SIGIO); + sigaddset(&sigset, SIGUSR1); + + pthread_sigmask(SIG_SETMASK, &sigset, NULL); +}
diff --git a/arch/um/os-Linux/process.c b/arch/um/os-Linux/process.c index 9f086f9..184566e 100644 --- a/arch/um/os-Linux/process.c +++ b/arch/um/os-Linux/process.c
@@ -142,57 +142,6 @@ int __init can_drop_memory(void) return ok; } -static int os_page_mincore(void *addr) -{ - char vec[2]; - int ret; - - ret = mincore(addr, UM_KERN_PAGE_SIZE, vec); - if (ret < 0) { - if (errno == ENOMEM || errno == EINVAL) - return 0; - else - return -errno; - } - - return vec[0] & 1; -} - -int os_mincore(void *addr, unsigned long len) -{ - char *vec; - int ret, i; - - if (len <= UM_KERN_PAGE_SIZE) - return os_page_mincore(addr); - - vec = calloc(1, (len + UM_KERN_PAGE_SIZE - 1) / UM_KERN_PAGE_SIZE); - if (!vec) - return -ENOMEM; - - ret = mincore(addr, UM_KERN_PAGE_SIZE, vec); - if (ret < 0) { - if (errno == ENOMEM || errno == EINVAL) - ret = 0; - else - ret = -errno; - - goto out; - } - - for (i = 0; i < ((len + UM_KERN_PAGE_SIZE - 1) / UM_KERN_PAGE_SIZE); i++) { - if (!(vec[i] & 1)) { - ret = 0; - goto out; - } - } - - ret = 1; -out: - free(vec); - return ret; -} - void init_new_thread_signals(void) { set_handler(SIGSEGV);
diff --git a/arch/um/os-Linux/sigio.c b/arch/um/os-Linux/sigio.c index 9aac8de..a05a6ec 100644 --- a/arch/um/os-Linux/sigio.c +++ b/arch/um/os-Linux/sigio.c
@@ -11,6 +11,7 @@ #include <sched.h> #include <signal.h> #include <string.h> +#include <sys/epoll.h> #include <kern_util.h> #include <init.h> #include <os.h> @@ -21,184 +22,51 @@ * Protected by sigio_lock(), also used by sigio_cleanup, which is an * exitcall. */ -static int write_sigio_pid = -1; -static unsigned long write_sigio_stack; +static struct os_helper_thread *write_sigio_td; -/* - * These arrays are initialized before the sigio thread is started, and - * the descriptors closed after it is killed. So, it can't see them change. - * On the UML side, they are changed under the sigio_lock. - */ -#define SIGIO_FDS_INIT {-1, -1} +static int epollfd = -1; -static int write_sigio_fds[2] = SIGIO_FDS_INIT; -static int sigio_private[2] = SIGIO_FDS_INIT; +#define MAX_EPOLL_EVENTS 64 -struct pollfds { - struct pollfd *poll; - int size; - int used; -}; +static struct epoll_event epoll_events[MAX_EPOLL_EVENTS]; -/* - * Protected by sigio_lock(). Used by the sigio thread, but the UML thread - * synchronizes with it. - */ -static struct pollfds current_poll; -static struct pollfds next_poll; -static struct pollfds all_sigio_fds; - -static int write_sigio_thread(void *unused) +static void *write_sigio_thread(void *unused) { - struct pollfds *fds, tmp; - struct pollfd *p; - int i, n, respond_fd; - char c; + int pid = getpid(); + int r; - os_set_pdeathsig(); - os_fix_helper_signals(); - fds = ¤t_poll; + os_fix_helper_thread_signals(); + while (1) { - n = poll(fds->poll, fds->used, -1); - if (n < 0) { + r = epoll_wait(epollfd, epoll_events, MAX_EPOLL_EVENTS, -1); + if (r < 0) { if (errno == EINTR) continue; - printk(UM_KERN_ERR "write_sigio_thread : poll returned " - "%d, errno = %d\n", n, errno); + printk(UM_KERN_ERR "%s: epoll_wait failed, errno = %d\n", + __func__, errno); } - for (i = 0; i < fds->used; i++) { - p = &fds->poll[i]; - if (p->revents == 0) - continue; - if (p->fd == sigio_private[1]) { - CATCH_EINTR(n = read(sigio_private[1], &c, - sizeof(c))); - if (n != sizeof(c)) - printk(UM_KERN_ERR - "write_sigio_thread : " - "read on socket failed, " - "err = %d\n", errno); - tmp = current_poll; - current_poll = next_poll; - next_poll = tmp; - respond_fd = sigio_private[1]; - } - else { - respond_fd = write_sigio_fds[1]; - fds->used--; - memmove(&fds->poll[i], &fds->poll[i + 1], - (fds->used - i) * sizeof(*fds->poll)); - } - CATCH_EINTR(n = write(respond_fd, &c, sizeof(c))); - if (n != sizeof(c)) - printk(UM_KERN_ERR "write_sigio_thread : " - "write on socket failed, err = %d\n", - errno); - } + CATCH_EINTR(r = tgkill(pid, pid, SIGIO)); + if (r < 0) + printk(UM_KERN_ERR "%s: tgkill failed, errno = %d\n", + __func__, errno); } - return 0; -} - -static int need_poll(struct pollfds *polls, int n) -{ - struct pollfd *new; - - if (n <= polls->size) - return 0; - - new = uml_kmalloc(n * sizeof(struct pollfd), UM_GFP_ATOMIC); - if (new == NULL) { - printk(UM_KERN_ERR "need_poll : failed to allocate new " - "pollfds\n"); - return -ENOMEM; - } - - memcpy(new, polls->poll, polls->used * sizeof(struct pollfd)); - kfree(polls->poll); - - polls->poll = new; - polls->size = n; - return 0; -} - -/* - * Must be called with sigio_lock held, because it's needed by the marked - * critical section. - */ -static void update_thread(void) -{ - unsigned long flags; - int n; - char c; - - flags = um_set_signals_trace(0); - CATCH_EINTR(n = write(sigio_private[0], &c, sizeof(c))); - if (n != sizeof(c)) { - printk(UM_KERN_ERR "update_thread : write failed, err = %d\n", - errno); - goto fail; - } - - CATCH_EINTR(n = read(sigio_private[0], &c, sizeof(c))); - if (n != sizeof(c)) { - printk(UM_KERN_ERR "update_thread : read failed, err = %d\n", - errno); - goto fail; - } - - um_set_signals_trace(flags); - return; - fail: - /* Critical section start */ - if (write_sigio_pid != -1) { - os_kill_process(write_sigio_pid, 1); - free_stack(write_sigio_stack, 0); - } - write_sigio_pid = -1; - close(sigio_private[0]); - close(sigio_private[1]); - close(write_sigio_fds[0]); - close(write_sigio_fds[1]); - /* Critical section end */ - um_set_signals_trace(flags); + return NULL; } int __add_sigio_fd(int fd) { - struct pollfd *p; - int err, i, n; + struct epoll_event event = { + .data.fd = fd, + .events = EPOLLIN | EPOLLET, + }; + int r; - for (i = 0; i < all_sigio_fds.used; i++) { - if (all_sigio_fds.poll[i].fd == fd) - break; - } - if (i == all_sigio_fds.used) - return -ENOSPC; - - p = &all_sigio_fds.poll[i]; - - for (i = 0; i < current_poll.used; i++) { - if (current_poll.poll[i].fd == fd) - return 0; - } - - n = current_poll.used; - err = need_poll(&next_poll, n + 1); - if (err) - return err; - - memcpy(next_poll.poll, current_poll.poll, - current_poll.used * sizeof(struct pollfd)); - next_poll.poll[n] = *p; - next_poll.used = n + 1; - update_thread(); - - return 0; + CATCH_EINTR(r = epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &event)); + return r < 0 ? -errno : 0; } - int add_sigio_fd(int fd) { int err; @@ -212,38 +80,11 @@ int add_sigio_fd(int fd) int __ignore_sigio_fd(int fd) { - struct pollfd *p; - int err, i, n = 0; + struct epoll_event event; + int r; - /* - * This is called from exitcalls elsewhere in UML - if - * sigio_cleanup has already run, then update_thread will hang - * or fail because the thread is no longer running. - */ - if (write_sigio_pid == -1) - return -EIO; - - for (i = 0; i < current_poll.used; i++) { - if (current_poll.poll[i].fd == fd) - break; - } - if (i == current_poll.used) - return -ENOENT; - - err = need_poll(&next_poll, current_poll.used - 1); - if (err) - return err; - - for (i = 0; i < current_poll.used; i++) { - p = ¤t_poll.poll[i]; - if (p->fd != fd) - next_poll.poll[n++] = *p; - } - next_poll.used = current_poll.used - 1; - - update_thread(); - - return 0; + CATCH_EINTR(r = epoll_ctl(epollfd, EPOLL_CTL_DEL, fd, &event)); + return r < 0 ? -errno : 0; } int ignore_sigio_fd(int fd) @@ -257,127 +98,39 @@ int ignore_sigio_fd(int fd) return err; } -static struct pollfd *setup_initial_poll(int fd) -{ - struct pollfd *p; - - p = uml_kmalloc(sizeof(struct pollfd), UM_GFP_KERNEL); - if (p == NULL) { - printk(UM_KERN_ERR "setup_initial_poll : failed to allocate " - "poll\n"); - return NULL; - } - *p = ((struct pollfd) { .fd = fd, - .events = POLLIN, - .revents = 0 }); - return p; -} - static void write_sigio_workaround(void) { - struct pollfd *p; - int err; - int l_write_sigio_fds[2]; - int l_sigio_private[2]; - int l_write_sigio_pid; - - /* We call this *tons* of times - and most ones we must just fail. */ - sigio_lock(); - l_write_sigio_pid = write_sigio_pid; - sigio_unlock(); - - if (l_write_sigio_pid != -1) - return; - - err = os_pipe(l_write_sigio_fds, 1, 1); - if (err < 0) { - printk(UM_KERN_ERR "write_sigio_workaround - os_pipe 1 failed, " - "err = %d\n", -err); - return; - } - err = os_pipe(l_sigio_private, 1, 1); - if (err < 0) { - printk(UM_KERN_ERR "write_sigio_workaround - os_pipe 2 failed, " - "err = %d\n", -err); - goto out_close1; - } - - p = setup_initial_poll(l_sigio_private[1]); - if (!p) - goto out_close2; - - sigio_lock(); - - /* - * Did we race? Don't try to optimize this, please, it's not so likely - * to happen, and no more than once at the boot. - */ - if (write_sigio_pid != -1) - goto out_free; - - current_poll = ((struct pollfds) { .poll = p, - .used = 1, - .size = 1 }); - - if (write_sigio_irq(l_write_sigio_fds[0])) - goto out_clear_poll; - - memcpy(write_sigio_fds, l_write_sigio_fds, sizeof(l_write_sigio_fds)); - memcpy(sigio_private, l_sigio_private, sizeof(l_sigio_private)); - - write_sigio_pid = run_helper_thread(write_sigio_thread, NULL, - CLONE_FILES | CLONE_VM, - &write_sigio_stack); - - if (write_sigio_pid < 0) - goto out_clear; - - sigio_unlock(); - return; - -out_clear: - write_sigio_pid = -1; - write_sigio_fds[0] = -1; - write_sigio_fds[1] = -1; - sigio_private[0] = -1; - sigio_private[1] = -1; -out_clear_poll: - current_poll = ((struct pollfds) { .poll = NULL, - .size = 0, - .used = 0 }); -out_free: - sigio_unlock(); - kfree(p); -out_close2: - close(l_sigio_private[0]); - close(l_sigio_private[1]); -out_close1: - close(l_write_sigio_fds[0]); - close(l_write_sigio_fds[1]); -} - -void sigio_broken(int fd) -{ int err; - write_sigio_workaround(); - sigio_lock(); - err = need_poll(&all_sigio_fds, all_sigio_fds.used + 1); - if (err) { - printk(UM_KERN_ERR "maybe_sigio_broken - failed to add pollfd " - "for descriptor %d\n", fd); + if (write_sigio_td) + goto out; + + epollfd = epoll_create(MAX_EPOLL_EVENTS); + if (epollfd < 0) { + printk(UM_KERN_ERR "%s: epoll_create failed, errno = %d\n", + __func__, errno); goto out; } - all_sigio_fds.poll[all_sigio_fds.used++] = - ((struct pollfd) { .fd = fd, - .events = POLLIN, - .revents = 0 }); + err = os_run_helper_thread(&write_sigio_td, write_sigio_thread, NULL); + if (err < 0) { + printk(UM_KERN_ERR "%s: os_run_helper_thread failed, errno = %d\n", + __func__, -err); + close(epollfd); + epollfd = -1; + goto out; + } + out: sigio_unlock(); } +void sigio_broken(void) +{ + write_sigio_workaround(); +} + /* Changed during early boot */ static int pty_output_sigio; @@ -389,17 +142,16 @@ void maybe_sigio_broken(int fd) if (pty_output_sigio) return; - sigio_broken(fd); + sigio_broken(); } static void sigio_cleanup(void) { - if (write_sigio_pid == -1) + if (!write_sigio_td) return; - os_kill_process(write_sigio_pid, 1); - free_stack(write_sigio_stack, 0); - write_sigio_pid = -1; + os_kill_helper_thread(write_sigio_td); + write_sigio_td = NULL; } __uml_exitcall(sigio_cleanup);
diff --git a/arch/um/os-Linux/signal.c b/arch/um/os-Linux/signal.c index 9ea7269f..e71e5b4 100644 --- a/arch/um/os-Linux/signal.c +++ b/arch/um/os-Linux/signal.c
@@ -21,7 +21,7 @@ #include <sys/ucontext.h> #include <timetravel.h> -void (*sig_info[NSIG])(int, struct siginfo *, struct uml_pt_regs *) = { +void (*sig_info[NSIG])(int, struct siginfo *, struct uml_pt_regs *, void *mc) = { [SIGTRAP] = relay_signal, [SIGFPE] = relay_signal, [SIGILL] = relay_signal, @@ -47,7 +47,7 @@ static void sig_handler_common(int sig, struct siginfo *si, mcontext_t *mc) if ((sig != SIGIO) && (sig != SIGWINCH)) unblock_signals_trace(); - (*sig_info[sig])(sig, si, &r); + (*sig_info[sig])(sig, si, &r, mc); errno = save_errno; }
diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c index e2f8f15..ae2aea0 100644 --- a/arch/um/os-Linux/skas/process.c +++ b/arch/um/os-Linux/skas/process.c
@@ -166,7 +166,7 @@ static void get_skas_faultinfo(int pid, struct faultinfo *fi) static void handle_segv(int pid, struct uml_pt_regs *regs) { get_skas_faultinfo(pid, ®s->faultinfo); - segv(regs->faultinfo, 0, 1, NULL); + segv(regs->faultinfo, 0, 1, NULL, NULL); } static void handle_trap(int pid, struct uml_pt_regs *regs) @@ -525,7 +525,7 @@ void userspace(struct uml_pt_regs *regs) get_skas_faultinfo(pid, ®s->faultinfo); (*sig_info[SIGSEGV])(SIGSEGV, (struct siginfo *)&si, - regs); + regs, NULL); } else handle_segv(pid, regs); break; @@ -533,7 +533,7 @@ void userspace(struct uml_pt_regs *regs) handle_trap(pid, regs); break; case SIGTRAP: - relay_signal(SIGTRAP, (struct siginfo *)&si, regs); + relay_signal(SIGTRAP, (struct siginfo *)&si, regs, NULL); break; case SIGALRM: break; @@ -543,7 +543,7 @@ void userspace(struct uml_pt_regs *regs) case SIGFPE: case SIGWINCH: block_signals_trace(); - (*sig_info[sig])(sig, (struct siginfo *)&si, regs); + (*sig_info[sig])(sig, (struct siginfo *)&si, regs, NULL); unblock_signals_trace(); break; default:
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 9395ec3..4b9f378 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig
@@ -27,6 +27,7 @@ # Options that are inherently 64-bit kernel only: select ARCH_HAS_GIGANTIC_PAGE select ARCH_HAS_PTDUMP + select ARCH_SUPPORTS_MSEAL_SYSTEM_MAPPINGS select ARCH_SUPPORTS_INT128 if CC_HAS_INT128 select ARCH_SUPPORTS_PER_VMA_LOCK select ARCH_SUPPORTS_HUGE_PFNMAP if TRANSPARENT_HUGEPAGE @@ -889,6 +890,7 @@ depends on X86_64 && CPU_SUP_INTEL depends on X86_X2APIC depends on EFI_STUB + depends on PARAVIRT select ARCH_HAS_CC_PLATFORM select X86_MEM_ENCRYPT select X86_MCE @@ -2136,6 +2138,7 @@ config X86_NEED_RELOCS def_bool y depends on RANDOMIZE_BASE || (X86_32 && RELOCATABLE) + select ARCH_VMLINUX_NEEDS_RELOCS config PHYSICAL_ALIGN hex "Alignment value to which kernel should be aligned"
diff --git a/arch/x86/Makefile b/arch/x86/Makefile index 27efe2d..5947230 100644 --- a/arch/x86/Makefile +++ b/arch/x86/Makefile
@@ -245,12 +245,6 @@ KBUILD_LDFLAGS += -m elf_$(UTS_MACHINE) -ifdef CONFIG_X86_NEED_RELOCS -LDFLAGS_vmlinux := --emit-relocs --discard-none -else -LDFLAGS_vmlinux := -endif - # # The 64-bit kernel must be aligned to 2MB. Pass -z max-page-size=0x200000 to # the linker to force 2MB page size regardless of the default page size used
diff --git a/arch/x86/Makefile.postlink b/arch/x86/Makefile.postlink deleted file mode 100644 index 8b8a681..0000000 --- a/arch/x86/Makefile.postlink +++ /dev/null
@@ -1,40 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -# =========================================================================== -# Post-link x86 pass -# =========================================================================== -# -# 1. Separate relocations from vmlinux into vmlinux.relocs. -# 2. Strip relocations from vmlinux. - -PHONY := __archpost -__archpost: - --include include/config/auto.conf -include $(srctree)/scripts/Kbuild.include -include $(srctree)/scripts/Makefile.lib - -CMD_RELOCS = arch/x86/tools/relocs -OUT_RELOCS = arch/x86/boot/compressed -quiet_cmd_relocs = RELOCS $(OUT_RELOCS)/$@.relocs - cmd_relocs = \ - mkdir -p $(OUT_RELOCS); \ - $(CMD_RELOCS) $@ > $(OUT_RELOCS)/$@.relocs; \ - $(CMD_RELOCS) --abs-relocs $@ - -# `@true` prevents complaint when there is nothing to be done - -vmlinux: FORCE - @true -ifeq ($(CONFIG_X86_NEED_RELOCS),y) - $(call cmd,relocs) - $(call cmd,strip_relocs) -endif - -clean: - @rm -f $(OUT_RELOCS)/vmlinux.relocs - -PHONY += FORCE clean - -FORCE: - -.PHONY: $(PHONY)
diff --git a/arch/x86/Makefile.um b/arch/x86/Makefile.um index a46b139..c86cbd9 100644 --- a/arch/x86/Makefile.um +++ b/arch/x86/Makefile.um
@@ -7,12 +7,13 @@ # GCC versions < 11. See: # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99652 # -ifeq ($(CONFIG_CC_IS_CLANG),y) -KBUILD_CFLAGS += -mno-sse -mno-mmx -mno-sse2 -mno-3dnow -mno-avx -KBUILD_RUSTFLAGS += --target=$(objtree)/scripts/target.json +ifeq ($(call gcc-min-version, 110000)$(CONFIG_CC_IS_CLANG),y) +KBUILD_CFLAGS += -mno-sse -mno-mmx -mno-sse2 -mno-3dnow -mno-avx KBUILD_RUSTFLAGS += -Ctarget-feature=-sse,-sse2,-sse3,-ssse3,-sse4.1,-sse4.2,-avx,-avx2 endif +KBUILD_RUSTFLAGS += --target=$(objtree)/scripts/target.json + ifeq ($(CONFIG_X86_32),y) START := 0x8048000
diff --git a/arch/x86/boot/Makefile b/arch/x86/boot/Makefile index 8589471..81f55da 100644 --- a/arch/x86/boot/Makefile +++ b/arch/x86/boot/Makefile
@@ -53,7 +53,6 @@ KBUILD_CFLAGS := $(REALMODE_CFLAGS) -D_SETUP KBUILD_AFLAGS := $(KBUILD_CFLAGS) -D__ASSEMBLY__ -KBUILD_CFLAGS += $(call cc-option,-fmacro-prefix-map=$(srctree)/=) KBUILD_CFLAGS += -fno-asynchronous-unwind-tables KBUILD_CFLAGS += $(CONFIG_CC_IMPLICIT_FALLTHROUGH)
diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile index 2eb6353..fdbce02 100644 --- a/arch/x86/boot/compressed/Makefile +++ b/arch/x86/boot/compressed/Makefile
@@ -38,7 +38,6 @@ KBUILD_CFLAGS += $(call cc-disable-warning, address-of-packed-member) KBUILD_CFLAGS += $(call cc-disable-warning, gnu) KBUILD_CFLAGS += -Wno-pointer-sign -KBUILD_CFLAGS += $(call cc-option,-fmacro-prefix-map=$(srctree)/=) KBUILD_CFLAGS += -fno-asynchronous-unwind-tables KBUILD_CFLAGS += -D__DISABLE_EXPORTS # Disable relocation relaxation in case the link is not PIE. @@ -117,9 +116,12 @@ targets += $(patsubst $(obj)/%,%,$(vmlinux-objs-y)) vmlinux.bin.all vmlinux.relocs -# vmlinux.relocs is created by the vmlinux postlink step. -$(obj)/vmlinux.relocs: vmlinux - @true +CMD_RELOCS = arch/x86/tools/relocs +quiet_cmd_relocs = RELOCS $@ + cmd_relocs = $(CMD_RELOCS) $< > $@;$(CMD_RELOCS) --abs-relocs $< + +$(obj)/vmlinux.relocs: vmlinux.unstripped FORCE + $(call if_changed,relocs) vmlinux.bin.all-y := $(obj)/vmlinux.bin vmlinux.bin.all-$(CONFIG_X86_NEED_RELOCS) += $(obj)/vmlinux.relocs
diff --git a/arch/x86/coco/tdx/tdx.c b/arch/x86/coco/tdx/tdx.c index 7772b01..edab6d6 100644 --- a/arch/x86/coco/tdx/tdx.c +++ b/arch/x86/coco/tdx/tdx.c
@@ -14,6 +14,7 @@ #include <asm/ia32.h> #include <asm/insn.h> #include <asm/insn-eval.h> +#include <asm/paravirt_types.h> #include <asm/pgtable.h> #include <asm/set_memory.h> #include <asm/traps.h> @@ -392,13 +393,21 @@ static int handle_halt(struct ve_info *ve) { const bool irq_disabled = irqs_disabled(); + /* + * HLT with IRQs enabled is unsafe, as an IRQ that is intended to be a + * wake event may be consumed before requesting HLT emulation, leaving + * the vCPU blocking indefinitely. + */ + if (WARN_ONCE(!irq_disabled, "HLT emulation with IRQs enabled")) + return -EIO; + if (__halt(irq_disabled)) return -EIO; return ve_instr_len(ve); } -void __cpuidle tdx_safe_halt(void) +void __cpuidle tdx_halt(void) { const bool irq_disabled = false; @@ -409,6 +418,16 @@ void __cpuidle tdx_safe_halt(void) WARN_ONCE(1, "HLT instruction emulation failed\n"); } +static void __cpuidle tdx_safe_halt(void) +{ + tdx_halt(); + /* + * "__cpuidle" section doesn't support instrumentation, so stick + * with raw_* variant that avoids tracing hooks. + */ + raw_local_irq_enable(); +} + static int read_msr(struct pt_regs *regs, struct ve_info *ve) { struct tdx_module_args args = { @@ -1110,6 +1129,19 @@ void __init tdx_early_init(void) x86_platform.guest.enc_kexec_finish = tdx_kexec_finish; /* + * Avoid "sti;hlt" execution in TDX guests as HLT induces a #VE that + * will enable interrupts before HLT TDCALL invocation if executed + * in STI-shadow, possibly resulting in missed wakeup events. + * + * Modify all possible HLT execution paths to use TDX specific routines + * that directly execute TDCALL and toggle the interrupt state as + * needed after TDCALL completion. This also reduces HLT related #VEs + * in addition to having a reliable halt logic execution. + */ + pv_ops.irq.safe_halt = tdx_safe_halt; + pv_ops.irq.halt = tdx_halt; + + /* * TDX intercepts the RDMSR to read the X2APIC ID in the parallel * bringup low level code. That raises #VE which cannot be handled * there.
diff --git a/arch/x86/entry/vdso/vma.c b/arch/x86/entry/vdso/vma.c index 9518bf1..adb299d 100644 --- a/arch/x86/entry/vdso/vma.c +++ b/arch/x86/entry/vdso/vma.c
@@ -162,7 +162,8 @@ static int map_vdso(const struct vdso_image *image, unsigned long addr) text_start, image->size, VM_READ|VM_EXEC| - VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC, + VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC| + VM_SEALED_SYSMAP, &vdso_mapping); if (IS_ERR(vma)) { @@ -181,7 +182,7 @@ static int map_vdso(const struct vdso_image *image, unsigned long addr) VDSO_VCLOCK_PAGES_START(addr), VDSO_NR_VCLOCK_PAGES * PAGE_SIZE, VM_READ|VM_MAYREAD|VM_IO|VM_DONTDUMP| - VM_PFNMAP, + VM_PFNMAP|VM_SEALED_SYSMAP, &vvar_vclock_mapping); if (IS_ERR(vma)) {
diff --git a/arch/x86/include/asm/arch_hweight.h b/arch/x86/include/asm/arch_hweight.h index b5982b9..cbc6157 100644 --- a/arch/x86/include/asm/arch_hweight.h +++ b/arch/x86/include/asm/arch_hweight.h
@@ -16,7 +16,8 @@ static __always_inline unsigned int __arch_hweight32(unsigned int w) { unsigned int res; - asm_inline (ALTERNATIVE("call __sw_hweight32", + asm_inline (ALTERNATIVE(ANNOTATE_IGNORE_ALTERNATIVE + "call __sw_hweight32", "popcntl %[val], %[cnt]", X86_FEATURE_POPCNT) : [cnt] "=" REG_OUT (res), ASM_CALL_CONSTRAINT : [val] REG_IN (w)); @@ -45,7 +46,8 @@ static __always_inline unsigned long __arch_hweight64(__u64 w) { unsigned long res; - asm_inline (ALTERNATIVE("call __sw_hweight64", + asm_inline (ALTERNATIVE(ANNOTATE_IGNORE_ALTERNATIVE + "call __sw_hweight64", "popcntq %[val], %[cnt]", X86_FEATURE_POPCNT) : [cnt] "=" REG_OUT (res), ASM_CALL_CONSTRAINT : [val] REG_IN (w));
diff --git a/arch/x86/include/asm/iosf_mbi.h b/arch/x86/include/asm/iosf_mbi.h index af7541c..8ace655 100644 --- a/arch/x86/include/asm/iosf_mbi.h +++ b/arch/x86/include/asm/iosf_mbi.h
@@ -168,13 +168,6 @@ void iosf_mbi_unblock_punit_i2c_access(void); int iosf_mbi_register_pmic_bus_access_notifier(struct notifier_block *nb); /** - * iosf_mbi_register_pmic_bus_access_notifier - Unregister PMIC bus notifier - * - * @nb: notifier_block to unregister - */ -int iosf_mbi_unregister_pmic_bus_access_notifier(struct notifier_block *nb); - -/** * iosf_mbi_unregister_pmic_bus_access_notifier_unlocked - Unregister PMIC bus * notifier, unlocked *
diff --git a/arch/x86/include/asm/irqflags.h b/arch/x86/include/asm/irqflags.h index abb8374..9a9b21b 100644 --- a/arch/x86/include/asm/irqflags.h +++ b/arch/x86/include/asm/irqflags.h
@@ -76,6 +76,28 @@ static __always_inline void native_local_irq_restore(unsigned long flags) #endif +#ifndef CONFIG_PARAVIRT +#ifndef __ASSEMBLY__ +/* + * Used in the idle loop; sti takes one instruction cycle + * to complete: + */ +static __always_inline void arch_safe_halt(void) +{ + native_safe_halt(); +} + +/* + * Used when interrupts are already enabled or to + * shutdown the processor: + */ +static __always_inline void halt(void) +{ + native_halt(); +} +#endif /* __ASSEMBLY__ */ +#endif /* CONFIG_PARAVIRT */ + #ifdef CONFIG_PARAVIRT_XXL #include <asm/paravirt.h> #else @@ -98,24 +120,6 @@ static __always_inline void arch_local_irq_enable(void) } /* - * Used in the idle loop; sti takes one instruction cycle - * to complete: - */ -static __always_inline void arch_safe_halt(void) -{ - native_safe_halt(); -} - -/* - * Used when interrupts are already enabled or to - * shutdown the processor: - */ -static __always_inline void halt(void) -{ - native_halt(); -} - -/* * For spinlocks, etc: */ static __always_inline unsigned long arch_local_irq_save(void)
diff --git a/arch/x86/include/asm/paravirt.h b/arch/x86/include/asm/paravirt.h index bed346b..c4c2319 100644 --- a/arch/x86/include/asm/paravirt.h +++ b/arch/x86/include/asm/paravirt.h
@@ -102,6 +102,16 @@ static inline void notify_page_enc_status_changed(unsigned long pfn, PVOP_VCALL3(mmu.notify_page_enc_status_changed, pfn, npages, enc); } +static __always_inline void arch_safe_halt(void) +{ + PVOP_VCALL0(irq.safe_halt); +} + +static inline void halt(void) +{ + PVOP_VCALL0(irq.halt); +} + #ifdef CONFIG_PARAVIRT_XXL static inline void load_sp0(unsigned long sp0) { @@ -165,16 +175,6 @@ static inline void __write_cr4(unsigned long x) PVOP_VCALL1(cpu.write_cr4, x); } -static __always_inline void arch_safe_halt(void) -{ - PVOP_VCALL0(irq.safe_halt); -} - -static inline void halt(void) -{ - PVOP_VCALL0(irq.halt); -} - static inline u64 paravirt_read_msr(unsigned msr) { return PVOP_CALL1(u64, cpu.read_msr, msr);
diff --git a/arch/x86/include/asm/paravirt_types.h b/arch/x86/include/asm/paravirt_types.h index 6291202..631c306 100644 --- a/arch/x86/include/asm/paravirt_types.h +++ b/arch/x86/include/asm/paravirt_types.h
@@ -120,10 +120,9 @@ struct pv_irq_ops { struct paravirt_callee_save save_fl; struct paravirt_callee_save irq_disable; struct paravirt_callee_save irq_enable; - +#endif void (*safe_halt)(void); void (*halt)(void); -#endif } __no_randomize_layout; struct pv_mmu_ops {
diff --git a/arch/x86/include/asm/smap.h b/arch/x86/include/asm/smap.h index daea94c..55a5e65 100644 --- a/arch/x86/include/asm/smap.h +++ b/arch/x86/include/asm/smap.h
@@ -16,23 +16,23 @@ #ifdef __ASSEMBLER__ #define ASM_CLAC \ - ALTERNATIVE "", "clac", X86_FEATURE_SMAP + ALTERNATIVE __stringify(ANNOTATE_IGNORE_ALTERNATIVE), "clac", X86_FEATURE_SMAP #define ASM_STAC \ - ALTERNATIVE "", "stac", X86_FEATURE_SMAP + ALTERNATIVE __stringify(ANNOTATE_IGNORE_ALTERNATIVE), "stac", X86_FEATURE_SMAP #else /* __ASSEMBLER__ */ static __always_inline void clac(void) { /* Note: a barrier is implicit in alternative() */ - alternative("", "clac", X86_FEATURE_SMAP); + alternative(ANNOTATE_IGNORE_ALTERNATIVE "", "clac", X86_FEATURE_SMAP); } static __always_inline void stac(void) { /* Note: a barrier is implicit in alternative() */ - alternative("", "stac", X86_FEATURE_SMAP); + alternative(ANNOTATE_IGNORE_ALTERNATIVE "", "stac", X86_FEATURE_SMAP); } static __always_inline unsigned long smap_save(void) @@ -40,7 +40,8 @@ static __always_inline unsigned long smap_save(void) unsigned long flags; asm volatile ("# smap_save\n\t" - ALTERNATIVE("", "pushf; pop %0; " "clac" "\n\t", + ALTERNATIVE(ANNOTATE_IGNORE_ALTERNATIVE + "", "pushf; pop %0; clac", X86_FEATURE_SMAP) : "=rm" (flags) : : "memory", "cc"); @@ -50,16 +51,22 @@ static __always_inline unsigned long smap_save(void) static __always_inline void smap_restore(unsigned long flags) { asm volatile ("# smap_restore\n\t" - ALTERNATIVE("", "push %0; popf\n\t", + ALTERNATIVE(ANNOTATE_IGNORE_ALTERNATIVE + "", "push %0; popf", X86_FEATURE_SMAP) : : "g" (flags) : "memory", "cc"); } /* These macros can be used in asm() statements */ #define ASM_CLAC \ - ALTERNATIVE("", "clac", X86_FEATURE_SMAP) + ALTERNATIVE(ANNOTATE_IGNORE_ALTERNATIVE "", "clac", X86_FEATURE_SMAP) #define ASM_STAC \ - ALTERNATIVE("", "stac", X86_FEATURE_SMAP) + ALTERNATIVE(ANNOTATE_IGNORE_ALTERNATIVE "", "stac", X86_FEATURE_SMAP) + +#define ASM_CLAC_UNSAFE \ + ALTERNATIVE("", ANNOTATE_IGNORE_ALTERNATIVE "clac", X86_FEATURE_SMAP) +#define ASM_STAC_UNSAFE \ + ALTERNATIVE("", ANNOTATE_IGNORE_ALTERNATIVE "stac", X86_FEATURE_SMAP) #endif /* __ASSEMBLER__ */
diff --git a/arch/x86/include/asm/tdx.h b/arch/x86/include/asm/tdx.h index 65394aa..4a1922e 100644 --- a/arch/x86/include/asm/tdx.h +++ b/arch/x86/include/asm/tdx.h
@@ -58,7 +58,7 @@ void tdx_get_ve_info(struct ve_info *ve); bool tdx_handle_virt_exception(struct pt_regs *regs, struct ve_info *ve); -void tdx_safe_halt(void); +void tdx_halt(void); bool tdx_early_handle_ve(struct pt_regs *regs); @@ -72,7 +72,7 @@ void __init tdx_dump_td_ctls(u64 td_ctls); #else static inline void tdx_early_init(void) { }; -static inline void tdx_safe_halt(void) { }; +static inline void tdx_halt(void) { }; static inline bool tdx_early_handle_ve(struct pt_regs *regs) { return false; }
diff --git a/arch/x86/include/asm/xen/hypercall.h b/arch/x86/include/asm/xen/hypercall.h index 97771b9..59a62c3 100644 --- a/arch/x86/include/asm/xen/hypercall.h +++ b/arch/x86/include/asm/xen/hypercall.h
@@ -231,14 +231,12 @@ static __always_inline void __xen_stac(void) * Suppress objtool seeing the STAC/CLAC and getting confused about it * calling random code with AC=1. */ - asm volatile(ANNOTATE_IGNORE_ALTERNATIVE - ASM_STAC ::: "memory", "flags"); + asm volatile(ASM_STAC_UNSAFE ::: "memory", "flags"); } static __always_inline void __xen_clac(void) { - asm volatile(ANNOTATE_IGNORE_ALTERNATIVE - ASM_CLAC ::: "memory", "flags"); + asm volatile(ASM_CLAC_UNSAFE ::: "memory", "flags"); } static inline long
diff --git a/arch/x86/kernel/apic/vector.c b/arch/x86/kernel/apic/vector.c index 72fa4bb..fee42a7 100644 --- a/arch/x86/kernel/apic/vector.c +++ b/arch/x86/kernel/apic/vector.c
@@ -799,7 +799,7 @@ int __init arch_early_irq_init(void) x86_vector_domain = irq_domain_create_tree(fn, &x86_vector_domain_ops, NULL); BUG_ON(x86_vector_domain == NULL); - irq_set_default_host(x86_vector_domain); + irq_set_default_domain(x86_vector_domain); BUG_ON(!alloc_cpumask_var(&vector_searchmask, GFP_KERNEL));
diff --git a/arch/x86/kernel/cpu/mce/core.c b/arch/x86/kernel/cpu/mce/core.c index 1f14c33..f6fd71b 100644 --- a/arch/x86/kernel/cpu/mce/core.c +++ b/arch/x86/kernel/cpu/mce/core.c
@@ -1786,13 +1786,13 @@ void mce_timer_kick(bool storm) __this_cpu_write(mce_next_interval, check_interval * HZ); } -/* Must not be called in IRQ context where del_timer_sync() can deadlock */ +/* Must not be called in IRQ context where timer_delete_sync() can deadlock */ static void mce_timer_delete_all(void) { int cpu; for_each_online_cpu(cpu) - del_timer_sync(&per_cpu(mce_timer, cpu)); + timer_delete_sync(&per_cpu(mce_timer, cpu)); } static void __mcheck_cpu_mce_banks_init(void) @@ -2820,7 +2820,7 @@ static int mce_cpu_pre_down(unsigned int cpu) struct timer_list *t = this_cpu_ptr(&mce_timer); mce_disable_cpu(); - del_timer_sync(t); + timer_delete_sync(t); mce_threshold_remove_device(cpu); mce_device_remove(cpu); return 0;
diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c index 9792563..1ccd05d 100644 --- a/arch/x86/kernel/paravirt.c +++ b/arch/x86/kernel/paravirt.c
@@ -75,6 +75,11 @@ void paravirt_set_sched_clock(u64 (*func)(void)) static_call_update(pv_sched_clock, func); } +static noinstr void pv_native_safe_halt(void) +{ + native_safe_halt(); +} + #ifdef CONFIG_PARAVIRT_XXL static noinstr void pv_native_write_cr2(unsigned long val) { @@ -100,11 +105,6 @@ static noinstr void pv_native_set_debugreg(int regno, unsigned long val) { native_set_debugreg(regno, val); } - -static noinstr void pv_native_safe_halt(void) -{ - native_safe_halt(); -} #endif struct pv_info pv_info = { @@ -161,9 +161,11 @@ struct paravirt_patch_template pv_ops = { .irq.save_fl = __PV_IS_CALLEE_SAVE(pv_native_save_fl), .irq.irq_disable = __PV_IS_CALLEE_SAVE(pv_native_irq_disable), .irq.irq_enable = __PV_IS_CALLEE_SAVE(pv_native_irq_enable), +#endif /* CONFIG_PARAVIRT_XXL */ + + /* Irq HLT ops. */ .irq.safe_halt = pv_native_safe_halt, .irq.halt = native_halt, -#endif /* CONFIG_PARAVIRT_XXL */ /* Mmu ops. */ .mmu.flush_tlb_user = native_flush_tlb_local,
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index 91f6ff6..962c3ce 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c
@@ -939,7 +939,7 @@ void __init select_idle_routine(void) static_call_update(x86_idle, mwait_idle); } else if (cpu_feature_enabled(X86_FEATURE_TDX_GUEST)) { pr_info("using TDX aware idle routine\n"); - static_call_update(x86_idle, tdx_safe_halt); + static_call_update(x86_idle, tdx_halt); } else { static_call_update(x86_idle, default_idle); }
diff --git a/arch/x86/kvm/xen.c b/arch/x86/kvm/xen.c index bd21e9c..38b33cd 100644 --- a/arch/x86/kvm/xen.c +++ b/arch/x86/kvm/xen.c
@@ -1553,7 +1553,7 @@ static bool kvm_xen_schedop_poll(struct kvm_vcpu *vcpu, bool longmode, kvm_vcpu_halt(vcpu); if (sched_poll.timeout) - del_timer(&vcpu->arch.xen.poll_timer); + timer_delete(&vcpu->arch.xen.poll_timer); kvm_set_mp_state(vcpu, KVM_MP_STATE_RUNNABLE); } @@ -2308,7 +2308,7 @@ void kvm_xen_destroy_vcpu(struct kvm_vcpu *vcpu) kvm_gpc_deactivate(&vcpu->arch.xen.vcpu_info_cache); kvm_gpc_deactivate(&vcpu->arch.xen.vcpu_time_info_cache); - del_timer_sync(&vcpu->arch.xen.poll_timer); + timer_delete_sync(&vcpu->arch.xen.poll_timer); } void kvm_xen_init_vm(struct kvm *kvm)
diff --git a/arch/x86/lib/copy_user_64.S b/arch/x86/lib/copy_user_64.S index aa8c341..06296eb 100644 --- a/arch/x86/lib/copy_user_64.S +++ b/arch/x86/lib/copy_user_64.S
@@ -77,6 +77,24 @@ _ASM_EXTABLE_UA( 0b, 1b) .Llarge_movsq: + /* Do the first possibly unaligned word */ +0: movq (%rsi),%rax +1: movq %rax,(%rdi) + + _ASM_EXTABLE_UA( 0b, .Lcopy_user_tail) + _ASM_EXTABLE_UA( 1b, .Lcopy_user_tail) + + /* What would be the offset to the aligned destination? */ + leaq 8(%rdi),%rax + andq $-8,%rax + subq %rdi,%rax + + /* .. and update pointers and count to match */ + addq %rax,%rdi + addq %rax,%rsi + subq %rax,%rcx + + /* make %rcx contain the number of words, %rax the remainder */ movq %rcx,%rax shrq $3,%rcx andl $7,%eax
diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c index 36a017b..7c4f6f5 100644 --- a/arch/x86/mm/init_64.c +++ b/arch/x86/mm/init_64.c
@@ -959,9 +959,18 @@ int add_pages(int nid, unsigned long start_pfn, unsigned long nr_pages, ret = __add_pages(nid, start_pfn, nr_pages, params); WARN_ON_ONCE(ret); - /* update max_pfn, max_low_pfn and high_memory */ - update_end_of_memory_vars(start_pfn << PAGE_SHIFT, - nr_pages << PAGE_SHIFT); + /* + * Special case: add_pages() is called by memremap_pages() for adding device + * private pages. Do not bump up max_pfn in the device private path, + * because max_pfn changes affect dma_addressing_limited(). + * + * dma_addressing_limited() returning true when max_pfn is the device's + * addressable memory can force device drivers to use bounce buffers + * and impact their performance negatively: + */ + if (!params->pgmap) + /* update max_pfn, max_low_pfn and high_memory */ + update_end_of_memory_vars(start_pfn << PAGE_SHIFT, nr_pages << PAGE_SHIFT); return ret; }
diff --git a/arch/x86/mm/pat/set_memory.c b/arch/x86/mm/pat/set_memory.c index 72405d3..def3d92 100644 --- a/arch/x86/mm/pat/set_memory.c +++ b/arch/x86/mm/pat/set_memory.c
@@ -2274,6 +2274,7 @@ int set_mce_nospec(unsigned long pfn) pr_warn("Could not invalidate pfn=0x%lx from 1:1 map\n", pfn); return rc; } +EXPORT_SYMBOL_GPL(set_mce_nospec); /* Restore full speculative operation to the pfn. */ int clear_mce_nospec(unsigned long pfn)
diff --git a/arch/x86/mm/pgtable.c b/arch/x86/mm/pgtable.c index cec321f..a05fcdd 100644 --- a/arch/x86/mm/pgtable.c +++ b/arch/x86/mm/pgtable.c
@@ -20,7 +20,7 @@ pgtable_t pte_alloc_one(struct mm_struct *mm) void ___pte_free_tlb(struct mmu_gather *tlb, struct page *pte) { paravirt_release_pte(page_to_pfn(pte)); - tlb_remove_table(tlb, page_ptdesc(pte)); + tlb_remove_ptdesc(tlb, page_ptdesc(pte)); } #if CONFIG_PGTABLE_LEVELS > 2 @@ -34,21 +34,21 @@ void ___pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd) #ifdef CONFIG_X86_PAE tlb->need_flush_all = 1; #endif - tlb_remove_table(tlb, virt_to_ptdesc(pmd)); + tlb_remove_ptdesc(tlb, virt_to_ptdesc(pmd)); } #if CONFIG_PGTABLE_LEVELS > 3 void ___pud_free_tlb(struct mmu_gather *tlb, pud_t *pud) { paravirt_release_pud(__pa(pud) >> PAGE_SHIFT); - tlb_remove_table(tlb, virt_to_ptdesc(pud)); + tlb_remove_ptdesc(tlb, virt_to_ptdesc(pud)); } #if CONFIG_PGTABLE_LEVELS > 4 void ___p4d_free_tlb(struct mmu_gather *tlb, p4d_t *p4d) { paravirt_release_p4d(__pa(p4d) >> PAGE_SHIFT); - tlb_remove_table(tlb, virt_to_ptdesc(p4d)); + tlb_remove_ptdesc(tlb, virt_to_ptdesc(p4d)); } #endif /* CONFIG_PGTABLE_LEVELS > 4 */ #endif /* CONFIG_PGTABLE_LEVELS > 3 */
diff --git a/arch/x86/platform/intel/iosf_mbi.c b/arch/x86/platform/intel/iosf_mbi.c index c81cea2..40ae94d 100644 --- a/arch/x86/platform/intel/iosf_mbi.c +++ b/arch/x86/platform/intel/iosf_mbi.c
@@ -422,19 +422,6 @@ int iosf_mbi_unregister_pmic_bus_access_notifier_unlocked( } EXPORT_SYMBOL(iosf_mbi_unregister_pmic_bus_access_notifier_unlocked); -int iosf_mbi_unregister_pmic_bus_access_notifier(struct notifier_block *nb) -{ - int ret; - - /* Wait for the bus to go inactive before unregistering */ - iosf_mbi_punit_acquire(); - ret = iosf_mbi_unregister_pmic_bus_access_notifier_unlocked(nb); - iosf_mbi_punit_release(); - - return ret; -} -EXPORT_SYMBOL(iosf_mbi_unregister_pmic_bus_access_notifier); - void iosf_mbi_assert_punit_acquired(void) { WARN_ON(iosf_mbi_pmic_punit_access_count == 0);
diff --git a/arch/x86/power/cpu.c b/arch/x86/power/cpu.c index 63230ff..08e76a5 100644 --- a/arch/x86/power/cpu.c +++ b/arch/x86/power/cpu.c
@@ -27,6 +27,7 @@ #include <asm/mmu_context.h> #include <asm/cpu_device_id.h> #include <asm/microcode.h> +#include <asm/fred.h> #ifdef CONFIG_X86_32 __visible unsigned long saved_context_ebx; @@ -231,6 +232,19 @@ static void notrace __restore_processor_state(struct saved_context *ctxt) */ #ifdef CONFIG_X86_64 wrmsrl(MSR_GS_BASE, ctxt->kernelmode_gs_base); + + /* + * Reinitialize FRED to ensure the FRED MSRs contain the same values + * as before hibernation. + * + * Note, the setup of FRED RSPs requires access to percpu data + * structures. Therefore, FRED reinitialization can only occur after + * the percpu access pointer (i.e., MSR_GS_BASE) is restored. + */ + if (ctxt->cr4 & X86_CR4_FRED) { + cpu_init_fred_exceptions(); + cpu_init_fred_rsps(); + } #else loadsegment(fs, __KERNEL_PERCPU); #endif
diff --git a/arch/x86/tools/insn_decoder_test.c b/arch/x86/tools/insn_decoder_test.c index 6c2986d..08cd913 100644 --- a/arch/x86/tools/insn_decoder_test.c +++ b/arch/x86/tools/insn_decoder_test.c
@@ -12,8 +12,6 @@ #include <stdarg.h> #include <linux/kallsyms.h> -#define unlikely(cond) (cond) - #include <asm/insn.h> #include <inat.c> #include <insn.c>
diff --git a/arch/x86/um/asm/barrier.h b/arch/x86/um/asm/barrier.h index 4da3369..b51aefd 100644 --- a/arch/x86/um/asm/barrier.h +++ b/arch/x86/um/asm/barrier.h
@@ -12,9 +12,9 @@ */ #ifdef CONFIG_X86_32 -#define mb() alternative("lock; addl $0,0(%%esp)", "mfence", X86_FEATURE_XMM2) -#define rmb() alternative("lock; addl $0,0(%%esp)", "lfence", X86_FEATURE_XMM2) -#define wmb() alternative("lock; addl $0,0(%%esp)", "sfence", X86_FEATURE_XMM) +#define mb() alternative("lock addl $0,0(%%esp)", "mfence", X86_FEATURE_XMM2) +#define rmb() alternative("lock addl $0,0(%%esp)", "lfence", X86_FEATURE_XMM2) +#define wmb() alternative("lock addl $0,0(%%esp)", "sfence", X86_FEATURE_XMM) #else /* CONFIG_X86_32 */
diff --git a/arch/x86/um/asm/module.h b/arch/x86/um/asm/module.h deleted file mode 100644 index a3b061d..0000000 --- a/arch/x86/um/asm/module.h +++ /dev/null
@@ -1,24 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef __UM_MODULE_H -#define __UM_MODULE_H - -/* UML is simple */ -struct mod_arch_specific -{ -}; - -#ifdef CONFIG_X86_32 - -#define Elf_Shdr Elf32_Shdr -#define Elf_Sym Elf32_Sym -#define Elf_Ehdr Elf32_Ehdr - -#else - -#define Elf_Shdr Elf64_Shdr -#define Elf_Sym Elf64_Sym -#define Elf_Ehdr Elf64_Ehdr - -#endif - -#endif
diff --git a/arch/x86/um/os-Linux/mcontext.c b/arch/x86/um/os-Linux/mcontext.c index e80ab7d..37decaa 100644 --- a/arch/x86/um/os-Linux/mcontext.c +++ b/arch/x86/um/os-Linux/mcontext.c
@@ -4,6 +4,7 @@ #include <asm/ptrace.h> #include <sysdep/ptrace.h> #include <sysdep/mcontext.h> +#include <arch.h> void get_regs_from_mc(struct uml_pt_regs *regs, mcontext_t *mc) { @@ -27,7 +28,17 @@ void get_regs_from_mc(struct uml_pt_regs *regs, mcontext_t *mc) COPY(RIP); COPY2(EFLAGS, EFL); COPY2(CS, CSGSFS); - regs->gp[CS / sizeof(unsigned long)] &= 0xffff; - regs->gp[CS / sizeof(unsigned long)] |= 3; + regs->gp[SS / sizeof(unsigned long)] = mc->gregs[REG_CSGSFS] >> 48; +#endif +} + +void mc_set_rip(void *_mc, void *target) +{ + mcontext_t *mc = _mc; + +#ifdef __i386__ + mc->gregs[REG_EIP] = (unsigned long)target; +#else + mc->gregs[REG_RIP] = (unsigned long)target; #endif }
diff --git a/arch/x86/um/shared/sysdep/faultinfo_32.h b/arch/x86/um/shared/sysdep/faultinfo_32.h index b6f2437..ab5c8e4 100644 --- a/arch/x86/um/shared/sysdep/faultinfo_32.h +++ b/arch/x86/um/shared/sysdep/faultinfo_32.h
@@ -29,4 +29,16 @@ struct faultinfo { #define PTRACE_FULL_FAULTINFO 0 +#define ___backtrack_faulted(_faulted) \ + asm volatile ( \ + "mov $0, %0\n" \ + "movl $__get_kernel_nofault_faulted_%=,%1\n" \ + "jmp _end_%=\n" \ + "__get_kernel_nofault_faulted_%=:\n" \ + "mov $1, %0;" \ + "_end_%=:" \ + : "=r" (_faulted), \ + "=m" (current->thread.segv_continue) :: \ + ) + #endif
diff --git a/arch/x86/um/shared/sysdep/faultinfo_64.h b/arch/x86/um/shared/sysdep/faultinfo_64.h index ee88f889..26fb483 100644 --- a/arch/x86/um/shared/sysdep/faultinfo_64.h +++ b/arch/x86/um/shared/sysdep/faultinfo_64.h
@@ -29,4 +29,16 @@ struct faultinfo { #define PTRACE_FULL_FAULTINFO 1 +#define ___backtrack_faulted(_faulted) \ + asm volatile ( \ + "mov $0, %0\n" \ + "movq $__get_kernel_nofault_faulted_%=,%1\n" \ + "jmp _end_%=\n" \ + "__get_kernel_nofault_faulted_%=:\n" \ + "mov $1, %0;" \ + "_end_%=:" \ + : "=r" (_faulted), \ + "=m" (current->thread.segv_continue) :: \ + ) + #endif
diff --git a/arch/x86/um/vdso/vma.c b/arch/x86/um/vdso/vma.c index f238f7b..dc8dfb2 100644 --- a/arch/x86/um/vdso/vma.c +++ b/arch/x86/um/vdso/vma.c
@@ -12,33 +12,22 @@ static unsigned int __read_mostly vdso_enabled = 1; unsigned long um_vdso_addr; +static struct page *um_vdso; extern unsigned long task_size; extern char vdso_start[], vdso_end[]; -static struct page **vdsop; - static int __init init_vdso(void) { - struct page *um_vdso; - BUG_ON(vdso_end - vdso_start > PAGE_SIZE); um_vdso_addr = task_size - PAGE_SIZE; - vdsop = kmalloc(sizeof(struct page *), GFP_KERNEL); - if (!vdsop) - goto oom; - um_vdso = alloc_page(GFP_KERNEL); - if (!um_vdso) { - kfree(vdsop); - + if (!um_vdso) goto oom; - } copy_page(page_address(um_vdso), vdso_start); - *vdsop = um_vdso; return 0; @@ -56,6 +45,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp) struct mm_struct *mm = current->mm; static struct vm_special_mapping vdso_mapping = { .name = "[vdso]", + .pages = &um_vdso, }; if (!vdso_enabled) @@ -64,7 +54,6 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp) if (mmap_write_lock_killable(mm)) return -EINTR; - vdso_mapping.pages = vdsop; vma = _install_special_mapping(mm, um_vdso_addr, PAGE_SIZE, VM_READ|VM_EXEC| VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC,
diff --git a/arch/xtensa/platforms/iss/console.c b/arch/xtensa/platforms/iss/console.c index abec44b6..8b95221 100644 --- a/arch/xtensa/platforms/iss/console.c +++ b/arch/xtensa/platforms/iss/console.c
@@ -48,7 +48,7 @@ static int rs_open(struct tty_struct *tty, struct file * filp) static void rs_close(struct tty_struct *tty, struct file * filp) { if (tty->count == 1) - del_timer_sync(&serial_timer); + timer_delete_sync(&serial_timer); }
diff --git a/arch/xtensa/platforms/iss/network.c b/arch/xtensa/platforms/iss/network.c index e89f27f..c6d8c62 100644 --- a/arch/xtensa/platforms/iss/network.c +++ b/arch/xtensa/platforms/iss/network.c
@@ -375,7 +375,7 @@ static int iss_net_close(struct net_device *dev) struct iss_net_private *lp = netdev_priv(dev); netif_stop_queue(dev); - del_timer_sync(&lp->timer); + timer_delete_sync(&lp->timer); lp->tp.net_ops->close(lp); return 0;
diff --git a/block/blk-core.c b/block/blk-core.c index 4623de7..e8cc270 100644 --- a/block/blk-core.c +++ b/block/blk-core.c
@@ -219,7 +219,7 @@ EXPORT_SYMBOL_GPL(blk_status_to_str); */ void blk_sync_queue(struct request_queue *q) { - del_timer_sync(&q->timeout); + timer_delete_sync(&q->timeout); cancel_work_sync(&q->timeout_work); } EXPORT_SYMBOL(blk_sync_queue);
diff --git a/block/blk-mq.c b/block/blk-mq.c index ae8494d..c2697db 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c
@@ -2965,8 +2965,7 @@ static bool blk_mq_attempt_bio_merge(struct request_queue *q, static struct request *blk_mq_get_new_requests(struct request_queue *q, struct blk_plug *plug, - struct bio *bio, - unsigned int nsegs) + struct bio *bio) { struct blk_mq_alloc_data data = { .q = q, @@ -3125,7 +3124,7 @@ void blk_mq_submit_bio(struct bio *bio) if (rq) { blk_mq_use_cached_rq(rq, plug, bio); } else { - rq = blk_mq_get_new_requests(q, plug, bio, nr_segs); + rq = blk_mq_get_new_requests(q, plug, bio); if (unlikely(!rq)) { if (bio->bi_opf & REQ_NOWAIT) bio_wouldblock_error(bio); @@ -4465,14 +4464,12 @@ static struct blk_mq_hw_ctx *blk_mq_alloc_and_init_hctx( return NULL; } -static void blk_mq_realloc_hw_ctxs(struct blk_mq_tag_set *set, - struct request_queue *q) +static void __blk_mq_realloc_hw_ctxs(struct blk_mq_tag_set *set, + struct request_queue *q) { struct blk_mq_hw_ctx *hctx; unsigned long i, j; - /* protect against switching io scheduler */ - mutex_lock(&q->elevator_lock); for (i = 0; i < set->nr_hw_queues; i++) { int old_node; int node = blk_mq_get_hctx_node(set, i); @@ -4505,7 +4502,19 @@ static void blk_mq_realloc_hw_ctxs(struct blk_mq_tag_set *set, xa_for_each_start(&q->hctx_table, j, hctx, j) blk_mq_exit_hctx(q, set, hctx, j); - mutex_unlock(&q->elevator_lock); +} + +static void blk_mq_realloc_hw_ctxs(struct blk_mq_tag_set *set, + struct request_queue *q, bool lock) +{ + if (lock) { + /* protect against switching io scheduler */ + mutex_lock(&q->elevator_lock); + __blk_mq_realloc_hw_ctxs(set, q); + mutex_unlock(&q->elevator_lock); + } else { + __blk_mq_realloc_hw_ctxs(set, q); + } /* unregister cpuhp callbacks for exited hctxs */ blk_mq_remove_hw_queues_cpuhp(q); @@ -4537,7 +4546,7 @@ int blk_mq_init_allocated_queue(struct blk_mq_tag_set *set, xa_init(&q->hctx_table); - blk_mq_realloc_hw_ctxs(set, q); + blk_mq_realloc_hw_ctxs(set, q, false); if (!q->nr_hw_queues) goto err_hctxs; @@ -5033,7 +5042,7 @@ static void __blk_mq_update_nr_hw_queues(struct blk_mq_tag_set *set, fallback: blk_mq_update_queue_map(set); list_for_each_entry(q, &set->tag_list, tag_set_list) { - blk_mq_realloc_hw_ctxs(set, q); + blk_mq_realloc_hw_ctxs(set, q, true); if (q->nr_hw_queues != set->nr_hw_queues) { int i = prev_nr_hw_queues;
diff --git a/block/blk-stat.c b/block/blk-stat.c index eaf6009..46449da 100644 --- a/block/blk-stat.c +++ b/block/blk-stat.c
@@ -162,7 +162,7 @@ void blk_stat_remove_callback(struct request_queue *q, blk_queue_flag_clear(QUEUE_FLAG_STATS, q); spin_unlock_irqrestore(&q->stats->lock, flags); - del_timer_sync(&cb->timer); + timer_delete_sync(&cb->timer); } static void blk_stat_free_callback_rcu(struct rcu_head *head)
diff --git a/block/blk-stat.h b/block/blk-stat.h index 5d7f18b..9e05bf1 100644 --- a/block/blk-stat.h +++ b/block/blk-stat.h
@@ -148,7 +148,7 @@ static inline void blk_stat_activate_nsecs(struct blk_stat_callback *cb, static inline void blk_stat_deactivate(struct blk_stat_callback *cb) { - del_timer_sync(&cb->timer); + timer_delete_sync(&cb->timer); } /**
diff --git a/block/blk-throttle.c b/block/blk-throttle.c index 91dab43..d6dd2e0 100644 --- a/block/blk-throttle.c +++ b/block/blk-throttle.c
@@ -333,7 +333,7 @@ static void throtl_pd_free(struct blkg_policy_data *pd) { struct throtl_grp *tg = pd_to_tg(pd); - del_timer_sync(&tg->service_queue.pending_timer); + timer_delete_sync(&tg->service_queue.pending_timer); blkg_rwstat_exit(&tg->stat_bytes); blkg_rwstat_exit(&tg->stat_ios); kfree(tg); @@ -1711,7 +1711,7 @@ void blk_throtl_exit(struct gendisk *disk) if (!blk_throtl_activated(q)) return; - del_timer_sync(&q->td->service_queue.pending_timer); + timer_delete_sync(&q->td->service_queue.pending_timer); throtl_shutdown_wq(q); blkcg_deactivate_policy(disk, &blkcg_policy_throtl); kfree(q->td);
diff --git a/crypto/testmgr.c b/crypto/testmgr.c index d294c59..abd609d 100644 --- a/crypto/testmgr.c +++ b/crypto/testmgr.c
@@ -302,13 +302,6 @@ struct test_sg_division { * @key_offset_relative_to_alignmask: if true, add the algorithm's alignmask to * the @key_offset * @finalization_type: what finalization function to use for hashes - * @multibuffer: test with multibuffer - * @multibuffer_index: random number used to generate the message index to use - * for multibuffer. - * @multibuffer_uneven: test with multibuffer using uneven lengths - * @multibuffer_lens: random lengths to make chained request uneven - * @multibuffer_count: random number used to generate the num_msgs parameter - * for multibuffer * @nosimd: execute with SIMD disabled? Requires !CRYPTO_TFM_REQ_MAY_SLEEP. * This applies to the parts of the operation that aren't controlled * individually by @nosimd_setkey or @src_divs[].nosimd. @@ -328,11 +321,6 @@ struct testvec_config { enum finalization_type finalization_type; bool nosimd; bool nosimd_setkey; - bool multibuffer; - unsigned int multibuffer_index; - unsigned int multibuffer_count; - bool multibuffer_uneven; - unsigned int multibuffer_lens[MAX_MB_MSGS]; }; #define TESTVEC_CONFIG_NAMELEN 192 @@ -572,7 +560,6 @@ struct test_sglist { char *bufs[XBUFSIZE]; struct scatterlist sgl[XBUFSIZE]; struct scatterlist sgl_saved[XBUFSIZE]; - struct scatterlist full_sgl[XBUFSIZE]; struct scatterlist *sgl_ptr; unsigned int nents; }; @@ -686,11 +673,6 @@ static int build_test_sglist(struct test_sglist *tsgl, sg_mark_end(&tsgl->sgl[tsgl->nents - 1]); tsgl->sgl_ptr = tsgl->sgl; memcpy(tsgl->sgl_saved, tsgl->sgl, tsgl->nents * sizeof(tsgl->sgl[0])); - - sg_init_table(tsgl->full_sgl, XBUFSIZE); - for (i = 0; i < XBUFSIZE; i++) - sg_set_buf(tsgl->full_sgl, tsgl->bufs[i], PAGE_SIZE * 2); - return 0; } @@ -1167,27 +1149,6 @@ static void generate_random_testvec_config(struct rnd_state *rng, break; } - if (prandom_bool(rng)) { - int i; - - cfg->multibuffer = true; - cfg->multibuffer_count = prandom_u32_state(rng); - cfg->multibuffer_count %= MAX_MB_MSGS; - if (cfg->multibuffer_count++) { - cfg->multibuffer_index = prandom_u32_state(rng); - cfg->multibuffer_index %= cfg->multibuffer_count; - } - - cfg->multibuffer_uneven = prandom_bool(rng); - for (i = 0; i < MAX_MB_MSGS; i++) - cfg->multibuffer_lens[i] = - generate_random_length(rng, PAGE_SIZE * 2 * XBUFSIZE); - - p += scnprintf(p, end - p, " multibuffer(%d/%d%s)", - cfg->multibuffer_index, cfg->multibuffer_count, - cfg->multibuffer_uneven ? "/uneven" : ""); - } - if (!(cfg->req_flags & CRYPTO_TFM_REQ_MAY_SLEEP)) { if (prandom_bool(rng)) { cfg->nosimd = true; @@ -1492,7 +1453,6 @@ static int do_ahash_op(int (*op)(struct ahash_request *req), struct ahash_request *req, struct crypto_wait *wait, bool nosimd) { - struct ahash_request *r2; int err; if (nosimd) @@ -1503,15 +1463,7 @@ static int do_ahash_op(int (*op)(struct ahash_request *req), if (nosimd) crypto_reenable_simd_for_test(); - err = crypto_wait_req(err, wait); - if (err) - return err; - - list_for_each_entry(r2, &req->base.list, base.list) - if (r2->base.err) - return r2->base.err; - - return 0; + return crypto_wait_req(err, wait); } static int check_nonfinal_ahash_op(const char *op, int err, @@ -1532,65 +1484,20 @@ static int check_nonfinal_ahash_op(const char *op, int err, return 0; } -static void setup_ahash_multibuffer( - struct ahash_request *reqs[MAX_MB_MSGS], - const struct testvec_config *cfg, - struct test_sglist *tsgl) -{ - struct scatterlist *sg = tsgl->full_sgl; - static u8 trash[HASH_MAX_DIGESTSIZE]; - struct ahash_request *req = reqs[0]; - unsigned int num_msgs; - unsigned int msg_idx; - int i; - - if (!cfg->multibuffer) - return; - - num_msgs = cfg->multibuffer_count; - if (num_msgs == 1) - return; - - msg_idx = cfg->multibuffer_index; - for (i = 1; i < num_msgs; i++) { - struct ahash_request *r2 = reqs[i]; - unsigned int nbytes = req->nbytes; - - if (cfg->multibuffer_uneven) - nbytes = cfg->multibuffer_lens[i]; - - ahash_request_set_callback(r2, req->base.flags, NULL, NULL); - ahash_request_set_crypt(r2, sg, trash, nbytes); - ahash_request_chain(r2, req); - } - - if (msg_idx) { - reqs[msg_idx]->src = req->src; - reqs[msg_idx]->nbytes = req->nbytes; - reqs[msg_idx]->result = req->result; - req->src = sg; - if (cfg->multibuffer_uneven) - req->nbytes = cfg->multibuffer_lens[0]; - req->result = trash; - } -} - /* Test one hash test vector in one configuration, using the ahash API */ static int test_ahash_vec_cfg(const struct hash_testvec *vec, const char *vec_name, const struct testvec_config *cfg, - struct ahash_request *reqs[MAX_MB_MSGS], + struct ahash_request *req, struct test_sglist *tsgl, u8 *hashstate) { - struct ahash_request *req = reqs[0]; struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); const unsigned int digestsize = crypto_ahash_digestsize(tfm); const unsigned int statesize = crypto_ahash_statesize(tfm); const char *driver = crypto_ahash_driver_name(tfm); const u32 req_flags = CRYPTO_TFM_REQ_MAY_BACKLOG | cfg->req_flags; const struct test_sg_division *divs[XBUFSIZE]; - struct ahash_request *reqi = req; DECLARE_CRYPTO_WAIT(wait); unsigned int i; struct scatterlist *pending_sgl; @@ -1598,9 +1505,6 @@ static int test_ahash_vec_cfg(const struct hash_testvec *vec, u8 result[HASH_MAX_DIGESTSIZE + TESTMGR_POISON_LEN]; int err; - if (cfg->multibuffer) - reqi = reqs[cfg->multibuffer_index]; - /* Set the key, if specified */ if (vec->ksize) { err = do_setkey(crypto_ahash_setkey, tfm, vec->key, vec->ksize, @@ -1630,7 +1534,7 @@ static int test_ahash_vec_cfg(const struct hash_testvec *vec, /* Do the actual hashing */ - testmgr_poison(reqi->__ctx, crypto_ahash_reqsize(tfm)); + testmgr_poison(req->__ctx, crypto_ahash_reqsize(tfm)); testmgr_poison(result, digestsize + TESTMGR_POISON_LEN); if (cfg->finalization_type == FINALIZATION_TYPE_DIGEST || @@ -1639,7 +1543,6 @@ static int test_ahash_vec_cfg(const struct hash_testvec *vec, ahash_request_set_callback(req, req_flags, crypto_req_done, &wait); ahash_request_set_crypt(req, tsgl->sgl, result, vec->psize); - setup_ahash_multibuffer(reqs, cfg, tsgl); err = do_ahash_op(crypto_ahash_digest, req, &wait, cfg->nosimd); if (err) { if (err == vec->digest_error) @@ -1661,7 +1564,6 @@ static int test_ahash_vec_cfg(const struct hash_testvec *vec, ahash_request_set_callback(req, req_flags, crypto_req_done, &wait); ahash_request_set_crypt(req, NULL, result, 0); - setup_ahash_multibuffer(reqs, cfg, tsgl); err = do_ahash_op(crypto_ahash_init, req, &wait, cfg->nosimd); err = check_nonfinal_ahash_op("init", err, result, digestsize, driver, vec_name, cfg); @@ -1678,7 +1580,6 @@ static int test_ahash_vec_cfg(const struct hash_testvec *vec, crypto_req_done, &wait); ahash_request_set_crypt(req, pending_sgl, result, pending_len); - setup_ahash_multibuffer(reqs, cfg, tsgl); err = do_ahash_op(crypto_ahash_update, req, &wait, divs[i]->nosimd); err = check_nonfinal_ahash_op("update", err, @@ -1693,7 +1594,7 @@ static int test_ahash_vec_cfg(const struct hash_testvec *vec, /* Test ->export() and ->import() */ testmgr_poison(hashstate + statesize, TESTMGR_POISON_LEN); - err = crypto_ahash_export(reqi, hashstate); + err = crypto_ahash_export(req, hashstate); err = check_nonfinal_ahash_op("export", err, result, digestsize, driver, vec_name, cfg); @@ -1706,8 +1607,8 @@ static int test_ahash_vec_cfg(const struct hash_testvec *vec, return -EOVERFLOW; } - testmgr_poison(reqi->__ctx, crypto_ahash_reqsize(tfm)); - err = crypto_ahash_import(reqi, hashstate); + testmgr_poison(req->__ctx, crypto_ahash_reqsize(tfm)); + err = crypto_ahash_import(req, hashstate); err = check_nonfinal_ahash_op("import", err, result, digestsize, driver, vec_name, cfg); @@ -1721,7 +1622,6 @@ static int test_ahash_vec_cfg(const struct hash_testvec *vec, ahash_request_set_callback(req, req_flags, crypto_req_done, &wait); ahash_request_set_crypt(req, pending_sgl, result, pending_len); - setup_ahash_multibuffer(reqs, cfg, tsgl); if (cfg->finalization_type == FINALIZATION_TYPE_FINAL) { /* finish with update() and final() */ err = do_ahash_op(crypto_ahash_update, req, &wait, cfg->nosimd); @@ -1753,7 +1653,7 @@ static int test_ahash_vec_cfg(const struct hash_testvec *vec, static int test_hash_vec_cfg(const struct hash_testvec *vec, const char *vec_name, const struct testvec_config *cfg, - struct ahash_request *reqs[MAX_MB_MSGS], + struct ahash_request *req, struct shash_desc *desc, struct test_sglist *tsgl, u8 *hashstate) @@ -1773,12 +1673,11 @@ static int test_hash_vec_cfg(const struct hash_testvec *vec, return err; } - return test_ahash_vec_cfg(vec, vec_name, cfg, reqs, tsgl, hashstate); + return test_ahash_vec_cfg(vec, vec_name, cfg, req, tsgl, hashstate); } static int test_hash_vec(const struct hash_testvec *vec, unsigned int vec_num, - struct ahash_request *reqs[MAX_MB_MSGS], - struct shash_desc *desc, + struct ahash_request *req, struct shash_desc *desc, struct test_sglist *tsgl, u8 *hashstate) { char vec_name[16]; @@ -1790,7 +1689,7 @@ static int test_hash_vec(const struct hash_testvec *vec, unsigned int vec_num, for (i = 0; i < ARRAY_SIZE(default_hash_testvec_configs); i++) { err = test_hash_vec_cfg(vec, vec_name, &default_hash_testvec_configs[i], - reqs, desc, tsgl, hashstate); + req, desc, tsgl, hashstate); if (err) return err; } @@ -1807,7 +1706,7 @@ static int test_hash_vec(const struct hash_testvec *vec, unsigned int vec_num, generate_random_testvec_config(&rng, &cfg, cfgname, sizeof(cfgname)); err = test_hash_vec_cfg(vec, vec_name, &cfg, - reqs, desc, tsgl, hashstate); + req, desc, tsgl, hashstate); if (err) return err; cond_resched(); @@ -1866,12 +1765,11 @@ static void generate_random_hash_testvec(struct rnd_state *rng, */ static int test_hash_vs_generic_impl(const char *generic_driver, unsigned int maxkeysize, - struct ahash_request *reqs[MAX_MB_MSGS], + struct ahash_request *req, struct shash_desc *desc, struct test_sglist *tsgl, u8 *hashstate) { - struct ahash_request *req = reqs[0]; struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); const unsigned int digestsize = crypto_ahash_digestsize(tfm); const unsigned int blocksize = crypto_ahash_blocksize(tfm); @@ -1969,7 +1867,7 @@ static int test_hash_vs_generic_impl(const char *generic_driver, sizeof(cfgname)); err = test_hash_vec_cfg(&vec, vec_name, cfg, - reqs, desc, tsgl, hashstate); + req, desc, tsgl, hashstate); if (err) goto out; cond_resched(); @@ -1987,7 +1885,7 @@ static int test_hash_vs_generic_impl(const char *generic_driver, #else /* !CONFIG_CRYPTO_MANAGER_EXTRA_TESTS */ static int test_hash_vs_generic_impl(const char *generic_driver, unsigned int maxkeysize, - struct ahash_request *reqs[MAX_MB_MSGS], + struct ahash_request *req, struct shash_desc *desc, struct test_sglist *tsgl, u8 *hashstate) @@ -2034,8 +1932,8 @@ static int __alg_test_hash(const struct hash_testvec *vecs, u32 type, u32 mask, const char *generic_driver, unsigned int maxkeysize) { - struct ahash_request *reqs[MAX_MB_MSGS] = {}; struct crypto_ahash *atfm = NULL; + struct ahash_request *req = NULL; struct crypto_shash *stfm = NULL; struct shash_desc *desc = NULL; struct test_sglist *tsgl = NULL; @@ -2059,14 +1957,12 @@ static int __alg_test_hash(const struct hash_testvec *vecs, } driver = crypto_ahash_driver_name(atfm); - for (i = 0; i < MAX_MB_MSGS; i++) { - reqs[i] = ahash_request_alloc(atfm, GFP_KERNEL); - if (!reqs[i]) { - pr_err("alg: hash: failed to allocate request for %s\n", - driver); - err = -ENOMEM; - goto out; - } + req = ahash_request_alloc(atfm, GFP_KERNEL); + if (!req) { + pr_err("alg: hash: failed to allocate request for %s\n", + driver); + err = -ENOMEM; + goto out; } /* @@ -2102,12 +1998,12 @@ static int __alg_test_hash(const struct hash_testvec *vecs, if (fips_enabled && vecs[i].fips_skip) continue; - err = test_hash_vec(&vecs[i], i, reqs, desc, tsgl, hashstate); + err = test_hash_vec(&vecs[i], i, req, desc, tsgl, hashstate); if (err) goto out; cond_resched(); } - err = test_hash_vs_generic_impl(generic_driver, maxkeysize, reqs, + err = test_hash_vs_generic_impl(generic_driver, maxkeysize, req, desc, tsgl, hashstate); out: kfree(hashstate); @@ -2117,12 +2013,7 @@ static int __alg_test_hash(const struct hash_testvec *vecs, } kfree(desc); crypto_free_shash(stfm); - if (reqs[0]) { - ahash_request_set_callback(reqs[0], 0, NULL, NULL); - for (i = 1; i < MAX_MB_MSGS && reqs[i]; i++) - ahash_request_chain(reqs[i], reqs[0]); - ahash_request_free(reqs[0]); - } + ahash_request_free(req); crypto_free_ahash(atfm); return err; }
diff --git a/drivers/accel/qaic/qaic_timesync.c b/drivers/accel/qaic/qaic_timesync.c index 2473c66..972833f 100644 --- a/drivers/accel/qaic/qaic_timesync.c +++ b/drivers/accel/qaic/qaic_timesync.c
@@ -221,7 +221,7 @@ static void qaic_timesync_remove(struct mhi_device *mhi_dev) { struct mqts_dev *mqtsdev = dev_get_drvdata(&mhi_dev->dev); - del_timer_sync(&mqtsdev->timer); + timer_delete_sync(&mqtsdev->timer); mhi_unprepare_from_transfer(mqtsdev->mhi_dev); kfree(mqtsdev->sync_msg); kfree(mqtsdev);
diff --git a/drivers/accessibility/speakup/main.c b/drivers/accessibility/speakup/main.c index f677ad2..e68cf1d 100644 --- a/drivers/accessibility/speakup/main.c +++ b/drivers/accessibility/speakup/main.c
@@ -1172,13 +1172,13 @@ static void do_handle_shift(struct vc_data *vc, u_char value, char up_flag) if (cursor_track == read_all_mode) { switch (value) { case KVAL(K_SHIFT): - del_timer(&cursor_timer); + timer_delete(&cursor_timer); spk_shut_up &= 0xfe; spk_do_flush(); read_all_doc(vc); break; case KVAL(K_CTRL): - del_timer(&cursor_timer); + timer_delete(&cursor_timer); cursor_track = prev_cursor_track; spk_shut_up &= 0xfe; spk_do_flush(); @@ -1399,7 +1399,7 @@ static void start_read_all_timer(struct vc_data *vc, enum read_all_command comma static void kbd_fakekey2(struct vc_data *vc, enum read_all_command command) { - del_timer(&cursor_timer); + timer_delete(&cursor_timer); speakup_fake_down_arrow(); start_read_all_timer(vc, command); } @@ -1415,7 +1415,7 @@ static void read_all_doc(struct vc_data *vc) cursor_track = read_all_mode; spk_reset_index_count(0); if (get_sentence_buf(vc, 0) == -1) { - del_timer(&cursor_timer); + timer_delete(&cursor_timer); if (!in_keyboard_notifier) speakup_fake_down_arrow(); start_read_all_timer(vc, RA_DOWN_ARROW); @@ -1428,7 +1428,7 @@ static void read_all_doc(struct vc_data *vc) static void stop_read_all(struct vc_data *vc) { - del_timer(&cursor_timer); + timer_delete(&cursor_timer); cursor_track = prev_cursor_track; spk_shut_up &= 0xfe; spk_do_flush(); @@ -1528,7 +1528,7 @@ static int pre_handle_cursor(struct vc_data *vc, u_char value, char up_flag) spin_unlock_irqrestore(&speakup_info.spinlock, flags); return NOTIFY_STOP; } - del_timer(&cursor_timer); + timer_delete(&cursor_timer); spk_shut_up &= 0xfe; spk_do_flush(); start_read_all_timer(vc, value + 1); @@ -1692,7 +1692,7 @@ static void cursor_done(struct timer_list *unused) struct vc_data *vc = vc_cons[cursor_con].d; unsigned long flags; - del_timer(&cursor_timer); + timer_delete(&cursor_timer); spin_lock_irqsave(&speakup_info.spinlock, flags); if (cursor_con != fg_console) { is_cursor = 0; @@ -2333,7 +2333,7 @@ static void __exit speakup_exit(void) speakup_unregister_devsynth(); speakup_cancel_selection(); speakup_cancel_paste(); - del_timer_sync(&cursor_timer); + timer_delete_sync(&cursor_timer); kthread_stop(speakup_task); speakup_task = NULL; mutex_lock(&spk_mutex); @@ -2437,7 +2437,7 @@ static int __init speakup_init(void) error_vtnotifier: unregister_keyboard_notifier(&keyboard_notifier_block); - del_timer(&cursor_timer); + timer_delete(&cursor_timer); error_kbdnotifier: speakup_unregister_devsynth();
diff --git a/drivers/accessibility/speakup/synth.c b/drivers/accessibility/speakup/synth.c index 85062e6..d8addbf 100644 --- a/drivers/accessibility/speakup/synth.c +++ b/drivers/accessibility/speakup/synth.c
@@ -521,7 +521,7 @@ void synth_release(void) spin_lock_irqsave(&speakup_info.spinlock, flags); pr_info("releasing synth %s\n", synth->name); synth->alive = 0; - del_timer(&thread_timer); + timer_delete(&thread_timer); spin_unlock_irqrestore(&speakup_info.spinlock, flags); if (synth->attributes.name) sysfs_remove_group(speakup_kobj, &synth->attributes);
diff --git a/drivers/acpi/acpi_pnp.c b/drivers/acpi/acpi_pnp.c index 435ec60..4ad8818 100644 --- a/drivers/acpi/acpi_pnp.c +++ b/drivers/acpi/acpi_pnp.c
@@ -353,8 +353,10 @@ static bool acpi_pnp_match(const char *idstr, const struct acpi_device_id **matc * device represented by it. */ static const struct acpi_device_id acpi_nonpnp_device_ids[] = { + {"INT3F0D"}, {"INTC1080"}, {"INTC1081"}, + {"INTC1099"}, {""}, };
diff --git a/drivers/acpi/acpi_video.c b/drivers/acpi/acpi_video.c index efdadc7..103f2966 100644 --- a/drivers/acpi/acpi_video.c +++ b/drivers/acpi/acpi_video.c
@@ -649,6 +649,13 @@ acpi_video_device_EDID(struct acpi_video_device *device, void **edid, int length obj = buffer.pointer; + /* + * Some buggy implementations incorrectly return the EDID buffer in an ACPI package. + * In this case, extract the buffer from the package. + */ + if (obj && obj->type == ACPI_TYPE_PACKAGE && obj->package.count == 1) + obj = &obj->package.elements[0]; + if (obj && obj->type == ACPI_TYPE_BUFFER) { *edid = kmemdup(obj->buffer.pointer, obj->buffer.length, GFP_KERNEL); ret = *edid ? obj->buffer.length : -ENOMEM; @@ -658,7 +665,7 @@ acpi_video_device_EDID(struct acpi_video_device *device, void **edid, int length ret = -EFAULT; } - kfree(obj); + kfree(buffer.pointer); return ret; }
diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c index b727724..289e365 100644 --- a/drivers/acpi/apei/ghes.c +++ b/drivers/acpi/apei/ghes.c
@@ -674,6 +674,105 @@ static void ghes_defer_non_standard_event(struct acpi_hest_generic_data *gdata, schedule_work(&entry->work); } +/* Room for 8 entries */ +#define CXL_CPER_PROT_ERR_FIFO_DEPTH 8 +static DEFINE_KFIFO(cxl_cper_prot_err_fifo, struct cxl_cper_prot_err_work_data, + CXL_CPER_PROT_ERR_FIFO_DEPTH); + +/* Synchronize schedule_work() with cxl_cper_prot_err_work changes */ +static DEFINE_SPINLOCK(cxl_cper_prot_err_work_lock); +struct work_struct *cxl_cper_prot_err_work; + +static void cxl_cper_post_prot_err(struct cxl_cper_sec_prot_err *prot_err, + int severity) +{ +#ifdef CONFIG_ACPI_APEI_PCIEAER + struct cxl_cper_prot_err_work_data wd; + u8 *dvsec_start, *cap_start; + + if (!(prot_err->valid_bits & PROT_ERR_VALID_AGENT_ADDRESS)) { + pr_err_ratelimited("CXL CPER invalid agent type\n"); + return; + } + + if (!(prot_err->valid_bits & PROT_ERR_VALID_ERROR_LOG)) { + pr_err_ratelimited("CXL CPER invalid protocol error log\n"); + return; + } + + if (prot_err->err_len != sizeof(struct cxl_ras_capability_regs)) { + pr_err_ratelimited("CXL CPER invalid RAS Cap size (%u)\n", + prot_err->err_len); + return; + } + + if (!(prot_err->valid_bits & PROT_ERR_VALID_SERIAL_NUMBER)) + pr_warn(FW_WARN "CXL CPER no device serial number\n"); + + guard(spinlock_irqsave)(&cxl_cper_prot_err_work_lock); + + if (!cxl_cper_prot_err_work) + return; + + switch (prot_err->agent_type) { + case RCD: + case DEVICE: + case LD: + case FMLD: + case RP: + case DSP: + case USP: + memcpy(&wd.prot_err, prot_err, sizeof(wd.prot_err)); + + dvsec_start = (u8 *)(prot_err + 1); + cap_start = dvsec_start + prot_err->dvsec_len; + + memcpy(&wd.ras_cap, cap_start, sizeof(wd.ras_cap)); + wd.severity = cper_severity_to_aer(severity); + break; + default: + pr_err_ratelimited("CXL CPER invalid agent type: %d\n", + prot_err->agent_type); + return; + } + + if (!kfifo_put(&cxl_cper_prot_err_fifo, wd)) { + pr_err_ratelimited("CXL CPER kfifo overflow\n"); + return; + } + + schedule_work(cxl_cper_prot_err_work); +#endif +} + +int cxl_cper_register_prot_err_work(struct work_struct *work) +{ + if (cxl_cper_prot_err_work) + return -EINVAL; + + guard(spinlock)(&cxl_cper_prot_err_work_lock); + cxl_cper_prot_err_work = work; + return 0; +} +EXPORT_SYMBOL_NS_GPL(cxl_cper_register_prot_err_work, "CXL"); + +int cxl_cper_unregister_prot_err_work(struct work_struct *work) +{ + if (cxl_cper_prot_err_work != work) + return -EINVAL; + + guard(spinlock)(&cxl_cper_prot_err_work_lock); + cxl_cper_prot_err_work = NULL; + return 0; +} +EXPORT_SYMBOL_NS_GPL(cxl_cper_unregister_prot_err_work, "CXL"); + +int cxl_cper_prot_err_kfifo_get(struct cxl_cper_prot_err_work_data *wd) +{ + return kfifo_get(&cxl_cper_prot_err_fifo, wd); +} +EXPORT_SYMBOL_NS_GPL(cxl_cper_prot_err_kfifo_get, "CXL"); + /* Room for 8 entries for each of the 4 event log queues */ #define CXL_CPER_FIFO_DEPTH 32 DEFINE_KFIFO(cxl_cper_fifo, struct cxl_cper_work_data, CXL_CPER_FIFO_DEPTH); @@ -777,6 +876,10 @@ static bool ghes_do_proc(struct ghes *ghes, } else if (guid_equal(sec_type, &CPER_SEC_PROC_ARM)) { queued = ghes_handle_arm_hw_error(gdata, sev, sync); + } else if (guid_equal(sec_type, &CPER_SEC_CXL_PROT_ERR)) { + struct cxl_cper_sec_prot_err *prot_err = acpi_hest_get_payload(gdata); + + cxl_cper_post_prot_err(prot_err, gdata->error_severity); } else if (guid_equal(sec_type, &CPER_SEC_CXL_GEN_MEDIA_GUID)) { struct cxl_cper_event_rec *rec = acpi_hest_get_payload(gdata);
diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c index a5d47819..ae035b9 100644 --- a/drivers/acpi/nfit/core.c +++ b/drivers/acpi/nfit/core.c
@@ -485,7 +485,7 @@ int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm, cmd_mask = nd_desc->cmd_mask; if (cmd == ND_CMD_CALL && call_pkg->nd_family) { family = call_pkg->nd_family; - if (family > NVDIMM_BUS_FAMILY_MAX || + if (call_pkg->nd_family > NVDIMM_BUS_FAMILY_MAX || !test_bit(family, &nd_desc->bus_family_mask)) return -EINVAL; family = array_index_nospec(family,
diff --git a/drivers/acpi/numa/hmat.c b/drivers/acpi/numa/hmat.c index bfbb08b..9d90522 100644 --- a/drivers/acpi/numa/hmat.c +++ b/drivers/acpi/numa/hmat.c
@@ -108,6 +108,45 @@ static struct memory_target *find_mem_target(unsigned int mem_pxm) return NULL; } +/** + * hmat_get_extended_linear_cache_size - Retrieve the extended linear cache size + * @backing_res: resource from the backing media + * @nid: node id for the memory region + * @cache_size: (Output) size of extended linear cache. + * + * Return: 0 on success. Errno on failure. + * + */ +int hmat_get_extended_linear_cache_size(struct resource *backing_res, int nid, + resource_size_t *cache_size) +{ + unsigned int pxm = node_to_pxm(nid); + struct memory_target *target; + struct target_cache *tcache; + struct resource *res; + + target = find_mem_target(pxm); + if (!target) + return -ENOENT; + + list_for_each_entry(tcache, &target->caches, node) { + if (tcache->cache_attrs.address_mode != + NODE_CACHE_ADDR_MODE_EXTENDED_LINEAR) + continue; + + res = &target->memregions; + if (!resource_contains(res, backing_res)) + continue; + + *cache_size = tcache->cache_attrs.size; + return 0; + } + + *cache_size = 0; + return 0; +} +EXPORT_SYMBOL_NS_GPL(hmat_get_extended_linear_cache_size, "CXL"); + static struct memory_target *acpi_find_genport_target(u32 uid) { struct memory_target *target; @@ -506,6 +545,11 @@ static __init int hmat_parse_cache(union acpi_subtable_headers *header, switch ((attrs & ACPI_HMAT_CACHE_ASSOCIATIVITY) >> 8) { case ACPI_HMAT_CA_DIRECT_MAPPED: tcache->cache_attrs.indexing = NODE_CACHE_DIRECT_MAP; + /* Extended Linear mode is only valid if cache is direct mapped */ + if (cache->address_mode == ACPI_HMAT_CACHE_MODE_EXTENDED_LINEAR) { + tcache->cache_attrs.address_mode = + NODE_CACHE_ADDR_MODE_EXTENDED_LINEAR; + } break; case ACPI_HMAT_CA_COMPLEX_CACHE_INDEXING: tcache->cache_attrs.indexing = NODE_CACHE_INDEXED;
diff --git a/drivers/acpi/numa/srat.c b/drivers/acpi/numa/srat.c index ce815d7..0a725e4 100644 --- a/drivers/acpi/numa/srat.c +++ b/drivers/acpi/numa/srat.c
@@ -18,6 +18,7 @@ #include <linux/nodemask.h> #include <linux/topology.h> #include <linux/numa_memblks.h> +#include <linux/string_choices.h> static nodemask_t nodes_found_map = NODE_MASK_NONE; @@ -188,8 +189,7 @@ acpi_table_print_srat_entry(struct acpi_subtable_header *header) pr_debug("SRAT Processor (id[0x%02x] eid[0x%02x]) in proximity domain %d %s\n", p->apic_id, p->local_sapic_eid, p->proximity_domain_lo, - (p->flags & ACPI_SRAT_CPU_ENABLED) ? - "enabled" : "disabled"); + str_enabled_disabled(p->flags & ACPI_SRAT_CPU_ENABLED)); } break; @@ -201,8 +201,7 @@ acpi_table_print_srat_entry(struct acpi_subtable_header *header) (unsigned long long)p->base_address, (unsigned long long)p->length, p->proximity_domain, - (p->flags & ACPI_SRAT_MEM_ENABLED) ? - "enabled" : "disabled", + str_enabled_disabled(p->flags & ACPI_SRAT_MEM_ENABLED), (p->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE) ? " hot-pluggable" : "", (p->flags & ACPI_SRAT_MEM_NON_VOLATILE) ? @@ -217,8 +216,7 @@ acpi_table_print_srat_entry(struct acpi_subtable_header *header) pr_debug("SRAT Processor (x2apicid[0x%08x]) in proximity domain %d %s\n", p->apic_id, p->proximity_domain, - (p->flags & ACPI_SRAT_CPU_ENABLED) ? - "enabled" : "disabled"); + str_enabled_disabled(p->flags & ACPI_SRAT_CPU_ENABLED)); } break; @@ -229,8 +227,7 @@ acpi_table_print_srat_entry(struct acpi_subtable_header *header) pr_debug("SRAT Processor (acpi id[0x%04x]) in proximity domain %d %s\n", p->acpi_processor_uid, p->proximity_domain, - (p->flags & ACPI_SRAT_GICC_ENABLED) ? - "enabled" : "disabled"); + str_enabled_disabled(p->flags & ACPI_SRAT_GICC_ENABLED)); } break; @@ -248,8 +245,7 @@ acpi_table_print_srat_entry(struct acpi_subtable_header *header) *(u16 *)(&p->device_handle[0]), *(u16 *)(&p->device_handle[2]), p->proximity_domain, - (p->flags & ACPI_SRAT_GENERIC_AFFINITY_ENABLED) ? - "enabled" : "disabled"); + str_enabled_disabled(p->flags & ACPI_SRAT_GENERIC_AFFINITY_ENABLED)); } else { /* * In this case we can rely on the device having a @@ -259,8 +255,7 @@ acpi_table_print_srat_entry(struct acpi_subtable_header *header) (char *)(&p->device_handle[0]), (char *)(&p->device_handle[8]), p->proximity_domain, - (p->flags & ACPI_SRAT_GENERIC_AFFINITY_ENABLED) ? - "enabled" : "disabled"); + str_enabled_disabled(p->flags & ACPI_SRAT_GENERIC_AFFINITY_ENABLED)); } } break; @@ -272,8 +267,7 @@ acpi_table_print_srat_entry(struct acpi_subtable_header *header) pr_debug("SRAT Processor (acpi id[0x%04x]) in proximity domain %d %s\n", p->acpi_processor_uid, p->proximity_domain, - (p->flags & ACPI_SRAT_RINTC_ENABLED) ? - "enabled" : "disabled"); + str_enabled_disabled(p->flags & ACPI_SRAT_RINTC_ENABLED)); } break;
diff --git a/drivers/acpi/platform_profile.c b/drivers/acpi/platform_profile.c index 671407f..ffbfd32 100644 --- a/drivers/acpi/platform_profile.c +++ b/drivers/acpi/platform_profile.c
@@ -245,7 +245,8 @@ static const struct class platform_profile_class = { /** * _aggregate_choices - Aggregate the available profile choices * @dev: The device - * @arg: struct aggregate_choices_data + * @arg: struct aggregate_choices_data, with it's aggregate member bitmap + * initially filled with ones * * Return: 0 on success, -errno on failure */ @@ -256,12 +257,10 @@ static int _aggregate_choices(struct device *dev, void *arg) struct platform_profile_handler *handler; lockdep_assert_held(&profile_lock); + handler = to_pprof_handler(dev); bitmap_or(tmp, handler->choices, handler->hidden_choices, PLATFORM_PROFILE_LAST); - if (test_bit(PLATFORM_PROFILE_LAST, data->aggregate)) - bitmap_copy(data->aggregate, tmp, PLATFORM_PROFILE_LAST); - else - bitmap_and(data->aggregate, tmp, data->aggregate, PLATFORM_PROFILE_LAST); + bitmap_and(data->aggregate, tmp, data->aggregate, PLATFORM_PROFILE_LAST); data->count++; return 0; @@ -305,7 +304,6 @@ static ssize_t platform_profile_choices_show(struct kobject *kobj, }; int err; - set_bit(PLATFORM_PROFILE_LAST, data.aggregate); scoped_cond_guard(mutex_intr, return -ERESTARTSYS, &profile_lock) { err = class_for_each_device(&platform_profile_class, NULL, &data, _aggregate_choices); @@ -422,7 +420,7 @@ static ssize_t platform_profile_store(struct kobject *kobj, i = sysfs_match_string(profile_names, buf); if (i < 0 || i == PLATFORM_PROFILE_CUSTOM) return -EINVAL; - set_bit(PLATFORM_PROFILE_LAST, data.aggregate); + scoped_cond_guard(mutex_intr, return -ERESTARTSYS, &profile_lock) { ret = class_for_each_device(&platform_profile_class, NULL, &data, _aggregate_choices); @@ -502,7 +500,6 @@ int platform_profile_cycle(void) enum platform_profile_option profile = PLATFORM_PROFILE_LAST; int err; - set_bit(PLATFORM_PROFILE_LAST, data.aggregate); scoped_cond_guard(mutex_intr, return -ERESTARTSYS, &profile_lock) { err = class_for_each_device(&platform_profile_class, NULL, &profile, _aggregate_profiles);
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 586cc7d..b181f7f 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c
@@ -268,6 +268,10 @@ static int acpi_processor_get_power_info_fadt(struct acpi_processor *pr) ACPI_CX_DESC_LEN, "ACPI P_LVL3 IOPORT 0x%x", pr->power.states[ACPI_STATE_C3].address); + if (!pr->power.states[ACPI_STATE_C2].address && + !pr->power.states[ACPI_STATE_C3].address) + return -ENODEV; + return 0; }
diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c index b4cd14e..14c7bac 100644 --- a/drivers/acpi/resource.c +++ b/drivers/acpi/resource.c
@@ -441,6 +441,13 @@ static const struct dmi_system_id irq1_level_low_skip_override[] = { }, }, { + /* Asus Vivobook X1404VAP */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_BOARD_NAME, "X1404VAP"), + }, + }, + { /* Asus Vivobook X1504VAP */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
diff --git a/drivers/acpi/x86/utils.c b/drivers/acpi/x86/utils.c index 068c161..4ee30c2 100644 --- a/drivers/acpi/x86/utils.c +++ b/drivers/acpi/x86/utils.c
@@ -374,7 +374,8 @@ static const struct dmi_system_id acpi_quirk_skip_dmi_ids[] = { DMI_MATCH(DMI_PRODUCT_VERSION, "Blade3-10A-001"), }, .driver_data = (void *)(ACPI_QUIRK_SKIP_I2C_CLIENTS | - ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY), + ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY | + ACPI_QUIRK_SKIP_GPIO_EVENT_HANDLERS), }, { /* Medion Lifetab S10346 */
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 16cd676..b990c1e 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c
@@ -700,7 +700,7 @@ void ata_scsi_port_error_handler(struct Scsi_Host *host, struct ata_port *ap) ata_eh_acquire(ap); repeat: /* kill fast drain timer */ - del_timer_sync(&ap->fastdrain_timer); + timer_delete_sync(&ap->fastdrain_timer); /* process port resume request */ ata_eh_handle_port_resume(ap);
diff --git a/drivers/atm/idt77105.c b/drivers/atm/idt77105.c index fcd70e0..e6a3002 100644 --- a/drivers/atm/idt77105.c +++ b/drivers/atm/idt77105.c
@@ -366,8 +366,8 @@ EXPORT_SYMBOL(idt77105_init); static void __exit idt77105_exit(void) { /* turn off timers */ - del_timer_sync(&stats_timer); - del_timer_sync(&restart_timer); + timer_delete_sync(&stats_timer); + timer_delete_sync(&restart_timer); } module_exit(idt77105_exit);
diff --git a/drivers/atm/iphase.c b/drivers/atm/iphase.c index d213adc..301e697 100644 --- a/drivers/atm/iphase.c +++ b/drivers/atm/iphase.c
@@ -3283,7 +3283,7 @@ static void __exit ia_module_exit(void) { pci_unregister_driver(&ia_driver); - del_timer_sync(&ia_timer); + timer_delete_sync(&ia_timer); } module_init(ia_module_init);
diff --git a/drivers/atm/lanai.c b/drivers/atm/lanai.c index 32d7aa1..00fe25b 100644 --- a/drivers/atm/lanai.c +++ b/drivers/atm/lanai.c
@@ -1792,7 +1792,7 @@ static inline void lanai_timed_poll_start(struct lanai_dev *lanai) static inline void lanai_timed_poll_stop(struct lanai_dev *lanai) { - del_timer_sync(&lanai->timer); + timer_delete_sync(&lanai->timer); } /* -------------------- INTERRUPT SERVICE: */
diff --git a/drivers/atm/nicstar.c b/drivers/atm/nicstar.c index 27153d6..45952cf 100644 --- a/drivers/atm/nicstar.c +++ b/drivers/atm/nicstar.c
@@ -300,7 +300,7 @@ static void __exit nicstar_cleanup(void) { XPRINTK("nicstar: nicstar_cleanup() called.\n"); - del_timer_sync(&ns_timer); + timer_delete_sync(&ns_timer); pci_unregister_driver(&nicstar_driver);
diff --git a/drivers/atm/suni.c b/drivers/atm/suni.c index 32802ea..7d0fa72 100644 --- a/drivers/atm/suni.c +++ b/drivers/atm/suni.c
@@ -347,7 +347,7 @@ static int suni_stop(struct atm_dev *dev) for (walk = &sunis; *walk != PRIV(dev); walk = &PRIV((*walk)->dev)->next); *walk = PRIV((*walk)->dev)->next; - if (!sunis) del_timer_sync(&poll_timer); + if (!sunis) timer_delete_sync(&poll_timer); spin_unlock_irqrestore(&sunis_lock,flags); kfree(PRIV(dev));
diff --git a/drivers/auxdisplay/line-display.c b/drivers/auxdisplay/line-display.c index fcec77f..b6808c4 100644 --- a/drivers/auxdisplay/line-display.c +++ b/drivers/auxdisplay/line-display.c
@@ -84,7 +84,7 @@ static int linedisp_display(struct linedisp *linedisp, const char *msg, char *new_msg; /* stop the scroll timer */ - del_timer_sync(&linedisp->timer); + timer_delete_sync(&linedisp->timer); if (count == -1) count = strlen(msg); @@ -183,7 +183,7 @@ static ssize_t scroll_step_ms_store(struct device *dev, linedisp->scroll_rate = msecs_to_jiffies(ms); if (linedisp->message && linedisp->message_len > linedisp->num_chars) { - del_timer_sync(&linedisp->timer); + timer_delete_sync(&linedisp->timer); if (linedisp->scroll_rate) linedisp_scroll(&linedisp->timer); } @@ -376,7 +376,7 @@ int linedisp_register(struct linedisp *linedisp, struct device *parent, out_del_dev: device_del(&linedisp->dev); out_del_timer: - del_timer_sync(&linedisp->timer); + timer_delete_sync(&linedisp->timer); out_put_device: put_device(&linedisp->dev); return err; @@ -391,7 +391,7 @@ EXPORT_SYMBOL_NS_GPL(linedisp_register, "LINEDISP"); void linedisp_unregister(struct linedisp *linedisp) { device_del(&linedisp->dev); - del_timer_sync(&linedisp->timer); + timer_delete_sync(&linedisp->timer); put_device(&linedisp->dev); } EXPORT_SYMBOL_NS_GPL(linedisp_unregister, "LINEDISP");
diff --git a/drivers/auxdisplay/panel.c b/drivers/auxdisplay/panel.c index 91ccb97..958c0e3 100644 --- a/drivers/auxdisplay/panel.c +++ b/drivers/auxdisplay/panel.c
@@ -1654,7 +1654,7 @@ static void panel_attach(struct parport *port) err_lcd_unreg: if (scan_timer.function) - del_timer_sync(&scan_timer); + timer_delete_sync(&scan_timer); if (lcd.enabled) charlcd_unregister(lcd.charlcd); err_unreg_device: @@ -1675,7 +1675,7 @@ static void panel_detach(struct parport *port) return; } if (scan_timer.function) - del_timer_sync(&scan_timer); + timer_delete_sync(&scan_timer); if (keypad.enabled) { misc_deregister(&keypad_dev);
diff --git a/drivers/base/devcoredump.c b/drivers/base/devcoredump.c index 64840e5..03a39c4 100644 --- a/drivers/base/devcoredump.c +++ b/drivers/base/devcoredump.c
@@ -41,7 +41,7 @@ struct devcd_entry { * devcd_data_write() * mod_delayed_work() * try_to_grab_pending() - * del_timer() + * timer_delete() * debug_assert_init() * INIT_DELAYED_WORK() * schedule_delayed_work()
diff --git a/drivers/base/node.c b/drivers/base/node.c index 0ea653f..cd13ef2 100644 --- a/drivers/base/node.c +++ b/drivers/base/node.c
@@ -244,12 +244,14 @@ CACHE_ATTR(size, "%llu") CACHE_ATTR(line_size, "%u") CACHE_ATTR(indexing, "%u") CACHE_ATTR(write_policy, "%u") +CACHE_ATTR(address_mode, "%#x") static struct attribute *cache_attrs[] = { &dev_attr_indexing.attr, &dev_attr_size.attr, &dev_attr_line_size.attr, &dev_attr_write_policy.attr, + &dev_attr_address_mode.attr, NULL, }; ATTRIBUTE_GROUPS(cache);
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index ac2a197..c8b0a9e 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c
@@ -559,7 +559,7 @@ static void dpm_watchdog_clear(struct dpm_watchdog *wd) { struct timer_list *timer = &wd->timer; - del_timer_sync(timer); + timer_delete_sync(timer); destroy_timer_on_stack(timer); } #else
diff --git a/drivers/base/power/wakeup.c b/drivers/base/power/wakeup.c index 752b417..63bf914 100644 --- a/drivers/base/power/wakeup.c +++ b/drivers/base/power/wakeup.c
@@ -197,7 +197,7 @@ void wakeup_source_remove(struct wakeup_source *ws) raw_spin_unlock_irqrestore(&events_lock, flags); synchronize_srcu(&wakeup_srcu); - del_timer_sync(&ws->timer); + timer_delete_sync(&ws->timer); /* * Clear timer.function to make wakeup_source_not_registered() treat * this wakeup source as not registered. @@ -613,7 +613,7 @@ void __pm_stay_awake(struct wakeup_source *ws) spin_lock_irqsave(&ws->lock, flags); wakeup_source_report_event(ws, false); - del_timer(&ws->timer); + timer_delete(&ws->timer); ws->timer_expires = 0; spin_unlock_irqrestore(&ws->lock, flags); @@ -693,7 +693,7 @@ static void wakeup_source_deactivate(struct wakeup_source *ws) ws->max_time = duration; ws->last_time = now; - del_timer(&ws->timer); + timer_delete(&ws->timer); ws->timer_expires = 0; if (ws->autosleep_enabled)
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig index a97f2c4..2551ebf 100644 --- a/drivers/block/Kconfig +++ b/drivers/block/Kconfig
@@ -367,7 +367,7 @@ tristate "Rados block device (RBD)" depends on INET && BLOCK select CEPH_LIB - select LIBCRC32C + select CRC32 select CRYPTO_AES select CRYPTO help
diff --git a/drivers/block/amiflop.c b/drivers/block/amiflop.c index 9edd446..6357d86 100644 --- a/drivers/block/amiflop.c +++ b/drivers/block/amiflop.c
@@ -457,7 +457,7 @@ static int fd_motor_on(int nr) { nr &= 3; - del_timer(motor_off_timer + nr); + timer_delete(motor_off_timer + nr); if (!unit[nr].motor) { unit[nr].motor = 1; @@ -1393,7 +1393,7 @@ static int non_int_flush_track (unsigned long nr) nr&=3; writefromint = 0; - del_timer(&post_write_timer); + timer_delete(&post_write_timer); get_fdc(nr); if (!fd_motor_on(nr)) { writepending = 0; @@ -1435,7 +1435,7 @@ static int get_track(int drive, int track) } if (unit[drive].dirty == 1) { - del_timer (flush_track_timer + drive); + timer_delete(flush_track_timer + drive); non_int_flush_track (drive); } errcnt = 0; @@ -1591,7 +1591,7 @@ static int fd_locked_ioctl(struct block_device *bdev, blk_mode_t mode, case FDDEFPRM: return -EINVAL; case FDFLUSH: /* unconditionally, even if not needed */ - del_timer (flush_track_timer + drive); + timer_delete(flush_track_timer + drive); non_int_flush_track(drive); break; #ifdef RAW_IOCTL @@ -1714,7 +1714,7 @@ static void floppy_release(struct gendisk *disk) mutex_lock(&amiflop_mutex); if (unit[drive].dirty == 1) { - del_timer (flush_track_timer + drive); + timer_delete(flush_track_timer + drive); non_int_flush_track (drive); }
diff --git a/drivers/block/aoe/aoedev.c b/drivers/block/aoe/aoedev.c index 4db7f6c..141b2a0 100644 --- a/drivers/block/aoe/aoedev.c +++ b/drivers/block/aoe/aoedev.c
@@ -274,7 +274,7 @@ freedev(struct aoedev *d) if (!freeing) return; - del_timer_sync(&d->timer); + timer_delete_sync(&d->timer); if (d->gd) { aoedisk_rm_debugfs(d); del_gendisk(d->gd);
diff --git a/drivers/block/aoe/aoemain.c b/drivers/block/aoe/aoemain.c index 6238c4c..cdf6e40 100644 --- a/drivers/block/aoe/aoemain.c +++ b/drivers/block/aoe/aoemain.c
@@ -28,7 +28,7 @@ static void discover_timer(struct timer_list *t) static void __exit aoe_exit(void) { - del_timer_sync(&timer); + timer_delete_sync(&timer); aoenet_exit(); unregister_blkdev(AOE_MAJOR, DEVICE_NAME);
diff --git a/drivers/block/ataflop.c b/drivers/block/ataflop.c index a81ade6..7fe1426 100644 --- a/drivers/block/ataflop.c +++ b/drivers/block/ataflop.c
@@ -494,7 +494,7 @@ static inline void start_timeout(void) static inline void stop_timeout(void) { - del_timer(&timeout_timer); + timer_delete(&timeout_timer); } /* Select the side to use. */ @@ -784,7 +784,7 @@ static int do_format(int drive, int type, struct atari_format_descr *desc) contents become invalid! */ BufferDrive = -1; /* stop deselect timer */ - del_timer( &motor_off_timer ); + timer_delete(&motor_off_timer); FILL( 60 * (nsect / 9), 0x4e ); for( sect = 0; sect < nsect; ++sect ) { @@ -1138,7 +1138,7 @@ static void fd_rwsec_done( int status ) DPRINT(("fd_rwsec_done()\n")); if (read_track) { - del_timer(&readtrack_timer); + timer_delete(&readtrack_timer); if (!MultReadInProgress) return; MultReadInProgress = 0; @@ -1356,7 +1356,7 @@ static void fd_times_out(struct timer_list *unused) /* If the timeout occurred while the readtrack_check timer was * active, we need to cancel it, else bad things will happen */ if (UseTrackbuffer) - del_timer( &readtrack_timer ); + timer_delete(&readtrack_timer); FDC_WRITE( FDCREG_CMD, FDCCMD_FORCI ); udelay( 25 ); @@ -1566,7 +1566,7 @@ static blk_status_t ataflop_queue_rq(struct blk_mq_hw_ctx *hctx, } /* stop deselect timer */ - del_timer( &motor_off_timer ); + timer_delete(&motor_off_timer); ReqCnt = 0; ReqCmd = rq_data_dir(fd_request); @@ -2055,7 +2055,7 @@ static void atari_floppy_cleanup(void) blk_mq_free_tag_set(&unit[i].tag_set); } - del_timer_sync(&fd_timer); + timer_delete_sync(&fd_timer); atari_stram_free(DMABuffer); }
diff --git a/drivers/block/drbd/Kconfig b/drivers/block/drbd/Kconfig index 6fb4e38..495a72d 100644 --- a/drivers/block/drbd/Kconfig +++ b/drivers/block/drbd/Kconfig
@@ -10,7 +10,7 @@ tristate "DRBD Distributed Replicated Block Device support" depends on PROC_FS && INET select LRU_CACHE - select LIBCRC32C + select CRC32 help NOTE: In order to authenticate connections you have to select
diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index 5bbd312..ced2cc5 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c
@@ -3034,7 +3034,7 @@ void drbd_md_sync(struct drbd_device *device) BUILD_BUG_ON(UI_SIZE != 4); BUILD_BUG_ON(sizeof(struct meta_data_on_disk) != 4096); - del_timer(&device->md_sync_timer); + timer_delete(&device->md_sync_timer); /* timer may be rearmed by drbd_md_mark_dirty() now. */ if (!test_and_clear_bit(MD_DIRTY, &device->flags)) return;
diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c index 720fc30..e09930c2 100644 --- a/drivers/block/drbd/drbd_nl.c +++ b/drivers/block/drbd/drbd_nl.c
@@ -1033,7 +1033,7 @@ drbd_determine_dev_size(struct drbd_device *device, enum dds_flags flags, struct /* We do some synchronous IO below, which may take some time. * Clear the timer, to avoid scary "timer expired!" messages, * "Superblock" is written out at least twice below, anyways. */ - del_timer(&device->md_sync_timer); + timer_delete(&device->md_sync_timer); /* We won't change the "al-extents" setting, we just may need * to move the on-disk location of the activity log ringbuffer.
diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index 0c9f541..e5a2e5f 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c
@@ -5187,7 +5187,7 @@ static int drbd_disconnected(struct drbd_peer_device *peer_device) atomic_set(&device->rs_pending_cnt, 0); wake_up(&device->misc_wait); - del_timer_sync(&device->resync_timer); + timer_delete_sync(&device->resync_timer); resync_timer_fn(&device->resync_timer); /* wait for all w_e_end_data_req, w_e_end_rsdata_req, w_send_barrier,
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index abf0486..e974320 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c
@@ -937,7 +937,7 @@ static void floppy_off(unsigned int drive) if (!(fdc_state[fdc].dor & (0x10 << UNIT(drive)))) return; - del_timer(motor_off_timer + drive); + timer_delete(motor_off_timer + drive); /* make spindle stop in a position which minimizes spinup time * next time */ @@ -1918,7 +1918,7 @@ static int start_motor(void (*function)(void)) mask &= ~(0x10 << UNIT(current_drive)); /* starts motor and selects floppy */ - del_timer(motor_off_timer + current_drive); + timer_delete(motor_off_timer + current_drive); set_dor(current_fdc, mask, data); /* wait_for_completion also schedules reset if needed. */ @@ -4762,7 +4762,7 @@ static int __init do_floppy_init(void) for (drive = 0; drive < N_DRIVE; drive++) { if (!disks[drive][0]) break; - del_timer_sync(&motor_off_timer[drive]); + timer_delete_sync(&motor_off_timer[drive]); put_disk(disks[drive][0]); blk_mq_free_tag_set(&tag_sets[drive]); } @@ -4983,7 +4983,7 @@ static void __exit floppy_module_exit(void) destroy_workqueue(floppy_wq); for (drive = 0; drive < N_DRIVE; drive++) { - del_timer_sync(&motor_off_timer[drive]); + timer_delete_sync(&motor_off_timer[drive]); if (floppy_available(drive)) { for (i = 0; i < ARRAY_SIZE(floppy_type); i++) {
diff --git a/drivers/block/sunvdc.c b/drivers/block/sunvdc.c index 2b33fb5..b5727de 100644 --- a/drivers/block/sunvdc.c +++ b/drivers/block/sunvdc.c
@@ -1070,7 +1070,7 @@ static void vdc_port_remove(struct vio_dev *vdev) flush_work(&port->ldc_reset_work); cancel_delayed_work_sync(&port->ldc_reset_timer_work); - del_timer_sync(&port->vio.timer); + timer_delete_sync(&port->vio.timer); del_gendisk(port->disk); put_disk(port->disk);
diff --git a/drivers/block/swim3.c b/drivers/block/swim3.c index 3aedcb5..ee6cade 100644 --- a/drivers/block/swim3.c +++ b/drivers/block/swim3.c
@@ -362,7 +362,7 @@ static void set_timeout(struct floppy_state *fs, int nticks, void (*proc)(struct timer_list *t)) { if (fs->timeout_pending) - del_timer(&fs->timeout); + timer_delete(&fs->timeout); fs->timeout.expires = jiffies + nticks; fs->timeout.function = proc; add_timer(&fs->timeout); @@ -677,7 +677,7 @@ static irqreturn_t swim3_interrupt(int irq, void *dev_id) out_8(&sw->control_bic, DO_ACTION | WRITE_SECTORS); out_8(&sw->select, RELAX); out_8(&sw->intr_enable, 0); - del_timer(&fs->timeout); + timer_delete(&fs->timeout); fs->timeout_pending = 0; if (sw->ctrack == 0xff) { swim3_err("%s", "Seen sector but cyl=ff?\n"); @@ -706,7 +706,7 @@ static irqreturn_t swim3_interrupt(int irq, void *dev_id) out_8(&sw->control_bic, DO_SEEK); out_8(&sw->select, RELAX); out_8(&sw->intr_enable, 0); - del_timer(&fs->timeout); + timer_delete(&fs->timeout); fs->timeout_pending = 0; if (fs->state == seeking) ++fs->retries; @@ -716,7 +716,7 @@ static irqreturn_t swim3_interrupt(int irq, void *dev_id) break; case settling: out_8(&sw->intr_enable, 0); - del_timer(&fs->timeout); + timer_delete(&fs->timeout); fs->timeout_pending = 0; act(fs); break; @@ -726,7 +726,7 @@ static irqreturn_t swim3_interrupt(int irq, void *dev_id) out_8(&sw->intr_enable, 0); out_8(&sw->control_bic, WRITE_SECTORS | DO_ACTION); out_8(&sw->select, RELAX); - del_timer(&fs->timeout); + timer_delete(&fs->timeout); fs->timeout_pending = 0; dr = fs->dma; cp = fs->dma_cmd;
diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c index c060da4..2fd05c1 100644 --- a/drivers/block/ublk_drv.c +++ b/drivers/block/ublk_drv.c
@@ -74,13 +74,30 @@ #define UBLK_PARAM_TYPE_ALL \ (UBLK_PARAM_TYPE_BASIC | UBLK_PARAM_TYPE_DISCARD | \ UBLK_PARAM_TYPE_DEVT | UBLK_PARAM_TYPE_ZONED | \ - UBLK_PARAM_TYPE_DMA_ALIGN) + UBLK_PARAM_TYPE_DMA_ALIGN | UBLK_PARAM_TYPE_SEGMENT) struct ublk_rq_data { struct kref ref; }; struct ublk_uring_cmd_pdu { + /* + * Store requests in same batch temporarily for queuing them to + * daemon context. + * + * It should have been stored to request payload, but we do want + * to avoid extra pre-allocation, and uring_cmd payload is always + * free for us + */ + union { + struct request *req; + struct request *req_list; + }; + + /* + * The following two are valid in this cmd whole lifetime, and + * setup in ublk uring_cmd handler + */ struct ublk_queue *ubq; u16 tag; }; @@ -141,10 +158,8 @@ struct ublk_queue { unsigned long flags; struct task_struct *ubq_daemon; - char *io_cmd_buf; + struct ublksrv_io_desc *io_cmd_buf; - unsigned long io_addr; /* mapped vm address */ - unsigned int max_io_sz; bool force_abort; bool timeout; bool canceling; @@ -582,6 +597,18 @@ static int ublk_validate_params(const struct ublk_device *ub) return -EINVAL; } + if (ub->params.types & UBLK_PARAM_TYPE_SEGMENT) { + const struct ublk_param_segment *p = &ub->params.seg; + + if (!is_power_of_2(p->seg_boundary_mask + 1)) + return -EINVAL; + + if (p->seg_boundary_mask + 1 < UBLK_MIN_SEGMENT_SIZE) + return -EINVAL; + if (p->max_segment_size < UBLK_MIN_SEGMENT_SIZE) + return -EINVAL; + } + return 0; } @@ -598,6 +625,11 @@ static inline bool ublk_support_user_copy(const struct ublk_queue *ubq) return ubq->flags & (UBLK_F_USER_COPY | UBLK_F_SUPPORT_ZERO_COPY); } +static inline bool ublk_need_map_io(const struct ublk_queue *ubq) +{ + return !ublk_support_user_copy(ubq); +} + static inline bool ublk_need_req_ref(const struct ublk_queue *ubq) { /* @@ -674,11 +706,11 @@ static inline bool ublk_rq_has_data(const struct request *rq) static inline struct ublksrv_io_desc *ublk_get_iod(struct ublk_queue *ubq, int tag) { - return (struct ublksrv_io_desc *) - &(ubq->io_cmd_buf[tag * sizeof(struct ublksrv_io_desc)]); + return &ubq->io_cmd_buf[tag]; } -static inline char *ublk_queue_cmd_buf(struct ublk_device *ub, int q_id) +static inline struct ublksrv_io_desc * +ublk_queue_cmd_buf(struct ublk_device *ub, int q_id) { return ublk_get_queue(ub, q_id)->io_cmd_buf; } @@ -925,7 +957,7 @@ static int ublk_map_io(const struct ublk_queue *ubq, const struct request *req, { const unsigned int rq_bytes = blk_rq_bytes(req); - if (ublk_support_user_copy(ubq)) + if (!ublk_need_map_io(ubq)) return rq_bytes; /* @@ -949,7 +981,7 @@ static int ublk_unmap_io(const struct ublk_queue *ubq, { const unsigned int rq_bytes = blk_rq_bytes(req); - if (ublk_support_user_copy(ubq)) + if (!ublk_need_map_io(ubq)) return rq_bytes; if (ublk_need_unmap_req(req)) { @@ -1037,7 +1069,7 @@ static blk_status_t ublk_setup_iod(struct ublk_queue *ubq, struct request *req) static inline struct ublk_uring_cmd_pdu *ublk_get_uring_cmd_pdu( struct io_uring_cmd *ioucmd) { - return (struct ublk_uring_cmd_pdu *)&ioucmd->pdu; + return io_uring_cmd_to_pdu(ioucmd, struct ublk_uring_cmd_pdu); } static inline bool ubq_daemon_is_dying(struct ublk_queue *ubq) @@ -1155,14 +1187,11 @@ static inline void __ublk_abort_rq(struct ublk_queue *ubq, blk_mq_end_request(rq, BLK_STS_IOERR); } -static void ublk_rq_task_work_cb(struct io_uring_cmd *cmd, - unsigned int issue_flags) +static void ublk_dispatch_req(struct ublk_queue *ubq, + struct request *req, + unsigned int issue_flags) { - struct ublk_uring_cmd_pdu *pdu = ublk_get_uring_cmd_pdu(cmd); - struct ublk_queue *ubq = pdu->ubq; - int tag = pdu->tag; - struct request *req = blk_mq_tag_to_rq( - ubq->dev->tag_set.tags[ubq->q_id], tag); + int tag = req->tag; struct ublk_io *io = &ubq->ios[tag]; unsigned int mapped_bytes; @@ -1237,11 +1266,49 @@ static void ublk_rq_task_work_cb(struct io_uring_cmd *cmd, ubq_complete_io_cmd(io, UBLK_IO_RES_OK, issue_flags); } +static void ublk_cmd_tw_cb(struct io_uring_cmd *cmd, + unsigned int issue_flags) +{ + struct ublk_uring_cmd_pdu *pdu = ublk_get_uring_cmd_pdu(cmd); + struct ublk_queue *ubq = pdu->ubq; + + ublk_dispatch_req(ubq, pdu->req, issue_flags); +} + static void ublk_queue_cmd(struct ublk_queue *ubq, struct request *rq) { - struct ublk_io *io = &ubq->ios[rq->tag]; + struct io_uring_cmd *cmd = ubq->ios[rq->tag].cmd; + struct ublk_uring_cmd_pdu *pdu = ublk_get_uring_cmd_pdu(cmd); - io_uring_cmd_complete_in_task(io->cmd, ublk_rq_task_work_cb); + pdu->req = rq; + io_uring_cmd_complete_in_task(cmd, ublk_cmd_tw_cb); +} + +static void ublk_cmd_list_tw_cb(struct io_uring_cmd *cmd, + unsigned int issue_flags) +{ + struct ublk_uring_cmd_pdu *pdu = ublk_get_uring_cmd_pdu(cmd); + struct request *rq = pdu->req_list; + struct ublk_queue *ubq = pdu->ubq; + struct request *next; + + do { + next = rq->rq_next; + rq->rq_next = NULL; + ublk_dispatch_req(ubq, rq, issue_flags); + rq = next; + } while (rq); +} + +static void ublk_queue_cmd_list(struct ublk_queue *ubq, struct rq_list *l) +{ + struct request *rq = rq_list_peek(l); + struct io_uring_cmd *cmd = ubq->ios[rq->tag].cmd; + struct ublk_uring_cmd_pdu *pdu = ublk_get_uring_cmd_pdu(cmd); + + pdu->req_list = rq; + rq_list_init(l); + io_uring_cmd_complete_in_task(cmd, ublk_cmd_list_tw_cb); } static enum blk_eh_timer_return ublk_timeout(struct request *rq) @@ -1282,21 +1349,12 @@ static enum blk_eh_timer_return ublk_timeout(struct request *rq) return BLK_EH_RESET_TIMER; } -static blk_status_t ublk_queue_rq(struct blk_mq_hw_ctx *hctx, - const struct blk_mq_queue_data *bd) +static blk_status_t ublk_prep_req(struct ublk_queue *ubq, struct request *rq) { - struct ublk_queue *ubq = hctx->driver_data; - struct request *rq = bd->rq; blk_status_t res; - if (unlikely(ubq->fail_io)) { + if (unlikely(ubq->fail_io)) return BLK_STS_TARGET; - } - - /* fill iod to slot in io cmd buffer */ - res = ublk_setup_iod(ubq, rq); - if (unlikely(res != BLK_STS_OK)) - return BLK_STS_IOERR; /* With recovery feature enabled, force_abort is set in * ublk_stop_dev() before calling del_gendisk(). We have to @@ -1310,17 +1368,68 @@ static blk_status_t ublk_queue_rq(struct blk_mq_hw_ctx *hctx, if (ublk_nosrv_should_queue_io(ubq) && unlikely(ubq->force_abort)) return BLK_STS_IOERR; + if (unlikely(ubq->canceling)) + return BLK_STS_IOERR; + + /* fill iod to slot in io cmd buffer */ + res = ublk_setup_iod(ubq, rq); + if (unlikely(res != BLK_STS_OK)) + return BLK_STS_IOERR; + + blk_mq_start_request(rq); + return BLK_STS_OK; +} + +static blk_status_t ublk_queue_rq(struct blk_mq_hw_ctx *hctx, + const struct blk_mq_queue_data *bd) +{ + struct ublk_queue *ubq = hctx->driver_data; + struct request *rq = bd->rq; + blk_status_t res; + + res = ublk_prep_req(ubq, rq); + if (res != BLK_STS_OK) + return res; + + /* + * ->canceling has to be handled after ->force_abort and ->fail_io + * is dealt with, otherwise this request may not be failed in case + * of recovery, and cause hang when deleting disk + */ if (unlikely(ubq->canceling)) { __ublk_abort_rq(ubq, rq); return BLK_STS_OK; } - blk_mq_start_request(bd->rq); ublk_queue_cmd(ubq, rq); - return BLK_STS_OK; } +static void ublk_queue_rqs(struct rq_list *rqlist) +{ + struct rq_list requeue_list = { }; + struct rq_list submit_list = { }; + struct ublk_queue *ubq = NULL; + struct request *req; + + while ((req = rq_list_pop(rqlist))) { + struct ublk_queue *this_q = req->mq_hctx->driver_data; + + if (ubq && ubq != this_q && !rq_list_empty(&submit_list)) + ublk_queue_cmd_list(ubq, &submit_list); + ubq = this_q; + + if (ublk_prep_req(ubq, req) == BLK_STS_OK) + rq_list_add_tail(&submit_list, req); + else + rq_list_add_tail(&requeue_list, req); + } + + if (ubq && !rq_list_empty(&submit_list)) + ublk_queue_cmd_list(ubq, &submit_list); + *rqlist = requeue_list; +} + static int ublk_init_hctx(struct blk_mq_hw_ctx *hctx, void *driver_data, unsigned int hctx_idx) { @@ -1333,6 +1442,7 @@ static int ublk_init_hctx(struct blk_mq_hw_ctx *hctx, void *driver_data, static const struct blk_mq_ops ublk_mq_ops = { .queue_rq = ublk_queue_rq, + .queue_rqs = ublk_queue_rqs, .init_hctx = ublk_init_hctx, .timeout = ublk_timeout, }; @@ -1446,18 +1556,28 @@ static void ublk_abort_queue(struct ublk_device *ub, struct ublk_queue *ubq) } } -static bool ublk_abort_requests(struct ublk_device *ub, struct ublk_queue *ubq) +/* Must be called when queue is frozen */ +static bool ublk_mark_queue_canceling(struct ublk_queue *ubq) { - struct gendisk *disk; + bool canceled; spin_lock(&ubq->cancel_lock); - if (ubq->canceling) { - spin_unlock(&ubq->cancel_lock); - return false; - } - ubq->canceling = true; + canceled = ubq->canceling; + if (!canceled) + ubq->canceling = true; spin_unlock(&ubq->cancel_lock); + return canceled; +} + +static bool ublk_abort_requests(struct ublk_device *ub, struct ublk_queue *ubq) +{ + bool was_canceled = ubq->canceling; + struct gendisk *disk; + + if (was_canceled) + return false; + spin_lock(&ub->lock); disk = ub->ub_disk; if (disk) @@ -1468,14 +1588,23 @@ static bool ublk_abort_requests(struct ublk_device *ub, struct ublk_queue *ubq) if (!disk) return false; - /* Now we are serialized with ublk_queue_rq() */ + /* + * Now we are serialized with ublk_queue_rq() + * + * Make sure that ubq->canceling is set when queue is frozen, + * because ublk_queue_rq() has to rely on this flag for avoiding to + * touch completed uring_cmd + */ blk_mq_quiesce_queue(disk->queue); - /* abort queue is for making forward progress */ - ublk_abort_queue(ub, ubq); + was_canceled = ublk_mark_queue_canceling(ubq); + if (!was_canceled) { + /* abort queue is for making forward progress */ + ublk_abort_queue(ub, ubq); + } blk_mq_unquiesce_queue(disk->queue); put_device(disk_to_dev(disk)); - return true; + return !was_canceled; } static void ublk_cancel_cmd(struct ublk_queue *ubq, struct ublk_io *io, @@ -1845,7 +1974,7 @@ static int __ublk_ch_uring_cmd(struct io_uring_cmd *cmd, if (io->flags & UBLK_IO_FLAG_OWNED_BY_SRV) goto out; - if (!ublk_support_user_copy(ubq)) { + if (ublk_need_map_io(ubq)) { /* * FETCH_RQ has to provide IO buffer if NEED GET * DATA is not enabled @@ -1867,7 +1996,7 @@ static int __ublk_ch_uring_cmd(struct io_uring_cmd *cmd, if (!(io->flags & UBLK_IO_FLAG_OWNED_BY_SRV)) goto out; - if (!ublk_support_user_copy(ubq)) { + if (ublk_need_map_io(ubq)) { /* * COMMIT_AND_FETCH_REQ has to provide IO buffer if * NEED GET DATA is not enabled or it is Read IO. @@ -2343,6 +2472,12 @@ static int ublk_ctrl_start_dev(struct ublk_device *ub, struct io_uring_cmd *cmd) if (ub->params.types & UBLK_PARAM_TYPE_DMA_ALIGN) lim.dma_alignment = ub->params.dma.alignment; + if (ub->params.types & UBLK_PARAM_TYPE_SEGMENT) { + lim.seg_boundary_mask = ub->params.seg.seg_boundary_mask; + lim.max_segment_size = ub->params.seg.max_segment_size; + lim.max_segments = ub->params.seg.max_segments; + } + if (wait_for_completion_interruptible(&ub->completion) != 0) return -EINTR;
diff --git a/drivers/bluetooth/bluecard_cs.c b/drivers/bluetooth/bluecard_cs.c index 36eabf6..1c7f89e 100644 --- a/drivers/bluetooth/bluecard_cs.c +++ b/drivers/bluetooth/bluecard_cs.c
@@ -638,7 +638,7 @@ static int bluecard_hci_close(struct hci_dev *hdev) bluecard_hci_flush(hdev); /* Stop LED timer */ - del_timer_sync(&(info->timer)); + timer_delete_sync(&(info->timer)); /* Disable power LED */ outb(0x00, iobase + 0x30); @@ -885,7 +885,7 @@ static void bluecard_release(struct pcmcia_device *link) bluecard_close(info); - del_timer_sync(&(info->timer)); + timer_delete_sync(&(info->timer)); pcmcia_disable_device(link); }
diff --git a/drivers/bluetooth/hci_bcsp.c b/drivers/bluetooth/hci_bcsp.c index 7687811..610d0e3 100644 --- a/drivers/bluetooth/hci_bcsp.c +++ b/drivers/bluetooth/hci_bcsp.c
@@ -382,7 +382,7 @@ static void bcsp_pkt_cull(struct bcsp_struct *bcsp) } if (skb_queue_empty(&bcsp->unack)) - del_timer(&bcsp->tbcsp); + timer_delete(&bcsp->tbcsp); spin_unlock_irqrestore(&bcsp->unack.lock, flags);
diff --git a/drivers/bluetooth/hci_h5.c b/drivers/bluetooth/hci_h5.c index c043688..edafa22 100644 --- a/drivers/bluetooth/hci_h5.c +++ b/drivers/bluetooth/hci_h5.c
@@ -197,7 +197,7 @@ static void h5_peer_reset(struct hci_uart *hu) h5->state = H5_UNINITIALIZED; - del_timer(&h5->timer); + timer_delete(&h5->timer); skb_queue_purge(&h5->rel); skb_queue_purge(&h5->unrel); @@ -254,7 +254,7 @@ static int h5_close(struct hci_uart *hu) { struct h5 *h5 = hu->priv; - del_timer_sync(&h5->timer); + timer_delete_sync(&h5->timer); skb_queue_purge(&h5->unack); skb_queue_purge(&h5->rel); @@ -318,7 +318,7 @@ static void h5_pkt_cull(struct h5 *h5) } if (skb_queue_empty(&h5->unack)) - del_timer(&h5->timer); + timer_delete(&h5->timer); unlock: spin_unlock_irqrestore(&h5->unack.lock, flags);
diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index f255850..e00590b 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c
@@ -867,7 +867,7 @@ static void device_woke_up(struct hci_uart *hu) skb_queue_tail(&qca->txq, skb); /* Switch timers and change state to HCI_IBS_TX_AWAKE */ - del_timer(&qca->wake_retrans_timer); + timer_delete(&qca->wake_retrans_timer); idle_delay = msecs_to_jiffies(qca->tx_idle_delay); mod_timer(&qca->tx_idle_timer, jiffies + idle_delay); qca->tx_ibs_state = HCI_IBS_TX_AWAKE; @@ -2239,8 +2239,8 @@ static int qca_power_off(struct hci_dev *hdev) hu->hdev->hw_error = NULL; hu->hdev->reset = NULL; - del_timer_sync(&qca->wake_retrans_timer); - del_timer_sync(&qca->tx_idle_timer); + timer_delete_sync(&qca->wake_retrans_timer); + timer_delete_sync(&qca->tx_idle_timer); /* Stop sending shutdown command if soc crashes. */ if (soc_type != QCA_ROME @@ -2629,10 +2629,10 @@ static int __maybe_unused qca_suspend(struct device *dev) switch (qca->tx_ibs_state) { case HCI_IBS_TX_WAKING: - del_timer(&qca->wake_retrans_timer); + timer_delete(&qca->wake_retrans_timer); fallthrough; case HCI_IBS_TX_AWAKE: - del_timer(&qca->tx_idle_timer); + timer_delete(&qca->tx_idle_timer); serdev_device_write_flush(hu->serdev); cmd = HCI_IBS_SLEEP_IND;
diff --git a/drivers/bus/fsl-mc/dpmcp.c b/drivers/bus/fsl-mc/dpmcp.c index 5fbd0dbd..7816c0a 100644 --- a/drivers/bus/fsl-mc/dpmcp.c +++ b/drivers/bus/fsl-mc/dpmcp.c
@@ -75,25 +75,3 @@ int dpmcp_close(struct fsl_mc_io *mc_io, /* send command to mc*/ return mc_send_command(mc_io, &cmd); } - -/** - * dpmcp_reset() - Reset the DPMCP, returns the object to initial state. - * @mc_io: Pointer to MC portal's I/O object - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' - * @token: Token of DPMCP object - * - * Return: '0' on Success; Error code otherwise. - */ -int dpmcp_reset(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token) -{ - struct fsl_mc_command cmd = { 0 }; - - /* prepare command */ - cmd.header = mc_encode_cmd_header(DPMCP_CMDID_RESET, - cmd_flags, token); - - /* send command to mc*/ - return mc_send_command(mc_io, &cmd); -}
diff --git a/drivers/bus/fsl-mc/fsl-mc-allocator.c b/drivers/bus/fsl-mc/fsl-mc-allocator.c index b5e8c02..6c3beb8 100644 --- a/drivers/bus/fsl-mc/fsl-mc-allocator.c +++ b/drivers/bus/fsl-mc/fsl-mc-allocator.c
@@ -656,8 +656,3 @@ int __init fsl_mc_allocator_driver_init(void) { return fsl_mc_driver_register(&fsl_mc_allocator_driver); } - -void fsl_mc_allocator_driver_exit(void) -{ - fsl_mc_driver_unregister(&fsl_mc_allocator_driver); -}
diff --git a/drivers/bus/fsl-mc/fsl-mc-private.h b/drivers/bus/fsl-mc/fsl-mc-private.h index b3520ea..e1b7ec3e 100644 --- a/drivers/bus/fsl-mc/fsl-mc-private.h +++ b/drivers/bus/fsl-mc/fsl-mc-private.h
@@ -66,10 +66,6 @@ int dpmcp_close(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token); -int dpmcp_reset(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token); - /* * Data Path Resource Container (DPRC) API */ @@ -631,8 +627,6 @@ int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev, int __init fsl_mc_allocator_driver_init(void); -void fsl_mc_allocator_driver_exit(void); - void fsl_mc_init_all_resource_pools(struct fsl_mc_device *mc_bus_dev); void fsl_mc_cleanup_all_resource_pools(struct fsl_mc_device *mc_bus_dev);
diff --git a/drivers/bus/fsl-mc/mc-io.c b/drivers/bus/fsl-mc/mc-io.c index 95b10a6..a0ad786 100644 --- a/drivers/bus/fsl-mc/mc-io.c +++ b/drivers/bus/fsl-mc/mc-io.c
@@ -263,23 +263,3 @@ void fsl_mc_portal_free(struct fsl_mc_io *mc_io) dpmcp_dev->consumer_link = NULL; } EXPORT_SYMBOL_GPL(fsl_mc_portal_free); - -/** - * fsl_mc_portal_reset - Resets the dpmcp object for a given fsl_mc_io object - * - * @mc_io: Pointer to the fsl_mc_io object that wraps the MC portal to free - */ -int fsl_mc_portal_reset(struct fsl_mc_io *mc_io) -{ - int error; - struct fsl_mc_device *dpmcp_dev = mc_io->dpmcp_dev; - - error = dpmcp_reset(mc_io, 0, dpmcp_dev->mc_handle); - if (error < 0) { - dev_err(&dpmcp_dev->dev, "dpmcp_reset() failed: %d\n", error); - return error; - } - - return 0; -} -EXPORT_SYMBOL_GPL(fsl_mc_portal_reset);
diff --git a/drivers/bus/mhi/host/pci_generic.c b/drivers/bus/mhi/host/pci_generic.c index 474f135..03aa887 100644 --- a/drivers/bus/mhi/host/pci_generic.c +++ b/drivers/bus/mhi/host/pci_generic.c
@@ -1096,7 +1096,7 @@ static void mhi_pci_recovery_work(struct work_struct *work) dev_warn(&pdev->dev, "device recovery started\n"); - del_timer(&mhi_pdev->health_check_timer); + timer_delete(&mhi_pdev->health_check_timer); pm_runtime_forbid(&pdev->dev); /* Clean up MHI state */ @@ -1293,7 +1293,7 @@ static void mhi_pci_remove(struct pci_dev *pdev) struct mhi_pci_device *mhi_pdev = pci_get_drvdata(pdev); struct mhi_controller *mhi_cntrl = &mhi_pdev->mhi_cntrl; - del_timer_sync(&mhi_pdev->health_check_timer); + timer_delete_sync(&mhi_pdev->health_check_timer); cancel_work_sync(&mhi_pdev->recovery_work); if (test_and_clear_bit(MHI_PCI_DEV_STARTED, &mhi_pdev->status)) { @@ -1321,7 +1321,7 @@ static void mhi_pci_reset_prepare(struct pci_dev *pdev) dev_info(&pdev->dev, "reset\n"); - del_timer(&mhi_pdev->health_check_timer); + timer_delete(&mhi_pdev->health_check_timer); /* Clean up MHI state */ if (test_and_clear_bit(MHI_PCI_DEV_STARTED, &mhi_pdev->status)) { @@ -1431,7 +1431,7 @@ static int __maybe_unused mhi_pci_runtime_suspend(struct device *dev) if (test_and_set_bit(MHI_PCI_DEV_SUSPENDED, &mhi_pdev->status)) return 0; - del_timer(&mhi_pdev->health_check_timer); + timer_delete(&mhi_pdev->health_check_timer); cancel_work_sync(&mhi_pdev->recovery_work); if (!test_bit(MHI_PCI_DEV_STARTED, &mhi_pdev->status) ||
diff --git a/drivers/char/dtlk.c b/drivers/char/dtlk.c index 27f5f9d..1661807 100644 --- a/drivers/char/dtlk.c +++ b/drivers/char/dtlk.c
@@ -243,11 +243,11 @@ static __poll_t dtlk_poll(struct file *file, poll_table * wait) poll_wait(file, &dtlk_process_list, wait); if (dtlk_has_indexing && dtlk_readable()) { - del_timer(&dtlk_timer); + timer_delete(&dtlk_timer); mask = EPOLLIN | EPOLLRDNORM; } if (dtlk_writeable()) { - del_timer(&dtlk_timer); + timer_delete(&dtlk_timer); mask |= EPOLLOUT | EPOLLWRNORM; } /* there are no exception conditions */ @@ -322,7 +322,7 @@ static int dtlk_release(struct inode *inode, struct file *file) } TRACE_RET; - del_timer_sync(&dtlk_timer); + timer_delete_sync(&dtlk_timer); return 0; }
diff --git a/drivers/char/hangcheck-timer.c b/drivers/char/hangcheck-timer.c index 4181bcc..497fc16 100644 --- a/drivers/char/hangcheck-timer.c +++ b/drivers/char/hangcheck-timer.c
@@ -167,7 +167,7 @@ static int __init hangcheck_init(void) static void __exit hangcheck_exit(void) { - del_timer_sync(&hangcheck_ticktock); + timer_delete_sync(&hangcheck_ticktock); printk("Hangcheck: Stopped hangcheck timer.\n"); }
diff --git a/drivers/char/hw_random/xgene-rng.c b/drivers/char/hw_random/xgene-rng.c index 39acaa5..a1a7510 100644 --- a/drivers/char/hw_random/xgene-rng.c +++ b/drivers/char/hw_random/xgene-rng.c
@@ -93,7 +93,7 @@ static void xgene_rng_expired_timer(struct timer_list *t) /* Clear failure counter as timer expired */ disable_irq(ctx->irq); ctx->failure_cnt = 0; - del_timer(&ctx->failure_timer); + timer_delete(&ctx->failure_timer); enable_irq(ctx->irq); }
diff --git a/drivers/char/ipmi/bt-bmc.c b/drivers/char/ipmi/bt-bmc.c index 009e3203..77146b5c 100644 --- a/drivers/char/ipmi/bt-bmc.c +++ b/drivers/char/ipmi/bt-bmc.c
@@ -465,7 +465,7 @@ static void bt_bmc_remove(struct platform_device *pdev) misc_deregister(&bt_bmc->miscdev); if (bt_bmc->irq < 0) - del_timer_sync(&bt_bmc->poll_timer); + timer_delete_sync(&bt_bmc->poll_timer); } static const struct of_device_id bt_bmc_match[] = {
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index 1e53137..3ba9d7e 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c
@@ -5538,7 +5538,7 @@ static void __exit cleanup_ipmi(void) * here. */ atomic_set(&stop_operation, 1); - del_timer_sync(&ipmi_timer); + timer_delete_sync(&ipmi_timer); initialized = false;
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index eea23a3..12b0b77 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -859,7 +859,7 @@ static enum si_sm_result smi_event_handler(struct smi_info *smi_info, if (si_sm_result == SI_SM_IDLE && smi_info->timer_running) { /* Ok it if fails, the timer will just go off. */ - if (del_timer(&smi_info->si_timer)) + if (timer_delete(&smi_info->si_timer)) smi_info->timer_running = false; } @@ -1839,7 +1839,7 @@ static inline void stop_timer_and_thread(struct smi_info *smi_info) } smi_info->timer_can_start = false; - del_timer_sync(&smi_info->si_timer); + timer_delete_sync(&smi_info->si_timer); } static struct smi_info *find_dup_si(struct smi_info *info)
diff --git a/drivers/char/ipmi/ipmi_ssif.c b/drivers/char/ipmi/ipmi_ssif.c index 506d998..0b45b07d 100644 --- a/drivers/char/ipmi/ipmi_ssif.c +++ b/drivers/char/ipmi/ipmi_ssif.c
@@ -599,7 +599,7 @@ static void ssif_alert(struct i2c_client *client, enum i2c_alert_protocol type, flags = ipmi_ssif_lock_cond(ssif_info, &oflags); if (ssif_info->waiting_alert) { ssif_info->waiting_alert = false; - del_timer(&ssif_info->retry_timer); + timer_delete(&ssif_info->retry_timer); do_get = true; } else if (ssif_info->curr_msg) { ssif_info->got_alert = true; @@ -1268,8 +1268,8 @@ static void shutdown_ssif(void *send_info) schedule_timeout(1); ssif_info->stopping = true; - del_timer_sync(&ssif_info->watch_timer); - del_timer_sync(&ssif_info->retry_timer); + timer_delete_sync(&ssif_info->watch_timer); + timer_delete_sync(&ssif_info->retry_timer); if (ssif_info->thread) { complete(&ssif_info->wake_thread); kthread_stop(ssif_info->thread);
diff --git a/drivers/char/ipmi/kcs_bmc_aspeed.c b/drivers/char/ipmi/kcs_bmc_aspeed.c index c03bc1e..a13a347 100644 --- a/drivers/char/ipmi/kcs_bmc_aspeed.c +++ b/drivers/char/ipmi/kcs_bmc_aspeed.c
@@ -428,7 +428,7 @@ static void aspeed_kcs_irq_mask_update(struct kcs_bmc_device *kcs_bmc, u8 mask, if (rc == -ETIMEDOUT) mod_timer(&priv->obe.timer, jiffies + OBE_POLL_PERIOD); } else { - del_timer(&priv->obe.timer); + timer_delete(&priv->obe.timer); } } @@ -655,7 +655,7 @@ static void aspeed_kcs_remove(struct platform_device *pdev) spin_lock_irq(&priv->obe.lock); priv->obe.remove = true; spin_unlock_irq(&priv->obe.lock); - del_timer_sync(&priv->obe.timer); + timer_delete_sync(&priv->obe.timer); } static const struct of_device_id ast_kcs_bmc_match[] = {
diff --git a/drivers/char/ipmi/ssif_bmc.c b/drivers/char/ipmi/ssif_bmc.c index 310f17d..e4bd745 100644 --- a/drivers/char/ipmi/ssif_bmc.c +++ b/drivers/char/ipmi/ssif_bmc.c
@@ -209,7 +209,7 @@ static ssize_t ssif_bmc_write(struct file *file, const char __user *buf, size_t if (ret) goto exit; - del_timer(&ssif_bmc->response_timer); + timer_delete(&ssif_bmc->response_timer); ssif_bmc->response_timer_inited = false; memcpy(&ssif_bmc->response, &msg, count);
diff --git a/drivers/char/random.c b/drivers/char/random.c index 92cbd24..38f2fab 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c
@@ -1352,7 +1352,7 @@ static void __cold try_to_generate_entropy(void) } mix_pool_bytes(&stack->entropy, sizeof(stack->entropy)); - del_timer_sync(&stack->timer); + timer_delete_sync(&stack->timer); destroy_timer_on_stack(&stack->timer); }
diff --git a/drivers/char/tlclk.c b/drivers/char/tlclk.c index 6c1d94e..b381ea7 100644 --- a/drivers/char/tlclk.c +++ b/drivers/char/tlclk.c
@@ -838,7 +838,7 @@ static void __exit tlclk_cleanup(void) unregister_chrdev(tlclk_major, "telco_clock"); release_region(TLCLK_BASE, 8); - del_timer_sync(&switchover_timer); + timer_delete_sync(&switchover_timer); kfree(alarm_events); } @@ -856,7 +856,7 @@ static void switchover_timeout(struct timer_list *unused) } /* Alarm processing is done, wake up read task */ - del_timer(&switchover_timer); + timer_delete(&switchover_timer); got_event = 1; wake_up(&wq); }
diff --git a/drivers/char/tpm/tpm-dev-common.c b/drivers/char/tpm/tpm-dev-common.c index 48ff874..11deaf5 100644 --- a/drivers/char/tpm/tpm-dev-common.c +++ b/drivers/char/tpm/tpm-dev-common.c
@@ -160,7 +160,7 @@ ssize_t tpm_common_read(struct file *file, char __user *buf, out: if (!priv->response_length) { *off = 0; - del_timer_sync(&priv->user_read_timer); + timer_delete_sync(&priv->user_read_timer); flush_work(&priv->timeout_work); } mutex_unlock(&priv->buffer_mutex); @@ -267,7 +267,7 @@ __poll_t tpm_common_poll(struct file *file, poll_table *wait) void tpm_common_release(struct file *file, struct file_priv *priv) { flush_work(&priv->async_work); - del_timer_sync(&priv->user_read_timer); + timer_delete_sync(&priv->user_read_timer); flush_work(&priv->timeout_work); file->private_data = NULL; priv->response_length = 0;
diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c index 2f83fb9..e0bede6 100644 --- a/drivers/clk/clkdev.c +++ b/drivers/clk/clkdev.c
@@ -153,7 +153,7 @@ struct clk_lookup_alloc { char con_id[MAX_CON_ID]; }; -static struct clk_lookup * __ref +static __printf(3, 0) struct clk_lookup * __ref vclkdev_alloc(struct clk_hw *hw, const char *con_id, const char *dev_fmt, va_list ap) { @@ -215,7 +215,7 @@ vclkdev_alloc(struct clk_hw *hw, const char *con_id, const char *dev_fmt, return &cla->cl; } -static struct clk_lookup * +static __printf(3, 0) struct clk_lookup * vclkdev_create(struct clk_hw *hw, const char *con_id, const char *dev_fmt, va_list ap) { @@ -303,9 +303,8 @@ void clkdev_drop(struct clk_lookup *cl) } EXPORT_SYMBOL(clkdev_drop); -static struct clk_lookup *__clk_register_clkdev(struct clk_hw *hw, - const char *con_id, - const char *dev_id, ...) +static __printf(3, 4) struct clk_lookup * +__clk_register_clkdev(struct clk_hw *hw, const char *con_id, const char *dev_id, ...) { struct clk_lookup *cl; va_list ap;
diff --git a/drivers/clocksource/timer-riscv.c b/drivers/clocksource/timer-riscv.c index 48ce50c..4d7cf33 100644 --- a/drivers/clocksource/timer-riscv.c +++ b/drivers/clocksource/timer-riscv.c
@@ -126,7 +126,13 @@ static int riscv_timer_starting_cpu(unsigned int cpu) static int riscv_timer_dying_cpu(unsigned int cpu) { + /* + * Stop the timer when the cpu is going to be offline otherwise + * the timer interrupt may be pending while performing power-down. + */ + riscv_clock_event_stop(); disable_percpu_irq(riscv_clock_event_irq); + return 0; }
diff --git a/drivers/comedi/drivers/comedi_test.c b/drivers/comedi/drivers/comedi_test.c index 05ae912..da17d89 100644 --- a/drivers/comedi/drivers/comedi_test.c +++ b/drivers/comedi/drivers/comedi_test.c
@@ -418,9 +418,9 @@ static int waveform_ai_cancel(struct comedi_device *dev, spin_unlock_bh(&dev->spinlock); if (in_softirq()) { /* Assume we were called from the timer routine itself. */ - del_timer(&devpriv->ai_timer); + timer_delete(&devpriv->ai_timer); } else { - del_timer_sync(&devpriv->ai_timer); + timer_delete_sync(&devpriv->ai_timer); } return 0; } @@ -628,9 +628,9 @@ static int waveform_ao_cancel(struct comedi_device *dev, spin_unlock_bh(&dev->spinlock); if (in_softirq()) { /* Assume we were called from the timer routine itself. */ - del_timer(&devpriv->ao_timer); + timer_delete(&devpriv->ao_timer); } else { - del_timer_sync(&devpriv->ao_timer); + timer_delete_sync(&devpriv->ao_timer); } return 0; } @@ -791,8 +791,8 @@ static void waveform_detach(struct comedi_device *dev) struct waveform_private *devpriv = dev->private; if (devpriv) { - del_timer_sync(&devpriv->ai_timer); - del_timer_sync(&devpriv->ao_timer); + timer_delete_sync(&devpriv->ai_timer); + timer_delete_sync(&devpriv->ao_timer); } }
diff --git a/drivers/comedi/drivers/das16.c b/drivers/comedi/drivers/das16.c index 4ed56a0..f5ca6c0 100644 --- a/drivers/comedi/drivers/das16.c +++ b/drivers/comedi/drivers/das16.c
@@ -775,7 +775,7 @@ static int das16_cancel(struct comedi_device *dev, struct comedi_subdevice *s) /* disable SW timer */ if (devpriv->timer_running) { devpriv->timer_running = 0; - del_timer(&devpriv->timer); + timer_delete(&devpriv->timer); } if (devpriv->can_burst) @@ -940,7 +940,7 @@ static void das16_free_dma(struct comedi_device *dev) struct das16_private_struct *devpriv = dev->private; if (devpriv) { - del_timer_sync(&devpriv->timer); + timer_delete_sync(&devpriv->timer); comedi_isadma_free(devpriv->dma); } }
diff --git a/drivers/comedi/drivers/jr3_pci.c b/drivers/comedi/drivers/jr3_pci.c index 951c23f..cdc842b 100644 --- a/drivers/comedi/drivers/jr3_pci.c +++ b/drivers/comedi/drivers/jr3_pci.c
@@ -758,7 +758,7 @@ static void jr3_pci_detach(struct comedi_device *dev) struct jr3_pci_dev_private *devpriv = dev->private; if (devpriv) - del_timer_sync(&devpriv->timer); + timer_delete_sync(&devpriv->timer); comedi_pci_detach(dev); }
diff --git a/drivers/counter/microchip-tcb-capture.c b/drivers/counter/microchip-tcb-capture.c index 00a463b..1de3c50 100644 --- a/drivers/counter/microchip-tcb-capture.c +++ b/drivers/counter/microchip-tcb-capture.c
@@ -519,6 +519,25 @@ static int mchp_tc_probe(struct platform_device *pdev) channel); } + /* Disable Quadrature Decoder and position measure */ + ret = regmap_update_bits(regmap, ATMEL_TC_BMR, ATMEL_TC_QDEN | ATMEL_TC_POSEN, 0); + if (ret) + return ret; + + /* Setup the period capture mode */ + ret = regmap_update_bits(regmap, ATMEL_TC_REG(priv->channel[0], CMR), + ATMEL_TC_WAVE | ATMEL_TC_ABETRG | ATMEL_TC_CMR_MASK | + ATMEL_TC_TCCLKS, + ATMEL_TC_CMR_MASK); + if (ret) + return ret; + + /* Enable clock and trigger counter */ + ret = regmap_write(regmap, ATMEL_TC_REG(priv->channel[0], CCR), + ATMEL_TC_CLKEN | ATMEL_TC_SWTRG); + if (ret) + return ret; + priv->tc_cfg = tcb_config; priv->regmap = regmap; counter->name = dev_name(&pdev->dev);
diff --git a/drivers/counter/stm32-lptimer-cnt.c b/drivers/counter/stm32-lptimer-cnt.c index cf73f65..b249c86 100644 --- a/drivers/counter/stm32-lptimer-cnt.c +++ b/drivers/counter/stm32-lptimer-cnt.c
@@ -58,37 +58,43 @@ static int stm32_lptim_set_enable_state(struct stm32_lptim_cnt *priv, return 0; } + ret = clk_enable(priv->clk); + if (ret) + goto disable_cnt; + /* LP timer must be enabled before writing CMP & ARR */ ret = regmap_write(priv->regmap, STM32_LPTIM_ARR, priv->ceiling); if (ret) - return ret; + goto disable_clk; ret = regmap_write(priv->regmap, STM32_LPTIM_CMP, 0); if (ret) - return ret; + goto disable_clk; /* ensure CMP & ARR registers are properly written */ ret = regmap_read_poll_timeout(priv->regmap, STM32_LPTIM_ISR, val, (val & STM32_LPTIM_CMPOK_ARROK) == STM32_LPTIM_CMPOK_ARROK, 100, 1000); if (ret) - return ret; + goto disable_clk; ret = regmap_write(priv->regmap, STM32_LPTIM_ICR, STM32_LPTIM_CMPOKCF_ARROKCF); if (ret) - return ret; + goto disable_clk; - ret = clk_enable(priv->clk); - if (ret) { - regmap_write(priv->regmap, STM32_LPTIM_CR, 0); - return ret; - } priv->enabled = true; /* Start LP timer in continuous mode */ return regmap_update_bits(priv->regmap, STM32_LPTIM_CR, STM32_LPTIM_CNTSTRT, STM32_LPTIM_CNTSTRT); + +disable_clk: + clk_disable(priv->clk); +disable_cnt: + regmap_write(priv->regmap, STM32_LPTIM_CR, 0); + + return ret; } static int stm32_lptim_setup(struct stm32_lptim_cnt *priv, int enable)
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 0cf5a32..3841c9d 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c
@@ -2809,6 +2809,12 @@ EXPORT_SYMBOL(cpufreq_update_policy); */ void cpufreq_update_limits(unsigned int cpu) { + struct cpufreq_policy *policy __free(put_cpufreq_policy); + + policy = cpufreq_cpu_get(cpu); + if (!policy) + return; + if (cpufreq_driver->update_limits) cpufreq_driver->update_limits(cpu); else
diff --git a/drivers/cpufreq/powernv-cpufreq.c b/drivers/cpufreq/powernv-cpufreq.c index 6094c53..afe5abf 100644 --- a/drivers/cpufreq/powernv-cpufreq.c +++ b/drivers/cpufreq/powernv-cpufreq.c
@@ -802,7 +802,7 @@ static int powernv_cpufreq_target_index(struct cpufreq_policy *policy, if (gpstate_idx != new_index) queue_gpstate_timer(gpstates); else - del_timer_sync(&gpstates->timer); + timer_delete_sync(&gpstates->timer); gpstates_done: freq_data.gpstate_id = idx_to_pstate(gpstate_idx); @@ -880,7 +880,7 @@ static void powernv_cpufreq_cpu_exit(struct cpufreq_policy *policy) freq_data.gpstate_id = idx_to_pstate(powernv_pstate_info.min); smp_call_function_single(policy->cpu, set_pstate, &freq_data, 1); if (gpstates) - del_timer_sync(&gpstates->timer); + timer_delete_sync(&gpstates->timer); kfree(policy->driver_data); }
diff --git a/drivers/crypto/axis/artpec6_crypto.c b/drivers/crypto/axis/artpec6_crypto.c index 500b08e..f8d50bd 100644 --- a/drivers/crypto/axis/artpec6_crypto.c +++ b/drivers/crypto/axis/artpec6_crypto.c
@@ -2067,7 +2067,7 @@ static void artpec6_crypto_process_queue(struct artpec6_crypto *ac, if (ac->pending_count) mod_timer(&ac->timer, jiffies + msecs_to_jiffies(100)); else - del_timer(&ac->timer); + timer_delete(&ac->timer); } static void artpec6_crypto_timeout(struct timer_list *t) @@ -2963,7 +2963,7 @@ static void artpec6_crypto_remove(struct platform_device *pdev) tasklet_disable(&ac->task); devm_free_irq(&pdev->dev, irq, ac); tasklet_kill(&ac->task); - del_timer_sync(&ac->timer); + timer_delete_sync(&ac->timer); artpec6_crypto_disable_hw(ac);
diff --git a/drivers/crypto/inside-secure/eip93/eip93-hash.c b/drivers/crypto/inside-secure/eip93/eip93-hash.c index 5e96274..df1b05a 100644 --- a/drivers/crypto/inside-secure/eip93/eip93-hash.c +++ b/drivers/crypto/inside-secure/eip93/eip93-hash.c
@@ -260,7 +260,8 @@ static int eip93_send_hash_req(struct crypto_async_request *async, u8 *data, } again: - ret = eip93_put_descriptor(eip93, &cdesc); + scoped_guard(spinlock_irqsave, &eip93->ring->write_lock) + ret = eip93_put_descriptor(eip93, &cdesc); if (ret) { usleep_range(EIP93_RING_BUSY_DELAY, EIP93_RING_BUSY_DELAY * 2);
diff --git a/drivers/cxl/Kconfig b/drivers/cxl/Kconfig index 8ac1e9d..cf1ba67 100644 --- a/drivers/cxl/Kconfig +++ b/drivers/cxl/Kconfig
@@ -158,4 +158,8 @@ If unsure, or if this kernel is meant for production environments, say N. +config CXL_MCE + def_bool y + depends on X86_MCE && MEMORY_FAILURE + endif
diff --git a/drivers/cxl/core/Makefile b/drivers/cxl/core/Makefile index b0bfbd9..086df97 100644 --- a/drivers/cxl/core/Makefile +++ b/drivers/cxl/core/Makefile
@@ -14,6 +14,9 @@ cxl_core-y += hdm.o cxl_core-y += pmu.o cxl_core-y += cdat.o +cxl_core-y += ras.o +cxl_core-y += acpi.o cxl_core-$(CONFIG_TRACING) += trace.o cxl_core-$(CONFIG_CXL_REGION) += region.o +cxl_core-$(CONFIG_CXL_MCE) += mce.o cxl_core-$(CONFIG_CXL_FEATURES) += features.o
diff --git a/drivers/cxl/core/acpi.c b/drivers/cxl/core/acpi.c new file mode 100644 index 0000000..f13b4da --- /dev/null +++ b/drivers/cxl/core/acpi.c
@@ -0,0 +1,11 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* Copyright(c) 2024 Intel Corporation. All rights reserved. */ +#include <linux/acpi.h> +#include "cxl.h" +#include "core.h" + +int cxl_acpi_get_extended_linear_cache_size(struct resource *backing_res, + int nid, resource_size_t *size) +{ + return hmat_get_extended_linear_cache_size(backing_res, nid, size); +}
diff --git a/drivers/cxl/core/cdat.c b/drivers/cxl/core/cdat.c index 8153f8d..edb4f41 100644 --- a/drivers/cxl/core/cdat.c +++ b/drivers/cxl/core/cdat.c
@@ -258,27 +258,29 @@ static void update_perf_entry(struct device *dev, struct dsmas_entry *dent, static void cxl_memdev_set_qos_class(struct cxl_dev_state *cxlds, struct xarray *dsmas_xa) { - struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlds); struct device *dev = cxlds->dev; - struct range pmem_range = { - .start = cxlds->pmem_res.start, - .end = cxlds->pmem_res.end, - }; - struct range ram_range = { - .start = cxlds->ram_res.start, - .end = cxlds->ram_res.end, - }; struct dsmas_entry *dent; unsigned long index; xa_for_each(dsmas_xa, index, dent) { - if (resource_size(&cxlds->ram_res) && - range_contains(&ram_range, &dent->dpa_range)) - update_perf_entry(dev, dent, &mds->ram_perf); - else if (resource_size(&cxlds->pmem_res) && - range_contains(&pmem_range, &dent->dpa_range)) - update_perf_entry(dev, dent, &mds->pmem_perf); - else + bool found = false; + + for (int i = 0; i < cxlds->nr_partitions; i++) { + struct resource *res = &cxlds->part[i].res; + struct range range = { + .start = res->start, + .end = res->end, + }; + + if (range_contains(&range, &dent->dpa_range)) { + update_perf_entry(dev, dent, + &cxlds->part[i].perf); + found = true; + break; + } + } + + if (!found) dev_dbg(dev, "no partition for dsmas dpa: %pra\n", &dent->dpa_range); } @@ -343,36 +345,46 @@ static int match_cxlrd_hb(struct device *dev, void *data) return 0; } -static int cxl_qos_class_verify(struct cxl_memdev *cxlmd) +static void cxl_qos_class_verify(struct cxl_memdev *cxlmd) { struct cxl_dev_state *cxlds = cxlmd->cxlds; - struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlds); struct cxl_port *root_port; - int rc; struct cxl_root *cxl_root __free(put_cxl_root) = find_cxl_root(cxlmd->endpoint); + /* + * No need to reset_dpa_perf() here as find_cxl_root() is guaranteed to + * succeed when called in the cxl_endpoint_port_probe() path. + */ if (!cxl_root) - return -ENODEV; + return; root_port = &cxl_root->port; - /* Check that the QTG IDs are all sane between end device and root decoders */ - if (!cxl_qos_match(root_port, &mds->ram_perf)) - reset_dpa_perf(&mds->ram_perf); - if (!cxl_qos_match(root_port, &mds->pmem_perf)) - reset_dpa_perf(&mds->pmem_perf); + /* + * Save userspace from needing to check if a qos class has any matches + * by hiding qos class info if the memdev is not mapped by a root + * decoder, or the partition class does not match any root decoder + * class. + */ + if (!device_for_each_child(&root_port->dev, + cxlmd->endpoint->host_bridge, + match_cxlrd_hb)) { + for (int i = 0; i < cxlds->nr_partitions; i++) { + struct cxl_dpa_perf *perf = &cxlds->part[i].perf; - /* Check to make sure that the device's host bridge is under a root decoder */ - rc = device_for_each_child(&root_port->dev, - cxlmd->endpoint->host_bridge, match_cxlrd_hb); - if (!rc) { - reset_dpa_perf(&mds->ram_perf); - reset_dpa_perf(&mds->pmem_perf); + reset_dpa_perf(perf); + } + return; } - return rc; + for (int i = 0; i < cxlds->nr_partitions; i++) { + struct cxl_dpa_perf *perf = &cxlds->part[i].perf; + + if (!cxl_qos_match(root_port, perf)) + reset_dpa_perf(perf); + } } static void discard_dsmas(struct xarray *xa) @@ -570,23 +582,18 @@ static bool dpa_perf_contains(struct cxl_dpa_perf *perf, return range_contains(&perf->dpa_range, &dpa); } -static struct cxl_dpa_perf *cxled_get_dpa_perf(struct cxl_endpoint_decoder *cxled, - enum cxl_decoder_mode mode) +static struct cxl_dpa_perf *cxled_get_dpa_perf(struct cxl_endpoint_decoder *cxled) { struct cxl_memdev *cxlmd = cxled_to_memdev(cxled); - struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds); + struct cxl_dev_state *cxlds = cxlmd->cxlds; struct cxl_dpa_perf *perf; - switch (mode) { - case CXL_DECODER_RAM: - perf = &mds->ram_perf; - break; - case CXL_DECODER_PMEM: - perf = &mds->pmem_perf; - break; - default: + if (cxled->part < 0) return ERR_PTR(-EINVAL); - } + perf = &cxlds->part[cxled->part].perf; + + if (!perf) + return ERR_PTR(-EINVAL); if (!dpa_perf_contains(perf, cxled->dpa_res)) return ERR_PTR(-EINVAL); @@ -647,11 +654,10 @@ static int cxl_endpoint_gather_bandwidth(struct cxl_region *cxlr, if (cxlds->rcd) return -ENODEV; - perf = cxled_get_dpa_perf(cxled, cxlr->mode); + perf = cxled_get_dpa_perf(cxled); if (IS_ERR(perf)) return PTR_ERR(perf); - gp_port = to_cxl_port(parent_port->dev.parent); *gp_is_root = is_cxl_root(gp_port); /* @@ -1053,7 +1059,7 @@ void cxl_region_perf_data_calculate(struct cxl_region *cxlr, lockdep_assert_held(&cxl_dpa_rwsem); - perf = cxled_get_dpa_perf(cxled, cxlr->mode); + perf = cxled_get_dpa_perf(cxled); if (IS_ERR(perf)) return;
diff --git a/drivers/cxl/core/core.h b/drivers/cxl/core/core.h index 17e99a25..1569929 100644 --- a/drivers/cxl/core/core.h +++ b/drivers/cxl/core/core.h
@@ -74,8 +74,8 @@ void __iomem *devm_cxl_iomap_block(struct device *dev, resource_size_t addr, resource_size_t length); struct dentry *cxl_debugfs_create_dir(const char *dir); -int cxl_dpa_set_mode(struct cxl_endpoint_decoder *cxled, - enum cxl_decoder_mode mode); +int cxl_dpa_set_part(struct cxl_endpoint_decoder *cxled, + enum cxl_partition_mode mode); int cxl_dpa_alloc(struct cxl_endpoint_decoder *cxled, unsigned long long size); int cxl_dpa_free(struct cxl_endpoint_decoder *cxled); resource_size_t cxl_dpa_size(struct cxl_endpoint_decoder *cxled); @@ -117,6 +117,12 @@ bool cxl_need_node_perf_attrs_update(int nid); int cxl_port_get_switch_dport_bandwidth(struct cxl_port *port, struct access_coordinate *c); +int cxl_ras_init(void); +void cxl_ras_exit(void); +int cxl_gpf_port_setup(struct device *dport_dev, struct cxl_port *port); +int cxl_acpi_get_extended_linear_cache_size(struct resource *backing_res, + int nid, resource_size_t *size); + #ifdef CONFIG_CXL_FEATURES size_t cxl_get_feature(struct cxl_mailbox *cxl_mbox, const uuid_t *feat_uuid, enum cxl_get_feat_selection selection,
diff --git a/drivers/cxl/core/hdm.c b/drivers/cxl/core/hdm.c index 50e6a45..70cae4e 100644 --- a/drivers/cxl/core/hdm.c +++ b/drivers/cxl/core/hdm.c
@@ -213,16 +213,46 @@ void cxl_dpa_debug(struct seq_file *file, struct cxl_dev_state *cxlds) { struct resource *p1, *p2; - down_read(&cxl_dpa_rwsem); + guard(rwsem_read)(&cxl_dpa_rwsem); for (p1 = cxlds->dpa_res.child; p1; p1 = p1->sibling) { __cxl_dpa_debug(file, p1, 0); for (p2 = p1->child; p2; p2 = p2->sibling) __cxl_dpa_debug(file, p2, 1); } - up_read(&cxl_dpa_rwsem); } EXPORT_SYMBOL_NS_GPL(cxl_dpa_debug, "CXL"); +/* See request_skip() kernel-doc */ +static resource_size_t __adjust_skip(struct cxl_dev_state *cxlds, + const resource_size_t skip_base, + const resource_size_t skip_len, + const char *requester) +{ + const resource_size_t skip_end = skip_base + skip_len - 1; + + for (int i = 0; i < cxlds->nr_partitions; i++) { + const struct resource *part_res = &cxlds->part[i].res; + resource_size_t adjust_start, adjust_end, size; + + adjust_start = max(skip_base, part_res->start); + adjust_end = min(skip_end, part_res->end); + + if (adjust_end < adjust_start) + continue; + + size = adjust_end - adjust_start + 1; + + if (!requester) + __release_region(&cxlds->dpa_res, adjust_start, size); + else if (!__request_region(&cxlds->dpa_res, adjust_start, size, + requester, 0)) + return adjust_start - skip_base; + } + + return skip_len; +} +#define release_skip(c, b, l) __adjust_skip((c), (b), (l), NULL) + /* * Must be called in a context that synchronizes against this decoder's * port ->remove() callback (like an endpoint decoder sysfs attribute) @@ -241,7 +271,7 @@ static void __cxl_dpa_release(struct cxl_endpoint_decoder *cxled) skip_start = res->start - cxled->skip; __release_region(&cxlds->dpa_res, res->start, resource_size(res)); if (cxled->skip) - __release_region(&cxlds->dpa_res, skip_start, cxled->skip); + release_skip(cxlds, skip_start, cxled->skip); cxled->skip = 0; cxled->dpa_res = NULL; put_device(&cxled->cxld.dev); @@ -250,9 +280,8 @@ static void __cxl_dpa_release(struct cxl_endpoint_decoder *cxled) static void cxl_dpa_release(void *cxled) { - down_write(&cxl_dpa_rwsem); + guard(rwsem_write)(&cxl_dpa_rwsem); __cxl_dpa_release(cxled); - up_write(&cxl_dpa_rwsem); } /* @@ -268,6 +297,58 @@ static void devm_cxl_dpa_release(struct cxl_endpoint_decoder *cxled) __cxl_dpa_release(cxled); } +/** + * request_skip() - Track DPA 'skip' in @cxlds->dpa_res resource tree + * @cxlds: CXL.mem device context that parents @cxled + * @cxled: Endpoint decoder establishing new allocation that skips lower DPA + * @skip_base: DPA < start of new DPA allocation (DPAnew) + * @skip_len: @skip_base + @skip_len == DPAnew + * + * DPA 'skip' arises from out-of-sequence DPA allocation events relative + * to free capacity across multiple partitions. It is a wasteful event + * as usable DPA gets thrown away, but if a deployment has, for example, + * a dual RAM+PMEM device, wants to use PMEM, and has unallocated RAM + * DPA, the free RAM DPA must be sacrificed to start allocating PMEM. + * See third "Implementation Note" in CXL 3.1 8.2.4.19.13 "Decoder + * Protection" for more details. + * + * A 'skip' always covers the last allocated DPA in a previous partition + * to the start of the current partition to allocate. Allocations never + * start in the middle of a partition, and allocations are always + * de-allocated in reverse order (see cxl_dpa_free(), or natural devm + * unwind order from forced in-order allocation). + * + * If @cxlds->nr_partitions was guaranteed to be <= 2 then the 'skip' + * would always be contained to a single partition. Given + * @cxlds->nr_partitions may be > 2 it results in cases where the 'skip' + * might span "tail capacity of partition[0], all of partition[1], ..., + * all of partition[N-1]" to support allocating from partition[N]. That + * in turn interacts with the partition 'struct resource' boundaries + * within @cxlds->dpa_res whereby 'skip' requests need to be divided by + * partition. I.e. this is a quirk of using a 'struct resource' tree to + * detect range conflicts while also tracking partition boundaries in + * @cxlds->dpa_res. + */ +static int request_skip(struct cxl_dev_state *cxlds, + struct cxl_endpoint_decoder *cxled, + const resource_size_t skip_base, + const resource_size_t skip_len) +{ + resource_size_t skipped = __adjust_skip(cxlds, skip_base, skip_len, + dev_name(&cxled->cxld.dev)); + + if (skipped == skip_len) + return 0; + + dev_dbg(cxlds->dev, + "%s: failed to reserve skipped space (%pa %pa %pa)\n", + dev_name(&cxled->cxld.dev), &skip_base, &skip_len, &skipped); + + release_skip(cxlds, skip_base, skipped); + + return -EBUSY; +} + static int __cxl_dpa_reserve(struct cxl_endpoint_decoder *cxled, resource_size_t base, resource_size_t len, resource_size_t skipped) @@ -277,6 +358,7 @@ static int __cxl_dpa_reserve(struct cxl_endpoint_decoder *cxled, struct cxl_dev_state *cxlds = cxlmd->cxlds; struct device *dev = &port->dev; struct resource *res; + int rc; lockdep_assert_held_write(&cxl_dpa_rwsem); @@ -305,14 +387,9 @@ static int __cxl_dpa_reserve(struct cxl_endpoint_decoder *cxled, } if (skipped) { - res = __request_region(&cxlds->dpa_res, base - skipped, skipped, - dev_name(&cxled->cxld.dev), 0); - if (!res) { - dev_dbg(dev, - "decoder%d.%d: failed to reserve skipped space\n", - port->id, cxled->cxld.id); - return -EBUSY; - } + rc = request_skip(cxlds, cxled, base - skipped, skipped); + if (rc) + return rc; } res = __request_region(&cxlds->dpa_res, base, len, dev_name(&cxled->cxld.dev), 0); @@ -320,28 +397,117 @@ static int __cxl_dpa_reserve(struct cxl_endpoint_decoder *cxled, dev_dbg(dev, "decoder%d.%d: failed to reserve allocation\n", port->id, cxled->cxld.id); if (skipped) - __release_region(&cxlds->dpa_res, base - skipped, - skipped); + release_skip(cxlds, base - skipped, skipped); return -EBUSY; } cxled->dpa_res = res; cxled->skip = skipped; - if (resource_contains(&cxlds->pmem_res, res)) - cxled->mode = CXL_DECODER_PMEM; - else if (resource_contains(&cxlds->ram_res, res)) - cxled->mode = CXL_DECODER_RAM; - else { - dev_warn(dev, "decoder%d.%d: %pr mixed mode not supported\n", - port->id, cxled->cxld.id, cxled->dpa_res); - cxled->mode = CXL_DECODER_MIXED; - } + /* + * When allocating new capacity, ->part is already set, when + * discovering decoder settings at initial enumeration, ->part + * is not set. + */ + if (cxled->part < 0) + for (int i = 0; cxlds->nr_partitions; i++) + if (resource_contains(&cxlds->part[i].res, res)) { + cxled->part = i; + break; + } + + if (cxled->part < 0) + dev_warn(dev, "decoder%d.%d: %pr does not map any partition\n", + port->id, cxled->cxld.id, res); port->hdm_end++; get_device(&cxled->cxld.dev); return 0; } +static int add_dpa_res(struct device *dev, struct resource *parent, + struct resource *res, resource_size_t start, + resource_size_t size, const char *type) +{ + int rc; + + *res = (struct resource) { + .name = type, + .start = start, + .end = start + size - 1, + .flags = IORESOURCE_MEM, + }; + if (resource_size(res) == 0) { + dev_dbg(dev, "DPA(%s): no capacity\n", res->name); + return 0; + } + rc = request_resource(parent, res); + if (rc) { + dev_err(dev, "DPA(%s): failed to track %pr (%d)\n", res->name, + res, rc); + return rc; + } + + dev_dbg(dev, "DPA(%s): %pr\n", res->name, res); + + return 0; +} + +static const char *cxl_mode_name(enum cxl_partition_mode mode) +{ + switch (mode) { + case CXL_PARTMODE_RAM: + return "ram"; + case CXL_PARTMODE_PMEM: + return "pmem"; + default: + return ""; + }; +} + +/* if this fails the caller must destroy @cxlds, there is no recovery */ +int cxl_dpa_setup(struct cxl_dev_state *cxlds, const struct cxl_dpa_info *info) +{ + struct device *dev = cxlds->dev; + + guard(rwsem_write)(&cxl_dpa_rwsem); + + if (cxlds->nr_partitions) + return -EBUSY; + + if (!info->size || !info->nr_partitions) { + cxlds->dpa_res = DEFINE_RES_MEM(0, 0); + cxlds->nr_partitions = 0; + return 0; + } + + cxlds->dpa_res = DEFINE_RES_MEM(0, info->size); + + for (int i = 0; i < info->nr_partitions; i++) { + const struct cxl_dpa_part_info *part = &info->part[i]; + int rc; + + cxlds->part[i].perf.qos_class = CXL_QOS_CLASS_INVALID; + cxlds->part[i].mode = part->mode; + + /* Require ordered + contiguous partitions */ + if (i) { + const struct cxl_dpa_part_info *prev = &info->part[i - 1]; + + if (prev->range.end + 1 != part->range.start) + return -EINVAL; + } + rc = add_dpa_res(dev, &cxlds->dpa_res, &cxlds->part[i].res, + part->range.start, range_len(&part->range), + cxl_mode_name(part->mode)); + if (rc) + return rc; + cxlds->nr_partitions++; + } + + return 0; +} +EXPORT_SYMBOL_GPL(cxl_dpa_setup); + int devm_cxl_dpa_reserve(struct cxl_endpoint_decoder *cxled, resource_size_t base, resource_size_t len, resource_size_t skipped) @@ -362,14 +528,11 @@ EXPORT_SYMBOL_NS_GPL(devm_cxl_dpa_reserve, "CXL"); resource_size_t cxl_dpa_size(struct cxl_endpoint_decoder *cxled) { - resource_size_t size = 0; - - down_read(&cxl_dpa_rwsem); + guard(rwsem_read)(&cxl_dpa_rwsem); if (cxled->dpa_res) - size = resource_size(cxled->dpa_res); - up_read(&cxl_dpa_rwsem); + return resource_size(cxled->dpa_res); - return size; + return 0; } resource_size_t cxl_dpa_resource_start(struct cxl_endpoint_decoder *cxled) @@ -387,151 +550,136 @@ int cxl_dpa_free(struct cxl_endpoint_decoder *cxled) { struct cxl_port *port = cxled_to_port(cxled); struct device *dev = &cxled->cxld.dev; - int rc; - down_write(&cxl_dpa_rwsem); - if (!cxled->dpa_res) { - rc = 0; - goto out; - } + guard(rwsem_write)(&cxl_dpa_rwsem); + if (!cxled->dpa_res) + return 0; if (cxled->cxld.region) { dev_dbg(dev, "decoder assigned to: %s\n", dev_name(&cxled->cxld.region->dev)); - rc = -EBUSY; - goto out; + return -EBUSY; } if (cxled->cxld.flags & CXL_DECODER_F_ENABLE) { dev_dbg(dev, "decoder enabled\n"); - rc = -EBUSY; - goto out; + return -EBUSY; } if (cxled->cxld.id != port->hdm_end) { dev_dbg(dev, "expected decoder%d.%d\n", port->id, port->hdm_end); - rc = -EBUSY; - goto out; + return -EBUSY; } + devm_cxl_dpa_release(cxled); - rc = 0; -out: - up_write(&cxl_dpa_rwsem); - return rc; + return 0; } -int cxl_dpa_set_mode(struct cxl_endpoint_decoder *cxled, - enum cxl_decoder_mode mode) +int cxl_dpa_set_part(struct cxl_endpoint_decoder *cxled, + enum cxl_partition_mode mode) { struct cxl_memdev *cxlmd = cxled_to_memdev(cxled); struct cxl_dev_state *cxlds = cxlmd->cxlds; struct device *dev = &cxled->cxld.dev; - - switch (mode) { - case CXL_DECODER_RAM: - case CXL_DECODER_PMEM: - break; - default: - dev_dbg(dev, "unsupported mode: %d\n", mode); - return -EINVAL; - } + int part; guard(rwsem_write)(&cxl_dpa_rwsem); if (cxled->cxld.flags & CXL_DECODER_F_ENABLE) return -EBUSY; - /* - * Only allow modes that are supported by the current partition - * configuration - */ - if (mode == CXL_DECODER_PMEM && !resource_size(&cxlds->pmem_res)) { - dev_dbg(dev, "no available pmem capacity\n"); - return -ENXIO; + for (part = 0; part < cxlds->nr_partitions; part++) + if (cxlds->part[part].mode == mode) + break; + + if (part >= cxlds->nr_partitions) { + dev_dbg(dev, "unsupported mode: %d\n", mode); + return -EINVAL; } - if (mode == CXL_DECODER_RAM && !resource_size(&cxlds->ram_res)) { - dev_dbg(dev, "no available ram capacity\n"); + + if (!resource_size(&cxlds->part[part].res)) { + dev_dbg(dev, "no available capacity for mode: %d\n", mode); return -ENXIO; } - cxled->mode = mode; + cxled->part = part; return 0; } -int cxl_dpa_alloc(struct cxl_endpoint_decoder *cxled, unsigned long long size) +static int __cxl_dpa_alloc(struct cxl_endpoint_decoder *cxled, unsigned long long size) { struct cxl_memdev *cxlmd = cxled_to_memdev(cxled); - resource_size_t free_ram_start, free_pmem_start; - struct cxl_port *port = cxled_to_port(cxled); struct cxl_dev_state *cxlds = cxlmd->cxlds; struct device *dev = &cxled->cxld.dev; - resource_size_t start, avail, skip; + struct resource *res, *prev = NULL; + resource_size_t start, avail, skip, skip_start; struct resource *p, *last; - int rc; + int part; - down_write(&cxl_dpa_rwsem); + guard(rwsem_write)(&cxl_dpa_rwsem); if (cxled->cxld.region) { dev_dbg(dev, "decoder attached to %s\n", dev_name(&cxled->cxld.region->dev)); - rc = -EBUSY; - goto out; + return -EBUSY; } if (cxled->cxld.flags & CXL_DECODER_F_ENABLE) { dev_dbg(dev, "decoder enabled\n"); - rc = -EBUSY; - goto out; + return -EBUSY; } - for (p = cxlds->ram_res.child, last = NULL; p; p = p->sibling) + part = cxled->part; + if (part < 0) { + dev_dbg(dev, "partition not set\n"); + return -EBUSY; + } + + res = &cxlds->part[part].res; + for (p = res->child, last = NULL; p; p = p->sibling) last = p; if (last) - free_ram_start = last->end + 1; + start = last->end + 1; else - free_ram_start = cxlds->ram_res.start; + start = res->start; - for (p = cxlds->pmem_res.child, last = NULL; p; p = p->sibling) - last = p; - if (last) - free_pmem_start = last->end + 1; - else - free_pmem_start = cxlds->pmem_res.start; + /* + * To allocate at partition N, a skip needs to be calculated for all + * unallocated space at lower partitions indices. + * + * If a partition has any allocations, the search can end because a + * previous cxl_dpa_alloc() invocation is assumed to have accounted for + * all previous partitions. + */ + skip_start = CXL_RESOURCE_NONE; + for (int i = part; i; i--) { + prev = &cxlds->part[i - 1].res; + for (p = prev->child, last = NULL; p; p = p->sibling) + last = p; + if (last) { + skip_start = last->end + 1; + break; + } + skip_start = prev->start; + } - if (cxled->mode == CXL_DECODER_RAM) { - start = free_ram_start; - avail = cxlds->ram_res.end - start + 1; + avail = res->end - start + 1; + if (skip_start == CXL_RESOURCE_NONE) skip = 0; - } else if (cxled->mode == CXL_DECODER_PMEM) { - resource_size_t skip_start, skip_end; - - start = free_pmem_start; - avail = cxlds->pmem_res.end - start + 1; - skip_start = free_ram_start; - - /* - * If some pmem is already allocated, then that allocation - * already handled the skip. - */ - if (cxlds->pmem_res.child && - skip_start == cxlds->pmem_res.child->start) - skip_end = skip_start - 1; - else - skip_end = start - 1; - skip = skip_end - skip_start + 1; - } else { - dev_dbg(dev, "mode not set\n"); - rc = -EINVAL; - goto out; - } + else + skip = res->start - skip_start; if (size > avail) { dev_dbg(dev, "%pa exceeds available %s capacity: %pa\n", &size, - cxl_decoder_mode_name(cxled->mode), &avail); - rc = -ENOSPC; - goto out; + res->name, &avail); + return -ENOSPC; } - rc = __cxl_dpa_reserve(cxled, start, size, skip); -out: - up_write(&cxl_dpa_rwsem); + return __cxl_dpa_reserve(cxled, start, size, skip); +} +int cxl_dpa_alloc(struct cxl_endpoint_decoder *cxled, unsigned long long size) +{ + struct cxl_port *port = cxled_to_port(cxled); + int rc; + + rc = __cxl_dpa_alloc(cxled, size); if (rc) return rc;
diff --git a/drivers/cxl/core/mbox.c b/drivers/cxl/core/mbox.c index 78c5346..d727640 100644 --- a/drivers/cxl/core/mbox.c +++ b/drivers/cxl/core/mbox.c
@@ -11,6 +11,7 @@ #include "core.h" #include "trace.h" +#include "mce.h" static bool cxl_raw_allow_all; @@ -900,7 +901,7 @@ void cxl_event_trace_record(const struct cxl_memdev *cxlmd, } if (trace_cxl_general_media_enabled() || trace_cxl_dram_enabled()) { - u64 dpa, hpa = ULLONG_MAX; + u64 dpa, hpa = ULLONG_MAX, hpa_alias = ULLONG_MAX; struct cxl_region *cxlr; /* @@ -913,14 +914,20 @@ void cxl_event_trace_record(const struct cxl_memdev *cxlmd, dpa = le64_to_cpu(evt->media_hdr.phys_addr) & CXL_DPA_MASK; cxlr = cxl_dpa_to_region(cxlmd, dpa); - if (cxlr) + if (cxlr) { + u64 cache_size = cxlr->params.cache_size; + hpa = cxl_dpa_to_hpa(cxlr, cxlmd, dpa); + if (cache_size) + hpa_alias = hpa - cache_size; + } if (event_type == CXL_CPER_EVENT_GEN_MEDIA) trace_cxl_general_media(cxlmd, type, cxlr, hpa, - &evt->gen_media); + hpa_alias, &evt->gen_media); else if (event_type == CXL_CPER_EVENT_DRAM) - trace_cxl_dram(cxlmd, type, cxlr, hpa, &evt->dram); + trace_cxl_dram(cxlmd, type, cxlr, hpa, hpa_alias, + &evt->dram); } } EXPORT_SYMBOL_NS_GPL(cxl_event_trace_record, "CXL"); @@ -1126,10 +1133,6 @@ static int cxl_mem_get_partition_info(struct cxl_memdev_state *mds) le64_to_cpu(pi.active_volatile_cap) * CXL_CAPACITY_MULTIPLIER; mds->active_persistent_bytes = le64_to_cpu(pi.active_persistent_cap) * CXL_CAPACITY_MULTIPLIER; - mds->next_volatile_bytes = - le64_to_cpu(pi.next_volatile_cap) * CXL_CAPACITY_MULTIPLIER; - mds->next_persistent_bytes = - le64_to_cpu(pi.next_volatile_cap) * CXL_CAPACITY_MULTIPLIER; return 0; } @@ -1251,74 +1254,54 @@ int cxl_mem_sanitize(struct cxl_memdev *cxlmd, u16 cmd) { struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds); struct cxl_port *endpoint; - int rc; /* synchronize with cxl_mem_probe() and decoder write operations */ guard(device)(&cxlmd->dev); endpoint = cxlmd->endpoint; - down_read(&cxl_region_rwsem); + guard(rwsem_read)(&cxl_region_rwsem); /* * Require an endpoint to be safe otherwise the driver can not * be sure that the device is unmapped. */ if (endpoint && cxl_num_decoders_committed(endpoint) == 0) - rc = __cxl_mem_sanitize(mds, cmd); - else - rc = -EBUSY; - up_read(&cxl_region_rwsem); + return __cxl_mem_sanitize(mds, cmd); - return rc; + return -EBUSY; } -static int add_dpa_res(struct device *dev, struct resource *parent, - struct resource *res, resource_size_t start, - resource_size_t size, const char *type) +static void add_part(struct cxl_dpa_info *info, u64 start, u64 size, enum cxl_partition_mode mode) { - int rc; + int i = info->nr_partitions; - res->name = type; - res->start = start; - res->end = start + size - 1; - res->flags = IORESOURCE_MEM; - if (resource_size(res) == 0) { - dev_dbg(dev, "DPA(%s): no capacity\n", res->name); - return 0; - } - rc = request_resource(parent, res); - if (rc) { - dev_err(dev, "DPA(%s): failed to track %pr (%d)\n", res->name, - res, rc); - return rc; - } + if (size == 0) + return; - dev_dbg(dev, "DPA(%s): %pr\n", res->name, res); - - return 0; + info->part[i].range = (struct range) { + .start = start, + .end = start + size - 1, + }; + info->part[i].mode = mode; + info->nr_partitions++; } -int cxl_mem_create_range_info(struct cxl_memdev_state *mds) +int cxl_mem_dpa_fetch(struct cxl_memdev_state *mds, struct cxl_dpa_info *info) { struct cxl_dev_state *cxlds = &mds->cxlds; struct device *dev = cxlds->dev; int rc; if (!cxlds->media_ready) { - cxlds->dpa_res = DEFINE_RES_MEM(0, 0); - cxlds->ram_res = DEFINE_RES_MEM(0, 0); - cxlds->pmem_res = DEFINE_RES_MEM(0, 0); + info->size = 0; return 0; } - cxlds->dpa_res = DEFINE_RES_MEM(0, mds->total_bytes); + info->size = mds->total_bytes; if (mds->partition_align_bytes == 0) { - rc = add_dpa_res(dev, &cxlds->dpa_res, &cxlds->ram_res, 0, - mds->volatile_only_bytes, "ram"); - if (rc) - return rc; - return add_dpa_res(dev, &cxlds->dpa_res, &cxlds->pmem_res, - mds->volatile_only_bytes, - mds->persistent_only_bytes, "pmem"); + add_part(info, 0, mds->volatile_only_bytes, CXL_PARTMODE_RAM); + add_part(info, mds->volatile_only_bytes, + mds->persistent_only_bytes, CXL_PARTMODE_PMEM); + return 0; } rc = cxl_mem_get_partition_info(mds); @@ -1327,15 +1310,52 @@ int cxl_mem_create_range_info(struct cxl_memdev_state *mds) return rc; } - rc = add_dpa_res(dev, &cxlds->dpa_res, &cxlds->ram_res, 0, - mds->active_volatile_bytes, "ram"); - if (rc) - return rc; - return add_dpa_res(dev, &cxlds->dpa_res, &cxlds->pmem_res, - mds->active_volatile_bytes, - mds->active_persistent_bytes, "pmem"); + add_part(info, 0, mds->active_volatile_bytes, CXL_PARTMODE_RAM); + add_part(info, mds->active_volatile_bytes, mds->active_persistent_bytes, + CXL_PARTMODE_PMEM); + + return 0; } -EXPORT_SYMBOL_NS_GPL(cxl_mem_create_range_info, "CXL"); +EXPORT_SYMBOL_NS_GPL(cxl_mem_dpa_fetch, "CXL"); + +int cxl_get_dirty_count(struct cxl_memdev_state *mds, u32 *count) +{ + struct cxl_mailbox *cxl_mbox = &mds->cxlds.cxl_mbox; + struct cxl_mbox_get_health_info_out hi; + struct cxl_mbox_cmd mbox_cmd; + int rc; + + mbox_cmd = (struct cxl_mbox_cmd) { + .opcode = CXL_MBOX_OP_GET_HEALTH_INFO, + .size_out = sizeof(hi), + .payload_out = &hi, + }; + + rc = cxl_internal_send_cmd(cxl_mbox, &mbox_cmd); + if (!rc) + *count = le32_to_cpu(hi.dirty_shutdown_cnt); + + return rc; +} +EXPORT_SYMBOL_NS_GPL(cxl_get_dirty_count, "CXL"); + +int cxl_arm_dirty_shutdown(struct cxl_memdev_state *mds) +{ + struct cxl_mailbox *cxl_mbox = &mds->cxlds.cxl_mbox; + struct cxl_mbox_cmd mbox_cmd; + struct cxl_mbox_set_shutdown_state_in in = { + .state = 1 + }; + + mbox_cmd = (struct cxl_mbox_cmd) { + .opcode = CXL_MBOX_OP_SET_SHUTDOWN_STATE, + .size_in = sizeof(in), + .payload_in = &in, + }; + + return cxl_internal_send_cmd(cxl_mbox, &mbox_cmd); +} +EXPORT_SYMBOL_NS_GPL(cxl_arm_dirty_shutdown, "CXL"); int cxl_set_timestamp(struct cxl_memdev_state *mds) { @@ -1467,6 +1487,7 @@ EXPORT_SYMBOL_NS_GPL(cxl_mailbox_init, "CXL"); struct cxl_memdev_state *cxl_memdev_state_create(struct device *dev) { struct cxl_memdev_state *mds; + int rc; mds = devm_kzalloc(dev, sizeof(*mds), GFP_KERNEL); if (!mds) { @@ -1480,8 +1501,12 @@ struct cxl_memdev_state *cxl_memdev_state_create(struct device *dev) mds->cxlds.cxl_mbox.host = dev; mds->cxlds.reg_map.resource = CXL_RESOURCE_NONE; mds->cxlds.type = CXL_DEVTYPE_CLASSMEM; - mds->ram_perf.qos_class = CXL_QOS_CLASS_INVALID; - mds->pmem_perf.qos_class = CXL_QOS_CLASS_INVALID; + + rc = devm_cxl_register_mce_notifier(dev, &mds->mce_notifier); + if (rc == -EOPNOTSUPP) + dev_warn(dev, "CXL MCE unsupported\n"); + else if (rc) + return ERR_PTR(rc); return mds; }
diff --git a/drivers/cxl/core/mce.c b/drivers/cxl/core/mce.c new file mode 100644 index 0000000..ff8d078 --- /dev/null +++ b/drivers/cxl/core/mce.c
@@ -0,0 +1,65 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* Copyright(c) 2024 Intel Corporation. All rights reserved. */ +#include <linux/mm.h> +#include <linux/notifier.h> +#include <linux/set_memory.h> +#include <asm/mce.h> +#include <cxlmem.h> +#include "mce.h" + +static int cxl_handle_mce(struct notifier_block *nb, unsigned long val, + void *data) +{ + struct cxl_memdev_state *mds = container_of(nb, struct cxl_memdev_state, + mce_notifier); + struct cxl_memdev *cxlmd = mds->cxlds.cxlmd; + struct cxl_port *endpoint = cxlmd->endpoint; + struct mce *mce = data; + u64 spa, spa_alias; + unsigned long pfn; + + if (!mce || !mce_usable_address(mce)) + return NOTIFY_DONE; + + if (!endpoint) + return NOTIFY_DONE; + + spa = mce->addr & MCI_ADDR_PHYSADDR; + + pfn = spa >> PAGE_SHIFT; + if (!pfn_valid(pfn)) + return NOTIFY_DONE; + + spa_alias = cxl_port_get_spa_cache_alias(endpoint, spa); + if (spa_alias == ~0ULL) + return NOTIFY_DONE; + + pfn = spa_alias >> PAGE_SHIFT; + + /* + * Take down the aliased memory page. The original memory page flagged + * by the MCE will be taken cared of by the standard MCE handler. + */ + dev_emerg(mds->cxlds.dev, "Offlining aliased SPA address0: %#llx\n", + spa_alias); + if (!memory_failure(pfn, 0)) + set_mce_nospec(pfn); + + return NOTIFY_OK; +} + +static void cxl_unregister_mce_notifier(void *mce_notifier) +{ + mce_unregister_decode_chain(mce_notifier); +} + +int devm_cxl_register_mce_notifier(struct device *dev, + struct notifier_block *mce_notifier) +{ + mce_notifier->notifier_call = cxl_handle_mce; + mce_notifier->priority = MCE_PRIO_UC; + mce_register_decode_chain(mce_notifier); + + return devm_add_action_or_reset(dev, cxl_unregister_mce_notifier, + mce_notifier); +}
diff --git a/drivers/cxl/core/mce.h b/drivers/cxl/core/mce.h new file mode 100644 index 0000000..ace7342 --- /dev/null +++ b/drivers/cxl/core/mce.h
@@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* Copyright(c) 2024 Intel Corporation. All rights reserved. */ +#ifndef _CXL_CORE_MCE_H_ +#define _CXL_CORE_MCE_H_ + +#include <linux/notifier.h> + +#ifdef CONFIG_CXL_MCE +int devm_cxl_register_mce_notifier(struct device *dev, + struct notifier_block *mce_notifer); +#else +static inline int +devm_cxl_register_mce_notifier(struct device *dev, + struct notifier_block *mce_notifier) +{ + return -EOPNOTSUPP; +} +#endif + +#endif
diff --git a/drivers/cxl/core/memdev.c b/drivers/cxl/core/memdev.c index 2e2e035..a16a588 100644 --- a/drivers/cxl/core/memdev.c +++ b/drivers/cxl/core/memdev.c
@@ -75,12 +75,20 @@ static ssize_t label_storage_size_show(struct device *dev, } static DEVICE_ATTR_RO(label_storage_size); +static resource_size_t cxl_ram_size(struct cxl_dev_state *cxlds) +{ + /* Static RAM is only expected at partition 0. */ + if (cxlds->part[0].mode != CXL_PARTMODE_RAM) + return 0; + return resource_size(&cxlds->part[0].res); +} + static ssize_t ram_size_show(struct device *dev, struct device_attribute *attr, char *buf) { struct cxl_memdev *cxlmd = to_cxl_memdev(dev); struct cxl_dev_state *cxlds = cxlmd->cxlds; - unsigned long long len = resource_size(&cxlds->ram_res); + unsigned long long len = cxl_ram_size(cxlds); return sysfs_emit(buf, "%#llx\n", len); } @@ -93,7 +101,7 @@ static ssize_t pmem_size_show(struct device *dev, struct device_attribute *attr, { struct cxl_memdev *cxlmd = to_cxl_memdev(dev); struct cxl_dev_state *cxlds = cxlmd->cxlds; - unsigned long long len = resource_size(&cxlds->pmem_res); + unsigned long long len = cxl_pmem_size(cxlds); return sysfs_emit(buf, "%#llx\n", len); } @@ -198,22 +206,17 @@ static int cxl_get_poison_by_memdev(struct cxl_memdev *cxlmd) int rc = 0; /* CXL 3.0 Spec 8.2.9.8.4.1 Separate pmem and ram poison requests */ - if (resource_size(&cxlds->pmem_res)) { - offset = cxlds->pmem_res.start; - length = resource_size(&cxlds->pmem_res); - rc = cxl_mem_get_poison(cxlmd, offset, length, NULL); - if (rc) - return rc; - } - if (resource_size(&cxlds->ram_res)) { - offset = cxlds->ram_res.start; - length = resource_size(&cxlds->ram_res); + for (int i = 0; i < cxlds->nr_partitions; i++) { + const struct resource *res = &cxlds->part[i].res; + + offset = res->start; + length = resource_size(res); rc = cxl_mem_get_poison(cxlmd, offset, length, NULL); /* * Invalid Physical Address is not an error for * volatile addresses. Device support is optional. */ - if (rc == -EFAULT) + if (rc == -EFAULT && cxlds->part[i].mode == CXL_PARTMODE_RAM) rc = 0; } return rc; @@ -404,14 +407,21 @@ static struct attribute *cxl_memdev_attributes[] = { NULL, }; +static struct cxl_dpa_perf *to_pmem_perf(struct cxl_dev_state *cxlds) +{ + for (int i = 0; i < cxlds->nr_partitions; i++) + if (cxlds->part[i].mode == CXL_PARTMODE_PMEM) + return &cxlds->part[i].perf; + return NULL; +} + static ssize_t pmem_qos_class_show(struct device *dev, struct device_attribute *attr, char *buf) { struct cxl_memdev *cxlmd = to_cxl_memdev(dev); struct cxl_dev_state *cxlds = cxlmd->cxlds; - struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlds); - return sysfs_emit(buf, "%d\n", mds->pmem_perf.qos_class); + return sysfs_emit(buf, "%d\n", to_pmem_perf(cxlds)->qos_class); } static struct device_attribute dev_attr_pmem_qos_class = @@ -423,14 +433,20 @@ static struct attribute *cxl_memdev_pmem_attributes[] = { NULL, }; +static struct cxl_dpa_perf *to_ram_perf(struct cxl_dev_state *cxlds) +{ + if (cxlds->part[0].mode != CXL_PARTMODE_RAM) + return NULL; + return &cxlds->part[0].perf; +} + static ssize_t ram_qos_class_show(struct device *dev, struct device_attribute *attr, char *buf) { struct cxl_memdev *cxlmd = to_cxl_memdev(dev); struct cxl_dev_state *cxlds = cxlmd->cxlds; - struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlds); - return sysfs_emit(buf, "%d\n", mds->ram_perf.qos_class); + return sysfs_emit(buf, "%d\n", to_ram_perf(cxlds)->qos_class); } static struct device_attribute dev_attr_ram_qos_class = @@ -466,11 +482,11 @@ static umode_t cxl_ram_visible(struct kobject *kobj, struct attribute *a, int n) { struct device *dev = kobj_to_dev(kobj); struct cxl_memdev *cxlmd = to_cxl_memdev(dev); - struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds); + struct cxl_dpa_perf *perf = to_ram_perf(cxlmd->cxlds); - if (a == &dev_attr_ram_qos_class.attr) - if (mds->ram_perf.qos_class == CXL_QOS_CLASS_INVALID) - return 0; + if (a == &dev_attr_ram_qos_class.attr && + (!perf || perf->qos_class == CXL_QOS_CLASS_INVALID)) + return 0; return a->mode; } @@ -485,11 +501,11 @@ static umode_t cxl_pmem_visible(struct kobject *kobj, struct attribute *a, int n { struct device *dev = kobj_to_dev(kobj); struct cxl_memdev *cxlmd = to_cxl_memdev(dev); - struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds); + struct cxl_dpa_perf *perf = to_pmem_perf(cxlmd->cxlds); - if (a == &dev_attr_pmem_qos_class.attr) - if (mds->pmem_perf.qos_class == CXL_QOS_CLASS_INVALID) - return 0; + if (a == &dev_attr_pmem_qos_class.attr && + (!perf || perf->qos_class == CXL_QOS_CLASS_INVALID)) + return 0; return a->mode; } @@ -566,10 +582,9 @@ void set_exclusive_cxl_commands(struct cxl_memdev_state *mds, { struct cxl_mailbox *cxl_mbox = &mds->cxlds.cxl_mbox; - down_write(&cxl_memdev_rwsem); + guard(rwsem_write)(&cxl_memdev_rwsem); bitmap_or(cxl_mbox->exclusive_cmds, cxl_mbox->exclusive_cmds, cmds, CXL_MEM_COMMAND_ID_MAX); - up_write(&cxl_memdev_rwsem); } EXPORT_SYMBOL_NS_GPL(set_exclusive_cxl_commands, "CXL"); @@ -583,10 +598,9 @@ void clear_exclusive_cxl_commands(struct cxl_memdev_state *mds, { struct cxl_mailbox *cxl_mbox = &mds->cxlds.cxl_mbox; - down_write(&cxl_memdev_rwsem); + guard(rwsem_write)(&cxl_memdev_rwsem); bitmap_andnot(cxl_mbox->exclusive_cmds, cxl_mbox->exclusive_cmds, cmds, CXL_MEM_COMMAND_ID_MAX); - up_write(&cxl_memdev_rwsem); } EXPORT_SYMBOL_NS_GPL(clear_exclusive_cxl_commands, "CXL"); @@ -594,9 +608,8 @@ static void cxl_memdev_shutdown(struct device *dev) { struct cxl_memdev *cxlmd = to_cxl_memdev(dev); - down_write(&cxl_memdev_rwsem); + guard(rwsem_write)(&cxl_memdev_rwsem); cxlmd->cxlds = NULL; - up_write(&cxl_memdev_rwsem); } static void cxl_memdev_unregister(void *_cxlmd) @@ -678,15 +691,13 @@ static long cxl_memdev_ioctl(struct file *file, unsigned int cmd, { struct cxl_memdev *cxlmd = file->private_data; struct cxl_dev_state *cxlds; - int rc = -ENXIO; - down_read(&cxl_memdev_rwsem); + guard(rwsem_read)(&cxl_memdev_rwsem); cxlds = cxlmd->cxlds; if (cxlds && cxlds->type == CXL_DEVTYPE_CLASSMEM) - rc = __cxl_memdev_ioctl(cxlmd, cmd, arg); - up_read(&cxl_memdev_rwsem); + return __cxl_memdev_ioctl(cxlmd, cmd, arg); - return rc; + return -ENXIO; } static int cxl_memdev_open(struct inode *inode, struct file *file)
diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c index 013b869..96fecb7 100644 --- a/drivers/cxl/core/pci.c +++ b/drivers/cxl/core/pci.c
@@ -1054,3 +1054,100 @@ int cxl_pci_get_bandwidth(struct pci_dev *pdev, struct access_coordinate *c) return 0; } + +/* + * Set max timeout such that platforms will optimize GPF flow to avoid + * the implied worst-case scenario delays. On a sane platform, all + * devices should always complete GPF within the energy budget of + * the GPF flow. The kernel does not have enough information to pick + * anything better than "maximize timeouts and hope it works". + * + * A misbehaving device could block forward progress of GPF for all + * the other devices, exhausting the energy budget of the platform. + * However, the spec seems to assume that moving on from slow to respond + * devices is a virtue. It is not possible to know that, in actuality, + * the slow to respond device is *the* most critical device in the + * system to wait. + */ +#define GPF_TIMEOUT_BASE_MAX 2 +#define GPF_TIMEOUT_SCALE_MAX 7 /* 10 seconds */ + +u16 cxl_gpf_get_dvsec(struct device *dev, bool is_port) +{ + u16 dvsec; + + if (!dev_is_pci(dev)) + return 0; + + dvsec = pci_find_dvsec_capability(to_pci_dev(dev), PCI_VENDOR_ID_CXL, + is_port ? CXL_DVSEC_PORT_GPF : CXL_DVSEC_DEVICE_GPF); + if (!dvsec) + dev_warn(dev, "%s GPF DVSEC not present\n", + is_port ? "Port" : "Device"); + return dvsec; +} +EXPORT_SYMBOL_NS_GPL(cxl_gpf_get_dvsec, "CXL"); + +static int update_gpf_port_dvsec(struct pci_dev *pdev, int dvsec, int phase) +{ + u64 base, scale; + int rc, offset; + u16 ctrl; + + switch (phase) { + case 1: + offset = CXL_DVSEC_PORT_GPF_PHASE_1_CONTROL_OFFSET; + base = CXL_DVSEC_PORT_GPF_PHASE_1_TMO_BASE_MASK; + scale = CXL_DVSEC_PORT_GPF_PHASE_1_TMO_SCALE_MASK; + break; + case 2: + offset = CXL_DVSEC_PORT_GPF_PHASE_2_CONTROL_OFFSET; + base = CXL_DVSEC_PORT_GPF_PHASE_2_TMO_BASE_MASK; + scale = CXL_DVSEC_PORT_GPF_PHASE_2_TMO_SCALE_MASK; + break; + default: + return -EINVAL; + } + + rc = pci_read_config_word(pdev, dvsec + offset, &ctrl); + if (rc) + return rc; + + if (FIELD_GET(base, ctrl) == GPF_TIMEOUT_BASE_MAX && + FIELD_GET(scale, ctrl) == GPF_TIMEOUT_SCALE_MAX) + return 0; + + ctrl = FIELD_PREP(base, GPF_TIMEOUT_BASE_MAX); + ctrl |= FIELD_PREP(scale, GPF_TIMEOUT_SCALE_MAX); + + rc = pci_write_config_word(pdev, dvsec + offset, ctrl); + if (!rc) + pci_dbg(pdev, "Port GPF phase %d timeout: %d0 secs\n", + phase, GPF_TIMEOUT_BASE_MAX); + + return rc; +} + +int cxl_gpf_port_setup(struct device *dport_dev, struct cxl_port *port) +{ + struct pci_dev *pdev; + + if (!port) + return -EINVAL; + + if (!port->gpf_dvsec) { + int dvsec; + + dvsec = cxl_gpf_get_dvsec(dport_dev, true); + if (!dvsec) + return -EINVAL; + + port->gpf_dvsec = dvsec; + } + + pdev = to_pci_dev(dport_dev); + update_gpf_port_dvsec(pdev, port->gpf_dvsec, 1); + update_gpf_port_dvsec(pdev, port->gpf_dvsec, 2); + + return 0; +}
diff --git a/drivers/cxl/core/port.c b/drivers/cxl/core/port.c index 78a5c2c..0fd6646c 100644 --- a/drivers/cxl/core/port.c +++ b/drivers/cxl/core/port.c
@@ -194,25 +194,35 @@ static ssize_t mode_show(struct device *dev, struct device_attribute *attr, char *buf) { struct cxl_endpoint_decoder *cxled = to_cxl_endpoint_decoder(dev); + struct cxl_memdev *cxlmd = cxled_to_memdev(cxled); + struct cxl_dev_state *cxlds = cxlmd->cxlds; + /* without @cxl_dpa_rwsem, make sure @part is not reloaded */ + int part = READ_ONCE(cxled->part); + const char *desc; - return sysfs_emit(buf, "%s\n", cxl_decoder_mode_name(cxled->mode)); + if (part < 0) + desc = "none"; + else + desc = cxlds->part[part].res.name; + + return sysfs_emit(buf, "%s\n", desc); } static ssize_t mode_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { struct cxl_endpoint_decoder *cxled = to_cxl_endpoint_decoder(dev); - enum cxl_decoder_mode mode; + enum cxl_partition_mode mode; ssize_t rc; if (sysfs_streq(buf, "pmem")) - mode = CXL_DECODER_PMEM; + mode = CXL_PARTMODE_PMEM; else if (sysfs_streq(buf, "ram")) - mode = CXL_DECODER_RAM; + mode = CXL_PARTMODE_RAM; else return -EINVAL; - rc = cxl_dpa_set_mode(cxled, mode); + rc = cxl_dpa_set_part(cxled, mode); if (rc) return rc; @@ -549,13 +559,9 @@ static ssize_t decoders_committed_show(struct device *dev, struct device_attribute *attr, char *buf) { struct cxl_port *port = to_cxl_port(dev); - int rc; - down_read(&cxl_region_rwsem); - rc = sysfs_emit(buf, "%d\n", cxl_num_decoders_committed(port)); - up_read(&cxl_region_rwsem); - - return rc; + guard(rwsem_read)(&cxl_region_rwsem); + return sysfs_emit(buf, "%d\n", cxl_num_decoders_committed(port)); } static DEVICE_ATTR_RO(decoders_committed); @@ -1672,6 +1678,8 @@ int devm_cxl_enumerate_ports(struct cxl_memdev *cxlmd) if (rc && rc != -EBUSY) return rc; + cxl_gpf_port_setup(dport_dev, port); + /* Any more ports to add between this one and the root? */ if (!dev_is_cxl_root_child(&port->dev)) continue; @@ -1899,6 +1907,7 @@ struct cxl_endpoint_decoder *cxl_endpoint_decoder_alloc(struct cxl_port *port) return ERR_PTR(-ENOMEM); cxled->pos = -1; + cxled->part = -1; cxld = &cxled->cxld; rc = cxl_decoder_init(port, cxld); if (rc) { @@ -2339,8 +2348,14 @@ static __init int cxl_core_init(void) if (rc) goto err_region; + rc = cxl_ras_init(); + if (rc) + goto err_ras; + return 0; +err_ras: + cxl_region_exit(); err_region: bus_unregister(&cxl_bus_type); err_bus: @@ -2352,6 +2367,7 @@ static __init int cxl_core_init(void) static void cxl_core_exit(void) { + cxl_ras_exit(); cxl_region_exit(); bus_unregister(&cxl_bus_type); destroy_workqueue(cxl_bus_wq);
diff --git a/drivers/cxl/core/ras.c b/drivers/cxl/core/ras.c new file mode 100644 index 0000000..485a831 --- /dev/null +++ b/drivers/cxl/core/ras.c
@@ -0,0 +1,119 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* Copyright(c) 2025 AMD Corporation. All rights reserved. */ + +#include <linux/pci.h> +#include <linux/aer.h> +#include <cxl/event.h> +#include <cxlmem.h> +#include "trace.h" + +static void cxl_cper_trace_corr_port_prot_err(struct pci_dev *pdev, + struct cxl_ras_capability_regs ras_cap) +{ + u32 status = ras_cap.cor_status & ~ras_cap.cor_mask; + + trace_cxl_port_aer_correctable_error(&pdev->dev, status); +} + +static void cxl_cper_trace_uncorr_port_prot_err(struct pci_dev *pdev, + struct cxl_ras_capability_regs ras_cap) +{ + u32 status = ras_cap.uncor_status & ~ras_cap.uncor_mask; + u32 fe; + + if (hweight32(status) > 1) + fe = BIT(FIELD_GET(CXL_RAS_CAP_CONTROL_FE_MASK, + ras_cap.cap_control)); + else + fe = status; + + trace_cxl_port_aer_uncorrectable_error(&pdev->dev, status, fe, + ras_cap.header_log); +} + +static void cxl_cper_trace_corr_prot_err(struct pci_dev *pdev, + struct cxl_ras_capability_regs ras_cap) +{ + u32 status = ras_cap.cor_status & ~ras_cap.cor_mask; + struct cxl_dev_state *cxlds; + + cxlds = pci_get_drvdata(pdev); + if (!cxlds) + return; + + trace_cxl_aer_correctable_error(cxlds->cxlmd, status); +} + +static void cxl_cper_trace_uncorr_prot_err(struct pci_dev *pdev, + struct cxl_ras_capability_regs ras_cap) +{ + u32 status = ras_cap.uncor_status & ~ras_cap.uncor_mask; + struct cxl_dev_state *cxlds; + u32 fe; + + cxlds = pci_get_drvdata(pdev); + if (!cxlds) + return; + + if (hweight32(status) > 1) + fe = BIT(FIELD_GET(CXL_RAS_CAP_CONTROL_FE_MASK, + ras_cap.cap_control)); + else + fe = status; + + trace_cxl_aer_uncorrectable_error(cxlds->cxlmd, status, fe, + ras_cap.header_log); +} + +static void cxl_cper_handle_prot_err(struct cxl_cper_prot_err_work_data *data) +{ + unsigned int devfn = PCI_DEVFN(data->prot_err.agent_addr.device, + data->prot_err.agent_addr.function); + struct pci_dev *pdev __free(pci_dev_put) = + pci_get_domain_bus_and_slot(data->prot_err.agent_addr.segment, + data->prot_err.agent_addr.bus, + devfn); + int port_type; + + if (!pdev) + return; + + guard(device)(&pdev->dev); + + port_type = pci_pcie_type(pdev); + if (port_type == PCI_EXP_TYPE_ROOT_PORT || + port_type == PCI_EXP_TYPE_DOWNSTREAM || + port_type == PCI_EXP_TYPE_UPSTREAM) { + if (data->severity == AER_CORRECTABLE) + cxl_cper_trace_corr_port_prot_err(pdev, data->ras_cap); + else + cxl_cper_trace_uncorr_port_prot_err(pdev, data->ras_cap); + + return; + } + + if (data->severity == AER_CORRECTABLE) + cxl_cper_trace_corr_prot_err(pdev, data->ras_cap); + else + cxl_cper_trace_uncorr_prot_err(pdev, data->ras_cap); +} + +static void cxl_cper_prot_err_work_fn(struct work_struct *work) +{ + struct cxl_cper_prot_err_work_data wd; + + while (cxl_cper_prot_err_kfifo_get(&wd)) + cxl_cper_handle_prot_err(&wd); +} +static DECLARE_WORK(cxl_cper_prot_err_work, cxl_cper_prot_err_work_fn); + +int cxl_ras_init(void) +{ + return cxl_cper_register_prot_err_work(&cxl_cper_prot_err_work); +} + +void cxl_ras_exit(void) +{ + cxl_cper_unregister_prot_err_work(&cxl_cper_prot_err_work); + cancel_work_sync(&cxl_cper_prot_err_work); +}
diff --git a/drivers/cxl/core/region.c b/drivers/cxl/core/region.c index e8d11a9..c3f4dc2 100644 --- a/drivers/cxl/core/region.c +++ b/drivers/cxl/core/region.c
@@ -144,7 +144,7 @@ static ssize_t uuid_show(struct device *dev, struct device_attribute *attr, rc = down_read_interruptible(&cxl_region_rwsem); if (rc) return rc; - if (cxlr->mode != CXL_DECODER_PMEM) + if (cxlr->mode != CXL_PARTMODE_PMEM) rc = sysfs_emit(buf, "\n"); else rc = sysfs_emit(buf, "%pUb\n", &p->uuid); @@ -441,7 +441,7 @@ static umode_t cxl_region_visible(struct kobject *kobj, struct attribute *a, * Support tooling that expects to find a 'uuid' attribute for all * regions regardless of mode. */ - if (a == &dev_attr_uuid.attr && cxlr->mode != CXL_DECODER_PMEM) + if (a == &dev_attr_uuid.attr && cxlr->mode != CXL_PARTMODE_PMEM) return 0444; return a->mode; } @@ -603,8 +603,16 @@ static ssize_t mode_show(struct device *dev, struct device_attribute *attr, char *buf) { struct cxl_region *cxlr = to_cxl_region(dev); + const char *desc; - return sysfs_emit(buf, "%s\n", cxl_decoder_mode_name(cxlr->mode)); + if (cxlr->mode == CXL_PARTMODE_RAM) + desc = "ram"; + else if (cxlr->mode == CXL_PARTMODE_PMEM) + desc = "pmem"; + else + desc = ""; + + return sysfs_emit(buf, "%s\n", desc); } static DEVICE_ATTR_RO(mode); @@ -630,7 +638,7 @@ static int alloc_hpa(struct cxl_region *cxlr, resource_size_t size) /* ways, granularity and uuid (if PMEM) need to be set before HPA */ if (!p->interleave_ways || !p->interleave_granularity || - (cxlr->mode == CXL_DECODER_PMEM && uuid_is_null(&p->uuid))) + (cxlr->mode == CXL_PARTMODE_PMEM && uuid_is_null(&p->uuid))) return -ENXIO; div64_u64_rem(size, (u64)SZ_256M * p->interleave_ways, &remainder); @@ -824,6 +832,21 @@ static int match_free_decoder(struct device *dev, const void *data) return 1; } +static bool region_res_match_cxl_range(const struct cxl_region_params *p, + struct range *range) +{ + if (!p->res) + return false; + + /* + * If an extended linear cache region then the CXL range is assumed + * to be fronted by the DRAM range in current known implementation. + * This assumption will be made until a variant implementation exists. + */ + return p->res->start + p->cache_size == range->start && + p->res->end == range->end; +} + static int match_auto_decoder(struct device *dev, const void *data) { const struct cxl_region_params *p = data; @@ -836,7 +859,7 @@ static int match_auto_decoder(struct device *dev, const void *data) cxld = to_cxl_decoder(dev); r = &cxld->hpa_range; - if (p->res && p->res->start == r->start && p->res->end == r->end) + if (region_res_match_cxl_range(p, r)) return 1; return 0; @@ -1424,8 +1447,7 @@ static int cxl_port_setup_targets(struct cxl_port *port, if (test_bit(CXL_REGION_F_AUTO, &cxlr->flags)) { if (cxld->interleave_ways != iw || cxld->interleave_granularity != ig || - cxld->hpa_range.start != p->res->start || - cxld->hpa_range.end != p->res->end || + !region_res_match_cxl_range(p, &cxld->hpa_range) || ((cxld->flags & CXL_DECODER_F_ENABLE) == 0)) { dev_err(&cxlr->dev, "%s:%s %s expected iw: %d ig: %d %pr\n", @@ -1888,6 +1910,7 @@ static int cxl_region_attach(struct cxl_region *cxlr, { struct cxl_root_decoder *cxlrd = to_cxl_root_decoder(cxlr->dev.parent); struct cxl_memdev *cxlmd = cxled_to_memdev(cxled); + struct cxl_dev_state *cxlds = cxlmd->cxlds; struct cxl_region_params *p = &cxlr->params; struct cxl_port *ep_port, *root_port; struct cxl_dport *dport; @@ -1902,17 +1925,17 @@ static int cxl_region_attach(struct cxl_region *cxlr, return rc; } - if (cxled->mode != cxlr->mode) { - dev_dbg(&cxlr->dev, "%s region mode: %d mismatch: %d\n", - dev_name(&cxled->cxld.dev), cxlr->mode, cxled->mode); - return -EINVAL; - } - - if (cxled->mode == CXL_DECODER_DEAD) { + if (cxled->part < 0) { dev_dbg(&cxlr->dev, "%s dead\n", dev_name(&cxled->cxld.dev)); return -ENODEV; } + if (cxlds->part[cxled->part].mode != cxlr->mode) { + dev_dbg(&cxlr->dev, "%s region mode: %d mismatch\n", + dev_name(&cxled->cxld.dev), cxlr->mode); + return -EINVAL; + } + /* all full of members, or interleave config not established? */ if (p->state > CXL_CONFIG_INTERLEAVE_ACTIVE) { dev_dbg(&cxlr->dev, "region already active\n"); @@ -1951,13 +1974,13 @@ static int cxl_region_attach(struct cxl_region *cxlr, return -ENXIO; } - if (resource_size(cxled->dpa_res) * p->interleave_ways != + if (resource_size(cxled->dpa_res) * p->interleave_ways + p->cache_size != resource_size(p->res)) { dev_dbg(&cxlr->dev, - "%s:%s: decoder-size-%#llx * ways-%d != region-size-%#llx\n", + "%s:%s-size-%#llx * ways-%d + cache-%#llx != region-size-%#llx\n", dev_name(&cxlmd->dev), dev_name(&cxled->cxld.dev), (u64)resource_size(cxled->dpa_res), p->interleave_ways, - (u64)resource_size(p->res)); + (u64)p->cache_size, (u64)resource_size(p->res)); return -EINVAL; } @@ -2115,7 +2138,7 @@ static int cxl_region_detach(struct cxl_endpoint_decoder *cxled) void cxl_decoder_kill_region(struct cxl_endpoint_decoder *cxled) { down_write(&cxl_region_rwsem); - cxled->mode = CXL_DECODER_DEAD; + cxled->part = -1; cxl_region_detach(cxled); up_write(&cxl_region_rwsem); } @@ -2471,7 +2494,7 @@ static int cxl_region_calculate_adistance(struct notifier_block *nb, */ static struct cxl_region *devm_cxl_add_region(struct cxl_root_decoder *cxlrd, int id, - enum cxl_decoder_mode mode, + enum cxl_partition_mode mode, enum cxl_decoder_type type) { struct cxl_port *port = to_cxl_port(cxlrd->cxlsd.cxld.dev.parent); @@ -2525,13 +2548,13 @@ static ssize_t create_ram_region_show(struct device *dev, } static struct cxl_region *__create_region(struct cxl_root_decoder *cxlrd, - enum cxl_decoder_mode mode, int id) + enum cxl_partition_mode mode, int id) { int rc; switch (mode) { - case CXL_DECODER_RAM: - case CXL_DECODER_PMEM: + case CXL_PARTMODE_RAM: + case CXL_PARTMODE_PMEM: break; default: dev_err(&cxlrd->cxlsd.cxld.dev, "unsupported mode %d\n", mode); @@ -2551,7 +2574,7 @@ static struct cxl_region *__create_region(struct cxl_root_decoder *cxlrd, } static ssize_t create_region_store(struct device *dev, const char *buf, - size_t len, enum cxl_decoder_mode mode) + size_t len, enum cxl_partition_mode mode) { struct cxl_root_decoder *cxlrd = to_cxl_root_decoder(dev); struct cxl_region *cxlr; @@ -2572,7 +2595,7 @@ static ssize_t create_pmem_region_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { - return create_region_store(dev, buf, len, CXL_DECODER_PMEM); + return create_region_store(dev, buf, len, CXL_PARTMODE_PMEM); } DEVICE_ATTR_RW(create_pmem_region); @@ -2580,7 +2603,7 @@ static ssize_t create_ram_region_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { - return create_region_store(dev, buf, len, CXL_DECODER_RAM); + return create_region_store(dev, buf, len, CXL_PARTMODE_RAM); } DEVICE_ATTR_RW(create_ram_region); @@ -2678,7 +2701,7 @@ EXPORT_SYMBOL_NS_GPL(to_cxl_pmem_region, "CXL"); struct cxl_poison_context { struct cxl_port *port; - enum cxl_decoder_mode mode; + int part; u64 offset; }; @@ -2686,47 +2709,45 @@ static int cxl_get_poison_unmapped(struct cxl_memdev *cxlmd, struct cxl_poison_context *ctx) { struct cxl_dev_state *cxlds = cxlmd->cxlds; + const struct resource *res; + struct resource *p, *last; u64 offset, length; int rc = 0; - /* - * Collect poison for the remaining unmapped resources - * after poison is collected by committed endpoints. - * - * Knowing that PMEM must always follow RAM, get poison - * for unmapped resources based on the last decoder's mode: - * ram: scan remains of ram range, then any pmem range - * pmem: scan remains of pmem range - */ - - if (ctx->mode == CXL_DECODER_RAM) { - offset = ctx->offset; - length = resource_size(&cxlds->ram_res) - offset; - rc = cxl_mem_get_poison(cxlmd, offset, length, NULL); - if (rc == -EFAULT) - rc = 0; - if (rc) - return rc; - } - if (ctx->mode == CXL_DECODER_PMEM) { - offset = ctx->offset; - length = resource_size(&cxlds->dpa_res) - offset; - if (!length) - return 0; - } else if (resource_size(&cxlds->pmem_res)) { - offset = cxlds->pmem_res.start; - length = resource_size(&cxlds->pmem_res); - } else { + if (ctx->part < 0) return 0; + + /* + * Collect poison for the remaining unmapped resources after + * poison is collected by committed endpoints decoders. + */ + for (int i = ctx->part; i < cxlds->nr_partitions; i++) { + res = &cxlds->part[i].res; + for (p = res->child, last = NULL; p; p = p->sibling) + last = p; + if (last) + offset = last->end + 1; + else + offset = res->start; + length = res->end - offset + 1; + if (!length) + break; + rc = cxl_mem_get_poison(cxlmd, offset, length, NULL); + if (rc == -EFAULT && cxlds->part[i].mode == CXL_PARTMODE_RAM) + continue; + if (rc) + break; } - return cxl_mem_get_poison(cxlmd, offset, length, NULL); + return rc; } static int poison_by_decoder(struct device *dev, void *arg) { struct cxl_poison_context *ctx = arg; struct cxl_endpoint_decoder *cxled; + enum cxl_partition_mode mode; + struct cxl_dev_state *cxlds; struct cxl_memdev *cxlmd; u64 offset, length; int rc = 0; @@ -2735,27 +2756,18 @@ static int poison_by_decoder(struct device *dev, void *arg) return rc; cxled = to_cxl_endpoint_decoder(dev); - if (!cxled->dpa_res || !resource_size(cxled->dpa_res)) + if (!cxled->dpa_res) return rc; - /* - * Regions are only created with single mode decoders: pmem or ram. - * Linux does not support mixed mode decoders. This means that - * reading poison per endpoint decoder adheres to the requirement - * that poison reads of pmem and ram must be separated. - * CXL 3.0 Spec 8.2.9.8.4.1 - */ - if (cxled->mode == CXL_DECODER_MIXED) { - dev_dbg(dev, "poison list read unsupported in mixed mode\n"); - return rc; - } - cxlmd = cxled_to_memdev(cxled); + cxlds = cxlmd->cxlds; + mode = cxlds->part[cxled->part].mode; + if (cxled->skip) { offset = cxled->dpa_res->start - cxled->skip; length = cxled->skip; rc = cxl_mem_get_poison(cxlmd, offset, length, NULL); - if (rc == -EFAULT && cxled->mode == CXL_DECODER_RAM) + if (rc == -EFAULT && mode == CXL_PARTMODE_RAM) rc = 0; if (rc) return rc; @@ -2764,7 +2776,7 @@ static int poison_by_decoder(struct device *dev, void *arg) offset = cxled->dpa_res->start; length = cxled->dpa_res->end - offset + 1; rc = cxl_mem_get_poison(cxlmd, offset, length, cxled->cxld.region); - if (rc == -EFAULT && cxled->mode == CXL_DECODER_RAM) + if (rc == -EFAULT && mode == CXL_PARTMODE_RAM) rc = 0; if (rc) return rc; @@ -2772,7 +2784,7 @@ static int poison_by_decoder(struct device *dev, void *arg) /* Iterate until commit_end is reached */ if (cxled->cxld.id == ctx->port->commit_end) { ctx->offset = cxled->dpa_res->end + 1; - ctx->mode = cxled->mode; + ctx->part = cxled->part; return 1; } @@ -2785,7 +2797,8 @@ int cxl_get_poison_by_endpoint(struct cxl_port *port) int rc = 0; ctx = (struct cxl_poison_context) { - .port = port + .port = port, + .part = -1, }; rc = device_for_each_child(&port->dev, &ctx, poison_by_decoder); @@ -2921,7 +2934,7 @@ u64 cxl_dpa_to_hpa(struct cxl_region *cxlr, const struct cxl_memdev *cxlmd, hpa_offset |= dpa_offset & GENMASK_ULL(eig + 7, 0); /* Apply the hpa_offset to the region base address */ - hpa = hpa_offset + p->res->start; + hpa = hpa_offset + p->res->start + p->cache_size; /* Root decoder translation overrides typical modulo decode */ if (cxlrd->hpa_to_spa) @@ -3038,17 +3051,13 @@ static struct cxl_dax_region *cxl_dax_region_alloc(struct cxl_region *cxlr) struct cxl_dax_region *cxlr_dax; struct device *dev; - down_read(&cxl_region_rwsem); - if (p->state != CXL_CONFIG_COMMIT) { - cxlr_dax = ERR_PTR(-ENXIO); - goto out; - } + guard(rwsem_read)(&cxl_region_rwsem); + if (p->state != CXL_CONFIG_COMMIT) + return ERR_PTR(-ENXIO); cxlr_dax = kzalloc(sizeof(*cxlr_dax), GFP_KERNEL); - if (!cxlr_dax) { - cxlr_dax = ERR_PTR(-ENOMEM); - goto out; - } + if (!cxlr_dax) + return ERR_PTR(-ENOMEM); cxlr_dax->hpa_range.start = p->res->start; cxlr_dax->hpa_range.end = p->res->end; @@ -3061,8 +3070,6 @@ static struct cxl_dax_region *cxl_dax_region_alloc(struct cxl_region *cxlr) dev->parent = &cxlr->dev; dev->bus = &cxl_bus_type; dev->type = &cxl_dax_region_type; -out: - up_read(&cxl_region_rwsem); return cxlr_dax; } @@ -3208,7 +3215,6 @@ static int match_region_by_range(struct device *dev, const void *data) struct cxl_region_params *p; struct cxl_region *cxlr; const struct range *r = data; - int rc = 0; if (!is_cxl_region(dev)) return 0; @@ -3216,60 +3222,96 @@ static int match_region_by_range(struct device *dev, const void *data) cxlr = to_cxl_region(dev); p = &cxlr->params; - down_read(&cxl_region_rwsem); + guard(rwsem_read)(&cxl_region_rwsem); if (p->res && p->res->start == r->start && p->res->end == r->end) - rc = 1; - up_read(&cxl_region_rwsem); + return 1; - return rc; + return 0; } -/* Establish an empty region covering the given HPA range */ -static struct cxl_region *construct_region(struct cxl_root_decoder *cxlrd, - struct cxl_endpoint_decoder *cxled) +static int cxl_extended_linear_cache_resize(struct cxl_region *cxlr, + struct resource *res) +{ + struct cxl_root_decoder *cxlrd = to_cxl_root_decoder(cxlr->dev.parent); + struct cxl_region_params *p = &cxlr->params; + int nid = phys_to_target_node(res->start); + resource_size_t size = resource_size(res); + resource_size_t cache_size, start; + int rc; + + rc = cxl_acpi_get_extended_linear_cache_size(res, nid, &cache_size); + if (rc) + return rc; + + if (!cache_size) + return 0; + + if (size != cache_size) { + dev_warn(&cxlr->dev, + "Extended Linear Cache size %pa != CXL size %pa. No Support!", + &cache_size, &size); + return -ENXIO; + } + + /* + * Move the start of the range to where the cache range starts. The + * implementation assumes that the cache range is in front of the + * CXL range. This is not dictated by the HMAT spec but is how the + * current known implementation is configured. + * + * The cache range is expected to be within the CFMWS. The adjusted + * res->start should not be less than cxlrd->res->start. + */ + start = res->start - cache_size; + if (start < cxlrd->res->start) + return -ENXIO; + + res->start = start; + p->cache_size = cache_size; + + return 0; +} + +static int __construct_region(struct cxl_region *cxlr, + struct cxl_root_decoder *cxlrd, + struct cxl_endpoint_decoder *cxled) { struct cxl_memdev *cxlmd = cxled_to_memdev(cxled); - struct cxl_port *port = cxlrd_to_port(cxlrd); struct range *hpa = &cxled->cxld.hpa_range; struct cxl_region_params *p; - struct cxl_region *cxlr; struct resource *res; int rc; - do { - cxlr = __create_region(cxlrd, cxled->mode, - atomic_read(&cxlrd->region_id)); - } while (IS_ERR(cxlr) && PTR_ERR(cxlr) == -EBUSY); - - if (IS_ERR(cxlr)) { - dev_err(cxlmd->dev.parent, - "%s:%s: %s failed assign region: %ld\n", - dev_name(&cxlmd->dev), dev_name(&cxled->cxld.dev), - __func__, PTR_ERR(cxlr)); - return cxlr; - } - - down_write(&cxl_region_rwsem); + guard(rwsem_write)(&cxl_region_rwsem); p = &cxlr->params; if (p->state >= CXL_CONFIG_INTERLEAVE_ACTIVE) { dev_err(cxlmd->dev.parent, "%s:%s: %s autodiscovery interrupted\n", dev_name(&cxlmd->dev), dev_name(&cxled->cxld.dev), __func__); - rc = -EBUSY; - goto err; + return -EBUSY; } set_bit(CXL_REGION_F_AUTO, &cxlr->flags); res = kmalloc(sizeof(*res), GFP_KERNEL); - if (!res) { - rc = -ENOMEM; - goto err; - } + if (!res) + return -ENOMEM; *res = DEFINE_RES_MEM_NAMED(hpa->start, range_len(hpa), dev_name(&cxlr->dev)); + + rc = cxl_extended_linear_cache_resize(cxlr, res); + if (rc && rc != -EOPNOTSUPP) { + /* + * Failing to support extended linear cache region resize does not + * prevent the region from functioning. Only causes cxl list showing + * incorrect region size. + */ + dev_warn(cxlmd->dev.parent, + "Extended linear cache calculation failed rc:%d\n", rc); + } + rc = insert_resource(cxlrd->res, res); if (rc) { /* @@ -3289,7 +3331,7 @@ static struct cxl_region *construct_region(struct cxl_root_decoder *cxlrd, rc = sysfs_update_group(&cxlr->dev.kobj, get_cxl_region_target_group()); if (rc) - goto err; + return rc; dev_dbg(cxlmd->dev.parent, "%s:%s: %s %s res: %pr iw: %d ig: %d\n", dev_name(&cxlmd->dev), dev_name(&cxled->cxld.dev), __func__, @@ -3298,14 +3340,40 @@ static struct cxl_region *construct_region(struct cxl_root_decoder *cxlrd, /* ...to match put_device() in cxl_add_to_region() */ get_device(&cxlr->dev); - up_write(&cxl_region_rwsem); + + return 0; +} + +/* Establish an empty region covering the given HPA range */ +static struct cxl_region *construct_region(struct cxl_root_decoder *cxlrd, + struct cxl_endpoint_decoder *cxled) +{ + struct cxl_memdev *cxlmd = cxled_to_memdev(cxled); + struct cxl_port *port = cxlrd_to_port(cxlrd); + struct cxl_dev_state *cxlds = cxlmd->cxlds; + int rc, part = READ_ONCE(cxled->part); + struct cxl_region *cxlr; + + do { + cxlr = __create_region(cxlrd, cxlds->part[part].mode, + atomic_read(&cxlrd->region_id)); + } while (IS_ERR(cxlr) && PTR_ERR(cxlr) == -EBUSY); + + if (IS_ERR(cxlr)) { + dev_err(cxlmd->dev.parent, + "%s:%s: %s failed assign region: %ld\n", + dev_name(&cxlmd->dev), dev_name(&cxled->cxld.dev), + __func__, PTR_ERR(cxlr)); + return cxlr; + } + + rc = __construct_region(cxlr, cxlrd, cxled); + if (rc) { + devm_release_action(port->uport_dev, unregister_region, cxlr); + return ERR_PTR(rc); + } return cxlr; - -err: - up_write(&cxl_region_rwsem); - devm_release_action(port->uport_dev, unregister_region, cxlr); - return ERR_PTR(rc); } int cxl_add_to_region(struct cxl_port *root, struct cxl_endpoint_decoder *cxled) @@ -3375,6 +3443,34 @@ int cxl_add_to_region(struct cxl_port *root, struct cxl_endpoint_decoder *cxled) } EXPORT_SYMBOL_NS_GPL(cxl_add_to_region, "CXL"); +u64 cxl_port_get_spa_cache_alias(struct cxl_port *endpoint, u64 spa) +{ + struct cxl_region_ref *iter; + unsigned long index; + + if (!endpoint) + return ~0ULL; + + guard(rwsem_write)(&cxl_region_rwsem); + + xa_for_each(&endpoint->regions, index, iter) { + struct cxl_region_params *p = &iter->region->params; + + if (p->res->start <= spa && spa <= p->res->end) { + if (!p->cache_size) + return ~0ULL; + + if (spa >= p->res->start + p->cache_size) + return spa - p->cache_size; + + return spa + p->cache_size; + } + } + + return ~0ULL; +} +EXPORT_SYMBOL_NS_GPL(cxl_port_get_spa_cache_alias, "CXL"); + static int is_system_ram(struct resource *res, void *arg) { struct cxl_region *cxlr = arg; @@ -3440,9 +3536,9 @@ static int cxl_region_probe(struct device *dev) return rc; switch (cxlr->mode) { - case CXL_DECODER_PMEM: + case CXL_PARTMODE_PMEM: return devm_cxl_add_pmem_region(cxlr); - case CXL_DECODER_RAM: + case CXL_PARTMODE_RAM: /* * The region can not be manged by CXL if any portion of * it is already online as 'System RAM'
diff --git a/drivers/cxl/core/trace.h b/drivers/cxl/core/trace.h index cea706b..25ebfbc 100644 --- a/drivers/cxl/core/trace.h +++ b/drivers/cxl/core/trace.h
@@ -48,6 +48,34 @@ { CXL_RAS_UC_IDE_RX_ERR, "IDE Rx Error" } \ ) +TRACE_EVENT(cxl_port_aer_uncorrectable_error, + TP_PROTO(struct device *dev, u32 status, u32 fe, u32 *hl), + TP_ARGS(dev, status, fe, hl), + TP_STRUCT__entry( + __string(device, dev_name(dev)) + __string(host, dev_name(dev->parent)) + __field(u32, status) + __field(u32, first_error) + __array(u32, header_log, CXL_HEADERLOG_SIZE_U32) + ), + TP_fast_assign( + __assign_str(device); + __assign_str(host); + __entry->status = status; + __entry->first_error = fe; + /* + * Embed the 512B headerlog data for user app retrieval and + * parsing, but no need to print this in the trace buffer. + */ + memcpy(__entry->header_log, hl, CXL_HEADERLOG_SIZE); + ), + TP_printk("device=%s host=%s status: '%s' first_error: '%s'", + __get_str(device), __get_str(host), + show_uc_errs(__entry->status), + show_uc_errs(__entry->first_error) + ) +); + TRACE_EVENT(cxl_aer_uncorrectable_error, TP_PROTO(const struct cxl_memdev *cxlmd, u32 status, u32 fe, u32 *hl), TP_ARGS(cxlmd, status, fe, hl), @@ -96,6 +124,25 @@ TRACE_EVENT(cxl_aer_uncorrectable_error, { CXL_RAS_CE_PHYS_LAYER_ERR, "Received Error From Physical Layer" } \ ) +TRACE_EVENT(cxl_port_aer_correctable_error, + TP_PROTO(struct device *dev, u32 status), + TP_ARGS(dev, status), + TP_STRUCT__entry( + __string(device, dev_name(dev)) + __string(host, dev_name(dev->parent)) + __field(u32, status) + ), + TP_fast_assign( + __assign_str(device); + __assign_str(host); + __entry->status = status; + ), + TP_printk("device=%s host=%s status='%s'", + __get_str(device), __get_str(host), + show_ce_errs(__entry->status) + ) +); + TRACE_EVENT(cxl_aer_correctable_error, TP_PROTO(const struct cxl_memdev *cxlmd, u32 status), TP_ARGS(cxlmd, status), @@ -392,9 +439,10 @@ TRACE_EVENT(cxl_generic_event, TRACE_EVENT(cxl_general_media, TP_PROTO(const struct cxl_memdev *cxlmd, enum cxl_event_log_type log, - struct cxl_region *cxlr, u64 hpa, struct cxl_event_gen_media *rec), + struct cxl_region *cxlr, u64 hpa, u64 hpa_alias0, + struct cxl_event_gen_media *rec), - TP_ARGS(cxlmd, log, cxlr, hpa, rec), + TP_ARGS(cxlmd, log, cxlr, hpa, hpa_alias0, rec), TP_STRUCT__entry( CXL_EVT_TP_entry @@ -408,6 +456,7 @@ TRACE_EVENT(cxl_general_media, __array(u8, comp_id, CXL_EVENT_GEN_MED_COMP_ID_SIZE) /* Following are out of order to pack trace record */ __field(u64, hpa) + __field(u64, hpa_alias0) __field_struct(uuid_t, region_uuid) __field(u16, validity_flags) __field(u8, rank) @@ -438,6 +487,7 @@ TRACE_EVENT(cxl_general_media, CXL_EVENT_GEN_MED_COMP_ID_SIZE); __entry->validity_flags = get_unaligned_le16(&rec->media_hdr.validity_flags); __entry->hpa = hpa; + __entry->hpa_alias0 = hpa_alias0; if (cxlr) { __assign_str(region_name); uuid_copy(&__entry->region_uuid, &cxlr->params.uuid); @@ -455,7 +505,7 @@ TRACE_EVENT(cxl_general_media, "device=%x validity_flags='%s' " \ "comp_id=%s comp_id_pldm_valid_flags='%s' " \ "pldm_entity_id=%s pldm_resource_id=%s " \ - "hpa=%llx region=%s region_uuid=%pUb " \ + "hpa=%llx hpa_alias0=%llx region=%s region_uuid=%pUb " \ "cme_threshold_ev_flags='%s' cme_count=%u", __entry->dpa, show_dpa_flags(__entry->dpa_flags), show_event_desc_flags(__entry->descriptor), @@ -470,7 +520,7 @@ TRACE_EVENT(cxl_general_media, CXL_GMER_VALID_COMPONENT_ID_FORMAT, __entry->comp_id), show_pldm_resource_id(__entry->validity_flags, CXL_GMER_VALID_COMPONENT, CXL_GMER_VALID_COMPONENT_ID_FORMAT, __entry->comp_id), - __entry->hpa, __get_str(region_name), &__entry->region_uuid, + __entry->hpa, __entry->hpa_alias0, __get_str(region_name), &__entry->region_uuid, show_cme_threshold_ev_flags(__entry->cme_threshold_ev_flags), __entry->cme_count ) ); @@ -529,9 +579,10 @@ TRACE_EVENT(cxl_general_media, TRACE_EVENT(cxl_dram, TP_PROTO(const struct cxl_memdev *cxlmd, enum cxl_event_log_type log, - struct cxl_region *cxlr, u64 hpa, struct cxl_event_dram *rec), + struct cxl_region *cxlr, u64 hpa, u64 hpa_alias0, + struct cxl_event_dram *rec), - TP_ARGS(cxlmd, log, cxlr, hpa, rec), + TP_ARGS(cxlmd, log, cxlr, hpa, hpa_alias0, rec), TP_STRUCT__entry( CXL_EVT_TP_entry @@ -547,6 +598,7 @@ TRACE_EVENT(cxl_dram, __field(u32, row) __array(u8, cor_mask, CXL_EVENT_DER_CORRECTION_MASK_SIZE) __field(u64, hpa) + __field(u64, hpa_alias0) __field_struct(uuid_t, region_uuid) __field(u8, rank) /* Out of order to pack trace record */ __field(u8, bank_group) /* Out of order to pack trace record */ @@ -584,6 +636,7 @@ TRACE_EVENT(cxl_dram, memcpy(__entry->cor_mask, &rec->correction_mask, CXL_EVENT_DER_CORRECTION_MASK_SIZE); __entry->hpa = hpa; + __entry->hpa_alias0 = hpa_alias0; if (cxlr) { __assign_str(region_name); uuid_copy(&__entry->region_uuid, &cxlr->params.uuid); @@ -604,7 +657,7 @@ TRACE_EVENT(cxl_dram, "validity_flags='%s' " \ "comp_id=%s comp_id_pldm_valid_flags='%s' " \ "pldm_entity_id=%s pldm_resource_id=%s " \ - "hpa=%llx region=%s region_uuid=%pUb " \ + "hpa=%llx hpa_alias0=%llx region=%s region_uuid=%pUb " \ "sub_channel=%u cme_threshold_ev_flags='%s' cvme_count=%u", __entry->dpa, show_dpa_flags(__entry->dpa_flags), show_event_desc_flags(__entry->descriptor), @@ -622,7 +675,7 @@ TRACE_EVENT(cxl_dram, CXL_DER_VALID_COMPONENT_ID_FORMAT, __entry->comp_id), show_pldm_resource_id(__entry->validity_flags, CXL_DER_VALID_COMPONENT, CXL_DER_VALID_COMPONENT_ID_FORMAT, __entry->comp_id), - __entry->hpa, __get_str(region_name), &__entry->region_uuid, + __entry->hpa, __entry->hpa_alias0, __get_str(region_name), &__entry->region_uuid, __entry->sub_channel, show_cme_threshold_ev_flags(__entry->cme_threshold_ev_flags), __entry->cvme_count ) @@ -870,6 +923,7 @@ TRACE_EVENT(cxl_poison, __string(region, cxlr ? dev_name(&cxlr->dev) : "") __field(u64, overflow_ts) __field(u64, hpa) + __field(u64, hpa_alias0) __field(u64, dpa) __field(u32, dpa_length) __array(char, uuid, 16) @@ -892,16 +946,22 @@ TRACE_EVENT(cxl_poison, memcpy(__entry->uuid, &cxlr->params.uuid, 16); __entry->hpa = cxl_dpa_to_hpa(cxlr, cxlmd, __entry->dpa); + if (__entry->hpa != ULLONG_MAX && cxlr->params.cache_size) + __entry->hpa_alias0 = __entry->hpa + + cxlr->params.cache_size; + else + __entry->hpa_alias0 = ULLONG_MAX; } else { __assign_str(region); memset(__entry->uuid, 0, 16); __entry->hpa = ULLONG_MAX; + __entry->hpa_alias0 = ULLONG_MAX; } ), TP_printk("memdev=%s host=%s serial=%lld trace_type=%s region=%s " \ - "region_uuid=%pU hpa=0x%llx dpa=0x%llx dpa_length=0x%x " \ - "source=%s flags=%s overflow_time=%llu", + "region_uuid=%pU hpa=0x%llx hpa_alias0=0x%llx dpa=0x%llx " \ + "dpa_length=0x%x source=%s flags=%s overflow_time=%llu", __get_str(memdev), __get_str(host), __entry->serial, @@ -909,6 +969,7 @@ TRACE_EVENT(cxl_poison, __get_str(region), __entry->uuid, __entry->hpa, + __entry->hpa_alias0, __entry->dpa, __entry->dpa_length, show_poison_source(__entry->source),
diff --git a/drivers/cxl/cxl.h b/drivers/cxl/cxl.h index bbbaa0d..be8a7dc 100644 --- a/drivers/cxl/cxl.h +++ b/drivers/cxl/cxl.h
@@ -373,32 +373,6 @@ struct cxl_decoder { }; /* - * CXL_DECODER_DEAD prevents endpoints from being reattached to regions - * while cxld_unregister() is running - */ -enum cxl_decoder_mode { - CXL_DECODER_NONE, - CXL_DECODER_RAM, - CXL_DECODER_PMEM, - CXL_DECODER_MIXED, - CXL_DECODER_DEAD, -}; - -static inline const char *cxl_decoder_mode_name(enum cxl_decoder_mode mode) -{ - static const char * const names[] = { - [CXL_DECODER_NONE] = "none", - [CXL_DECODER_RAM] = "ram", - [CXL_DECODER_PMEM] = "pmem", - [CXL_DECODER_MIXED] = "mixed", - }; - - if (mode >= CXL_DECODER_NONE && mode <= CXL_DECODER_MIXED) - return names[mode]; - return "mixed"; -} - -/* * Track whether this decoder is reserved for region autodiscovery, or * free for userspace provisioning. */ @@ -412,16 +386,16 @@ enum cxl_decoder_state { * @cxld: base cxl_decoder_object * @dpa_res: actively claimed DPA span of this decoder * @skip: offset into @dpa_res where @cxld.hpa_range maps - * @mode: which memory type / access-mode-partition this decoder targets * @state: autodiscovery state + * @part: partition index this decoder maps * @pos: interleave position in @cxld.region */ struct cxl_endpoint_decoder { struct cxl_decoder cxld; struct resource *dpa_res; resource_size_t skip; - enum cxl_decoder_mode mode; enum cxl_decoder_state state; + int part; int pos; }; @@ -493,6 +467,7 @@ enum cxl_config_state { * @res: allocated iomem capacity for this region * @targets: active ordered targets in current decoder configuration * @nr_targets: number of targets + * @cache_size: extended linear cache size if exists, otherwise zero. * * State transitions are protected by the cxl_region_rwsem */ @@ -504,6 +479,12 @@ struct cxl_region_params { struct resource *res; struct cxl_endpoint_decoder *targets[CXL_DECODER_MAX_INTERLEAVE]; int nr_targets; + resource_size_t cache_size; +}; + +enum cxl_partition_mode { + CXL_PARTMODE_RAM, + CXL_PARTMODE_PMEM, }; /* @@ -525,7 +506,7 @@ struct cxl_region_params { * struct cxl_region - CXL region * @dev: This region's device * @id: This region's id. Id is globally unique across all regions - * @mode: Endpoint decoder allocation / access mode + * @mode: Operational mode of the mapped capacity * @type: Endpoint decoder target type * @cxl_nvb: nvdimm bridge for coordinating @cxlr_pmem setup / shutdown * @cxlr_pmem: (for pmem regions) cached copy of the nvdimm bridge @@ -538,7 +519,7 @@ struct cxl_region_params { struct cxl_region { struct device dev; int id; - enum cxl_decoder_mode mode; + enum cxl_partition_mode mode; enum cxl_decoder_type type; struct cxl_nvdimm_bridge *cxl_nvb; struct cxl_pmem_region *cxlr_pmem; @@ -563,6 +544,7 @@ struct cxl_nvdimm { struct device dev; struct cxl_memdev *cxlmd; u8 dev_id[CXL_DEV_ID_LEN]; /* for nvdimm, string of 'serial' */ + u64 dirty_shutdowns; }; struct cxl_pmem_region_mapping { @@ -610,6 +592,7 @@ struct cxl_dax_region { * @cdat: Cached CDAT data * @cdat_available: Should a CDAT attribute be available in sysfs * @pci_latency: Upstream latency in picoseconds + * @gpf_dvsec: Cached GPF port DVSEC */ struct cxl_port { struct device dev; @@ -633,6 +616,7 @@ struct cxl_port { } cdat; bool cdat_available; long pci_latency; + int gpf_dvsec; }; /** @@ -875,6 +859,7 @@ struct cxl_pmem_region *to_cxl_pmem_region(struct device *dev); int cxl_add_to_region(struct cxl_port *root, struct cxl_endpoint_decoder *cxled); struct cxl_dax_region *to_cxl_dax_region(struct device *dev); +u64 cxl_port_get_spa_cache_alias(struct cxl_port *endpoint, u64 spa); #else static inline bool is_cxl_pmem_region(struct device *dev) { @@ -893,6 +878,11 @@ static inline struct cxl_dax_region *to_cxl_dax_region(struct device *dev) { return NULL; } +static inline u64 cxl_port_get_spa_cache_alias(struct cxl_port *endpoint, + u64 spa) +{ + return 0; +} #endif void cxl_endpoint_parse_cdat(struct cxl_port *port); @@ -920,4 +910,6 @@ bool cxl_endpoint_decoder_reset_detected(struct cxl_port *port); #define __mock static #endif +u16 cxl_gpf_get_dvsec(struct device *dev, bool is_port); + #endif /* __CXL_H__ */
diff --git a/drivers/cxl/cxlmem.h b/drivers/cxl/cxlmem.h index dd2b706..3ec6b90 100644 --- a/drivers/cxl/cxlmem.h +++ b/drivers/cxl/cxlmem.h
@@ -97,6 +97,19 @@ int devm_cxl_dpa_reserve(struct cxl_endpoint_decoder *cxled, resource_size_t base, resource_size_t len, resource_size_t skipped); +#define CXL_NR_PARTITIONS_MAX 2 + +struct cxl_dpa_info { + u64 size; + struct cxl_dpa_part_info { + struct range range; + enum cxl_partition_mode mode; + } part[CXL_NR_PARTITIONS_MAX]; + int nr_partitions; +}; + +int cxl_dpa_setup(struct cxl_dev_state *cxlds, const struct cxl_dpa_info *info); + static inline struct cxl_ep *cxl_ep_load(struct cxl_port *port, struct cxl_memdev *cxlmd) { @@ -373,6 +386,18 @@ struct cxl_dpa_perf { }; /** + * struct cxl_dpa_partition - DPA partition descriptor + * @res: shortcut to the partition in the DPA resource tree (cxlds->dpa_res) + * @perf: performance attributes of the partition from CDAT + * @mode: operation mode for the DPA capacity, e.g. ram, pmem, dynamic... + */ +struct cxl_dpa_partition { + struct resource res; + struct cxl_dpa_perf perf; + enum cxl_partition_mode mode; +}; + +/** * struct cxl_dev_state - The driver device state * * cxl_dev_state represents the CXL driver/device state. It provides an @@ -387,8 +412,8 @@ struct cxl_dpa_perf { * @rcd: operating in RCD mode (CXL 3.0 9.11.8 CXL Devices Attached to an RCH) * @media_ready: Indicate whether the device media is usable * @dpa_res: Overall DPA resource tree for the device - * @pmem_res: Active Persistent memory capacity configuration - * @ram_res: Active Volatile memory capacity configuration + * @part: DPA partition array + * @nr_partitions: Number of DPA partitions * @serial: PCIe Device Serial Number * @type: Generic Memory Class device or Vendor Specific Memory device * @cxl_mbox: CXL mailbox context @@ -403,8 +428,8 @@ struct cxl_dev_state { bool rcd; bool media_ready; struct resource dpa_res; - struct resource pmem_res; - struct resource ram_res; + struct cxl_dpa_partition part[CXL_NR_PARTITIONS_MAX]; + unsigned int nr_partitions; u64 serial; enum cxl_devtype type; struct cxl_mailbox cxl_mbox; @@ -413,6 +438,18 @@ struct cxl_dev_state { #endif }; +static inline resource_size_t cxl_pmem_size(struct cxl_dev_state *cxlds) +{ + /* + * Static PMEM may be at partition index 0 when there is no static RAM + * capacity. + */ + for (int i = 0; i < cxlds->nr_partitions; i++) + if (cxlds->part[i].mode == CXL_PARTMODE_PMEM) + return resource_size(&cxlds->part[i].res); + return 0; +} + static inline struct cxl_dev_state *mbox_to_cxlds(struct cxl_mailbox *cxl_mbox) { return dev_get_drvdata(cxl_mbox->host); @@ -435,14 +472,11 @@ static inline struct cxl_dev_state *mbox_to_cxlds(struct cxl_mailbox *cxl_mbox) * @partition_align_bytes: alignment size for partition-able capacity * @active_volatile_bytes: sum of hard + soft volatile * @active_persistent_bytes: sum of hard + soft persistent - * @next_volatile_bytes: volatile capacity change pending device reset - * @next_persistent_bytes: persistent capacity change pending device reset - * @ram_perf: performance data entry matched to RAM partition - * @pmem_perf: performance data entry matched to PMEM partition * @event: event log driver state * @poison: poison driver state info * @security: security driver state info * @fw: firmware upload / activation state + * @mce_notifier: MCE notifier * * See CXL 3.0 8.2.9.8.2 Capacity Configuration and Label Storage for * details on capacity parameters. @@ -457,16 +491,12 @@ struct cxl_memdev_state { u64 partition_align_bytes; u64 active_volatile_bytes; u64 active_persistent_bytes; - u64 next_volatile_bytes; - u64 next_persistent_bytes; - - struct cxl_dpa_perf ram_perf; - struct cxl_dpa_perf pmem_perf; struct cxl_event_state event; struct cxl_poison_state poison; struct cxl_security_state security; struct cxl_fw_state fw; + struct notifier_block mce_notifier; }; static inline struct cxl_memdev_state * @@ -660,6 +690,23 @@ struct cxl_mbox_set_partition_info { #define CXL_SET_PARTITION_IMMEDIATE_FLAG BIT(0) +/* Get Health Info Output Payload CXL 3.2 Spec 8.2.10.9.3.1 Table 8-148 */ +struct cxl_mbox_get_health_info_out { + u8 health_status; + u8 media_status; + u8 additional_status; + u8 life_used; + __le16 device_temperature; + __le32 dirty_shutdown_cnt; + __le32 corrected_volatile_error_cnt; + __le32 corrected_persistent_error_cnt; +} __packed; + +/* Set Shutdown State Input Payload CXL 3.2 Spec 8.2.10.9.3.5 Table 8-152 */ +struct cxl_mbox_set_shutdown_state_in { + u8 state; +} __packed; + /* Set Timestamp CXL 3.0 Spec 8.2.9.4.2 */ struct cxl_mbox_set_timestamp_in { __le64 timestamp; @@ -785,7 +832,7 @@ int cxl_internal_send_cmd(struct cxl_mailbox *cxl_mbox, int cxl_dev_state_identify(struct cxl_memdev_state *mds); int cxl_await_media_ready(struct cxl_dev_state *cxlds); int cxl_enumerate_cmds(struct cxl_memdev_state *mds); -int cxl_mem_create_range_info(struct cxl_memdev_state *mds); +int cxl_mem_dpa_fetch(struct cxl_memdev_state *mds, struct cxl_dpa_info *info); struct cxl_memdev_state *cxl_memdev_state_create(struct device *dev); void set_exclusive_cxl_commands(struct cxl_memdev_state *mds, unsigned long *cmds); @@ -796,6 +843,8 @@ void cxl_event_trace_record(const struct cxl_memdev *cxlmd, enum cxl_event_log_type type, enum cxl_event_type event_type, const uuid_t *uuid, union cxl_event *evt); +int cxl_get_dirty_count(struct cxl_memdev_state *mds, u32 *count); +int cxl_arm_dirty_shutdown(struct cxl_memdev_state *mds); int cxl_set_timestamp(struct cxl_memdev_state *mds); int cxl_poison_state_init(struct cxl_memdev_state *mds); int cxl_mem_get_poison(struct cxl_memdev *cxlmd, u64 offset, u64 len,
diff --git a/drivers/cxl/cxlpci.h b/drivers/cxl/cxlpci.h index 4da0772..54e219b 100644 --- a/drivers/cxl/cxlpci.h +++ b/drivers/cxl/cxlpci.h
@@ -40,6 +40,12 @@ /* CXL 2.0 8.1.6: GPF DVSEC for CXL Port */ #define CXL_DVSEC_PORT_GPF 4 +#define CXL_DVSEC_PORT_GPF_PHASE_1_CONTROL_OFFSET 0x0C +#define CXL_DVSEC_PORT_GPF_PHASE_1_TMO_BASE_MASK GENMASK(3, 0) +#define CXL_DVSEC_PORT_GPF_PHASE_1_TMO_SCALE_MASK GENMASK(11, 8) +#define CXL_DVSEC_PORT_GPF_PHASE_2_CONTROL_OFFSET 0xE +#define CXL_DVSEC_PORT_GPF_PHASE_2_TMO_BASE_MASK GENMASK(3, 0) +#define CXL_DVSEC_PORT_GPF_PHASE_2_TMO_SCALE_MASK GENMASK(11, 8) /* CXL 2.0 8.1.7: GPF DVSEC for CXL Device */ #define CXL_DVSEC_DEVICE_GPF 5
diff --git a/drivers/cxl/mem.c b/drivers/cxl/mem.c index 2f03a4d..9675243 100644 --- a/drivers/cxl/mem.c +++ b/drivers/cxl/mem.c
@@ -152,7 +152,7 @@ static int cxl_mem_probe(struct device *dev) return -ENXIO; } - if (resource_size(&cxlds->pmem_res) && IS_ENABLED(CONFIG_CXL_PMEM)) { + if (cxl_pmem_size(cxlds) && IS_ENABLED(CONFIG_CXL_PMEM)) { rc = devm_cxl_add_nvdimm(parent_port, cxlmd); if (rc) { if (rc == -ENODEV)
diff --git a/drivers/cxl/pci.c b/drivers/cxl/pci.c index 993fa60..7b14a15 100644 --- a/drivers/cxl/pci.c +++ b/drivers/cxl/pci.c
@@ -903,6 +903,7 @@ __ATTRIBUTE_GROUPS(cxl_rcd); static int cxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) { struct pci_host_bridge *host_bridge = pci_find_host_bridge(pdev->bus); + struct cxl_dpa_info range_info = { 0 }; struct cxl_memdev_state *mds; struct cxl_dev_state *cxlds; struct cxl_register_map map; @@ -993,7 +994,11 @@ static int cxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) if (rc) return rc; - rc = cxl_mem_create_range_info(mds); + rc = cxl_mem_dpa_fetch(mds, &range_info); + if (rc) + return rc; + + rc = cxl_dpa_setup(cxlds, &range_info); if (rc) return rc;
diff --git a/drivers/cxl/pmem.c b/drivers/cxl/pmem.c index f9c9599..d061fe3 100644 --- a/drivers/cxl/pmem.c +++ b/drivers/cxl/pmem.c
@@ -42,15 +42,44 @@ static ssize_t id_show(struct device *dev, struct device_attribute *attr, char * } static DEVICE_ATTR_RO(id); +static ssize_t dirty_shutdown_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct nvdimm *nvdimm = to_nvdimm(dev); + struct cxl_nvdimm *cxl_nvd = nvdimm_provider_data(nvdimm); + + return sysfs_emit(buf, "%llu\n", cxl_nvd->dirty_shutdowns); +} +static DEVICE_ATTR_RO(dirty_shutdown); + static struct attribute *cxl_dimm_attributes[] = { &dev_attr_id.attr, &dev_attr_provider.attr, + &dev_attr_dirty_shutdown.attr, NULL }; +#define CXL_INVALID_DIRTY_SHUTDOWN_COUNT ULLONG_MAX +static umode_t cxl_dimm_visible(struct kobject *kobj, + struct attribute *a, int n) +{ + if (a == &dev_attr_dirty_shutdown.attr) { + struct device *dev = kobj_to_dev(kobj); + struct nvdimm *nvdimm = to_nvdimm(dev); + struct cxl_nvdimm *cxl_nvd = nvdimm_provider_data(nvdimm); + + if (cxl_nvd->dirty_shutdowns == + CXL_INVALID_DIRTY_SHUTDOWN_COUNT) + return 0; + } + + return a->mode; +} + static const struct attribute_group cxl_dimm_attribute_group = { .name = "cxl", .attrs = cxl_dimm_attributes, + .is_visible = cxl_dimm_visible }; static const struct attribute_group *cxl_dimm_attribute_groups[] = { @@ -58,6 +87,38 @@ static const struct attribute_group *cxl_dimm_attribute_groups[] = { NULL }; +static void cxl_nvdimm_arm_dirty_shutdown_tracking(struct cxl_nvdimm *cxl_nvd) +{ + struct cxl_memdev *cxlmd = cxl_nvd->cxlmd; + struct cxl_dev_state *cxlds = cxlmd->cxlds; + struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlds); + struct device *dev = &cxl_nvd->dev; + u32 count; + + /* + * Dirty tracking is enabled and exposed to the user, only when: + * - dirty shutdown on the device can be set, and, + * - the device has a Device GPF DVSEC (albeit unused), and, + * - the Get Health Info cmd can retrieve the device's dirty count. + */ + cxl_nvd->dirty_shutdowns = CXL_INVALID_DIRTY_SHUTDOWN_COUNT; + + if (cxl_arm_dirty_shutdown(mds)) { + dev_warn(dev, "GPF: could not set dirty shutdown state\n"); + return; + } + + if (!cxl_gpf_get_dvsec(cxlds->dev, false)) + return; + + if (cxl_get_dirty_count(mds, &count)) { + dev_warn(dev, "GPF: could not retrieve dirty count\n"); + return; + } + + cxl_nvd->dirty_shutdowns = count; +} + static int cxl_nvdimm_probe(struct device *dev) { struct cxl_nvdimm *cxl_nvd = to_cxl_nvdimm(dev); @@ -78,6 +139,14 @@ static int cxl_nvdimm_probe(struct device *dev) set_bit(ND_CMD_GET_CONFIG_SIZE, &cmd_mask); set_bit(ND_CMD_GET_CONFIG_DATA, &cmd_mask); set_bit(ND_CMD_SET_CONFIG_DATA, &cmd_mask); + + /* + * Set dirty shutdown now, with the expectation that the device + * clear it upon a successful GPF flow. The exception to this + * is upon Viral detection, per CXL 3.2 section 12.4.2. + */ + cxl_nvdimm_arm_dirty_shutdown_tracking(cxl_nvd); + nvdimm = __nvdimm_create(cxl_nvb->nvdimm_bus, cxl_nvd, cxl_dimm_attribute_groups, flags, cmd_mask, 0, NULL, cxl_nvd->dev_id, @@ -375,6 +444,16 @@ static int cxl_pmem_region_probe(struct device *dev) goto out_nvd; } + if (cxlds->serial == 0) { + /* include missing alongside invalid in this error message. */ + dev_err(dev, "%s: invalid or missing serial number\n", + dev_name(&cxlmd->dev)); + rc = -ENXIO; + goto out_nvd; + } + info[i].serial = cxlds->serial; + info[i].offset = m->start; + m->cxl_nvd = cxl_nvd; mappings[i] = (struct nd_mapping_desc) { .nvdimm = nvdimm, @@ -382,8 +461,6 @@ static int cxl_pmem_region_probe(struct device *dev) .size = m->size, .position = i, }; - info[i].offset = m->start; - info[i].serial = cxlds->serial; } ndr_desc.num_mappings = cxlr_pmem->nr_mappings; ndr_desc.mapping = mappings;
diff --git a/drivers/dma-buf/st-dma-fence.c b/drivers/dma-buf/st-dma-fence.c index cf2ce37..9f80a45 100644 --- a/drivers/dma-buf/st-dma-fence.c +++ b/drivers/dma-buf/st-dma-fence.c
@@ -412,7 +412,7 @@ static int test_wait_timeout(void *arg) err = 0; err_free: - del_timer_sync(&wt.timer); + timer_delete_sync(&wt.timer); destroy_timer_on_stack(&wt.timer); dma_fence_signal(wt.f); dma_fence_put(wt.f);
diff --git a/drivers/dma/imx-dma.c b/drivers/dma/imx-dma.c index de8d707..b96cc0a 100644 --- a/drivers/dma/imx-dma.c +++ b/drivers/dma/imx-dma.c
@@ -324,7 +324,7 @@ static void imxdma_disable_hw(struct imxdma_channel *imxdmac) dev_dbg(imxdma->dev, "%s channel %d\n", __func__, channel); if (imxdma_hw_chain(imxdmac)) - del_timer(&imxdmac->watchdog); + timer_delete(&imxdmac->watchdog); local_irq_save(flags); imx_dmav1_writel(imxdma, imx_dmav1_readl(imxdma, DMA_DIMR) | @@ -454,7 +454,7 @@ static void dma_irq_handle_channel(struct imxdma_channel *imxdmac) } if (imxdma_hw_chain(imxdmac)) { - del_timer(&imxdmac->watchdog); + timer_delete(&imxdmac->watchdog); return; } }
diff --git a/drivers/dma/ioat/dma.c b/drivers/dma/ioat/dma.c index 79d8957..06a813c 100644 --- a/drivers/dma/ioat/dma.c +++ b/drivers/dma/ioat/dma.c
@@ -159,7 +159,7 @@ void ioat_stop(struct ioatdma_chan *ioat_chan) } /* flush inflight timers */ - del_timer_sync(&ioat_chan->timer); + timer_delete_sync(&ioat_chan->timer); /* flush inflight tasklet runs */ tasklet_kill(&ioat_chan->cleanup_task);
diff --git a/drivers/dma/ioat/init.c b/drivers/dma/ioat/init.c index cc9ddd6c..02f68b3 100644 --- a/drivers/dma/ioat/init.c +++ b/drivers/dma/ioat/init.c
@@ -1224,12 +1224,12 @@ static void ioat_shutdown(struct pci_dev *pdev) set_bit(IOAT_CHAN_DOWN, &ioat_chan->state); spin_unlock_bh(&ioat_chan->prep_lock); /* - * Synchronization rule for del_timer_sync(): + * Synchronization rule for timer_delete_sync(): * - The caller must not hold locks which would prevent * completion of the timer's handler. * So prep_lock cannot be held before calling it. */ - del_timer_sync(&ioat_chan->timer); + timer_delete_sync(&ioat_chan->timer); /* this should quiesce then reset */ ioat_reset_hw(ioat_chan);
diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c index b360dca..bd04980 100644 --- a/drivers/firewire/core-cdev.c +++ b/drivers/firewire/core-cdev.c
@@ -1137,10 +1137,7 @@ static int ioctl_queue_iso(struct client *client, union ioctl_arg *arg) unsigned long payload, buffer_end, transmit_header_bytes = 0; u32 control; int count; - struct { - struct fw_iso_packet packet; - u8 header[256]; - } u; + DEFINE_RAW_FLEX(struct fw_iso_packet, u, header, 64); if (ctx == NULL || a->handle != 0) return -EINVAL; @@ -1172,29 +1169,29 @@ static int ioctl_queue_iso(struct client *client, union ioctl_arg *arg) while (p < end) { if (get_user(control, &p->control)) return -EFAULT; - u.packet.payload_length = GET_PAYLOAD_LENGTH(control); - u.packet.interrupt = GET_INTERRUPT(control); - u.packet.skip = GET_SKIP(control); - u.packet.tag = GET_TAG(control); - u.packet.sy = GET_SY(control); - u.packet.header_length = GET_HEADER_LENGTH(control); + u->payload_length = GET_PAYLOAD_LENGTH(control); + u->interrupt = GET_INTERRUPT(control); + u->skip = GET_SKIP(control); + u->tag = GET_TAG(control); + u->sy = GET_SY(control); + u->header_length = GET_HEADER_LENGTH(control); switch (ctx->type) { case FW_ISO_CONTEXT_TRANSMIT: - if (u.packet.header_length & 3) + if (u->header_length & 3) return -EINVAL; - transmit_header_bytes = u.packet.header_length; + transmit_header_bytes = u->header_length; break; case FW_ISO_CONTEXT_RECEIVE: - if (u.packet.header_length == 0 || - u.packet.header_length % ctx->header_size != 0) + if (u->header_length == 0 || + u->header_length % ctx->header_size != 0) return -EINVAL; break; case FW_ISO_CONTEXT_RECEIVE_MULTICHANNEL: - if (u.packet.payload_length == 0 || - u.packet.payload_length & 3) + if (u->payload_length == 0 || + u->payload_length & 3) return -EINVAL; break; } @@ -1204,20 +1201,19 @@ static int ioctl_queue_iso(struct client *client, union ioctl_arg *arg) if (next > end) return -EINVAL; if (copy_from_user - (u.packet.header, p->header, transmit_header_bytes)) + (u->header, p->header, transmit_header_bytes)) return -EFAULT; - if (u.packet.skip && ctx->type == FW_ISO_CONTEXT_TRANSMIT && - u.packet.header_length + u.packet.payload_length > 0) + if (u->skip && ctx->type == FW_ISO_CONTEXT_TRANSMIT && + u->header_length + u->payload_length > 0) return -EINVAL; - if (payload + u.packet.payload_length > buffer_end) + if (payload + u->payload_length > buffer_end) return -EINVAL; - if (fw_iso_context_queue(ctx, &u.packet, - &client->buffer, payload)) + if (fw_iso_context_queue(ctx, u, &client->buffer, payload)) break; p = next; - payload += u.packet.payload_length; + payload += u->payload_length; count++; } fw_iso_context_queue_flush(ctx);
diff --git a/drivers/firewire/core-transaction.c b/drivers/firewire/core-transaction.c index e141d24..b0f9ef6 100644 --- a/drivers/firewire/core-transaction.c +++ b/drivers/firewire/core-transaction.c
@@ -39,7 +39,7 @@ static int try_cancel_split_timeout(struct fw_transaction *t) { if (t->is_split_transaction) - return del_timer(&t->split_timeout_timer); + return timer_delete(&t->split_timeout_timer); else return 1; }
diff --git a/drivers/firmware/cirrus/cs_dsp.c b/drivers/firmware/cirrus/cs_dsp.c index 42433c1..560724c 100644 --- a/drivers/firmware/cirrus/cs_dsp.c +++ b/drivers/firmware/cirrus/cs_dsp.c
@@ -1631,6 +1631,7 @@ static int cs_dsp_load(struct cs_dsp *dsp, const struct firmware *firmware, cs_dsp_debugfs_save_wmfwname(dsp, file); + ret = 0; out_fw: cs_dsp_buf_free(&buf_list); @@ -2338,6 +2339,7 @@ static int cs_dsp_load_coeff(struct cs_dsp *dsp, const struct firmware *firmware cs_dsp_debugfs_save_binname(dsp, file); + ret = 0; out_fw: cs_dsp_buf_free(&buf_list);
diff --git a/drivers/firmware/efi/cper.c b/drivers/firmware/efi/cper.c index b69e68e..9284091 100644 --- a/drivers/firmware/efi/cper.c +++ b/drivers/firmware/efi/cper.c
@@ -24,7 +24,7 @@ #include <linux/bcd.h> #include <acpi/ghes.h> #include <ras/ras_event.h> -#include "cper_cxl.h" +#include <cxl/event.h> /* * CPER record ID need to be unique even after reboot, because record @@ -624,11 +624,11 @@ cper_estatus_print_section(const char *pfx, struct acpi_hest_generic_data *gdata else goto err_section_too_small; } else if (guid_equal(sec_type, &CPER_SEC_CXL_PROT_ERR)) { - struct cper_sec_prot_err *prot_err = acpi_hest_get_payload(gdata); + struct cxl_cper_sec_prot_err *prot_err = acpi_hest_get_payload(gdata); printk("%ssection_type: CXL Protocol Error\n", newpfx); if (gdata->error_data_length >= sizeof(*prot_err)) - cper_print_prot_err(newpfx, prot_err); + cxl_cper_print_prot_err(newpfx, prot_err); else goto err_section_too_small; } else {
diff --git a/drivers/firmware/efi/cper_cxl.c b/drivers/firmware/efi/cper_cxl.c index a55771b..8a7667f 100644 --- a/drivers/firmware/efi/cper_cxl.c +++ b/drivers/firmware/efi/cper_cxl.c
@@ -8,26 +8,7 @@ */ #include <linux/cper.h> -#include "cper_cxl.h" - -#define PROT_ERR_VALID_AGENT_TYPE BIT_ULL(0) -#define PROT_ERR_VALID_AGENT_ADDRESS BIT_ULL(1) -#define PROT_ERR_VALID_DEVICE_ID BIT_ULL(2) -#define PROT_ERR_VALID_SERIAL_NUMBER BIT_ULL(3) -#define PROT_ERR_VALID_CAPABILITY BIT_ULL(4) -#define PROT_ERR_VALID_DVSEC BIT_ULL(5) -#define PROT_ERR_VALID_ERROR_LOG BIT_ULL(6) - -/* CXL RAS Capability Structure, CXL v3.0 sec 8.2.4.16 */ -struct cxl_ras_capability_regs { - u32 uncor_status; - u32 uncor_mask; - u32 uncor_severity; - u32 cor_status; - u32 cor_mask; - u32 cap_control; - u32 header_log[16]; -}; +#include <cxl/event.h> static const char * const prot_err_agent_type_strs[] = { "Restricted CXL Device", @@ -40,22 +21,8 @@ static const char * const prot_err_agent_type_strs[] = { "CXL Upstream Switch Port", }; -/* - * The layout of the enumeration and the values matches CXL Agent Type - * field in the UEFI 2.10 Section N.2.13, - */ -enum { - RCD, /* Restricted CXL Device */ - RCH_DP, /* Restricted CXL Host Downstream Port */ - DEVICE, /* CXL Device */ - LD, /* CXL Logical Device */ - FMLD, /* CXL Fabric Manager managed Logical Device */ - RP, /* CXL Root Port */ - DSP, /* CXL Downstream Switch Port */ - USP, /* CXL Upstream Switch Port */ -}; - -void cper_print_prot_err(const char *pfx, const struct cper_sec_prot_err *prot_err) +void cxl_cper_print_prot_err(const char *pfx, + const struct cxl_cper_sec_prot_err *prot_err) { if (prot_err->valid_bits & PROT_ERR_VALID_AGENT_TYPE) pr_info("%s agent_type: %d, %s\n", pfx, prot_err->agent_type,
diff --git a/drivers/firmware/efi/cper_cxl.h b/drivers/firmware/efi/cper_cxl.h deleted file mode 100644 index 86bfcf7..0000000 --- a/drivers/firmware/efi/cper_cxl.h +++ /dev/null
@@ -1,66 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * UEFI Common Platform Error Record (CPER) support for CXL Section. - * - * Copyright (C) 2022 Advanced Micro Devices, Inc. - * - * Author: Smita Koralahalli <Smita.KoralahalliChannabasappa@amd.com> - */ - -#ifndef LINUX_CPER_CXL_H -#define LINUX_CPER_CXL_H - -/* CXL Protocol Error Section */ -#define CPER_SEC_CXL_PROT_ERR \ - GUID_INIT(0x80B9EFB4, 0x52B5, 0x4DE3, 0xA7, 0x77, 0x68, 0x78, \ - 0x4B, 0x77, 0x10, 0x48) - -#pragma pack(1) - -/* Compute Express Link Protocol Error Section, UEFI v2.10 sec N.2.13 */ -struct cper_sec_prot_err { - u64 valid_bits; - u8 agent_type; - u8 reserved[7]; - - /* - * Except for RCH Downstream Port, all the remaining CXL Agent - * types are uniquely identified by the PCIe compatible SBDF number. - */ - union { - u64 rcrb_base_addr; - struct { - u8 function; - u8 device; - u8 bus; - u16 segment; - u8 reserved_1[3]; - }; - } agent_addr; - - struct { - u16 vendor_id; - u16 device_id; - u16 subsystem_vendor_id; - u16 subsystem_id; - u8 class_code[2]; - u16 slot; - u8 reserved_1[4]; - } device_id; - - struct { - u32 lower_dw; - u32 upper_dw; - } dev_serial_num; - - u8 capability[60]; - u16 dvsec_len; - u16 err_len; - u8 reserved_2[4]; -}; - -#pragma pack() - -void cper_print_prot_err(const char *pfx, const struct cper_sec_prot_err *prot_err); - -#endif //__CPER_CXL_
diff --git a/drivers/firmware/psci/psci_checker.c b/drivers/firmware/psci/psci_checker.c index 116eb465..b662b7e 100644 --- a/drivers/firmware/psci/psci_checker.c +++ b/drivers/firmware/psci/psci_checker.c
@@ -342,7 +342,7 @@ static int suspend_test_thread(void *arg) * Disable the timer to make sure that the timer will not trigger * later. */ - del_timer(&wakeup_timer); + timer_delete(&wakeup_timer); destroy_timer_on_stack(&wakeup_timer); if (atomic_dec_return_relaxed(&nb_active_threads) == 0)
diff --git a/drivers/gpu/drm/adp/adp_drv.c b/drivers/gpu/drm/adp/adp_drv.c index 0eeb9e5..c98c647 100644 --- a/drivers/gpu/drm/adp/adp_drv.c +++ b/drivers/gpu/drm/adp/adp_drv.c
@@ -232,9 +232,9 @@ static struct drm_plane *adp_plane_new(struct adp_drv_private *adp) ALL_CRTCS, &adp_plane_funcs, plane_formats, ARRAY_SIZE(plane_formats), NULL, DRM_PLANE_TYPE_PRIMARY, "plane"); - if (!plane) { + if (IS_ERR(plane)) { drm_err(drm, "failed to allocate plane"); - return ERR_PTR(-ENOMEM); + return plane; } drm_plane_helper_add(plane, &adp_plane_helper_funcs);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_aca.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_aca.c index dc47f5f..b4ad163 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_aca.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_aca.c
@@ -195,6 +195,10 @@ static bool aca_bank_is_valid(struct aca_handle *handle, struct aca_bank *bank, { const struct aca_bank_ops *bank_ops = handle->bank_ops; + /* Parse all deferred errors with UMC aca handle */ + if (ACA_BANK_ERR_IS_DEFFERED(bank)) + return handle->hwip == ACA_HWIP_TYPE_UMC; + if (!aca_bank_hwip_is_matched(bank, handle->hwip)) return false;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_aca.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_aca.h index 6b180f1..38c8889 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_aca.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_aca.h
@@ -80,14 +80,6 @@ struct ras_query_context; (ACA_REG__STATUS__POISON((bank)->regs[ACA_REG_IDX_STATUS]) || \ ACA_REG__STATUS__DEFERRED((bank)->regs[ACA_REG_IDX_STATUS])) -#define ACA_BANK_ERR_CE_DE_DECODE(bank) \ - (ACA_BANK_ERR_IS_DEFFERED(bank) ? ACA_ERROR_TYPE_DEFERRED : \ - ACA_ERROR_TYPE_CE) - -#define ACA_BANK_ERR_UE_DE_DECODE(bank) \ - (ACA_BANK_ERR_IS_DEFFERED(bank) ? ACA_ERROR_TYPE_DEFERRED : \ - ACA_ERROR_TYPE_UE) - enum aca_reg_idx { ACA_REG_IDX_CTL = 0, ACA_REG_IDX_STATUS = 1,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c index 75fcc52..00e9641 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c
@@ -447,6 +447,13 @@ static bool amdgpu_get_bios_apu(struct amdgpu_device *adev) return true; } +static bool amdgpu_prefer_rom_resource(struct amdgpu_device *adev) +{ + struct resource *res = &adev->pdev->resource[PCI_ROM_RESOURCE]; + + return (res->flags & IORESOURCE_ROM_SHADOW); +} + static bool amdgpu_get_bios_dgpu(struct amdgpu_device *adev) { if (amdgpu_atrm_get_bios(adev)) { @@ -465,14 +472,27 @@ static bool amdgpu_get_bios_dgpu(struct amdgpu_device *adev) goto success; } - if (amdgpu_read_platform_bios(adev)) { - dev_info(adev->dev, "Fetched VBIOS from platform\n"); - goto success; - } + if (amdgpu_prefer_rom_resource(adev)) { + if (amdgpu_read_bios(adev)) { + dev_info(adev->dev, "Fetched VBIOS from ROM BAR\n"); + goto success; + } - if (amdgpu_read_bios(adev)) { - dev_info(adev->dev, "Fetched VBIOS from ROM BAR\n"); - goto success; + if (amdgpu_read_platform_bios(adev)) { + dev_info(adev->dev, "Fetched VBIOS from platform\n"); + goto success; + } + + } else { + if (amdgpu_read_platform_bios(adev)) { + dev_info(adev->dev, "Fetched VBIOS from platform\n"); + goto success; + } + + if (amdgpu_read_bios(adev)) { + dev_info(adev->dev, "Fetched VBIOS from ROM BAR\n"); + goto success; + } } if (amdgpu_read_bios_from_rom(adev)) {
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 23cfce5..26bf896 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
@@ -1809,7 +1809,6 @@ static const u16 amdgpu_unsupported_pciidlist[] = { }; static const struct pci_device_id pciidlist[] = { -#ifdef CONFIG_DRM_AMDGPU_SI {0x1002, 0x6780, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI}, {0x1002, 0x6784, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI}, {0x1002, 0x6788, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI}, @@ -1882,8 +1881,6 @@ static const struct pci_device_id pciidlist[] = { {0x1002, 0x6665, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HAINAN|AMD_IS_MOBILITY}, {0x1002, 0x6667, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HAINAN|AMD_IS_MOBILITY}, {0x1002, 0x666F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HAINAN|AMD_IS_MOBILITY}, -#endif -#ifdef CONFIG_DRM_AMDGPU_CIK /* Kaveri */ {0x1002, 0x1304, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KAVERI|AMD_IS_MOBILITY|AMD_IS_APU}, {0x1002, 0x1305, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KAVERI|AMD_IS_APU}, @@ -1966,7 +1963,6 @@ static const struct pci_device_id pciidlist[] = { {0x1002, 0x985D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|AMD_IS_MOBILITY|AMD_IS_APU}, {0x1002, 0x985E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|AMD_IS_MOBILITY|AMD_IS_APU}, {0x1002, 0x985F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|AMD_IS_MOBILITY|AMD_IS_APU}, -#endif /* topaz */ {0x1002, 0x6900, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ}, {0x1002, 0x6901, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ}, @@ -2313,14 +2309,14 @@ static int amdgpu_pci_probe(struct pci_dev *pdev, return -ENOTSUPP; } + switch (flags & AMD_ASIC_MASK) { + case CHIP_TAHITI: + case CHIP_PITCAIRN: + case CHIP_VERDE: + case CHIP_OLAND: + case CHIP_HAINAN: #ifdef CONFIG_DRM_AMDGPU_SI - if (!amdgpu_si_support) { - switch (flags & AMD_ASIC_MASK) { - case CHIP_TAHITI: - case CHIP_PITCAIRN: - case CHIP_VERDE: - case CHIP_OLAND: - case CHIP_HAINAN: + if (!amdgpu_si_support) { dev_info(&pdev->dev, "SI support provided by radeon.\n"); dev_info(&pdev->dev, @@ -2328,16 +2324,18 @@ static int amdgpu_pci_probe(struct pci_dev *pdev, ); return -ENODEV; } - } + break; +#else + dev_info(&pdev->dev, "amdgpu is built without SI support.\n"); + return -ENODEV; #endif + case CHIP_KAVERI: + case CHIP_BONAIRE: + case CHIP_HAWAII: + case CHIP_KABINI: + case CHIP_MULLINS: #ifdef CONFIG_DRM_AMDGPU_CIK - if (!amdgpu_cik_support) { - switch (flags & AMD_ASIC_MASK) { - case CHIP_KAVERI: - case CHIP_BONAIRE: - case CHIP_HAWAII: - case CHIP_KABINI: - case CHIP_MULLINS: + if (!amdgpu_cik_support) { dev_info(&pdev->dev, "CIK support provided by radeon.\n"); dev_info(&pdev->dev, @@ -2345,8 +2343,14 @@ static int amdgpu_pci_probe(struct pci_dev *pdev, ); return -ENODEV; } - } + break; +#else + dev_info(&pdev->dev, "amdgpu is built without CIK support.\n"); + return -ENODEV; #endif + default: + break; + } adev = devm_drm_dev_alloc(&pdev->dev, &amdgpu_kms_driver, typeof(*adev), ddev); if (IS_ERR(adev))
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c index 2f24a6a..5f5c00a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c
@@ -280,7 +280,7 @@ bool amdgpu_fence_process(struct amdgpu_ring *ring) } while (atomic_cmpxchg(&drv->last_seq, last_seq, seq) != last_seq); - if (del_timer(&ring->fence_drv.fallback_timer) && + if (timer_delete(&ring->fence_drv.fallback_timer) && seq != ring->fence_drv.sync_seq) amdgpu_fence_schedule_fallback(ring); @@ -618,7 +618,7 @@ void amdgpu_fence_driver_hw_fini(struct amdgpu_device *adev) amdgpu_irq_put(adev, ring->fence_drv.irq_src, ring->fence_drv.irq_type); - del_timer_sync(&ring->fence_drv.fallback_timer); + timer_delete_sync(&ring->fence_drv.fallback_timer); } }
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c index 85f7740..fb212f0 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c
@@ -1239,7 +1239,7 @@ void amdgpu_mes_remove_ring(struct amdgpu_device *adev, return; amdgpu_mes_remove_hw_queue(adev, ring->hw_queue_id); - del_timer_sync(&ring->fence_drv.fallback_timer); + timer_delete_sync(&ring->fence_drv.fallback_timer); amdgpu_ring_fini(ring); kfree(ring); }
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index 68685ac..443409d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
@@ -77,6 +77,7 @@ const char *ras_block_string[] = { "jpeg", "ih", "mpio", + "mmsch", }; const char *ras_mca_block_string[] = {
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h index 764e9fa..927d6bf 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h
@@ -98,6 +98,7 @@ enum amdgpu_ras_block { AMDGPU_RAS_BLOCK__JPEG, AMDGPU_RAS_BLOCK__IH, AMDGPU_RAS_BLOCK__MPIO, + AMDGPU_RAS_BLOCK__MMSCH, AMDGPU_RAS_BLOCK__LAST, AMDGPU_RAS_BLOCK__ANY = -1 @@ -795,6 +796,12 @@ amdgpu_ras_block_to_ta(enum amdgpu_ras_block block) { return TA_RAS_BLOCK__VCN; case AMDGPU_RAS_BLOCK__JPEG: return TA_RAS_BLOCK__JPEG; + case AMDGPU_RAS_BLOCK__IH: + return TA_RAS_BLOCK__IH; + case AMDGPU_RAS_BLOCK__MPIO: + return TA_RAS_BLOCK__MPIO; + case AMDGPU_RAS_BLOCK__MMSCH: + return TA_RAS_BLOCK__MMSCH; default: WARN_ONCE(1, "RAS ERROR: unexpected block id %d\n", block); return TA_RAS_BLOCK__UMC;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c index d55c8b7..59acdbf 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c
@@ -608,59 +608,17 @@ static ssize_t amdgpu_debugfs_mqd_read(struct file *f, char __user *buf, size_t size, loff_t *pos) { struct amdgpu_ring *ring = file_inode(f)->i_private; - volatile u32 *mqd; - u32 *kbuf; - int r, i; - uint32_t value, result; + ssize_t bytes = min_t(ssize_t, ring->mqd_size - *pos, size); + void *from = ((u8 *)ring->mqd_ptr) + *pos; - if (*pos & 3 || size & 3) - return -EINVAL; + if (*pos > ring->mqd_size) + return 0; - kbuf = kmalloc(ring->mqd_size, GFP_KERNEL); - if (!kbuf) - return -ENOMEM; + if (copy_to_user(buf, from, bytes)) + return -EFAULT; - r = amdgpu_bo_reserve(ring->mqd_obj, false); - if (unlikely(r != 0)) - goto err_free; - - r = amdgpu_bo_kmap(ring->mqd_obj, (void **)&mqd); - if (r) - goto err_unreserve; - - /* - * Copy to local buffer to avoid put_user(), which might fault - * and acquire mmap_sem, under reservation_ww_class_mutex. - */ - for (i = 0; i < ring->mqd_size/sizeof(u32); i++) - kbuf[i] = mqd[i]; - - amdgpu_bo_kunmap(ring->mqd_obj); - amdgpu_bo_unreserve(ring->mqd_obj); - - result = 0; - while (size) { - if (*pos >= ring->mqd_size) - break; - - value = kbuf[*pos/4]; - r = put_user(value, (uint32_t *)buf); - if (r) - goto err_free; - buf += 4; - result += 4; - size -= 4; - *pos += 4; - } - - kfree(kbuf); - return result; - -err_unreserve: - amdgpu_bo_unreserve(ring->mqd_obj); -err_free: - kfree(kbuf); - return r; + *pos += bytes; + return bytes; } static const struct file_operations amdgpu_debugfs_mqd_fops = {
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring_mux.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring_mux.c index 1c66da1..03ed146 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring_mux.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring_mux.c
@@ -124,7 +124,7 @@ static void amdgpu_mux_resubmit_chunks(struct amdgpu_ring_mux *mux) } } - del_timer(&mux->resubmit_timer); + timer_delete(&mux->resubmit_timer); mux->s_resubmit = false; }
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c index 6029a79..4774244 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c
@@ -1172,7 +1172,7 @@ static int xgmi_v6_4_0_aca_bank_parser(struct aca_handle *handle, struct aca_ban break; case ACA_SMU_TYPE_CE: count = ext_error_code == 6 ? count : 0ULL; - bank->aca_err_type = ACA_BANK_ERR_CE_DE_DECODE(bank); + bank->aca_err_type = ACA_ERROR_TYPE_CE; ret = aca_error_cache_log_bank_error(handle, &info, bank->aca_err_type, count); break; default:
diff --git a/drivers/gpu/drm/amd/amdgpu/aqua_vanjaram.c b/drivers/gpu/drm/amd/amdgpu/aqua_vanjaram.c index 3c07517..ae07198 100644 --- a/drivers/gpu/drm/amd/amdgpu/aqua_vanjaram.c +++ b/drivers/gpu/drm/amd/amdgpu/aqua_vanjaram.c
@@ -473,7 +473,8 @@ static int aqua_vanjaram_get_xcp_res_info(struct amdgpu_xcp_mgr *xcp_mgr, break; case AMDGPU_DPX_PARTITION_MODE: num_xcp = 2; - nps_modes = BIT(AMDGPU_NPS1_PARTITION_MODE); + nps_modes = BIT(AMDGPU_NPS1_PARTITION_MODE) | + BIT(AMDGPU_NPS2_PARTITION_MODE); break; case AMDGPU_TPX_PARTITION_MODE: num_xcp = 3;
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c index 6d514ef..a63ce74 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
@@ -6851,22 +6851,9 @@ static int gfx_v10_0_kgq_init_queue(struct amdgpu_ring *ring, bool reset) static int gfx_v10_0_cp_async_gfx_ring_resume(struct amdgpu_device *adev) { int r, i; - struct amdgpu_ring *ring; for (i = 0; i < adev->gfx.num_gfx_rings; i++) { - ring = &adev->gfx.gfx_ring[i]; - - r = amdgpu_bo_reserve(ring->mqd_obj, false); - if (unlikely(r != 0)) - return r; - - r = amdgpu_bo_kmap(ring->mqd_obj, (void **)&ring->mqd_ptr); - if (!r) { - r = gfx_v10_0_kgq_init_queue(ring, false); - amdgpu_bo_kunmap(ring->mqd_obj); - ring->mqd_ptr = NULL; - } - amdgpu_bo_unreserve(ring->mqd_obj); + r = gfx_v10_0_kgq_init_queue(&adev->gfx.gfx_ring[i], false); if (r) return r; } @@ -7173,55 +7160,24 @@ static int gfx_v10_0_kcq_init_queue(struct amdgpu_ring *ring, bool restore) static int gfx_v10_0_kiq_resume(struct amdgpu_device *adev) { - struct amdgpu_ring *ring; - int r; - - ring = &adev->gfx.kiq[0].ring; - - r = amdgpu_bo_reserve(ring->mqd_obj, false); - if (unlikely(r != 0)) - return r; - - r = amdgpu_bo_kmap(ring->mqd_obj, (void **)&ring->mqd_ptr); - if (unlikely(r != 0)) { - amdgpu_bo_unreserve(ring->mqd_obj); - return r; - } - - gfx_v10_0_kiq_init_queue(ring); - amdgpu_bo_kunmap(ring->mqd_obj); - ring->mqd_ptr = NULL; - amdgpu_bo_unreserve(ring->mqd_obj); + gfx_v10_0_kiq_init_queue(&adev->gfx.kiq[0].ring); return 0; } static int gfx_v10_0_kcq_resume(struct amdgpu_device *adev) { - struct amdgpu_ring *ring = NULL; - int r = 0, i; + int i, r; gfx_v10_0_cp_compute_enable(adev, true); for (i = 0; i < adev->gfx.num_compute_rings; i++) { - ring = &adev->gfx.compute_ring[i]; - - r = amdgpu_bo_reserve(ring->mqd_obj, false); - if (unlikely(r != 0)) - goto done; - r = amdgpu_bo_kmap(ring->mqd_obj, (void **)&ring->mqd_ptr); - if (!r) { - r = gfx_v10_0_kcq_init_queue(ring, false); - amdgpu_bo_kunmap(ring->mqd_obj); - ring->mqd_ptr = NULL; - } - amdgpu_bo_unreserve(ring->mqd_obj); + r = gfx_v10_0_kcq_init_queue(&adev->gfx.compute_ring[i], + false); if (r) - goto done; + return r; } - r = amdgpu_gfx_enable_kcq(adev, 0); -done: - return r; + return amdgpu_gfx_enable_kcq(adev, 0); } static int gfx_v10_0_cp_resume(struct amdgpu_device *adev) @@ -9579,20 +9535,9 @@ static int gfx_v10_0_reset_kgq(struct amdgpu_ring *ring, unsigned int vmid) if (r) return r; - r = amdgpu_bo_reserve(ring->mqd_obj, false); - if (unlikely(r != 0)) { - DRM_ERROR("fail to resv mqd_obj\n"); - return r; - } - r = amdgpu_bo_kmap(ring->mqd_obj, (void **)&ring->mqd_ptr); - if (!r) { - r = gfx_v10_0_kgq_init_queue(ring, true); - amdgpu_bo_kunmap(ring->mqd_obj); - ring->mqd_ptr = NULL; - } - amdgpu_bo_unreserve(ring->mqd_obj); + r = gfx_v10_0_kgq_init_queue(ring, true); if (r) { - DRM_ERROR("fail to unresv mqd_obj\n"); + DRM_ERROR("fail to init kgq\n"); return r; } @@ -9649,20 +9594,9 @@ static int gfx_v10_0_reset_kcq(struct amdgpu_ring *ring, return r; } - r = amdgpu_bo_reserve(ring->mqd_obj, false); - if (unlikely(r != 0)) { - dev_err(adev->dev, "fail to resv mqd_obj\n"); - return r; - } - r = amdgpu_bo_kmap(ring->mqd_obj, (void **)&ring->mqd_ptr); - if (!r) { - r = gfx_v10_0_kcq_init_queue(ring, true); - amdgpu_bo_kunmap(ring->mqd_obj); - ring->mqd_ptr = NULL; - } - amdgpu_bo_unreserve(ring->mqd_obj); + r = gfx_v10_0_kcq_init_queue(ring, true); if (r) { - dev_err(adev->dev, "fail to unresv mqd_obj\n"); + dev_err(adev->dev, "fail to init kcq\n"); return r; }
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c index d8772cd..d57db42 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
@@ -1581,7 +1581,7 @@ static int gfx_v11_0_sw_init(struct amdgpu_ip_block *ip_block) adev->gfx.me.num_me = 1; adev->gfx.me.num_pipe_per_me = 1; adev->gfx.me.num_queue_per_pipe = 1; - adev->gfx.mec.num_mec = 2; + adev->gfx.mec.num_mec = 1; adev->gfx.mec.num_pipe_per_mec = 4; adev->gfx.mec.num_queue_per_pipe = 4; break; @@ -4115,22 +4115,9 @@ static int gfx_v11_0_kgq_init_queue(struct amdgpu_ring *ring, bool reset) static int gfx_v11_0_cp_async_gfx_ring_resume(struct amdgpu_device *adev) { int r, i; - struct amdgpu_ring *ring; for (i = 0; i < adev->gfx.num_gfx_rings; i++) { - ring = &adev->gfx.gfx_ring[i]; - - r = amdgpu_bo_reserve(ring->mqd_obj, false); - if (unlikely(r != 0)) - return r; - - r = amdgpu_bo_kmap(ring->mqd_obj, (void **)&ring->mqd_ptr); - if (!r) { - r = gfx_v11_0_kgq_init_queue(ring, false); - amdgpu_bo_kunmap(ring->mqd_obj); - ring->mqd_ptr = NULL; - } - amdgpu_bo_unreserve(ring->mqd_obj); + r = gfx_v11_0_kgq_init_queue(&adev->gfx.gfx_ring[i], false); if (r) return r; } @@ -4452,57 +4439,24 @@ static int gfx_v11_0_kcq_init_queue(struct amdgpu_ring *ring, bool reset) static int gfx_v11_0_kiq_resume(struct amdgpu_device *adev) { - struct amdgpu_ring *ring; - int r; - - ring = &adev->gfx.kiq[0].ring; - - r = amdgpu_bo_reserve(ring->mqd_obj, false); - if (unlikely(r != 0)) - return r; - - r = amdgpu_bo_kmap(ring->mqd_obj, (void **)&ring->mqd_ptr); - if (unlikely(r != 0)) { - amdgpu_bo_unreserve(ring->mqd_obj); - return r; - } - - gfx_v11_0_kiq_init_queue(ring); - amdgpu_bo_kunmap(ring->mqd_obj); - ring->mqd_ptr = NULL; - amdgpu_bo_unreserve(ring->mqd_obj); - ring->sched.ready = true; + gfx_v11_0_kiq_init_queue(&adev->gfx.kiq[0].ring); return 0; } static int gfx_v11_0_kcq_resume(struct amdgpu_device *adev) { - struct amdgpu_ring *ring = NULL; - int r = 0, i; + int i, r; if (!amdgpu_async_gfx_ring) gfx_v11_0_cp_compute_enable(adev, true); for (i = 0; i < adev->gfx.num_compute_rings; i++) { - ring = &adev->gfx.compute_ring[i]; - - r = amdgpu_bo_reserve(ring->mqd_obj, false); - if (unlikely(r != 0)) - goto done; - r = amdgpu_bo_kmap(ring->mqd_obj, (void **)&ring->mqd_ptr); - if (!r) { - r = gfx_v11_0_kcq_init_queue(ring, false); - amdgpu_bo_kunmap(ring->mqd_obj); - ring->mqd_ptr = NULL; - } - amdgpu_bo_unreserve(ring->mqd_obj); + r = gfx_v11_0_kcq_init_queue(&adev->gfx.compute_ring[i], false); if (r) - goto done; + return r; } - r = amdgpu_gfx_enable_kcq(adev, 0); -done: - return r; + return amdgpu_gfx_enable_kcq(adev, 0); } static int gfx_v11_0_cp_resume(struct amdgpu_device *adev) @@ -6667,20 +6621,9 @@ static int gfx_v11_0_reset_kgq(struct amdgpu_ring *ring, unsigned int vmid) if (r) return r; - r = amdgpu_bo_reserve(ring->mqd_obj, false); - if (unlikely(r != 0)) { - dev_err(adev->dev, "fail to resv mqd_obj\n"); - return r; - } - r = amdgpu_bo_kmap(ring->mqd_obj, (void **)&ring->mqd_ptr); - if (!r) { - r = gfx_v11_0_kgq_init_queue(ring, true); - amdgpu_bo_kunmap(ring->mqd_obj); - ring->mqd_ptr = NULL; - } - amdgpu_bo_unreserve(ring->mqd_obj); + r = gfx_v11_0_kgq_init_queue(ring, true); if (r) { - dev_err(adev->dev, "fail to unresv mqd_obj\n"); + dev_err(adev->dev, "failed to init kgq\n"); return r; } @@ -6707,20 +6650,9 @@ static int gfx_v11_0_reset_kcq(struct amdgpu_ring *ring, unsigned int vmid) return r; } - r = amdgpu_bo_reserve(ring->mqd_obj, false); - if (unlikely(r != 0)) { - dev_err(adev->dev, "fail to resv mqd_obj\n"); - return r; - } - r = amdgpu_bo_kmap(ring->mqd_obj, (void **)&ring->mqd_ptr); - if (!r) { - r = gfx_v11_0_kcq_init_queue(ring, true); - amdgpu_bo_kunmap(ring->mqd_obj); - ring->mqd_ptr = NULL; - } - amdgpu_bo_unreserve(ring->mqd_obj); + r = gfx_v11_0_kcq_init_queue(ring, true); if (r) { - dev_err(adev->dev, "fail to unresv mqd_obj\n"); + dev_err(adev->dev, "fail to init kcq\n"); return r; } r = amdgpu_mes_map_legacy_queue(adev, ring);
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c index dceb5ad..e7b58e4 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c
@@ -1355,7 +1355,7 @@ static int gfx_v12_0_sw_init(struct amdgpu_ip_block *ip_block) adev->gfx.me.num_me = 1; adev->gfx.me.num_pipe_per_me = 1; adev->gfx.me.num_queue_per_pipe = 1; - adev->gfx.mec.num_mec = 2; + adev->gfx.mec.num_mec = 1; adev->gfx.mec.num_pipe_per_mec = 2; adev->gfx.mec.num_queue_per_pipe = 4; break; @@ -3001,37 +3001,19 @@ static int gfx_v12_0_kgq_init_queue(struct amdgpu_ring *ring, bool reset) static int gfx_v12_0_cp_async_gfx_ring_resume(struct amdgpu_device *adev) { - int r, i; - struct amdgpu_ring *ring; + int i, r; for (i = 0; i < adev->gfx.num_gfx_rings; i++) { - ring = &adev->gfx.gfx_ring[i]; - - r = amdgpu_bo_reserve(ring->mqd_obj, false); - if (unlikely(r != 0)) - goto done; - - r = amdgpu_bo_kmap(ring->mqd_obj, (void **)&ring->mqd_ptr); - if (!r) { - r = gfx_v12_0_kgq_init_queue(ring, false); - amdgpu_bo_kunmap(ring->mqd_obj); - ring->mqd_ptr = NULL; - } - amdgpu_bo_unreserve(ring->mqd_obj); + r = gfx_v12_0_kgq_init_queue(&adev->gfx.gfx_ring[i], false); if (r) - goto done; + return r; } r = amdgpu_gfx_enable_kgq(adev, 0); if (r) - goto done; + return r; - r = gfx_v12_0_cp_gfx_start(adev); - if (r) - goto done; - -done: - return r; + return gfx_v12_0_cp_gfx_start(adev); } static int gfx_v12_0_compute_mqd_init(struct amdgpu_device *adev, void *m, @@ -3344,57 +3326,25 @@ static int gfx_v12_0_kcq_init_queue(struct amdgpu_ring *ring, bool reset) static int gfx_v12_0_kiq_resume(struct amdgpu_device *adev) { - struct amdgpu_ring *ring; - int r; - - ring = &adev->gfx.kiq[0].ring; - - r = amdgpu_bo_reserve(ring->mqd_obj, false); - if (unlikely(r != 0)) - return r; - - r = amdgpu_bo_kmap(ring->mqd_obj, (void **)&ring->mqd_ptr); - if (unlikely(r != 0)) { - amdgpu_bo_unreserve(ring->mqd_obj); - return r; - } - - gfx_v12_0_kiq_init_queue(ring); - amdgpu_bo_kunmap(ring->mqd_obj); - ring->mqd_ptr = NULL; - amdgpu_bo_unreserve(ring->mqd_obj); - ring->sched.ready = true; + gfx_v12_0_kiq_init_queue(&adev->gfx.kiq[0].ring); + adev->gfx.kiq[0].ring.sched.ready = true; return 0; } static int gfx_v12_0_kcq_resume(struct amdgpu_device *adev) { - struct amdgpu_ring *ring = NULL; - int r = 0, i; + int i, r; if (!amdgpu_async_gfx_ring) gfx_v12_0_cp_compute_enable(adev, true); for (i = 0; i < adev->gfx.num_compute_rings; i++) { - ring = &adev->gfx.compute_ring[i]; - - r = amdgpu_bo_reserve(ring->mqd_obj, false); - if (unlikely(r != 0)) - goto done; - r = amdgpu_bo_kmap(ring->mqd_obj, (void **)&ring->mqd_ptr); - if (!r) { - r = gfx_v12_0_kcq_init_queue(ring, false); - amdgpu_bo_kunmap(ring->mqd_obj); - ring->mqd_ptr = NULL; - } - amdgpu_bo_unreserve(ring->mqd_obj); + r = gfx_v12_0_kcq_init_queue(&adev->gfx.compute_ring[i], false); if (r) - goto done; + return r; } - r = amdgpu_gfx_enable_kcq(adev, 0); -done: - return r; + return amdgpu_gfx_enable_kcq(adev, 0); } static int gfx_v12_0_cp_resume(struct amdgpu_device *adev) @@ -5224,20 +5174,9 @@ static int gfx_v12_0_reset_kgq(struct amdgpu_ring *ring, unsigned int vmid) return r; } - r = amdgpu_bo_reserve(ring->mqd_obj, false); - if (unlikely(r != 0)) { - dev_err(adev->dev, "fail to resv mqd_obj\n"); - return r; - } - r = amdgpu_bo_kmap(ring->mqd_obj, (void **)&ring->mqd_ptr); - if (!r) { - r = gfx_v12_0_kgq_init_queue(ring, true); - amdgpu_bo_kunmap(ring->mqd_obj); - ring->mqd_ptr = NULL; - } - amdgpu_bo_unreserve(ring->mqd_obj); + r = gfx_v12_0_kgq_init_queue(ring, true); if (r) { - DRM_ERROR("fail to unresv mqd_obj\n"); + dev_err(adev->dev, "failed to init kgq\n"); return r; } @@ -5264,20 +5203,9 @@ static int gfx_v12_0_reset_kcq(struct amdgpu_ring *ring, unsigned int vmid) return r; } - r = amdgpu_bo_reserve(ring->mqd_obj, false); - if (unlikely(r != 0)) { - DRM_ERROR("fail to resv mqd_obj\n"); - return r; - } - r = amdgpu_bo_kmap(ring->mqd_obj, (void **)&ring->mqd_ptr); - if (!r) { - r = gfx_v12_0_kcq_init_queue(ring, true); - amdgpu_bo_kunmap(ring->mqd_obj); - ring->mqd_ptr = NULL; - } - amdgpu_bo_unreserve(ring->mqd_obj); + r = gfx_v12_0_kcq_init_queue(ring, true); if (r) { - DRM_ERROR("fail to unresv mqd_obj\n"); + dev_err(adev->dev, "failed to init kcq\n"); return r; } r = amdgpu_mes_map_legacy_queue(adev, ring);
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c index d116a2e..bfedd48 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
@@ -4683,60 +4683,25 @@ static void gfx_v8_0_set_mec_doorbell_range(struct amdgpu_device *adev) static int gfx_v8_0_kiq_resume(struct amdgpu_device *adev) { - struct amdgpu_ring *ring; - int r; - - ring = &adev->gfx.kiq[0].ring; - - r = amdgpu_bo_reserve(ring->mqd_obj, false); - if (unlikely(r != 0)) - return r; - - r = amdgpu_bo_kmap(ring->mqd_obj, &ring->mqd_ptr); - if (unlikely(r != 0)) { - amdgpu_bo_unreserve(ring->mqd_obj); - return r; - } - - gfx_v8_0_kiq_init_queue(ring); - amdgpu_bo_kunmap(ring->mqd_obj); - ring->mqd_ptr = NULL; - amdgpu_bo_unreserve(ring->mqd_obj); + gfx_v8_0_kiq_init_queue(&adev->gfx.kiq[0].ring); return 0; } static int gfx_v8_0_kcq_resume(struct amdgpu_device *adev) { - struct amdgpu_ring *ring = NULL; - int r = 0, i; + int i, r; gfx_v8_0_cp_compute_enable(adev, true); for (i = 0; i < adev->gfx.num_compute_rings; i++) { - ring = &adev->gfx.compute_ring[i]; - - r = amdgpu_bo_reserve(ring->mqd_obj, false); - if (unlikely(r != 0)) - goto done; - r = amdgpu_bo_kmap(ring->mqd_obj, &ring->mqd_ptr); - if (!r) { - r = gfx_v8_0_kcq_init_queue(ring); - amdgpu_bo_kunmap(ring->mqd_obj); - ring->mqd_ptr = NULL; - } - amdgpu_bo_unreserve(ring->mqd_obj); + r = gfx_v8_0_kcq_init_queue(&adev->gfx.compute_ring[i]); if (r) - goto done; + return r; } gfx_v8_0_set_mec_doorbell_range(adev); - r = gfx_v8_0_kiq_kcq_enable(adev); - if (r) - goto done; - -done: - return r; + return gfx_v8_0_kiq_kcq_enable(adev); } static int gfx_v8_0_cp_test_all_rings(struct amdgpu_device *adev)
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c index d345285..d7db4cb 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
@@ -1269,6 +1269,7 @@ static void gfx_v9_0_check_fw_write_wait(struct amdgpu_device *adev) adev->gfx.mec_fw_write_wait = false; if ((amdgpu_ip_version(adev, GC_HWIP, 0) != IP_VERSION(9, 4, 1)) && + (amdgpu_ip_version(adev, GC_HWIP, 0) != IP_VERSION(9, 4, 2)) && ((adev->gfx.mec_fw_version < 0x000001a5) || (adev->gfx.mec_feature_version < 46) || (adev->gfx.pfp_fw_version < 0x000000b7) || @@ -3890,55 +3891,23 @@ static int gfx_v9_0_kcq_init_queue(struct amdgpu_ring *ring, bool restore) static int gfx_v9_0_kiq_resume(struct amdgpu_device *adev) { - struct amdgpu_ring *ring; - int r; - - ring = &adev->gfx.kiq[0].ring; - - r = amdgpu_bo_reserve(ring->mqd_obj, false); - if (unlikely(r != 0)) - return r; - - r = amdgpu_bo_kmap(ring->mqd_obj, (void **)&ring->mqd_ptr); - if (unlikely(r != 0)) { - amdgpu_bo_unreserve(ring->mqd_obj); - return r; - } - - gfx_v9_0_kiq_init_queue(ring); - amdgpu_bo_kunmap(ring->mqd_obj); - ring->mqd_ptr = NULL; - amdgpu_bo_unreserve(ring->mqd_obj); + gfx_v9_0_kiq_init_queue(&adev->gfx.kiq[0].ring); return 0; } static int gfx_v9_0_kcq_resume(struct amdgpu_device *adev) { - struct amdgpu_ring *ring = NULL; - int r = 0, i; + int i, r; gfx_v9_0_cp_compute_enable(adev, true); for (i = 0; i < adev->gfx.num_compute_rings; i++) { - ring = &adev->gfx.compute_ring[i]; - - r = amdgpu_bo_reserve(ring->mqd_obj, false); - if (unlikely(r != 0)) - goto done; - r = amdgpu_bo_kmap(ring->mqd_obj, (void **)&ring->mqd_ptr); - if (!r) { - r = gfx_v9_0_kcq_init_queue(ring, false); - amdgpu_bo_kunmap(ring->mqd_obj); - ring->mqd_ptr = NULL; - } - amdgpu_bo_unreserve(ring->mqd_obj); + r = gfx_v9_0_kcq_init_queue(&adev->gfx.compute_ring[i], false); if (r) - goto done; + return r; } - r = amdgpu_gfx_enable_kcq(adev, 0); -done: - return r; + return amdgpu_gfx_enable_kcq(adev, 0); } static int gfx_v9_0_cp_resume(struct amdgpu_device *adev) @@ -7319,20 +7288,9 @@ static int gfx_v9_0_reset_kcq(struct amdgpu_ring *ring, return r; } - r = amdgpu_bo_reserve(ring->mqd_obj, false); - if (unlikely(r != 0)){ - dev_err(adev->dev, "fail to resv mqd_obj\n"); - return r; - } - r = amdgpu_bo_kmap(ring->mqd_obj, (void **)&ring->mqd_ptr); - if (!r) { - r = gfx_v9_0_kcq_init_queue(ring, true); - amdgpu_bo_kunmap(ring->mqd_obj); - ring->mqd_ptr = NULL; - } - amdgpu_bo_unreserve(ring->mqd_obj); + r = gfx_v9_0_kcq_init_queue(ring, true); if (r) { - dev_err(adev->dev, "fail to unresv mqd_obj\n"); + dev_err(adev->dev, "fail to init kcq\n"); return r; } spin_lock_irqsave(&kiq->ring_lock, flags);
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c index 736398b..53fbf6c 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c
@@ -867,13 +867,12 @@ static int gfx_v9_4_3_aca_bank_parser(struct aca_handle *handle, switch (type) { case ACA_SMU_TYPE_UE: - bank->aca_err_type = ACA_BANK_ERR_UE_DE_DECODE(bank); + bank->aca_err_type = ACA_ERROR_TYPE_UE; ret = aca_error_cache_log_bank_error(handle, &info, bank->aca_err_type, 1ULL); break; case ACA_SMU_TYPE_CE: - bank->aca_err_type = ACA_BANK_ERR_CE_DE_DECODE(bank); - ret = aca_error_cache_log_bank_error(handle, &info, - bank->aca_err_type, + bank->aca_err_type = ACA_ERROR_TYPE_CE; + ret = aca_error_cache_log_bank_error(handle, &info, bank->aca_err_type, ACA_REG__MISC0__ERRCNT(misc0)); break; default: @@ -2168,55 +2167,27 @@ static int gfx_v9_4_3_xcc_kcq_fini_register(struct amdgpu_device *adev, int xcc_ static int gfx_v9_4_3_xcc_kiq_resume(struct amdgpu_device *adev, int xcc_id) { - struct amdgpu_ring *ring; - int r; - - ring = &adev->gfx.kiq[xcc_id].ring; - - r = amdgpu_bo_reserve(ring->mqd_obj, false); - if (unlikely(r != 0)) - return r; - - r = amdgpu_bo_kmap(ring->mqd_obj, (void **)&ring->mqd_ptr); - if (unlikely(r != 0)) { - amdgpu_bo_unreserve(ring->mqd_obj); - return r; - } - - gfx_v9_4_3_xcc_kiq_init_queue(ring, xcc_id); - amdgpu_bo_kunmap(ring->mqd_obj); - ring->mqd_ptr = NULL; - amdgpu_bo_unreserve(ring->mqd_obj); + gfx_v9_4_3_xcc_kiq_init_queue(&adev->gfx.kiq[xcc_id].ring, xcc_id); return 0; } static int gfx_v9_4_3_xcc_kcq_resume(struct amdgpu_device *adev, int xcc_id) { - struct amdgpu_ring *ring = NULL; - int r = 0, i; + struct amdgpu_ring *ring; + int i, r; gfx_v9_4_3_xcc_cp_compute_enable(adev, true, xcc_id); for (i = 0; i < adev->gfx.num_compute_rings; i++) { - ring = &adev->gfx.compute_ring[i + xcc_id * adev->gfx.num_compute_rings]; + ring = &adev->gfx.compute_ring[i + xcc_id * + adev->gfx.num_compute_rings]; - r = amdgpu_bo_reserve(ring->mqd_obj, false); - if (unlikely(r != 0)) - goto done; - r = amdgpu_bo_kmap(ring->mqd_obj, (void **)&ring->mqd_ptr); - if (!r) { - r = gfx_v9_4_3_xcc_kcq_init_queue(ring, xcc_id, false); - amdgpu_bo_kunmap(ring->mqd_obj); - ring->mqd_ptr = NULL; - } - amdgpu_bo_unreserve(ring->mqd_obj); + r = gfx_v9_4_3_xcc_kcq_init_queue(ring, xcc_id, false); if (r) - goto done; + return r; } - r = amdgpu_gfx_enable_kcq(adev, xcc_id); -done: - return r; + return amdgpu_gfx_enable_kcq(adev, xcc_id); } static int gfx_v9_4_3_xcc_cp_resume(struct amdgpu_device *adev, int xcc_id) @@ -3588,20 +3559,9 @@ static int gfx_v9_4_3_reset_kcq(struct amdgpu_ring *ring, return r; } - r = amdgpu_bo_reserve(ring->mqd_obj, false); - if (unlikely(r != 0)){ - dev_err(adev->dev, "fail to resv mqd_obj\n"); - return r; - } - r = amdgpu_bo_kmap(ring->mqd_obj, (void **)&ring->mqd_ptr); - if (!r) { - r = gfx_v9_4_3_xcc_kcq_init_queue(ring, ring->xcc_id, true); - amdgpu_bo_kunmap(ring->mqd_obj); - ring->mqd_ptr = NULL; - } - amdgpu_bo_unreserve(ring->mqd_obj); + r = gfx_v9_4_3_xcc_kcq_init_queue(ring, ring->xcc_id, true); if (r) { - dev_err(adev->dev, "fail to unresv mqd_obj\n"); + dev_err(adev->dev, "fail to init kcq\n"); return r; } spin_lock_irqsave(&kiq->ring_lock, flags);
diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c index 5598a35..a8ccae3 100644 --- a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c +++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c
@@ -1328,7 +1328,7 @@ static int jpeg_v4_0_3_aca_bank_parser(struct aca_handle *handle, struct aca_ban 1ULL); break; case ACA_SMU_TYPE_CE: - bank->aca_err_type = ACA_BANK_ERR_CE_DE_DECODE(bank); + bank->aca_err_type = ACA_ERROR_TYPE_CE; ret = aca_error_cache_log_bank_error(handle, &info, bank->aca_err_type, ACA_REG__MISC0__ERRCNT(misc0)); break;
diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_8.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_8.c index a54e7b9..84cde12 100644 --- a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_8.c +++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_8.c
@@ -751,7 +751,7 @@ static int mmhub_v1_8_aca_bank_parser(struct aca_handle *handle, struct aca_bank 1ULL); break; case ACA_SMU_TYPE_CE: - bank->aca_err_type = ACA_BANK_ERR_CE_DE_DECODE(bank); + bank->aca_err_type = ACA_ERROR_TYPE_CE; ret = aca_error_cache_log_bank_error(handle, &info, bank->aca_err_type, ACA_REG__MISC0__ERRCNT(misc0)); break;
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c b/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c index dc94d58..688a720 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c
@@ -31,7 +31,6 @@ #include "amdgpu_ucode.h" #include "amdgpu_trace.h" #include "amdgpu_reset.h" -#include "gc/gc_9_0_sh_mask.h" #include "sdma/sdma_4_4_2_offset.h" #include "sdma/sdma_4_4_2_sh_mask.h" @@ -1291,71 +1290,21 @@ static void sdma_v4_4_2_ring_emit_pipeline_sync(struct amdgpu_ring *ring) seq, 0xffffffff, 4); } -/* - * sdma_v4_4_2_get_invalidate_req - Construct the VM_INVALIDATE_ENG0_REQ register value - * @vmid: The VMID to invalidate - * @flush_type: The type of flush (0 = legacy, 1 = lightweight, 2 = heavyweight) + +/** + * sdma_v4_4_2_ring_emit_vm_flush - vm flush using sDMA * - * This function constructs the VM_INVALIDATE_ENG0_REQ register value for the specified VMID - * and flush type. It ensures that all relevant page table cache levels (L1 PTEs, L2 PTEs, and - * L2 PDEs) are invalidated. - */ -static uint32_t sdma_v4_4_2_get_invalidate_req(unsigned int vmid, - uint32_t flush_type) -{ - u32 req = 0; - - req = REG_SET_FIELD(req, VM_INVALIDATE_ENG0_REQ, - PER_VMID_INVALIDATE_REQ, 1 << vmid); - req = REG_SET_FIELD(req, VM_INVALIDATE_ENG0_REQ, FLUSH_TYPE, flush_type); - req = REG_SET_FIELD(req, VM_INVALIDATE_ENG0_REQ, INVALIDATE_L2_PTES, 1); - req = REG_SET_FIELD(req, VM_INVALIDATE_ENG0_REQ, INVALIDATE_L2_PDE0, 1); - req = REG_SET_FIELD(req, VM_INVALIDATE_ENG0_REQ, INVALIDATE_L2_PDE1, 1); - req = REG_SET_FIELD(req, VM_INVALIDATE_ENG0_REQ, INVALIDATE_L2_PDE2, 1); - req = REG_SET_FIELD(req, VM_INVALIDATE_ENG0_REQ, INVALIDATE_L1_PTES, 1); - req = REG_SET_FIELD(req, VM_INVALIDATE_ENG0_REQ, - CLEAR_PROTECTION_FAULT_STATUS_ADDR, 0); - - return req; -} - -/* - * sdma_v4_4_2_ring_emit_vm_flush - Emit VM flush commands for SDMA - * @ring: The SDMA ring - * @vmid: The VMID to flush - * @pd_addr: The page directory address + * @ring: amdgpu_ring pointer + * @vmid: vmid number to use + * @pd_addr: address * - * This function emits the necessary register writes and waits to perform a VM flush for the - * specified VMID. It updates the PTB address registers and issues a VM invalidation request - * using the specified VM invalidation engine. + * Update the page table base and flush the VM TLB + * using sDMA. */ static void sdma_v4_4_2_ring_emit_vm_flush(struct amdgpu_ring *ring, - unsigned int vmid, uint64_t pd_addr) + unsigned vmid, uint64_t pd_addr) { - struct amdgpu_device *adev = ring->adev; - uint32_t req = sdma_v4_4_2_get_invalidate_req(vmid, 0); - unsigned int eng = ring->vm_inv_eng; - struct amdgpu_vmhub *hub = &adev->vmhub[ring->vm_hub]; - - amdgpu_ring_emit_wreg(ring, hub->ctx0_ptb_addr_lo32 + - (hub->ctx_addr_distance * vmid), - lower_32_bits(pd_addr)); - - amdgpu_ring_emit_wreg(ring, hub->ctx0_ptb_addr_hi32 + - (hub->ctx_addr_distance * vmid), - upper_32_bits(pd_addr)); - /* - * Construct and emit the VM invalidation packet - */ - amdgpu_ring_write(ring, - SDMA_PKT_VM_INVALIDATION_HEADER_OP(SDMA_OP_VM_INVALIDATE) | - SDMA_PKT_VM_INVALIDATION_HEADER_SUB_OP(SDMA_SUBOP_VM_INVALIDATE) | - SDMA_PKT_VM_INVALIDATION_HEADER_XCC0_ENG_ID(0x1f) | - SDMA_PKT_VM_INVALIDATION_HEADER_XCC1_ENG_ID(0x1f) | - SDMA_PKT_VM_INVALIDATION_HEADER_MMHUB_ENG_ID(eng)); - amdgpu_ring_write(ring, SDMA_PKT_VM_INVALIDATION_INVALIDATEREQ_INVALIDATEREQ(req)); - amdgpu_ring_write(ring, 0); - amdgpu_ring_write(ring, SDMA_PKT_VM_INVALIDATION_ADDRESSRANGEHI_INVALIDATEACK(BIT(vmid))); + amdgpu_gmc_emit_flush_gpu_tlb(ring, vmid, pd_addr); } static void sdma_v4_4_2_ring_emit_wreg(struct amdgpu_ring *ring, @@ -2177,7 +2126,8 @@ static const struct amdgpu_ring_funcs sdma_v4_4_2_ring_funcs = { 3 + /* hdp invalidate */ 6 + /* sdma_v4_4_2_ring_emit_pipeline_sync */ /* sdma_v4_4_2_ring_emit_vm_flush */ - 4 + 2 * 3 + + SOC15_FLUSH_GPU_TLB_NUM_WREG * 3 + + SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 6 + 10 + 10 + 10, /* sdma_v4_4_2_ring_emit_fence x3 for user fence, vm fence */ .emit_ib_size = 7 + 6, /* sdma_v4_4_2_ring_emit_ib */ .emit_ib = sdma_v4_4_2_ring_emit_ib, @@ -2209,7 +2159,8 @@ static const struct amdgpu_ring_funcs sdma_v4_4_2_page_ring_funcs = { 3 + /* hdp invalidate */ 6 + /* sdma_v4_4_2_ring_emit_pipeline_sync */ /* sdma_v4_4_2_ring_emit_vm_flush */ - 4 + 2 * 3 + + SOC15_FLUSH_GPU_TLB_NUM_WREG * 3 + + SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 6 + 10 + 10 + 10, /* sdma_v4_4_2_ring_emit_fence x3 for user fence, vm fence */ .emit_ib_size = 7 + 6, /* sdma_v4_4_2_ring_emit_ib */ .emit_ib = sdma_v4_4_2_ring_emit_ib, @@ -2595,7 +2546,7 @@ static int sdma_v4_4_2_aca_bank_parser(struct aca_handle *handle, struct aca_ban 1ULL); break; case ACA_SMU_TYPE_CE: - bank->aca_err_type = ACA_BANK_ERR_CE_DE_DECODE(bank); + bank->aca_err_type = ACA_ERROR_TYPE_CE; ret = aca_error_cache_log_bank_error(handle, &info, bank->aca_err_type, ACA_REG__MISC0__ERRCNT(misc0)); break;
diff --git a/drivers/gpu/drm/amd/amdgpu/ta_ras_if.h b/drivers/gpu/drm/amd/amdgpu/ta_ras_if.h index a3b5fda..8a3f326 100644 --- a/drivers/gpu/drm/amd/amdgpu/ta_ras_if.h +++ b/drivers/gpu/drm/amd/amdgpu/ta_ras_if.h
@@ -92,6 +92,9 @@ enum ta_ras_block { TA_RAS_BLOCK__MCA, TA_RAS_BLOCK__VCN, TA_RAS_BLOCK__JPEG, + TA_RAS_BLOCK__IH, + TA_RAS_BLOCK__MPIO, + TA_RAS_BLOCK__MMSCH, TA_NUM_BLOCK_MAX };
diff --git a/drivers/gpu/drm/amd/amdgpu/umc_v12_0.c b/drivers/gpu/drm/amd/amdgpu/umc_v12_0.c index 74f57b2..0e404c0 100644 --- a/drivers/gpu/drm/amd/amdgpu/umc_v12_0.c +++ b/drivers/gpu/drm/amd/amdgpu/umc_v12_0.c
@@ -85,7 +85,8 @@ bool umc_v12_0_is_deferred_error(struct amdgpu_device *adev, uint64_t mc_umc_sta return (amdgpu_ras_is_poison_mode_supported(adev) && (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Val) == 1) && - (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Deferred) == 1)); + ((REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Deferred) == 1) || + (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Poison) == 1))); } bool umc_v12_0_is_uncorrectable_error(struct amdgpu_device *adev, uint64_t mc_umc_status)
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c index 7446ecc..3e176b4 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
@@ -1965,7 +1965,7 @@ static int vcn_v4_0_3_aca_bank_parser(struct aca_handle *handle, struct aca_bank 1ULL); break; case ACA_SMU_TYPE_CE: - bank->aca_err_type = ACA_BANK_ERR_CE_DE_DECODE(bank); + bank->aca_err_type = ACA_ERROR_TYPE_CE; ret = aca_error_cache_log_bank_error(handle, &info, bank->aca_err_type, ACA_REG__MISC0__ERRCNT(misc0)); break;
diff --git a/drivers/gpu/drm/amd/amdgpu/vega10_sdma_pkt_open.h b/drivers/gpu/drm/amd/amdgpu/vega10_sdma_pkt_open.h index 3ca8a417..8de4ccc 100644 --- a/drivers/gpu/drm/amd/amdgpu/vega10_sdma_pkt_open.h +++ b/drivers/gpu/drm/amd/amdgpu/vega10_sdma_pkt_open.h
@@ -64,9 +64,6 @@ #define HEADER_BARRIER 5 #define SDMA_OP_AQL_COPY 0 #define SDMA_OP_AQL_BARRIER_OR 0 -/* vm invalidation is only available for GC9.4.3/GC9.4.4/GC9.5.0 */ -#define SDMA_OP_VM_INVALIDATE 8 -#define SDMA_SUBOP_VM_INVALIDATE 4 /*define for op field*/ #define SDMA_PKT_HEADER_op_offset 0 @@ -3334,72 +3331,5 @@ #define SDMA_AQL_PKT_BARRIER_OR_COMPLETION_SIGNAL_HI_completion_signal_63_32_shift 0 #define SDMA_AQL_PKT_BARRIER_OR_COMPLETION_SIGNAL_HI_COMPLETION_SIGNAL_63_32(x) (((x) & SDMA_AQL_PKT_BARRIER_OR_COMPLETION_SIGNAL_HI_completion_signal_63_32_mask) << SDMA_AQL_PKT_BARRIER_OR_COMPLETION_SIGNAL_HI_completion_signal_63_32_shift) -/* -** Definitions for SDMA_PKT_VM_INVALIDATION packet -*/ - -/*define for HEADER word*/ -/*define for op field*/ -#define SDMA_PKT_VM_INVALIDATION_HEADER_op_offset 0 -#define SDMA_PKT_VM_INVALIDATION_HEADER_op_mask 0x000000FF -#define SDMA_PKT_VM_INVALIDATION_HEADER_op_shift 0 -#define SDMA_PKT_VM_INVALIDATION_HEADER_OP(x) ((x & SDMA_PKT_VM_INVALIDATION_HEADER_op_mask) << SDMA_PKT_VM_INVALIDATION_HEADER_op_shift) - -/*define for sub_op field*/ -#define SDMA_PKT_VM_INVALIDATION_HEADER_sub_op_offset 0 -#define SDMA_PKT_VM_INVALIDATION_HEADER_sub_op_mask 0x000000FF -#define SDMA_PKT_VM_INVALIDATION_HEADER_sub_op_shift 8 -#define SDMA_PKT_VM_INVALIDATION_HEADER_SUB_OP(x) ((x & SDMA_PKT_VM_INVALIDATION_HEADER_sub_op_mask) << SDMA_PKT_VM_INVALIDATION_HEADER_sub_op_shift) - -/*define for xcc0_eng_id field*/ -#define SDMA_PKT_VM_INVALIDATION_HEADER_xcc0_eng_id_offset 0 -#define SDMA_PKT_VM_INVALIDATION_HEADER_xcc0_eng_id_mask 0x0000001F -#define SDMA_PKT_VM_INVALIDATION_HEADER_xcc0_eng_id_shift 16 -#define SDMA_PKT_VM_INVALIDATION_HEADER_XCC0_ENG_ID(x) ((x & SDMA_PKT_VM_INVALIDATION_HEADER_xcc0_eng_id_mask) << SDMA_PKT_VM_INVALIDATION_HEADER_xcc0_eng_id_shift) - -/*define for xcc1_eng_id field*/ -#define SDMA_PKT_VM_INVALIDATION_HEADER_xcc1_eng_id_offset 0 -#define SDMA_PKT_VM_INVALIDATION_HEADER_xcc1_eng_id_mask 0x0000001F -#define SDMA_PKT_VM_INVALIDATION_HEADER_xcc1_eng_id_shift 21 -#define SDMA_PKT_VM_INVALIDATION_HEADER_XCC1_ENG_ID(x) ((x & SDMA_PKT_VM_INVALIDATION_HEADER_xcc1_eng_id_mask) << SDMA_PKT_VM_INVALIDATION_HEADER_xcc1_eng_id_shift) - -/*define for mmhub_eng_id field*/ -#define SDMA_PKT_VM_INVALIDATION_HEADER_mmhub_eng_id_offset 0 -#define SDMA_PKT_VM_INVALIDATION_HEADER_mmhub_eng_id_mask 0x0000001F -#define SDMA_PKT_VM_INVALIDATION_HEADER_mmhub_eng_id_shift 26 -#define SDMA_PKT_VM_INVALIDATION_HEADER_MMHUB_ENG_ID(x) ((x & SDMA_PKT_VM_INVALIDATION_HEADER_mmhub_eng_id_mask) << SDMA_PKT_VM_INVALIDATION_HEADER_mmhub_eng_id_shift) - -/*define for INVALIDATEREQ word*/ -/*define for invalidatereq field*/ -#define SDMA_PKT_VM_INVALIDATION_INVALIDATEREQ_invalidatereq_offset 1 -#define SDMA_PKT_VM_INVALIDATION_INVALIDATEREQ_invalidatereq_mask 0xFFFFFFFF -#define SDMA_PKT_VM_INVALIDATION_INVALIDATEREQ_invalidatereq_shift 0 -#define SDMA_PKT_VM_INVALIDATION_INVALIDATEREQ_INVALIDATEREQ(x) ((x & SDMA_PKT_VM_INVALIDATION_INVALIDATEREQ_invalidatereq_mask) << SDMA_PKT_VM_INVALIDATION_INVALIDATEREQ_invalidatereq_shift) - -/*define for ADDRESSRANGELO word*/ -/*define for addressrangelo field*/ -#define SDMA_PKT_VM_INVALIDATION_ADDRESSRANGELO_addressrangelo_offset 2 -#define SDMA_PKT_VM_INVALIDATION_ADDRESSRANGELO_addressrangelo_mask 0xFFFFFFFF -#define SDMA_PKT_VM_INVALIDATION_ADDRESSRANGELO_addressrangelo_shift 0 -#define SDMA_PKT_VM_INVALIDATION_ADDRESSRANGELO_ADDRESSRANGELO(x) ((x & SDMA_PKT_VM_INVALIDATION_ADDRESSRANGELO_addressrangelo_mask) << SDMA_PKT_VM_INVALIDATION_ADDRESSRANGELO_addressrangelo_shift) - -/*define for ADDRESSRANGEHI word*/ -/*define for invalidateack field*/ -#define SDMA_PKT_VM_INVALIDATION_ADDRESSRANGEHI_invalidateack_offset 3 -#define SDMA_PKT_VM_INVALIDATION_ADDRESSRANGEHI_invalidateack_mask 0x0000FFFF -#define SDMA_PKT_VM_INVALIDATION_ADDRESSRANGEHI_invalidateack_shift 0 -#define SDMA_PKT_VM_INVALIDATION_ADDRESSRANGEHI_INVALIDATEACK(x) ((x & SDMA_PKT_VM_INVALIDATION_ADDRESSRANGEHI_invalidateack_mask) << SDMA_PKT_VM_INVALIDATION_ADDRESSRANGEHI_invalidateack_shift) - -/*define for addressrangehi field*/ -#define SDMA_PKT_VM_INVALIDATION_ADDRESSRANGEHI_addressrangehi_offset 3 -#define SDMA_PKT_VM_INVALIDATION_ADDRESSRANGEHI_addressrangehi_mask 0x0000001F -#define SDMA_PKT_VM_INVALIDATION_ADDRESSRANGEHI_addressrangehi_shift 16 -#define SDMA_PKT_VM_INVALIDATION_ADDRESSRANGEHI_ADDRESSRANGEHI(x) ((x & SDMA_PKT_VM_INVALIDATION_ADDRESSRANGEHI_addressrangehi_mask) << SDMA_PKT_VM_INVALIDATION_ADDRESSRANGEHI_addressrangehi_shift) - -/*define for reserved field*/ -#define SDMA_PKT_VM_INVALIDATION_ADDRESSRANGEHI_reserved_offset 3 -#define SDMA_PKT_VM_INVALIDATION_ADDRESSRANGEHI_reserved_mask 0x000001FF -#define SDMA_PKT_VM_INVALIDATION_ADDRESSRANGEHI_reserved_shift 23 -#define SDMA_PKT_VM_INVALIDATION_ADDRESSRANGEHI_RESERVED(x) ((x & SDMA_PKT_VM_INVALIDATION_ADDRESSRANGEHI_reserved_mask) << SDMA_PKT_VM_INVALIDATION_ADDRESSRANGEHI_reserved_shift) #endif /* __SDMA_PKT_OPEN_H_ */
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index bae83a1..d0d8ad5 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -8707,14 +8707,39 @@ static void manage_dm_interrupts(struct amdgpu_device *adev, int offdelay; if (acrtc_state) { - if (amdgpu_ip_version(adev, DCE_HWIP, 0) < - IP_VERSION(3, 5, 0) || - acrtc_state->stream->link->psr_settings.psr_version < - DC_PSR_VERSION_UNSUPPORTED || - !(adev->flags & AMD_IS_APU)) { - timing = &acrtc_state->stream->timing; + timing = &acrtc_state->stream->timing; - /* at least 2 frames */ + /* + * Depending on when the HW latching event of double-buffered + * registers happen relative to the PSR SDP deadline, and how + * bad the Panel clock has drifted since the last ALPM off + * event, there can be up to 3 frames of delay between sending + * the PSR exit cmd to DMUB fw, and when the panel starts + * displaying live frames. + * + * We can set: + * + * 20/100 * offdelay_ms = 3_frames_ms + * => offdelay_ms = 5 * 3_frames_ms + * + * This ensures that `3_frames_ms` will only be experienced as a + * 20% delay on top how long the display has been static, and + * thus make the delay less perceivable. + */ + if (acrtc_state->stream->link->psr_settings.psr_version < + DC_PSR_VERSION_UNSUPPORTED) { + offdelay = DIV64_U64_ROUND_UP((u64)5 * 3 * 10 * + timing->v_total * + timing->h_total, + timing->pix_clk_100hz); + config.offdelay_ms = offdelay ?: 30; + } else if (amdgpu_ip_version(adev, DCE_HWIP, 0) < + IP_VERSION(3, 5, 0) || + !(adev->flags & AMD_IS_APU)) { + /* + * Older HW and DGPU have issues with instant off; + * use a 2 frame offdelay. + */ offdelay = DIV64_U64_ROUND_UP((u64)20 * timing->v_total * timing->h_total, @@ -8722,6 +8747,8 @@ static void manage_dm_interrupts(struct amdgpu_device *adev, config.offdelay_ms = offdelay ?: 30; } else { + /* offdelay_ms = 0 will never disable vblank */ + config.offdelay_ms = 1; config.disable_immediate = true; }
diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml2_translation_helper.c b/drivers/gpu/drm/amd/display/dc/dml2/dml2_translation_helper.c index 70c39df..2061d43 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/dml2_translation_helper.c +++ b/drivers/gpu/drm/amd/display/dc/dml2/dml2_translation_helper.c
@@ -590,11 +590,11 @@ void dml2_init_soc_states(struct dml2_context *dml2, const struct dc *in_dc, p->out_states->state_array[i].dtbclk_mhz = max_dtbclk_mhz; p->out_states->state_array[i].phyclk_mhz = max_phyclk_mhz; + p->out_states->state_array[i].dscclk_mhz = max_dispclk_mhz / 3.0; p->out_states->state_array[i].phyclk_mhz = max_phyclk_mhz; p->out_states->state_array[i].dtbclk_mhz = max_dtbclk_mhz; /* Dependent states. */ - p->out_states->state_array[i].dscclk_mhz = p->in_states->state_array[i].dscclk_mhz; p->out_states->state_array[i].dram_speed_mts = p->in_states->state_array[i].dram_speed_mts; p->out_states->state_array[i].fabricclk_mhz = p->in_states->state_array[i].fabricclk_mhz; p->out_states->state_array[i].socclk_mhz = p->in_states->state_array[i].socclk_mhz;
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c index 926c08e..846c9c5 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c
@@ -3033,7 +3033,11 @@ void dcn20_enable_stream(struct pipe_ctx *pipe_ctx) dccg->funcs->set_dpstreamclk(dccg, DTBCLK0, tg->inst, dp_hpo_inst); phyd32clk = get_phyd32clk_src(link); - dccg->funcs->enable_symclk32_se(dccg, dp_hpo_inst, phyd32clk); + if (link->cur_link_settings.link_rate == LINK_RATE_UNKNOWN) { + dccg->funcs->disable_symclk32_se(dccg, dp_hpo_inst); + } else { + dccg->funcs->enable_symclk32_se(dccg, dp_hpo_inst, phyd32clk); + } } else { if (dccg->funcs->enable_symclk_se) dccg->funcs->enable_symclk_se(dccg, stream_enc->stream_enc_inst,
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c index 8f5da0d..5489f3d 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
@@ -936,8 +936,11 @@ void dcn401_enable_stream(struct pipe_ctx *pipe_ctx) if (dc_is_dp_signal(pipe_ctx->stream->signal) || dc_is_virtual_signal(pipe_ctx->stream->signal)) { if (dc->link_srv->dp_is_128b_132b_signal(pipe_ctx)) { dccg->funcs->set_dpstreamclk(dccg, DPREFCLK, tg->inst, dp_hpo_inst); - - dccg->funcs->enable_symclk32_se(dccg, dp_hpo_inst, phyd32clk); + if (link->cur_link_settings.link_rate == LINK_RATE_UNKNOWN) { + dccg->funcs->disable_symclk32_se(dccg, dp_hpo_inst); + } else { + dccg->funcs->enable_symclk32_se(dccg, dp_hpo_inst, phyd32clk); + } } else { dccg->funcs->enable_symclk_se(dccg, stream_enc->stream_enc_inst, link_enc->transmitter - TRANSMITTER_UNIPHY_A);
diff --git a/drivers/gpu/drm/amd/include/kgd_pp_interface.h b/drivers/gpu/drm/amd/include/kgd_pp_interface.h index 9189dcb..2a96061 100644 --- a/drivers/gpu/drm/amd/include/kgd_pp_interface.h +++ b/drivers/gpu/drm/amd/include/kgd_pp_interface.h
@@ -341,6 +341,7 @@ enum pp_policy_soc_pstate { #define MAX_CLKS 4 #define NUM_VCN 4 #define NUM_JPEG_ENG 32 +#define NUM_JPEG_ENG_V1 40 #define MAX_XCC 8 #define NUM_XCP 8 struct seq_file; @@ -376,6 +377,20 @@ struct amdgpu_xcp_metrics_v1_1 { uint64_t gfx_below_host_limit_acc[MAX_XCC]; }; +struct amdgpu_xcp_metrics_v1_2 { + /* Utilization Instantaneous (%) */ + uint32_t gfx_busy_inst[MAX_XCC]; + uint16_t jpeg_busy[NUM_JPEG_ENG_V1]; + uint16_t vcn_busy[NUM_VCN]; + /* Utilization Accumulated (%) */ + uint64_t gfx_busy_acc[MAX_XCC]; + /* Total App Clock Counter Accumulated */ + uint64_t gfx_below_host_limit_ppt_acc[MAX_XCC]; + uint64_t gfx_below_host_limit_thm_acc[MAX_XCC]; + uint64_t gfx_low_utilization_acc[MAX_XCC]; + uint64_t gfx_below_host_limit_total_acc[MAX_XCC]; +}; + struct amd_pm_funcs { /* export for dpm on ci and si */ int (*pre_set_power_state)(void *handle); @@ -1090,6 +1105,105 @@ struct gpu_metrics_v1_7 { uint32_t pcie_lc_perf_other_end_recovery; }; +struct gpu_metrics_v1_8 { + struct metrics_table_header common_header; + + /* Temperature (Celsius) */ + uint16_t temperature_hotspot; + uint16_t temperature_mem; + uint16_t temperature_vrsoc; + + /* Power (Watts) */ + uint16_t curr_socket_power; + + /* Utilization (%) */ + uint16_t average_gfx_activity; + uint16_t average_umc_activity; // memory controller + + /* VRAM max bandwidthi (in GB/sec) at max memory clock */ + uint64_t mem_max_bandwidth; + + /* Energy (15.259uJ (2^-16) units) */ + uint64_t energy_accumulator; + + /* Driver attached timestamp (in ns) */ + uint64_t system_clock_counter; + + /* Accumulation cycle counter */ + uint32_t accumulation_counter; + + /* Accumulated throttler residencies */ + uint32_t prochot_residency_acc; + uint32_t ppt_residency_acc; + uint32_t socket_thm_residency_acc; + uint32_t vr_thm_residency_acc; + uint32_t hbm_thm_residency_acc; + + /* Clock Lock Status. Each bit corresponds to clock instance */ + uint32_t gfxclk_lock_status; + + /* Link width (number of lanes) and speed (in 0.1 GT/s) */ + uint16_t pcie_link_width; + uint16_t pcie_link_speed; + + /* XGMI bus width and bitrate (in Gbps) */ + uint16_t xgmi_link_width; + uint16_t xgmi_link_speed; + + /* Utilization Accumulated (%) */ + uint32_t gfx_activity_acc; + uint32_t mem_activity_acc; + + /*PCIE accumulated bandwidth (GB/sec) */ + uint64_t pcie_bandwidth_acc; + + /*PCIE instantaneous bandwidth (GB/sec) */ + uint64_t pcie_bandwidth_inst; + + /* PCIE L0 to recovery state transition accumulated count */ + uint64_t pcie_l0_to_recov_count_acc; + + /* PCIE replay accumulated count */ + uint64_t pcie_replay_count_acc; + + /* PCIE replay rollover accumulated count */ + uint64_t pcie_replay_rover_count_acc; + + /* PCIE NAK sent accumulated count */ + uint32_t pcie_nak_sent_count_acc; + + /* PCIE NAK received accumulated count */ + uint32_t pcie_nak_rcvd_count_acc; + + /* XGMI accumulated data transfer size(KiloBytes) */ + uint64_t xgmi_read_data_acc[NUM_XGMI_LINKS]; + uint64_t xgmi_write_data_acc[NUM_XGMI_LINKS]; + + /* XGMI link status(active/inactive) */ + uint16_t xgmi_link_status[NUM_XGMI_LINKS]; + + uint16_t padding; + + /* PMFW attached timestamp (10ns resolution) */ + uint64_t firmware_timestamp; + + /* Current clocks (Mhz) */ + uint16_t current_gfxclk[MAX_GFX_CLKS]; + uint16_t current_socclk[MAX_CLKS]; + uint16_t current_vclk0[MAX_CLKS]; + uint16_t current_dclk0[MAX_CLKS]; + uint16_t current_uclk; + + /* Number of current partition */ + uint16_t num_partition; + + /* XCP metrics stats */ + struct amdgpu_xcp_metrics_v1_2 xcp_stats[NUM_XCP]; + + /* PCIE other end recovery counter */ + uint32_t pcie_lc_perf_other_end_recovery; +}; + /* * gpu_metrics_v2_0 is not recommended as it's not naturally aligned. * Use gpu_metrics_v2_1 or later instead.
diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_thermal.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_thermal.c index a8fc0fa..ba5c123 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_thermal.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_thermal.c
@@ -267,10 +267,10 @@ int smu7_fan_ctrl_set_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t speed) if (hwmgr->thermal_controller.fanInfo.bNoFan || (hwmgr->thermal_controller.fanInfo. ucTachometerPulsesPerRevolution == 0) || - speed == 0 || + (!speed || speed > UINT_MAX/8) || (speed < hwmgr->thermal_controller.fanInfo.ulMinRPM) || (speed > hwmgr->thermal_controller.fanInfo.ulMaxRPM)) - return 0; + return -EINVAL; if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl)) smu7_fan_ctrl_stop_smc_fan_control(hwmgr);
diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_thermal.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_thermal.c index 3790124..56423ae 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_thermal.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_thermal.c
@@ -307,10 +307,10 @@ int vega10_fan_ctrl_set_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t speed) int result = 0; if (hwmgr->thermal_controller.fanInfo.bNoFan || - speed == 0 || + (!speed || speed > UINT_MAX/8) || (speed < hwmgr->thermal_controller.fanInfo.ulMinRPM) || (speed > hwmgr->thermal_controller.fanInfo.ulMaxRPM)) - return -1; + return -EINVAL; if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl)) result = vega10_fan_ctrl_stop_smc_fan_control(hwmgr);
diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_thermal.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_thermal.c index a3331ff..1b1c885 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_thermal.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_thermal.c
@@ -191,7 +191,7 @@ int vega20_fan_ctrl_set_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t speed) uint32_t tach_period, crystal_clock_freq; int result = 0; - if (!speed) + if (!speed || speed > UINT_MAX/8) return -EINVAL; if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl)) {
diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v13_0_6_pmfw.h b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v13_0_6_pmfw.h index f8ed458..d26f351 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v13_0_6_pmfw.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v13_0_6_pmfw.h
@@ -127,7 +127,7 @@ typedef enum { VOLTAGE_GUARDBAND_COUNT } GFX_GUARDBAND_e; -#define SMU_METRICS_TABLE_VERSION 0xF +#define SMU_METRICS_TABLE_VERSION 0x10 // Unified metrics table for smu_v13_0_6 typedef struct __attribute__((packed, aligned(4))) { @@ -241,7 +241,10 @@ typedef struct __attribute__((packed, aligned(4))) { uint32_t PCIeOtherEndRecoveryAcc; // The Pcie counter itself is accumulated //Total App Clock Counter - uint64_t GfxclkBelowHostLimitAcc[8]; + uint64_t GfxclkBelowHostLimitPptAcc[8]; + uint64_t GfxclkBelowHostLimitThmAcc[8]; + uint64_t GfxclkBelowHostLimitTotalAcc[8]; + uint64_t GfxclkLowUtilizationAcc[8]; } MetricsTableV0_t; // Metrics table for smu_v13_0_6 APUS
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c index 8aa61a9..453952c 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
@@ -1267,6 +1267,9 @@ static int arcturus_set_fan_speed_rpm(struct smu_context *smu, uint32_t crystal_clock_freq = 2500; uint32_t tach_period; + if (!speed || speed > UINT_MAX/8) + return -EINVAL; + tach_period = 60 * crystal_clock_freq * 10000 / (8 * speed); WREG32_SOC15(THM, 0, mmCG_TACH_CTRL_ARCT, REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_TACH_CTRL_ARCT),
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c index 0915d63..ba5a901 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c
@@ -1226,7 +1226,7 @@ int smu_v13_0_set_fan_speed_rpm(struct smu_context *smu, uint32_t tach_period; int ret; - if (!speed) + if (!speed || speed > UINT_MAX/8) return -EINVAL; ret = smu_v13_0_auto_fan_control(smu, 0);
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c index 6826460..c478b3b 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c
@@ -109,7 +109,6 @@ enum smu_v13_0_6_caps { SMU_CAP(OTHER_END_METRICS), SMU_CAP(SET_UCLK_MAX), SMU_CAP(PCIE_METRICS), - SMU_CAP(HST_LIMIT_METRICS), SMU_CAP(MCA_DEBUG_MODE), SMU_CAP(PER_INST_METRICS), SMU_CAP(CTF_LIMIT), @@ -325,8 +324,6 @@ static void smu_v13_0_14_init_caps(struct smu_context *smu) if (fw_ver >= 0x05550E00) smu_v13_0_6_cap_set(smu, SMU_CAP(OTHER_END_METRICS)); - if (fw_ver >= 0x05551000) - smu_v13_0_6_cap_set(smu, SMU_CAP(HST_LIMIT_METRICS)); if (fw_ver >= 0x05550B00) smu_v13_0_6_cap_set(smu, SMU_CAP(PER_INST_METRICS)); if (fw_ver >= 0x5551200) @@ -342,7 +339,6 @@ static void smu_v13_0_12_init_caps(struct smu_context *smu) SMU_CAP(RMA_MSG), SMU_CAP(ACA_SYND), SMU_CAP(OTHER_END_METRICS), - SMU_CAP(HST_LIMIT_METRICS), SMU_CAP(PER_INST_METRICS) }; uint32_t fw_ver = smu->smc_fw_version; @@ -387,8 +383,6 @@ static void smu_v13_0_6_init_caps(struct smu_context *smu) smu_v13_0_6_cap_clear(smu, SMU_CAP(RMA_MSG)); smu_v13_0_6_cap_clear(smu, SMU_CAP(ACA_SYND)); - if (fw_ver >= 0x04556F00) - smu_v13_0_6_cap_set(smu, SMU_CAP(HST_LIMIT_METRICS)); if (fw_ver >= 0x04556A00) smu_v13_0_6_cap_set(smu, SMU_CAP(PER_INST_METRICS)); } else { @@ -408,8 +402,6 @@ static void smu_v13_0_6_init_caps(struct smu_context *smu) smu_v13_0_6_cap_clear(smu, SMU_CAP(RMA_MSG)); if (fw_ver < 0x00555600) smu_v13_0_6_cap_clear(smu, SMU_CAP(ACA_SYND)); - if (pgm == 0 && fw_ver >= 0x557900) - smu_v13_0_6_cap_set(smu, SMU_CAP(HST_LIMIT_METRICS)); } if (((pgm == 7) && (fw_ver >= 0x7550700)) || ((pgm == 0) && (fw_ver >= 0x00557900)) || @@ -2674,13 +2666,6 @@ static ssize_t smu_v13_0_6_get_gpu_metrics(struct smu_context *smu, void **table gpu_metrics->xcp_stats[i].gfx_busy_acc[idx] = SMUQ10_ROUND(GET_GPU_METRIC_FIELD(GfxBusyAcc, version)[inst]); - - if (smu_v13_0_6_cap_supported( - smu, SMU_CAP(HST_LIMIT_METRICS))) - gpu_metrics->xcp_stats[i].gfx_below_host_limit_acc[idx] = - SMUQ10_ROUND(GET_GPU_METRIC_FIELD - (GfxclkBelowHostLimitAcc, version) - [inst]); idx++; } }
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c index f7cfe1f..82c2db9 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c
@@ -79,6 +79,7 @@ #define PP_OD_FEATURE_FAN_ACOUSTIC_TARGET 8 #define PP_OD_FEATURE_FAN_TARGET_TEMPERATURE 9 #define PP_OD_FEATURE_FAN_MINIMUM_PWM 10 +#define PP_OD_FEATURE_FAN_ZERO_RPM_ENABLE 11 static struct cmn2asic_msg_mapping smu_v14_0_2_message_map[SMU_MSG_MAX_COUNT] = { MSG_MAP(TestMessage, PPSMC_MSG_TestMessage, 1), @@ -1052,6 +1053,10 @@ static void smu_v14_0_2_get_od_setting_limits(struct smu_context *smu, od_min_setting = overdrive_lowerlimits->FanMinimumPwm; od_max_setting = overdrive_upperlimits->FanMinimumPwm; break; + case PP_OD_FEATURE_FAN_ZERO_RPM_ENABLE: + od_min_setting = overdrive_lowerlimits->FanZeroRpmEnable; + od_max_setting = overdrive_upperlimits->FanZeroRpmEnable; + break; default: od_min_setting = od_max_setting = INT_MAX; break; @@ -1330,6 +1335,24 @@ static int smu_v14_0_2_print_clk_levels(struct smu_context *smu, min_value, max_value); break; + case SMU_OD_FAN_ZERO_RPM_ENABLE: + if (!smu_v14_0_2_is_od_feature_supported(smu, + PP_OD_FEATURE_ZERO_FAN_BIT)) + break; + + size += sysfs_emit_at(buf, size, "FAN_ZERO_RPM_ENABLE:\n"); + size += sysfs_emit_at(buf, size, "%d\n", + (int)od_table->OverDriveTable.FanZeroRpmEnable); + + size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE"); + smu_v14_0_2_get_od_setting_limits(smu, + PP_OD_FEATURE_FAN_ZERO_RPM_ENABLE, + &min_value, + &max_value); + size += sysfs_emit_at(buf, size, "ZERO_RPM_ENABLE: %u %u\n", + min_value, max_value); + break; + case SMU_OD_RANGE: if (!smu_v14_0_2_is_od_feature_supported(smu, PP_OD_FEATURE_GFXCLK_BIT) && !smu_v14_0_2_is_od_feature_supported(smu, PP_OD_FEATURE_UCLK_BIT) && @@ -2270,7 +2293,9 @@ static void smu_v14_0_2_set_supported_od_feature_mask(struct smu_context *smu) OD_OPS_SUPPORT_FAN_TARGET_TEMPERATURE_RETRIEVE | OD_OPS_SUPPORT_FAN_TARGET_TEMPERATURE_SET | OD_OPS_SUPPORT_FAN_MINIMUM_PWM_RETRIEVE | - OD_OPS_SUPPORT_FAN_MINIMUM_PWM_SET; + OD_OPS_SUPPORT_FAN_MINIMUM_PWM_SET | + OD_OPS_SUPPORT_FAN_ZERO_RPM_ENABLE_RETRIEVE | + OD_OPS_SUPPORT_FAN_ZERO_RPM_ENABLE_SET; } static int smu_v14_0_2_get_overdrive_table(struct smu_context *smu, @@ -2349,6 +2374,8 @@ static int smu_v14_0_2_set_default_od_settings(struct smu_context *smu) user_od_table_bak.OverDriveTable.FanTargetTemperature; user_od_table->OverDriveTable.FanMinimumPwm = user_od_table_bak.OverDriveTable.FanMinimumPwm; + user_od_table->OverDriveTable.FanZeroRpmEnable = + user_od_table_bak.OverDriveTable.FanZeroRpmEnable; } smu_v14_0_2_set_supported_od_feature_mask(smu); @@ -2396,6 +2423,11 @@ static int smu_v14_0_2_od_restore_table_single(struct smu_context *smu, long inp od_table->OverDriveTable.FanMode = FAN_MODE_AUTO; od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT); break; + case PP_OD_EDIT_FAN_ZERO_RPM_ENABLE: + od_table->OverDriveTable.FanZeroRpmEnable = + boot_overdrive_table->OverDriveTable.FanZeroRpmEnable; + od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_ZERO_FAN_BIT); + break; case PP_OD_EDIT_ACOUSTIC_LIMIT: od_table->OverDriveTable.AcousticLimitRpmThreshold = boot_overdrive_table->OverDriveTable.AcousticLimitRpmThreshold; @@ -2678,6 +2710,27 @@ static int smu_v14_0_2_od_edit_dpm_table(struct smu_context *smu, od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT); break; + case PP_OD_EDIT_FAN_ZERO_RPM_ENABLE: + if (!smu_v14_0_2_is_od_feature_supported(smu, PP_OD_FEATURE_ZERO_FAN_BIT)) { + dev_warn(adev->dev, "Zero RPM setting not supported!\n"); + return -ENOTSUPP; + } + + smu_v14_0_2_get_od_setting_limits(smu, + PP_OD_FEATURE_FAN_ZERO_RPM_ENABLE, + &minimum, + &maximum); + if (input[0] < minimum || + input[0] > maximum) { + dev_info(adev->dev, "zero RPM enable setting(%ld) must be within [%d, %d]!\n", + input[0], minimum, maximum); + return -EINVAL; + } + + od_table->OverDriveTable.FanZeroRpmEnable = input[0]; + od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_ZERO_FAN_BIT); + break; + case PP_OD_RESTORE_DEFAULT_TABLE: if (size == 1) { ret = smu_v14_0_2_od_restore_table_single(smu, input[0]);
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c index d834d13..80eb1a0 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c
@@ -1083,6 +1083,9 @@ void smu_cmn_init_soft_gpu_metrics(void *table, uint8_t frev, uint8_t crev) case METRICS_VERSION(1, 7): structure_size = sizeof(struct gpu_metrics_v1_7); break; + case METRICS_VERSION(1, 8): + structure_size = sizeof(struct gpu_metrics_v1_8); + break; case METRICS_VERSION(2, 0): structure_size = sizeof(struct gpu_metrics_v2_0); break;
diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig index d20f164..09a1be2 100644 --- a/drivers/gpu/drm/bridge/Kconfig +++ b/drivers/gpu/drm/bridge/Kconfig
@@ -91,12 +91,13 @@ Support for i.MX8MP DPI-to-LVDS on-SoC encoder. config DRM_I2C_NXP_TDA998X - tristate "NXP Semiconductors TDA998X HDMI encoder" - default m if DRM_TILCDC - select CEC_CORE if CEC_NOTIFIER - select SND_SOC_HDMI_CODEC if SND_SOC - help - Support for NXP Semiconductors TDA998X HDMI encoders. + tristate "NXP Semiconductors TDA998X HDMI encoder" + default m if DRM_TILCDC + select CEC_CORE if CEC_NOTIFIER + select DRM_KMS_HELPER + select SND_SOC_HDMI_CODEC if SND_SOC + help + Support for NXP Semiconductors TDA998X HDMI encoders. config DRM_ITE_IT6263 tristate "ITE IT6263 LVDS/HDMI bridge"
diff --git a/drivers/gpu/drm/bridge/tda998x_drv.c b/drivers/gpu/drm/bridge/tda998x_drv.c index ebc758c..2065825 100644 --- a/drivers/gpu/drm/bridge/tda998x_drv.c +++ b/drivers/gpu/drm/bridge/tda998x_drv.c
@@ -1763,7 +1763,7 @@ static void tda998x_destroy(struct device *dev) if (priv->hdmi->irq) free_irq(priv->hdmi->irq, priv); - del_timer_sync(&priv->edid_delay_timer); + timer_delete_sync(&priv->edid_delay_timer); cancel_work_sync(&priv->detect_work); i2c_unregister_device(priv->cec);
diff --git a/drivers/gpu/drm/drm_vblank.c b/drivers/gpu/drm/drm_vblank.c index 94e45ed..78958dd 100644 --- a/drivers/gpu/drm/drm_vblank.c +++ b/drivers/gpu/drm/drm_vblank.c
@@ -508,7 +508,7 @@ static void drm_vblank_init_release(struct drm_device *dev, void *ptr) drm_core_check_feature(dev, DRIVER_MODESET)); drm_vblank_destroy_worker(vblank); - del_timer_sync(&vblank->disable_timer); + timer_delete_sync(&vblank->disable_timer); } /**
diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c index fd388b1..08cf79a 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
@@ -427,7 +427,7 @@ static void vidi_unbind(struct device *dev, struct device *master, void *data) { struct vidi_context *ctx = dev_get_drvdata(dev); - del_timer_sync(&ctx->timer); + timer_delete_sync(&ctx->timer); } static const struct component_ops vidi_component_ops = {
diff --git a/drivers/gpu/drm/gud/gud_pipe.c b/drivers/gpu/drm/gud/gud_pipe.c index e163649..77cfcf3 100644 --- a/drivers/gpu/drm/gud/gud_pipe.c +++ b/drivers/gpu/drm/gud/gud_pipe.c
@@ -254,7 +254,7 @@ static int gud_usb_bulk(struct gud_device *gdrm, size_t len) usb_sg_wait(&ctx.sgr); - if (!del_timer_sync(&ctx.timer)) + if (!timer_delete_sync(&ctx.timer)) ret = -ETIMEDOUT; else if (ctx.sgr.status < 0) ret = ctx.sgr.status;
diff --git a/drivers/gpu/drm/i915/display/intel_fbdev.h b/drivers/gpu/drm/i915/display/intel_fbdev.h index ca2c8c4..89bad3a 100644 --- a/drivers/gpu/drm/i915/display/intel_fbdev.h +++ b/drivers/gpu/drm/i915/display/intel_fbdev.h
@@ -6,6 +6,8 @@ #ifndef __INTEL_FBDEV_H__ #define __INTEL_FBDEV_H__ +#include <linux/types.h> + struct drm_fb_helper; struct drm_fb_helper_surface_size; struct drm_i915_private;
diff --git a/drivers/gpu/drm/i915/display/skl_watermark.c b/drivers/gpu/drm/i915/display/skl_watermark.c index 2d0de1c..621e979 100644 --- a/drivers/gpu/drm/i915/display/skl_watermark.c +++ b/drivers/gpu/drm/i915/display/skl_watermark.c
@@ -2314,6 +2314,7 @@ cdclk_prefill_adjustment(const struct intel_crtc_state *crtc_state) static int dsc_prefill_latency(const struct intel_crtc_state *crtc_state) { + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); const struct intel_crtc_scaler_state *scaler_state = &crtc_state->scaler_state; int linetime = DIV_ROUND_UP(1000 * crtc_state->hw.adjusted_mode.htotal, @@ -2323,7 +2324,9 @@ dsc_prefill_latency(const struct intel_crtc_state *crtc_state) crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR420 ? 2 : 1; u32 dsc_prefill_latency = 0; - if (!crtc_state->dsc.compression_enable || !num_scaler_users) + if (!crtc_state->dsc.compression_enable || + !num_scaler_users || + num_scaler_users > crtc->num_scalers) return dsc_prefill_latency; dsc_prefill_latency = DIV_ROUND_UP(15 * linetime * chroma_downscaling_factor, 10);
diff --git a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c index 4a80ffa..03baa7f 100644 --- a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c +++ b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c
@@ -2502,7 +2502,7 @@ static void execlists_irq_handler(struct intel_engine_cs *engine, u16 iir) ENGINE_READ_FW(engine, RING_EXECLIST_STATUS_HI)); ENGINE_TRACE(engine, "semaphore yield: %08x\n", engine->execlists.yield); - if (del_timer(&engine->execlists.timer)) + if (timer_delete(&engine->execlists.timer)) tasklet = true; } @@ -3370,8 +3370,8 @@ static void execlists_set_default_submission(struct intel_engine_cs *engine) static void execlists_shutdown(struct intel_engine_cs *engine) { /* Synchronise with residual timers and any softirq they raise */ - del_timer_sync(&engine->execlists.timer); - del_timer_sync(&engine->execlists.preempt); + timer_delete_sync(&engine->execlists.timer); + timer_delete_sync(&engine->execlists.preempt); tasklet_kill(&engine->sched_engine->tasklet); }
diff --git a/drivers/gpu/drm/i915/gt/intel_rps.c b/drivers/gpu/drm/i915/gt/intel_rps.c index 2cfaedb..64e9317 100644 --- a/drivers/gpu/drm/i915/gt/intel_rps.c +++ b/drivers/gpu/drm/i915/gt/intel_rps.c
@@ -161,7 +161,7 @@ static void rps_start_timer(struct intel_rps *rps) static void rps_stop_timer(struct intel_rps *rps) { - del_timer_sync(&rps->timer); + timer_delete_sync(&rps->timer); rps->pm_timestamp = ktime_sub(ktime_get(), rps->pm_timestamp); cancel_work_sync(&rps->work); }
diff --git a/drivers/gpu/drm/i915/gt/mock_engine.c b/drivers/gpu/drm/i915/gt/mock_engine.c index c0637bf..64315b7 100644 --- a/drivers/gpu/drm/i915/gt/mock_engine.c +++ b/drivers/gpu/drm/i915/gt/mock_engine.c
@@ -297,7 +297,7 @@ static void mock_reset_cancel(struct intel_engine_cs *engine) struct i915_request *rq; unsigned long flags; - del_timer_sync(&mock->hw_delay); + timer_delete_sync(&mock->hw_delay); spin_lock_irqsave(&engine->sched_engine->lock, flags); @@ -432,7 +432,7 @@ void mock_engine_flush(struct intel_engine_cs *engine) container_of(engine, typeof(*mock), base); struct i915_request *request, *rn; - del_timer_sync(&mock->hw_delay); + timer_delete_sync(&mock->hw_delay); spin_lock_irq(&mock->hw_lock); list_for_each_entry_safe(request, rn, &mock->hw_queue, mock.link)
diff --git a/drivers/gpu/drm/i915/gt/selftest_execlists.c b/drivers/gpu/drm/i915/gt/selftest_execlists.c index d7717de..0454eb1 100644 --- a/drivers/gpu/drm/i915/gt/selftest_execlists.c +++ b/drivers/gpu/drm/i915/gt/selftest_execlists.c
@@ -1198,7 +1198,7 @@ static int live_timeslice_rewind(void *arg) ENGINE_TRACE(engine, "forcing tasklet for rewind\n"); while (i915_request_is_active(rq[A2])) { /* semaphore yield! */ /* Wait for the timeslice to kick in */ - del_timer(&engine->execlists.timer); + timer_delete(&engine->execlists.timer); tasklet_hi_schedule(&engine->sched_engine->tasklet); intel_engine_flush_submission(engine); } @@ -2357,7 +2357,7 @@ static int __cancel_fail(struct live_preempt_cancel *arg) /* force preempt reset [failure] */ while (!engine->execlists.pending[0]) intel_engine_flush_submission(engine); - del_timer_sync(&engine->execlists.preempt); + timer_delete_sync(&engine->execlists.preempt); intel_engine_flush_submission(engine); cancel_reset_timeout(engine);
diff --git a/drivers/gpu/drm/i915/gt/selftest_migrate.c b/drivers/gpu/drm/i915/gt/selftest_migrate.c index 1bf7b88..401bee0 100644 --- a/drivers/gpu/drm/i915/gt/selftest_migrate.c +++ b/drivers/gpu/drm/i915/gt/selftest_migrate.c
@@ -660,7 +660,7 @@ static int live_emit_pte_full_ring(void *arg) out_rq: i915_request_add(rq); /* GEM_BUG_ON(rq->reserved_space > ring->space)? */ - del_timer_sync(&st.timer); + timer_delete_sync(&st.timer); destroy_timer_on_stack(&st.timer); out_unpin: intel_context_unpin(ce);
diff --git a/drivers/gpu/drm/i915/i915_iosf_mbi.h b/drivers/gpu/drm/i915/i915_iosf_mbi.h index 8f81b76..317075d 100644 --- a/drivers/gpu/drm/i915/i915_iosf_mbi.h +++ b/drivers/gpu/drm/i915/i915_iosf_mbi.h
@@ -31,12 +31,6 @@ iosf_mbi_unregister_pmic_bus_access_notifier_unlocked(struct notifier_block *nb) { return 0; } - -static inline -int iosf_mbi_unregister_pmic_bus_access_notifier(struct notifier_block *nb) -{ - return 0; -} #endif #endif /* __I915_IOSF_MBI_H__ */
diff --git a/drivers/gpu/drm/i915/i915_utils.c b/drivers/gpu/drm/i915/i915_utils.c index 2576f8f..b60c28f 100644 --- a/drivers/gpu/drm/i915/i915_utils.c +++ b/drivers/gpu/drm/i915/i915_utils.c
@@ -52,7 +52,7 @@ void cancel_timer(struct timer_list *t) if (!timer_active(t)) return; - del_timer(t); + timer_delete(t); WRITE_ONCE(t->expires, 0); }
diff --git a/drivers/gpu/drm/i915/intel_wakeref.c b/drivers/gpu/drm/i915/intel_wakeref.c index 87f2460..07e81be 100644 --- a/drivers/gpu/drm/i915/intel_wakeref.c +++ b/drivers/gpu/drm/i915/intel_wakeref.c
@@ -163,7 +163,7 @@ void intel_wakeref_auto(struct intel_wakeref_auto *wf, unsigned long timeout) unsigned long flags; if (!timeout) { - if (del_timer_sync(&wf->timer)) + if (timer_delete_sync(&wf->timer)) wakeref_auto_timeout(&wf->timer); return; }
diff --git a/drivers/gpu/drm/i915/selftests/lib_sw_fence.c b/drivers/gpu/drm/i915/selftests/lib_sw_fence.c index bf2752c..d5ecc68 100644 --- a/drivers/gpu/drm/i915/selftests/lib_sw_fence.c +++ b/drivers/gpu/drm/i915/selftests/lib_sw_fence.c
@@ -74,7 +74,7 @@ void timed_fence_init(struct timed_fence *tf, unsigned long expires) void timed_fence_fini(struct timed_fence *tf) { - if (del_timer_sync(&tf->timer)) + if (timer_delete_sync(&tf->timer)) i915_sw_fence_commit(&tf->fence); destroy_timer_on_stack(&tf->timer);
diff --git a/drivers/gpu/drm/mediatek/mtk_dp.c b/drivers/gpu/drm/mediatek/mtk_dp.c index ccdc57c..fed3307 100644 --- a/drivers/gpu/drm/mediatek/mtk_dp.c +++ b/drivers/gpu/drm/mediatek/mtk_dp.c
@@ -2847,7 +2847,7 @@ static void mtk_dp_remove(struct platform_device *pdev) pm_runtime_put(&pdev->dev); pm_runtime_disable(&pdev->dev); if (mtk_dp->data->bridge_type != DRM_MODE_CONNECTOR_eDP) - del_timer_sync(&mtk_dp->debounce_timer); + timer_delete_sync(&mtk_dp->debounce_timer); platform_device_unregister(mtk_dp->phy_dev); if (mtk_dp->audio_pdev) platform_device_unregister(mtk_dp->audio_pdev);
diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c index 71dca78..650e5ba 100644 --- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
@@ -1253,7 +1253,7 @@ static void a5xx_fault_detect_irq(struct msm_gpu *gpu) gpu_read(gpu, REG_A5XX_CP_IB2_BUFSZ)); /* Turn off the hangcheck timer to keep it from bothering us */ - del_timer(&gpu->hangcheck_timer); + timer_delete(&gpu->hangcheck_timer); kthread_queue_work(gpu->worker, &gpu->recover_work); }
diff --git a/drivers/gpu/drm/msm/adreno/a5xx_preempt.c b/drivers/gpu/drm/msm/adreno/a5xx_preempt.c index 0469fea..36f72c4 100644 --- a/drivers/gpu/drm/msm/adreno/a5xx_preempt.c +++ b/drivers/gpu/drm/msm/adreno/a5xx_preempt.c
@@ -182,7 +182,7 @@ void a5xx_preempt_irq(struct msm_gpu *gpu) return; /* Delete the preemption watchdog timer */ - del_timer(&a5xx_gpu->preempt_timer); + timer_delete(&a5xx_gpu->preempt_timer); /* * The hardware should be setting CP_CONTEXT_SWITCH_CNTL to zero before
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c index 38c9491..c871193 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
@@ -28,7 +28,7 @@ static void a6xx_gmu_fault(struct a6xx_gmu *gmu) gmu->hung = true; /* Turn off the hangcheck timer while we are resetting */ - del_timer(&gpu->hangcheck_timer); + timer_delete(&gpu->hangcheck_timer); /* Queue the GPU handler because we need to treat this as a recovery */ kthread_queue_work(gpu->worker, &gpu->recover_work);
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c index 1820c16..06465bc 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
@@ -1706,7 +1706,7 @@ static void a6xx_fault_detect_irq(struct msm_gpu *gpu) gpu_read(gpu, REG_A6XX_CP_IB2_REM_SIZE)); /* Turn off the hangcheck timer to keep it from bothering us */ - del_timer(&gpu->hangcheck_timer); + timer_delete(&gpu->hangcheck_timer); kthread_queue_work(gpu->worker, &gpu->recover_work); } @@ -1726,7 +1726,7 @@ static void a7xx_sw_fuse_violation_irq(struct msm_gpu *gpu) */ if (status & (A7XX_CX_MISC_SW_FUSE_VALUE_RAYTRACING | A7XX_CX_MISC_SW_FUSE_VALUE_LPAC)) { - del_timer(&gpu->hangcheck_timer); + timer_delete(&gpu->hangcheck_timer); kthread_queue_work(gpu->worker, &gpu->recover_work); }
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_preempt.c b/drivers/gpu/drm/msm/adreno/a6xx_preempt.c index 2fd4e39..9b5e27d 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_preempt.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_preempt.c
@@ -146,7 +146,7 @@ void a6xx_preempt_irq(struct msm_gpu *gpu) return; /* Delete the preemption watchdog timer */ - del_timer(&a6xx_gpu->preempt_timer); + timer_delete(&a6xx_gpu->preempt_timer); /* * The hardware should be setting the stop bit of CP_CONTEXT_SWITCH_CNTL
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c index 7156cda..26db1f4 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
@@ -292,7 +292,7 @@ int adreno_fault_handler(struct msm_gpu *gpu, unsigned long iova, int flags, if (do_devcoredump) { /* Turn off the hangcheck timer to keep it from bothering us */ - del_timer(&gpu->hangcheck_timer); + timer_delete(&gpu->hangcheck_timer); gpu->fault_info.ttbr0 = info->ttbr0; gpu->fault_info.iova = iova;
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index 284e69b..8610bbf 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -1410,7 +1410,7 @@ static void dpu_encoder_virt_atomic_disable(struct drm_encoder *drm_enc, /* after phys waits for frame-done, should be no more frames pending */ if (atomic_xchg(&dpu_enc->frame_done_timeout_ms, 0)) { DPU_ERROR("enc%d timeout pending\n", drm_enc->base.id); - del_timer_sync(&dpu_enc->frame_done_timer); + timer_delete_sync(&dpu_enc->frame_done_timer); } dpu_encoder_resource_control(drm_enc, DPU_ENC_RC_EVENT_STOP); @@ -1582,7 +1582,7 @@ void dpu_encoder_frame_done_callback( if (!dpu_enc->frame_busy_mask[0]) { atomic_set(&dpu_enc->frame_done_timeout_ms, 0); - del_timer(&dpu_enc->frame_done_timer); + timer_delete(&dpu_enc->frame_done_timer); dpu_encoder_resource_control(drm_enc, DPU_ENC_RC_EVENT_FRAME_DONE);
diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c b/drivers/gpu/drm/omapdrm/dss/dsi.c index 59d20eb..9b9cc59 100644 --- a/drivers/gpu/drm/omapdrm/dss/dsi.c +++ b/drivers/gpu/drm/omapdrm/dss/dsi.c
@@ -452,7 +452,7 @@ static irqreturn_t omap_dsi_irq_handler(int irq, void *arg) #ifdef DSI_CATCH_MISSING_TE if (irqstatus & DSI_IRQ_TE_TRIGGER) - del_timer(&dsi->te_timer); + timer_delete(&dsi->te_timer); #endif /* make a copy and unlock, so that isrs can unregister
diff --git a/drivers/gpu/drm/vc4/vc4_bo.c b/drivers/gpu/drm/vc4/vc4_bo.c index fb450b6..7125773 100644 --- a/drivers/gpu/drm/vc4/vc4_bo.c +++ b/drivers/gpu/drm/vc4/vc4_bo.c
@@ -1043,7 +1043,7 @@ static void vc4_bo_cache_destroy(struct drm_device *dev, void *unused) struct vc4_dev *vc4 = to_vc4_dev(dev); int i; - del_timer(&vc4->bo_cache.time_timer); + timer_delete(&vc4->bo_cache.time_timer); cancel_work_sync(&vc4->bo_cache.time_work); vc4_bo_cache_purge(dev);
diff --git a/drivers/gpu/drm/vgem/vgem_fence.c b/drivers/gpu/drm/vgem/vgem_fence.c index e1575417..37bb1fb 100644 --- a/drivers/gpu/drm/vgem/vgem_fence.c +++ b/drivers/gpu/drm/vgem/vgem_fence.c
@@ -49,7 +49,7 @@ static void vgem_fence_release(struct dma_fence *base) { struct vgem_fence *fence = container_of(base, typeof(*fence), base); - del_timer_sync(&fence->timer); + timer_delete_sync(&fence->timer); dma_fence_free(&fence->base); }
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_msg.c b/drivers/gpu/drm/vmwgfx/vmwgfx_msg.c index 1f15990..1d9a42c 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_msg.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_msg.c
@@ -289,7 +289,7 @@ static int vmw_send_msg(struct rpc_channel *channel, const char *msg) return -EINVAL; } -STACK_FRAME_NON_STANDARD(vmw_send_msg); +STACK_FRAME_NON_STANDARD_FP(vmw_send_msg); /**
diff --git a/drivers/gpu/drm/xe/Kconfig b/drivers/gpu/drm/xe/Kconfig index 7d79951..5c2f459 100644 --- a/drivers/gpu/drm/xe/Kconfig +++ b/drivers/gpu/drm/xe/Kconfig
@@ -53,7 +53,7 @@ config DRM_XE_DISPLAY bool "Enable display support" depends on DRM_XE && DRM_XE=m && HAS_IOPORT - select FB_IOMEM_HELPERS + select FB_IOMEM_HELPERS if DRM_FBDEV_EMULATION select I2C select I2C_ALGOBIT default y
diff --git a/drivers/gpu/drm/xe/regs/xe_engine_regs.h b/drivers/gpu/drm/xe/regs/xe_engine_regs.h index 4f372dc..fb8ec31 100644 --- a/drivers/gpu/drm/xe/regs/xe_engine_regs.h +++ b/drivers/gpu/drm/xe/regs/xe_engine_regs.h
@@ -130,6 +130,10 @@ #define RING_EXECLIST_STATUS_LO(base) XE_REG((base) + 0x234) #define RING_EXECLIST_STATUS_HI(base) XE_REG((base) + 0x234 + 4) +#define RING_IDLEDLY(base) XE_REG((base) + 0x23c) +#define INHIBIT_SWITCH_UNTIL_PREEMPTED REG_BIT(31) +#define IDLE_DELAY REG_GENMASK(20, 0) + #define RING_CONTEXT_CONTROL(base) XE_REG((base) + 0x244, XE_REG_OPTION_MASKED) #define CTX_CTRL_PXP_ENABLE REG_BIT(10) #define CTX_CTRL_OAC_CONTEXT_ENABLE REG_BIT(8)
diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c index 5d79b43..0019122 100644 --- a/drivers/gpu/drm/xe/xe_device.c +++ b/drivers/gpu/drm/xe/xe_device.c
@@ -53,6 +53,7 @@ #include "xe_pxp.h" #include "xe_query.h" #include "xe_shrinker.h" +#include "xe_survivability_mode.h" #include "xe_sriov.h" #include "xe_tile.h" #include "xe_ttm_stolen_mgr.h" @@ -705,8 +706,20 @@ int xe_device_probe_early(struct xe_device *xe) sriov_update_device_info(xe); err = xe_pcode_probe_early(xe); - if (err) - return err; + if (err) { + int save_err = err; + + /* + * Try to leave device in survivability mode if device is + * possible, but still return the previous error for error + * propagation + */ + err = xe_survivability_mode_enable(xe); + if (err) + return err; + + return save_err; + } err = wait_for_lmem_ready(xe); if (err)
diff --git a/drivers/gpu/drm/xe/xe_eu_stall.c b/drivers/gpu/drm/xe/xe_eu_stall.c index 88a92ba..f2bb916 100644 --- a/drivers/gpu/drm/xe/xe_eu_stall.c +++ b/drivers/gpu/drm/xe/xe_eu_stall.c
@@ -222,13 +222,7 @@ int xe_eu_stall_init(struct xe_gt *gt) goto exit_free; } - ret = devm_add_action_or_reset(xe->drm.dev, xe_eu_stall_fini, gt); - if (ret) - goto exit_destroy; - - return 0; -exit_destroy: - destroy_workqueue(gt->eu_stall->buf_ptr_poll_wq); + return devm_add_action_or_reset(xe->drm.dev, xe_eu_stall_fini, gt); exit_free: mutex_destroy(>->eu_stall->stream_lock); kfree(gt->eu_stall);
diff --git a/drivers/gpu/drm/xe/xe_execlist.c b/drivers/gpu/drm/xe/xe_execlist.c index 9fbed1a..788f56b 100644 --- a/drivers/gpu/drm/xe/xe_execlist.c +++ b/drivers/gpu/drm/xe/xe_execlist.c
@@ -297,7 +297,7 @@ struct xe_execlist_port *xe_execlist_port_create(struct xe_device *xe, void xe_execlist_port_destroy(struct xe_execlist_port *port) { - del_timer(&port->irq_fail); + timer_delete(&port->irq_fail); /* Prevent an interrupt while we're destroying */ spin_lock_irq(>_to_xe(port->hwe->gt)->irq.lock);
diff --git a/drivers/gpu/drm/xe/xe_gt_clock.c b/drivers/gpu/drm/xe/xe_gt_clock.c index 2a958c9..4f011d1 100644 --- a/drivers/gpu/drm/xe/xe_gt_clock.c +++ b/drivers/gpu/drm/xe/xe_gt_clock.c
@@ -16,35 +16,47 @@ #include "xe_macros.h" #include "xe_mmio.h" -static u32 get_crystal_clock_freq(u32 rpm_config_reg) +#define f19_2_mhz 19200000 +#define f24_mhz 24000000 +#define f25_mhz 25000000 +#define f38_4_mhz 38400000 +#define ts_base_83 83333 +#define ts_base_52 52083 +#define ts_base_80 80000 + +static void read_crystal_clock(struct xe_gt *gt, u32 rpm_config_reg, u32 *freq, + u32 *timestamp_base) { - const u32 f19_2_mhz = 19200000; - const u32 f24_mhz = 24000000; - const u32 f25_mhz = 25000000; - const u32 f38_4_mhz = 38400000; u32 crystal_clock = REG_FIELD_GET(RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_MASK, rpm_config_reg); switch (crystal_clock) { case RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_24_MHZ: - return f24_mhz; + *freq = f24_mhz; + *timestamp_base = ts_base_83; + return; case RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_19_2_MHZ: - return f19_2_mhz; + *freq = f19_2_mhz; + *timestamp_base = ts_base_52; + return; case RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_38_4_MHZ: - return f38_4_mhz; + *freq = f38_4_mhz; + *timestamp_base = ts_base_52; + return; case RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_25_MHZ: - return f25_mhz; + *freq = f25_mhz; + *timestamp_base = ts_base_80; + return; default: - XE_WARN_ON("NOT_POSSIBLE"); - return 0; + xe_gt_warn(gt, "Invalid crystal clock frequency: %u", crystal_clock); + *freq = 0; + *timestamp_base = 0; + return; } } -int xe_gt_clock_init(struct xe_gt *gt) +static void check_ctc_mode(struct xe_gt *gt) { - u32 c0 = xe_mmio_read32(>->mmio, RPM_CONFIG0); - u32 freq = 0; - /* * CTC_MODE[0] = 1 is definitely not supported for Xe2 and later * platforms. In theory it could be a valid setting for pre-Xe2 @@ -57,8 +69,18 @@ int xe_gt_clock_init(struct xe_gt *gt) */ if (xe_mmio_read32(>->mmio, CTC_MODE) & CTC_SOURCE_DIVIDE_LOGIC) xe_gt_warn(gt, "CTC_MODE[0] is set; this is unexpected and undocumented\n"); +} - freq = get_crystal_clock_freq(c0); +int xe_gt_clock_init(struct xe_gt *gt) +{ + u32 freq; + u32 c0; + + if (!IS_SRIOV_VF(gt_to_xe(gt))) + check_ctc_mode(gt); + + c0 = xe_mmio_read32(>->mmio, RPM_CONFIG0); + read_crystal_clock(gt, c0, &freq, >->info.timestamp_base); /* * Now figure out how the command stream's timestamp
diff --git a/drivers/gpu/drm/xe/xe_gt_types.h b/drivers/gpu/drm/xe/xe_gt_types.h index e3cfb02..7def095 100644 --- a/drivers/gpu/drm/xe/xe_gt_types.h +++ b/drivers/gpu/drm/xe/xe_gt_types.h
@@ -121,6 +121,8 @@ struct xe_gt { enum xe_gt_type type; /** @info.reference_clock: clock frequency */ u32 reference_clock; + /** @info.timestamp_base: GT timestamp base */ + u32 timestamp_base; /** * @info.engine_mask: mask of engines present on GT. Some of * them may be reserved in runtime and not available for user.
diff --git a/drivers/gpu/drm/xe/xe_hw_engine.c b/drivers/gpu/drm/xe/xe_hw_engine.c index 223b95d..8c05fd3 100644 --- a/drivers/gpu/drm/xe/xe_hw_engine.c +++ b/drivers/gpu/drm/xe/xe_hw_engine.c
@@ -8,7 +8,9 @@ #include <linux/nospec.h> #include <drm/drm_managed.h> +#include <drm/drm_print.h> #include <uapi/drm/xe_drm.h> +#include <generated/xe_wa_oob.h> #include "regs/xe_engine_regs.h" #include "regs/xe_gt_regs.h" @@ -21,6 +23,7 @@ #include "xe_gsc.h" #include "xe_gt.h" #include "xe_gt_ccs_mode.h" +#include "xe_gt_clock.h" #include "xe_gt_printk.h" #include "xe_gt_mcr.h" #include "xe_gt_topology.h" @@ -564,6 +567,33 @@ static void hw_engine_init_early(struct xe_gt *gt, struct xe_hw_engine *hwe, xe_reg_whitelist_process_engine(hwe); } +static void adjust_idledly(struct xe_hw_engine *hwe) +{ + struct xe_gt *gt = hwe->gt; + u32 idledly, maxcnt; + u32 idledly_units_ps = 8 * gt->info.timestamp_base; + u32 maxcnt_units_ns = 640; + bool inhibit_switch = 0; + + if (!IS_SRIOV_VF(gt_to_xe(hwe->gt)) && XE_WA(gt, 16023105232)) { + idledly = xe_mmio_read32(>->mmio, RING_IDLEDLY(hwe->mmio_base)); + maxcnt = xe_mmio_read32(>->mmio, RING_PWRCTX_MAXCNT(hwe->mmio_base)); + + inhibit_switch = idledly & INHIBIT_SWITCH_UNTIL_PREEMPTED; + idledly = REG_FIELD_GET(IDLE_DELAY, idledly); + idledly = DIV_ROUND_CLOSEST(idledly * idledly_units_ps, 1000); + maxcnt = REG_FIELD_GET(IDLE_WAIT_TIME, maxcnt); + maxcnt *= maxcnt_units_ns; + + if (xe_gt_WARN_ON(gt, idledly >= maxcnt || inhibit_switch)) { + idledly = DIV_ROUND_CLOSEST(((maxcnt - 1) * maxcnt_units_ns), + idledly_units_ps); + idledly = DIV_ROUND_CLOSEST(idledly, 1000); + xe_mmio_write32(>->mmio, RING_IDLEDLY(hwe->mmio_base), idledly); + } + } +} + static int hw_engine_init(struct xe_gt *gt, struct xe_hw_engine *hwe, enum xe_hw_engine_id id) { @@ -604,6 +634,9 @@ static int hw_engine_init(struct xe_gt *gt, struct xe_hw_engine *hwe, if (xe->info.has_usm && hwe->class == XE_ENGINE_CLASS_COPY) gt->usm.reserved_bcs_instance = hwe->instance; + /* Ensure IDLEDLY is lower than MAXCNT */ + adjust_idledly(hwe); + return devm_add_action_or_reset(xe->drm.dev, hw_engine_fini, hwe); err_hwsp:
diff --git a/drivers/gpu/drm/xe/xe_pci.c b/drivers/gpu/drm/xe/xe_pci.c index da9679c..818f023 100644 --- a/drivers/gpu/drm/xe/xe_pci.c +++ b/drivers/gpu/drm/xe/xe_pci.c
@@ -803,16 +803,14 @@ static int xe_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) return err; err = xe_device_probe_early(xe); - - /* - * In Boot Survivability mode, no drm card is exposed and driver is - * loaded with bare minimum to allow for firmware to be flashed through - * mei. If early probe fails, check if survivability mode is flagged by - * HW to be enabled. In that case enable it and return success. - */ if (err) { - if (xe_survivability_mode_required(xe) && - xe_survivability_mode_enable(xe)) + /* + * In Boot Survivability mode, no drm card is exposed and driver + * is loaded with bare minimum to allow for firmware to be + * flashed through mei. If early probe failed, but it managed to + * enable survivability mode, return success. + */ + if (xe_survivability_mode_is_enabled(xe)) return 0; return err;
diff --git a/drivers/gpu/drm/xe/xe_survivability_mode.c b/drivers/gpu/drm/xe/xe_survivability_mode.c index d939ce7..cb813b3 100644 --- a/drivers/gpu/drm/xe/xe_survivability_mode.c +++ b/drivers/gpu/drm/xe/xe_survivability_mode.c
@@ -155,13 +155,21 @@ static int enable_survivability_mode(struct pci_dev *pdev) if (ret) return ret; + /* Make sure xe_heci_gsc_init() knows about survivability mode */ + survivability->mode = true; + ret = xe_heci_gsc_init(xe); - if (ret) + if (ret) { + /* + * But if it fails, device can't enter survivability + * so move it back for correct error handling + */ + survivability->mode = false; return ret; + } xe_vsec_init(xe); - survivability->mode = true; dev_err(dev, "In Survivability Mode\n"); return 0; @@ -178,15 +186,16 @@ bool xe_survivability_mode_is_enabled(struct xe_device *xe) return xe->survivability.mode; } -/** - * xe_survivability_mode_required - checks if survivability mode is required - * @xe: xe device instance +/* + * survivability_mode_requested - check if it's possible to enable + * survivability mode and that was requested by firmware * - * This function reads the boot status from Pcode + * This function reads the boot status from Pcode. * - * Return: true if boot status indicates failure, false otherwise + * Return: true if platform support is available and boot status indicates + * failure, false otherwise. */ -bool xe_survivability_mode_required(struct xe_device *xe) +static bool survivability_mode_requested(struct xe_device *xe) { struct xe_survivability *survivability = &xe->survivability; struct xe_mmio *mmio = xe_root_tile_mmio(xe); @@ -208,7 +217,8 @@ bool xe_survivability_mode_required(struct xe_device *xe) * * Initialize survivability information and enable survivability mode * - * Return: 0 for success, negative error code otherwise. + * Return: 0 if survivability mode is enabled or not requested; negative error + * code otherwise. */ int xe_survivability_mode_enable(struct xe_device *xe) { @@ -216,6 +226,9 @@ int xe_survivability_mode_enable(struct xe_device *xe) struct xe_survivability_info *info; struct pci_dev *pdev = to_pci_dev(xe->drm.dev); + if (!survivability_mode_requested(xe)) + return 0; + survivability->size = MAX_SCRATCH_MMIO; info = devm_kcalloc(xe->drm.dev, survivability->size, sizeof(*info),
diff --git a/drivers/gpu/drm/xe/xe_survivability_mode.h b/drivers/gpu/drm/xe/xe_survivability_mode.h index f4df5f90..d7e6488 100644 --- a/drivers/gpu/drm/xe/xe_survivability_mode.h +++ b/drivers/gpu/drm/xe/xe_survivability_mode.h
@@ -12,6 +12,5 @@ struct xe_device; int xe_survivability_mode_enable(struct xe_device *xe); bool xe_survivability_mode_is_enabled(struct xe_device *xe); -bool xe_survivability_mode_required(struct xe_device *xe); #endif /* _XE_SURVIVABILITY_MODE_H_ */
diff --git a/drivers/gpu/drm/xe/xe_wa.c b/drivers/gpu/drm/xe/xe_wa.c index a25afb7..24f644c 100644 --- a/drivers/gpu/drm/xe/xe_wa.c +++ b/drivers/gpu/drm/xe/xe_wa.c
@@ -622,6 +622,12 @@ static const struct xe_rtp_entry_sr engine_was[] = { FUNC(xe_rtp_match_first_render_or_compute)), XE_RTP_ACTIONS(SET(TDL_TSL_CHICKEN, RES_CHK_SPR_DIS)) }, + { XE_RTP_NAME("16023105232"), + XE_RTP_RULES(MEDIA_VERSION_RANGE(1301, 3000), OR, + GRAPHICS_VERSION_RANGE(2001, 3001)), + XE_RTP_ACTIONS(SET(RING_PSMI_CTL(0), RC_SEMA_IDLE_MSG_DISABLE, + XE_RTP_ACTION_FLAG(ENGINE_BASE))) + }, }; static const struct xe_rtp_entry_sr lrc_was[] = {
diff --git a/drivers/gpu/drm/xe/xe_wa_oob.rules b/drivers/gpu/drm/xe/xe_wa_oob.rules index e0c5fa4..0c738af 100644 --- a/drivers/gpu/drm/xe/xe_wa_oob.rules +++ b/drivers/gpu/drm/xe/xe_wa_oob.rules
@@ -53,3 +53,5 @@ GRAPHICS_VERSION_RANGE(1270, 1274) 1508761755 GRAPHICS_VERSION(1255) GRAPHICS_VERSION(1260), GRAPHICS_STEP(A0, B0) +16023105232 GRAPHICS_VERSION_RANGE(2001, 3001) + MEDIA_VERSION_RANGE(1301, 3000)
diff --git a/drivers/greybus/operation.c b/drivers/greybus/operation.c index 8459e9b..f6beeeb 100644 --- a/drivers/greybus/operation.c +++ b/drivers/greybus/operation.c
@@ -279,7 +279,7 @@ static void gb_operation_work(struct work_struct *work) if (gb_operation_is_incoming(operation)) { gb_operation_request_handle(operation); } else { - ret = del_timer_sync(&operation->timer); + ret = timer_delete_sync(&operation->timer); if (!ret) { /* Cancel request message if scheduled by timeout. */ if (gb_operation_result(operation) == -ETIMEDOUT)
diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c index d900dd0..ed34f5c 100644 --- a/drivers/hid/hid-apple.c +++ b/drivers/hid/hid-apple.c
@@ -950,7 +950,7 @@ static int apple_probe(struct hid_device *hdev, return 0; out_err: - del_timer_sync(&asc->battery_timer); + timer_delete_sync(&asc->battery_timer); hid_hw_stop(hdev); return ret; } @@ -959,7 +959,7 @@ static void apple_remove(struct hid_device *hdev) { struct apple_sc *asc = hid_get_drvdata(hdev); - del_timer_sync(&asc->battery_timer); + timer_delete_sync(&asc->battery_timer); hid_hw_stop(hdev); }
diff --git a/drivers/hid/hid-appleir.c b/drivers/hid/hid-appleir.c index c45e5aa..bb7db9a 100644 --- a/drivers/hid/hid-appleir.c +++ b/drivers/hid/hid-appleir.c
@@ -319,7 +319,7 @@ static void appleir_remove(struct hid_device *hid) { struct appleir *appleir = hid_get_drvdata(hid); hid_hw_stop(hid); - del_timer_sync(&appleir->key_up_timer); + timer_delete_sync(&appleir->key_up_timer); } static const struct hid_device_id appleir_devices[] = {
diff --git a/drivers/hid/hid-appletb-kbd.c b/drivers/hid/hid-appletb-kbd.c index d4b95aa..029ccba 100644 --- a/drivers/hid/hid-appletb-kbd.c +++ b/drivers/hid/hid-appletb-kbd.c
@@ -448,7 +448,7 @@ static void appletb_kbd_remove(struct hid_device *hdev) appletb_kbd_set_mode(kbd, APPLETB_KBD_MODE_OFF); input_unregister_handler(&kbd->inp_handler); - del_timer_sync(&kbd->inactivity_timer); + timer_delete_sync(&kbd->inactivity_timer); hid_hw_close(hdev); hid_hw_stop(hdev);
diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c index a76f171..adfa329 100644 --- a/drivers/hid/hid-magicmouse.c +++ b/drivers/hid/hid-magicmouse.c
@@ -915,7 +915,7 @@ static int magicmouse_probe(struct hid_device *hdev, return 0; err_stop_hw: - del_timer_sync(&msc->battery_timer); + timer_delete_sync(&msc->battery_timer); hid_hw_stop(hdev); return ret; } @@ -926,7 +926,7 @@ static void magicmouse_remove(struct hid_device *hdev) if (msc) { cancel_delayed_work_sync(&msc->work); - del_timer_sync(&msc->battery_timer); + timer_delete_sync(&msc->battery_timer); } hid_hw_stop(hdev);
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index e50887a..7ac8e16 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c
@@ -1299,7 +1299,7 @@ static void mt_touch_report(struct hid_device *hid, mod_timer(&td->release_timer, jiffies + msecs_to_jiffies(100)); else - del_timer(&td->release_timer); + timer_delete(&td->release_timer); } clear_bit_unlock(MT_IO_FLAGS_RUNNING, &td->mt_io_flags); @@ -1881,7 +1881,7 @@ static void mt_remove(struct hid_device *hdev) { struct mt_device *td = hid_get_drvdata(hdev); - del_timer_sync(&td->release_timer); + timer_delete_sync(&td->release_timer); sysfs_remove_group(&hdev->dev.kobj, &mt_attribute_group); hid_hw_stop(hdev);
diff --git a/drivers/hid/hid-nvidia-shield.c b/drivers/hid/hid-nvidia-shield.c index ff9078a..b0c40a2 100644 --- a/drivers/hid/hid-nvidia-shield.c +++ b/drivers/hid/hid-nvidia-shield.c
@@ -1102,7 +1102,7 @@ static void shield_remove(struct hid_device *hdev) hid_hw_close(hdev); thunderstrike_destroy(ts); - del_timer_sync(&ts->psy_stats_timer); + timer_delete_sync(&ts->psy_stats_timer); cancel_work_sync(&ts->hostcmd_req_work); hid_hw_stop(hdev); }
diff --git a/drivers/hid/hid-prodikeys.c b/drivers/hid/hid-prodikeys.c index 3d08c19..c6b922c 100644 --- a/drivers/hid/hid-prodikeys.c +++ b/drivers/hid/hid-prodikeys.c
@@ -254,7 +254,7 @@ static void stop_sustain_timers(struct pcmidi_snd *pm) for (i = 0; i < PCMIDI_SUSTAINED_MAX; i++) { pms = &pm->sustained_notes[i]; pms->in_use = 1; - del_timer_sync(&pms->timer); + timer_delete_sync(&pms->timer); } }
diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index 5258b45..a2be652 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c
@@ -2164,7 +2164,7 @@ static void sony_remove(struct hid_device *hdev) struct sony_sc *sc = hid_get_drvdata(hdev); if (sc->quirks & (GHL_GUITAR_PS3WIIU | GHL_GUITAR_PS4)) { - del_timer_sync(&sc->ghl_poke_timer); + timer_delete_sync(&sc->ghl_poke_timer); usb_free_urb(sc->ghl_urb); }
diff --git a/drivers/hid/hid-uclogic-core.c b/drivers/hid/hid-uclogic-core.c index d800893..a367df6 100644 --- a/drivers/hid/hid-uclogic-core.c +++ b/drivers/hid/hid-uclogic-core.c
@@ -474,7 +474,7 @@ static void uclogic_remove(struct hid_device *hdev) { struct uclogic_drvdata *drvdata = hid_get_drvdata(hdev); - del_timer_sync(&drvdata->inrange_timer); + timer_delete_sync(&drvdata->inrange_timer); hid_hw_stop(hdev); kfree(drvdata->desc_ptr); uclogic_params_cleanup(&drvdata->params);
diff --git a/drivers/hid/hid-wiimote-core.c b/drivers/hid/hid-wiimote-core.c index 26167cf..8080083 100644 --- a/drivers/hid/hid-wiimote-core.c +++ b/drivers/hid/hid-wiimote-core.c
@@ -1171,7 +1171,7 @@ static void wiimote_init_hotplug(struct wiimote_data *wdata) wiimote_cmd_release(wdata); /* delete MP hotplug timer */ - del_timer_sync(&wdata->timer); + timer_delete_sync(&wdata->timer); } else { /* reschedule MP hotplug timer */ if (!(flags & WIIPROTO_FLAG_BUILTIN_MP) &&
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index 44c2351..7d9297f 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c
@@ -1462,13 +1462,13 @@ static void usbhid_disconnect(struct usb_interface *intf) static void hid_cancel_delayed_stuff(struct usbhid_device *usbhid) { - del_timer_sync(&usbhid->io_retry); + timer_delete_sync(&usbhid->io_retry); cancel_work_sync(&usbhid->reset_work); } static void hid_cease_io(struct usbhid_device *usbhid) { - del_timer_sync(&usbhid->io_retry); + timer_delete_sync(&usbhid->io_retry); usb_kill_urb(usbhid->urbin); usb_kill_urb(usbhid->urbctrl); usb_kill_urb(usbhid->urbout);
diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c index 97393a3..1556d4287 100644 --- a/drivers/hid/wacom_sys.c +++ b/drivers/hid/wacom_sys.c
@@ -2896,7 +2896,7 @@ static void wacom_remove(struct hid_device *hdev) cancel_work_sync(&wacom->battery_work); cancel_work_sync(&wacom->remote_work); cancel_work_sync(&wacom->mode_change_work); - del_timer_sync(&wacom->idleprox_timer); + timer_delete_sync(&wacom->idleprox_timer); if (hdev->bus == BUS_BLUETOOTH) device_remove_file(&hdev->dev, &dev_attr_speed);
diff --git a/drivers/hsi/clients/ssi_protocol.c b/drivers/hsi/clients/ssi_protocol.c index 6105ea9..cbc5e72 100644 --- a/drivers/hsi/clients/ssi_protocol.c +++ b/drivers/hsi/clients/ssi_protocol.c
@@ -281,9 +281,9 @@ static void ssip_set_rxstate(struct ssi_protocol *ssi, unsigned int state) ssi->recv_state = state; switch (state) { case RECV_IDLE: - del_timer(&ssi->rx_wd); + timer_delete(&ssi->rx_wd); if (ssi->send_state == SEND_IDLE) - del_timer(&ssi->keep_alive); + timer_delete(&ssi->keep_alive); break; case RECV_READY: /* CMT speech workaround */ @@ -306,9 +306,9 @@ static void ssip_set_txstate(struct ssi_protocol *ssi, unsigned int state) switch (state) { case SEND_IDLE: case SEND_READY: - del_timer(&ssi->tx_wd); + timer_delete(&ssi->tx_wd); if (ssi->recv_state == RECV_IDLE) - del_timer(&ssi->keep_alive); + timer_delete(&ssi->keep_alive); break; case WAIT4READY: case SENDING: @@ -398,9 +398,9 @@ static void ssip_reset(struct hsi_client *cl) if (test_and_clear_bit(SSIP_WAKETEST_FLAG, &ssi->flags)) ssi_waketest(cl, 0); /* FIXME: To be removed */ spin_lock_bh(&ssi->lock); - del_timer(&ssi->rx_wd); - del_timer(&ssi->tx_wd); - del_timer(&ssi->keep_alive); + timer_delete(&ssi->rx_wd); + timer_delete(&ssi->tx_wd); + timer_delete(&ssi->keep_alive); cancel_work_sync(&ssi->work); ssi->main_state = 0; ssi->send_state = 0; @@ -648,7 +648,7 @@ static void ssip_rx_data_complete(struct hsi_msg *msg) ssip_error(cl); return; } - del_timer(&ssi->rx_wd); /* FIXME: Revisit */ + timer_delete(&ssi->rx_wd); /* FIXME: Revisit */ skb = msg->context; ssip_pn_rx(skb); hsi_free_msg(msg); @@ -731,7 +731,7 @@ static void ssip_rx_waketest(struct hsi_client *cl, u32 cmd) spin_lock_bh(&ssi->lock); ssi->main_state = ACTIVE; - del_timer(&ssi->tx_wd); /* Stop boot handshake timer */ + timer_delete(&ssi->tx_wd); /* Stop boot handshake timer */ spin_unlock_bh(&ssi->lock); dev_notice(&cl->device, "WAKELINES TEST %s\n",
diff --git a/drivers/hte/hte-tegra194-test.c b/drivers/hte/hte-tegra194-test.c index f890b79..94e931f 100644 --- a/drivers/hte/hte-tegra194-test.c +++ b/drivers/hte/hte-tegra194-test.c
@@ -221,7 +221,7 @@ static void tegra_hte_test_remove(struct platform_device *pdev) free_irq(hte.gpio_in_irq, &hte); gpiod_put(hte.gpio_in); gpiod_put(hte.gpio_out); - del_timer_sync(&hte.timer); + timer_delete_sync(&hte.timer); } static struct platform_driver tegra_hte_test_driver = {
diff --git a/drivers/hwmon/pwm-fan.c b/drivers/hwmon/pwm-fan.c index 579d31b..d506a5e 100644 --- a/drivers/hwmon/pwm-fan.c +++ b/drivers/hwmon/pwm-fan.c
@@ -483,7 +483,7 @@ static void pwm_fan_cleanup(void *__ctx) { struct pwm_fan_ctx *ctx = __ctx; - del_timer_sync(&ctx->rpm_timer); + timer_delete_sync(&ctx->rpm_timer); /* Switch off everything */ ctx->enable_mode = pwm_disable_reg_disable; pwm_fan_power_off(ctx, true);
diff --git a/drivers/i2c/busses/i2c-img-scb.c b/drivers/i2c/busses/i2c-img-scb.c index 02f75cf..5d8b82a 100644 --- a/drivers/i2c/busses/i2c-img-scb.c +++ b/drivers/i2c/busses/i2c-img-scb.c
@@ -1122,7 +1122,7 @@ static int img_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, time_left = wait_for_completion_timeout(&i2c->msg_complete, IMG_I2C_TIMEOUT); - del_timer_sync(&i2c->check_timer); + timer_delete_sync(&i2c->check_timer); if (time_left == 0) i2c->msg_status = -ETIMEDOUT;
diff --git a/drivers/iio/common/ssp_sensors/ssp_dev.c b/drivers/iio/common/ssp_sensors/ssp_dev.c index 65f8a2b..22ea10e 100644 --- a/drivers/iio/common/ssp_sensors/ssp_dev.c +++ b/drivers/iio/common/ssp_sensors/ssp_dev.c
@@ -190,7 +190,7 @@ static void ssp_enable_wdt_timer(struct ssp_data *data) static void ssp_disable_wdt_timer(struct ssp_data *data) { - del_timer_sync(&data->wdt_timer); + timer_delete_sync(&data->wdt_timer); cancel_work_sync(&data->work_wdt); } @@ -589,7 +589,7 @@ static void ssp_remove(struct spi_device *spi) free_irq(data->spi->irq, data); - del_timer_sync(&data->wdt_timer); + timer_delete_sync(&data->wdt_timer); cancel_work_sync(&data->work_wdt); mutex_destroy(&data->comm_lock);
diff --git a/drivers/infiniband/hw/cxgb4/cm.c b/drivers/infiniband/hw/cxgb4/cm.c index 8d753e6..e02721a 100644 --- a/drivers/infiniband/hw/cxgb4/cm.c +++ b/drivers/infiniband/hw/cxgb4/cm.c
@@ -191,7 +191,7 @@ static void start_ep_timer(struct c4iw_ep *ep) static int stop_ep_timer(struct c4iw_ep *ep) { pr_debug("ep %p stopping\n", ep); - del_timer_sync(&ep->timer); + timer_delete_sync(&ep->timer); if (!test_and_set_bit(TIMEOUT, &ep->com.flags)) { c4iw_put_ep(&ep->com); return 0;
diff --git a/drivers/infiniband/hw/hfi1/aspm.c b/drivers/infiniband/hw/hfi1/aspm.c index a3c53be4..9b508ea 100644 --- a/drivers/infiniband/hw/hfi1/aspm.c +++ b/drivers/infiniband/hw/hfi1/aspm.c
@@ -191,7 +191,7 @@ void aspm_disable_all(struct hfi1_devdata *dd) for (i = 0; i < dd->first_dyn_alloc_ctxt; i++) { rcd = hfi1_rcd_get_by_index(dd, i); if (rcd) { - del_timer_sync(&rcd->aspm_timer); + timer_delete_sync(&rcd->aspm_timer); spin_lock_irqsave(&rcd->aspm_lock, flags); rcd->aspm_intr_enable = false; spin_unlock_irqrestore(&rcd->aspm_lock, flags);
diff --git a/drivers/infiniband/hw/hfi1/chip.c b/drivers/infiniband/hw/hfi1/chip.c index 368b6be..e908f52 100644 --- a/drivers/infiniband/hw/hfi1/chip.c +++ b/drivers/infiniband/hw/hfi1/chip.c
@@ -5576,7 +5576,7 @@ static int init_rcverr(struct hfi1_devdata *dd) static void free_rcverr(struct hfi1_devdata *dd) { if (dd->rcverr_timer.function) - del_timer_sync(&dd->rcverr_timer); + timer_delete_sync(&dd->rcverr_timer); } static void handle_rxe_err(struct hfi1_devdata *dd, u32 unused, u64 reg) @@ -12308,7 +12308,7 @@ static void free_cntrs(struct hfi1_devdata *dd) int i; if (dd->synth_stats_timer.function) - del_timer_sync(&dd->synth_stats_timer); + timer_delete_sync(&dd->synth_stats_timer); cancel_work_sync(&dd->update_cntr_work); ppd = (struct hfi1_pportdata *)(dd + 1); for (i = 0; i < dd->num_pports; i++, ppd++) {
diff --git a/drivers/infiniband/hw/hfi1/driver.c b/drivers/infiniband/hw/hfi1/driver.c index 50826e7..3da90f2 100644 --- a/drivers/infiniband/hw/hfi1/driver.c +++ b/drivers/infiniband/hw/hfi1/driver.c
@@ -1303,7 +1303,7 @@ void shutdown_led_override(struct hfi1_pportdata *ppd) */ smp_rmb(); if (atomic_read(&ppd->led_override_timer_active)) { - del_timer_sync(&ppd->led_override_timer); + timer_delete_sync(&ppd->led_override_timer); atomic_set(&ppd->led_override_timer_active, 0); /* Ensure the atomic_set is visible to all CPUs */ smp_wmb();
diff --git a/drivers/infiniband/hw/hfi1/init.c b/drivers/infiniband/hw/hfi1/init.c index d6fbd9c..b35f92e 100644 --- a/drivers/infiniband/hw/hfi1/init.c +++ b/drivers/infiniband/hw/hfi1/init.c
@@ -985,7 +985,7 @@ static void stop_timers(struct hfi1_devdata *dd) for (pidx = 0; pidx < dd->num_pports; ++pidx) { ppd = dd->pport + pidx; if (ppd->led_override_timer.function) { - del_timer_sync(&ppd->led_override_timer); + timer_delete_sync(&ppd->led_override_timer); atomic_set(&ppd->led_override_timer_active, 0); } }
diff --git a/drivers/infiniband/hw/hfi1/sdma.c b/drivers/infiniband/hw/hfi1/sdma.c index b67d23b..0d2b39b 100644 --- a/drivers/infiniband/hw/hfi1/sdma.c +++ b/drivers/infiniband/hw/hfi1/sdma.c
@@ -1575,7 +1575,7 @@ void sdma_exit(struct hfi1_devdata *dd) sde->this_idx); sdma_process_event(sde, sdma_event_e00_go_hw_down); - del_timer_sync(&sde->err_progress_check_timer); + timer_delete_sync(&sde->err_progress_check_timer); /* * This waits for the state machine to exit so it is not
diff --git a/drivers/infiniband/hw/hfi1/tid_rdma.c b/drivers/infiniband/hw/hfi1/tid_rdma.c index c465966..78bf4a4 100644 --- a/drivers/infiniband/hw/hfi1/tid_rdma.c +++ b/drivers/infiniband/hw/hfi1/tid_rdma.c
@@ -3965,7 +3965,7 @@ static int hfi1_stop_tid_reap_timer(struct rvt_qp *qp) lockdep_assert_held(&qp->s_lock); if (qpriv->s_flags & HFI1_R_TID_RSC_TIMER) { - rval = del_timer(&qpriv->s_tid_timer); + rval = timer_delete(&qpriv->s_tid_timer); qpriv->s_flags &= ~HFI1_R_TID_RSC_TIMER; } return rval; @@ -3975,7 +3975,7 @@ void hfi1_del_tid_reap_timer(struct rvt_qp *qp) { struct hfi1_qp_priv *qpriv = qp->priv; - del_timer_sync(&qpriv->s_tid_timer); + timer_delete_sync(&qpriv->s_tid_timer); qpriv->s_flags &= ~HFI1_R_TID_RSC_TIMER; } @@ -4781,7 +4781,7 @@ static int hfi1_stop_tid_retry_timer(struct rvt_qp *qp) lockdep_assert_held(&qp->s_lock); if (priv->s_flags & HFI1_S_TID_RETRY_TIMER) { - rval = del_timer(&priv->s_tid_retry_timer); + rval = timer_delete(&priv->s_tid_retry_timer); priv->s_flags &= ~HFI1_S_TID_RETRY_TIMER; } return rval; @@ -4791,7 +4791,7 @@ void hfi1_del_tid_retry_timer(struct rvt_qp *qp) { struct hfi1_qp_priv *priv = qp->priv; - del_timer_sync(&priv->s_tid_retry_timer); + timer_delete_sync(&priv->s_tid_retry_timer); priv->s_flags &= ~HFI1_S_TID_RETRY_TIMER; }
diff --git a/drivers/infiniband/hw/hfi1/verbs.c b/drivers/infiniband/hw/hfi1/verbs.c index 33af219..49e0f79 100644 --- a/drivers/infiniband/hw/hfi1/verbs.c +++ b/drivers/infiniband/hw/hfi1/verbs.c
@@ -1900,7 +1900,7 @@ void hfi1_unregister_ib_device(struct hfi1_devdata *dd) if (!list_empty(&dev->memwait)) dd_dev_err(dd, "memwait list not empty!\n"); - del_timer_sync(&dev->mem_timer); + timer_delete_sync(&dev->mem_timer); verbs_txreq_exit(dev); kfree(dev_cntr_descs);
diff --git a/drivers/infiniband/hw/irdma/cm.c b/drivers/infiniband/hw/irdma/cm.c index ce8d821..23207f1 100644 --- a/drivers/infiniband/hw/irdma/cm.c +++ b/drivers/infiniband/hw/irdma/cm.c
@@ -3303,7 +3303,7 @@ void irdma_cleanup_cm_core(struct irdma_cm_core *cm_core) if (!cm_core) return; - del_timer_sync(&cm_core->tcp_timer); + timer_delete_sync(&cm_core->tcp_timer); destroy_workqueue(cm_core->event_wq); cm_core->dev->ws_reset(&cm_core->iwdev->vsi);
diff --git a/drivers/infiniband/hw/irdma/utils.c b/drivers/infiniband/hw/irdma/utils.c index e73b14f..d66b4f7 100644 --- a/drivers/infiniband/hw/irdma/utils.c +++ b/drivers/infiniband/hw/irdma/utils.c
@@ -963,7 +963,7 @@ void irdma_terminate_del_timer(struct irdma_sc_qp *qp) int ret; iwqp = qp->qp_uk.back_qp; - ret = del_timer(&iwqp->terminate_timer); + ret = timer_delete(&iwqp->terminate_timer); if (ret) irdma_qp_rem_ref(&iwqp->ibqp); } @@ -1570,7 +1570,7 @@ void irdma_hw_stats_stop_timer(struct irdma_sc_vsi *vsi) { struct irdma_vsi_pestat *devstat = vsi->pestat; - del_timer_sync(&devstat->stats_timer); + timer_delete_sync(&devstat->stats_timer); } /**
diff --git a/drivers/infiniband/hw/mlx5/mr.c b/drivers/infiniband/hw/mlx5/mr.c index b7c8c92..5fbebaf 100644 --- a/drivers/infiniband/hw/mlx5/mr.c +++ b/drivers/infiniband/hw/mlx5/mr.c
@@ -1026,7 +1026,7 @@ void mlx5_mkey_cache_cleanup(struct mlx5_ib_dev *dev) mlx5r_destroy_cache_entries(dev); destroy_workqueue(dev->cache.wq); - del_timer_sync(&dev->delay_timer); + timer_delete_sync(&dev->delay_timer); } struct ib_mr *mlx5_ib_get_dma_mr(struct ib_pd *pd, int acc)
diff --git a/drivers/infiniband/hw/mthca/mthca_catas.c b/drivers/infiniband/hw/mthca/mthca_catas.c index ffb98ea..6eabef9 100644 --- a/drivers/infiniband/hw/mthca/mthca_catas.c +++ b/drivers/infiniband/hw/mthca/mthca_catas.c
@@ -171,7 +171,7 @@ void mthca_start_catas_poll(struct mthca_dev *dev) void mthca_stop_catas_poll(struct mthca_dev *dev) { - del_timer_sync(&dev->catas_err.timer); + timer_delete_sync(&dev->catas_err.timer); if (dev->catas_err.map) iounmap(dev->catas_err.map);
diff --git a/drivers/infiniband/hw/qib/qib_driver.c b/drivers/infiniband/hw/qib/qib_driver.c index 4fcbef9..bdd724a 100644 --- a/drivers/infiniband/hw/qib/qib_driver.c +++ b/drivers/infiniband/hw/qib/qib_driver.c
@@ -768,7 +768,7 @@ int qib_reset_device(int unit) ppd = dd->pport + pidx; if (atomic_read(&ppd->led_override_timer_active)) { /* Need to stop LED timer, _then_ shut off LEDs */ - del_timer_sync(&ppd->led_override_timer); + timer_delete_sync(&ppd->led_override_timer); atomic_set(&ppd->led_override_timer_active, 0); }
diff --git a/drivers/infiniband/hw/qib/qib_fs.c b/drivers/infiniband/hw/qib/qib_fs.c index b277910..b9f4a29 100644 --- a/drivers/infiniband/hw/qib/qib_fs.c +++ b/drivers/infiniband/hw/qib/qib_fs.c
@@ -55,6 +55,7 @@ static int qibfs_mknod(struct inode *dir, struct dentry *dentry, struct inode *inode = new_inode(dir->i_sb); if (!inode) { + dput(dentry); error = -EPERM; goto bail; }
diff --git a/drivers/infiniband/hw/qib/qib_iba7220.c b/drivers/infiniband/hw/qib/qib_iba7220.c index 78dfe98..302c0d1 100644 --- a/drivers/infiniband/hw/qib/qib_iba7220.c +++ b/drivers/infiniband/hw/qib/qib_iba7220.c
@@ -1656,7 +1656,7 @@ static void qib_7220_quiet_serdes(struct qib_pportdata *ppd) ppd->cpspec->chase_end = 0; if (ppd->cpspec->chase_timer.function) /* if initted */ - del_timer_sync(&ppd->cpspec->chase_timer); + timer_delete_sync(&ppd->cpspec->chase_timer); if (ppd->cpspec->ibsymdelta || ppd->cpspec->iblnkerrdelta || ppd->cpspec->ibdeltainprog) { @@ -2605,7 +2605,7 @@ static int qib_7220_set_ib_cfg(struct qib_pportdata *ppd, int which, u32 val) * wait forpending timer, but don't clear .data (ppd)! */ if (ppd->cpspec->chase_timer.expires) { - del_timer_sync(&ppd->cpspec->chase_timer); + timer_delete_sync(&ppd->cpspec->chase_timer); ppd->cpspec->chase_timer.expires = 0; } break;
diff --git a/drivers/infiniband/hw/qib/qib_iba7322.c b/drivers/infiniband/hw/qib/qib_iba7322.c index 9db2991..7b4bf06 100644 --- a/drivers/infiniband/hw/qib/qib_iba7322.c +++ b/drivers/infiniband/hw/qib/qib_iba7322.c
@@ -2512,7 +2512,7 @@ static void qib_7322_mini_quiet_serdes(struct qib_pportdata *ppd) ppd->cpspec->chase_end = 0; if (ppd->cpspec->chase_timer.function) /* if initted */ - del_timer_sync(&ppd->cpspec->chase_timer); + timer_delete_sync(&ppd->cpspec->chase_timer); /* * Despite the name, actually disables IBC as well. Do it when @@ -4239,7 +4239,7 @@ static int qib_7322_set_ib_cfg(struct qib_pportdata *ppd, int which, u32 val) * wait forpending timer, but don't clear .data (ppd)! */ if (ppd->cpspec->chase_timer.expires) { - del_timer_sync(&ppd->cpspec->chase_timer); + timer_delete_sync(&ppd->cpspec->chase_timer); ppd->cpspec->chase_timer.expires = 0; } break;
diff --git a/drivers/infiniband/hw/qib/qib_init.c b/drivers/infiniband/hw/qib/qib_init.c index 4100656f..33c23ad 100644 --- a/drivers/infiniband/hw/qib/qib_init.c +++ b/drivers/infiniband/hw/qib/qib_init.c
@@ -796,19 +796,19 @@ static void qib_stop_timers(struct qib_devdata *dd) int pidx; if (dd->stats_timer.function) - del_timer_sync(&dd->stats_timer); + timer_delete_sync(&dd->stats_timer); if (dd->intrchk_timer.function) - del_timer_sync(&dd->intrchk_timer); + timer_delete_sync(&dd->intrchk_timer); for (pidx = 0; pidx < dd->num_pports; ++pidx) { ppd = dd->pport + pidx; if (ppd->hol_timer.function) - del_timer_sync(&ppd->hol_timer); + timer_delete_sync(&ppd->hol_timer); if (ppd->led_override_timer.function) { - del_timer_sync(&ppd->led_override_timer); + timer_delete_sync(&ppd->led_override_timer); atomic_set(&ppd->led_override_timer_active, 0); } if (ppd->symerr_clear_timer.function) - del_timer_sync(&ppd->symerr_clear_timer); + timer_delete_sync(&ppd->symerr_clear_timer); } }
diff --git a/drivers/infiniband/hw/qib/qib_mad.c b/drivers/infiniband/hw/qib/qib_mad.c index ef02f2b..568deb7 100644 --- a/drivers/infiniband/hw/qib/qib_mad.c +++ b/drivers/infiniband/hw/qib/qib_mad.c
@@ -2441,7 +2441,7 @@ void qib_notify_free_mad_agent(struct rvt_dev_info *rdi, int port_idx) struct qib_devdata, verbs_dev); if (dd->pport[port_idx].cong_stats.timer.function) - del_timer_sync(&dd->pport[port_idx].cong_stats.timer); + timer_delete_sync(&dd->pport[port_idx].cong_stats.timer); if (dd->pport[port_idx].ibport_data.smi_ah) rdma_destroy_ah(&dd->pport[port_idx].ibport_data.smi_ah->ibah,
diff --git a/drivers/infiniband/hw/qib/qib_sd7220.c b/drivers/infiniband/hw/qib/qib_sd7220.c index 1dc3ccf..c4ee120 100644 --- a/drivers/infiniband/hw/qib/qib_sd7220.c +++ b/drivers/infiniband/hw/qib/qib_sd7220.c
@@ -1375,7 +1375,7 @@ void toggle_7220_rclkrls(struct qib_devdata *dd) void shutdown_7220_relock_poll(struct qib_devdata *dd) { if (dd->cspec->relock_timer_active) - del_timer_sync(&dd->cspec->relock_timer); + timer_delete_sync(&dd->cspec->relock_timer); } static unsigned qib_relock_by_timer = 1;
diff --git a/drivers/infiniband/hw/qib/qib_verbs.c b/drivers/infiniband/hw/qib/qib_verbs.c index 5fcb419..9832567 100644 --- a/drivers/infiniband/hw/qib/qib_verbs.c +++ b/drivers/infiniband/hw/qib/qib_verbs.c
@@ -1655,7 +1655,7 @@ void qib_unregister_ib_device(struct qib_devdata *dd) if (!list_empty(&dev->memwait)) qib_dev_err(dd, "memwait list not empty!\n"); - del_timer_sync(&dev->mem_timer); + timer_delete_sync(&dev->mem_timer); while (!list_empty(&dev->txreq_free)) { struct list_head *l = dev->txreq_free.next; struct qib_verbs_txreq *tx;
diff --git a/drivers/infiniband/sw/rdmavt/qp.c b/drivers/infiniband/sw/rdmavt/qp.c index 614009f..583debe 100644 --- a/drivers/infiniband/sw/rdmavt/qp.c +++ b/drivers/infiniband/sw/rdmavt/qp.c
@@ -1297,7 +1297,7 @@ int rvt_error_qp(struct rvt_qp *qp, enum ib_wc_status err) if (qp->s_flags & (RVT_S_TIMER | RVT_S_WAIT_RNR)) { qp->s_flags &= ~(RVT_S_TIMER | RVT_S_WAIT_RNR); - del_timer(&qp->s_timer); + timer_delete(&qp->s_timer); } if (qp->s_flags & RVT_S_ANY_WAIT_SEND) @@ -2546,7 +2546,7 @@ void rvt_stop_rc_timers(struct rvt_qp *qp) /* Remove QP from all timers */ if (qp->s_flags & (RVT_S_TIMER | RVT_S_WAIT_RNR)) { qp->s_flags &= ~(RVT_S_TIMER | RVT_S_WAIT_RNR); - del_timer(&qp->s_timer); + timer_delete(&qp->s_timer); hrtimer_try_to_cancel(&qp->s_rnr_timer); } } @@ -2575,7 +2575,7 @@ static void rvt_stop_rnr_timer(struct rvt_qp *qp) */ void rvt_del_timers_sync(struct rvt_qp *qp) { - del_timer_sync(&qp->s_timer); + timer_delete_sync(&qp->s_timer); hrtimer_cancel(&qp->s_rnr_timer); } EXPORT_SYMBOL(rvt_del_timers_sync); @@ -2596,7 +2596,7 @@ static void rvt_rc_timeout(struct timer_list *t) qp->s_flags &= ~RVT_S_TIMER; rvp->n_rc_timeouts++; - del_timer(&qp->s_timer); + timer_delete(&qp->s_timer); trace_rvt_rc_timeout(qp, qp->s_last_psn + 1); if (rdi->driver_f.notify_restart_rc) rdi->driver_f.notify_restart_rc(qp,
diff --git a/drivers/infiniband/sw/rxe/rxe_qp.c b/drivers/infiniband/sw/rxe/rxe_qp.c index 91d329e..7975fb0 100644 --- a/drivers/infiniband/sw/rxe/rxe_qp.c +++ b/drivers/infiniband/sw/rxe/rxe_qp.c
@@ -812,8 +812,8 @@ static void rxe_qp_do_cleanup(struct work_struct *work) qp->qp_timeout_jiffies = 0; if (qp_type(qp) == IB_QPT_RC) { - del_timer_sync(&qp->retrans_timer); - del_timer_sync(&qp->rnr_nak_timer); + timer_delete_sync(&qp->retrans_timer); + timer_delete_sync(&qp->rnr_nak_timer); } if (qp->recv_task.func)
diff --git a/drivers/input/ff-memless.c b/drivers/input/ff-memless.c index e9120ba..009822f 100644 --- a/drivers/input/ff-memless.c +++ b/drivers/input/ff-memless.c
@@ -136,7 +136,7 @@ static void ml_schedule_timer(struct ml_device *ml) if (!events) { pr_debug("no actions\n"); - del_timer(&ml->timer); + timer_delete(&ml->timer); } else { pr_debug("timer set\n"); mod_timer(&ml->timer, earliest); @@ -489,7 +489,7 @@ static void ml_ff_destroy(struct ff_device *ff) * do not actually stop the timer, and therefore we should * do it here. */ - del_timer_sync(&ml->timer); + timer_delete_sync(&ml->timer); kfree(ml->private); }
diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c index 10cc958..ae51f10 100644 --- a/drivers/input/gameport/gameport.c +++ b/drivers/input/gameport/gameport.c
@@ -191,7 +191,7 @@ void gameport_stop_polling(struct gameport *gameport) spin_lock(&gameport->timer_lock); if (!--gameport->poll_cnt) - del_timer(&gameport->poll_timer); + timer_delete(&gameport->poll_timer); spin_unlock(&gameport->timer_lock); } @@ -847,7 +847,7 @@ EXPORT_SYMBOL(gameport_open); void gameport_close(struct gameport *gameport) { - del_timer_sync(&gameport->poll_timer); + timer_delete_sync(&gameport->poll_timer); gameport->poll_handler = NULL; gameport->poll_interval = 0; gameport_set_drv(gameport, NULL);
diff --git a/drivers/input/input.c b/drivers/input/input.c index c9e3ac6..ec4346f 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c
@@ -96,7 +96,7 @@ static void input_start_autorepeat(struct input_dev *dev, int code) static void input_stop_autorepeat(struct input_dev *dev) { - del_timer(&dev->timer); + timer_delete(&dev->timer); } /* @@ -2223,7 +2223,7 @@ static void __input_unregister_device(struct input_dev *dev) handle->handler->disconnect(handle); WARN_ON(!list_empty(&dev->h_list)); - del_timer_sync(&dev->timer); + timer_delete_sync(&dev->timer); list_del_init(&dev->node); input_wakeup_procfs_readers();
diff --git a/drivers/input/joystick/db9.c b/drivers/input/joystick/db9.c index a9f1946..d7a2538 100644 --- a/drivers/input/joystick/db9.c +++ b/drivers/input/joystick/db9.c
@@ -531,7 +531,7 @@ static void db9_close(struct input_dev *dev) guard(mutex)(&db9->mutex); if (!--db9->used) { - del_timer_sync(&db9->timer); + timer_delete_sync(&db9->timer); parport_write_control(port, 0x00); parport_data_forward(port); parport_release(db9->pd);
diff --git a/drivers/input/joystick/gamecon.c b/drivers/input/joystick/gamecon.c index b53cafd..9fc629a 100644 --- a/drivers/input/joystick/gamecon.c +++ b/drivers/input/joystick/gamecon.c
@@ -786,7 +786,7 @@ static void gc_close(struct input_dev *dev) guard(mutex)(&gc->mutex); if (!--gc->used) { - del_timer_sync(&gc->timer); + timer_delete_sync(&gc->timer); parport_write_control(gc->pd->port, 0x00); parport_release(gc->pd); }
diff --git a/drivers/input/joystick/n64joy.c b/drivers/input/joystick/n64joy.c index c344dbc..94d2f4e 100644 --- a/drivers/input/joystick/n64joy.c +++ b/drivers/input/joystick/n64joy.c
@@ -216,7 +216,7 @@ static void n64joy_close(struct input_dev *dev) guard(mutex)(&priv->n64joy_mutex); if (!--priv->n64joy_opened) - del_timer_sync(&priv->timer); + timer_delete_sync(&priv->timer); } static const u64 __initconst scandata[] ____cacheline_aligned = {
diff --git a/drivers/input/joystick/turbografx.c b/drivers/input/joystick/turbografx.c index db696ba61..aa3e7d4 100644 --- a/drivers/input/joystick/turbografx.c +++ b/drivers/input/joystick/turbografx.c
@@ -124,7 +124,7 @@ static void tgfx_close(struct input_dev *dev) guard(mutex)(&tgfx->sem); if (!--tgfx->used) { - del_timer_sync(&tgfx->timer); + timer_delete_sync(&tgfx->timer); parport_write_control(tgfx->pd->port, 0x00); parport_release(tgfx->pd); }
diff --git a/drivers/input/joystick/walkera0701.c b/drivers/input/joystick/walkera0701.c index 59eea81..15370fb 100644 --- a/drivers/input/joystick/walkera0701.c +++ b/drivers/input/joystick/walkera0701.c
@@ -232,8 +232,7 @@ static void walkera0701_attach(struct parport *pp) goto err_unregister_device; } - hrtimer_init(&w->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); - w->timer.function = timer_handler; + hrtimer_setup(&w->timer, timer_handler, CLOCK_MONOTONIC, HRTIMER_MODE_REL); w->input_dev = input_allocate_device(); if (!w->input_dev) {
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index 5eef665..5c39a21 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c
@@ -590,9 +590,8 @@ static int gpio_keys_setup_key(struct platform_device *pdev, INIT_DELAYED_WORK(&bdata->work, gpio_keys_gpio_work_func); - hrtimer_init(&bdata->debounce_timer, - CLOCK_REALTIME, HRTIMER_MODE_REL); - bdata->debounce_timer.function = gpio_keys_debounce_timer; + hrtimer_setup(&bdata->debounce_timer, gpio_keys_debounce_timer, + CLOCK_REALTIME, HRTIMER_MODE_REL); isr = gpio_keys_gpio_isr; irqflags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING; @@ -628,9 +627,8 @@ static int gpio_keys_setup_key(struct platform_device *pdev, } bdata->release_delay = button->debounce_interval; - hrtimer_init(&bdata->release_timer, - CLOCK_REALTIME, HRTIMER_MODE_REL_HARD); - bdata->release_timer.function = gpio_keys_irq_timer; + hrtimer_setup(&bdata->release_timer, gpio_keys_irq_timer, + CLOCK_REALTIME, HRTIMER_MODE_REL_HARD); isr = gpio_keys_irq_isr; irqflags = 0;
diff --git a/drivers/input/keyboard/imx_keypad.c b/drivers/input/keyboard/imx_keypad.c index b92268d..3cd47fa 100644 --- a/drivers/input/keyboard/imx_keypad.c +++ b/drivers/input/keyboard/imx_keypad.c
@@ -370,7 +370,7 @@ static void imx_keypad_close(struct input_dev *dev) /* Mark keypad as being inactive */ keypad->enabled = false; synchronize_irq(keypad->irq); - del_timer_sync(&keypad->check_matrix_timer); + timer_delete_sync(&keypad->check_matrix_timer); imx_keypad_inhibit(keypad);
diff --git a/drivers/input/keyboard/matrix_keypad.c b/drivers/input/keyboard/matrix_keypad.c index 2a3b3bf..e46473c 100644 --- a/drivers/input/keyboard/matrix_keypad.c +++ b/drivers/input/keyboard/matrix_keypad.c
@@ -26,6 +26,7 @@ struct matrix_keypad { unsigned int row_shift; unsigned int col_scan_delay_us; + unsigned int all_cols_on_delay_us; /* key debounce interval in milli-second */ unsigned int debounce_ms; bool drive_inactive_cols; @@ -68,7 +69,7 @@ static void activate_col(struct matrix_keypad *keypad, int col, bool on) __activate_col(keypad, col, on); if (on && keypad->col_scan_delay_us) - udelay(keypad->col_scan_delay_us); + fsleep(keypad->col_scan_delay_us); } static void activate_all_cols(struct matrix_keypad *keypad, bool on) @@ -77,6 +78,9 @@ static void activate_all_cols(struct matrix_keypad *keypad, bool on) for (col = 0; col < keypad->num_col_gpios; col++) __activate_col(keypad, col, on); + + if (on && keypad->all_cols_on_delay_us) + fsleep(keypad->all_cols_on_delay_us); } static bool row_asserted(struct matrix_keypad *keypad, int row) @@ -392,6 +396,8 @@ static int matrix_keypad_probe(struct platform_device *pdev) &keypad->debounce_ms); device_property_read_u32(&pdev->dev, "col-scan-delay-us", &keypad->col_scan_delay_us); + device_property_read_u32(&pdev->dev, "all-cols-on-delay-us", + &keypad->all_cols_on_delay_us); err = matrix_keypad_init_gpio(pdev, keypad); if (err)
diff --git a/drivers/input/keyboard/snvs_pwrkey.c b/drivers/input/keyboard/snvs_pwrkey.c index f7b5f1e..bbf409d 100644 --- a/drivers/input/keyboard/snvs_pwrkey.c +++ b/drivers/input/keyboard/snvs_pwrkey.c
@@ -104,7 +104,7 @@ static void imx_snvs_pwrkey_act(void *pdata) { struct pwrkey_drv_data *pd = pdata; - del_timer_sync(&pd->check_timer); + timer_delete_sync(&pd->check_timer); } static int imx_snvs_pwrkey_probe(struct platform_device *pdev)
diff --git a/drivers/input/keyboard/tegra-kbc.c b/drivers/input/keyboard/tegra-kbc.c index 6776dd9..32a676f0 100644 --- a/drivers/input/keyboard/tegra-kbc.c +++ b/drivers/input/keyboard/tegra-kbc.c
@@ -416,7 +416,7 @@ static void tegra_kbc_stop(struct tegra_kbc *kbc) } disable_irq(kbc->irq); - del_timer_sync(&kbc->timer); + timer_delete_sync(&kbc->timer); clk_disable_unprepare(kbc->clk); } @@ -703,7 +703,7 @@ static int tegra_kbc_suspend(struct device *dev) if (device_may_wakeup(&pdev->dev)) { disable_irq(kbc->irq); - del_timer_sync(&kbc->timer); + timer_delete_sync(&kbc->timer); tegra_kbc_set_fifo_interrupt(kbc, false); /* Forcefully clear the interrupt status */
diff --git a/drivers/input/misc/pm8941-pwrkey.c b/drivers/input/misc/pm8941-pwrkey.c index d0c4666..d952c16 100644 --- a/drivers/input/misc/pm8941-pwrkey.c +++ b/drivers/input/misc/pm8941-pwrkey.c
@@ -154,8 +154,8 @@ static irqreturn_t pm8941_pwrkey_irq(int irq, void *_data) if (pwrkey->sw_debounce_time_us) { if (ktime_before(ktime_get(), pwrkey->sw_debounce_end_time)) { dev_dbg(pwrkey->dev, - "ignoring key event received before debounce end %llu us\n", - pwrkey->sw_debounce_end_time); + "ignoring key event received before debounce end %lld us\n", + ktime_to_us(pwrkey->sw_debounce_end_time)); return IRQ_HANDLED; } }
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c index 0728b5c..0bd7b09 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c
@@ -1519,7 +1519,7 @@ static psmouse_ret_t alps_handle_interleaved_ps2(struct psmouse *psmouse) return PSMOUSE_GOOD_DATA; } - del_timer(&priv->timer); + timer_delete(&priv->timer); if (psmouse->packet[6] & 0x80) {
diff --git a/drivers/input/mouse/byd.c b/drivers/input/mouse/byd.c index 654b38d..4ee084e 100644 --- a/drivers/input/mouse/byd.c +++ b/drivers/input/mouse/byd.c
@@ -425,7 +425,7 @@ static void byd_disconnect(struct psmouse *psmouse) struct byd_data *priv = psmouse->private; if (priv) { - del_timer(&priv->timer); + timer_delete(&priv->timer); kfree(psmouse->private); psmouse->private = NULL; }
diff --git a/drivers/input/mouse/cyapa.c b/drivers/input/mouse/cyapa.c index 2f2d925..00c87c0 100644 --- a/drivers/input/mouse/cyapa.c +++ b/drivers/input/mouse/cyapa.c
@@ -1080,8 +1080,8 @@ static ssize_t cyapa_update_fw_store(struct device *dev, char fw_name[NAME_MAX]; int ret, error; - if (count >= NAME_MAX) { - dev_err(dev, "File name too long\n"); + if (!count || count >= NAME_MAX) { + dev_err(dev, "Bad file name size\n"); return -EINVAL; }
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index aba57ab..309c360 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c
@@ -161,6 +161,7 @@ static const char * const topbuttonpad_pnp_ids[] = { NULL }; +#ifdef CONFIG_MOUSE_PS2_SYNAPTICS_SMBUS static const char * const smbus_pnp_ids[] = { /* all of the topbuttonpad_pnp_ids are valid, we just add some extras */ "LEN0048", /* X1 Carbon 3 */ @@ -196,6 +197,7 @@ static const char * const smbus_pnp_ids[] = { "SYN3257", /* HP Envy 13-ad105ng */ NULL }; +#endif static const char * const forcepad_pnp_ids[] = { "SYN300D",
diff --git a/drivers/input/rmi4/rmi_f54.c b/drivers/input/rmi4/rmi_f54.c index 5c3da91..ac4041a 100644 --- a/drivers/input/rmi4/rmi_f54.c +++ b/drivers/input/rmi4/rmi_f54.c
@@ -372,8 +372,6 @@ static const struct vb2_ops rmi_f54_queue_ops = { .queue_setup = rmi_f54_queue_setup, .buf_queue = rmi_f54_buffer_queue, .stop_streaming = rmi_f54_stop_streaming, - .wait_prepare = vb2_ops_wait_prepare, - .wait_finish = vb2_ops_wait_finish, }; static const struct vb2_queue rmi_f54_queue = {
diff --git a/drivers/input/serio/hil_mlc.c b/drivers/input/serio/hil_mlc.c index d36e89d..94e8bcb 100644 --- a/drivers/input/serio/hil_mlc.c +++ b/drivers/input/serio/hil_mlc.c
@@ -1017,7 +1017,7 @@ static int __init hil_mlc_init(void) static void __exit hil_mlc_exit(void) { - del_timer_sync(&hil_mlcs_kicker); + timer_delete_sync(&hil_mlcs_kicker); tasklet_kill(&hil_mlcs_tasklet); }
diff --git a/drivers/input/serio/hp_sdc.c b/drivers/input/serio/hp_sdc.c index 13eacf6..0eec4c5 100644 --- a/drivers/input/serio/hp_sdc.c +++ b/drivers/input/serio/hp_sdc.c
@@ -980,7 +980,7 @@ static void hp_sdc_exit(void) free_irq(hp_sdc.irq, &hp_sdc); write_unlock_irq(&hp_sdc.lock); - del_timer_sync(&hp_sdc.kicker); + timer_delete_sync(&hp_sdc.kicker); tasklet_kill(&hp_sdc.task);
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 1a03de7..91a2b58 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig
@@ -103,6 +103,19 @@ To compile this driver as a module, choose M here: the module will be called resistive-adc-touch.ko. +config TOUCHSCREEN_APPLE_Z2 + tristate "Apple Z2 touchscreens" + default ARCH_APPLE + depends on SPI && (ARCH_APPLE || COMPILE_TEST) + help + Say Y here if you have an ARM Apple device with + a touchscreen or a touchbar. + + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called apple_z2. + config TOUCHSCREEN_AR1021_I2C tristate "Microchip AR1020/1021 i2c touchscreen" depends on I2C && OF
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index 82bc837..97a025c 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile
@@ -15,6 +15,7 @@ obj-$(CONFIG_TOUCHSCREEN_AD7879_SPI) += ad7879-spi.o obj-$(CONFIG_TOUCHSCREEN_ADC) += resistive-adc-touch.o obj-$(CONFIG_TOUCHSCREEN_ADS7846) += ads7846.o +obj-$(CONFIG_TOUCHSCREEN_APPLE_Z2) += apple_z2.o obj-$(CONFIG_TOUCHSCREEN_AR1021_I2C) += ar1021_i2c.o obj-$(CONFIG_TOUCHSCREEN_ATMEL_MXT) += atmel_mxt_ts.o obj-$(CONFIG_TOUCHSCREEN_AUO_PIXCIR) += auo-pixcir-ts.o
diff --git a/drivers/input/touchscreen/ad7877.c b/drivers/input/touchscreen/ad7877.c index a0598e9..8d8392c 100644 --- a/drivers/input/touchscreen/ad7877.c +++ b/drivers/input/touchscreen/ad7877.c
@@ -415,7 +415,7 @@ static void ad7877_disable(void *data) ts->disabled = true; disable_irq(ts->spi->irq); - if (del_timer_sync(&ts->timer)) + if (timer_delete_sync(&ts->timer)) ad7877_ts_event_release(ts); }
diff --git a/drivers/input/touchscreen/ad7879.c b/drivers/input/touchscreen/ad7879.c index e5d69bf..f661e19 100644 --- a/drivers/input/touchscreen/ad7879.c +++ b/drivers/input/touchscreen/ad7879.c
@@ -273,7 +273,7 @@ static void __ad7879_disable(struct ad7879 *ts) AD7879_PM(AD7879_PM_SHUTDOWN); disable_irq(ts->irq); - if (del_timer_sync(&ts->timer)) + if (timer_delete_sync(&ts->timer)) ad7879_ts_event_release(ts); ad7879_write(ts, AD7879_REG_CTRL2, reg);
diff --git a/drivers/input/touchscreen/apple_z2.c b/drivers/input/touchscreen/apple_z2.c new file mode 100644 index 0000000..0de161e --- /dev/null +++ b/drivers/input/touchscreen/apple_z2.c
@@ -0,0 +1,477 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Apple Z2 touchscreen driver + * + * Copyright (C) The Asahi Linux Contributors + */ + +#include <linux/delay.h> +#include <linux/firmware.h> +#include <linux/input.h> +#include <linux/input/mt.h> +#include <linux/input/touchscreen.h> +#include <linux/interrupt.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/spi/spi.h> +#include <linux/unaligned.h> + +#define APPLE_Z2_NUM_FINGERS_OFFSET 16 +#define APPLE_Z2_FINGERS_OFFSET 24 +#define APPLE_Z2_TOUCH_STARTED 3 +#define APPLE_Z2_TOUCH_MOVED 4 +#define APPLE_Z2_CMD_READ_INTERRUPT_DATA 0xEB +#define APPLE_Z2_HBPP_CMD_BLOB 0x3001 +#define APPLE_Z2_FW_MAGIC 0x5746325A +#define LOAD_COMMAND_INIT_PAYLOAD 0 +#define LOAD_COMMAND_SEND_BLOB 1 +#define LOAD_COMMAND_SEND_CALIBRATION 2 +#define CAL_PROP_NAME "apple,z2-cal-blob" + +struct apple_z2 { + struct spi_device *spidev; + struct gpio_desc *reset_gpio; + struct input_dev *input_dev; + struct completion boot_irq; + bool booted; + int index_parity; + struct touchscreen_properties props; + const char *fw_name; + u8 *tx_buf; + u8 *rx_buf; +}; + +struct apple_z2_finger { + u8 finger; + u8 state; + __le16 unknown2; + __le16 abs_x; + __le16 abs_y; + __le16 rel_x; + __le16 rel_y; + __le16 tool_major; + __le16 tool_minor; + __le16 orientation; + __le16 touch_major; + __le16 touch_minor; + __le16 unused[2]; + __le16 pressure; + __le16 multi; +} __packed; + +struct apple_z2_hbpp_blob_hdr { + __le16 cmd; + __le16 len; + __le32 addr; + __le16 checksum; +}; + +struct apple_z2_fw_hdr { + __le32 magic; + __le32 version; +}; + +struct apple_z2_read_interrupt_cmd { + u8 cmd; + u8 counter; + u8 unused[12]; + __le16 checksum; +}; + +static void apple_z2_parse_touches(struct apple_z2 *z2, + const u8 *msg, size_t msg_len) +{ + int i; + int nfingers; + int slot; + int slot_valid; + struct apple_z2_finger *fingers; + + if (msg_len <= APPLE_Z2_NUM_FINGERS_OFFSET) + return; + nfingers = msg[APPLE_Z2_NUM_FINGERS_OFFSET]; + fingers = (struct apple_z2_finger *)(msg + APPLE_Z2_FINGERS_OFFSET); + for (i = 0; i < nfingers; i++) { + slot = input_mt_get_slot_by_key(z2->input_dev, fingers[i].finger); + if (slot < 0) { + dev_warn(&z2->spidev->dev, "unable to get slot for finger\n"); + continue; + } + slot_valid = fingers[i].state == APPLE_Z2_TOUCH_STARTED || + fingers[i].state == APPLE_Z2_TOUCH_MOVED; + input_mt_slot(z2->input_dev, slot); + if (!input_mt_report_slot_state(z2->input_dev, MT_TOOL_FINGER, slot_valid)) + continue; + touchscreen_report_pos(z2->input_dev, &z2->props, + le16_to_cpu(fingers[i].abs_x), + le16_to_cpu(fingers[i].abs_y), + true); + input_report_abs(z2->input_dev, ABS_MT_WIDTH_MAJOR, + le16_to_cpu(fingers[i].tool_major)); + input_report_abs(z2->input_dev, ABS_MT_WIDTH_MINOR, + le16_to_cpu(fingers[i].tool_minor)); + input_report_abs(z2->input_dev, ABS_MT_ORIENTATION, + le16_to_cpu(fingers[i].orientation)); + input_report_abs(z2->input_dev, ABS_MT_TOUCH_MAJOR, + le16_to_cpu(fingers[i].touch_major)); + input_report_abs(z2->input_dev, ABS_MT_TOUCH_MINOR, + le16_to_cpu(fingers[i].touch_minor)); + } + input_mt_sync_frame(z2->input_dev); + input_sync(z2->input_dev); +} + +static int apple_z2_read_packet(struct apple_z2 *z2) +{ + struct apple_z2_read_interrupt_cmd *len_cmd = (void *)z2->tx_buf; + struct spi_transfer xfer; + int error; + size_t pkt_len; + + memset(&xfer, 0, sizeof(xfer)); + len_cmd->cmd = APPLE_Z2_CMD_READ_INTERRUPT_DATA; + len_cmd->counter = z2->index_parity + 1; + len_cmd->checksum = + cpu_to_le16(APPLE_Z2_CMD_READ_INTERRUPT_DATA + len_cmd->counter); + z2->index_parity = !z2->index_parity; + xfer.tx_buf = z2->tx_buf; + xfer.rx_buf = z2->rx_buf; + xfer.len = sizeof(*len_cmd); + + error = spi_sync_transfer(z2->spidev, &xfer, 1); + if (error) + return error; + + pkt_len = (get_unaligned_le16(z2->rx_buf + 1) + 8) & 0xfffffffc; + + error = spi_read(z2->spidev, z2->rx_buf, pkt_len); + if (error) + return error; + + apple_z2_parse_touches(z2, z2->rx_buf + 5, pkt_len - 5); + + return 0; +} + +static irqreturn_t apple_z2_irq(int irq, void *data) +{ + struct apple_z2 *z2 = data; + + if (unlikely(!z2->booted)) + complete(&z2->boot_irq); + else + apple_z2_read_packet(z2); + + return IRQ_HANDLED; +} + +/* Build calibration blob, caller is responsible for freeing the blob data. */ +static const u8 *apple_z2_build_cal_blob(struct apple_z2 *z2, + u32 address, size_t *size) +{ + u8 *cal_data; + int cal_size; + size_t blob_size; + u32 checksum; + u16 checksum_hdr; + int i; + struct apple_z2_hbpp_blob_hdr *hdr; + int error; + + if (!device_property_present(&z2->spidev->dev, CAL_PROP_NAME)) + return NULL; + + cal_size = device_property_count_u8(&z2->spidev->dev, CAL_PROP_NAME); + if (cal_size < 0) + return ERR_PTR(cal_size); + + blob_size = sizeof(struct apple_z2_hbpp_blob_hdr) + cal_size + sizeof(__le32); + u8 *blob_data __free(kfree) = kzalloc(blob_size, GFP_KERNEL); + if (!blob_data) + return ERR_PTR(-ENOMEM); + + hdr = (struct apple_z2_hbpp_blob_hdr *)blob_data; + hdr->cmd = cpu_to_le16(APPLE_Z2_HBPP_CMD_BLOB); + hdr->len = cpu_to_le16(round_up(cal_size, 4) / 4); + hdr->addr = cpu_to_le32(address); + + checksum_hdr = 0; + for (i = 2; i < 8; i++) + checksum_hdr += blob_data[i]; + hdr->checksum = cpu_to_le16(checksum_hdr); + + cal_data = blob_data + sizeof(struct apple_z2_hbpp_blob_hdr); + error = device_property_read_u8_array(&z2->spidev->dev, CAL_PROP_NAME, + cal_data, cal_size); + if (error) + return ERR_PTR(error); + + checksum = 0; + for (i = 0; i < cal_size; i++) + checksum += cal_data[i]; + put_unaligned_le32(checksum, cal_data + cal_size); + + *size = blob_size; + return no_free_ptr(blob_data); +} + +static int apple_z2_send_firmware_blob(struct apple_z2 *z2, const u8 *data, + u32 size, bool init) +{ + struct spi_message msg; + struct spi_transfer blob_xfer, ack_xfer; + int error; + + z2->tx_buf[0] = 0x1a; + z2->tx_buf[1] = 0xa1; + + spi_message_init(&msg); + memset(&blob_xfer, 0, sizeof(blob_xfer)); + memset(&ack_xfer, 0, sizeof(ack_xfer)); + + blob_xfer.tx_buf = data; + blob_xfer.len = size; + blob_xfer.bits_per_word = init ? 8 : 16; + spi_message_add_tail(&blob_xfer, &msg); + + ack_xfer.tx_buf = z2->tx_buf; + ack_xfer.len = 2; + spi_message_add_tail(&ack_xfer, &msg); + + reinit_completion(&z2->boot_irq); + error = spi_sync(z2->spidev, &msg); + if (error) + return error; + + /* Irq only happens sometimes, but the thing boots reliably nonetheless */ + wait_for_completion_timeout(&z2->boot_irq, msecs_to_jiffies(20)); + + return 0; +} + +static int apple_z2_upload_firmware(struct apple_z2 *z2) +{ + const struct apple_z2_fw_hdr *fw_hdr; + size_t fw_idx = sizeof(struct apple_z2_fw_hdr); + int error; + u32 load_cmd; + u32 address; + bool init; + size_t size; + + const struct firmware *fw __free(firmware) = NULL; + error = request_firmware(&fw, z2->fw_name, &z2->spidev->dev); + if (error) { + dev_err(&z2->spidev->dev, "unable to load firmware\n"); + return error; + } + + fw_hdr = (const struct apple_z2_fw_hdr *)fw->data; + if (le32_to_cpu(fw_hdr->magic) != APPLE_Z2_FW_MAGIC || le32_to_cpu(fw_hdr->version) != 1) { + dev_err(&z2->spidev->dev, "invalid firmware header\n"); + return -EINVAL; + } + + /* + * This will interrupt the upload half-way if the file is malformed + * As the device has no non-volatile storage to corrupt, and gets reset + * on boot anyway, this is fine. + */ + while (fw_idx < fw->size) { + if (fw->size - fw_idx < 8) { + dev_err(&z2->spidev->dev, "firmware malformed\n"); + return -EINVAL; + } + + load_cmd = le32_to_cpup((__force __le32 *)(fw->data + fw_idx)); + fw_idx += sizeof(u32); + if (load_cmd == LOAD_COMMAND_INIT_PAYLOAD || load_cmd == LOAD_COMMAND_SEND_BLOB) { + size = le32_to_cpup((__force __le32 *)(fw->data + fw_idx)); + fw_idx += sizeof(u32); + if (fw->size - fw_idx < size) { + dev_err(&z2->spidev->dev, "firmware malformed\n"); + return -EINVAL; + } + init = load_cmd == LOAD_COMMAND_INIT_PAYLOAD; + error = apple_z2_send_firmware_blob(z2, fw->data + fw_idx, + size, init); + if (error) + return error; + fw_idx += size; + } else if (load_cmd == LOAD_COMMAND_SEND_CALIBRATION) { + address = le32_to_cpup((__force __le32 *)(fw->data + fw_idx)); + fw_idx += sizeof(u32); + + const u8 *data __free(kfree) = + apple_z2_build_cal_blob(z2, address, &size); + if (IS_ERR(data)) + return PTR_ERR(data); + + if (data) { + error = apple_z2_send_firmware_blob(z2, data, size, false); + if (error) + return error; + } + } else { + dev_err(&z2->spidev->dev, "firmware malformed\n"); + return -EINVAL; + } + fw_idx = round_up(fw_idx, 4); + } + + + z2->booted = true; + apple_z2_read_packet(z2); + return 0; +} + +static int apple_z2_boot(struct apple_z2 *z2) +{ + int error; + + reinit_completion(&z2->boot_irq); + enable_irq(z2->spidev->irq); + gpiod_set_value(z2->reset_gpio, 0); + if (!wait_for_completion_timeout(&z2->boot_irq, msecs_to_jiffies(20))) + return -ETIMEDOUT; + + error = apple_z2_upload_firmware(z2); + if (error) { + gpiod_set_value(z2->reset_gpio, 1); + disable_irq(z2->spidev->irq); + return error; + } + + return 0; +} + +static int apple_z2_probe(struct spi_device *spi) +{ + struct device *dev = &spi->dev; + struct apple_z2 *z2; + int error; + + z2 = devm_kzalloc(dev, sizeof(*z2), GFP_KERNEL); + if (!z2) + return -ENOMEM; + + z2->tx_buf = devm_kzalloc(dev, sizeof(struct apple_z2_read_interrupt_cmd), GFP_KERNEL); + if (!z2->tx_buf) + return -ENOMEM; + /* 4096 will end up being rounded up to 8192 due to devres header */ + z2->rx_buf = devm_kzalloc(dev, 4000, GFP_KERNEL); + if (!z2->rx_buf) + return -ENOMEM; + + z2->spidev = spi; + init_completion(&z2->boot_irq); + spi_set_drvdata(spi, z2); + + /* Reset the device on boot */ + z2->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH); + if (IS_ERR(z2->reset_gpio)) + return dev_err_probe(dev, PTR_ERR(z2->reset_gpio), "unable to get reset\n"); + + error = devm_request_threaded_irq(dev, z2->spidev->irq, NULL, apple_z2_irq, + IRQF_ONESHOT | IRQF_NO_AUTOEN, + "apple-z2-irq", z2); + if (error) + return dev_err_probe(dev, error, "unable to request irq\n"); + + error = device_property_read_string(dev, "firmware-name", &z2->fw_name); + if (error) + return dev_err_probe(dev, error, "unable to get firmware name\n"); + + z2->input_dev = devm_input_allocate_device(dev); + if (!z2->input_dev) + return -ENOMEM; + + z2->input_dev->name = (char *)spi_get_device_id(spi)->driver_data; + z2->input_dev->phys = "apple_z2"; + z2->input_dev->id.bustype = BUS_SPI; + + /* Allocate the axes before setting from DT */ + input_set_abs_params(z2->input_dev, ABS_MT_POSITION_X, 0, 0, 0, 0); + input_set_abs_params(z2->input_dev, ABS_MT_POSITION_Y, 0, 0, 0, 0); + touchscreen_parse_properties(z2->input_dev, true, &z2->props); + input_abs_set_res(z2->input_dev, ABS_MT_POSITION_X, 100); + input_abs_set_res(z2->input_dev, ABS_MT_POSITION_Y, 100); + input_set_abs_params(z2->input_dev, ABS_MT_WIDTH_MAJOR, 0, 65535, 0, 0); + input_set_abs_params(z2->input_dev, ABS_MT_WIDTH_MINOR, 0, 65535, 0, 0); + input_set_abs_params(z2->input_dev, ABS_MT_TOUCH_MAJOR, 0, 65535, 0, 0); + input_set_abs_params(z2->input_dev, ABS_MT_TOUCH_MINOR, 0, 65535, 0, 0); + input_set_abs_params(z2->input_dev, ABS_MT_ORIENTATION, -32768, 32767, 0, 0); + + error = input_mt_init_slots(z2->input_dev, 256, INPUT_MT_DIRECT); + if (error) + return dev_err_probe(dev, error, "unable to initialize multitouch slots\n"); + + error = input_register_device(z2->input_dev); + if (error) + return dev_err_probe(dev, error, "unable to register input device\n"); + + /* Wait for device reset to finish */ + usleep_range(5000, 10000); + error = apple_z2_boot(z2); + if (error) + return error; + + return 0; +} + +static void apple_z2_shutdown(struct spi_device *spi) +{ + struct apple_z2 *z2 = spi_get_drvdata(spi); + + disable_irq(z2->spidev->irq); + gpiod_direction_output(z2->reset_gpio, 1); + z2->booted = false; +} + +static int apple_z2_suspend(struct device *dev) +{ + apple_z2_shutdown(to_spi_device(dev)); + + return 0; +} + +static int apple_z2_resume(struct device *dev) +{ + struct apple_z2 *z2 = spi_get_drvdata(to_spi_device(dev)); + + return apple_z2_boot(z2); +} + +static DEFINE_SIMPLE_DEV_PM_OPS(apple_z2_pm, apple_z2_suspend, apple_z2_resume); + +static const struct of_device_id apple_z2_of_match[] = { + { .compatible = "apple,j293-touchbar" }, + { .compatible = "apple,j493-touchbar" }, + {} +}; +MODULE_DEVICE_TABLE(of, apple_z2_of_match); + +static struct spi_device_id apple_z2_of_id[] = { + { .name = "j293-touchbar", .driver_data = (kernel_ulong_t)"MacBookPro17,1 Touch Bar" }, + { .name = "j493-touchbar", .driver_data = (kernel_ulong_t)"Mac14,7 Touch Bar" }, + {} +}; +MODULE_DEVICE_TABLE(spi, apple_z2_of_id); + +static struct spi_driver apple_z2_driver = { + .driver = { + .name = "apple-z2", + .pm = pm_sleep_ptr(&apple_z2_pm), + .of_match_table = apple_z2_of_match, + .probe_type = PROBE_PREFER_ASYNCHRONOUS, + }, + .id_table = apple_z2_of_id, + .probe = apple_z2_probe, + .remove = apple_z2_shutdown, +}; + +module_spi_driver(apple_z2_driver); + +MODULE_LICENSE("GPL"); +MODULE_FIRMWARE("apple/dfrmtfw-*.bin"); +MODULE_DESCRIPTION("Apple Z2 touchscreens driver");
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 3ddabc5..322d5a3 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -2535,8 +2535,6 @@ static void mxt_buffer_queue(struct vb2_buffer *vb) static const struct vb2_ops mxt_queue_ops = { .queue_setup = mxt_queue_setup, .buf_queue = mxt_buffer_queue, - .wait_prepare = vb2_ops_wait_prepare, - .wait_finish = vb2_ops_wait_finish, }; static const struct vb2_queue mxt_queue = {
diff --git a/drivers/input/touchscreen/bu21029_ts.c b/drivers/input/touchscreen/bu21029_ts.c index 686d0a6..3c997fb 100644 --- a/drivers/input/touchscreen/bu21029_ts.c +++ b/drivers/input/touchscreen/bu21029_ts.c
@@ -325,7 +325,7 @@ static void bu21029_stop_chip(struct input_dev *dev) struct bu21029_ts_data *bu21029 = input_get_drvdata(dev); disable_irq(bu21029->client->irq); - del_timer_sync(&bu21029->timer); + timer_delete_sync(&bu21029->timer); bu21029_put_chip_in_reset(bu21029); regulator_disable(bu21029->vdd);
diff --git a/drivers/input/touchscreen/exc3000.c b/drivers/input/touchscreen/exc3000.c index fdda841..9a5977d 100644 --- a/drivers/input/touchscreen/exc3000.c +++ b/drivers/input/touchscreen/exc3000.c
@@ -174,7 +174,7 @@ static int exc3000_handle_mt_event(struct exc3000_data *data) /* * We read full state successfully, no contacts will be "stuck". */ - del_timer_sync(&data->timer); + timer_delete_sync(&data->timer); while (total_slots > 0) { int slots = min(total_slots, EXC3000_SLOTS_PER_FRAME);
diff --git a/drivers/input/touchscreen/goodix_berlin.h b/drivers/input/touchscreen/goodix_berlin.h index 38b6f9d..d8bbd48 100644 --- a/drivers/input/touchscreen/goodix_berlin.h +++ b/drivers/input/touchscreen/goodix_berlin.h
@@ -12,12 +12,26 @@ #include <linux/pm.h> +#define GOODIX_BERLIN_FW_VERSION_INFO_ADDR_A 0x1000C +#define GOODIX_BERLIN_FW_VERSION_INFO_ADDR_D 0x10014 + +#define GOODIX_BERLIN_IC_INFO_ADDR_A 0x10068 +#define GOODIX_BERLIN_IC_INFO_ADDR_D 0x10070 + +struct goodix_berlin_ic_data { + int fw_version_info_addr; + int ic_info_addr; + ssize_t read_dummy_len; + ssize_t read_prefix_len; +}; + struct device; struct input_id; struct regmap; int goodix_berlin_probe(struct device *dev, int irq, const struct input_id *id, - struct regmap *regmap); + struct regmap *regmap, + const struct goodix_berlin_ic_data *ic_data); extern const struct dev_pm_ops goodix_berlin_pm_ops; extern const struct attribute_group *goodix_berlin_groups[];
diff --git a/drivers/input/touchscreen/goodix_berlin_core.c b/drivers/input/touchscreen/goodix_berlin_core.c index f7ea443..02a1d9a 100644 --- a/drivers/input/touchscreen/goodix_berlin_core.c +++ b/drivers/input/touchscreen/goodix_berlin_core.c
@@ -12,7 +12,7 @@ * to the previous generations. * * Currently the driver only handles Multitouch events with already - * programmed firmware and "config" for "Revision D" Berlin IC. + * programmed firmware and "config" for "Revision A/D" Berlin IC. * * Support is missing for: * - ESD Management @@ -20,7 +20,7 @@ * - "Config" update/flashing * - Stylus Events * - Gesture Events - * - Support for older revisions (A & B) + * - Support for revision B */ #include <linux/bitfield.h> @@ -28,6 +28,7 @@ #include <linux/input.h> #include <linux/input/mt.h> #include <linux/input/touchscreen.h> +#include <linux/property.h> #include <linux/regmap.h> #include <linux/regulator/consumer.h> #include <linux/sizes.h> @@ -53,10 +54,8 @@ #define GOODIX_BERLIN_DEV_CONFIRM_VAL 0xAA #define GOODIX_BERLIN_BOOTOPTION_ADDR 0x10000 -#define GOODIX_BERLIN_FW_VERSION_INFO_ADDR 0x10014 #define GOODIX_BERLIN_IC_INFO_MAX_LEN SZ_1K -#define GOODIX_BERLIN_IC_INFO_ADDR 0x10070 #define GOODIX_BERLIN_CHECKSUM_SIZE sizeof(u16) @@ -175,6 +174,8 @@ struct goodix_berlin_core { /* Runtime parameters extracted from IC_INFO buffer */ u32 touch_data_addr; + const struct goodix_berlin_ic_data *ic_data; + struct goodix_berlin_event event; }; @@ -299,7 +300,7 @@ static int goodix_berlin_read_version(struct goodix_berlin_core *cd) { int error; - error = regmap_raw_read(cd->regmap, GOODIX_BERLIN_FW_VERSION_INFO_ADDR, + error = regmap_raw_read(cd->regmap, cd->ic_data->fw_version_info_addr, &cd->fw_version, sizeof(cd->fw_version)); if (error) { dev_err(cd->dev, "error reading fw version, %d\n", error); @@ -367,7 +368,7 @@ static int goodix_berlin_get_ic_info(struct goodix_berlin_core *cd) if (!afe_data) return -ENOMEM; - error = regmap_raw_read(cd->regmap, GOODIX_BERLIN_IC_INFO_ADDR, + error = regmap_raw_read(cd->regmap, cd->ic_data->ic_info_addr, &length_raw, sizeof(length_raw)); if (error) { dev_err(cd->dev, "failed get ic info length, %d\n", error); @@ -380,8 +381,8 @@ static int goodix_berlin_get_ic_info(struct goodix_berlin_core *cd) return -EINVAL; } - error = regmap_raw_read(cd->regmap, GOODIX_BERLIN_IC_INFO_ADDR, - afe_data, length); + error = regmap_raw_read(cd->regmap, cd->ic_data->ic_info_addr, afe_data, + length); if (error) { dev_err(cd->dev, "failed get ic info data, %d\n", error); return error; @@ -716,7 +717,8 @@ const struct attribute_group *goodix_berlin_groups[] = { EXPORT_SYMBOL_GPL(goodix_berlin_groups); int goodix_berlin_probe(struct device *dev, int irq, const struct input_id *id, - struct regmap *regmap) + struct regmap *regmap, + const struct goodix_berlin_ic_data *ic_data) { struct goodix_berlin_core *cd; int error; @@ -733,6 +735,7 @@ int goodix_berlin_probe(struct device *dev, int irq, const struct input_id *id, cd->dev = dev; cd->regmap = regmap; cd->irq = irq; + cd->ic_data = ic_data; cd->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH); if (IS_ERR(cd->reset_gpio))
diff --git a/drivers/input/touchscreen/goodix_berlin_i2c.c b/drivers/input/touchscreen/goodix_berlin_i2c.c index ad7a60d9..929090a 100644 --- a/drivers/input/touchscreen/goodix_berlin_i2c.c +++ b/drivers/input/touchscreen/goodix_berlin_i2c.c
@@ -31,6 +31,8 @@ static const struct input_id goodix_berlin_i2c_input_id = { static int goodix_berlin_i2c_probe(struct i2c_client *client) { + const struct goodix_berlin_ic_data *ic_data = + i2c_get_match_data(client); struct regmap *regmap; int error; @@ -39,22 +41,28 @@ static int goodix_berlin_i2c_probe(struct i2c_client *client) return PTR_ERR(regmap); error = goodix_berlin_probe(&client->dev, client->irq, - &goodix_berlin_i2c_input_id, regmap); + &goodix_berlin_i2c_input_id, regmap, + ic_data); if (error) return error; return 0; } +static const struct goodix_berlin_ic_data gt9916_data = { + .fw_version_info_addr = GOODIX_BERLIN_FW_VERSION_INFO_ADDR_D, + .ic_info_addr = GOODIX_BERLIN_IC_INFO_ADDR_D, +}; + static const struct i2c_device_id goodix_berlin_i2c_id[] = { - { "gt9916" }, + { .name = "gt9916", .driver_data = (long)>9916_data }, { } }; MODULE_DEVICE_TABLE(i2c, goodix_berlin_i2c_id); static const struct of_device_id goodix_berlin_i2c_of_match[] = { - { .compatible = "goodix,gt9916", }, + { .compatible = "goodix,gt9916", .data = >9916_data }, { } }; MODULE_DEVICE_TABLE(of, goodix_berlin_i2c_of_match);
diff --git a/drivers/input/touchscreen/goodix_berlin_spi.c b/drivers/input/touchscreen/goodix_berlin_spi.c index 0662e87..01f850f 100644 --- a/drivers/input/touchscreen/goodix_berlin_spi.c +++ b/drivers/input/touchscreen/goodix_berlin_spi.c
@@ -18,10 +18,14 @@ #define GOODIX_BERLIN_SPI_TRANS_PREFIX_LEN 1 #define GOODIX_BERLIN_REGISTER_WIDTH 4 -#define GOODIX_BERLIN_SPI_READ_DUMMY_LEN 3 -#define GOODIX_BERLIN_SPI_READ_PREFIX_LEN (GOODIX_BERLIN_SPI_TRANS_PREFIX_LEN + \ +#define GOODIX_BERLIN_SPI_READ_DUMMY_LEN_A 4 +#define GOODIX_BERLIN_SPI_READ_DUMMY_LEN_D 3 +#define GOODIX_BERLIN_SPI_READ_PREFIX_LEN_A (GOODIX_BERLIN_SPI_TRANS_PREFIX_LEN + \ GOODIX_BERLIN_REGISTER_WIDTH + \ - GOODIX_BERLIN_SPI_READ_DUMMY_LEN) + GOODIX_BERLIN_SPI_READ_DUMMY_LEN_A) +#define GOODIX_BERLIN_SPI_READ_PREFIX_LEN_D (GOODIX_BERLIN_SPI_TRANS_PREFIX_LEN + \ + GOODIX_BERLIN_REGISTER_WIDTH + \ + GOODIX_BERLIN_SPI_READ_DUMMY_LEN_D) #define GOODIX_BERLIN_SPI_WRITE_PREFIX_LEN (GOODIX_BERLIN_SPI_TRANS_PREFIX_LEN + \ GOODIX_BERLIN_REGISTER_WIDTH) @@ -33,6 +37,7 @@ static int goodix_berlin_spi_read(void *context, const void *reg_buf, size_t val_size) { struct spi_device *spi = context; + const struct goodix_berlin_ic_data *ic_data = spi_get_device_match_data(spi); struct spi_transfer xfers; struct spi_message spi_msg; const u32 *reg = reg_buf; /* reg is stored as native u32 at start of buffer */ @@ -42,23 +47,22 @@ static int goodix_berlin_spi_read(void *context, const void *reg_buf, return -EINVAL; u8 *buf __free(kfree) = - kzalloc(GOODIX_BERLIN_SPI_READ_PREFIX_LEN + val_size, - GFP_KERNEL); + kzalloc(ic_data->read_prefix_len + val_size, GFP_KERNEL); if (!buf) return -ENOMEM; spi_message_init(&spi_msg); memset(&xfers, 0, sizeof(xfers)); - /* buffer format: 0xF1 + addr(4bytes) + dummy(3bytes) + data */ + /* buffer format: 0xF1 + addr(4bytes) + dummy(3/4bytes) + data */ buf[0] = GOODIX_BERLIN_SPI_READ_FLAG; put_unaligned_be32(*reg, buf + GOODIX_BERLIN_SPI_TRANS_PREFIX_LEN); memset(buf + GOODIX_BERLIN_SPI_TRANS_PREFIX_LEN + GOODIX_BERLIN_REGISTER_WIDTH, - 0xff, GOODIX_BERLIN_SPI_READ_DUMMY_LEN); + 0xff, ic_data->read_dummy_len); xfers.tx_buf = buf; xfers.rx_buf = buf; - xfers.len = GOODIX_BERLIN_SPI_READ_PREFIX_LEN + val_size; + xfers.len = ic_data->read_prefix_len + val_size; xfers.cs_change = 0; spi_message_add_tail(&xfers, &spi_msg); @@ -68,7 +72,7 @@ static int goodix_berlin_spi_read(void *context, const void *reg_buf, return error; } - memcpy(val_buf, buf + GOODIX_BERLIN_SPI_READ_PREFIX_LEN, val_size); + memcpy(val_buf, buf + ic_data->read_prefix_len, val_size); return error; } @@ -123,6 +127,7 @@ static const struct input_id goodix_berlin_spi_input_id = { static int goodix_berlin_spi_probe(struct spi_device *spi) { + const struct goodix_berlin_ic_data *ic_data = spi_get_device_match_data(spi); struct regmap_config regmap_config; struct regmap *regmap; size_t max_size; @@ -137,7 +142,7 @@ static int goodix_berlin_spi_probe(struct spi_device *spi) max_size = spi_max_transfer_size(spi); regmap_config = goodix_berlin_spi_regmap_conf; - regmap_config.max_raw_read = max_size - GOODIX_BERLIN_SPI_READ_PREFIX_LEN; + regmap_config.max_raw_read = max_size - ic_data->read_prefix_len; regmap_config.max_raw_write = max_size - GOODIX_BERLIN_SPI_WRITE_PREFIX_LEN; regmap = devm_regmap_init(&spi->dev, NULL, spi, ®map_config); @@ -145,21 +150,38 @@ static int goodix_berlin_spi_probe(struct spi_device *spi) return PTR_ERR(regmap); error = goodix_berlin_probe(&spi->dev, spi->irq, - &goodix_berlin_spi_input_id, regmap); + &goodix_berlin_spi_input_id, regmap, + ic_data); if (error) return error; return 0; } +static const struct goodix_berlin_ic_data gt9897_data = { + .fw_version_info_addr = GOODIX_BERLIN_FW_VERSION_INFO_ADDR_A, + .ic_info_addr = GOODIX_BERLIN_IC_INFO_ADDR_A, + .read_dummy_len = GOODIX_BERLIN_SPI_READ_DUMMY_LEN_A, + .read_prefix_len = GOODIX_BERLIN_SPI_READ_PREFIX_LEN_A, +}; + +static const struct goodix_berlin_ic_data gt9916_data = { + .fw_version_info_addr = GOODIX_BERLIN_FW_VERSION_INFO_ADDR_D, + .ic_info_addr = GOODIX_BERLIN_IC_INFO_ADDR_D, + .read_dummy_len = GOODIX_BERLIN_SPI_READ_DUMMY_LEN_D, + .read_prefix_len = GOODIX_BERLIN_SPI_READ_PREFIX_LEN_D, +}; + static const struct spi_device_id goodix_berlin_spi_ids[] = { - { "gt9916" }, + { .name = "gt9897", .driver_data = (long)>9897_data }, + { .name = "gt9916", .driver_data = (long)>9916_data }, { }, }; MODULE_DEVICE_TABLE(spi, goodix_berlin_spi_ids); static const struct of_device_id goodix_berlin_spi_of_match[] = { - { .compatible = "goodix,gt9916", }, + { .compatible = "goodix,gt9897", .data = >9897_data }, + { .compatible = "goodix,gt9916", .data = >9916_data }, { } }; MODULE_DEVICE_TABLE(of, goodix_berlin_spi_of_match);
diff --git a/drivers/input/touchscreen/sur40.c b/drivers/input/touchscreen/sur40.c index 8365a2a..7b3b10c 100644 --- a/drivers/input/touchscreen/sur40.c +++ b/drivers/input/touchscreen/sur40.c
@@ -1108,8 +1108,6 @@ static const struct vb2_ops sur40_queue_ops = { .buf_queue = sur40_buffer_queue, .start_streaming = sur40_start_streaming, .stop_streaming = sur40_stop_streaming, - .wait_prepare = vb2_ops_wait_prepare, - .wait_finish = vb2_ops_wait_finish, }; static const struct vb2_queue sur40_queue = {
diff --git a/drivers/input/touchscreen/sx8654.c b/drivers/input/touchscreen/sx8654.c index f5c5881..e59b8d0 100644 --- a/drivers/input/touchscreen/sx8654.c +++ b/drivers/input/touchscreen/sx8654.c
@@ -290,7 +290,7 @@ static void sx8654_close(struct input_dev *dev) disable_irq(client->irq); if (!sx8654->data->has_irq_penrelease) - del_timer_sync(&sx8654->timer); + timer_delete_sync(&sx8654->timer); /* enable manual mode mode */ error = i2c_smbus_write_byte(client, sx8654->data->cmd_manual);
diff --git a/drivers/input/touchscreen/tsc2007.h b/drivers/input/touchscreen/tsc2007.h index 69b08dd..e346fb4 100644 --- a/drivers/input/touchscreen/tsc2007.h +++ b/drivers/input/touchscreen/tsc2007.h
@@ -19,6 +19,7 @@ #ifndef _TSC2007_H #define _TSC2007_H +#include <linux/input/touchscreen.h> struct gpio_desc; #define TSC2007_MEASURE_TEMP0 (0x0 << 4) @@ -63,6 +64,7 @@ struct tsc2007 { struct i2c_client *client; + struct touchscreen_properties prop; u16 model; u16 x_plate_ohms; u16 max_rt;
diff --git a/drivers/input/touchscreen/tsc2007_core.c b/drivers/input/touchscreen/tsc2007_core.c index 8d832a3..5252301 100644 --- a/drivers/input/touchscreen/tsc2007_core.c +++ b/drivers/input/touchscreen/tsc2007_core.c
@@ -142,8 +142,7 @@ static irqreturn_t tsc2007_soft_irq(int irq, void *handle) rt = ts->max_rt - rt; input_report_key(input, BTN_TOUCH, 1); - input_report_abs(input, ABS_X, tc.x); - input_report_abs(input, ABS_Y, tc.y); + touchscreen_report_pos(input, &ts->prop, tc.x, tc.y, false); input_report_abs(input, ABS_PRESSURE, rt); input_sync(input); @@ -339,9 +338,9 @@ static int tsc2007_probe(struct i2c_client *client) input_set_drvdata(input_dev, ts); input_set_capability(input_dev, EV_KEY, BTN_TOUCH); - input_set_abs_params(input_dev, ABS_X, 0, MAX_12BIT, ts->fuzzx, 0); input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, ts->fuzzy, 0); + touchscreen_parse_properties(input_dev, false, &ts->prop); input_set_abs_params(input_dev, ABS_PRESSURE, 0, MAX_12BIT, ts->fuzzz, 0);
diff --git a/drivers/input/touchscreen/tsc200x-core.c b/drivers/input/touchscreen/tsc200x-core.c index df39dee..252a937 100644 --- a/drivers/input/touchscreen/tsc200x-core.c +++ b/drivers/input/touchscreen/tsc200x-core.c
@@ -229,7 +229,7 @@ static void __tsc200x_disable(struct tsc200x *ts) guard(disable_irq)(&ts->irq); - del_timer_sync(&ts->penup_timer); + timer_delete_sync(&ts->penup_timer); cancel_delayed_work_sync(&ts->esd_work); } @@ -388,7 +388,7 @@ static void tsc200x_esd_work(struct work_struct *work) dev_info(ts->dev, "TSC200X not responding - resetting\n"); scoped_guard(disable_irq, &ts->irq) { - del_timer_sync(&ts->penup_timer); + timer_delete_sync(&ts->penup_timer); tsc200x_update_pen_state(ts, 0, 0, 0); tsc200x_reset(ts); }
diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c index 6054d0a..cb7e29d 100644 --- a/drivers/iommu/dma-iommu.c +++ b/drivers/iommu/dma-iommu.c
@@ -271,7 +271,7 @@ static void iommu_dma_free_fq(struct iommu_dma_cookie *cookie) if (!cookie->fq_domain) return; - del_timer_sync(&cookie->fq_timer); + timer_delete_sync(&cookie->fq_timer); if (cookie->options.qt == IOMMU_DMA_OPTS_SINGLE_QUEUE) iommu_dma_free_fq_single(cookie->single_fq); else
diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c index d7c5ef2..2aa6a51 100644 --- a/drivers/irqchip/irq-armada-370-xp.c +++ b/drivers/irqchip/irq-armada-370-xp.c
@@ -564,7 +564,7 @@ static void mpic_reenable_percpu(struct mpic *mpic) static int mpic_starting_cpu(unsigned int cpu) { - struct mpic *mpic = irq_get_default_host()->host_data; + struct mpic *mpic = irq_get_default_domain()->host_data; mpic_perf_init(mpic); mpic_smp_cpu_init(mpic); @@ -700,7 +700,7 @@ static void mpic_handle_cascade_irq(struct irq_desc *desc) static void __exception_irq_entry mpic_handle_irq(struct pt_regs *regs) { - struct mpic *mpic = irq_get_default_host()->host_data; + struct mpic *mpic = irq_get_default_domain()->host_data; irq_hw_number_t i; u32 irqstat; @@ -880,7 +880,7 @@ static int __init mpic_of_init(struct device_node *node, struct device_node *par } if (mpic_is_ipi_available(mpic)) { - irq_set_default_host(mpic->domain); + irq_set_default_domain(mpic->domain); set_handle_irq(mpic_handle_irq); #ifdef CONFIG_SMP err = mpic_ipi_init(mpic, node);
diff --git a/drivers/irqchip/irq-clps711x.c b/drivers/irqchip/irq-clps711x.c index 806ebb1..48c73c9 100644 --- a/drivers/irqchip/irq-clps711x.c +++ b/drivers/irqchip/irq-clps711x.c
@@ -191,7 +191,7 @@ static int __init _clps711x_intc_init(struct device_node *np, goto out_irqfree; } - irq_set_default_host(clps711x_intc->domain); + irq_set_default_domain(clps711x_intc->domain); set_handle_irq(clps711x_irqh); #ifdef CONFIG_FIQ
diff --git a/drivers/irqchip/irq-imx-gpcv2.c b/drivers/irqchip/irq-imx-gpcv2.c index 8a0e820..095ae8e 100644 --- a/drivers/irqchip/irq-imx-gpcv2.c +++ b/drivers/irqchip/irq-imx-gpcv2.c
@@ -247,7 +247,7 @@ static int __init imx_gpcv2_irqchip_init(struct device_node *node, kfree(cd); return -ENOMEM; } - irq_set_default_host(domain); + irq_set_default_domain(domain); /* Initially mask all interrupts */ for (i = 0; i < IMR_NUM; i++) {
diff --git a/drivers/irqchip/irq-pic32-evic.c b/drivers/irqchip/irq-pic32-evic.c index eb6ca51..b546b10 100644 --- a/drivers/irqchip/irq-pic32-evic.c +++ b/drivers/irqchip/irq-pic32-evic.c
@@ -291,7 +291,7 @@ static int __init pic32_of_init(struct device_node *node, gc->private = &priv[i]; } - irq_set_default_host(evic_irq_domain); + irq_set_default_domain(evic_irq_domain); /* * External interrupts have software configurable edge polarity. These
diff --git a/drivers/irqchip/irq-xilinx-intc.c b/drivers/irqchip/irq-xilinx-intc.c index 7e08714..38727e9 100644 --- a/drivers/irqchip/irq-xilinx-intc.c +++ b/drivers/irqchip/irq-xilinx-intc.c
@@ -233,7 +233,7 @@ static int __init xilinx_intc_of_init(struct device_node *intc, } } else { primary_intc = irqc; - irq_set_default_host(primary_intc->root_domain); + irq_set_default_domain(primary_intc->root_domain); set_handle_irq(xil_intc_handle_irq); }
diff --git a/drivers/irqchip/irq-xtensa-mx.c b/drivers/irqchip/irq-xtensa-mx.c index 7f314e5..9b441d1 100644 --- a/drivers/irqchip/irq-xtensa-mx.c +++ b/drivers/irqchip/irq-xtensa-mx.c
@@ -156,7 +156,7 @@ static void __init xtensa_mx_init_common(struct irq_domain *root_domain) { unsigned int i; - irq_set_default_host(root_domain); + irq_set_default_domain(root_domain); secondary_init_irq(); /* Initialize default IRQ routing to CPU 0 */
diff --git a/drivers/irqchip/irq-xtensa-pic.c b/drivers/irqchip/irq-xtensa-pic.c index f9d6fce..9be7b7c 100644 --- a/drivers/irqchip/irq-xtensa-pic.c +++ b/drivers/irqchip/irq-xtensa-pic.c
@@ -87,7 +87,7 @@ int __init xtensa_pic_init_legacy(struct device_node *interrupt_parent) struct irq_domain *root_domain = irq_domain_add_legacy(NULL, NR_IRQS - 1, 1, 0, &xtensa_irq_domain_ops, &xtensa_irq_chip); - irq_set_default_host(root_domain); + irq_set_default_domain(root_domain); return 0; } @@ -97,7 +97,7 @@ static int __init xtensa_pic_init(struct device_node *np, struct irq_domain *root_domain = irq_domain_add_linear(np, NR_IRQS, &xtensa_irq_domain_ops, &xtensa_irq_chip); - irq_set_default_host(root_domain); + irq_set_default_domain(root_domain); return 0; } IRQCHIP_DECLARE(xtensa_irq_chip, "cdns,xtensa-pic", xtensa_pic_init);
diff --git a/drivers/isdn/hardware/mISDN/hfcmulti.c b/drivers/isdn/hardware/mISDN/hfcmulti.c index 45ff0e1..f6c27ca 100644 --- a/drivers/isdn/hardware/mISDN/hfcmulti.c +++ b/drivers/isdn/hardware/mISDN/hfcmulti.c
@@ -3249,7 +3249,7 @@ hfcm_l1callback(struct dchannel *dch, u_int cmd) } test_and_clear_bit(FLG_TX_BUSY, &dch->Flags); if (test_and_clear_bit(FLG_BUSY_TIMER, &dch->Flags)) - del_timer(&dch->timer); + timer_delete(&dch->timer); spin_unlock_irqrestore(&hc->lock, flags); __skb_queue_purge(&free_queue); break; @@ -3394,7 +3394,7 @@ handle_dmsg(struct mISDNchannel *ch, struct sk_buff *skb) } test_and_clear_bit(FLG_TX_BUSY, &dch->Flags); if (test_and_clear_bit(FLG_BUSY_TIMER, &dch->Flags)) - del_timer(&dch->timer); + timer_delete(&dch->timer); #ifdef FIXME if (test_and_clear_bit(FLG_L1_BUSY, &dch->Flags)) dchannel_sched_event(&hc->dch, D_CLEARBUSY); @@ -4522,7 +4522,7 @@ release_port(struct hfc_multi *hc, struct dchannel *dch) spin_lock_irqsave(&hc->lock, flags); if (dch->timer.function) { - del_timer(&dch->timer); + timer_delete(&dch->timer); dch->timer.function = NULL; }
diff --git a/drivers/isdn/hardware/mISDN/hfcpci.c b/drivers/isdn/hardware/mISDN/hfcpci.c index ce7bccc..e3870d9 100644 --- a/drivers/isdn/hardware/mISDN/hfcpci.c +++ b/drivers/isdn/hardware/mISDN/hfcpci.c
@@ -158,7 +158,7 @@ release_io_hfcpci(struct hfc_pci *hc) { /* disable memory mapped ports + busmaster */ pci_write_config_word(hc->pdev, PCI_COMMAND, 0); - del_timer(&hc->hw.timer); + timer_delete(&hc->hw.timer); dma_free_coherent(&hc->pdev->dev, 0x8000, hc->hw.fifos, hc->hw.dmahandle); iounmap(hc->hw.pci_io); @@ -1087,7 +1087,7 @@ hfc_l1callback(struct dchannel *dch, u_int cmd) } test_and_clear_bit(FLG_TX_BUSY, &dch->Flags); if (test_and_clear_bit(FLG_BUSY_TIMER, &dch->Flags)) - del_timer(&dch->timer); + timer_delete(&dch->timer); break; case HW_POWERUP_REQ: Write_hfc(hc, HFCPCI_STATES, HFCPCI_DO_ACTION); @@ -1216,7 +1216,7 @@ hfcpci_int(int intno, void *dev_id) receive_dmsg(hc); if (val & 0x04) { /* D tx */ if (test_and_clear_bit(FLG_BUSY_TIMER, &hc->dch.Flags)) - del_timer(&hc->dch.timer); + timer_delete(&hc->dch.timer); tx_dirq(&hc->dch); } spin_unlock(&hc->lock); @@ -1635,7 +1635,7 @@ hfcpci_l2l1D(struct mISDNchannel *ch, struct sk_buff *skb) } test_and_clear_bit(FLG_TX_BUSY, &dch->Flags); if (test_and_clear_bit(FLG_BUSY_TIMER, &dch->Flags)) - del_timer(&dch->timer); + timer_delete(&dch->timer); #ifdef FIXME if (test_and_clear_bit(FLG_L1_BUSY, &dch->Flags)) dchannel_sched_event(&hc->dch, D_CLEARBUSY); @@ -2064,7 +2064,7 @@ release_card(struct hfc_pci *hc) { mode_hfcpci(&hc->bch[0], 1, ISDN_P_NONE); mode_hfcpci(&hc->bch[1], 2, ISDN_P_NONE); if (hc->dch.timer.function != NULL) { - del_timer(&hc->dch.timer); + timer_delete(&hc->dch.timer); hc->dch.timer.function = NULL; } spin_unlock_irqrestore(&hc->lock, flags); @@ -2342,7 +2342,7 @@ HFC_init(void) err = pci_register_driver(&hfc_driver); if (err) { if (timer_pending(&hfc_tl)) - del_timer(&hfc_tl); + timer_delete(&hfc_tl); } return err; @@ -2351,7 +2351,7 @@ HFC_init(void) static void __exit HFC_cleanup(void) { - del_timer_sync(&hfc_tl); + timer_delete_sync(&hfc_tl); pci_unregister_driver(&hfc_driver); }
diff --git a/drivers/isdn/hardware/mISDN/mISDNipac.c b/drivers/isdn/hardware/mISDN/mISDNipac.c index d0b7271..165a639 100644 --- a/drivers/isdn/hardware/mISDN/mISDNipac.c +++ b/drivers/isdn/hardware/mISDN/mISDNipac.c
@@ -158,7 +158,7 @@ isac_fill_fifo(struct isac_hw *isac) WriteISAC(isac, ISAC_CMDR, more ? 0x8 : 0xa); if (test_and_set_bit(FLG_BUSY_TIMER, &isac->dch.Flags)) { pr_debug("%s: %s dbusytimer running\n", isac->name, __func__); - del_timer(&isac->dch.timer); + timer_delete(&isac->dch.timer); } isac->dch.timer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ)/1000); add_timer(&isac->dch.timer); @@ -206,7 +206,7 @@ static void isac_xpr_irq(struct isac_hw *isac) { if (test_and_clear_bit(FLG_BUSY_TIMER, &isac->dch.Flags)) - del_timer(&isac->dch.timer); + timer_delete(&isac->dch.timer); if (isac->dch.tx_skb && isac->dch.tx_idx < isac->dch.tx_skb->len) { isac_fill_fifo(isac); } else { @@ -220,7 +220,7 @@ static void isac_retransmit(struct isac_hw *isac) { if (test_and_clear_bit(FLG_BUSY_TIMER, &isac->dch.Flags)) - del_timer(&isac->dch.timer); + timer_delete(&isac->dch.timer); if (test_bit(FLG_TX_BUSY, &isac->dch.Flags)) { /* Restart frame */ isac->dch.tx_idx = 0; @@ -665,7 +665,7 @@ isac_l1cmd(struct dchannel *dch, u32 cmd) } test_and_clear_bit(FLG_TX_BUSY, &dch->Flags); if (test_and_clear_bit(FLG_BUSY_TIMER, &dch->Flags)) - del_timer(&dch->timer); + timer_delete(&dch->timer); break; case HW_POWERUP_REQ: spin_lock_irqsave(isac->hwlock, flags); @@ -698,7 +698,7 @@ isac_release(struct isac_hw *isac) else if (isac->type != 0) WriteISAC(isac, ISAC_MASK, 0xff); if (isac->dch.timer.function != NULL) { - del_timer(&isac->dch.timer); + timer_delete(&isac->dch.timer); isac->dch.timer.function = NULL; } kfree(isac->mon_rx);
diff --git a/drivers/isdn/hardware/mISDN/mISDNisar.c b/drivers/isdn/hardware/mISDN/mISDNisar.c index b3e03c4..e48f89c 100644 --- a/drivers/isdn/hardware/mISDN/mISDNisar.c +++ b/drivers/isdn/hardware/mISDN/mISDNisar.c
@@ -930,7 +930,7 @@ isar_pump_statev_fax(struct isar_ch *ch, u8 devt) { /* 1s (200 ms) Flags before data */ if (test_and_set_bit(FLG_FTI_RUN, &ch->bch.Flags)) - del_timer(&ch->ftimer); + timer_delete(&ch->ftimer); ch->ftimer.expires = jiffies + ((delay * HZ) / 1000); test_and_set_bit(FLG_LL_CONN, @@ -1603,8 +1603,8 @@ free_isar(struct isar_hw *isar) { modeisar(&isar->ch[0], ISDN_P_NONE); modeisar(&isar->ch[1], ISDN_P_NONE); - del_timer(&isar->ch[0].ftimer); - del_timer(&isar->ch[1].ftimer); + timer_delete(&isar->ch[0].ftimer); + timer_delete(&isar->ch[1].ftimer); test_and_clear_bit(FLG_INITIALIZED, &isar->ch[0].bch.Flags); test_and_clear_bit(FLG_INITIALIZED, &isar->ch[1].bch.Flags); }
diff --git a/drivers/isdn/hardware/mISDN/w6692.c b/drivers/isdn/hardware/mISDN/w6692.c index ee69212..da933f4 100644 --- a/drivers/isdn/hardware/mISDN/w6692.c +++ b/drivers/isdn/hardware/mISDN/w6692.c
@@ -294,7 +294,7 @@ W6692_fill_Dfifo(struct w6692_hw *card) WriteW6692(card, W_D_CMDR, cmd); if (test_and_set_bit(FLG_BUSY_TIMER, &dch->Flags)) { pr_debug("%s: fill_Dfifo dbusytimer running\n", card->name); - del_timer(&dch->timer); + timer_delete(&dch->timer); } dch->timer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ) / 1000); add_timer(&dch->timer); @@ -311,7 +311,7 @@ d_retransmit(struct w6692_hw *card) struct dchannel *dch = &card->dch; if (test_and_clear_bit(FLG_BUSY_TIMER, &dch->Flags)) - del_timer(&dch->timer); + timer_delete(&dch->timer); #ifdef FIXME if (test_and_clear_bit(FLG_L1_BUSY, &dch->Flags)) dchannel_sched_event(dch, D_CLEARBUSY); @@ -372,7 +372,7 @@ handle_rxD(struct w6692_hw *card) { static void handle_txD(struct w6692_hw *card) { if (test_and_clear_bit(FLG_BUSY_TIMER, &card->dch.Flags)) - del_timer(&card->dch.timer); + timer_delete(&card->dch.timer); if (card->dch.tx_skb && card->dch.tx_idx < card->dch.tx_skb->len) { W6692_fill_Dfifo(card); } else { @@ -1130,7 +1130,7 @@ w6692_l1callback(struct dchannel *dch, u32 cmd) } test_and_clear_bit(FLG_TX_BUSY, &dch->Flags); if (test_and_clear_bit(FLG_BUSY_TIMER, &dch->Flags)) - del_timer(&dch->timer); + timer_delete(&dch->timer); break; case HW_POWERUP_REQ: spin_lock_irqsave(&card->lock, flags);
diff --git a/drivers/isdn/mISDN/dsp_core.c b/drivers/isdn/mISDN/dsp_core.c index 753232e..d0aa415 100644 --- a/drivers/isdn/mISDN/dsp_core.c +++ b/drivers/isdn/mISDN/dsp_core.c
@@ -928,7 +928,7 @@ dsp_function(struct mISDNchannel *ch, struct sk_buff *skb) dsp->tone.hardware = 0; dsp->tone.software = 0; if (timer_pending(&dsp->tone.tl)) - del_timer(&dsp->tone.tl); + timer_delete(&dsp->tone.tl); if (dsp->conf) dsp_cmx_conf(dsp, 0); /* dsp_cmx_hardware will also be called here */ @@ -975,7 +975,7 @@ dsp_ctrl(struct mISDNchannel *ch, u_int cmd, void *arg) cancel_work_sync(&dsp->workq); spin_lock_irqsave(&dsp_lock, flags); if (timer_pending(&dsp->tone.tl)) - del_timer(&dsp->tone.tl); + timer_delete(&dsp->tone.tl); skb_queue_purge(&dsp->sendq); if (dsp_debug & DEBUG_DSP_CTRL) printk(KERN_DEBUG "%s: releasing member %s\n", @@ -1209,7 +1209,7 @@ static void __exit dsp_cleanup(void) { mISDN_unregister_Bprotocol(&DSP); - del_timer_sync(&dsp_spl_tl); + timer_delete_sync(&dsp_spl_tl); if (!list_empty(&dsp_ilist)) { printk(KERN_ERR "mISDN_dsp: Audio DSP object inst list not "
diff --git a/drivers/isdn/mISDN/dsp_tones.c b/drivers/isdn/mISDN/dsp_tones.c index 8389e21..456b313 100644 --- a/drivers/isdn/mISDN/dsp_tones.c +++ b/drivers/isdn/mISDN/dsp_tones.c
@@ -505,7 +505,7 @@ dsp_tone(struct dsp *dsp, int tone) /* we turn off the tone */ if (!tone) { if (dsp->features.hfc_loops && timer_pending(&tonet->tl)) - del_timer(&tonet->tl); + timer_delete(&tonet->tl); if (dsp->features.hfc_loops) dsp_tone_hw_message(dsp, NULL, 0); tonet->tone = 0; @@ -539,7 +539,7 @@ dsp_tone(struct dsp *dsp, int tone) dsp_tone_hw_message(dsp, pat->data[0], *(pat->siz[0])); /* set timer */ if (timer_pending(&tonet->tl)) - del_timer(&tonet->tl); + timer_delete(&tonet->tl); tonet->tl.expires = jiffies + (pat->seq[0] * HZ) / 8000; add_timer(&tonet->tl); } else {
diff --git a/drivers/isdn/mISDN/fsm.c b/drivers/isdn/mISDN/fsm.c index 7c5c2ca..5ed0a61 100644 --- a/drivers/isdn/mISDN/fsm.c +++ b/drivers/isdn/mISDN/fsm.c
@@ -123,7 +123,7 @@ mISDN_FsmDelTimer(struct FsmTimer *ft, int where) ft->fi->printdebug(ft->fi, "mISDN_FsmDelTimer %lx %d", (long) ft, where); #endif - del_timer(&ft->tl); + timer_delete(&ft->tl); } EXPORT_SYMBOL(mISDN_FsmDelTimer); @@ -167,7 +167,7 @@ mISDN_FsmRestartTimer(struct FsmTimer *ft, #endif if (timer_pending(&ft->tl)) - del_timer(&ft->tl); + timer_delete(&ft->tl); ft->event = event; ft->arg = arg; ft->tl.expires = jiffies + (millisec * HZ) / 1000;
diff --git a/drivers/leds/flash/leds-rt8515.c b/drivers/leds/flash/leds-rt8515.c index 6b051f1..32ba397 100644 --- a/drivers/leds/flash/leds-rt8515.c +++ b/drivers/leds/flash/leds-rt8515.c
@@ -127,7 +127,7 @@ static int rt8515_led_flash_strobe_set(struct led_classdev_flash *fled, mod_timer(&rt->powerdown_timer, jiffies + usecs_to_jiffies(timeout->val)); } else { - del_timer_sync(&rt->powerdown_timer); + timer_delete_sync(&rt->powerdown_timer); /* Turn the LED off */ rt8515_gpio_led_off(rt); } @@ -372,7 +372,7 @@ static void rt8515_remove(struct platform_device *pdev) struct rt8515 *rt = platform_get_drvdata(pdev); rt8515_v4l2_flash_release(rt); - del_timer_sync(&rt->powerdown_timer); + timer_delete_sync(&rt->powerdown_timer); mutex_destroy(&rt->lock); }
diff --git a/drivers/leds/flash/leds-sgm3140.c b/drivers/leds/flash/leds-sgm3140.c index 3c01739..48fb8a9 100644 --- a/drivers/leds/flash/leds-sgm3140.c +++ b/drivers/leds/flash/leds-sgm3140.c
@@ -55,7 +55,7 @@ static int sgm3140_strobe_set(struct led_classdev_flash *fled_cdev, bool state) mod_timer(&priv->powerdown_timer, jiffies + usecs_to_jiffies(priv->timeout)); } else { - del_timer_sync(&priv->powerdown_timer); + timer_delete_sync(&priv->powerdown_timer); gpiod_set_value_cansleep(priv->enable_gpio, 0); gpiod_set_value_cansleep(priv->flash_gpio, 0); ret = regulator_disable(priv->vin_regulator); @@ -117,7 +117,7 @@ static int sgm3140_brightness_set(struct led_classdev *led_cdev, gpiod_set_value_cansleep(priv->flash_gpio, 0); gpiod_set_value_cansleep(priv->enable_gpio, 1); } else { - del_timer_sync(&priv->powerdown_timer); + timer_delete_sync(&priv->powerdown_timer); gpiod_set_value_cansleep(priv->flash_gpio, 0); gpiod_set_value_cansleep(priv->enable_gpio, 0); ret = regulator_disable(priv->vin_regulator); @@ -285,7 +285,7 @@ static void sgm3140_remove(struct platform_device *pdev) { struct sgm3140 *priv = platform_get_drvdata(pdev); - del_timer_sync(&priv->powerdown_timer); + timer_delete_sync(&priv->powerdown_timer); v4l2_flash_release(priv->v4l2_flash); }
diff --git a/drivers/leds/led-core.c b/drivers/leds/led-core.c index e3d8ddc..907fc70 100644 --- a/drivers/leds/led-core.c +++ b/drivers/leds/led-core.c
@@ -245,7 +245,7 @@ void led_blink_set(struct led_classdev *led_cdev, unsigned long *delay_on, unsigned long *delay_off) { - del_timer_sync(&led_cdev->blink_timer); + timer_delete_sync(&led_cdev->blink_timer); clear_bit(LED_BLINK_SW, &led_cdev->work_flags); clear_bit(LED_BLINK_ONESHOT, &led_cdev->work_flags); @@ -294,7 +294,7 @@ EXPORT_SYMBOL_GPL(led_blink_set_nosleep); void led_stop_software_blink(struct led_classdev *led_cdev) { - del_timer_sync(&led_cdev->blink_timer); + timer_delete_sync(&led_cdev->blink_timer); led_cdev->blink_delay_on = 0; led_cdev->blink_delay_off = 0; clear_bit(LED_BLINK_SW, &led_cdev->work_flags);
diff --git a/drivers/leds/trigger/ledtrig-pattern.c b/drivers/leds/trigger/ledtrig-pattern.c index a594bd5..06d0529 100644 --- a/drivers/leds/trigger/ledtrig-pattern.c +++ b/drivers/leds/trigger/ledtrig-pattern.c
@@ -94,7 +94,7 @@ static void pattern_trig_timer_cancel(struct pattern_trig_data *data) if (data->type == PATTERN_TYPE_HR) hrtimer_cancel(&data->hrtimer); else - del_timer_sync(&data->timer); + timer_delete_sync(&data->timer); } static void pattern_trig_timer_restart(struct pattern_trig_data *data,
diff --git a/drivers/leds/trigger/ledtrig-transient.c b/drivers/leds/trigger/ledtrig-transient.c index f111fa76..e103c7e 100644 --- a/drivers/leds/trigger/ledtrig-transient.c +++ b/drivers/leds/trigger/ledtrig-transient.c
@@ -66,7 +66,7 @@ static ssize_t transient_activate_store(struct device *dev, /* cancel the running timer */ if (state == 0 && transient_data->activate == 1) { - del_timer(&transient_data->timer); + timer_delete(&transient_data->timer); transient_data->activate = state; led_set_brightness_nosleep(led_cdev, transient_data->restore_state);
diff --git a/drivers/macintosh/adbhid.c b/drivers/macintosh/adbhid.c index b2fe7a3..c5aabf2 100644 --- a/drivers/macintosh/adbhid.c +++ b/drivers/macintosh/adbhid.c
@@ -724,7 +724,7 @@ adb_message_handler(struct notifier_block *this, unsigned long code, void *x) int i; for (i = 1; i < 16; i++) { if (adbhid[i]) - del_timer_sync(&adbhid[i]->input->timer); + timer_delete_sync(&adbhid[i]->input->timer); } }
diff --git a/drivers/mailbox/mailbox-altera.c b/drivers/mailbox/mailbox-altera.c index afb320e..7481286 100644 --- a/drivers/mailbox/mailbox-altera.c +++ b/drivers/mailbox/mailbox-altera.c
@@ -270,7 +270,7 @@ static void altera_mbox_shutdown(struct mbox_chan *chan) writel_relaxed(~0, mbox->mbox_base + MAILBOX_INTMASK_REG); free_irq(mbox->irq, chan); } else if (!mbox->is_sender) { - del_timer_sync(&mbox->rxpoll_timer); + timer_delete_sync(&mbox->rxpoll_timer); } }
diff --git a/drivers/md/Kconfig b/drivers/md/Kconfig index 0b1870a..ddb37f6 100644 --- a/drivers/md/Kconfig +++ b/drivers/md/Kconfig
@@ -139,7 +139,7 @@ tristate "RAID-4/RAID-5/RAID-6 mode" depends on BLK_DEV_MD select RAID6_PQ - select LIBCRC32C + select CRC32 select ASYNC_MEMCPY select ASYNC_XOR select ASYNC_PQ @@ -267,6 +267,7 @@ depends on BLK_DEV_DM depends on (ENCRYPTED_KEYS || ENCRYPTED_KEYS=n) depends on (TRUSTED_KEYS || TRUSTED_KEYS=n) + select CRC32 select CRYPTO select CRYPTO_CBC select CRYPTO_ESSIV
diff --git a/drivers/md/bcache/stats.c b/drivers/md/bcache/stats.c index 68b0221..d39dec3 100644 --- a/drivers/md/bcache/stats.c +++ b/drivers/md/bcache/stats.c
@@ -123,7 +123,7 @@ void bch_cache_accounting_destroy(struct cache_accounting *acc) kobject_put(&acc->day.kobj); atomic_set(&acc->closing, 1); - if (del_timer_sync(&acc->timer)) + if (timer_delete_sync(&acc->timer)) closure_return(&acc->cl); }
diff --git a/drivers/md/dm-bufio.c b/drivers/md/dm-bufio.c index aab8240..9c8ed65 100644 --- a/drivers/md/dm-bufio.c +++ b/drivers/md/dm-bufio.c
@@ -2234,7 +2234,7 @@ int dm_bufio_issue_discard(struct dm_bufio_client *c, sector_t block, sector_t c } EXPORT_SYMBOL_GPL(dm_bufio_issue_discard); -static bool forget_buffer(struct dm_bufio_client *c, sector_t block) +static void forget_buffer(struct dm_bufio_client *c, sector_t block) { struct dm_buffer *b; @@ -2249,8 +2249,6 @@ static bool forget_buffer(struct dm_bufio_client *c, sector_t block) cache_put_and_wake(c, b); } } - - return b ? true : false; } /*
diff --git a/drivers/md/dm-cache-target.c b/drivers/md/dm-cache-target.c index 9cb797a..a10d75a 100644 --- a/drivers/md/dm-cache-target.c +++ b/drivers/md/dm-cache-target.c
@@ -406,6 +406,12 @@ struct cache { mempool_t migration_pool; struct bio_set bs; + + /* + * Cache_size entries. Set bits indicate blocks mapped beyond the + * target length, which are marked for invalidation. + */ + unsigned long *invalid_bitset; }; struct per_bio_data { @@ -1922,6 +1928,9 @@ static void __destroy(struct cache *cache) if (cache->discard_bitset) free_bitset(cache->discard_bitset); + if (cache->invalid_bitset) + free_bitset(cache->invalid_bitset); + if (cache->copier) dm_kcopyd_client_destroy(cache->copier); @@ -2510,6 +2519,13 @@ static int cache_create(struct cache_args *ca, struct cache **result) } clear_bitset(cache->discard_bitset, from_dblock(cache->discard_nr_blocks)); + cache->invalid_bitset = alloc_bitset(from_cblock(cache->cache_size)); + if (!cache->invalid_bitset) { + *error = "could not allocate bitset for invalid blocks"; + goto bad; + } + clear_bitset(cache->invalid_bitset, from_cblock(cache->cache_size)); + cache->copier = dm_kcopyd_client_create(&dm_kcopyd_throttle); if (IS_ERR(cache->copier)) { *error = "could not create kcopyd client"; @@ -2808,6 +2824,24 @@ static int load_mapping(void *context, dm_oblock_t oblock, dm_cblock_t cblock, return policy_load_mapping(cache->policy, oblock, cblock, dirty, hint, hint_valid); } +static int load_filtered_mapping(void *context, dm_oblock_t oblock, dm_cblock_t cblock, + bool dirty, uint32_t hint, bool hint_valid) +{ + struct cache *cache = context; + + if (from_oblock(oblock) >= from_oblock(cache->origin_blocks)) { + if (dirty) { + DMERR("%s: unable to shrink origin; cache block %u is dirty", + cache_device_name(cache), from_cblock(cblock)); + return -EFBIG; + } + set_bit(from_cblock(cblock), cache->invalid_bitset); + return 0; + } + + return load_mapping(context, oblock, cblock, dirty, hint, hint_valid); +} + /* * The discard block size in the on disk metadata is not * necessarily the same as we're currently using. So we have to @@ -2899,6 +2933,27 @@ static dm_cblock_t get_cache_dev_size(struct cache *cache) return to_cblock(size); } +static bool can_resume(struct cache *cache) +{ + /* + * Disallow retrying the resume operation for devices that failed the + * first resume attempt, as the failure leaves the policy object partially + * initialized. Retrying could trigger BUG_ON when loading cache mappings + * into the incomplete policy object. + */ + if (cache->sized && !cache->loaded_mappings) { + if (get_cache_mode(cache) != CM_WRITE) + DMERR("%s: unable to resume a failed-loaded cache, please check metadata.", + cache_device_name(cache)); + else + DMERR("%s: unable to resume cache due to missing proper cache table reload", + cache_device_name(cache)); + return false; + } + + return true; +} + static bool can_resize(struct cache *cache, dm_cblock_t new_size) { if (from_cblock(new_size) > from_cblock(cache->cache_size)) { @@ -2941,12 +2996,33 @@ static int resize_cache_dev(struct cache *cache, dm_cblock_t new_size) return 0; } +static int truncate_oblocks(struct cache *cache) +{ + uint32_t nr_blocks = from_cblock(cache->cache_size); + uint32_t i; + int r; + + for_each_set_bit(i, cache->invalid_bitset, nr_blocks) { + r = dm_cache_remove_mapping(cache->cmd, to_cblock(i)); + if (r) { + DMERR_LIMIT("%s: invalidation failed; couldn't update on disk metadata", + cache_device_name(cache)); + return r; + } + } + + return 0; +} + static int cache_preresume(struct dm_target *ti) { int r = 0; struct cache *cache = ti->private; dm_cblock_t csize = get_cache_dev_size(cache); + if (!can_resume(cache)) + return -EINVAL; + /* * Check to see if the cache has resized. */ @@ -2962,11 +3038,25 @@ static int cache_preresume(struct dm_target *ti) } if (!cache->loaded_mappings) { + /* + * The fast device could have been resized since the last + * failed preresume attempt. To be safe we start by a blank + * bitset for cache blocks. + */ + clear_bitset(cache->invalid_bitset, from_cblock(cache->cache_size)); + r = dm_cache_load_mappings(cache->cmd, cache->policy, - load_mapping, cache); + load_filtered_mapping, cache); if (r) { DMERR("%s: could not load cache mappings", cache_device_name(cache)); - metadata_operation_failed(cache, "dm_cache_load_mappings", r); + if (r != -EFBIG) + metadata_operation_failed(cache, "dm_cache_load_mappings", r); + return r; + } + + r = truncate_oblocks(cache); + if (r) { + metadata_operation_failed(cache, "dm_cache_remove_mapping", r); return r; } @@ -3426,7 +3516,7 @@ static void cache_io_hints(struct dm_target *ti, struct queue_limits *limits) static struct target_type cache_target = { .name = "cache", - .version = {2, 2, 0}, + .version = {2, 3, 0}, .module = THIS_MODULE, .ctr = cache_ctr, .dtr = cache_dtr,
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index 02a2919..9dfdb63 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c
@@ -17,6 +17,7 @@ #include <linux/bio.h> #include <linux/blkdev.h> #include <linux/blk-integrity.h> +#include <linux/crc32.h> #include <linux/mempool.h> #include <linux/slab.h> #include <linux/crypto.h> @@ -125,7 +126,6 @@ struct iv_lmk_private { #define TCW_WHITENING_SIZE 16 struct iv_tcw_private { - struct crypto_shash *crc32_tfm; u8 *iv_seed; u8 *whitening; }; @@ -607,10 +607,6 @@ static void crypt_iv_tcw_dtr(struct crypt_config *cc) tcw->iv_seed = NULL; kfree_sensitive(tcw->whitening); tcw->whitening = NULL; - - if (tcw->crc32_tfm && !IS_ERR(tcw->crc32_tfm)) - crypto_free_shash(tcw->crc32_tfm); - tcw->crc32_tfm = NULL; } static int crypt_iv_tcw_ctr(struct crypt_config *cc, struct dm_target *ti, @@ -628,13 +624,6 @@ static int crypt_iv_tcw_ctr(struct crypt_config *cc, struct dm_target *ti, return -EINVAL; } - tcw->crc32_tfm = crypto_alloc_shash("crc32", 0, - CRYPTO_ALG_ALLOCATES_MEMORY); - if (IS_ERR(tcw->crc32_tfm)) { - ti->error = "Error initializing CRC32 in TCW"; - return PTR_ERR(tcw->crc32_tfm); - } - tcw->iv_seed = kzalloc(cc->iv_size, GFP_KERNEL); tcw->whitening = kzalloc(TCW_WHITENING_SIZE, GFP_KERNEL); if (!tcw->iv_seed || !tcw->whitening) { @@ -668,36 +657,28 @@ static int crypt_iv_tcw_wipe(struct crypt_config *cc) return 0; } -static int crypt_iv_tcw_whitening(struct crypt_config *cc, - struct dm_crypt_request *dmreq, - u8 *data) +static void crypt_iv_tcw_whitening(struct crypt_config *cc, + struct dm_crypt_request *dmreq, u8 *data) { struct iv_tcw_private *tcw = &cc->iv_gen_private.tcw; __le64 sector = cpu_to_le64(dmreq->iv_sector); u8 buf[TCW_WHITENING_SIZE]; - SHASH_DESC_ON_STACK(desc, tcw->crc32_tfm); - int i, r; + int i; /* xor whitening with sector number */ crypto_xor_cpy(buf, tcw->whitening, (u8 *)§or, 8); crypto_xor_cpy(&buf[8], tcw->whitening + 8, (u8 *)§or, 8); /* calculate crc32 for every 32bit part and xor it */ - desc->tfm = tcw->crc32_tfm; - for (i = 0; i < 4; i++) { - r = crypto_shash_digest(desc, &buf[i * 4], 4, &buf[i * 4]); - if (r) - goto out; - } + for (i = 0; i < 4; i++) + put_unaligned_le32(crc32(0, &buf[i * 4], 4), &buf[i * 4]); crypto_xor(&buf[0], &buf[12], 4); crypto_xor(&buf[4], &buf[8], 4); /* apply whitening (8 bytes) to whole sector */ for (i = 0; i < ((1 << SECTOR_SHIFT) / 8); i++) crypto_xor(data + i * 8, buf, 8); -out: memzero_explicit(buf, sizeof(buf)); - return r; } static int crypt_iv_tcw_gen(struct crypt_config *cc, u8 *iv, @@ -707,13 +688,12 @@ static int crypt_iv_tcw_gen(struct crypt_config *cc, u8 *iv, struct iv_tcw_private *tcw = &cc->iv_gen_private.tcw; __le64 sector = cpu_to_le64(dmreq->iv_sector); u8 *src; - int r = 0; /* Remove whitening from ciphertext */ if (bio_data_dir(dmreq->ctx->bio_in) != WRITE) { sg = crypt_get_sg_data(cc, dmreq->sg_in); src = kmap_local_page(sg_page(sg)); - r = crypt_iv_tcw_whitening(cc, dmreq, src + sg->offset); + crypt_iv_tcw_whitening(cc, dmreq, src + sg->offset); kunmap_local(src); } @@ -723,7 +703,7 @@ static int crypt_iv_tcw_gen(struct crypt_config *cc, u8 *iv, crypto_xor_cpy(&iv[8], tcw->iv_seed + 8, (u8 *)§or, cc->iv_size - 8); - return r; + return 0; } static int crypt_iv_tcw_post(struct crypt_config *cc, u8 *iv, @@ -731,7 +711,6 @@ static int crypt_iv_tcw_post(struct crypt_config *cc, u8 *iv, { struct scatterlist *sg; u8 *dst; - int r; if (bio_data_dir(dmreq->ctx->bio_in) != WRITE) return 0; @@ -739,10 +718,10 @@ static int crypt_iv_tcw_post(struct crypt_config *cc, u8 *iv, /* Apply whitening on ciphertext */ sg = crypt_get_sg_data(cc, dmreq->sg_out); dst = kmap_local_page(sg_page(sg)); - r = crypt_iv_tcw_whitening(cc, dmreq, dst + sg->offset); + crypt_iv_tcw_whitening(cc, dmreq, dst + sg->offset); kunmap_local(dst); - return r; + return 0; } static int crypt_iv_random_gen(struct crypt_config *cc, u8 *iv,
diff --git a/drivers/md/dm-delay.c b/drivers/md/dm-delay.c index 08f6387..d4cf0ac 100644 --- a/drivers/md/dm-delay.c +++ b/drivers/md/dm-delay.c
@@ -369,6 +369,21 @@ static int delay_map(struct dm_target *ti, struct bio *bio) return delay_bio(dc, c, bio); } +#ifdef CONFIG_BLK_DEV_ZONED +static int delay_report_zones(struct dm_target *ti, + struct dm_report_zones_args *args, unsigned int nr_zones) +{ + struct delay_c *dc = ti->private; + struct delay_class *c = &dc->read; + + return dm_report_zones(c->dev->bdev, c->start, + c->start + dm_target_offset(ti, args->next_sector), + args, nr_zones); +} +#else +#define delay_report_zones NULL +#endif + #define DMEMIT_DELAY_CLASS(c) \ DMEMIT("%s %llu %u", (c)->dev->name, (unsigned long long)(c)->start, (c)->delay) @@ -424,11 +439,12 @@ static int delay_iterate_devices(struct dm_target *ti, static struct target_type delay_target = { .name = "delay", .version = {1, 4, 0}, - .features = DM_TARGET_PASSES_INTEGRITY, + .features = DM_TARGET_PASSES_INTEGRITY | DM_TARGET_ZONED_HM, .module = THIS_MODULE, .ctr = delay_ctr, .dtr = delay_dtr, .map = delay_map, + .report_zones = delay_report_zones, .presuspend = delay_presuspend, .resume = delay_resume, .status = delay_status,
diff --git a/drivers/md/dm-ebs-target.c b/drivers/md/dm-ebs-target.c index 18ae45d..b19b014 100644 --- a/drivers/md/dm-ebs-target.c +++ b/drivers/md/dm-ebs-target.c
@@ -390,6 +390,12 @@ static int ebs_map(struct dm_target *ti, struct bio *bio) return DM_MAPIO_REMAPPED; } +static void ebs_postsuspend(struct dm_target *ti) +{ + struct ebs_c *ec = ti->private; + dm_bufio_client_reset(ec->bufio); +} + static void ebs_status(struct dm_target *ti, status_type_t type, unsigned int status_flags, char *result, unsigned int maxlen) { @@ -447,6 +453,7 @@ static struct target_type ebs_target = { .ctr = ebs_ctr, .dtr = ebs_dtr, .map = ebs_map, + .postsuspend = ebs_postsuspend, .status = ebs_status, .io_hints = ebs_io_hints, .prepare_ioctl = ebs_prepare_ioctl,
diff --git a/drivers/md/dm-integrity.c b/drivers/md/dm-integrity.c index c8c1a00..2a283fe 100644 --- a/drivers/md/dm-integrity.c +++ b/drivers/md/dm-integrity.c
@@ -21,6 +21,7 @@ #include <linux/reboot.h> #include <crypto/hash.h> #include <crypto/skcipher.h> +#include <crypto/utils.h> #include <linux/async_tx.h> #include <linux/dm-bufio.h> @@ -516,7 +517,7 @@ static int sb_mac(struct dm_integrity_c *ic, bool wr) dm_integrity_io_error(ic, "crypto_shash_digest", r); return r; } - if (memcmp(mac, actual_mac, mac_size)) { + if (crypto_memneq(mac, actual_mac, mac_size)) { dm_integrity_io_error(ic, "superblock mac", -EILSEQ); dm_audit_log_target(DM_MSG_PREFIX, "mac-superblock", ic->ti, 0); return -EILSEQ; @@ -859,7 +860,7 @@ static void rw_section_mac(struct dm_integrity_c *ic, unsigned int section, bool if (likely(wr)) memcpy(&js->mac, result + (j * JOURNAL_MAC_PER_SECTOR), JOURNAL_MAC_PER_SECTOR); else { - if (memcmp(&js->mac, result + (j * JOURNAL_MAC_PER_SECTOR), JOURNAL_MAC_PER_SECTOR)) { + if (crypto_memneq(&js->mac, result + (j * JOURNAL_MAC_PER_SECTOR), JOURNAL_MAC_PER_SECTOR)) { dm_integrity_io_error(ic, "journal mac", -EILSEQ); dm_audit_log_target(DM_MSG_PREFIX, "mac-journal", ic->ti, 0); } @@ -1401,10 +1402,9 @@ static bool find_newer_committed_node(struct dm_integrity_c *ic, struct journal_ static int dm_integrity_rw_tag(struct dm_integrity_c *ic, unsigned char *tag, sector_t *metadata_block, unsigned int *metadata_offset, unsigned int total_size, int op) { -#define MAY_BE_FILLER 1 -#define MAY_BE_HASH 2 unsigned int hash_offset = 0; - unsigned int may_be = MAY_BE_HASH | (ic->discard ? MAY_BE_FILLER : 0); + unsigned char mismatch_hash = 0; + unsigned char mismatch_filler = !ic->discard; do { unsigned char *data, *dp; @@ -1425,7 +1425,7 @@ static int dm_integrity_rw_tag(struct dm_integrity_c *ic, unsigned char *tag, se if (op == TAG_READ) { memcpy(tag, dp, to_copy); } else if (op == TAG_WRITE) { - if (memcmp(dp, tag, to_copy)) { + if (crypto_memneq(dp, tag, to_copy)) { memcpy(dp, tag, to_copy); dm_bufio_mark_partial_buffer_dirty(b, *metadata_offset, *metadata_offset + to_copy); } @@ -1433,29 +1433,30 @@ static int dm_integrity_rw_tag(struct dm_integrity_c *ic, unsigned char *tag, se /* e.g.: op == TAG_CMP */ if (likely(is_power_of_2(ic->tag_size))) { - if (unlikely(memcmp(dp, tag, to_copy))) - if (unlikely(!ic->discard) || - unlikely(memchr_inv(dp, DISCARD_FILLER, to_copy) != NULL)) { - goto thorough_test; - } + if (unlikely(crypto_memneq(dp, tag, to_copy))) + goto thorough_test; } else { unsigned int i, ts; thorough_test: ts = total_size; for (i = 0; i < to_copy; i++, ts--) { - if (unlikely(dp[i] != tag[i])) - may_be &= ~MAY_BE_HASH; - if (likely(dp[i] != DISCARD_FILLER)) - may_be &= ~MAY_BE_FILLER; + /* + * Warning: the control flow must not be + * dependent on match/mismatch of + * individual bytes. + */ + mismatch_hash |= dp[i] ^ tag[i]; + mismatch_filler |= dp[i] ^ DISCARD_FILLER; hash_offset++; if (unlikely(hash_offset == ic->tag_size)) { - if (unlikely(!may_be)) { + if (unlikely(mismatch_hash) && unlikely(mismatch_filler)) { dm_bufio_release(b); return ts; } hash_offset = 0; - may_be = MAY_BE_HASH | (ic->discard ? MAY_BE_FILLER : 0); + mismatch_hash = 0; + mismatch_filler = !ic->discard; } } } @@ -1476,8 +1477,6 @@ static int dm_integrity_rw_tag(struct dm_integrity_c *ic, unsigned char *tag, se } while (unlikely(total_size)); return 0; -#undef MAY_BE_FILLER -#undef MAY_BE_HASH } struct flush_request { @@ -2076,7 +2075,7 @@ static bool __journal_read_write(struct dm_integrity_io *dio, struct bio *bio, char checksums_onstack[MAX_T(size_t, HASH_MAX_DIGESTSIZE, MAX_TAG_SIZE)]; integrity_sector_checksum(ic, logical_sector, mem + bv.bv_offset, checksums_onstack); - if (unlikely(memcmp(checksums_onstack, journal_entry_tag(ic, je), ic->tag_size))) { + if (unlikely(crypto_memneq(checksums_onstack, journal_entry_tag(ic, je), ic->tag_size))) { DMERR_LIMIT("Checksum failed when reading from journal, at sector 0x%llx", logical_sector); dm_audit_log_bio(DM_MSG_PREFIX, "journal-checksum", @@ -2595,7 +2594,7 @@ static void dm_integrity_inline_recheck(struct work_struct *w) bio_put(outgoing_bio); integrity_sector_checksum(ic, dio->bio_details.bi_iter.bi_sector, outgoing_data, digest); - if (unlikely(memcmp(digest, dio->integrity_payload, min(crypto_shash_digestsize(ic->internal_hash), ic->tag_size)))) { + if (unlikely(crypto_memneq(digest, dio->integrity_payload, min(crypto_shash_digestsize(ic->internal_hash), ic->tag_size)))) { DMERR_LIMIT("%pg: Checksum failed at sector 0x%llx", ic->dev->bdev, dio->bio_details.bi_iter.bi_sector); atomic64_inc(&ic->number_of_mismatches); @@ -2634,7 +2633,7 @@ static int dm_integrity_end_io(struct dm_target *ti, struct bio *bio, blk_status char *mem = bvec_kmap_local(&bv); //memset(mem, 0xff, ic->sectors_per_block << SECTOR_SHIFT); integrity_sector_checksum(ic, dio->bio_details.bi_iter.bi_sector, mem, digest); - if (unlikely(memcmp(digest, dio->integrity_payload + pos, + if (unlikely(crypto_memneq(digest, dio->integrity_payload + pos, min(crypto_shash_digestsize(ic->internal_hash), ic->tag_size)))) { kunmap_local(mem); dm_integrity_free_payload(dio); @@ -2708,7 +2707,7 @@ static void integrity_commit(struct work_struct *w) unsigned int i, j, n; struct bio *flushes; - del_timer(&ic->autocommit_timer); + timer_delete(&ic->autocommit_timer); if (ic->mode == 'I') return; @@ -2911,7 +2910,7 @@ static void do_journal_write(struct dm_integrity_c *ic, unsigned int write_start integrity_sector_checksum(ic, sec + ((l - j) << ic->sb->log2_sectors_per_block), (char *)access_journal_data(ic, i, l), test_tag); - if (unlikely(memcmp(test_tag, journal_entry_tag(ic, je2), ic->tag_size))) { + if (unlikely(crypto_memneq(test_tag, journal_entry_tag(ic, je2), ic->tag_size))) { dm_integrity_io_error(ic, "tag mismatch when replaying journal", -EILSEQ); dm_audit_log_target(DM_MSG_PREFIX, "integrity-replay-journal", ic->ti, 0); } @@ -3607,7 +3606,7 @@ static void dm_integrity_postsuspend(struct dm_target *ti) WARN_ON(unregister_reboot_notifier(&ic->reboot_notifier)); - del_timer_sync(&ic->autocommit_timer); + timer_delete_sync(&ic->autocommit_timer); if (ic->recalc_wq) drain_workqueue(ic->recalc_wq); @@ -5072,16 +5071,19 @@ static int dm_integrity_ctr(struct dm_target *ti, unsigned int argc, char **argv ic->recalc_bitmap = dm_integrity_alloc_page_list(n_bitmap_pages); if (!ic->recalc_bitmap) { + ti->error = "Could not allocate memory for bitmap"; r = -ENOMEM; goto bad; } ic->may_write_bitmap = dm_integrity_alloc_page_list(n_bitmap_pages); if (!ic->may_write_bitmap) { + ti->error = "Could not allocate memory for bitmap"; r = -ENOMEM; goto bad; } ic->bbs = kvmalloc_array(ic->n_bitmap_blocks, sizeof(struct bitmap_block_status), GFP_KERNEL); if (!ic->bbs) { + ti->error = "Could not allocate memory for bitmap"; r = -ENOMEM; goto bad; }
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c index 637977a..6c98f4a 100644 --- a/drivers/md/dm-mpath.c +++ b/drivers/md/dm-mpath.c
@@ -815,7 +815,7 @@ static void enable_nopath_timeout(struct multipath *m) static void disable_nopath_timeout(struct multipath *m) { - del_timer_sync(&m->nopath_timer); + timer_delete_sync(&m->nopath_timer); } /*
diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c index 8c6f1f7..9e615b4 100644 --- a/drivers/md/dm-raid1.c +++ b/drivers/md/dm-raid1.c
@@ -1182,7 +1182,7 @@ static void mirror_dtr(struct dm_target *ti) { struct mirror_set *ms = ti->private; - del_timer_sync(&ms->timer); + timer_delete_sync(&ms->timer); flush_workqueue(ms->kmirrord_wq); flush_work(&ms->trigger_event); dm_kcopyd_client_destroy(ms->kcopyd_client);
diff --git a/drivers/md/dm-stripe.c b/drivers/md/dm-stripe.c index 3786ac6..a1b7535 100644 --- a/drivers/md/dm-stripe.c +++ b/drivers/md/dm-stripe.c
@@ -467,7 +467,7 @@ static struct target_type stripe_target = { .name = "striped", .version = {1, 7, 0}, .features = DM_TARGET_PASSES_INTEGRITY | DM_TARGET_NOWAIT | - DM_TARGET_ATOMIC_WRITES, + DM_TARGET_ATOMIC_WRITES | DM_TARGET_PASSES_CRYPTO, .module = THIS_MODULE, .ctr = stripe_ctr, .dtr = stripe_dtr,
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index 453803f..35100a4 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c
@@ -697,6 +697,10 @@ int dm_table_add_target(struct dm_table *t, const char *type, DMERR("%s: zero-length target", dm_device_name(t->md)); return -EINVAL; } + if (start + len < start || start + len > LLONG_MAX >> SECTOR_SHIFT) { + DMERR("%s: too large device", dm_device_name(t->md)); + return -EINVAL; + } ti->type = dm_get_target_type(type); if (!ti->type) {
diff --git a/drivers/md/dm-vdo/block-map.c b/drivers/md/dm-vdo/block-map.c index 89cb794..baf683c 100644 --- a/drivers/md/dm-vdo/block-map.c +++ b/drivers/md/dm-vdo/block-map.c
@@ -451,7 +451,7 @@ static struct page_info * __must_check find_page(struct vdo_page_cache *cache, * select_lru_page() - Determine which page is least recently used. * * Picks the least recently used from among the non-busy entries at the front of each of the lru - * ring. Since whenever we mark a page busy we also put it to the end of the ring it is unlikely + * list. Since whenever we mark a page busy we also put it to the end of the list it is unlikely * that the entries at the front are busy unless the queue is very short, but not impossible. * * Return: A pointer to the info structure for a relevant page, or NULL if no such page can be @@ -1544,7 +1544,7 @@ static void write_page_if_not_dirtied(struct vdo_waiter *waiter, void *context) static void return_to_pool(struct block_map_zone *zone, struct pooled_vio *vio) { - return_vio_to_pool(zone->vio_pool, vio); + return_vio_to_pool(vio); check_for_drain_complete(zone); } @@ -1837,7 +1837,7 @@ static void finish_block_map_page_load(struct vdo_completion *completion) if (!vdo_copy_valid_page(vio->data, nonce, pbn, page)) vdo_format_block_map_page(page, nonce, pbn, false); - return_vio_to_pool(zone->vio_pool, pooled); + return_vio_to_pool(pooled); /* Release our claim to the load and wake any waiters */ release_page_lock(data_vio, "load"); @@ -1851,10 +1851,9 @@ static void handle_io_error(struct vdo_completion *completion) struct vio *vio = as_vio(completion); struct pooled_vio *pooled = container_of(vio, struct pooled_vio, vio); struct data_vio *data_vio = completion->parent; - struct block_map_zone *zone = pooled->context; vio_record_metadata_io_error(vio); - return_vio_to_pool(zone->vio_pool, pooled); + return_vio_to_pool(pooled); abort_load(data_vio, result); } @@ -2499,7 +2498,7 @@ static void finish_cursor(struct cursor *cursor) struct cursors *cursors = cursor->parent; struct vdo_completion *completion = cursors->completion; - return_vio_to_pool(cursors->pool, vdo_forget(cursor->vio)); + return_vio_to_pool(vdo_forget(cursor->vio)); if (--cursors->active_roots > 0) return; @@ -2746,7 +2745,7 @@ static int __must_check initialize_block_map_zone(struct block_map *map, if (result != VDO_SUCCESS) return result; - result = make_vio_pool(vdo, BLOCK_MAP_VIO_POOL_SIZE, + result = make_vio_pool(vdo, BLOCK_MAP_VIO_POOL_SIZE, 1, zone->thread_id, VIO_TYPE_BLOCK_MAP_INTERIOR, VIO_PRIORITY_METADATA, zone, &zone->vio_pool); if (result != VDO_SUCCESS)
diff --git a/drivers/md/dm-vdo/constants.h b/drivers/md/dm-vdo/constants.h index a8c4d6e..2a8b037 100644 --- a/drivers/md/dm-vdo/constants.h +++ b/drivers/md/dm-vdo/constants.h
@@ -44,9 +44,6 @@ enum { /* The default size of each slab journal, in blocks */ DEFAULT_VDO_SLAB_JOURNAL_SIZE = 224, - /* Unit test minimum */ - MINIMUM_VDO_SLAB_JOURNAL_BLOCKS = 2, - /* * The initial size of lbn_operations and pbn_operations, which is based upon the expected * maximum number of outstanding VIOs. This value was chosen to make it highly unlikely
diff --git a/drivers/md/dm-vdo/dedupe.c b/drivers/md/dm-vdo/dedupe.c index 3f3d29a..3c58b94 100644 --- a/drivers/md/dm-vdo/dedupe.c +++ b/drivers/md/dm-vdo/dedupe.c
@@ -226,7 +226,7 @@ struct hash_lock { * A list containing the data VIOs sharing this lock, all having the same record name and * data block contents, linked by their hash_lock_node fields. */ - struct list_head duplicate_ring; + struct list_head duplicate_vios; /* The number of data_vios sharing this lock instance */ data_vio_count_t reference_count; @@ -343,7 +343,7 @@ static void return_hash_lock_to_pool(struct hash_zone *zone, struct hash_lock *l { memset(lock, 0, sizeof(*lock)); INIT_LIST_HEAD(&lock->pool_node); - INIT_LIST_HEAD(&lock->duplicate_ring); + INIT_LIST_HEAD(&lock->duplicate_vios); vdo_waitq_init(&lock->waiters); list_add_tail(&lock->pool_node, &zone->lock_pool); } @@ -441,7 +441,7 @@ static void set_hash_lock(struct data_vio *data_vio, struct hash_lock *new_lock) VDO_ASSERT_LOG_ONLY(data_vio->hash_zone != NULL, "must have a hash zone when holding a hash lock"); VDO_ASSERT_LOG_ONLY(!list_empty(&data_vio->hash_lock_entry), - "must be on a hash lock ring when holding a hash lock"); + "must be on a hash lock list when holding a hash lock"); VDO_ASSERT_LOG_ONLY(old_lock->reference_count > 0, "hash lock reference must be counted"); @@ -464,10 +464,10 @@ static void set_hash_lock(struct data_vio *data_vio, struct hash_lock *new_lock) if (new_lock != NULL) { /* - * Keep all data_vios sharing the lock on a ring since they can complete in any + * Keep all data_vios sharing the lock on a list since they can complete in any * order and we'll always need a pointer to one to compare data. */ - list_move_tail(&data_vio->hash_lock_entry, &new_lock->duplicate_ring); + list_move_tail(&data_vio->hash_lock_entry, &new_lock->duplicate_vios); new_lock->reference_count += 1; if (new_lock->max_references < new_lock->reference_count) new_lock->max_references = new_lock->reference_count; @@ -1789,10 +1789,10 @@ static bool is_hash_collision(struct hash_lock *lock, struct data_vio *candidate struct hash_zone *zone; bool collides; - if (list_empty(&lock->duplicate_ring)) + if (list_empty(&lock->duplicate_vios)) return false; - lock_holder = list_first_entry(&lock->duplicate_ring, struct data_vio, + lock_holder = list_first_entry(&lock->duplicate_vios, struct data_vio, hash_lock_entry); zone = candidate->hash_zone; collides = !blocks_equal(lock_holder->vio.data, candidate->vio.data); @@ -1815,7 +1815,7 @@ static inline int assert_hash_lock_preconditions(const struct data_vio *data_vio return result; result = VDO_ASSERT(list_empty(&data_vio->hash_lock_entry), - "must not already be a member of a hash lock ring"); + "must not already be a member of a hash lock list"); if (result != VDO_SUCCESS) return result; @@ -1942,8 +1942,8 @@ void vdo_release_hash_lock(struct data_vio *data_vio) "returned hash lock must not be in use with state %s", get_hash_lock_state_name(lock->state)); VDO_ASSERT_LOG_ONLY(list_empty(&lock->pool_node), - "hash lock returned to zone must not be in a pool ring"); - VDO_ASSERT_LOG_ONLY(list_empty(&lock->duplicate_ring), + "hash lock returned to zone must not be in a pool list"); + VDO_ASSERT_LOG_ONLY(list_empty(&lock->duplicate_vios), "hash lock returned to zone must not reference DataVIOs"); return_hash_lock_to_pool(zone, lock); @@ -2261,7 +2261,7 @@ static void check_for_drain_complete(struct hash_zone *zone) if ((atomic_read(&zone->timer_state) == DEDUPE_QUERY_TIMER_IDLE) || change_timer_state(zone, DEDUPE_QUERY_TIMER_RUNNING, DEDUPE_QUERY_TIMER_IDLE)) { - del_timer_sync(&zone->timer); + timer_delete_sync(&zone->timer); } else { /* * There is an in flight time-out, which must get processed before we can continue.
diff --git a/drivers/md/dm-vdo/encodings.c b/drivers/md/dm-vdo/encodings.c index 100e92f..b7cc0f4 100644 --- a/drivers/md/dm-vdo/encodings.c +++ b/drivers/md/dm-vdo/encodings.c
@@ -711,24 +711,11 @@ int vdo_configure_slab(block_count_t slab_size, block_count_t slab_journal_block ref_blocks = vdo_get_saved_reference_count_size(slab_size - slab_journal_blocks); meta_blocks = (ref_blocks + slab_journal_blocks); - /* Make sure test code hasn't configured slabs to be too small. */ + /* Make sure configured slabs are not too small. */ if (meta_blocks >= slab_size) return VDO_BAD_CONFIGURATION; - /* - * If the slab size is very small, assume this must be a unit test and override the number - * of data blocks to be a power of two (wasting blocks in the slab). Many tests need their - * data_blocks fields to be the exact capacity of the configured volume, and that used to - * fall out since they use a power of two for the number of data blocks, the slab size was - * a power of two, and every block in a slab was a data block. - * - * TODO: Try to figure out some way of structuring testParameters and unit tests so this - * hack isn't needed without having to edit several unit tests every time the metadata size - * changes by one block. - */ data_blocks = slab_size - meta_blocks; - if ((slab_size < 1024) && !is_power_of_2(data_blocks)) - data_blocks = ((block_count_t) 1 << ilog2(data_blocks)); /* * Configure the slab journal thresholds. The flush threshold is 168 of 224 blocks in @@ -1221,11 +1208,6 @@ int vdo_validate_config(const struct vdo_config *config, if (result != VDO_SUCCESS) return result; - result = VDO_ASSERT(config->slab_journal_blocks >= MINIMUM_VDO_SLAB_JOURNAL_BLOCKS, - "slab journal size meets minimum size"); - if (result != VDO_SUCCESS) - return result; - result = VDO_ASSERT(config->slab_journal_blocks <= config->slab_size, "slab journal size is within expected bound"); if (result != VDO_SUCCESS)
diff --git a/drivers/md/dm-vdo/indexer/index-layout.c b/drivers/md/dm-vdo/indexer/index-layout.c index af8fab8..61edf2b 100644 --- a/drivers/md/dm-vdo/indexer/index-layout.c +++ b/drivers/md/dm-vdo/indexer/index-layout.c
@@ -54,7 +54,6 @@ * Each save also has a unique nonce. */ -#define MAGIC_SIZE 32 #define NONCE_INFO_SIZE 32 #define MAX_SAVES 2 @@ -98,9 +97,11 @@ enum region_type { #define SUPER_VERSION_CURRENT 3 #define SUPER_VERSION_MAXIMUM 7 -static const u8 LAYOUT_MAGIC[MAGIC_SIZE] = "*ALBIREO*SINGLE*FILE*LAYOUT*001*"; +static const u8 LAYOUT_MAGIC[] = "*ALBIREO*SINGLE*FILE*LAYOUT*001*"; static const u64 REGION_MAGIC = 0x416c6252676e3031; /* 'AlbRgn01' */ +#define MAGIC_SIZE (sizeof(LAYOUT_MAGIC) - 1) + struct region_header { u64 magic; u64 region_blocks;
diff --git a/drivers/md/dm-vdo/indexer/index-session.c b/drivers/md/dm-vdo/indexer/index-session.c index aee0914..aa575a2 100644 --- a/drivers/md/dm-vdo/indexer/index-session.c +++ b/drivers/md/dm-vdo/indexer/index-session.c
@@ -100,7 +100,6 @@ static int get_index_session(struct uds_index_session *index_session) int uds_launch_request(struct uds_request *request) { - size_t internal_size; int result; if (request->callback == NULL) { @@ -121,10 +120,7 @@ int uds_launch_request(struct uds_request *request) } /* Reset all internal fields before processing. */ - internal_size = - sizeof(struct uds_request) - offsetof(struct uds_request, zone_number); - // FIXME should be using struct_group for this instead - memset((char *) request + sizeof(*request) - internal_size, 0, internal_size); + memset(&request->internal, 0, sizeof(request->internal)); result = get_index_session(request->session); if (result != UDS_SUCCESS)
diff --git a/drivers/md/dm-vdo/indexer/indexer.h b/drivers/md/dm-vdo/indexer/indexer.h index 183a94eb..7c1fc45 100644 --- a/drivers/md/dm-vdo/indexer/indexer.h +++ b/drivers/md/dm-vdo/indexer/indexer.h
@@ -8,6 +8,7 @@ #include <linux/mutex.h> #include <linux/sched.h> +#include <linux/stddef.h> #include <linux/types.h> #include <linux/wait.h> @@ -73,7 +74,7 @@ enum uds_request_type { /* Remove any mapping for a name. */ UDS_DELETE, -}; +} __packed; enum uds_open_index_type { /* Create a new index. */ @@ -226,7 +227,7 @@ struct uds_zone_message { enum uds_zone_message_type type; /* The virtual chapter number to which the message applies */ u64 virtual_chapter; -}; +} __packed; struct uds_index_session; struct uds_index; @@ -253,34 +254,32 @@ struct uds_request { /* The existing data associated with the request name, if any */ struct uds_record_data old_metadata; - /* Either UDS_SUCCESS or an error code for the request */ - int status; /* True if the record name had an existing entry in the index */ bool found; + /* Either UDS_SUCCESS or an error code for the request */ + int status; - /* - * The remaining fields are used internally and should not be altered by clients. The index - * relies on zone_number being the first field in this section. - */ - - /* The number of the zone which will process this request*/ - unsigned int zone_number; - /* A link for adding a request to a lock-free queue */ - struct funnel_queue_entry queue_link; - /* A link for adding a request to a standard linked list */ - struct uds_request *next_request; - /* A pointer to the index processing this request */ - struct uds_index *index; - /* Control message for coordinating between zones */ - struct uds_zone_message zone_message; - /* If true, process request immediately by waking the worker thread */ - bool unbatched; - /* If true, continue this request before processing newer requests */ - bool requeued; - /* The virtual chapter containing the record name, if known */ - u64 virtual_chapter; - /* The region of the index containing the record name */ - enum uds_index_region location; + /* The remaining fields are used internally and should not be altered by clients. */ + struct_group(internal, + /* The virtual chapter containing the record name, if known */ + u64 virtual_chapter; + /* The region of the index containing the record name */ + enum uds_index_region location; + /* If true, process request immediately by waking the worker thread */ + bool unbatched; + /* If true, continue this request before processing newer requests */ + bool requeued; + /* Control message for coordinating between zones */ + struct uds_zone_message zone_message; + /* The number of the zone which will process this request*/ + unsigned int zone_number; + /* A link for adding a request to a lock-free queue */ + struct funnel_queue_entry queue_link; + /* A link for adding a request to a standard linked list */ + struct uds_request *next_request; + /* A pointer to the index processing this request */ + struct uds_index *index; + ); }; /* A session is required for most index operations. */
diff --git a/drivers/md/dm-vdo/io-submitter.c b/drivers/md/dm-vdo/io-submitter.c index 421e543..11d4777 100644 --- a/drivers/md/dm-vdo/io-submitter.c +++ b/drivers/md/dm-vdo/io-submitter.c
@@ -327,6 +327,7 @@ void vdo_submit_data_vio(struct data_vio *data_vio) * @error_handler: the handler for submission or I/O errors (may be NULL) * @operation: the type of I/O to perform * @data: the buffer to read or write (may be NULL) + * @size: the I/O amount in bytes * * The vio is enqueued on a vdo bio queue so that bio submission (which may block) does not block * other vdo threads. @@ -338,7 +339,7 @@ void vdo_submit_data_vio(struct data_vio *data_vio) */ void __submit_metadata_vio(struct vio *vio, physical_block_number_t physical, bio_end_io_t callback, vdo_action_fn error_handler, - blk_opf_t operation, char *data) + blk_opf_t operation, char *data, int size) { int result; struct vdo_completion *completion = &vio->completion; @@ -349,7 +350,8 @@ void __submit_metadata_vio(struct vio *vio, physical_block_number_t physical, vdo_reset_completion(completion); completion->error_handler = error_handler; - result = vio_reset_bio(vio, data, callback, operation | REQ_META, physical); + result = vio_reset_bio_with_size(vio, data, size, callback, operation | REQ_META, + physical); if (result != VDO_SUCCESS) { continue_vio(vio, result); return;
diff --git a/drivers/md/dm-vdo/io-submitter.h b/drivers/md/dm-vdo/io-submitter.h index 8074869..3088f11 100644 --- a/drivers/md/dm-vdo/io-submitter.h +++ b/drivers/md/dm-vdo/io-submitter.h
@@ -8,6 +8,7 @@ #include <linux/bio.h> +#include "constants.h" #include "types.h" struct io_submitter; @@ -26,14 +27,25 @@ void vdo_submit_data_vio(struct data_vio *data_vio); void __submit_metadata_vio(struct vio *vio, physical_block_number_t physical, bio_end_io_t callback, vdo_action_fn error_handler, - blk_opf_t operation, char *data); + blk_opf_t operation, char *data, int size); static inline void vdo_submit_metadata_vio(struct vio *vio, physical_block_number_t physical, bio_end_io_t callback, vdo_action_fn error_handler, blk_opf_t operation) { __submit_metadata_vio(vio, physical, callback, error_handler, - operation, vio->data); + operation, vio->data, vio->block_count * VDO_BLOCK_SIZE); +} + +static inline void vdo_submit_metadata_vio_with_size(struct vio *vio, + physical_block_number_t physical, + bio_end_io_t callback, + vdo_action_fn error_handler, + blk_opf_t operation, + int size) +{ + __submit_metadata_vio(vio, physical, callback, error_handler, + operation, vio->data, size); } static inline void vdo_submit_flush_vio(struct vio *vio, bio_end_io_t callback, @@ -41,7 +53,7 @@ static inline void vdo_submit_flush_vio(struct vio *vio, bio_end_io_t callback, { /* FIXME: Can we just use REQ_OP_FLUSH? */ __submit_metadata_vio(vio, 0, callback, error_handler, - REQ_OP_WRITE | REQ_PREFLUSH, NULL); + REQ_OP_WRITE | REQ_PREFLUSH, NULL, 0); } #endif /* VDO_IO_SUBMITTER_H */
diff --git a/drivers/md/dm-vdo/packer.h b/drivers/md/dm-vdo/packer.h index 0f3be44..8c8d689 100644 --- a/drivers/md/dm-vdo/packer.h +++ b/drivers/md/dm-vdo/packer.h
@@ -46,7 +46,7 @@ struct compressed_block { /* * Each packer_bin holds an incomplete batch of data_vios that only partially fill a compressed - * block. The bins are kept in a ring sorted by the amount of unused space so the first bin with + * block. The bins are kept in a list sorted by the amount of unused space so the first bin with * enough space to hold a newly-compressed data_vio can easily be found. When the bin fills up or * is flushed, the first uncanceled data_vio in the bin is selected to be the agent for that bin. * Upon entering the packer, each data_vio already has its compressed data in the first slot of the
diff --git a/drivers/md/dm-vdo/priority-table.c b/drivers/md/dm-vdo/priority-table.c index 42d3d8d0..9bae825 100644 --- a/drivers/md/dm-vdo/priority-table.c +++ b/drivers/md/dm-vdo/priority-table.c
@@ -199,7 +199,7 @@ void vdo_priority_table_remove(struct priority_table *table, struct list_head *e /* * Remove the entry from the bucket list, remembering a pointer to another entry in the - * ring. + * list. */ next_entry = entry->next; list_del_init(entry);
diff --git a/drivers/md/dm-vdo/recovery-journal.h b/drivers/md/dm-vdo/recovery-journal.h index 8990711..25e7ec6 100644 --- a/drivers/md/dm-vdo/recovery-journal.h +++ b/drivers/md/dm-vdo/recovery-journal.h
@@ -43,9 +43,9 @@ * has a vio which is used to commit that block to disk. The vio's data is the on-disk * representation of the journal block. In addition each in-memory block has a buffer which is used * to accumulate entries while a partial commit of the block is in progress. In-memory blocks are - * kept on two rings. Free blocks live on the 'free_tail_blocks' ring. When a block becomes active - * (see below) it is moved to the 'active_tail_blocks' ring. When a block is fully committed, it is - * moved back to the 'free_tail_blocks' ring. + * kept on two lists. Free blocks live on the 'free_tail_blocks' list. When a block becomes active + * (see below) it is moved to the 'active_tail_blocks' list. When a block is fully committed, it is + * moved back to the 'free_tail_blocks' list. * * When entries are added to the journal, they are added to the active in-memory block, as * indicated by the 'active_block' field. If the caller wishes to wait for the entry to be
diff --git a/drivers/md/dm-vdo/slab-depot.c b/drivers/md/dm-vdo/slab-depot.c index 8f0a35c..f3d80ff 100644 --- a/drivers/md/dm-vdo/slab-depot.c +++ b/drivers/md/dm-vdo/slab-depot.c
@@ -139,7 +139,7 @@ static bool is_slab_journal_blank(const struct vdo_slab *slab) } /** - * mark_slab_journal_dirty() - Put a slab journal on the dirty ring of its allocator in the correct + * mark_slab_journal_dirty() - Put a slab journal on the dirty list of its allocator in the correct * order. * @journal: The journal to be marked dirty. * @lock: The recovery journal lock held by the slab journal. @@ -414,8 +414,7 @@ static void complete_reaping(struct vdo_completion *completion) { struct slab_journal *journal = completion->parent; - return_vio_to_pool(journal->slab->allocator->vio_pool, - vio_as_pooled_vio(as_vio(vdo_forget(completion)))); + return_vio_to_pool(vio_as_pooled_vio(as_vio(completion))); finish_reaping(journal); reap_slab_journal(journal); } @@ -698,7 +697,7 @@ static void complete_write(struct vdo_completion *completion) sequence_number_t committed = get_committing_sequence_number(pooled); list_del_init(&pooled->list_entry); - return_vio_to_pool(journal->slab->allocator->vio_pool, vdo_forget(pooled)); + return_vio_to_pool(pooled); if (result != VDO_SUCCESS) { vio_record_metadata_io_error(as_vio(completion)); @@ -822,7 +821,7 @@ static void commit_tail(struct slab_journal *journal) /* * Since we are about to commit the tail block, this journal no longer needs to be on the - * ring of journals which the recovery journal might ask to commit. + * list of journals which the recovery journal might ask to commit. */ mark_slab_journal_clean(journal); @@ -1076,7 +1075,7 @@ static void finish_reference_block_write(struct vdo_completion *completion) /* Release the slab journal lock. */ adjust_slab_journal_block_reference(&slab->journal, block->slab_journal_lock_to_release, -1); - return_vio_to_pool(slab->allocator->vio_pool, pooled); + return_vio_to_pool(pooled); /* * We can't clear the is_writing flag earlier as releasing the slab journal lock may cause @@ -1170,8 +1169,8 @@ static void handle_io_error(struct vdo_completion *completion) struct vdo_slab *slab = ((struct reference_block *) completion->parent)->slab; vio_record_metadata_io_error(vio); - return_vio_to_pool(slab->allocator->vio_pool, vio_as_pooled_vio(vio)); - slab->active_count--; + return_vio_to_pool(vio_as_pooled_vio(vio)); + slab->active_count -= vio->io_size / VDO_BLOCK_SIZE; vdo_enter_read_only_mode(slab->allocator->depot->vdo, result); check_if_slab_drained(slab); } @@ -1372,7 +1371,7 @@ static unsigned int calculate_slab_priority(struct vdo_slab *slab) static void prioritize_slab(struct vdo_slab *slab) { VDO_ASSERT_LOG_ONLY(list_empty(&slab->allocq_entry), - "a slab must not already be on a ring when prioritizing"); + "a slab must not already be on a list when prioritizing"); slab->priority = calculate_slab_priority(slab); vdo_priority_table_enqueue(slab->allocator->prioritized_slabs, slab->priority, &slab->allocq_entry); @@ -2165,23 +2164,6 @@ static void dirty_all_reference_blocks(struct vdo_slab *slab) dirty_block(&slab->reference_blocks[i]); } -/** - * clear_provisional_references() - Clear the provisional reference counts from a reference block. - * @block: The block to clear. - */ -static void clear_provisional_references(struct reference_block *block) -{ - vdo_refcount_t *counters = get_reference_counters_for_block(block); - block_count_t j; - - for (j = 0; j < COUNTS_PER_BLOCK; j++) { - if (counters[j] == PROVISIONAL_REFERENCE_COUNT) { - counters[j] = EMPTY_REFERENCE_COUNT; - block->allocated_count--; - } - } -} - static inline bool journal_points_equal(struct journal_point first, struct journal_point second) { @@ -2190,6 +2172,90 @@ static inline bool journal_points_equal(struct journal_point first, } /** + * match_bytes() - Check an 8-byte word for bytes matching the value specified + * @input: A word to examine the bytes of + * @match: The byte value sought + * + * Return: 1 in each byte when the corresponding input byte matched, 0 otherwise + */ +static inline u64 match_bytes(u64 input, u8 match) +{ + u64 temp = input ^ (match * 0x0101010101010101ULL); + /* top bit of each byte is set iff top bit of temp byte is clear; rest are 0 */ + u64 test_top_bits = ~temp & 0x8080808080808080ULL; + /* top bit of each byte is set iff low 7 bits of temp byte are clear; rest are useless */ + u64 test_low_bits = 0x8080808080808080ULL - (temp & 0x7f7f7f7f7f7f7f7fULL); + /* return 1 when both tests indicate temp byte is 0 */ + return (test_top_bits & test_low_bits) >> 7; +} + +/** + * count_valid_references() - Process a newly loaded refcount array + * @counters: the array of counters from a metadata block + * + * Scan a 8-byte-aligned array of counters, fixing up any "provisional" values that weren't + * cleaned up at shutdown, changing them internally to "empty". + * + * Return: the number of blocks that are referenced (counters not "empty") + */ +static unsigned int count_valid_references(vdo_refcount_t *counters) +{ + u64 *words = (u64 *)counters; + /* It's easier to count occurrences of a specific byte than its absences. */ + unsigned int empty_count = 0; + /* For speed, we process 8 bytes at once. */ + unsigned int words_left = COUNTS_PER_BLOCK / sizeof(u64); + + /* + * Sanity check assumptions used for optimizing this code: Counters are bytes. The counter + * array is a multiple of the word size. + */ + BUILD_BUG_ON(sizeof(vdo_refcount_t) != 1); + BUILD_BUG_ON((COUNTS_PER_BLOCK % sizeof(u64)) != 0); + + while (words_left > 0) { + /* + * This is used effectively as 8 byte-size counters. Byte 0 counts how many words + * had the target value found in byte 0, etc. We just have to avoid overflow. + */ + u64 split_count = 0; + /* + * The counter "% 255" trick used below to fold split_count into empty_count + * imposes a limit of 254 bytes examined each iteration of the outer loop. We + * process a word at a time, so that limit gets rounded down to 31 u64 words. + */ + const unsigned int max_words_per_iteration = 254 / sizeof(u64); + unsigned int iter_words_left = min_t(unsigned int, words_left, + max_words_per_iteration); + + words_left -= iter_words_left; + + while (iter_words_left--) { + u64 word = *words; + u64 temp; + + /* First, if we have any provisional refcount values, clear them. */ + temp = match_bytes(word, PROVISIONAL_REFERENCE_COUNT); + if (temp) { + /* + * 'temp' has 0x01 bytes where 'word' has PROVISIONAL; this xor + * will alter just those bytes, changing PROVISIONAL to EMPTY. + */ + word ^= temp * (PROVISIONAL_REFERENCE_COUNT ^ EMPTY_REFERENCE_COUNT); + *words = word; + } + + /* Now count the EMPTY_REFERENCE_COUNT bytes, updating the 8 counters. */ + split_count += match_bytes(word, EMPTY_REFERENCE_COUNT); + words++; + } + empty_count += split_count % 255; + } + + return COUNTS_PER_BLOCK - empty_count; +} + +/** * unpack_reference_block() - Unpack reference counts blocks into the internal memory structure. * @packed: The written reference block to be unpacked. * @block: The internal reference block to be loaded. @@ -2197,7 +2263,6 @@ static inline bool journal_points_equal(struct journal_point first, static void unpack_reference_block(struct packed_reference_block *packed, struct reference_block *block) { - block_count_t index; sector_count_t i; struct vdo_slab *slab = block->slab; vdo_refcount_t *counters = get_reference_counters_for_block(block); @@ -2223,11 +2288,7 @@ static void unpack_reference_block(struct packed_reference_block *packed, } } - block->allocated_count = 0; - for (index = 0; index < COUNTS_PER_BLOCK; index++) { - if (counters[index] != EMPTY_REFERENCE_COUNT) - block->allocated_count++; - } + block->allocated_count = count_valid_references(counters); } /** @@ -2240,13 +2301,19 @@ static void finish_reference_block_load(struct vdo_completion *completion) struct pooled_vio *pooled = vio_as_pooled_vio(vio); struct reference_block *block = completion->parent; struct vdo_slab *slab = block->slab; + unsigned int block_count = vio->io_size / VDO_BLOCK_SIZE; + unsigned int i; + char *data = vio->data; - unpack_reference_block((struct packed_reference_block *) vio->data, block); - return_vio_to_pool(slab->allocator->vio_pool, pooled); - slab->active_count--; - clear_provisional_references(block); + for (i = 0; i < block_count; i++, block++, data += VDO_BLOCK_SIZE) { + struct packed_reference_block *packed = (struct packed_reference_block *) data; - slab->free_blocks -= block->allocated_count; + unpack_reference_block(packed, block); + slab->free_blocks -= block->allocated_count; + } + return_vio_to_pool(pooled); + slab->active_count -= block_count; + check_if_slab_drained(slab); } @@ -2260,23 +2327,25 @@ static void load_reference_block_endio(struct bio *bio) } /** - * load_reference_block() - After a block waiter has gotten a VIO from the VIO pool, load the - * block. - * @waiter: The waiter of the block to load. + * load_reference_block_group() - After a block waiter has gotten a VIO from the VIO pool, load + * a set of blocks. + * @waiter: The waiter of the first block to load. * @context: The VIO returned by the pool. */ -static void load_reference_block(struct vdo_waiter *waiter, void *context) +static void load_reference_block_group(struct vdo_waiter *waiter, void *context) { struct pooled_vio *pooled = context; struct vio *vio = &pooled->vio; struct reference_block *block = container_of(waiter, struct reference_block, waiter); - size_t block_offset = (block - block->slab->reference_blocks); + u32 block_offset = block - block->slab->reference_blocks; + u32 max_block_count = block->slab->reference_block_count - block_offset; + u32 block_count = min_t(int, vio->block_count, max_block_count); vio->completion.parent = block; - vdo_submit_metadata_vio(vio, block->slab->ref_counts_origin + block_offset, - load_reference_block_endio, handle_io_error, - REQ_OP_READ); + vdo_submit_metadata_vio_with_size(vio, block->slab->ref_counts_origin + block_offset, + load_reference_block_endio, handle_io_error, + REQ_OP_READ, block_count * VDO_BLOCK_SIZE); } /** @@ -2286,14 +2355,21 @@ static void load_reference_block(struct vdo_waiter *waiter, void *context) static void load_reference_blocks(struct vdo_slab *slab) { block_count_t i; + u64 blocks_per_vio = slab->allocator->refcount_blocks_per_big_vio; + struct vio_pool *pool = slab->allocator->refcount_big_vio_pool; + + if (!pool) { + pool = slab->allocator->vio_pool; + blocks_per_vio = 1; + } slab->free_blocks = slab->block_count; slab->active_count = slab->reference_block_count; - for (i = 0; i < slab->reference_block_count; i++) { + for (i = 0; i < slab->reference_block_count; i += blocks_per_vio) { struct vdo_waiter *waiter = &slab->reference_blocks[i].waiter; - waiter->callback = load_reference_block; - acquire_vio_from_pool(slab->allocator->vio_pool, waiter); + waiter->callback = load_reference_block_group; + acquire_vio_from_pool(pool, waiter); } } @@ -2429,7 +2505,7 @@ static void finish_loading_journal(struct vdo_completion *completion) initialize_journal_state(journal); } - return_vio_to_pool(slab->allocator->vio_pool, vio_as_pooled_vio(vio)); + return_vio_to_pool(vio_as_pooled_vio(vio)); vdo_finish_loading_with_result(&slab->state, allocate_counters_if_clean(slab)); } @@ -2449,7 +2525,7 @@ static void handle_load_error(struct vdo_completion *completion) struct vio *vio = as_vio(completion); vio_record_metadata_io_error(vio); - return_vio_to_pool(journal->slab->allocator->vio_pool, vio_as_pooled_vio(vio)); + return_vio_to_pool(vio_as_pooled_vio(vio)); vdo_finish_loading_with_result(&journal->slab->state, result); } @@ -2547,7 +2623,7 @@ static void queue_slab(struct vdo_slab *slab) int result; VDO_ASSERT_LOG_ONLY(list_empty(&slab->allocq_entry), - "a requeued slab must not already be on a ring"); + "a requeued slab must not already be on a list"); if (vdo_is_read_only(allocator->depot->vdo)) return; @@ -2700,6 +2776,7 @@ static void finish_scrubbing(struct slab_scrubber *scrubber, int result) vdo_log_info("VDO commencing normal operation"); else if (prior_state == VDO_RECOVERING) vdo_log_info("Exiting recovery mode"); + free_vio_pool(vdo_forget(allocator->refcount_big_vio_pool)); } /* @@ -3281,7 +3358,7 @@ int vdo_release_block_reference(struct block_allocator *allocator, * This is a min_heap callback function orders slab_status structures using the 'is_clean' field as * the primary key and the 'emptiness' field as the secondary key. * - * Slabs need to be pushed onto the rings in the same order they are to be popped off. Popping + * Slabs need to be pushed onto the lists in the same order they are to be popped off. Popping * should always get the most empty first, so pushing should be from most empty to least empty. * Thus, the ordering is reversed from the usual sense since min_heap returns smaller elements * before larger ones. @@ -3983,6 +4060,7 @@ static int __must_check initialize_block_allocator(struct slab_depot *depot, struct vdo *vdo = depot->vdo; block_count_t max_free_blocks = depot->slab_config.data_blocks; unsigned int max_priority = (2 + ilog2(max_free_blocks)); + u32 reference_block_count, refcount_reads_needed, refcount_blocks_per_vio; *allocator = (struct block_allocator) { .depot = depot, @@ -4000,12 +4078,24 @@ static int __must_check initialize_block_allocator(struct slab_depot *depot, return result; vdo_initialize_completion(&allocator->completion, vdo, VDO_BLOCK_ALLOCATOR_COMPLETION); - result = make_vio_pool(vdo, BLOCK_ALLOCATOR_VIO_POOL_SIZE, allocator->thread_id, + result = make_vio_pool(vdo, BLOCK_ALLOCATOR_VIO_POOL_SIZE, 1, allocator->thread_id, VIO_TYPE_SLAB_JOURNAL, VIO_PRIORITY_METADATA, allocator, &allocator->vio_pool); if (result != VDO_SUCCESS) return result; + /* Initialize the refcount-reading vio pool. */ + reference_block_count = vdo_get_saved_reference_count_size(depot->slab_config.slab_blocks); + refcount_reads_needed = DIV_ROUND_UP(reference_block_count, MAX_BLOCKS_PER_VIO); + refcount_blocks_per_vio = DIV_ROUND_UP(reference_block_count, refcount_reads_needed); + allocator->refcount_blocks_per_big_vio = refcount_blocks_per_vio; + result = make_vio_pool(vdo, BLOCK_ALLOCATOR_REFCOUNT_VIO_POOL_SIZE, + allocator->refcount_blocks_per_big_vio, allocator->thread_id, + VIO_TYPE_SLAB_JOURNAL, VIO_PRIORITY_METADATA, + NULL, &allocator->refcount_big_vio_pool); + if (result != VDO_SUCCESS) + return result; + result = initialize_slab_scrubber(allocator); if (result != VDO_SUCCESS) return result; @@ -4223,6 +4313,7 @@ void vdo_free_slab_depot(struct slab_depot *depot) uninitialize_allocator_summary(allocator); uninitialize_scrubber_vio(&allocator->scrubber); free_vio_pool(vdo_forget(allocator->vio_pool)); + free_vio_pool(vdo_forget(allocator->refcount_big_vio_pool)); vdo_free_priority_table(vdo_forget(allocator->prioritized_slabs)); }
diff --git a/drivers/md/dm-vdo/slab-depot.h b/drivers/md/dm-vdo/slab-depot.h index f234853..fadc0c9 100644 --- a/drivers/md/dm-vdo/slab-depot.h +++ b/drivers/md/dm-vdo/slab-depot.h
@@ -45,6 +45,13 @@ enum { /* The number of vios in the vio pool is proportional to the throughput of the VDO. */ BLOCK_ALLOCATOR_VIO_POOL_SIZE = 128, + + /* + * The number of vios in the vio pool used for loading reference count data. A slab's + * refcounts is capped at ~8MB, and we process one at a time in a zone, so 9 should be + * plenty. + */ + BLOCK_ALLOCATOR_REFCOUNT_VIO_POOL_SIZE = 9, }; /* @@ -248,7 +255,7 @@ struct vdo_slab { /* A list of the dirty blocks waiting to be written out */ struct vdo_wait_queue dirty_blocks; - /* The number of blocks which are currently writing */ + /* The number of blocks which are currently reading or writing */ size_t active_count; /* A waiter object for updating the slab summary */ @@ -425,6 +432,10 @@ struct block_allocator { /* The vio pool for reading and writing block allocator metadata */ struct vio_pool *vio_pool; + /* The vio pool for large initial reads of ref count areas */ + struct vio_pool *refcount_big_vio_pool; + /* How many ref count blocks are read per vio at initial load */ + u32 refcount_blocks_per_big_vio; /* The dm_kcopyd client for erasing slab journals */ struct dm_kcopyd_client *eraser; /* Iterator over the slabs to be erased */
diff --git a/drivers/md/dm-vdo/types.h b/drivers/md/dm-vdo/types.h index dbe892b..cdf36e7 100644 --- a/drivers/md/dm-vdo/types.h +++ b/drivers/md/dm-vdo/types.h
@@ -376,6 +376,9 @@ struct vio { /* The size of this vio in blocks */ unsigned int block_count; + /* The amount of data to be read or written, in bytes */ + unsigned int io_size; + /* The data being read or written. */ char *data;
diff --git a/drivers/md/dm-vdo/vdo.c b/drivers/md/dm-vdo/vdo.c index a7e32ba..80b6086 100644 --- a/drivers/md/dm-vdo/vdo.c +++ b/drivers/md/dm-vdo/vdo.c
@@ -31,9 +31,7 @@ #include <linux/completion.h> #include <linux/device-mapper.h> -#include <linux/kernel.h> #include <linux/lz4.h> -#include <linux/module.h> #include <linux/mutex.h> #include <linux/spinlock.h> #include <linux/types.h> @@ -142,12 +140,6 @@ static void finish_vdo_request_queue(void *ptr) vdo_unregister_allocating_thread(); } -#ifdef MODULE -#define MODULE_NAME THIS_MODULE->name -#else -#define MODULE_NAME "dm-vdo" -#endif /* MODULE */ - static const struct vdo_work_queue_type default_queue_type = { .start = start_vdo_request_queue, .finish = finish_vdo_request_queue, @@ -559,8 +551,7 @@ int vdo_make(unsigned int instance, struct device_config *config, char **reason, *vdo_ptr = vdo; snprintf(vdo->thread_name_prefix, sizeof(vdo->thread_name_prefix), - "%s%u", MODULE_NAME, instance); - BUG_ON(vdo->thread_name_prefix[0] == '\0'); + "vdo%u", instance); result = vdo_allocate(vdo->thread_config.thread_count, struct vdo_thread, __func__, &vdo->threads); if (result != VDO_SUCCESS) {
diff --git a/drivers/md/dm-vdo/vio.c b/drivers/md/dm-vdo/vio.c index e710f3c..e7f4153 100644 --- a/drivers/md/dm-vdo/vio.c +++ b/drivers/md/dm-vdo/vio.c
@@ -188,14 +188,23 @@ void vdo_set_bio_properties(struct bio *bio, struct vio *vio, bio_end_io_t callb /* * Prepares the bio to perform IO with the specified buffer. May only be used on a VDO-allocated - * bio, as it assumes the bio wraps a 4k buffer that is 4k aligned, but there does not have to be a - * vio associated with the bio. + * bio, as it assumes the bio wraps a 4k-multiple buffer that is 4k aligned, but there does not + * have to be a vio associated with the bio. */ int vio_reset_bio(struct vio *vio, char *data, bio_end_io_t callback, blk_opf_t bi_opf, physical_block_number_t pbn) { - int bvec_count, offset, len, i; + return vio_reset_bio_with_size(vio, data, vio->block_count * VDO_BLOCK_SIZE, + callback, bi_opf, pbn); +} + +int vio_reset_bio_with_size(struct vio *vio, char *data, int size, bio_end_io_t callback, + blk_opf_t bi_opf, physical_block_number_t pbn) +{ + int bvec_count, offset, i; struct bio *bio = vio->bio; + int vio_size = vio->block_count * VDO_BLOCK_SIZE; + int remaining; bio_reset(bio, bio->bi_bdev, bi_opf); vdo_set_bio_properties(bio, vio, callback, bi_opf, pbn); @@ -205,22 +214,21 @@ int vio_reset_bio(struct vio *vio, char *data, bio_end_io_t callback, bio->bi_ioprio = 0; bio->bi_io_vec = bio->bi_inline_vecs; bio->bi_max_vecs = vio->block_count + 1; - len = VDO_BLOCK_SIZE * vio->block_count; + if (VDO_ASSERT(size <= vio_size, "specified size %d is not greater than allocated %d", + size, vio_size) != VDO_SUCCESS) + size = vio_size; + vio->io_size = size; offset = offset_in_page(data); - bvec_count = DIV_ROUND_UP(offset + len, PAGE_SIZE); + bvec_count = DIV_ROUND_UP(offset + size, PAGE_SIZE); + remaining = size; - /* - * If we knew that data was always on one page, or contiguous pages, we wouldn't need the - * loop. But if we're using vmalloc, it's not impossible that the data is in different - * pages that can't be merged in bio_add_page... - */ - for (i = 0; (i < bvec_count) && (len > 0); i++) { + for (i = 0; (i < bvec_count) && (remaining > 0); i++) { struct page *page; int bytes_added; int bytes = PAGE_SIZE - offset; - if (bytes > len) - bytes = len; + if (bytes > remaining) + bytes = remaining; page = is_vmalloc_addr(data) ? vmalloc_to_page(data) : virt_to_page(data); bytes_added = bio_add_page(bio, page, bytes, offset); @@ -232,7 +240,7 @@ int vio_reset_bio(struct vio *vio, char *data, bio_end_io_t callback, } data += bytes; - len -= bytes; + remaining -= bytes; offset = 0; } @@ -301,6 +309,7 @@ void vio_record_metadata_io_error(struct vio *vio) * make_vio_pool() - Create a new vio pool. * @vdo: The vdo. * @pool_size: The number of vios in the pool. + * @block_count: The number of 4k blocks per vio. * @thread_id: The ID of the thread using this pool. * @vio_type: The type of vios in the pool. * @priority: The priority with which vios from the pool should be enqueued. @@ -309,13 +318,14 @@ void vio_record_metadata_io_error(struct vio *vio) * * Return: A success or error code. */ -int make_vio_pool(struct vdo *vdo, size_t pool_size, thread_id_t thread_id, +int make_vio_pool(struct vdo *vdo, size_t pool_size, size_t block_count, thread_id_t thread_id, enum vio_type vio_type, enum vio_priority priority, void *context, struct vio_pool **pool_ptr) { struct vio_pool *pool; char *ptr; int result; + size_t per_vio_size = VDO_BLOCK_SIZE * block_count; result = vdo_allocate_extended(struct vio_pool, pool_size, struct pooled_vio, __func__, &pool); @@ -326,7 +336,7 @@ int make_vio_pool(struct vdo *vdo, size_t pool_size, thread_id_t thread_id, INIT_LIST_HEAD(&pool->available); INIT_LIST_HEAD(&pool->busy); - result = vdo_allocate(pool_size * VDO_BLOCK_SIZE, char, + result = vdo_allocate(pool_size * per_vio_size, char, "VIO pool buffer", &pool->buffer); if (result != VDO_SUCCESS) { free_vio_pool(pool); @@ -334,10 +344,10 @@ int make_vio_pool(struct vdo *vdo, size_t pool_size, thread_id_t thread_id, } ptr = pool->buffer; - for (pool->size = 0; pool->size < pool_size; pool->size++, ptr += VDO_BLOCK_SIZE) { + for (pool->size = 0; pool->size < pool_size; pool->size++, ptr += per_vio_size) { struct pooled_vio *pooled = &pool->vios[pool->size]; - result = allocate_vio_components(vdo, vio_type, priority, NULL, 1, ptr, + result = allocate_vio_components(vdo, vio_type, priority, NULL, block_count, ptr, &pooled->vio); if (result != VDO_SUCCESS) { free_vio_pool(pool); @@ -345,6 +355,7 @@ int make_vio_pool(struct vdo *vdo, size_t pool_size, thread_id_t thread_id, } pooled->context = context; + pooled->pool = pool; list_add_tail(&pooled->pool_entry, &pool->available); } @@ -419,12 +430,13 @@ void acquire_vio_from_pool(struct vio_pool *pool, struct vdo_waiter *waiter) } /** - * return_vio_to_pool() - Return a vio to the pool - * @pool: The vio pool. + * return_vio_to_pool() - Return a vio to its pool * @vio: The pooled vio to return. */ -void return_vio_to_pool(struct vio_pool *pool, struct pooled_vio *vio) +void return_vio_to_pool(struct pooled_vio *vio) { + struct vio_pool *pool = vio->pool; + VDO_ASSERT_LOG_ONLY((pool->thread_id == vdo_get_callback_thread_id()), "vio pool entry returned on same thread as it was acquired");
diff --git a/drivers/md/dm-vdo/vio.h b/drivers/md/dm-vdo/vio.h index 3490e9f..4bfcb21 100644 --- a/drivers/md/dm-vdo/vio.h +++ b/drivers/md/dm-vdo/vio.h
@@ -30,6 +30,8 @@ struct pooled_vio { void *context; /* The list entry used by the pool */ struct list_head pool_entry; + /* The pool this vio is allocated from */ + struct vio_pool *pool; }; /** @@ -123,6 +125,8 @@ void vdo_set_bio_properties(struct bio *bio, struct vio *vio, bio_end_io_t callb int vio_reset_bio(struct vio *vio, char *data, bio_end_io_t callback, blk_opf_t bi_opf, physical_block_number_t pbn); +int vio_reset_bio_with_size(struct vio *vio, char *data, int size, bio_end_io_t callback, + blk_opf_t bi_opf, physical_block_number_t pbn); void update_vio_error_stats(struct vio *vio, const char *format, ...) __printf(2, 3); @@ -188,12 +192,13 @@ static inline struct pooled_vio *vio_as_pooled_vio(struct vio *vio) struct vio_pool; -int __must_check make_vio_pool(struct vdo *vdo, size_t pool_size, thread_id_t thread_id, - enum vio_type vio_type, enum vio_priority priority, - void *context, struct vio_pool **pool_ptr); +int __must_check make_vio_pool(struct vdo *vdo, size_t pool_size, size_t block_count, + thread_id_t thread_id, enum vio_type vio_type, + enum vio_priority priority, void *context, + struct vio_pool **pool_ptr); void free_vio_pool(struct vio_pool *pool); bool __must_check is_vio_pool_busy(struct vio_pool *pool); void acquire_vio_from_pool(struct vio_pool *pool, struct vdo_waiter *waiter); -void return_vio_to_pool(struct vio_pool *pool, struct pooled_vio *vio); +void return_vio_to_pool(struct pooled_vio *vio); #endif /* VIO_H */
diff --git a/drivers/md/dm-vdo/wait-queue.c b/drivers/md/dm-vdo/wait-queue.c index 6e1e739..f81ed0c 100644 --- a/drivers/md/dm-vdo/wait-queue.c +++ b/drivers/md/dm-vdo/wait-queue.c
@@ -34,7 +34,7 @@ void vdo_waitq_enqueue_waiter(struct vdo_wait_queue *waitq, struct vdo_waiter *w waitq->last_waiter->next_waiter = waiter; } - /* In both cases, the waiter we added to the ring becomes the last waiter. */ + /* In both cases, the waiter we added to the list becomes the last waiter. */ waitq->last_waiter = waiter; waitq->length += 1; }
diff --git a/drivers/md/dm-verity-target.c b/drivers/md/dm-verity-target.c index e86c143..3c427f1 100644 --- a/drivers/md/dm-verity-target.c +++ b/drivers/md/dm-verity-target.c
@@ -30,6 +30,7 @@ #define DM_VERITY_ENV_VAR_NAME "DM_VERITY_ERR_BLOCK_NR" #define DM_VERITY_DEFAULT_PREFETCH_SIZE 262144 +#define DM_VERITY_USE_BH_DEFAULT_BYTES 8192 #define DM_VERITY_MAX_CORRUPTED_ERRS 100 @@ -49,6 +50,15 @@ static unsigned int dm_verity_prefetch_cluster = DM_VERITY_DEFAULT_PREFETCH_SIZE module_param_named(prefetch_cluster, dm_verity_prefetch_cluster, uint, 0644); +static unsigned int dm_verity_use_bh_bytes[4] = { + DM_VERITY_USE_BH_DEFAULT_BYTES, // IOPRIO_CLASS_NONE + DM_VERITY_USE_BH_DEFAULT_BYTES, // IOPRIO_CLASS_RT + DM_VERITY_USE_BH_DEFAULT_BYTES, // IOPRIO_CLASS_BE + 0 // IOPRIO_CLASS_IDLE +}; + +module_param_array_named(use_bh_bytes, dm_verity_use_bh_bytes, uint, NULL, 0644); + static DEFINE_STATIC_KEY_FALSE(use_bh_wq_enabled); /* Is at least one dm-verity instance using ahash_tfm instead of shash_tfm? */ @@ -311,7 +321,7 @@ static int verity_verify_level(struct dm_verity *v, struct dm_verity_io *io, if (static_branch_unlikely(&use_bh_wq_enabled) && io->in_bh) { data = dm_bufio_get(v->bufio, hash_block, &buf); - if (data == NULL) { + if (IS_ERR_OR_NULL(data)) { /* * In tasklet and the hash was not in the bufio cache. * Return early and resume execution from a work-queue @@ -324,8 +334,24 @@ static int verity_verify_level(struct dm_verity *v, struct dm_verity_io *io, &buf, bio->bi_ioprio); } - if (IS_ERR(data)) - return PTR_ERR(data); + if (IS_ERR(data)) { + if (skip_unverified) + return 1; + r = PTR_ERR(data); + data = dm_bufio_new(v->bufio, hash_block, &buf); + if (IS_ERR(data)) + return r; + if (verity_fec_decode(v, io, DM_VERITY_BLOCK_TYPE_METADATA, + hash_block, data) == 0) { + aux = dm_bufio_get_aux_data(buf); + aux->hash_verified = 1; + goto release_ok; + } else { + dm_bufio_release(buf); + dm_bufio_forget(v->bufio, hash_block); + return r; + } + } aux = dm_bufio_get_aux_data(buf); @@ -366,6 +392,7 @@ static int verity_verify_level(struct dm_verity *v, struct dm_verity_io *io, } } +release_ok: data += offset; memcpy(want_digest, data, v->digest_size); r = 0; @@ -652,9 +679,17 @@ static void verity_bh_work(struct work_struct *w) verity_finish_io(io, errno_to_blk_status(err)); } +static inline bool verity_use_bh(unsigned int bytes, unsigned short ioprio) +{ + return ioprio <= IOPRIO_CLASS_IDLE && + bytes <= READ_ONCE(dm_verity_use_bh_bytes[ioprio]); +} + static void verity_end_io(struct bio *bio) { struct dm_verity_io *io = bio->bi_private; + unsigned short ioprio = IOPRIO_PRIO_CLASS(bio->bi_ioprio); + unsigned int bytes = io->n_blocks << io->v->data_dev_block_bits; if (bio->bi_status && (!verity_fec_is_enabled(io->v) || @@ -664,9 +699,14 @@ static void verity_end_io(struct bio *bio) return; } - if (static_branch_unlikely(&use_bh_wq_enabled) && io->v->use_bh_wq) { - INIT_WORK(&io->bh_work, verity_bh_work); - queue_work(system_bh_wq, &io->bh_work); + if (static_branch_unlikely(&use_bh_wq_enabled) && io->v->use_bh_wq && + verity_use_bh(bytes, ioprio)) { + if (in_hardirq() || irqs_disabled()) { + INIT_WORK(&io->bh_work, verity_bh_work); + queue_work(system_bh_wq, &io->bh_work); + } else { + verity_bh_work(&io->bh_work); + } } else { INIT_WORK(&io->work, verity_work); queue_work(io->v->verify_wq, &io->work); @@ -796,6 +836,13 @@ static int verity_map(struct dm_target *ti, struct bio *bio) return DM_MAPIO_SUBMITTED; } +static void verity_postsuspend(struct dm_target *ti) +{ + struct dm_verity *v = ti->private; + flush_workqueue(v->verify_wq); + dm_bufio_client_reset(v->bufio); +} + /* * Status: V (valid) or C (corruption found) */ @@ -1761,11 +1808,12 @@ static struct target_type verity_target = { .name = "verity", /* Note: the LSMs depend on the singleton and immutable features */ .features = DM_TARGET_SINGLETON | DM_TARGET_IMMUTABLE, - .version = {1, 10, 0}, + .version = {1, 11, 0}, .module = THIS_MODULE, .ctr = verity_ctr, .dtr = verity_dtr, .map = verity_map, + .postsuspend = verity_postsuspend, .status = verity_status, .prepare_ioctl = verity_prepare_ioctl, .iterate_devices = verity_iterate_devices,
diff --git a/drivers/md/dm-writecache.c b/drivers/md/dm-writecache.c index 7ce8847..d6a04a5 100644 --- a/drivers/md/dm-writecache.c +++ b/drivers/md/dm-writecache.c
@@ -797,7 +797,7 @@ static void writecache_flush(struct dm_writecache *wc) bool need_flush_after_free; wc->uncommitted_blocks = 0; - del_timer(&wc->autocommit_timer); + timer_delete(&wc->autocommit_timer); if (list_empty(&wc->lru)) return; @@ -927,8 +927,8 @@ static void writecache_suspend(struct dm_target *ti) struct dm_writecache *wc = ti->private; bool flush_on_suspend; - del_timer_sync(&wc->autocommit_timer); - del_timer_sync(&wc->max_age_timer); + timer_delete_sync(&wc->autocommit_timer); + timer_delete_sync(&wc->max_age_timer); wc_lock(wc); writecache_flush(wc);
diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 4d1e428..5ab7574 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c
@@ -1540,14 +1540,18 @@ static void __send_empty_flush(struct clone_info *ci) { struct dm_table *t = ci->map; struct bio flush_bio; + blk_opf_t opf = REQ_OP_WRITE | REQ_PREFLUSH | REQ_SYNC; + + if ((ci->io->orig_bio->bi_opf & (REQ_IDLE | REQ_SYNC)) == + (REQ_IDLE | REQ_SYNC)) + opf |= REQ_IDLE; /* * Use an on-stack bio for this, it's safe since we don't * need to reference it after submit. It's just used as * the basis for the clone(s). */ - bio_init(&flush_bio, ci->io->md->disk->part0, NULL, 0, - REQ_OP_WRITE | REQ_PREFLUSH | REQ_SYNC); + bio_init(&flush_bio, ci->io->md->disk->part0, NULL, 0, opf); ci->bio = &flush_bio; ci->sector_count = 0;
diff --git a/drivers/md/md.c b/drivers/md/md.c index 438e71e..9daa78c 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c
@@ -4064,7 +4064,7 @@ level_store(struct mddev *mddev, const char *buf, size_t len) * it must always be in_sync */ mddev->in_sync = 1; - del_timer_sync(&mddev->safemode_timer); + timer_delete_sync(&mddev->safemode_timer); } pers->run(mddev); set_bit(MD_SB_CHANGE_DEVS, &mddev->sb_flags); @@ -6405,7 +6405,7 @@ static void md_clean(struct mddev *mddev) static void __md_stop_writes(struct mddev *mddev) { - del_timer_sync(&mddev->safemode_timer); + timer_delete_sync(&mddev->safemode_timer); if (mddev->pers && mddev->pers->quiesce) { mddev->pers->quiesce(mddev, 1);
diff --git a/drivers/md/persistent-data/Kconfig b/drivers/md/persistent-data/Kconfig index f4f948b..dbb97a7 100644 --- a/drivers/md/persistent-data/Kconfig +++ b/drivers/md/persistent-data/Kconfig
@@ -2,7 +2,7 @@ config DM_PERSISTENT_DATA tristate depends on BLK_DEV_DM - select LIBCRC32C + select CRC32 select DM_BUFIO help Library providing immutable on-disk data structure support for
diff --git a/drivers/media/common/saa7146/saa7146_fops.c b/drivers/media/common/saa7146/saa7146_fops.c index a7047e5..2952678 100644 --- a/drivers/media/common/saa7146/saa7146_fops.c +++ b/drivers/media/common/saa7146/saa7146_fops.c
@@ -147,7 +147,7 @@ void saa7146_buffer_next(struct saa7146_dev *dev, printk("vdma%d.num_line_byte: 0x%08x\n", 1,saa7146_read(dev,NUM_LINE_BYTE1)); */ } - del_timer(&q->timeout); + timer_delete(&q->timeout); } }
diff --git a/drivers/media/common/saa7146/saa7146_vbi.c b/drivers/media/common/saa7146/saa7146_vbi.c index a1854b3..6c324a6 100644 --- a/drivers/media/common/saa7146/saa7146_vbi.c +++ b/drivers/media/common/saa7146/saa7146_vbi.c
@@ -322,8 +322,8 @@ static void vbi_stop(struct saa7146_dev *dev) /* shut down dma 3 transfers */ saa7146_write(dev, MC1, MASK_20); - del_timer(&vv->vbi_dmaq.timeout); - del_timer(&vv->vbi_read_timeout); + timer_delete(&vv->vbi_dmaq.timeout); + timer_delete(&vv->vbi_read_timeout); spin_unlock_irqrestore(&dev->slock, flags); }
diff --git a/drivers/media/common/saa7146/saa7146_video.c b/drivers/media/common/saa7146/saa7146_video.c index 94e1cd4..733e180 100644 --- a/drivers/media/common/saa7146/saa7146_video.c +++ b/drivers/media/common/saa7146/saa7146_video.c
@@ -668,7 +668,7 @@ static void stop_streaming(struct vb2_queue *q) struct saa7146_dev *dev = vb2_get_drv_priv(q); struct saa7146_dmaqueue *dq = &dev->vv_data->video_dmaq; - del_timer(&dq->timeout); + timer_delete(&dq->timeout); video_end(dev); return_buffers(q, VB2_BUF_STATE_ERROR); }
diff --git a/drivers/media/dvb-core/dmxdev.c b/drivers/media/dvb-core/dmxdev.c index 6063782..1e985f9 100644 --- a/drivers/media/dvb-core/dmxdev.c +++ b/drivers/media/dvb-core/dmxdev.c
@@ -365,7 +365,7 @@ static void dvb_dmxdev_filter_timer(struct dmxdev_filter *dmxdevfilter) { struct dmx_sct_filter_params *para = &dmxdevfilter->params.sec; - del_timer(&dmxdevfilter->timer); + timer_delete(&dmxdevfilter->timer); if (para->timeout) { dmxdevfilter->timer.expires = jiffies + 1 + (HZ / 2 + HZ * para->timeout) / 1000; @@ -391,7 +391,7 @@ static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len, spin_unlock(&dmxdevfilter->dev->lock); return 0; } - del_timer(&dmxdevfilter->timer); + timer_delete(&dmxdevfilter->timer); dprintk("section callback %*ph\n", 6, buffer1); if (dvb_vb2_is_streaming(&dmxdevfilter->vb2_ctx)) { ret = dvb_vb2_fill_buffer(&dmxdevfilter->vb2_ctx, @@ -482,7 +482,7 @@ static int dvb_dmxdev_feed_stop(struct dmxdev_filter *dmxdevfilter) switch (dmxdevfilter->type) { case DMXDEV_TYPE_SEC: - del_timer(&dmxdevfilter->timer); + timer_delete(&dmxdevfilter->timer); dmxdevfilter->feed.sec->stop_filtering(dmxdevfilter->feed.sec); break; case DMXDEV_TYPE_PES:
diff --git a/drivers/media/dvb-frontends/dib8000.c b/drivers/media/dvb-frontends/dib8000.c index 2f51659..cfe59c3 100644 --- a/drivers/media/dvb-frontends/dib8000.c +++ b/drivers/media/dvb-frontends/dib8000.c
@@ -2701,8 +2701,11 @@ static void dib8000_set_dds(struct dib8000_state *state, s32 offset_khz) u8 ratio; if (state->revision == 0x8090) { + u32 internal = dib8000_read32(state, 23) / 1000; + ratio = 4; - unit_khz_dds_val = (1<<26) / (dib8000_read32(state, 23) / 1000); + + unit_khz_dds_val = (1<<26) / (internal ?: 1); if (offset_khz < 0) dds = (1 << 26) - (abs_offset_khz * unit_khz_dds_val); else
diff --git a/drivers/media/i2c/tc358743.c b/drivers/media/i2c/tc358743.c index c50d4e85..2d5f42f 100644 --- a/drivers/media/i2c/tc358743.c +++ b/drivers/media/i2c/tc358743.c
@@ -2201,7 +2201,7 @@ static int tc358743_probe(struct i2c_client *client) err_work_queues: cec_unregister_adapter(state->cec_adap); if (!state->i2c_client->irq) { - del_timer(&state->timer); + timer_delete(&state->timer); flush_work(&state->work_i2c_poll); } cancel_delayed_work(&state->delayed_work_enable_hotplug); @@ -2218,7 +2218,7 @@ static void tc358743_remove(struct i2c_client *client) struct tc358743_state *state = to_state(sd); if (!state->i2c_client->irq) { - del_timer_sync(&state->timer); + timer_delete_sync(&state->timer); flush_work(&state->work_i2c_poll); } cancel_delayed_work_sync(&state->delayed_work_enable_hotplug);
diff --git a/drivers/media/i2c/tvaudio.c b/drivers/media/i2c/tvaudio.c index 654725d..4211511 100644 --- a/drivers/media/i2c/tvaudio.c +++ b/drivers/media/i2c/tvaudio.c
@@ -1787,7 +1787,7 @@ static int tvaudio_s_radio(struct v4l2_subdev *sd) struct CHIPSTATE *chip = to_state(sd); chip->radio = 1; - /* del_timer(&chip->wt); */ + /* timer_delete(&chip->wt); */ return 0; } @@ -2071,7 +2071,7 @@ static void tvaudio_remove(struct i2c_client *client) struct v4l2_subdev *sd = i2c_get_clientdata(client); struct CHIPSTATE *chip = to_state(sd); - del_timer_sync(&chip->wt); + timer_delete_sync(&chip->wt); if (chip->thread) { /* shutdown async thread */ kthread_stop(chip->thread);
diff --git a/drivers/media/pci/bt8xx/bttv-driver.c b/drivers/media/pci/bt8xx/bttv-driver.c index 2782832..377a7e7 100644 --- a/drivers/media/pci/bt8xx/bttv-driver.c +++ b/drivers/media/pci/bt8xx/bttv-driver.c
@@ -3491,7 +3491,7 @@ static void bttv_remove(struct pci_dev *pci_dev) /* free resources */ free_irq(btv->c.pci->irq,btv); - del_timer_sync(&btv->timeout); + timer_delete_sync(&btv->timeout); iounmap(btv->bt848_mmio); release_mem_region(pci_resource_start(btv->c.pci,0), pci_resource_len(btv->c.pci,0));
diff --git a/drivers/media/pci/bt8xx/bttv-input.c b/drivers/media/pci/bt8xx/bttv-input.c index 41226f1..9eb7a53 100644 --- a/drivers/media/pci/bt8xx/bttv-input.c +++ b/drivers/media/pci/bt8xx/bttv-input.c
@@ -304,12 +304,12 @@ static void bttv_ir_start(struct bttv_ir *ir) static void bttv_ir_stop(struct bttv *btv) { if (btv->remote->polling) - del_timer_sync(&btv->remote->timer); + timer_delete_sync(&btv->remote->timer); if (btv->remote->rc5_gpio) { u32 gpio; - del_timer_sync(&btv->remote->timer); + timer_delete_sync(&btv->remote->timer); gpio = bttv_gpio_read(&btv->c); bttv_gpio_write(&btv->c, gpio & ~(1 << 4));
diff --git a/drivers/media/pci/bt8xx/bttv-risc.c b/drivers/media/pci/bt8xx/bttv-risc.c index 241a696..79581cd 100644 --- a/drivers/media/pci/bt8xx/bttv-risc.c +++ b/drivers/media/pci/bt8xx/bttv-risc.c
@@ -376,7 +376,7 @@ static void bttv_set_irq_timer(struct bttv *btv) if (btv->curr.frame_irq || btv->loop_irq || btv->cvbi) mod_timer(&btv->timeout, jiffies + BTTV_TIMEOUT); else - del_timer(&btv->timeout); + timer_delete(&btv->timeout); } static int bttv_set_capture_control(struct bttv *btv, int start_capture)
diff --git a/drivers/media/pci/ivtv/ivtv-irq.c b/drivers/media/pci/ivtv/ivtv-irq.c index b7aaa8b..b3b670b 100644 --- a/drivers/media/pci/ivtv/ivtv-irq.c +++ b/drivers/media/pci/ivtv/ivtv-irq.c
@@ -532,7 +532,7 @@ static void ivtv_irq_dma_read(struct ivtv *itv) IVTV_DEBUG_HI_IRQ("DEC DMA READ\n"); - del_timer(&itv->dma_timer); + timer_delete(&itv->dma_timer); if (!test_bit(IVTV_F_I_UDMA, &itv->i_flags) && itv->cur_dma_stream < 0) return; @@ -597,7 +597,7 @@ static void ivtv_irq_enc_dma_complete(struct ivtv *itv) ivtv_api_get_data(&itv->enc_mbox, IVTV_MBOX_DMA_END, 2, data); IVTV_DEBUG_HI_IRQ("ENC DMA COMPLETE %x %d (%d)\n", data[0], data[1], itv->cur_dma_stream); - del_timer(&itv->dma_timer); + timer_delete(&itv->dma_timer); if (itv->cur_dma_stream < 0) return; @@ -670,7 +670,7 @@ static void ivtv_irq_dma_err(struct ivtv *itv) u32 data[CX2341X_MBOX_MAX_DATA]; u32 status; - del_timer(&itv->dma_timer); + timer_delete(&itv->dma_timer); ivtv_api_get_data(&itv->enc_mbox, IVTV_MBOX_DMA_END, 2, data); status = read_reg(IVTV_REG_DMASTATUS);
diff --git a/drivers/media/pci/ivtv/ivtv-streams.c b/drivers/media/pci/ivtv/ivtv-streams.c index af9e623..ac08592 100644 --- a/drivers/media/pci/ivtv/ivtv-streams.c +++ b/drivers/media/pci/ivtv/ivtv-streams.c
@@ -891,7 +891,7 @@ int ivtv_stop_v4l2_encode_stream(struct ivtv_stream *s, int gop_end) /* Set the following Interrupt mask bits for capture */ ivtv_set_irq_mask(itv, IVTV_IRQ_MASK_CAPTURE); - del_timer(&itv->dma_timer); + timer_delete(&itv->dma_timer); /* event notification (off) */ if (test_and_clear_bit(IVTV_F_I_DIG_RST, &itv->i_flags)) { @@ -956,7 +956,7 @@ int ivtv_stop_v4l2_decode_stream(struct ivtv_stream *s, int flags, u64 pts) ivtv_vapi(itv, CX2341X_DEC_SET_EVENT_NOTIFICATION, 4, 0, 0, IVTV_IRQ_DEC_AUD_MODE_CHG, -1); ivtv_set_irq_mask(itv, IVTV_IRQ_MASK_DECODE); - del_timer(&itv->dma_timer); + timer_delete(&itv->dma_timer); clear_bit(IVTV_F_S_NEEDS_DATA, &s->s_flags); clear_bit(IVTV_F_S_STREAMING, &s->s_flags);
diff --git a/drivers/media/pci/netup_unidvb/netup_unidvb_core.c b/drivers/media/pci/netup_unidvb/netup_unidvb_core.c index 557985b..16338d1 100644 --- a/drivers/media/pci/netup_unidvb/netup_unidvb_core.c +++ b/drivers/media/pci/netup_unidvb/netup_unidvb_core.c
@@ -698,7 +698,7 @@ static void netup_unidvb_dma_fini(struct netup_unidvb_dev *ndev, int num) netup_unidvb_dma_enable(dma, 0); msleep(50); cancel_work_sync(&dma->work); - del_timer_sync(&dma->timeout); + timer_delete_sync(&dma->timeout); } static int netup_unidvb_dma_setup(struct netup_unidvb_dev *ndev)
diff --git a/drivers/media/pci/saa7134/saa7134-core.c b/drivers/media/pci/saa7134/saa7134-core.c index ea0585e..84295bd 100644 --- a/drivers/media/pci/saa7134/saa7134-core.c +++ b/drivers/media/pci/saa7134/saa7134-core.c
@@ -322,7 +322,7 @@ void saa7134_buffer_next(struct saa7134_dev *dev, /* nothing to do -- just stop DMA */ core_dbg("buffer_next %p\n", NULL); saa7134_set_dmabits(dev); - del_timer(&q->timeout); + timer_delete(&q->timeout); } } @@ -364,7 +364,7 @@ void saa7134_stop_streaming(struct saa7134_dev *dev, struct saa7134_dmaqueue *q) tmp = NULL; } spin_unlock_irqrestore(&dev->slock, flags); - saa7134_buffer_timeout(&q->timeout); /* also calls del_timer(&q->timeout) */ + saa7134_buffer_timeout(&q->timeout); /* also calls timer_delete(&q->timeout) */ } EXPORT_SYMBOL_GPL(saa7134_stop_streaming); @@ -1390,9 +1390,9 @@ static int __maybe_unused saa7134_suspend(struct device *dev_d) /* Disable timeout timers - if we have active buffers, we will fill them on resume*/ - del_timer(&dev->video_q.timeout); - del_timer(&dev->vbi_q.timeout); - del_timer(&dev->ts_q.timeout); + timer_delete(&dev->video_q.timeout); + timer_delete(&dev->vbi_q.timeout); + timer_delete(&dev->ts_q.timeout); if (dev->remote && dev->remote->dev->users) saa7134_ir_close(dev->remote->dev);
diff --git a/drivers/media/pci/saa7134/saa7134-input.c b/drivers/media/pci/saa7134/saa7134-input.c index 8610eb4..d7d97c7 100644 --- a/drivers/media/pci/saa7134/saa7134-input.c +++ b/drivers/media/pci/saa7134/saa7134-input.c
@@ -496,7 +496,7 @@ void saa7134_ir_close(struct rc_dev *rc) struct saa7134_card_ir *ir = dev->remote; if (ir->polling) - del_timer_sync(&ir->timer); + timer_delete_sync(&ir->timer); ir->running = false; }
diff --git a/drivers/media/pci/saa7134/saa7134-ts.c b/drivers/media/pci/saa7134/saa7134-ts.c index ec699ea..1b44033 100644 --- a/drivers/media/pci/saa7134/saa7134-ts.c +++ b/drivers/media/pci/saa7134/saa7134-ts.c
@@ -298,7 +298,7 @@ int saa7134_ts_start(struct saa7134_dev *dev) int saa7134_ts_fini(struct saa7134_dev *dev) { - del_timer_sync(&dev->ts_q.timeout); + timer_delete_sync(&dev->ts_q.timeout); saa7134_pgtable_free(dev->pci, &dev->ts_q.pt); return 0; }
diff --git a/drivers/media/pci/saa7134/saa7134-vbi.c b/drivers/media/pci/saa7134/saa7134-vbi.c index efa6e4f..28bf774 100644 --- a/drivers/media/pci/saa7134/saa7134-vbi.c +++ b/drivers/media/pci/saa7134/saa7134-vbi.c
@@ -183,7 +183,7 @@ int saa7134_vbi_init1(struct saa7134_dev *dev) int saa7134_vbi_fini(struct saa7134_dev *dev) { /* nothing */ - del_timer_sync(&dev->vbi_q.timeout); + timer_delete_sync(&dev->vbi_q.timeout); return 0; }
diff --git a/drivers/media/pci/saa7134/saa7134-video.c b/drivers/media/pci/saa7134/saa7134-video.c index 43e7b00..c88939b 100644 --- a/drivers/media/pci/saa7134/saa7134-video.c +++ b/drivers/media/pci/saa7134/saa7134-video.c
@@ -1741,7 +1741,7 @@ int saa7134_video_init1(struct saa7134_dev *dev) void saa7134_video_fini(struct saa7134_dev *dev) { - del_timer_sync(&dev->video_q.timeout); + timer_delete_sync(&dev->video_q.timeout); /* free stuff */ saa7134_pgtable_free(dev->pci, &dev->video_q.pt); saa7134_pgtable_free(dev->pci, &dev->vbi_q.pt);
diff --git a/drivers/media/pci/tw686x/tw686x-core.c b/drivers/media/pci/tw686x/tw686x-core.c index c53099c..80bd268 100644 --- a/drivers/media/pci/tw686x/tw686x-core.c +++ b/drivers/media/pci/tw686x/tw686x-core.c
@@ -373,7 +373,7 @@ static void tw686x_remove(struct pci_dev *pci_dev) tw686x_video_free(dev); tw686x_audio_free(dev); - del_timer_sync(&dev->dma_delay_timer); + timer_delete_sync(&dev->dma_delay_timer); pci_iounmap(pci_dev, dev->mmio); pci_release_regions(pci_dev);
diff --git a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc.c b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc.c index 5f80931..c8e0ee3 100644 --- a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc.c +++ b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc.c
@@ -935,7 +935,7 @@ static int s5p_mfc_open(struct file *file) if (dev->num_inst == 1) { if (s5p_mfc_power_off(dev) < 0) mfc_err("power off failed\n"); - del_timer_sync(&dev->watchdog_timer); + timer_delete_sync(&dev->watchdog_timer); } err_ctrls_setup: s5p_mfc_dec_ctrls_delete(ctx); @@ -985,7 +985,7 @@ static int s5p_mfc_release(struct file *file) if (dev->num_inst == 0) { mfc_debug(2, "Last instance\n"); s5p_mfc_deinit_hw(dev); - del_timer_sync(&dev->watchdog_timer); + timer_delete_sync(&dev->watchdog_timer); s5p_mfc_clock_off(dev); if (s5p_mfc_power_off(dev) < 0) mfc_err("Power off failed\n"); @@ -1461,7 +1461,7 @@ static void s5p_mfc_remove(struct platform_device *pdev) } mutex_unlock(&dev->mfc_mutex); - del_timer_sync(&dev->watchdog_timer); + timer_delete_sync(&dev->watchdog_timer); flush_work(&dev->watchdog_work); video_unregister_device(dev->vfd_enc);
diff --git a/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.c b/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.c index d151d2e..87a817d 100644 --- a/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.c +++ b/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.c
@@ -351,7 +351,7 @@ static int c8sectpfe_stop_feed(struct dvb_demux_feed *dvbdmxfeed) dev_dbg(fei->dev, "%s:%d global_feed_count=%d\n" , __func__, __LINE__, fei->global_feed_count); - del_timer(&fei->timer); + timer_delete(&fei->timer); } mutex_unlock(&fei->lock);
diff --git a/drivers/media/radio/radio-cadet.c b/drivers/media/radio/radio-cadet.c index a5db9b4..2ddf1df 100644 --- a/drivers/media/radio/radio-cadet.c +++ b/drivers/media/radio/radio-cadet.c
@@ -471,7 +471,7 @@ static int cadet_release(struct file *file) mutex_lock(&dev->lock); if (v4l2_fh_is_singular_file(file) && dev->rdsstat) { - del_timer_sync(&dev->readtimer); + timer_delete_sync(&dev->readtimer); dev->rdsstat = 0; } v4l2_fh_release(file);
diff --git a/drivers/media/rc/ene_ir.c b/drivers/media/rc/ene_ir.c index 67722e2..9435cba 100644 --- a/drivers/media/rc/ene_ir.c +++ b/drivers/media/rc/ene_ir.c
@@ -1104,7 +1104,7 @@ static void ene_remove(struct pnp_dev *pnp_dev) unsigned long flags; rc_unregister_device(dev->rdev); - del_timer_sync(&dev->tx_sim_timer); + timer_delete_sync(&dev->tx_sim_timer); spin_lock_irqsave(&dev->hw_lock, flags); ene_rx_disable(dev); ene_rx_restore_hw_buffer(dev);
diff --git a/drivers/media/rc/igorplugusb.c b/drivers/media/rc/igorplugusb.c index 1464ef9..bfe8658 100644 --- a/drivers/media/rc/igorplugusb.c +++ b/drivers/media/rc/igorplugusb.c
@@ -223,7 +223,7 @@ static int igorplugusb_probe(struct usb_interface *intf, return 0; fail: usb_poison_urb(ir->urb); - del_timer(&ir->timer); + timer_delete(&ir->timer); usb_unpoison_urb(ir->urb); usb_free_urb(ir->urb); rc_free_device(ir->rc); @@ -238,7 +238,7 @@ static void igorplugusb_disconnect(struct usb_interface *intf) rc_unregister_device(ir->rc); usb_poison_urb(ir->urb); - del_timer_sync(&ir->timer); + timer_delete_sync(&ir->timer); usb_set_intfdata(intf, NULL); usb_unpoison_urb(ir->urb); usb_free_urb(ir->urb);
diff --git a/drivers/media/rc/img-ir/img-ir-hw.c b/drivers/media/rc/img-ir/img-ir-hw.c index 5da7479..da89ddf 100644 --- a/drivers/media/rc/img-ir/img-ir-hw.c +++ b/drivers/media/rc/img-ir/img-ir-hw.c
@@ -556,8 +556,8 @@ static void img_ir_set_decoder(struct img_ir_priv *priv, * acquires the lock and we don't want to deadlock waiting for it. */ spin_unlock_irq(&priv->lock); - del_timer_sync(&hw->end_timer); - del_timer_sync(&hw->suspend_timer); + timer_delete_sync(&hw->end_timer); + timer_delete_sync(&hw->suspend_timer); spin_lock_irq(&priv->lock); hw->stopping = false;
diff --git a/drivers/media/rc/img-ir/img-ir-raw.c b/drivers/media/rc/img-ir/img-ir-raw.c index 8b0bdd9..669f330 100644 --- a/drivers/media/rc/img-ir/img-ir-raw.c +++ b/drivers/media/rc/img-ir/img-ir-raw.c
@@ -147,5 +147,5 @@ void img_ir_remove_raw(struct img_ir_priv *priv) rc_unregister_device(rdev); - del_timer_sync(&raw->timer); + timer_delete_sync(&raw->timer); }
diff --git a/drivers/media/rc/imon.c b/drivers/media/rc/imon.c index 8f1361b..cb6f36e 100644 --- a/drivers/media/rc/imon.c +++ b/drivers/media/rc/imon.c
@@ -2534,7 +2534,7 @@ static void imon_disconnect(struct usb_interface *interface) ictx->dev_present_intf1 = false; usb_kill_urb(ictx->rx_urb_intf1); if (ictx->display_type == IMON_DISPLAY_TYPE_VGA) { - del_timer_sync(&ictx->ttimer); + timer_delete_sync(&ictx->ttimer); input_unregister_device(ictx->touch); } usb_put_dev(ictx->usbdev_intf1);
diff --git a/drivers/media/rc/ir-mce_kbd-decoder.c b/drivers/media/rc/ir-mce_kbd-decoder.c index 66e8feb..817030f 100644 --- a/drivers/media/rc/ir-mce_kbd-decoder.c +++ b/drivers/media/rc/ir-mce_kbd-decoder.c
@@ -324,7 +324,7 @@ static int ir_mce_kbd_decode(struct rc_dev *dev, struct ir_raw_event ev) msecs_to_jiffies(100); mod_timer(&data->rx_timeout, jiffies + delay); } else { - del_timer(&data->rx_timeout); + timer_delete(&data->rx_timeout); } /* Pass data to keyboard buffer parser */ ir_mce_kbd_process_keyboard_data(dev, scancode); @@ -372,7 +372,7 @@ static int ir_mce_kbd_unregister(struct rc_dev *dev) { struct mce_kbd_dec *mce_kbd = &dev->raw->mce_kbd; - del_timer_sync(&mce_kbd->rx_timeout); + timer_delete_sync(&mce_kbd->rx_timeout); return 0; }
diff --git a/drivers/media/rc/rc-ir-raw.c b/drivers/media/rc/rc-ir-raw.c index 16e33d7..aa4ac43 100644 --- a/drivers/media/rc/rc-ir-raw.c +++ b/drivers/media/rc/rc-ir-raw.c
@@ -662,7 +662,7 @@ void ir_raw_event_unregister(struct rc_dev *dev) return; kthread_stop(dev->raw->thread); - del_timer_sync(&dev->raw->edge_handle); + timer_delete_sync(&dev->raw->edge_handle); mutex_lock(&ir_raw_handler_lock); list_del(&dev->raw->list);
diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c index a4c539b..e46358f 100644 --- a/drivers/media/rc/rc-main.c +++ b/drivers/media/rc/rc-main.c
@@ -639,7 +639,7 @@ static void ir_do_keyup(struct rc_dev *dev, bool sync) return; dev_dbg(&dev->dev, "keyup key 0x%04x\n", dev->last_keycode); - del_timer(&dev->timer_repeat); + timer_delete(&dev->timer_repeat); input_report_key(dev->input_dev, dev->last_keycode, 0); led_trigger_event(led_feedback, LED_OFF); if (sync) @@ -2021,8 +2021,8 @@ void rc_unregister_device(struct rc_dev *dev) if (dev->driver_type == RC_DRIVER_IR_RAW) ir_raw_event_unregister(dev); - del_timer_sync(&dev->timer_keyup); - del_timer_sync(&dev->timer_repeat); + timer_delete_sync(&dev->timer_keyup); + timer_delete_sync(&dev->timer_repeat); mutex_lock(&dev->lock); if (dev->users && dev->close)
diff --git a/drivers/media/rc/serial_ir.c b/drivers/media/rc/serial_ir.c index fc5fd39..992fff8 100644 --- a/drivers/media/rc/serial_ir.c +++ b/drivers/media/rc/serial_ir.c
@@ -798,7 +798,7 @@ static int __init serial_ir_init_module(void) static void __exit serial_ir_exit_module(void) { - del_timer_sync(&serial_ir.timeout_timer); + timer_delete_sync(&serial_ir.timeout_timer); serial_ir_exit(); }
diff --git a/drivers/media/usb/au0828/au0828-dvb.c b/drivers/media/usb/au0828/au0828-dvb.c index 09f9948..3666f44 100644 --- a/drivers/media/usb/au0828/au0828-dvb.c +++ b/drivers/media/usb/au0828/au0828-dvb.c
@@ -143,7 +143,7 @@ static void urb_completion(struct urb *purb) */ dprintk(1, "%s cancelling bulk timeout\n", __func__); dev->bulk_timeout_running = 0; - del_timer(&dev->bulk_timeout); + timer_delete(&dev->bulk_timeout); } /* Feed the transport payload into the kernel demux */ @@ -168,7 +168,7 @@ static int stop_urb_transfer(struct au0828_dev *dev) if (dev->bulk_timeout_running == 1) { dev->bulk_timeout_running = 0; - del_timer(&dev->bulk_timeout); + timer_delete(&dev->bulk_timeout); } dev->urb_streaming = false;
diff --git a/drivers/media/usb/au0828/au0828-video.c b/drivers/media/usb/au0828/au0828-video.c index e9cd2a3..33d1fad 100644 --- a/drivers/media/usb/au0828/au0828-video.c +++ b/drivers/media/usb/au0828/au0828-video.c
@@ -857,7 +857,7 @@ static void au0828_stop_streaming(struct vb2_queue *vq) } dev->vid_timeout_running = 0; - del_timer_sync(&dev->vid_timeout); + timer_delete_sync(&dev->vid_timeout); spin_lock_irqsave(&dev->slock, flags); if (dev->isoc_ctl.buf != NULL) { @@ -905,7 +905,7 @@ void au0828_stop_vbi_streaming(struct vb2_queue *vq) spin_unlock_irqrestore(&dev->slock, flags); dev->vbi_timeout_running = 0; - del_timer_sync(&dev->vbi_timeout); + timer_delete_sync(&dev->vbi_timeout); } static const struct vb2_ops au0828_video_qops = { @@ -1040,12 +1040,12 @@ static int au0828_v4l2_close(struct file *filp) if (vdev->vfl_type == VFL_TYPE_VIDEO && dev->vid_timeout_running) { /* Cancel timeout thread in case they didn't call streamoff */ dev->vid_timeout_running = 0; - del_timer_sync(&dev->vid_timeout); + timer_delete_sync(&dev->vid_timeout); } else if (vdev->vfl_type == VFL_TYPE_VBI && dev->vbi_timeout_running) { /* Cancel timeout thread in case they didn't call streamoff */ dev->vbi_timeout_running = 0; - del_timer_sync(&dev->vbi_timeout); + timer_delete_sync(&dev->vbi_timeout); } if (test_bit(DEV_DISCONNECTED, &dev->dev_state)) @@ -1694,9 +1694,9 @@ void au0828_v4l2_suspend(struct au0828_dev *dev) } if (dev->vid_timeout_running) - del_timer_sync(&dev->vid_timeout); + timer_delete_sync(&dev->vid_timeout); if (dev->vbi_timeout_running) - del_timer_sync(&dev->vbi_timeout); + timer_delete_sync(&dev->vbi_timeout); } void au0828_v4l2_resume(struct au0828_dev *dev)
diff --git a/drivers/media/usb/pvrusb2/pvrusb2-encoder.c b/drivers/media/usb/pvrusb2/pvrusb2-encoder.c index c810277..a5eabac 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-encoder.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-encoder.c
@@ -257,7 +257,7 @@ rdData[0]); ret = -EBUSY; } if (ret) { - del_timer_sync(&hdw->encoder_run_timer); + timer_delete_sync(&hdw->encoder_run_timer); hdw->state_encoder_ok = 0; pvr2_trace(PVR2_TRACE_STBITS, "State bit %s <-- %s",
diff --git a/drivers/media/usb/pvrusb2/pvrusb2-hdw.c b/drivers/media/usb/pvrusb2/pvrusb2-hdw.c index 29cc207..9a583ee 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-hdw.c
@@ -1527,7 +1527,7 @@ int pvr2_upload_firmware2(struct pvr2_hdw *hdw) /* Encoder is about to be reset so note that as far as we're concerned now, the encoder has never been run. */ - del_timer_sync(&hdw->encoder_run_timer); + timer_delete_sync(&hdw->encoder_run_timer); if (hdw->state_encoder_runok) { hdw->state_encoder_runok = 0; trace_stbit("state_encoder_runok",hdw->state_encoder_runok); @@ -3724,7 +3724,7 @@ status); hdw->cmd_debug_state = 5; /* Stop timer */ - del_timer_sync(&timer.timer); + timer_delete_sync(&timer.timer); hdw->cmd_debug_state = 6; status = 0; @@ -4248,7 +4248,7 @@ static int state_eval_encoder_config(struct pvr2_hdw *hdw) hdw->state_encoder_waitok = 0; trace_stbit("state_encoder_waitok",hdw->state_encoder_waitok); /* paranoia - solve race if timer just completed */ - del_timer_sync(&hdw->encoder_wait_timer); + timer_delete_sync(&hdw->encoder_wait_timer); } else { if (!hdw->state_pathway_ok || (hdw->pathway_state != PVR2_PATHWAY_ANALOG) || @@ -4261,7 +4261,7 @@ static int state_eval_encoder_config(struct pvr2_hdw *hdw) anything has happened that might have disturbed the encoder. This should be a rare case. */ if (timer_pending(&hdw->encoder_wait_timer)) { - del_timer_sync(&hdw->encoder_wait_timer); + timer_delete_sync(&hdw->encoder_wait_timer); } if (hdw->state_encoder_waitok) { /* Must clear the state - therefore we did @@ -4399,7 +4399,7 @@ static int state_eval_encoder_run(struct pvr2_hdw *hdw) if (hdw->state_encoder_run) { if (!state_check_disable_encoder_run(hdw)) return 0; if (hdw->state_encoder_ok) { - del_timer_sync(&hdw->encoder_run_timer); + timer_delete_sync(&hdw->encoder_run_timer); if (pvr2_encoder_stop(hdw) < 0) return !0; } hdw->state_encoder_run = 0; @@ -4479,11 +4479,11 @@ static int state_eval_decoder_run(struct pvr2_hdw *hdw) hdw->state_decoder_quiescent = 0; hdw->state_decoder_run = 0; /* paranoia - solve race if timer(s) just completed */ - del_timer_sync(&hdw->quiescent_timer); + timer_delete_sync(&hdw->quiescent_timer); /* Kill the stabilization timer, in case we're killing the encoder before the previous stabilization interval has been properly timed. */ - del_timer_sync(&hdw->decoder_stabilization_timer); + timer_delete_sync(&hdw->decoder_stabilization_timer); hdw->state_decoder_ready = 0; } else { if (!hdw->state_decoder_quiescent) { @@ -4517,7 +4517,7 @@ static int state_eval_decoder_run(struct pvr2_hdw *hdw) !hdw->state_pipeline_config || !hdw->state_encoder_config || !hdw->state_encoder_ok) return 0; - del_timer_sync(&hdw->quiescent_timer); + timer_delete_sync(&hdw->quiescent_timer); if (hdw->flag_decoder_missed) return 0; if (pvr2_decoder_enable(hdw,!0) < 0) return 0; hdw->state_decoder_quiescent = 0;
diff --git a/drivers/memory/tegra/tegra210-emc-core.c b/drivers/memory/tegra/tegra210-emc-core.c index 2d5d824..e63f626 100644 --- a/drivers/memory/tegra/tegra210-emc-core.c +++ b/drivers/memory/tegra/tegra210-emc-core.c
@@ -583,7 +583,7 @@ static void tegra210_emc_training_start(struct tegra210_emc *emc) static void tegra210_emc_training_stop(struct tegra210_emc *emc) { - del_timer(&emc->training); + timer_delete(&emc->training); } static unsigned int tegra210_emc_get_temperature(struct tegra210_emc *emc) @@ -666,7 +666,7 @@ static void tegra210_emc_poll_refresh(struct timer_list *timer) static void tegra210_emc_poll_refresh_stop(struct tegra210_emc *emc) { atomic_set(&emc->refresh_poll, 0); - del_timer_sync(&emc->refresh_timer); + timer_delete_sync(&emc->refresh_timer); } static void tegra210_emc_poll_refresh_start(struct tegra210_emc *emc)
diff --git a/drivers/memstick/core/ms_block.c b/drivers/memstick/core/ms_block.c index f439838..7dc2c99 100644 --- a/drivers/memstick/core/ms_block.c +++ b/drivers/memstick/core/ms_block.c
@@ -1510,7 +1510,7 @@ static void msb_cache_discard(struct msb_data *msb) if (msb->cache_block_lba == MS_BLOCK_INVALID) return; - del_timer_sync(&msb->cache_flush_timer); + timer_delete_sync(&msb->cache_flush_timer); dbg_verbose("Discarding the write cache"); msb->cache_block_lba = MS_BLOCK_INVALID; @@ -2027,7 +2027,7 @@ static void msb_stop(struct memstick_dev *card) msb->io_queue_stopped = true; spin_unlock_irqrestore(&msb->q_lock, flags); - del_timer_sync(&msb->cache_flush_timer); + timer_delete_sync(&msb->cache_flush_timer); flush_workqueue(msb->io_queue); spin_lock_irqsave(&msb->q_lock, flags);
diff --git a/drivers/memstick/host/jmb38x_ms.c b/drivers/memstick/host/jmb38x_ms.c index e77eb8b..a5a9bb3 100644 --- a/drivers/memstick/host/jmb38x_ms.c +++ b/drivers/memstick/host/jmb38x_ms.c
@@ -469,7 +469,7 @@ static void jmb38x_ms_complete_cmd(struct memstick_host *msh, int last) unsigned int t_val = 0; int rc; - del_timer(&host->timer); + timer_delete(&host->timer); dev_dbg(&msh->dev, "c control %08x\n", readl(host->addr + HOST_CONTROL));
diff --git a/drivers/memstick/host/r592.c b/drivers/memstick/host/r592.c index 544a31f..488ef8e 100644 --- a/drivers/memstick/host/r592.c +++ b/drivers/memstick/host/r592.c
@@ -827,7 +827,7 @@ static void r592_remove(struct pci_dev *pdev) /* Stop the processing thread. That ensures that we won't take any more requests */ kthread_stop(dev->io_thread); - del_timer_sync(&dev->detect_timer); + timer_delete_sync(&dev->detect_timer); r592_enable_device(dev, false); while (!error && dev->req) { @@ -854,7 +854,7 @@ static int r592_suspend(struct device *core_dev) r592_clear_interrupts(dev); memstick_suspend_host(dev->host); - del_timer_sync(&dev->detect_timer); + timer_delete_sync(&dev->detect_timer); return 0; }
diff --git a/drivers/memstick/host/tifm_ms.c b/drivers/memstick/host/tifm_ms.c index c272453..676348e 100644 --- a/drivers/memstick/host/tifm_ms.c +++ b/drivers/memstick/host/tifm_ms.c
@@ -337,7 +337,7 @@ static void tifm_ms_complete_cmd(struct tifm_ms *host) struct memstick_host *msh = tifm_get_drvdata(sock); int rc; - del_timer(&host->timer); + timer_delete(&host->timer); host->req->int_reg = readl(sock->addr + SOCK_MS_STATUS) & 0xff; host->req->int_reg = (host->req->int_reg & 1) @@ -600,7 +600,7 @@ static void tifm_ms_remove(struct tifm_dev *sock) spin_lock_irqsave(&sock->lock, flags); host->eject = 1; if (host->req) { - del_timer(&host->timer); + timer_delete(&host->timer); writel(TIFM_FIFO_INT_SETALL, sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR); writel(TIFM_DMA_RESET, sock->addr + SOCK_DMA_CONTROL);
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 56bc72c..6b37d61 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig
@@ -641,7 +641,6 @@ source "drivers/misc/vmw_vmci/Kconfig" source "drivers/misc/genwqe/Kconfig" source "drivers/misc/echo/Kconfig" -source "drivers/misc/cxl/Kconfig" source "drivers/misc/ocxl/Kconfig" source "drivers/misc/bcm-vk/Kconfig" source "drivers/misc/cardreader/Kconfig"
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 545aad0..d6c9172 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile
@@ -50,7 +50,6 @@ obj-$(CONFIG_SRAM_EXEC) += sram-exec.o obj-$(CONFIG_GENWQE) += genwqe/ obj-$(CONFIG_ECHO) += echo/ -obj-$(CONFIG_CXL_BASE) += cxl/ obj-$(CONFIG_DW_XDATA_PCIE) += dw-xdata-pcie.o obj-$(CONFIG_PCI_ENDPOINT_TEST) += pci_endpoint_test.o obj-$(CONFIG_OCXL) += ocxl/
diff --git a/drivers/misc/bcm-vk/bcm_vk_tty.c b/drivers/misc/bcm-vk/bcm_vk_tty.c index 59bab76..44a2dd8 100644 --- a/drivers/misc/bcm-vk/bcm_vk_tty.c +++ b/drivers/misc/bcm-vk/bcm_vk_tty.c
@@ -177,7 +177,7 @@ static void bcm_vk_tty_close(struct tty_struct *tty, struct file *file) vk->tty[tty->index].is_opened = false; if (tty->count == 1) - del_timer_sync(&vk->serial_timer); + timer_delete_sync(&vk->serial_timer); } static void bcm_vk_tty_doorbell(struct bcm_vk *vk, u32 db_val) @@ -304,7 +304,7 @@ void bcm_vk_tty_exit(struct bcm_vk *vk) { int i; - del_timer_sync(&vk->serial_timer); + timer_delete_sync(&vk->serial_timer); for (i = 0; i < BCM_VK_NUM_TTY; ++i) { tty_port_unregister_device(&vk->tty[i].port, vk->tty_drv,
diff --git a/drivers/misc/cardreader/rtsx_usb.c b/drivers/misc/cardreader/rtsx_usb.c index 77b0490..7314c8d 100644 --- a/drivers/misc/cardreader/rtsx_usb.c +++ b/drivers/misc/cardreader/rtsx_usb.c
@@ -53,7 +53,7 @@ static int rtsx_usb_bulk_transfer_sglist(struct rtsx_ucr *ucr, ucr->sg_timer.expires = jiffies + msecs_to_jiffies(timeout); add_timer(&ucr->sg_timer); usb_sg_wait(&ucr->current_sg); - if (!del_timer_sync(&ucr->sg_timer)) + if (!timer_delete_sync(&ucr->sg_timer)) ret = -ETIMEDOUT; else ret = ucr->current_sg.status;
diff --git a/drivers/misc/cxl/Kconfig b/drivers/misc/cxl/Kconfig deleted file mode 100644 index 15307f5e..0000000 --- a/drivers/misc/cxl/Kconfig +++ /dev/null
@@ -1,28 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -# -# IBM Coherent Accelerator (CXL) compatible devices -# - -config CXL_BASE - bool - select PPC_COPRO_BASE - select PPC_64S_HASH_MMU - -config CXL - tristate "Support for IBM Coherent Accelerators (CXL) (DEPRECATED)" - depends on PPC_POWERNV && PCI_MSI && EEH - select CXL_BASE - help - The cxl driver is deprecated and will be removed in a future - kernel release. - - Select this option to enable driver support for IBM Coherent - Accelerators (CXL). CXL is otherwise known as Coherent Accelerator - Processor Interface (CAPI). CAPI allows accelerators in FPGAs to be - coherently attached to a CPU via an MMU. This driver enables - userspace programs to access these accelerators via /dev/cxl/afuM.N - devices. - - CAPI adapters are found in POWER8 based systems. - - If unsure, say N.
diff --git a/drivers/misc/cxl/Makefile b/drivers/misc/cxl/Makefile deleted file mode 100644 index 5eea61b..0000000 --- a/drivers/misc/cxl/Makefile +++ /dev/null
@@ -1,14 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -ccflags-y := $(call cc-disable-warning, unused-const-variable) -ccflags-$(CONFIG_PPC_WERROR) += -Werror - -cxl-y += main.o file.o irq.o fault.o native.o -cxl-y += context.o sysfs.o pci.o trace.o -cxl-y += vphb.o api.o cxllib.o -cxl-$(CONFIG_PPC_PSERIES) += flash.o guest.o of.o hcalls.o -cxl-$(CONFIG_DEBUG_FS) += debugfs.o -obj-$(CONFIG_CXL) += cxl.o -obj-$(CONFIG_CXL_BASE) += base.o - -# For tracepoints to include our trace.h from tracepoint infrastructure: -CFLAGS_trace.o := -I$(src)
diff --git a/drivers/misc/cxl/api.c b/drivers/misc/cxl/api.c deleted file mode 100644 index d85c565..0000000 --- a/drivers/misc/cxl/api.c +++ /dev/null
@@ -1,532 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Copyright 2014 IBM Corp. - */ - -#include <linux/pci.h> -#include <linux/slab.h> -#include <linux/file.h> -#include <misc/cxl.h> -#include <linux/module.h> -#include <linux/mount.h> -#include <linux/pseudo_fs.h> -#include <linux/sched/mm.h> -#include <linux/mmu_context.h> -#include <linux/irqdomain.h> - -#include "cxl.h" - -/* - * Since we want to track memory mappings to be able to force-unmap - * when the AFU is no longer reachable, we need an inode. For devices - * opened through the cxl user API, this is not a problem, but a - * userland process can also get a cxl fd through the cxl_get_fd() - * API, which is used by the cxlflash driver. - * - * Therefore we implement our own simple pseudo-filesystem and inode - * allocator. We don't use the anonymous inode, as we need the - * meta-data associated with it (address_space) and it is shared by - * other drivers/processes, so it could lead to cxl unmapping VMAs - * from random processes. - */ - -#define CXL_PSEUDO_FS_MAGIC 0x1697697f - -static int cxl_fs_cnt; -static struct vfsmount *cxl_vfs_mount; - -static int cxl_fs_init_fs_context(struct fs_context *fc) -{ - return init_pseudo(fc, CXL_PSEUDO_FS_MAGIC) ? 0 : -ENOMEM; -} - -static struct file_system_type cxl_fs_type = { - .name = "cxl", - .owner = THIS_MODULE, - .init_fs_context = cxl_fs_init_fs_context, - .kill_sb = kill_anon_super, -}; - - -void cxl_release_mapping(struct cxl_context *ctx) -{ - if (ctx->kernelapi && ctx->mapping) - simple_release_fs(&cxl_vfs_mount, &cxl_fs_cnt); -} - -static struct file *cxl_getfile(const char *name, - const struct file_operations *fops, - void *priv, int flags) -{ - struct file *file; - struct inode *inode; - int rc; - - /* strongly inspired by anon_inode_getfile() */ - - if (fops->owner && !try_module_get(fops->owner)) - return ERR_PTR(-ENOENT); - - rc = simple_pin_fs(&cxl_fs_type, &cxl_vfs_mount, &cxl_fs_cnt); - if (rc < 0) { - pr_err("Cannot mount cxl pseudo filesystem: %d\n", rc); - file = ERR_PTR(rc); - goto err_module; - } - - inode = alloc_anon_inode(cxl_vfs_mount->mnt_sb); - if (IS_ERR(inode)) { - file = ERR_CAST(inode); - goto err_fs; - } - - file = alloc_file_pseudo(inode, cxl_vfs_mount, name, - flags & (O_ACCMODE | O_NONBLOCK), fops); - if (IS_ERR(file)) - goto err_inode; - - file->private_data = priv; - - return file; - -err_inode: - iput(inode); -err_fs: - simple_release_fs(&cxl_vfs_mount, &cxl_fs_cnt); -err_module: - module_put(fops->owner); - return file; -} - -struct cxl_context *cxl_dev_context_init(struct pci_dev *dev) -{ - struct cxl_afu *afu; - struct cxl_context *ctx; - int rc; - - afu = cxl_pci_to_afu(dev); - if (IS_ERR(afu)) - return ERR_CAST(afu); - - ctx = cxl_context_alloc(); - if (!ctx) - return ERR_PTR(-ENOMEM); - - ctx->kernelapi = true; - - /* Make it a slave context. We can promote it later? */ - rc = cxl_context_init(ctx, afu, false); - if (rc) - goto err_ctx; - - return ctx; - -err_ctx: - kfree(ctx); - return ERR_PTR(rc); -} -EXPORT_SYMBOL_GPL(cxl_dev_context_init); - -struct cxl_context *cxl_get_context(struct pci_dev *dev) -{ - return dev->dev.archdata.cxl_ctx; -} -EXPORT_SYMBOL_GPL(cxl_get_context); - -int cxl_release_context(struct cxl_context *ctx) -{ - if (ctx->status >= STARTED) - return -EBUSY; - - cxl_context_free(ctx); - - return 0; -} -EXPORT_SYMBOL_GPL(cxl_release_context); - -static irq_hw_number_t cxl_find_afu_irq(struct cxl_context *ctx, int num) -{ - __u16 range; - int r; - - for (r = 0; r < CXL_IRQ_RANGES; r++) { - range = ctx->irqs.range[r]; - if (num < range) { - return ctx->irqs.offset[r] + num; - } - num -= range; - } - return 0; -} - - -int cxl_set_priv(struct cxl_context *ctx, void *priv) -{ - if (!ctx) - return -EINVAL; - - ctx->priv = priv; - - return 0; -} -EXPORT_SYMBOL_GPL(cxl_set_priv); - -void *cxl_get_priv(struct cxl_context *ctx) -{ - if (!ctx) - return ERR_PTR(-EINVAL); - - return ctx->priv; -} -EXPORT_SYMBOL_GPL(cxl_get_priv); - -int cxl_allocate_afu_irqs(struct cxl_context *ctx, int num) -{ - int res; - irq_hw_number_t hwirq; - - if (num == 0) - num = ctx->afu->pp_irqs; - res = afu_allocate_irqs(ctx, num); - if (res) - return res; - - if (!cpu_has_feature(CPU_FTR_HVMODE)) { - /* In a guest, the PSL interrupt is not multiplexed. It was - * allocated above, and we need to set its handler - */ - hwirq = cxl_find_afu_irq(ctx, 0); - if (hwirq) - cxl_map_irq(ctx->afu->adapter, hwirq, cxl_ops->psl_interrupt, ctx, "psl"); - } - - if (ctx->status == STARTED) { - if (cxl_ops->update_ivtes) - cxl_ops->update_ivtes(ctx); - else WARN(1, "BUG: cxl_allocate_afu_irqs must be called prior to starting the context on this platform\n"); - } - - return res; -} -EXPORT_SYMBOL_GPL(cxl_allocate_afu_irqs); - -void cxl_free_afu_irqs(struct cxl_context *ctx) -{ - irq_hw_number_t hwirq; - unsigned int virq; - - if (!cpu_has_feature(CPU_FTR_HVMODE)) { - hwirq = cxl_find_afu_irq(ctx, 0); - if (hwirq) { - virq = irq_find_mapping(NULL, hwirq); - if (virq) - cxl_unmap_irq(virq, ctx); - } - } - afu_irq_name_free(ctx); - cxl_ops->release_irq_ranges(&ctx->irqs, ctx->afu->adapter); -} -EXPORT_SYMBOL_GPL(cxl_free_afu_irqs); - -int cxl_map_afu_irq(struct cxl_context *ctx, int num, - irq_handler_t handler, void *cookie, char *name) -{ - irq_hw_number_t hwirq; - - /* - * Find interrupt we are to register. - */ - hwirq = cxl_find_afu_irq(ctx, num); - if (!hwirq) - return -ENOENT; - - return cxl_map_irq(ctx->afu->adapter, hwirq, handler, cookie, name); -} -EXPORT_SYMBOL_GPL(cxl_map_afu_irq); - -void cxl_unmap_afu_irq(struct cxl_context *ctx, int num, void *cookie) -{ - irq_hw_number_t hwirq; - unsigned int virq; - - hwirq = cxl_find_afu_irq(ctx, num); - if (!hwirq) - return; - - virq = irq_find_mapping(NULL, hwirq); - if (virq) - cxl_unmap_irq(virq, cookie); -} -EXPORT_SYMBOL_GPL(cxl_unmap_afu_irq); - -/* - * Start a context - * Code here similar to afu_ioctl_start_work(). - */ -int cxl_start_context(struct cxl_context *ctx, u64 wed, - struct task_struct *task) -{ - int rc = 0; - bool kernel = true; - - pr_devel("%s: pe: %i\n", __func__, ctx->pe); - - mutex_lock(&ctx->status_mutex); - if (ctx->status == STARTED) - goto out; /* already started */ - - /* - * Increment the mapped context count for adapter. This also checks - * if adapter_context_lock is taken. - */ - rc = cxl_adapter_context_get(ctx->afu->adapter); - if (rc) - goto out; - - if (task) { - ctx->pid = get_task_pid(task, PIDTYPE_PID); - kernel = false; - - /* acquire a reference to the task's mm */ - ctx->mm = get_task_mm(current); - - /* ensure this mm_struct can't be freed */ - cxl_context_mm_count_get(ctx); - - if (ctx->mm) { - /* decrement the use count from above */ - mmput(ctx->mm); - /* make TLBIs for this context global */ - mm_context_add_copro(ctx->mm); - } - } - - /* - * Increment driver use count. Enables global TLBIs for hash - * and callbacks to handle the segment table - */ - cxl_ctx_get(); - - /* See the comment in afu_ioctl_start_work() */ - smp_mb(); - - if ((rc = cxl_ops->attach_process(ctx, kernel, wed, 0))) { - put_pid(ctx->pid); - ctx->pid = NULL; - cxl_adapter_context_put(ctx->afu->adapter); - cxl_ctx_put(); - if (task) { - cxl_context_mm_count_put(ctx); - if (ctx->mm) - mm_context_remove_copro(ctx->mm); - } - goto out; - } - - ctx->status = STARTED; -out: - mutex_unlock(&ctx->status_mutex); - return rc; -} -EXPORT_SYMBOL_GPL(cxl_start_context); - -int cxl_process_element(struct cxl_context *ctx) -{ - return ctx->external_pe; -} -EXPORT_SYMBOL_GPL(cxl_process_element); - -/* Stop a context. Returns 0 on success, otherwise -Errno */ -int cxl_stop_context(struct cxl_context *ctx) -{ - return __detach_context(ctx); -} -EXPORT_SYMBOL_GPL(cxl_stop_context); - -void cxl_set_master(struct cxl_context *ctx) -{ - ctx->master = true; -} -EXPORT_SYMBOL_GPL(cxl_set_master); - -/* wrappers around afu_* file ops which are EXPORTED */ -int cxl_fd_open(struct inode *inode, struct file *file) -{ - return afu_open(inode, file); -} -EXPORT_SYMBOL_GPL(cxl_fd_open); -int cxl_fd_release(struct inode *inode, struct file *file) -{ - return afu_release(inode, file); -} -EXPORT_SYMBOL_GPL(cxl_fd_release); -long cxl_fd_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -{ - return afu_ioctl(file, cmd, arg); -} -EXPORT_SYMBOL_GPL(cxl_fd_ioctl); -int cxl_fd_mmap(struct file *file, struct vm_area_struct *vm) -{ - return afu_mmap(file, vm); -} -EXPORT_SYMBOL_GPL(cxl_fd_mmap); -__poll_t cxl_fd_poll(struct file *file, struct poll_table_struct *poll) -{ - return afu_poll(file, poll); -} -EXPORT_SYMBOL_GPL(cxl_fd_poll); -ssize_t cxl_fd_read(struct file *file, char __user *buf, size_t count, - loff_t *off) -{ - return afu_read(file, buf, count, off); -} -EXPORT_SYMBOL_GPL(cxl_fd_read); - -#define PATCH_FOPS(NAME) if (!fops->NAME) fops->NAME = afu_fops.NAME - -/* Get a struct file and fd for a context and attach the ops */ -struct file *cxl_get_fd(struct cxl_context *ctx, struct file_operations *fops, - int *fd) -{ - struct file *file; - int rc, flags, fdtmp; - char *name = NULL; - - /* only allow one per context */ - if (ctx->mapping) - return ERR_PTR(-EEXIST); - - flags = O_RDWR | O_CLOEXEC; - - /* This code is similar to anon_inode_getfd() */ - rc = get_unused_fd_flags(flags); - if (rc < 0) - return ERR_PTR(rc); - fdtmp = rc; - - /* - * Patch the file ops. Needs to be careful that this is rentrant safe. - */ - if (fops) { - PATCH_FOPS(open); - PATCH_FOPS(poll); - PATCH_FOPS(read); - PATCH_FOPS(release); - PATCH_FOPS(unlocked_ioctl); - PATCH_FOPS(compat_ioctl); - PATCH_FOPS(mmap); - } else /* use default ops */ - fops = (struct file_operations *)&afu_fops; - - name = kasprintf(GFP_KERNEL, "cxl:%d", ctx->pe); - file = cxl_getfile(name, fops, ctx, flags); - kfree(name); - if (IS_ERR(file)) - goto err_fd; - - cxl_context_set_mapping(ctx, file->f_mapping); - *fd = fdtmp; - return file; - -err_fd: - put_unused_fd(fdtmp); - return NULL; -} -EXPORT_SYMBOL_GPL(cxl_get_fd); - -struct cxl_context *cxl_fops_get_context(struct file *file) -{ - return file->private_data; -} -EXPORT_SYMBOL_GPL(cxl_fops_get_context); - -void cxl_set_driver_ops(struct cxl_context *ctx, - struct cxl_afu_driver_ops *ops) -{ - WARN_ON(!ops->fetch_event || !ops->event_delivered); - atomic_set(&ctx->afu_driver_events, 0); - ctx->afu_driver_ops = ops; -} -EXPORT_SYMBOL_GPL(cxl_set_driver_ops); - -void cxl_context_events_pending(struct cxl_context *ctx, - unsigned int new_events) -{ - atomic_add(new_events, &ctx->afu_driver_events); - wake_up_all(&ctx->wq); -} -EXPORT_SYMBOL_GPL(cxl_context_events_pending); - -int cxl_start_work(struct cxl_context *ctx, - struct cxl_ioctl_start_work *work) -{ - int rc; - - /* code taken from afu_ioctl_start_work */ - if (!(work->flags & CXL_START_WORK_NUM_IRQS)) - work->num_interrupts = ctx->afu->pp_irqs; - else if ((work->num_interrupts < ctx->afu->pp_irqs) || - (work->num_interrupts > ctx->afu->irqs_max)) { - return -EINVAL; - } - - rc = afu_register_irqs(ctx, work->num_interrupts); - if (rc) - return rc; - - rc = cxl_start_context(ctx, work->work_element_descriptor, current); - if (rc < 0) { - afu_release_irqs(ctx, ctx); - return rc; - } - - return 0; -} -EXPORT_SYMBOL_GPL(cxl_start_work); - -void __iomem *cxl_psa_map(struct cxl_context *ctx) -{ - if (ctx->status != STARTED) - return NULL; - - pr_devel("%s: psn_phys%llx size:%llx\n", - __func__, ctx->psn_phys, ctx->psn_size); - return ioremap(ctx->psn_phys, ctx->psn_size); -} -EXPORT_SYMBOL_GPL(cxl_psa_map); - -void cxl_psa_unmap(void __iomem *addr) -{ - iounmap(addr); -} -EXPORT_SYMBOL_GPL(cxl_psa_unmap); - -int cxl_afu_reset(struct cxl_context *ctx) -{ - struct cxl_afu *afu = ctx->afu; - int rc; - - rc = cxl_ops->afu_reset(afu); - if (rc) - return rc; - - return cxl_ops->afu_check_and_enable(afu); -} -EXPORT_SYMBOL_GPL(cxl_afu_reset); - -void cxl_perst_reloads_same_image(struct cxl_afu *afu, - bool perst_reloads_same_image) -{ - afu->adapter->perst_same_image = perst_reloads_same_image; -} -EXPORT_SYMBOL_GPL(cxl_perst_reloads_same_image); - -ssize_t cxl_read_adapter_vpd(struct pci_dev *dev, void *buf, size_t count) -{ - struct cxl_afu *afu = cxl_pci_to_afu(dev); - if (IS_ERR(afu)) - return -ENODEV; - - return cxl_ops->read_adapter_vpd(afu->adapter, buf, count); -} -EXPORT_SYMBOL_GPL(cxl_read_adapter_vpd);
diff --git a/drivers/misc/cxl/base.c b/drivers/misc/cxl/base.c deleted file mode 100644 index b054562..0000000 --- a/drivers/misc/cxl/base.c +++ /dev/null
@@ -1,126 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Copyright 2014 IBM Corp. - */ - -#include <linux/module.h> -#include <linux/rcupdate.h> -#include <asm/errno.h> -#include <misc/cxl-base.h> -#include <linux/of.h> -#include <linux/of_platform.h> -#include "cxl.h" - -/* protected by rcu */ -static struct cxl_calls *cxl_calls; - -atomic_t cxl_use_count = ATOMIC_INIT(0); -EXPORT_SYMBOL(cxl_use_count); - -#ifdef CONFIG_CXL_MODULE - -static inline struct cxl_calls *cxl_calls_get(void) -{ - struct cxl_calls *calls = NULL; - - rcu_read_lock(); - calls = rcu_dereference(cxl_calls); - if (calls && !try_module_get(calls->owner)) - calls = NULL; - rcu_read_unlock(); - - return calls; -} - -static inline void cxl_calls_put(struct cxl_calls *calls) -{ - BUG_ON(calls != cxl_calls); - - /* we don't need to rcu this, as we hold a reference to the module */ - module_put(cxl_calls->owner); -} - -#else /* !defined CONFIG_CXL_MODULE */ - -static inline struct cxl_calls *cxl_calls_get(void) -{ - return cxl_calls; -} - -static inline void cxl_calls_put(struct cxl_calls *calls) { } - -#endif /* CONFIG_CXL_MODULE */ - -/* AFU refcount management */ -struct cxl_afu *cxl_afu_get(struct cxl_afu *afu) -{ - return (get_device(&afu->dev) == NULL) ? NULL : afu; -} -EXPORT_SYMBOL_GPL(cxl_afu_get); - -void cxl_afu_put(struct cxl_afu *afu) -{ - put_device(&afu->dev); -} -EXPORT_SYMBOL_GPL(cxl_afu_put); - -void cxl_slbia(struct mm_struct *mm) -{ - struct cxl_calls *calls; - - calls = cxl_calls_get(); - if (!calls) - return; - - if (cxl_ctx_in_use()) - calls->cxl_slbia(mm); - - cxl_calls_put(calls); -} - -int register_cxl_calls(struct cxl_calls *calls) -{ - if (cxl_calls) - return -EBUSY; - - rcu_assign_pointer(cxl_calls, calls); - return 0; -} -EXPORT_SYMBOL_GPL(register_cxl_calls); - -void unregister_cxl_calls(struct cxl_calls *calls) -{ - BUG_ON(cxl_calls->owner != calls->owner); - RCU_INIT_POINTER(cxl_calls, NULL); - synchronize_rcu(); -} -EXPORT_SYMBOL_GPL(unregister_cxl_calls); - -int cxl_update_properties(struct device_node *dn, - struct property *new_prop) -{ - return of_update_property(dn, new_prop); -} -EXPORT_SYMBOL_GPL(cxl_update_properties); - -static int __init cxl_base_init(void) -{ - struct device_node *np; - struct platform_device *dev; - int count = 0; - - /* - * Scan for compatible devices in guest only - */ - if (cpu_has_feature(CPU_FTR_HVMODE)) - return 0; - - for_each_compatible_node(np, NULL, "ibm,coherent-platform-facility") { - dev = of_platform_device_create(np, NULL, NULL); - if (dev) - count++; - } - pr_devel("Found %d cxl device(s)\n", count); - return 0; -} -device_initcall(cxl_base_init);
diff --git a/drivers/misc/cxl/context.c b/drivers/misc/cxl/context.c deleted file mode 100644 index 76b5ea6..0000000 --- a/drivers/misc/cxl/context.c +++ /dev/null
@@ -1,362 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Copyright 2014 IBM Corp. - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/bitmap.h> -#include <linux/sched.h> -#include <linux/pid.h> -#include <linux/fs.h> -#include <linux/mm.h> -#include <linux/debugfs.h> -#include <linux/slab.h> -#include <linux/idr.h> -#include <linux/sched/mm.h> -#include <linux/mmu_context.h> -#include <asm/cputable.h> -#include <asm/current.h> -#include <asm/copro.h> - -#include "cxl.h" - -/* - * Allocates space for a CXL context. - */ -struct cxl_context *cxl_context_alloc(void) -{ - return kzalloc(sizeof(struct cxl_context), GFP_KERNEL); -} - -/* - * Initialises a CXL context. - */ -int cxl_context_init(struct cxl_context *ctx, struct cxl_afu *afu, bool master) -{ - int i; - - ctx->afu = afu; - ctx->master = master; - ctx->pid = NULL; /* Set in start work ioctl */ - mutex_init(&ctx->mapping_lock); - ctx->mapping = NULL; - ctx->tidr = 0; - ctx->assign_tidr = false; - - if (cxl_is_power8()) { - spin_lock_init(&ctx->sste_lock); - - /* - * Allocate the segment table before we put it in the IDR so that we - * can always access it when dereferenced from IDR. For the same - * reason, the segment table is only destroyed after the context is - * removed from the IDR. Access to this in the IOCTL is protected by - * Linux filesystem semantics (can't IOCTL until open is complete). - */ - i = cxl_alloc_sst(ctx); - if (i) - return i; - } - - INIT_WORK(&ctx->fault_work, cxl_handle_fault); - - init_waitqueue_head(&ctx->wq); - spin_lock_init(&ctx->lock); - - ctx->irq_bitmap = NULL; - ctx->pending_irq = false; - ctx->pending_fault = false; - ctx->pending_afu_err = false; - - INIT_LIST_HEAD(&ctx->irq_names); - - /* - * When we have to destroy all contexts in cxl_context_detach_all() we - * end up with afu_release_irqs() called from inside a - * idr_for_each_entry(). Hence we need to make sure that anything - * dereferenced from this IDR is ok before we allocate the IDR here. - * This clears out the IRQ ranges to ensure this. - */ - for (i = 0; i < CXL_IRQ_RANGES; i++) - ctx->irqs.range[i] = 0; - - mutex_init(&ctx->status_mutex); - - ctx->status = OPENED; - - /* - * Allocating IDR! We better make sure everything's setup that - * dereferences from it. - */ - mutex_lock(&afu->contexts_lock); - idr_preload(GFP_KERNEL); - i = idr_alloc(&ctx->afu->contexts_idr, ctx, 0, - ctx->afu->num_procs, GFP_NOWAIT); - idr_preload_end(); - mutex_unlock(&afu->contexts_lock); - if (i < 0) - return i; - - ctx->pe = i; - if (cpu_has_feature(CPU_FTR_HVMODE)) { - ctx->elem = &ctx->afu->native->spa[i]; - ctx->external_pe = ctx->pe; - } else { - ctx->external_pe = -1; /* assigned when attaching */ - } - ctx->pe_inserted = false; - - /* - * take a ref on the afu so that it stays alive at-least till - * this context is reclaimed inside reclaim_ctx. - */ - cxl_afu_get(afu); - return 0; -} - -void cxl_context_set_mapping(struct cxl_context *ctx, - struct address_space *mapping) -{ - mutex_lock(&ctx->mapping_lock); - ctx->mapping = mapping; - mutex_unlock(&ctx->mapping_lock); -} - -static vm_fault_t cxl_mmap_fault(struct vm_fault *vmf) -{ - struct vm_area_struct *vma = vmf->vma; - struct cxl_context *ctx = vma->vm_file->private_data; - u64 area, offset; - vm_fault_t ret; - - offset = vmf->pgoff << PAGE_SHIFT; - - pr_devel("%s: pe: %i address: 0x%lx offset: 0x%llx\n", - __func__, ctx->pe, vmf->address, offset); - - if (ctx->afu->current_mode == CXL_MODE_DEDICATED) { - area = ctx->afu->psn_phys; - if (offset >= ctx->afu->adapter->ps_size) - return VM_FAULT_SIGBUS; - } else { - area = ctx->psn_phys; - if (offset >= ctx->psn_size) - return VM_FAULT_SIGBUS; - } - - mutex_lock(&ctx->status_mutex); - - if (ctx->status != STARTED) { - mutex_unlock(&ctx->status_mutex); - pr_devel("%s: Context not started, failing problem state access\n", __func__); - if (ctx->mmio_err_ff) { - if (!ctx->ff_page) { - ctx->ff_page = alloc_page(GFP_USER); - if (!ctx->ff_page) - return VM_FAULT_OOM; - memset(page_address(ctx->ff_page), 0xff, PAGE_SIZE); - } - get_page(ctx->ff_page); - vmf->page = ctx->ff_page; - vma->vm_page_prot = pgprot_cached(vma->vm_page_prot); - return 0; - } - return VM_FAULT_SIGBUS; - } - - ret = vmf_insert_pfn(vma, vmf->address, (area + offset) >> PAGE_SHIFT); - - mutex_unlock(&ctx->status_mutex); - - return ret; -} - -static const struct vm_operations_struct cxl_mmap_vmops = { - .fault = cxl_mmap_fault, -}; - -/* - * Map a per-context mmio space into the given vma. - */ -int cxl_context_iomap(struct cxl_context *ctx, struct vm_area_struct *vma) -{ - u64 start = vma->vm_pgoff << PAGE_SHIFT; - u64 len = vma->vm_end - vma->vm_start; - - if (ctx->afu->current_mode == CXL_MODE_DEDICATED) { - if (start + len > ctx->afu->adapter->ps_size) - return -EINVAL; - - if (cxl_is_power9()) { - /* - * Make sure there is a valid problem state - * area space for this AFU. - */ - if (ctx->master && !ctx->afu->psa) { - pr_devel("AFU doesn't support mmio space\n"); - return -EINVAL; - } - - /* Can't mmap until the AFU is enabled */ - if (!ctx->afu->enabled) - return -EBUSY; - } - } else { - if (start + len > ctx->psn_size) - return -EINVAL; - - /* Make sure there is a valid per process space for this AFU */ - if ((ctx->master && !ctx->afu->psa) || (!ctx->afu->pp_psa)) { - pr_devel("AFU doesn't support mmio space\n"); - return -EINVAL; - } - - /* Can't mmap until the AFU is enabled */ - if (!ctx->afu->enabled) - return -EBUSY; - } - - pr_devel("%s: mmio physical: %llx pe: %i master:%i\n", __func__, - ctx->psn_phys, ctx->pe , ctx->master); - - vm_flags_set(vma, VM_IO | VM_PFNMAP); - vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); - vma->vm_ops = &cxl_mmap_vmops; - return 0; -} - -/* - * Detach a context from the hardware. This disables interrupts and doesn't - * return until all outstanding interrupts for this context have completed. The - * hardware should no longer access *ctx after this has returned. - */ -int __detach_context(struct cxl_context *ctx) -{ - enum cxl_context_status status; - - mutex_lock(&ctx->status_mutex); - status = ctx->status; - ctx->status = CLOSED; - mutex_unlock(&ctx->status_mutex); - if (status != STARTED) - return -EBUSY; - - /* Only warn if we detached while the link was OK. - * If detach fails when hw is down, we don't care. - */ - WARN_ON(cxl_ops->detach_process(ctx) && - cxl_ops->link_ok(ctx->afu->adapter, ctx->afu)); - flush_work(&ctx->fault_work); /* Only needed for dedicated process */ - - /* - * Wait until no further interrupts are presented by the PSL - * for this context. - */ - if (cxl_ops->irq_wait) - cxl_ops->irq_wait(ctx); - - /* release the reference to the group leader and mm handling pid */ - put_pid(ctx->pid); - - cxl_ctx_put(); - - /* Decrease the attached context count on the adapter */ - cxl_adapter_context_put(ctx->afu->adapter); - - /* Decrease the mm count on the context */ - cxl_context_mm_count_put(ctx); - if (ctx->mm) - mm_context_remove_copro(ctx->mm); - ctx->mm = NULL; - - return 0; -} - -/* - * Detach the given context from the AFU. This doesn't actually - * free the context but it should stop the context running in hardware - * (ie. prevent this context from generating any further interrupts - * so that it can be freed). - */ -void cxl_context_detach(struct cxl_context *ctx) -{ - int rc; - - rc = __detach_context(ctx); - if (rc) - return; - - afu_release_irqs(ctx, ctx); - wake_up_all(&ctx->wq); -} - -/* - * Detach all contexts on the given AFU. - */ -void cxl_context_detach_all(struct cxl_afu *afu) -{ - struct cxl_context *ctx; - int tmp; - - mutex_lock(&afu->contexts_lock); - idr_for_each_entry(&afu->contexts_idr, ctx, tmp) { - /* - * Anything done in here needs to be setup before the IDR is - * created and torn down after the IDR removed - */ - cxl_context_detach(ctx); - - /* - * We are force detaching - remove any active PSA mappings so - * userspace cannot interfere with the card if it comes back. - * Easiest way to exercise this is to unbind and rebind the - * driver via sysfs while it is in use. - */ - mutex_lock(&ctx->mapping_lock); - if (ctx->mapping) - unmap_mapping_range(ctx->mapping, 0, 0, 1); - mutex_unlock(&ctx->mapping_lock); - } - mutex_unlock(&afu->contexts_lock); -} - -static void reclaim_ctx(struct rcu_head *rcu) -{ - struct cxl_context *ctx = container_of(rcu, struct cxl_context, rcu); - - if (cxl_is_power8()) - free_page((u64)ctx->sstp); - if (ctx->ff_page) - __free_page(ctx->ff_page); - ctx->sstp = NULL; - - bitmap_free(ctx->irq_bitmap); - - /* Drop ref to the afu device taken during cxl_context_init */ - cxl_afu_put(ctx->afu); - - kfree(ctx); -} - -void cxl_context_free(struct cxl_context *ctx) -{ - if (ctx->kernelapi && ctx->mapping) - cxl_release_mapping(ctx); - mutex_lock(&ctx->afu->contexts_lock); - idr_remove(&ctx->afu->contexts_idr, ctx->pe); - mutex_unlock(&ctx->afu->contexts_lock); - call_rcu(&ctx->rcu, reclaim_ctx); -} - -void cxl_context_mm_count_get(struct cxl_context *ctx) -{ - if (ctx->mm) - mmgrab(ctx->mm); -} - -void cxl_context_mm_count_put(struct cxl_context *ctx) -{ - if (ctx->mm) - mmdrop(ctx->mm); -}
diff --git a/drivers/misc/cxl/cxl.h b/drivers/misc/cxl/cxl.h deleted file mode 100644 index 6ad0ab8..0000000 --- a/drivers/misc/cxl/cxl.h +++ /dev/null
@@ -1,1135 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * Copyright 2014 IBM Corp. - */ - -#ifndef _CXL_H_ -#define _CXL_H_ - -#include <linux/interrupt.h> -#include <linux/semaphore.h> -#include <linux/device.h> -#include <linux/types.h> -#include <linux/cdev.h> -#include <linux/pid.h> -#include <linux/io.h> -#include <linux/pci.h> -#include <linux/fs.h> -#include <asm/cputable.h> -#include <asm/mmu.h> -#include <asm/reg.h> -#include <misc/cxl-base.h> - -#include <misc/cxl.h> -#include <uapi/misc/cxl.h> - -extern uint cxl_verbose; - -struct property; - -#define CXL_TIMEOUT 5 - -/* - * Bump version each time a user API change is made, whether it is - * backwards compatible ot not. - */ -#define CXL_API_VERSION 3 -#define CXL_API_VERSION_COMPATIBLE 1 - -/* - * Opaque types to avoid accidentally passing registers for the wrong MMIO - * - * At the end of the day, I'm not married to using typedef here, but it might - * (and has!) help avoid bugs like mixing up CXL_PSL_CtxTime and - * CXL_PSL_CtxTime_An, or calling cxl_p1n_write instead of cxl_p1_write. - * - * I'm quite happy if these are changed back to #defines before upstreaming, it - * should be little more than a regexp search+replace operation in this file. - */ -typedef struct { - const int x; -} cxl_p1_reg_t; -typedef struct { - const int x; -} cxl_p1n_reg_t; -typedef struct { - const int x; -} cxl_p2n_reg_t; -#define cxl_reg_off(reg) \ - (reg.x) - -/* Memory maps. Ref CXL Appendix A */ - -/* PSL Privilege 1 Memory Map */ -/* Configuration and Control area - CAIA 1&2 */ -static const cxl_p1_reg_t CXL_PSL_CtxTime = {0x0000}; -static const cxl_p1_reg_t CXL_PSL_ErrIVTE = {0x0008}; -static const cxl_p1_reg_t CXL_PSL_KEY1 = {0x0010}; -static const cxl_p1_reg_t CXL_PSL_KEY2 = {0x0018}; -static const cxl_p1_reg_t CXL_PSL_Control = {0x0020}; -/* Downloading */ -static const cxl_p1_reg_t CXL_PSL_DLCNTL = {0x0060}; -static const cxl_p1_reg_t CXL_PSL_DLADDR = {0x0068}; - -/* PSL Lookaside Buffer Management Area - CAIA 1 */ -static const cxl_p1_reg_t CXL_PSL_LBISEL = {0x0080}; -static const cxl_p1_reg_t CXL_PSL_SLBIE = {0x0088}; -static const cxl_p1_reg_t CXL_PSL_SLBIA = {0x0090}; -static const cxl_p1_reg_t CXL_PSL_TLBIE = {0x00A0}; -static const cxl_p1_reg_t CXL_PSL_TLBIA = {0x00A8}; -static const cxl_p1_reg_t CXL_PSL_AFUSEL = {0x00B0}; - -/* 0x00C0:7EFF Implementation dependent area */ -/* PSL registers - CAIA 1 */ -static const cxl_p1_reg_t CXL_PSL_FIR1 = {0x0100}; -static const cxl_p1_reg_t CXL_PSL_FIR2 = {0x0108}; -static const cxl_p1_reg_t CXL_PSL_Timebase = {0x0110}; -static const cxl_p1_reg_t CXL_PSL_VERSION = {0x0118}; -static const cxl_p1_reg_t CXL_PSL_RESLCKTO = {0x0128}; -static const cxl_p1_reg_t CXL_PSL_TB_CTLSTAT = {0x0140}; -static const cxl_p1_reg_t CXL_PSL_FIR_CNTL = {0x0148}; -static const cxl_p1_reg_t CXL_PSL_DSNDCTL = {0x0150}; -static const cxl_p1_reg_t CXL_PSL_SNWRALLOC = {0x0158}; -static const cxl_p1_reg_t CXL_PSL_TRACE = {0x0170}; -/* PSL registers - CAIA 2 */ -static const cxl_p1_reg_t CXL_PSL9_CONTROL = {0x0020}; -static const cxl_p1_reg_t CXL_XSL9_INV = {0x0110}; -static const cxl_p1_reg_t CXL_XSL9_DBG = {0x0130}; -static const cxl_p1_reg_t CXL_XSL9_DEF = {0x0140}; -static const cxl_p1_reg_t CXL_XSL9_DSNCTL = {0x0168}; -static const cxl_p1_reg_t CXL_PSL9_FIR1 = {0x0300}; -static const cxl_p1_reg_t CXL_PSL9_FIR_MASK = {0x0308}; -static const cxl_p1_reg_t CXL_PSL9_Timebase = {0x0310}; -static const cxl_p1_reg_t CXL_PSL9_DEBUG = {0x0320}; -static const cxl_p1_reg_t CXL_PSL9_FIR_CNTL = {0x0348}; -static const cxl_p1_reg_t CXL_PSL9_DSNDCTL = {0x0350}; -static const cxl_p1_reg_t CXL_PSL9_TB_CTLSTAT = {0x0340}; -static const cxl_p1_reg_t CXL_PSL9_TRACECFG = {0x0368}; -static const cxl_p1_reg_t CXL_PSL9_APCDEDALLOC = {0x0378}; -static const cxl_p1_reg_t CXL_PSL9_APCDEDTYPE = {0x0380}; -static const cxl_p1_reg_t CXL_PSL9_TNR_ADDR = {0x0388}; -static const cxl_p1_reg_t CXL_PSL9_CTCCFG = {0x0390}; -static const cxl_p1_reg_t CXL_PSL9_GP_CT = {0x0398}; -static const cxl_p1_reg_t CXL_XSL9_IERAT = {0x0588}; -static const cxl_p1_reg_t CXL_XSL9_ILPP = {0x0590}; - -/* 0x7F00:7FFF Reserved PCIe MSI-X Pending Bit Array area */ -/* 0x8000:FFFF Reserved PCIe MSI-X Table Area */ - -/* PSL Slice Privilege 1 Memory Map */ -/* Configuration Area - CAIA 1&2 */ -static const cxl_p1n_reg_t CXL_PSL_SR_An = {0x00}; -static const cxl_p1n_reg_t CXL_PSL_LPID_An = {0x08}; -static const cxl_p1n_reg_t CXL_PSL_AMBAR_An = {0x10}; -static const cxl_p1n_reg_t CXL_PSL_SPOffset_An = {0x18}; -static const cxl_p1n_reg_t CXL_PSL_ID_An = {0x20}; -static const cxl_p1n_reg_t CXL_PSL_SERR_An = {0x28}; -/* Memory Management and Lookaside Buffer Management - CAIA 1*/ -static const cxl_p1n_reg_t CXL_PSL_SDR_An = {0x30}; -/* Memory Management and Lookaside Buffer Management - CAIA 1&2 */ -static const cxl_p1n_reg_t CXL_PSL_AMOR_An = {0x38}; -/* Pointer Area - CAIA 1&2 */ -static const cxl_p1n_reg_t CXL_HAURP_An = {0x80}; -static const cxl_p1n_reg_t CXL_PSL_SPAP_An = {0x88}; -static const cxl_p1n_reg_t CXL_PSL_LLCMD_An = {0x90}; -/* Control Area - CAIA 1&2 */ -static const cxl_p1n_reg_t CXL_PSL_SCNTL_An = {0xA0}; -static const cxl_p1n_reg_t CXL_PSL_CtxTime_An = {0xA8}; -static const cxl_p1n_reg_t CXL_PSL_IVTE_Offset_An = {0xB0}; -static const cxl_p1n_reg_t CXL_PSL_IVTE_Limit_An = {0xB8}; -/* 0xC0:FF Implementation Dependent Area - CAIA 1&2 */ -static const cxl_p1n_reg_t CXL_PSL_FIR_SLICE_An = {0xC0}; -static const cxl_p1n_reg_t CXL_AFU_DEBUG_An = {0xC8}; -/* 0xC0:FF Implementation Dependent Area - CAIA 1 */ -static const cxl_p1n_reg_t CXL_PSL_APCALLOC_A = {0xD0}; -static const cxl_p1n_reg_t CXL_PSL_COALLOC_A = {0xD8}; -static const cxl_p1n_reg_t CXL_PSL_RXCTL_A = {0xE0}; -static const cxl_p1n_reg_t CXL_PSL_SLICE_TRACE = {0xE8}; - -/* PSL Slice Privilege 2 Memory Map */ -/* Configuration and Control Area - CAIA 1&2 */ -static const cxl_p2n_reg_t CXL_PSL_PID_TID_An = {0x000}; -static const cxl_p2n_reg_t CXL_CSRP_An = {0x008}; -/* Configuration and Control Area - CAIA 1 */ -static const cxl_p2n_reg_t CXL_AURP0_An = {0x010}; -static const cxl_p2n_reg_t CXL_AURP1_An = {0x018}; -static const cxl_p2n_reg_t CXL_SSTP0_An = {0x020}; -static const cxl_p2n_reg_t CXL_SSTP1_An = {0x028}; -/* Configuration and Control Area - CAIA 1 */ -static const cxl_p2n_reg_t CXL_PSL_AMR_An = {0x030}; -/* Segment Lookaside Buffer Management - CAIA 1 */ -static const cxl_p2n_reg_t CXL_SLBIE_An = {0x040}; -static const cxl_p2n_reg_t CXL_SLBIA_An = {0x048}; -static const cxl_p2n_reg_t CXL_SLBI_Select_An = {0x050}; -/* Interrupt Registers - CAIA 1&2 */ -static const cxl_p2n_reg_t CXL_PSL_DSISR_An = {0x060}; -static const cxl_p2n_reg_t CXL_PSL_DAR_An = {0x068}; -static const cxl_p2n_reg_t CXL_PSL_DSR_An = {0x070}; -static const cxl_p2n_reg_t CXL_PSL_TFC_An = {0x078}; -static const cxl_p2n_reg_t CXL_PSL_PEHandle_An = {0x080}; -static const cxl_p2n_reg_t CXL_PSL_ErrStat_An = {0x088}; -/* AFU Registers - CAIA 1&2 */ -static const cxl_p2n_reg_t CXL_AFU_Cntl_An = {0x090}; -static const cxl_p2n_reg_t CXL_AFU_ERR_An = {0x098}; -/* Work Element Descriptor - CAIA 1&2 */ -static const cxl_p2n_reg_t CXL_PSL_WED_An = {0x0A0}; -/* 0x0C0:FFF Implementation Dependent Area */ - -#define CXL_PSL_SPAP_Addr 0x0ffffffffffff000ULL -#define CXL_PSL_SPAP_Size 0x0000000000000ff0ULL -#define CXL_PSL_SPAP_Size_Shift 4 -#define CXL_PSL_SPAP_V 0x0000000000000001ULL - -/****** CXL_PSL_Control ****************************************************/ -#define CXL_PSL_Control_tb (0x1ull << (63-63)) -#define CXL_PSL_Control_Fr (0x1ull << (63-31)) -#define CXL_PSL_Control_Fs_MASK (0x3ull << (63-29)) -#define CXL_PSL_Control_Fs_Complete (0x3ull << (63-29)) - -/****** CXL_PSL_DLCNTL *****************************************************/ -#define CXL_PSL_DLCNTL_D (0x1ull << (63-28)) -#define CXL_PSL_DLCNTL_C (0x1ull << (63-29)) -#define CXL_PSL_DLCNTL_E (0x1ull << (63-30)) -#define CXL_PSL_DLCNTL_S (0x1ull << (63-31)) -#define CXL_PSL_DLCNTL_CE (CXL_PSL_DLCNTL_C | CXL_PSL_DLCNTL_E) -#define CXL_PSL_DLCNTL_DCES (CXL_PSL_DLCNTL_D | CXL_PSL_DLCNTL_CE | CXL_PSL_DLCNTL_S) - -/****** CXL_PSL_SR_An ******************************************************/ -#define CXL_PSL_SR_An_SF MSR_SF /* 64bit */ -#define CXL_PSL_SR_An_TA (1ull << (63-1)) /* Tags active, GA1: 0 */ -#define CXL_PSL_SR_An_HV MSR_HV /* Hypervisor, GA1: 0 */ -#define CXL_PSL_SR_An_XLAT_hpt (0ull << (63-6))/* Hashed page table (HPT) mode */ -#define CXL_PSL_SR_An_XLAT_roh (2ull << (63-6))/* Radix on HPT mode */ -#define CXL_PSL_SR_An_XLAT_ror (3ull << (63-6))/* Radix on Radix mode */ -#define CXL_PSL_SR_An_BOT (1ull << (63-10)) /* Use the in-memory segment table */ -#define CXL_PSL_SR_An_PR MSR_PR /* Problem state, GA1: 1 */ -#define CXL_PSL_SR_An_ISL (1ull << (63-53)) /* Ignore Segment Large Page */ -#define CXL_PSL_SR_An_TC (1ull << (63-54)) /* Page Table secondary hash */ -#define CXL_PSL_SR_An_US (1ull << (63-56)) /* User state, GA1: X */ -#define CXL_PSL_SR_An_SC (1ull << (63-58)) /* Segment Table secondary hash */ -#define CXL_PSL_SR_An_R MSR_DR /* Relocate, GA1: 1 */ -#define CXL_PSL_SR_An_MP (1ull << (63-62)) /* Master Process */ -#define CXL_PSL_SR_An_LE (1ull << (63-63)) /* Little Endian */ - -/****** CXL_PSL_ID_An ****************************************************/ -#define CXL_PSL_ID_An_F (1ull << (63-31)) -#define CXL_PSL_ID_An_L (1ull << (63-30)) - -/****** CXL_PSL_SERR_An ****************************************************/ -#define CXL_PSL_SERR_An_afuto (1ull << (63-0)) -#define CXL_PSL_SERR_An_afudis (1ull << (63-1)) -#define CXL_PSL_SERR_An_afuov (1ull << (63-2)) -#define CXL_PSL_SERR_An_badsrc (1ull << (63-3)) -#define CXL_PSL_SERR_An_badctx (1ull << (63-4)) -#define CXL_PSL_SERR_An_llcmdis (1ull << (63-5)) -#define CXL_PSL_SERR_An_llcmdto (1ull << (63-6)) -#define CXL_PSL_SERR_An_afupar (1ull << (63-7)) -#define CXL_PSL_SERR_An_afudup (1ull << (63-8)) -#define CXL_PSL_SERR_An_IRQS ( \ - CXL_PSL_SERR_An_afuto | CXL_PSL_SERR_An_afudis | CXL_PSL_SERR_An_afuov | \ - CXL_PSL_SERR_An_badsrc | CXL_PSL_SERR_An_badctx | CXL_PSL_SERR_An_llcmdis | \ - CXL_PSL_SERR_An_llcmdto | CXL_PSL_SERR_An_afupar | CXL_PSL_SERR_An_afudup) -#define CXL_PSL_SERR_An_afuto_mask (1ull << (63-32)) -#define CXL_PSL_SERR_An_afudis_mask (1ull << (63-33)) -#define CXL_PSL_SERR_An_afuov_mask (1ull << (63-34)) -#define CXL_PSL_SERR_An_badsrc_mask (1ull << (63-35)) -#define CXL_PSL_SERR_An_badctx_mask (1ull << (63-36)) -#define CXL_PSL_SERR_An_llcmdis_mask (1ull << (63-37)) -#define CXL_PSL_SERR_An_llcmdto_mask (1ull << (63-38)) -#define CXL_PSL_SERR_An_afupar_mask (1ull << (63-39)) -#define CXL_PSL_SERR_An_afudup_mask (1ull << (63-40)) -#define CXL_PSL_SERR_An_IRQ_MASKS ( \ - CXL_PSL_SERR_An_afuto_mask | CXL_PSL_SERR_An_afudis_mask | CXL_PSL_SERR_An_afuov_mask | \ - CXL_PSL_SERR_An_badsrc_mask | CXL_PSL_SERR_An_badctx_mask | CXL_PSL_SERR_An_llcmdis_mask | \ - CXL_PSL_SERR_An_llcmdto_mask | CXL_PSL_SERR_An_afupar_mask | CXL_PSL_SERR_An_afudup_mask) - -#define CXL_PSL_SERR_An_AE (1ull << (63-30)) - -/****** CXL_PSL_SCNTL_An ****************************************************/ -#define CXL_PSL_SCNTL_An_CR (0x1ull << (63-15)) -/* Programming Modes: */ -#define CXL_PSL_SCNTL_An_PM_MASK (0xffffull << (63-31)) -#define CXL_PSL_SCNTL_An_PM_Shared (0x0000ull << (63-31)) -#define CXL_PSL_SCNTL_An_PM_OS (0x0001ull << (63-31)) -#define CXL_PSL_SCNTL_An_PM_Process (0x0002ull << (63-31)) -#define CXL_PSL_SCNTL_An_PM_AFU (0x0004ull << (63-31)) -#define CXL_PSL_SCNTL_An_PM_AFU_PBT (0x0104ull << (63-31)) -/* Purge Status (ro) */ -#define CXL_PSL_SCNTL_An_Ps_MASK (0x3ull << (63-39)) -#define CXL_PSL_SCNTL_An_Ps_Pending (0x1ull << (63-39)) -#define CXL_PSL_SCNTL_An_Ps_Complete (0x3ull << (63-39)) -/* Purge */ -#define CXL_PSL_SCNTL_An_Pc (0x1ull << (63-48)) -/* Suspend Status (ro) */ -#define CXL_PSL_SCNTL_An_Ss_MASK (0x3ull << (63-55)) -#define CXL_PSL_SCNTL_An_Ss_Pending (0x1ull << (63-55)) -#define CXL_PSL_SCNTL_An_Ss_Complete (0x3ull << (63-55)) -/* Suspend Control */ -#define CXL_PSL_SCNTL_An_Sc (0x1ull << (63-63)) - -/* AFU Slice Enable Status (ro) */ -#define CXL_AFU_Cntl_An_ES_MASK (0x7ull << (63-2)) -#define CXL_AFU_Cntl_An_ES_Disabled (0x0ull << (63-2)) -#define CXL_AFU_Cntl_An_ES_Enabled (0x4ull << (63-2)) -/* AFU Slice Enable */ -#define CXL_AFU_Cntl_An_E (0x1ull << (63-3)) -/* AFU Slice Reset status (ro) */ -#define CXL_AFU_Cntl_An_RS_MASK (0x3ull << (63-5)) -#define CXL_AFU_Cntl_An_RS_Pending (0x1ull << (63-5)) -#define CXL_AFU_Cntl_An_RS_Complete (0x2ull << (63-5)) -/* AFU Slice Reset */ -#define CXL_AFU_Cntl_An_RA (0x1ull << (63-7)) - -/****** CXL_SSTP0/1_An ******************************************************/ -/* These top bits are for the segment that CONTAINS the segment table */ -#define CXL_SSTP0_An_B_SHIFT SLB_VSID_SSIZE_SHIFT -#define CXL_SSTP0_An_KS (1ull << (63-2)) -#define CXL_SSTP0_An_KP (1ull << (63-3)) -#define CXL_SSTP0_An_N (1ull << (63-4)) -#define CXL_SSTP0_An_L (1ull << (63-5)) -#define CXL_SSTP0_An_C (1ull << (63-6)) -#define CXL_SSTP0_An_TA (1ull << (63-7)) -#define CXL_SSTP0_An_LP_SHIFT (63-9) /* 2 Bits */ -/* And finally, the virtual address & size of the segment table: */ -#define CXL_SSTP0_An_SegTableSize_SHIFT (63-31) /* 12 Bits */ -#define CXL_SSTP0_An_SegTableSize_MASK \ - (((1ull << 12) - 1) << CXL_SSTP0_An_SegTableSize_SHIFT) -#define CXL_SSTP0_An_STVA_U_MASK ((1ull << (63-49))-1) -#define CXL_SSTP1_An_STVA_L_MASK (~((1ull << (63-55))-1)) -#define CXL_SSTP1_An_V (1ull << (63-63)) - -/****** CXL_PSL_SLBIE_[An] - CAIA 1 **************************************************/ -/* write: */ -#define CXL_SLBIE_C PPC_BIT(36) /* Class */ -#define CXL_SLBIE_SS PPC_BITMASK(37, 38) /* Segment Size */ -#define CXL_SLBIE_SS_SHIFT PPC_BITLSHIFT(38) -#define CXL_SLBIE_TA PPC_BIT(38) /* Tags Active */ -/* read: */ -#define CXL_SLBIE_MAX PPC_BITMASK(24, 31) -#define CXL_SLBIE_PENDING PPC_BITMASK(56, 63) - -/****** Common to all CXL_TLBIA/SLBIA_[An] - CAIA 1 **********************************/ -#define CXL_TLB_SLB_P (1ull) /* Pending (read) */ - -/****** Common to all CXL_TLB/SLB_IA/IE_[An] registers - CAIA 1 **********************/ -#define CXL_TLB_SLB_IQ_ALL (0ull) /* Inv qualifier */ -#define CXL_TLB_SLB_IQ_LPID (1ull) /* Inv qualifier */ -#define CXL_TLB_SLB_IQ_LPIDPID (3ull) /* Inv qualifier */ - -/****** CXL_PSL_AFUSEL ******************************************************/ -#define CXL_PSL_AFUSEL_A (1ull << (63-55)) /* Adapter wide invalidates affect all AFUs */ - -/****** CXL_PSL_DSISR_An - CAIA 1 ****************************************************/ -#define CXL_PSL_DSISR_An_DS (1ull << (63-0)) /* Segment not found */ -#define CXL_PSL_DSISR_An_DM (1ull << (63-1)) /* PTE not found (See also: M) or protection fault */ -#define CXL_PSL_DSISR_An_ST (1ull << (63-2)) /* Segment Table PTE not found */ -#define CXL_PSL_DSISR_An_UR (1ull << (63-3)) /* AURP PTE not found */ -#define CXL_PSL_DSISR_TRANS (CXL_PSL_DSISR_An_DS | CXL_PSL_DSISR_An_DM | CXL_PSL_DSISR_An_ST | CXL_PSL_DSISR_An_UR) -#define CXL_PSL_DSISR_An_PE (1ull << (63-4)) /* PSL Error (implementation specific) */ -#define CXL_PSL_DSISR_An_AE (1ull << (63-5)) /* AFU Error */ -#define CXL_PSL_DSISR_An_OC (1ull << (63-6)) /* OS Context Warning */ -#define CXL_PSL_DSISR_PENDING (CXL_PSL_DSISR_TRANS | CXL_PSL_DSISR_An_PE | CXL_PSL_DSISR_An_AE | CXL_PSL_DSISR_An_OC) -/* NOTE: Bits 32:63 are undefined if DSISR[DS] = 1 */ -#define CXL_PSL_DSISR_An_M DSISR_NOHPTE /* PTE not found */ -#define CXL_PSL_DSISR_An_P DSISR_PROTFAULT /* Storage protection violation */ -#define CXL_PSL_DSISR_An_A (1ull << (63-37)) /* AFU lock access to write through or cache inhibited storage */ -#define CXL_PSL_DSISR_An_S DSISR_ISSTORE /* Access was afu_wr or afu_zero */ -#define CXL_PSL_DSISR_An_K DSISR_KEYFAULT /* Access not permitted by virtual page class key protection */ - -/****** CXL_PSL_DSISR_An - CAIA 2 ****************************************************/ -#define CXL_PSL9_DSISR_An_TF (1ull << (63-3)) /* Translation fault */ -#define CXL_PSL9_DSISR_An_PE (1ull << (63-4)) /* PSL Error (implementation specific) */ -#define CXL_PSL9_DSISR_An_AE (1ull << (63-5)) /* AFU Error */ -#define CXL_PSL9_DSISR_An_OC (1ull << (63-6)) /* OS Context Warning */ -#define CXL_PSL9_DSISR_An_S (1ull << (63-38)) /* TF for a write operation */ -#define CXL_PSL9_DSISR_PENDING (CXL_PSL9_DSISR_An_TF | CXL_PSL9_DSISR_An_PE | CXL_PSL9_DSISR_An_AE | CXL_PSL9_DSISR_An_OC) -/* - * NOTE: Bits 56:63 (Checkout Response Status) are valid when DSISR_An[TF] = 1 - * Status (0:7) Encoding - */ -#define CXL_PSL9_DSISR_An_CO_MASK 0x00000000000000ffULL -#define CXL_PSL9_DSISR_An_SF 0x0000000000000080ULL /* Segment Fault 0b10000000 */ -#define CXL_PSL9_DSISR_An_PF_SLR 0x0000000000000088ULL /* PTE not found (Single Level Radix) 0b10001000 */ -#define CXL_PSL9_DSISR_An_PF_RGC 0x000000000000008CULL /* PTE not found (Radix Guest (child)) 0b10001100 */ -#define CXL_PSL9_DSISR_An_PF_RGP 0x0000000000000090ULL /* PTE not found (Radix Guest (parent)) 0b10010000 */ -#define CXL_PSL9_DSISR_An_PF_HRH 0x0000000000000094ULL /* PTE not found (HPT/Radix Host) 0b10010100 */ -#define CXL_PSL9_DSISR_An_PF_STEG 0x000000000000009CULL /* PTE not found (STEG VA) 0b10011100 */ -#define CXL_PSL9_DSISR_An_URTCH 0x00000000000000B4ULL /* Unsupported Radix Tree Configuration 0b10110100 */ - -/****** CXL_PSL_TFC_An ******************************************************/ -#define CXL_PSL_TFC_An_A (1ull << (63-28)) /* Acknowledge non-translation fault */ -#define CXL_PSL_TFC_An_C (1ull << (63-29)) /* Continue (abort transaction) */ -#define CXL_PSL_TFC_An_AE (1ull << (63-30)) /* Restart PSL with address error */ -#define CXL_PSL_TFC_An_R (1ull << (63-31)) /* Restart PSL transaction */ - -/****** CXL_PSL_DEBUG *****************************************************/ -#define CXL_PSL_DEBUG_CDC (1ull << (63-27)) /* Coherent Data cache support */ - -/****** CXL_XSL9_IERAT_ERAT - CAIA 2 **********************************/ -#define CXL_XSL9_IERAT_MLPID (1ull << (63-0)) /* Match LPID */ -#define CXL_XSL9_IERAT_MPID (1ull << (63-1)) /* Match PID */ -#define CXL_XSL9_IERAT_PRS (1ull << (63-4)) /* PRS bit for Radix invalidations */ -#define CXL_XSL9_IERAT_INVR (1ull << (63-3)) /* Invalidate Radix */ -#define CXL_XSL9_IERAT_IALL (1ull << (63-8)) /* Invalidate All */ -#define CXL_XSL9_IERAT_IINPROG (1ull << (63-63)) /* Invalidate in progress */ - -/* cxl_process_element->software_status */ -#define CXL_PE_SOFTWARE_STATE_V (1ul << (31 - 0)) /* Valid */ -#define CXL_PE_SOFTWARE_STATE_C (1ul << (31 - 29)) /* Complete */ -#define CXL_PE_SOFTWARE_STATE_S (1ul << (31 - 30)) /* Suspend */ -#define CXL_PE_SOFTWARE_STATE_T (1ul << (31 - 31)) /* Terminate */ - -/****** CXL_PSL_RXCTL_An (Implementation Specific) ************************** - * Controls AFU Hang Pulse, which sets the timeout for the AFU to respond to - * the PSL for any response (except MMIO). Timeouts will occur between 1x to 2x - * of the hang pulse frequency. - */ -#define CXL_PSL_RXCTL_AFUHP_4S 0x7000000000000000ULL - -/* SPA->sw_command_status */ -#define CXL_SPA_SW_CMD_MASK 0xffff000000000000ULL -#define CXL_SPA_SW_CMD_TERMINATE 0x0001000000000000ULL -#define CXL_SPA_SW_CMD_REMOVE 0x0002000000000000ULL -#define CXL_SPA_SW_CMD_SUSPEND 0x0003000000000000ULL -#define CXL_SPA_SW_CMD_RESUME 0x0004000000000000ULL -#define CXL_SPA_SW_CMD_ADD 0x0005000000000000ULL -#define CXL_SPA_SW_CMD_UPDATE 0x0006000000000000ULL -#define CXL_SPA_SW_STATE_MASK 0x0000ffff00000000ULL -#define CXL_SPA_SW_STATE_TERMINATED 0x0000000100000000ULL -#define CXL_SPA_SW_STATE_REMOVED 0x0000000200000000ULL -#define CXL_SPA_SW_STATE_SUSPENDED 0x0000000300000000ULL -#define CXL_SPA_SW_STATE_RESUMED 0x0000000400000000ULL -#define CXL_SPA_SW_STATE_ADDED 0x0000000500000000ULL -#define CXL_SPA_SW_STATE_UPDATED 0x0000000600000000ULL -#define CXL_SPA_SW_PSL_ID_MASK 0x00000000ffff0000ULL -#define CXL_SPA_SW_LINK_MASK 0x000000000000ffffULL - -#define CXL_MAX_SLICES 4 -#define MAX_AFU_MMIO_REGS 3 - -#define CXL_MODE_TIME_SLICED 0x4 -#define CXL_SUPPORTED_MODES (CXL_MODE_DEDICATED | CXL_MODE_DIRECTED) - -#define CXL_DEV_MINORS 13 /* 1 control + 4 AFUs * 3 (dedicated/master/shared) */ -#define CXL_CARD_MINOR(adapter) (adapter->adapter_num * CXL_DEV_MINORS) -#define CXL_DEVT_ADAPTER(dev) (MINOR(dev) / CXL_DEV_MINORS) - -#define CXL_PSL9_TRACEID_MAX 0xAU -#define CXL_PSL9_TRACESTATE_FIN 0x3U - -enum cxl_context_status { - CLOSED, - OPENED, - STARTED -}; - -enum prefault_modes { - CXL_PREFAULT_NONE, - CXL_PREFAULT_WED, - CXL_PREFAULT_ALL, -}; - -enum cxl_attrs { - CXL_ADAPTER_ATTRS, - CXL_AFU_MASTER_ATTRS, - CXL_AFU_ATTRS, -}; - -struct cxl_sste { - __be64 esid_data; - __be64 vsid_data; -}; - -#define to_cxl_adapter(d) container_of(d, struct cxl, dev) -#define to_cxl_afu(d) container_of(d, struct cxl_afu, dev) - -struct cxl_afu_native { - void __iomem *p1n_mmio; - void __iomem *afu_desc_mmio; - irq_hw_number_t psl_hwirq; - unsigned int psl_virq; - struct mutex spa_mutex; - /* - * Only the first part of the SPA is used for the process element - * linked list. The only other part that software needs to worry about - * is sw_command_status, which we store a separate pointer to. - * Everything else in the SPA is only used by hardware - */ - struct cxl_process_element *spa; - __be64 *sw_command_status; - unsigned int spa_size; - int spa_order; - int spa_max_procs; - u64 pp_offset; -}; - -struct cxl_afu_guest { - struct cxl_afu *parent; - u64 handle; - phys_addr_t p2n_phys; - u64 p2n_size; - int max_ints; - bool handle_err; - struct delayed_work work_err; - int previous_state; -}; - -struct cxl_afu { - struct cxl_afu_native *native; - struct cxl_afu_guest *guest; - irq_hw_number_t serr_hwirq; - unsigned int serr_virq; - char *psl_irq_name; - char *err_irq_name; - void __iomem *p2n_mmio; - phys_addr_t psn_phys; - u64 pp_size; - - struct cxl *adapter; - struct device dev; - struct cdev afu_cdev_s, afu_cdev_m, afu_cdev_d; - struct device *chardev_s, *chardev_m, *chardev_d; - struct idr contexts_idr; - struct dentry *debugfs; - struct mutex contexts_lock; - spinlock_t afu_cntl_lock; - - /* -1: AFU deconfigured/locked, >= 0: number of readers */ - atomic_t configured_state; - - /* AFU error buffer fields and bin attribute for sysfs */ - u64 eb_len, eb_offset; - struct bin_attribute attr_eb; - - /* pointer to the vphb */ - struct pci_controller *phb; - - int pp_irqs; - int irqs_max; - int num_procs; - int max_procs_virtualised; - int slice; - int modes_supported; - int current_mode; - int crs_num; - u64 crs_len; - u64 crs_offset; - struct list_head crs; - enum prefault_modes prefault_mode; - bool psa; - bool pp_psa; - bool enabled; -}; - - -struct cxl_irq_name { - struct list_head list; - char *name; -}; - -struct irq_avail { - irq_hw_number_t offset; - irq_hw_number_t range; - unsigned long *bitmap; -}; - -/* - * This is a cxl context. If the PSL is in dedicated mode, there will be one - * of these per AFU. If in AFU directed there can be lots of these. - */ -struct cxl_context { - struct cxl_afu *afu; - - /* Problem state MMIO */ - phys_addr_t psn_phys; - u64 psn_size; - - /* Used to unmap any mmaps when force detaching */ - struct address_space *mapping; - struct mutex mapping_lock; - struct page *ff_page; - bool mmio_err_ff; - bool kernelapi; - - spinlock_t sste_lock; /* Protects segment table entries */ - struct cxl_sste *sstp; - u64 sstp0, sstp1; - unsigned int sst_size, sst_lru; - - wait_queue_head_t wq; - /* use mm context associated with this pid for ds faults */ - struct pid *pid; - spinlock_t lock; /* Protects pending_irq_mask, pending_fault and fault_addr */ - /* Only used in PR mode */ - u64 process_token; - - /* driver private data */ - void *priv; - - unsigned long *irq_bitmap; /* Accessed from IRQ context */ - struct cxl_irq_ranges irqs; - struct list_head irq_names; - u64 fault_addr; - u64 fault_dsisr; - u64 afu_err; - - /* - * This status and it's lock pretects start and detach context - * from racing. It also prevents detach from racing with - * itself - */ - enum cxl_context_status status; - struct mutex status_mutex; - - - /* XXX: Is it possible to need multiple work items at once? */ - struct work_struct fault_work; - u64 dsisr; - u64 dar; - - struct cxl_process_element *elem; - - /* - * pe is the process element handle, assigned by this driver when the - * context is initialized. - * - * external_pe is the PE shown outside of cxl. - * On bare-metal, pe=external_pe, because we decide what the handle is. - * In a guest, we only find out about the pe used by pHyp when the - * context is attached, and that's the value we want to report outside - * of cxl. - */ - int pe; - int external_pe; - - u32 irq_count; - bool pe_inserted; - bool master; - bool kernel; - bool pending_irq; - bool pending_fault; - bool pending_afu_err; - - /* Used by AFU drivers for driver specific event delivery */ - struct cxl_afu_driver_ops *afu_driver_ops; - atomic_t afu_driver_events; - - struct rcu_head rcu; - - struct mm_struct *mm; - - u16 tidr; - bool assign_tidr; -}; - -struct cxl_irq_info; - -struct cxl_service_layer_ops { - int (*adapter_regs_init)(struct cxl *adapter, struct pci_dev *dev); - int (*invalidate_all)(struct cxl *adapter); - int (*afu_regs_init)(struct cxl_afu *afu); - int (*sanitise_afu_regs)(struct cxl_afu *afu); - int (*register_serr_irq)(struct cxl_afu *afu); - void (*release_serr_irq)(struct cxl_afu *afu); - irqreturn_t (*handle_interrupt)(int irq, struct cxl_context *ctx, struct cxl_irq_info *irq_info); - irqreturn_t (*fail_irq)(struct cxl_afu *afu, struct cxl_irq_info *irq_info); - int (*activate_dedicated_process)(struct cxl_afu *afu); - int (*attach_afu_directed)(struct cxl_context *ctx, u64 wed, u64 amr); - int (*attach_dedicated_process)(struct cxl_context *ctx, u64 wed, u64 amr); - void (*update_dedicated_ivtes)(struct cxl_context *ctx); - void (*debugfs_add_adapter_regs)(struct cxl *adapter, struct dentry *dir); - void (*debugfs_add_afu_regs)(struct cxl_afu *afu, struct dentry *dir); - void (*psl_irq_dump_registers)(struct cxl_context *ctx); - void (*err_irq_dump_registers)(struct cxl *adapter); - void (*debugfs_stop_trace)(struct cxl *adapter); - void (*write_timebase_ctrl)(struct cxl *adapter); - u64 (*timebase_read)(struct cxl *adapter); - int capi_mode; - bool needs_reset_before_disable; -}; - -struct cxl_native { - u64 afu_desc_off; - u64 afu_desc_size; - void __iomem *p1_mmio; - void __iomem *p2_mmio; - irq_hw_number_t err_hwirq; - unsigned int err_virq; - u64 ps_off; - bool no_data_cache; /* set if no data cache on the card */ - const struct cxl_service_layer_ops *sl_ops; -}; - -struct cxl_guest { - struct platform_device *pdev; - int irq_nranges; - struct cdev cdev; - irq_hw_number_t irq_base_offset; - struct irq_avail *irq_avail; - spinlock_t irq_alloc_lock; - u64 handle; - char *status; - u16 vendor; - u16 device; - u16 subsystem_vendor; - u16 subsystem; -}; - -struct cxl { - struct cxl_native *native; - struct cxl_guest *guest; - spinlock_t afu_list_lock; - struct cxl_afu *afu[CXL_MAX_SLICES]; - struct device dev; - struct dentry *trace; - struct dentry *psl_err_chk; - struct dentry *debugfs; - char *irq_name; - struct bin_attribute cxl_attr; - int adapter_num; - int user_irqs; - u64 ps_size; - u16 psl_rev; - u16 base_image; - u8 vsec_status; - u8 caia_major; - u8 caia_minor; - u8 slices; - bool user_image_loaded; - bool perst_loads_image; - bool perst_select_user; - bool perst_same_image; - bool psl_timebase_synced; - bool tunneled_ops_supported; - - /* - * number of contexts mapped on to this card. Possible values are: - * >0: Number of contexts mapped and new one can be mapped. - * 0: No active contexts and new ones can be mapped. - * -1: No contexts mapped and new ones cannot be mapped. - */ - atomic_t contexts_num; -}; - -int cxl_pci_alloc_one_irq(struct cxl *adapter); -void cxl_pci_release_one_irq(struct cxl *adapter, int hwirq); -int cxl_pci_alloc_irq_ranges(struct cxl_irq_ranges *irqs, struct cxl *adapter, unsigned int num); -void cxl_pci_release_irq_ranges(struct cxl_irq_ranges *irqs, struct cxl *adapter); -int cxl_pci_setup_irq(struct cxl *adapter, unsigned int hwirq, unsigned int virq); -int cxl_update_image_control(struct cxl *adapter); -int cxl_pci_reset(struct cxl *adapter); -void cxl_pci_release_afu(struct device *dev); -ssize_t cxl_pci_read_adapter_vpd(struct cxl *adapter, void *buf, size_t len); - -/* common == phyp + powernv - CAIA 1&2 */ -struct cxl_process_element_common { - __be32 tid; - __be32 pid; - __be64 csrp; - union { - struct { - __be64 aurp0; - __be64 aurp1; - __be64 sstp0; - __be64 sstp1; - } psl8; /* CAIA 1 */ - struct { - u8 reserved2[8]; - u8 reserved3[8]; - u8 reserved4[8]; - u8 reserved5[8]; - } psl9; /* CAIA 2 */ - } u; - __be64 amr; - u8 reserved6[4]; - __be64 wed; -} __packed; - -/* just powernv - CAIA 1&2 */ -struct cxl_process_element { - __be64 sr; - __be64 SPOffset; - union { - __be64 sdr; /* CAIA 1 */ - u8 reserved1[8]; /* CAIA 2 */ - } u; - __be64 haurp; - __be32 ctxtime; - __be16 ivte_offsets[4]; - __be16 ivte_ranges[4]; - __be32 lpid; - struct cxl_process_element_common common; - __be32 software_state; -} __packed; - -static inline bool cxl_adapter_link_ok(struct cxl *cxl, struct cxl_afu *afu) -{ - struct pci_dev *pdev; - - if (cpu_has_feature(CPU_FTR_HVMODE)) { - pdev = to_pci_dev(cxl->dev.parent); - return !pci_channel_offline(pdev); - } - return true; -} - -static inline void __iomem *_cxl_p1_addr(struct cxl *cxl, cxl_p1_reg_t reg) -{ - WARN_ON(!cpu_has_feature(CPU_FTR_HVMODE)); - return cxl->native->p1_mmio + cxl_reg_off(reg); -} - -static inline void cxl_p1_write(struct cxl *cxl, cxl_p1_reg_t reg, u64 val) -{ - if (likely(cxl_adapter_link_ok(cxl, NULL))) - out_be64(_cxl_p1_addr(cxl, reg), val); -} - -static inline u64 cxl_p1_read(struct cxl *cxl, cxl_p1_reg_t reg) -{ - if (likely(cxl_adapter_link_ok(cxl, NULL))) - return in_be64(_cxl_p1_addr(cxl, reg)); - else - return ~0ULL; -} - -static inline void __iomem *_cxl_p1n_addr(struct cxl_afu *afu, cxl_p1n_reg_t reg) -{ - WARN_ON(!cpu_has_feature(CPU_FTR_HVMODE)); - return afu->native->p1n_mmio + cxl_reg_off(reg); -} - -static inline void cxl_p1n_write(struct cxl_afu *afu, cxl_p1n_reg_t reg, u64 val) -{ - if (likely(cxl_adapter_link_ok(afu->adapter, afu))) - out_be64(_cxl_p1n_addr(afu, reg), val); -} - -static inline u64 cxl_p1n_read(struct cxl_afu *afu, cxl_p1n_reg_t reg) -{ - if (likely(cxl_adapter_link_ok(afu->adapter, afu))) - return in_be64(_cxl_p1n_addr(afu, reg)); - else - return ~0ULL; -} - -static inline void __iomem *_cxl_p2n_addr(struct cxl_afu *afu, cxl_p2n_reg_t reg) -{ - return afu->p2n_mmio + cxl_reg_off(reg); -} - -static inline void cxl_p2n_write(struct cxl_afu *afu, cxl_p2n_reg_t reg, u64 val) -{ - if (likely(cxl_adapter_link_ok(afu->adapter, afu))) - out_be64(_cxl_p2n_addr(afu, reg), val); -} - -static inline u64 cxl_p2n_read(struct cxl_afu *afu, cxl_p2n_reg_t reg) -{ - if (likely(cxl_adapter_link_ok(afu->adapter, afu))) - return in_be64(_cxl_p2n_addr(afu, reg)); - else - return ~0ULL; -} - -static inline bool cxl_is_power8(void) -{ - if ((pvr_version_is(PVR_POWER8E)) || - (pvr_version_is(PVR_POWER8NVL)) || - (pvr_version_is(PVR_POWER8)) || - (pvr_version_is(PVR_HX_C2000))) - return true; - return false; -} - -static inline bool cxl_is_power9(void) -{ - if (pvr_version_is(PVR_POWER9)) - return true; - return false; -} - -ssize_t cxl_pci_afu_read_err_buffer(struct cxl_afu *afu, char *buf, - loff_t off, size_t count); - - -struct cxl_calls { - void (*cxl_slbia)(struct mm_struct *mm); - struct module *owner; -}; -int register_cxl_calls(struct cxl_calls *calls); -void unregister_cxl_calls(struct cxl_calls *calls); -int cxl_update_properties(struct device_node *dn, struct property *new_prop); - -void cxl_remove_adapter_nr(struct cxl *adapter); - -void cxl_release_spa(struct cxl_afu *afu); - -dev_t cxl_get_dev(void); -int cxl_file_init(void); -void cxl_file_exit(void); -int cxl_register_adapter(struct cxl *adapter); -int cxl_register_afu(struct cxl_afu *afu); -int cxl_chardev_d_afu_add(struct cxl_afu *afu); -int cxl_chardev_m_afu_add(struct cxl_afu *afu); -int cxl_chardev_s_afu_add(struct cxl_afu *afu); -void cxl_chardev_afu_remove(struct cxl_afu *afu); - -void cxl_context_detach_all(struct cxl_afu *afu); -void cxl_context_free(struct cxl_context *ctx); -void cxl_context_detach(struct cxl_context *ctx); - -int cxl_sysfs_adapter_add(struct cxl *adapter); -void cxl_sysfs_adapter_remove(struct cxl *adapter); -int cxl_sysfs_afu_add(struct cxl_afu *afu); -void cxl_sysfs_afu_remove(struct cxl_afu *afu); -int cxl_sysfs_afu_m_add(struct cxl_afu *afu); -void cxl_sysfs_afu_m_remove(struct cxl_afu *afu); - -struct cxl *cxl_alloc_adapter(void); -struct cxl_afu *cxl_alloc_afu(struct cxl *adapter, int slice); -int cxl_afu_select_best_mode(struct cxl_afu *afu); - -int cxl_native_register_psl_irq(struct cxl_afu *afu); -void cxl_native_release_psl_irq(struct cxl_afu *afu); -int cxl_native_register_psl_err_irq(struct cxl *adapter); -void cxl_native_release_psl_err_irq(struct cxl *adapter); -int cxl_native_register_serr_irq(struct cxl_afu *afu); -void cxl_native_release_serr_irq(struct cxl_afu *afu); -int afu_register_irqs(struct cxl_context *ctx, u32 count); -void afu_release_irqs(struct cxl_context *ctx, void *cookie); -void afu_irq_name_free(struct cxl_context *ctx); - -int cxl_attach_afu_directed_psl9(struct cxl_context *ctx, u64 wed, u64 amr); -int cxl_attach_afu_directed_psl8(struct cxl_context *ctx, u64 wed, u64 amr); -int cxl_activate_dedicated_process_psl9(struct cxl_afu *afu); -int cxl_activate_dedicated_process_psl8(struct cxl_afu *afu); -int cxl_attach_dedicated_process_psl9(struct cxl_context *ctx, u64 wed, u64 amr); -int cxl_attach_dedicated_process_psl8(struct cxl_context *ctx, u64 wed, u64 amr); -void cxl_update_dedicated_ivtes_psl9(struct cxl_context *ctx); -void cxl_update_dedicated_ivtes_psl8(struct cxl_context *ctx); - -#ifdef CONFIG_DEBUG_FS - -void cxl_debugfs_init(void); -void cxl_debugfs_exit(void); -void cxl_debugfs_adapter_add(struct cxl *adapter); -void cxl_debugfs_adapter_remove(struct cxl *adapter); -void cxl_debugfs_afu_add(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_psl8(struct cxl *adapter, struct dentry *dir); -void cxl_debugfs_add_afu_regs_psl9(struct cxl_afu *afu, struct dentry *dir); -void cxl_debugfs_add_afu_regs_psl8(struct cxl_afu *afu, struct dentry *dir); - -#else /* CONFIG_DEBUG_FS */ - -static inline void __init cxl_debugfs_init(void) -{ -} - -static inline void cxl_debugfs_exit(void) -{ -} - -static inline void cxl_debugfs_adapter_add(struct cxl *adapter) -{ -} - -static inline void cxl_debugfs_adapter_remove(struct cxl *adapter) -{ -} - -static inline void cxl_debugfs_afu_add(struct cxl_afu *afu) -{ -} - -static inline void cxl_debugfs_afu_remove(struct cxl_afu *afu) -{ -} - -static inline void cxl_debugfs_add_adapter_regs_psl9(struct cxl *adapter, - struct dentry *dir) -{ -} - -static inline void cxl_debugfs_add_adapter_regs_psl8(struct cxl *adapter, - struct dentry *dir) -{ -} - -static inline void cxl_debugfs_add_afu_regs_psl9(struct cxl_afu *afu, struct dentry *dir) -{ -} - -static inline void cxl_debugfs_add_afu_regs_psl8(struct cxl_afu *afu, struct dentry *dir) -{ -} - -#endif /* CONFIG_DEBUG_FS */ - -void cxl_handle_fault(struct work_struct *work); -void cxl_prefault(struct cxl_context *ctx, u64 wed); -int cxl_handle_mm_fault(struct mm_struct *mm, u64 dsisr, u64 dar); - -struct cxl *get_cxl_adapter(int num); -int cxl_alloc_sst(struct cxl_context *ctx); -void cxl_dump_debug_buffer(void *addr, size_t size); - -void init_cxl_native(void); - -struct cxl_context *cxl_context_alloc(void); -int cxl_context_init(struct cxl_context *ctx, struct cxl_afu *afu, bool master); -void cxl_context_set_mapping(struct cxl_context *ctx, - struct address_space *mapping); -void cxl_context_free(struct cxl_context *ctx); -int cxl_context_iomap(struct cxl_context *ctx, struct vm_area_struct *vma); -unsigned int cxl_map_irq(struct cxl *adapter, irq_hw_number_t hwirq, - irq_handler_t handler, void *cookie, const char *name); -void cxl_unmap_irq(unsigned int virq, void *cookie); -int __detach_context(struct cxl_context *ctx); - -/* - * This must match the layout of the H_COLLECT_CA_INT_INFO retbuf defined - * in PAPR. - * Field pid_tid is now 'reserved' because it's no more used on bare-metal. - * On a guest environment, PSL_PID_An is located on the upper 32 bits and - * PSL_TID_An register in the lower 32 bits. - */ -struct cxl_irq_info { - u64 dsisr; - u64 dar; - u64 dsr; - u64 reserved; - u64 afu_err; - u64 errstat; - u64 proc_handle; - u64 padding[2]; /* to match the expected retbuf size for plpar_hcall9 */ -}; - -void cxl_assign_psn_space(struct cxl_context *ctx); -int cxl_invalidate_all_psl9(struct cxl *adapter); -int cxl_invalidate_all_psl8(struct cxl *adapter); -irqreturn_t cxl_irq_psl9(int irq, struct cxl_context *ctx, struct cxl_irq_info *irq_info); -irqreturn_t cxl_irq_psl8(int irq, struct cxl_context *ctx, struct cxl_irq_info *irq_info); -irqreturn_t cxl_fail_irq_psl(struct cxl_afu *afu, struct cxl_irq_info *irq_info); -int cxl_register_one_irq(struct cxl *adapter, irq_handler_t handler, - void *cookie, irq_hw_number_t *dest_hwirq, - unsigned int *dest_virq, const char *name); - -int cxl_check_error(struct cxl_afu *afu); -int cxl_afu_slbia(struct cxl_afu *afu); -int cxl_data_cache_flush(struct cxl *adapter); -int cxl_afu_disable(struct cxl_afu *afu); -int cxl_psl_purge(struct cxl_afu *afu); -int cxl_calc_capp_routing(struct pci_dev *dev, u64 *chipid, - u32 *phb_index, u64 *capp_unit_id); -int cxl_slot_is_switched(struct pci_dev *dev); -int cxl_get_xsl9_dsnctl(struct pci_dev *dev, u64 capp_unit_id, u64 *reg); -u64 cxl_calculate_sr(bool master, bool kernel, bool real_mode, bool p9); - -void cxl_native_irq_dump_regs_psl9(struct cxl_context *ctx); -void cxl_native_irq_dump_regs_psl8(struct cxl_context *ctx); -void cxl_native_err_irq_dump_regs_psl8(struct cxl *adapter); -void cxl_native_err_irq_dump_regs_psl9(struct cxl *adapter); -int cxl_pci_vphb_add(struct cxl_afu *afu); -void cxl_pci_vphb_remove(struct cxl_afu *afu); -void cxl_release_mapping(struct cxl_context *ctx); - -extern struct pci_driver cxl_pci_driver; -extern struct platform_driver cxl_of_driver; -int afu_allocate_irqs(struct cxl_context *ctx, u32 count); - -int afu_open(struct inode *inode, struct file *file); -int afu_release(struct inode *inode, struct file *file); -long afu_ioctl(struct file *file, unsigned int cmd, unsigned long arg); -int afu_mmap(struct file *file, struct vm_area_struct *vm); -__poll_t afu_poll(struct file *file, struct poll_table_struct *poll); -ssize_t afu_read(struct file *file, char __user *buf, size_t count, loff_t *off); -extern const struct file_operations afu_fops; - -struct cxl *cxl_guest_init_adapter(struct device_node *np, struct platform_device *dev); -void cxl_guest_remove_adapter(struct cxl *adapter); -int cxl_of_read_adapter_handle(struct cxl *adapter, struct device_node *np); -int cxl_of_read_adapter_properties(struct cxl *adapter, struct device_node *np); -ssize_t cxl_guest_read_adapter_vpd(struct cxl *adapter, void *buf, size_t len); -ssize_t cxl_guest_read_afu_vpd(struct cxl_afu *afu, void *buf, size_t len); -int cxl_guest_init_afu(struct cxl *adapter, int slice, struct device_node *afu_np); -void cxl_guest_remove_afu(struct cxl_afu *afu); -int cxl_of_read_afu_handle(struct cxl_afu *afu, struct device_node *afu_np); -int cxl_of_read_afu_properties(struct cxl_afu *afu, struct device_node *afu_np); -int cxl_guest_add_chardev(struct cxl *adapter); -void cxl_guest_remove_chardev(struct cxl *adapter); -void cxl_guest_reload_module(struct cxl *adapter); -int cxl_of_probe(struct platform_device *pdev); - -struct cxl_backend_ops { - struct module *module; - int (*adapter_reset)(struct cxl *adapter); - int (*alloc_one_irq)(struct cxl *adapter); - void (*release_one_irq)(struct cxl *adapter, int hwirq); - int (*alloc_irq_ranges)(struct cxl_irq_ranges *irqs, - struct cxl *adapter, unsigned int num); - void (*release_irq_ranges)(struct cxl_irq_ranges *irqs, - struct cxl *adapter); - int (*setup_irq)(struct cxl *adapter, unsigned int hwirq, - unsigned int virq); - irqreturn_t (*handle_psl_slice_error)(struct cxl_context *ctx, - u64 dsisr, u64 errstat); - irqreturn_t (*psl_interrupt)(int irq, void *data); - int (*ack_irq)(struct cxl_context *ctx, u64 tfc, u64 psl_reset_mask); - void (*irq_wait)(struct cxl_context *ctx); - int (*attach_process)(struct cxl_context *ctx, bool kernel, - u64 wed, u64 amr); - int (*detach_process)(struct cxl_context *ctx); - void (*update_ivtes)(struct cxl_context *ctx); - bool (*support_attributes)(const char *attr_name, enum cxl_attrs type); - bool (*link_ok)(struct cxl *cxl, struct cxl_afu *afu); - void (*release_afu)(struct device *dev); - ssize_t (*afu_read_err_buffer)(struct cxl_afu *afu, char *buf, - loff_t off, size_t count); - int (*afu_check_and_enable)(struct cxl_afu *afu); - int (*afu_activate_mode)(struct cxl_afu *afu, int mode); - int (*afu_deactivate_mode)(struct cxl_afu *afu, int mode); - int (*afu_reset)(struct cxl_afu *afu); - int (*afu_cr_read8)(struct cxl_afu *afu, int cr_idx, u64 offset, u8 *val); - int (*afu_cr_read16)(struct cxl_afu *afu, int cr_idx, u64 offset, u16 *val); - int (*afu_cr_read32)(struct cxl_afu *afu, int cr_idx, u64 offset, u32 *val); - int (*afu_cr_read64)(struct cxl_afu *afu, int cr_idx, u64 offset, u64 *val); - int (*afu_cr_write8)(struct cxl_afu *afu, int cr_idx, u64 offset, u8 val); - int (*afu_cr_write16)(struct cxl_afu *afu, int cr_idx, u64 offset, u16 val); - int (*afu_cr_write32)(struct cxl_afu *afu, int cr_idx, u64 offset, u32 val); - ssize_t (*read_adapter_vpd)(struct cxl *adapter, void *buf, size_t count); -}; -extern const struct cxl_backend_ops cxl_native_ops; -extern const struct cxl_backend_ops cxl_guest_ops; -extern const struct cxl_backend_ops *cxl_ops; - -/* check if the given pci_dev is on the cxl vphb bus */ -bool cxl_pci_is_vphb_device(struct pci_dev *dev); - -/* decode AFU error bits in the PSL register PSL_SERR_An */ -void cxl_afu_decode_psl_serr(struct cxl_afu *afu, u64 serr); - -/* - * Increments the number of attached contexts on an adapter. - * In case an adapter_context_lock is taken the return -EBUSY. - */ -int cxl_adapter_context_get(struct cxl *adapter); - -/* Decrements the number of attached contexts on an adapter */ -void cxl_adapter_context_put(struct cxl *adapter); - -/* If no active contexts then prevents contexts from being attached */ -int cxl_adapter_context_lock(struct cxl *adapter); - -/* Unlock the contexts-lock if taken. Warn and force unlock otherwise */ -void cxl_adapter_context_unlock(struct cxl *adapter); - -/* Increases the reference count to "struct mm_struct" */ -void cxl_context_mm_count_get(struct cxl_context *ctx); - -/* Decrements the reference count to "struct mm_struct" */ -void cxl_context_mm_count_put(struct cxl_context *ctx); - -#endif
diff --git a/drivers/misc/cxl/cxllib.c b/drivers/misc/cxl/cxllib.c deleted file mode 100644 index e5fe0a1..0000000 --- a/drivers/misc/cxl/cxllib.c +++ /dev/null
@@ -1,271 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Copyright 2017 IBM Corp. - */ - -#include <linux/hugetlb.h> -#include <linux/sched/mm.h> -#include <asm/opal-api.h> -#include <asm/pnv-pci.h> -#include <misc/cxllib.h> - -#include "cxl.h" - -#define CXL_INVALID_DRA ~0ull -#define CXL_DUMMY_READ_SIZE 128 -#define CXL_DUMMY_READ_ALIGN 8 -#define CXL_CAPI_WINDOW_START 0x2000000000000ull -#define CXL_CAPI_WINDOW_LOG_SIZE 48 -#define CXL_XSL_CONFIG_CURRENT_VERSION CXL_XSL_CONFIG_VERSION1 - - -bool cxllib_slot_is_supported(struct pci_dev *dev, unsigned long flags) -{ - int rc; - u32 phb_index; - u64 chip_id, capp_unit_id; - - /* No flags currently supported */ - if (flags) - return false; - - if (!cpu_has_feature(CPU_FTR_HVMODE)) - return false; - - if (!cxl_is_power9()) - return false; - - if (cxl_slot_is_switched(dev)) - return false; - - /* on p9, some pci slots are not connected to a CAPP unit */ - rc = cxl_calc_capp_routing(dev, &chip_id, &phb_index, &capp_unit_id); - if (rc) - return false; - - return true; -} -EXPORT_SYMBOL_GPL(cxllib_slot_is_supported); - -static DEFINE_MUTEX(dra_mutex); -static u64 dummy_read_addr = CXL_INVALID_DRA; - -static int allocate_dummy_read_buf(void) -{ - u64 buf, vaddr; - size_t buf_size; - - /* - * Dummy read buffer is 128-byte long, aligned on a - * 256-byte boundary and we need the physical address. - */ - buf_size = CXL_DUMMY_READ_SIZE + (1ull << CXL_DUMMY_READ_ALIGN); - buf = (u64) kzalloc(buf_size, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - vaddr = (buf + (1ull << CXL_DUMMY_READ_ALIGN) - 1) & - (~0ull << CXL_DUMMY_READ_ALIGN); - - WARN((vaddr + CXL_DUMMY_READ_SIZE) > (buf + buf_size), - "Dummy read buffer alignment issue"); - dummy_read_addr = virt_to_phys((void *) vaddr); - return 0; -} - -int cxllib_get_xsl_config(struct pci_dev *dev, struct cxllib_xsl_config *cfg) -{ - int rc; - u32 phb_index; - u64 chip_id, capp_unit_id; - - if (!cpu_has_feature(CPU_FTR_HVMODE)) - return -EINVAL; - - mutex_lock(&dra_mutex); - if (dummy_read_addr == CXL_INVALID_DRA) { - rc = allocate_dummy_read_buf(); - if (rc) { - mutex_unlock(&dra_mutex); - return rc; - } - } - mutex_unlock(&dra_mutex); - - rc = cxl_calc_capp_routing(dev, &chip_id, &phb_index, &capp_unit_id); - if (rc) - return rc; - - rc = cxl_get_xsl9_dsnctl(dev, capp_unit_id, &cfg->dsnctl); - if (rc) - return rc; - - cfg->version = CXL_XSL_CONFIG_CURRENT_VERSION; - cfg->log_bar_size = CXL_CAPI_WINDOW_LOG_SIZE; - cfg->bar_addr = CXL_CAPI_WINDOW_START; - cfg->dra = dummy_read_addr; - return 0; -} -EXPORT_SYMBOL_GPL(cxllib_get_xsl_config); - -int cxllib_switch_phb_mode(struct pci_dev *dev, enum cxllib_mode mode, - unsigned long flags) -{ - int rc = 0; - - if (!cpu_has_feature(CPU_FTR_HVMODE)) - return -EINVAL; - - switch (mode) { - case CXL_MODE_PCI: - /* - * We currently don't support going back to PCI mode - * However, we'll turn the invalidations off, so that - * the firmware doesn't have to ack them and can do - * things like reset, etc.. with no worries. - * So always return EPERM (can't go back to PCI) or - * EBUSY if we couldn't even turn off snooping - */ - rc = pnv_phb_to_cxl_mode(dev, OPAL_PHB_CAPI_MODE_SNOOP_OFF); - if (rc) - rc = -EBUSY; - else - rc = -EPERM; - break; - case CXL_MODE_CXL: - /* DMA only supported on TVT1 for the time being */ - if (flags != CXL_MODE_DMA_TVT1) - return -EINVAL; - rc = pnv_phb_to_cxl_mode(dev, OPAL_PHB_CAPI_MODE_DMA_TVT1); - if (rc) - return rc; - rc = pnv_phb_to_cxl_mode(dev, OPAL_PHB_CAPI_MODE_SNOOP_ON); - break; - default: - rc = -EINVAL; - } - return rc; -} -EXPORT_SYMBOL_GPL(cxllib_switch_phb_mode); - -/* - * When switching the PHB to capi mode, the TVT#1 entry for - * the Partitionable Endpoint is set in bypass mode, like - * in PCI mode. - * Configure the device dma to use TVT#1, which is done - * by calling dma_set_mask() with a mask large enough. - */ -int cxllib_set_device_dma(struct pci_dev *dev, unsigned long flags) -{ - int rc; - - if (flags) - return -EINVAL; - - rc = dma_set_mask(&dev->dev, DMA_BIT_MASK(64)); - return rc; -} -EXPORT_SYMBOL_GPL(cxllib_set_device_dma); - -int cxllib_get_PE_attributes(struct task_struct *task, - unsigned long translation_mode, - struct cxllib_pe_attributes *attr) -{ - if (translation_mode != CXL_TRANSLATED_MODE && - translation_mode != CXL_REAL_MODE) - return -EINVAL; - - attr->sr = cxl_calculate_sr(false, - task == NULL, - translation_mode == CXL_REAL_MODE, - true); - attr->lpid = mfspr(SPRN_LPID); - if (task) { - struct mm_struct *mm = get_task_mm(task); - if (mm == NULL) - return -EINVAL; - /* - * Caller is keeping a reference on mm_users for as long - * as XSL uses the memory context - */ - attr->pid = mm->context.id; - mmput(mm); - attr->tid = task->thread.tidr; - } else { - attr->pid = 0; - attr->tid = 0; - } - return 0; -} -EXPORT_SYMBOL_GPL(cxllib_get_PE_attributes); - -static int get_vma_info(struct mm_struct *mm, u64 addr, - u64 *vma_start, u64 *vma_end, - unsigned long *page_size) -{ - struct vm_area_struct *vma = NULL; - int rc = 0; - - mmap_read_lock(mm); - - vma = find_vma(mm, addr); - if (!vma) { - rc = -EFAULT; - goto out; - } - *page_size = vma_kernel_pagesize(vma); - *vma_start = vma->vm_start; - *vma_end = vma->vm_end; -out: - mmap_read_unlock(mm); - return rc; -} - -int cxllib_handle_fault(struct mm_struct *mm, u64 addr, u64 size, u64 flags) -{ - int rc; - u64 dar, vma_start, vma_end; - unsigned long page_size; - - if (mm == NULL) - return -EFAULT; - - /* - * The buffer we have to process can extend over several pages - * and may also cover several VMAs. - * We iterate over all the pages. The page size could vary - * between VMAs. - */ - rc = get_vma_info(mm, addr, &vma_start, &vma_end, &page_size); - if (rc) - return rc; - - for (dar = (addr & ~(page_size - 1)); dar < (addr + size); - dar += page_size) { - if (dar < vma_start || dar >= vma_end) { - /* - * We don't hold mm->mmap_lock while iterating, since - * the lock is required by one of the lower-level page - * fault processing functions and it could - * create a deadlock. - * - * It means the VMAs can be altered between 2 - * loop iterations and we could theoretically - * miss a page (however unlikely). But that's - * not really a problem, as the driver will - * retry access, get another page fault on the - * missing page and call us again. - */ - rc = get_vma_info(mm, dar, &vma_start, &vma_end, - &page_size); - if (rc) - return rc; - } - - rc = cxl_handle_mm_fault(mm, flags, dar); - if (rc) - return -EFAULT; - } - return 0; -} -EXPORT_SYMBOL_GPL(cxllib_handle_fault);
diff --git a/drivers/misc/cxl/debugfs.c b/drivers/misc/cxl/debugfs.c deleted file mode 100644 index 7b987bf..0000000 --- a/drivers/misc/cxl/debugfs.c +++ /dev/null
@@ -1,134 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Copyright 2014 IBM Corp. - */ - -#include <linux/debugfs.h> -#include <linux/kernel.h> -#include <linux/slab.h> - -#include "cxl.h" - -static struct dentry *cxl_debugfs; - -/* Helpers to export CXL mmaped IO registers via debugfs */ -static int debugfs_io_u64_get(void *data, u64 *val) -{ - *val = in_be64((u64 __iomem *)data); - return 0; -} - -static int debugfs_io_u64_set(void *data, u64 val) -{ - out_be64((u64 __iomem *)data, val); - return 0; -} -DEFINE_DEBUGFS_ATTRIBUTE(fops_io_x64, debugfs_io_u64_get, debugfs_io_u64_set, - "0x%016llx\n"); - -static void debugfs_create_io_x64(const char *name, umode_t mode, - struct dentry *parent, u64 __iomem *value) -{ - debugfs_create_file_unsafe(name, mode, parent, (void __force *)value, - &fops_io_x64); -} - -void cxl_debugfs_add_adapter_regs_psl9(struct cxl *adapter, struct dentry *dir) -{ - debugfs_create_io_x64("fir1", S_IRUSR, dir, _cxl_p1_addr(adapter, CXL_PSL9_FIR1)); - debugfs_create_io_x64("fir_mask", 0400, dir, - _cxl_p1_addr(adapter, CXL_PSL9_FIR_MASK)); - debugfs_create_io_x64("fir_cntl", S_IRUSR, dir, _cxl_p1_addr(adapter, CXL_PSL9_FIR_CNTL)); - debugfs_create_io_x64("trace", S_IRUSR | S_IWUSR, dir, _cxl_p1_addr(adapter, CXL_PSL9_TRACECFG)); - debugfs_create_io_x64("debug", 0600, dir, - _cxl_p1_addr(adapter, CXL_PSL9_DEBUG)); - debugfs_create_io_x64("xsl-debug", 0600, dir, - _cxl_p1_addr(adapter, CXL_XSL9_DBG)); -} - -void cxl_debugfs_add_adapter_regs_psl8(struct cxl *adapter, struct dentry *dir) -{ - debugfs_create_io_x64("fir1", S_IRUSR, dir, _cxl_p1_addr(adapter, CXL_PSL_FIR1)); - debugfs_create_io_x64("fir2", S_IRUSR, dir, _cxl_p1_addr(adapter, CXL_PSL_FIR2)); - debugfs_create_io_x64("fir_cntl", S_IRUSR, dir, _cxl_p1_addr(adapter, CXL_PSL_FIR_CNTL)); - debugfs_create_io_x64("trace", S_IRUSR | S_IWUSR, dir, _cxl_p1_addr(adapter, CXL_PSL_TRACE)); -} - -void cxl_debugfs_adapter_add(struct cxl *adapter) -{ - struct dentry *dir; - char buf[32]; - - if (!cxl_debugfs) - return; - - snprintf(buf, 32, "card%i", adapter->adapter_num); - dir = debugfs_create_dir(buf, cxl_debugfs); - adapter->debugfs = dir; - - 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) - adapter->native->sl_ops->debugfs_add_adapter_regs(adapter, dir); -} - -void cxl_debugfs_adapter_remove(struct cxl *adapter) -{ - debugfs_remove_recursive(adapter->debugfs); -} - -void cxl_debugfs_add_afu_regs_psl9(struct cxl_afu *afu, struct dentry *dir) -{ - debugfs_create_io_x64("serr", S_IRUSR, dir, _cxl_p1n_addr(afu, CXL_PSL_SERR_An)); -} - -void cxl_debugfs_add_afu_regs_psl8(struct cxl_afu *afu, struct dentry *dir) -{ - debugfs_create_io_x64("sstp0", S_IRUSR, dir, _cxl_p2n_addr(afu, CXL_SSTP0_An)); - debugfs_create_io_x64("sstp1", S_IRUSR, dir, _cxl_p2n_addr(afu, CXL_SSTP1_An)); - - debugfs_create_io_x64("fir", S_IRUSR, dir, _cxl_p1n_addr(afu, CXL_PSL_FIR_SLICE_An)); - debugfs_create_io_x64("serr", S_IRUSR, dir, _cxl_p1n_addr(afu, CXL_PSL_SERR_An)); - debugfs_create_io_x64("afu_debug", S_IRUSR, dir, _cxl_p1n_addr(afu, CXL_AFU_DEBUG_An)); - debugfs_create_io_x64("trace", S_IRUSR | S_IWUSR, dir, _cxl_p1n_addr(afu, CXL_PSL_SLICE_TRACE)); -} - -void cxl_debugfs_afu_add(struct cxl_afu *afu) -{ - struct dentry *dir; - char buf[32]; - - if (!afu->adapter->debugfs) - return; - - snprintf(buf, 32, "psl%i.%i", afu->adapter->adapter_num, afu->slice); - dir = debugfs_create_dir(buf, afu->adapter->debugfs); - afu->debugfs = dir; - - debugfs_create_io_x64("sr", S_IRUSR, dir, _cxl_p1n_addr(afu, CXL_PSL_SR_An)); - debugfs_create_io_x64("dsisr", S_IRUSR, dir, _cxl_p2n_addr(afu, CXL_PSL_DSISR_An)); - debugfs_create_io_x64("dar", S_IRUSR, dir, _cxl_p2n_addr(afu, CXL_PSL_DAR_An)); - - debugfs_create_io_x64("err_status", S_IRUSR, dir, _cxl_p2n_addr(afu, CXL_PSL_ErrStat_An)); - - if (afu->adapter->native->sl_ops->debugfs_add_afu_regs) - afu->adapter->native->sl_ops->debugfs_add_afu_regs(afu, dir); -} - -void cxl_debugfs_afu_remove(struct cxl_afu *afu) -{ - debugfs_remove_recursive(afu->debugfs); -} - -void __init cxl_debugfs_init(void) -{ - if (!cpu_has_feature(CPU_FTR_HVMODE)) - return; - - cxl_debugfs = debugfs_create_dir("cxl", NULL); -} - -void cxl_debugfs_exit(void) -{ - debugfs_remove_recursive(cxl_debugfs); -}
diff --git a/drivers/misc/cxl/fault.c b/drivers/misc/cxl/fault.c deleted file mode 100644 index 2c64f55..0000000 --- a/drivers/misc/cxl/fault.c +++ /dev/null
@@ -1,341 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Copyright 2014 IBM Corp. - */ - -#include <linux/workqueue.h> -#include <linux/sched/signal.h> -#include <linux/sched/mm.h> -#include <linux/pid.h> -#include <linux/mm.h> -#include <linux/moduleparam.h> - -#undef MODULE_PARAM_PREFIX -#define MODULE_PARAM_PREFIX "cxl" "." -#include <asm/current.h> -#include <asm/copro.h> -#include <asm/mmu.h> - -#include "cxl.h" -#include "trace.h" - -static bool sste_matches(struct cxl_sste *sste, struct copro_slb *slb) -{ - return ((sste->vsid_data == cpu_to_be64(slb->vsid)) && - (sste->esid_data == cpu_to_be64(slb->esid))); -} - -/* - * This finds a free SSTE for the given SLB, or returns NULL if it's already in - * the segment table. - */ -static struct cxl_sste *find_free_sste(struct cxl_context *ctx, - struct copro_slb *slb) -{ - struct cxl_sste *primary, *sste, *ret = NULL; - unsigned int mask = (ctx->sst_size >> 7) - 1; /* SSTP0[SegTableSize] */ - unsigned int entry; - unsigned int hash; - - if (slb->vsid & SLB_VSID_B_1T) - hash = (slb->esid >> SID_SHIFT_1T) & mask; - else /* 256M */ - hash = (slb->esid >> SID_SHIFT) & mask; - - primary = ctx->sstp + (hash << 3); - - for (entry = 0, sste = primary; entry < 8; entry++, sste++) { - if (!ret && !(be64_to_cpu(sste->esid_data) & SLB_ESID_V)) - ret = sste; - if (sste_matches(sste, slb)) - return NULL; - } - if (ret) - return ret; - - /* Nothing free, select an entry to cast out */ - ret = primary + ctx->sst_lru; - ctx->sst_lru = (ctx->sst_lru + 1) & 0x7; - - return ret; -} - -static void cxl_load_segment(struct cxl_context *ctx, struct copro_slb *slb) -{ - /* mask is the group index, we search primary and secondary here. */ - struct cxl_sste *sste; - unsigned long flags; - - spin_lock_irqsave(&ctx->sste_lock, flags); - sste = find_free_sste(ctx, slb); - if (!sste) - goto out_unlock; - - pr_devel("CXL Populating SST[%li]: %#llx %#llx\n", - sste - ctx->sstp, slb->vsid, slb->esid); - trace_cxl_ste_write(ctx, sste - ctx->sstp, slb->esid, slb->vsid); - - sste->vsid_data = cpu_to_be64(slb->vsid); - sste->esid_data = cpu_to_be64(slb->esid); -out_unlock: - spin_unlock_irqrestore(&ctx->sste_lock, flags); -} - -static int cxl_fault_segment(struct cxl_context *ctx, struct mm_struct *mm, - u64 ea) -{ - struct copro_slb slb = {0,0}; - int rc; - - if (!(rc = copro_calculate_slb(mm, ea, &slb))) { - cxl_load_segment(ctx, &slb); - } - - return rc; -} - -static void cxl_ack_ae(struct cxl_context *ctx) -{ - unsigned long flags; - - cxl_ops->ack_irq(ctx, CXL_PSL_TFC_An_AE, 0); - - spin_lock_irqsave(&ctx->lock, flags); - ctx->pending_fault = true; - ctx->fault_addr = ctx->dar; - ctx->fault_dsisr = ctx->dsisr; - spin_unlock_irqrestore(&ctx->lock, flags); - - wake_up_all(&ctx->wq); -} - -static int cxl_handle_segment_miss(struct cxl_context *ctx, - struct mm_struct *mm, u64 ea) -{ - int rc; - - pr_devel("CXL interrupt: Segment fault pe: %i ea: %#llx\n", ctx->pe, ea); - trace_cxl_ste_miss(ctx, ea); - - if ((rc = cxl_fault_segment(ctx, mm, ea))) - cxl_ack_ae(ctx); - else { - - mb(); /* Order seg table write to TFC MMIO write */ - cxl_ops->ack_irq(ctx, CXL_PSL_TFC_An_R, 0); - } - - return IRQ_HANDLED; -} - -int cxl_handle_mm_fault(struct mm_struct *mm, u64 dsisr, u64 dar) -{ - vm_fault_t flt = 0; - int result; - unsigned long access, flags, inv_flags = 0; - - /* - * Add the fault handling cpu to task mm cpumask so that we - * can do a safe lockless page table walk when inserting the - * hash page table entry. This function get called with a - * valid mm for user space addresses. Hence using the if (mm) - * check is sufficient here. - */ - if (mm && !cpumask_test_cpu(smp_processor_id(), mm_cpumask(mm))) { - cpumask_set_cpu(smp_processor_id(), mm_cpumask(mm)); - /* - * We need to make sure we walk the table only after - * we update the cpumask. The other side of the barrier - * is explained in serialize_against_pte_lookup() - */ - smp_mb(); - } - if ((result = copro_handle_mm_fault(mm, dar, dsisr, &flt))) { - pr_devel("copro_handle_mm_fault failed: %#x\n", result); - return result; - } - - if (!radix_enabled()) { - /* - * update_mmu_cache() will not have loaded the hash since current->trap - * is not a 0x400 or 0x300, so just call hash_page_mm() here. - */ - access = _PAGE_PRESENT | _PAGE_READ; - if (dsisr & CXL_PSL_DSISR_An_S) - access |= _PAGE_WRITE; - - if (!mm && (get_region_id(dar) != USER_REGION_ID)) - access |= _PAGE_PRIVILEGED; - - if (dsisr & DSISR_NOHPTE) - inv_flags |= HPTE_NOHPTE_UPDATE; - - local_irq_save(flags); - hash_page_mm(mm, dar, access, 0x300, inv_flags); - local_irq_restore(flags); - } - return 0; -} - -static void cxl_handle_page_fault(struct cxl_context *ctx, - struct mm_struct *mm, - u64 dsisr, u64 dar) -{ - trace_cxl_pte_miss(ctx, dsisr, dar); - - if (cxl_handle_mm_fault(mm, dsisr, dar)) { - cxl_ack_ae(ctx); - } else { - pr_devel("Page fault successfully handled for pe: %i!\n", ctx->pe); - cxl_ops->ack_irq(ctx, CXL_PSL_TFC_An_R, 0); - } -} - -/* - * Returns the mm_struct corresponding to the context ctx. - * mm_users == 0, the context may be in the process of being closed. - */ -static struct mm_struct *get_mem_context(struct cxl_context *ctx) -{ - if (ctx->mm == NULL) - return NULL; - - if (!mmget_not_zero(ctx->mm)) - return NULL; - - return ctx->mm; -} - -static bool cxl_is_segment_miss(struct cxl_context *ctx, u64 dsisr) -{ - if ((cxl_is_power8() && (dsisr & CXL_PSL_DSISR_An_DS))) - return true; - - return false; -} - -static bool cxl_is_page_fault(struct cxl_context *ctx, u64 dsisr) -{ - if ((cxl_is_power8()) && (dsisr & CXL_PSL_DSISR_An_DM)) - return true; - - if (cxl_is_power9()) - return true; - - return false; -} - -void cxl_handle_fault(struct work_struct *fault_work) -{ - struct cxl_context *ctx = - container_of(fault_work, struct cxl_context, fault_work); - u64 dsisr = ctx->dsisr; - u64 dar = ctx->dar; - struct mm_struct *mm = NULL; - - if (cpu_has_feature(CPU_FTR_HVMODE)) { - if (cxl_p2n_read(ctx->afu, CXL_PSL_DSISR_An) != dsisr || - cxl_p2n_read(ctx->afu, CXL_PSL_DAR_An) != dar || - cxl_p2n_read(ctx->afu, CXL_PSL_PEHandle_An) != ctx->pe) { - /* Most likely explanation is harmless - a dedicated - * process has detached and these were cleared by the - * PSL purge, but warn about it just in case - */ - dev_notice(&ctx->afu->dev, "cxl_handle_fault: Translation fault regs changed\n"); - return; - } - } - - /* Early return if the context is being / has been detached */ - if (ctx->status == CLOSED) { - cxl_ack_ae(ctx); - return; - } - - pr_devel("CXL BOTTOM HALF handling fault for afu pe: %i. " - "DSISR: %#llx DAR: %#llx\n", ctx->pe, dsisr, dar); - - if (!ctx->kernel) { - - mm = get_mem_context(ctx); - if (mm == NULL) { - pr_devel("%s: unable to get mm for pe=%d pid=%i\n", - __func__, ctx->pe, pid_nr(ctx->pid)); - cxl_ack_ae(ctx); - return; - } else { - pr_devel("Handling page fault for pe=%d pid=%i\n", - ctx->pe, pid_nr(ctx->pid)); - } - } - - if (cxl_is_segment_miss(ctx, dsisr)) - cxl_handle_segment_miss(ctx, mm, dar); - else if (cxl_is_page_fault(ctx, dsisr)) - cxl_handle_page_fault(ctx, mm, dsisr, dar); - else - WARN(1, "cxl_handle_fault has nothing to handle\n"); - - if (mm) - mmput(mm); -} - -static u64 next_segment(u64 ea, u64 vsid) -{ - if (vsid & SLB_VSID_B_1T) - ea |= (1ULL << 40) - 1; - else - ea |= (1ULL << 28) - 1; - - return ea + 1; -} - -static void cxl_prefault_vma(struct cxl_context *ctx, struct mm_struct *mm) -{ - u64 ea, last_esid = 0; - struct copro_slb slb; - VMA_ITERATOR(vmi, mm, 0); - struct vm_area_struct *vma; - int rc; - - mmap_read_lock(mm); - for_each_vma(vmi, vma) { - for (ea = vma->vm_start; ea < vma->vm_end; - ea = next_segment(ea, slb.vsid)) { - rc = copro_calculate_slb(mm, ea, &slb); - if (rc) - continue; - - if (last_esid == slb.esid) - continue; - - cxl_load_segment(ctx, &slb); - last_esid = slb.esid; - } - } - mmap_read_unlock(mm); -} - -void cxl_prefault(struct cxl_context *ctx, u64 wed) -{ - struct mm_struct *mm = get_mem_context(ctx); - - if (mm == NULL) { - pr_devel("cxl_prefault unable to get mm %i\n", - pid_nr(ctx->pid)); - return; - } - - switch (ctx->afu->prefault_mode) { - case CXL_PREFAULT_WED: - cxl_fault_segment(ctx, mm, wed); - break; - case CXL_PREFAULT_ALL: - cxl_prefault_vma(ctx, mm); - break; - default: - break; - } - - mmput(mm); -}
diff --git a/drivers/misc/cxl/file.c b/drivers/misc/cxl/file.c deleted file mode 100644 index 012e11b..0000000 --- a/drivers/misc/cxl/file.c +++ /dev/null
@@ -1,699 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Copyright 2014 IBM Corp. - */ - -#include <linux/spinlock.h> -#include <linux/module.h> -#include <linux/export.h> -#include <linux/kernel.h> -#include <linux/bitmap.h> -#include <linux/sched/signal.h> -#include <linux/poll.h> -#include <linux/pid.h> -#include <linux/fs.h> -#include <linux/mm.h> -#include <linux/slab.h> -#include <linux/sched/mm.h> -#include <linux/mmu_context.h> -#include <asm/cputable.h> -#include <asm/current.h> -#include <asm/copro.h> - -#include "cxl.h" -#include "trace.h" - -#define CXL_NUM_MINORS 256 /* Total to reserve */ - -#define CXL_AFU_MINOR_D(afu) (CXL_CARD_MINOR(afu->adapter) + 1 + (3 * afu->slice)) -#define CXL_AFU_MINOR_M(afu) (CXL_AFU_MINOR_D(afu) + 1) -#define CXL_AFU_MINOR_S(afu) (CXL_AFU_MINOR_D(afu) + 2) -#define CXL_AFU_MKDEV_D(afu) MKDEV(MAJOR(cxl_dev), CXL_AFU_MINOR_D(afu)) -#define CXL_AFU_MKDEV_M(afu) MKDEV(MAJOR(cxl_dev), CXL_AFU_MINOR_M(afu)) -#define CXL_AFU_MKDEV_S(afu) MKDEV(MAJOR(cxl_dev), CXL_AFU_MINOR_S(afu)) - -#define CXL_DEVT_AFU(dev) ((MINOR(dev) % CXL_DEV_MINORS - 1) / 3) - -#define CXL_DEVT_IS_CARD(dev) (MINOR(dev) % CXL_DEV_MINORS == 0) - -static dev_t cxl_dev; - -static int __afu_open(struct inode *inode, struct file *file, bool master) -{ - struct cxl *adapter; - struct cxl_afu *afu; - struct cxl_context *ctx; - int adapter_num = CXL_DEVT_ADAPTER(inode->i_rdev); - int slice = CXL_DEVT_AFU(inode->i_rdev); - int rc = -ENODEV; - - pr_devel("afu_open afu%i.%i\n", slice, adapter_num); - - if (!(adapter = get_cxl_adapter(adapter_num))) - return -ENODEV; - - if (slice > adapter->slices) - goto err_put_adapter; - - spin_lock(&adapter->afu_list_lock); - if (!(afu = adapter->afu[slice])) { - spin_unlock(&adapter->afu_list_lock); - goto err_put_adapter; - } - - /* - * taking a ref to the afu so that it doesn't go away - * for rest of the function. This ref is released before - * we return. - */ - cxl_afu_get(afu); - spin_unlock(&adapter->afu_list_lock); - - if (!afu->current_mode) - goto err_put_afu; - - if (!cxl_ops->link_ok(adapter, afu)) { - rc = -EIO; - goto err_put_afu; - } - - if (!(ctx = cxl_context_alloc())) { - rc = -ENOMEM; - goto err_put_afu; - } - - rc = cxl_context_init(ctx, afu, master); - if (rc) - goto err_put_afu; - - cxl_context_set_mapping(ctx, inode->i_mapping); - - pr_devel("afu_open pe: %i\n", ctx->pe); - file->private_data = ctx; - - /* indicate success */ - rc = 0; - -err_put_afu: - /* release the ref taken earlier */ - cxl_afu_put(afu); -err_put_adapter: - put_device(&adapter->dev); - return rc; -} - -int afu_open(struct inode *inode, struct file *file) -{ - return __afu_open(inode, file, false); -} - -static int afu_master_open(struct inode *inode, struct file *file) -{ - return __afu_open(inode, file, true); -} - -int afu_release(struct inode *inode, struct file *file) -{ - struct cxl_context *ctx = file->private_data; - - pr_devel("%s: closing cxl file descriptor. pe: %i\n", - __func__, ctx->pe); - cxl_context_detach(ctx); - - - /* - * Delete the context's mapping pointer, unless it's created by the - * kernel API, in which case leave it so it can be freed by reclaim_ctx() - */ - if (!ctx->kernelapi) { - mutex_lock(&ctx->mapping_lock); - ctx->mapping = NULL; - mutex_unlock(&ctx->mapping_lock); - } - - /* - * At this this point all bottom halfs have finished and we should be - * getting no more IRQs from the hardware for this context. Once it's - * removed from the IDR (and RCU synchronised) it's safe to free the - * sstp and context. - */ - cxl_context_free(ctx); - - return 0; -} - -static long afu_ioctl_start_work(struct cxl_context *ctx, - struct cxl_ioctl_start_work __user *uwork) -{ - struct cxl_ioctl_start_work work; - u64 amr = 0; - int rc; - - pr_devel("%s: pe: %i\n", __func__, ctx->pe); - - /* Do this outside the status_mutex to avoid a circular dependency with - * the locking in cxl_mmap_fault() */ - if (copy_from_user(&work, uwork, sizeof(work))) - return -EFAULT; - - mutex_lock(&ctx->status_mutex); - if (ctx->status != OPENED) { - rc = -EIO; - goto out; - } - - /* - * if any of the reserved fields are set or any of the unused - * flags are set it's invalid - */ - if (work.reserved1 || work.reserved2 || work.reserved3 || - work.reserved4 || work.reserved5 || - (work.flags & ~CXL_START_WORK_ALL)) { - rc = -EINVAL; - goto out; - } - - if (!(work.flags & CXL_START_WORK_NUM_IRQS)) - work.num_interrupts = ctx->afu->pp_irqs; - else if ((work.num_interrupts < ctx->afu->pp_irqs) || - (work.num_interrupts > ctx->afu->irqs_max)) { - rc = -EINVAL; - goto out; - } - - if ((rc = afu_register_irqs(ctx, work.num_interrupts))) - goto out; - - if (work.flags & CXL_START_WORK_AMR) - amr = work.amr & mfspr(SPRN_UAMOR); - - if (work.flags & CXL_START_WORK_TID) - ctx->assign_tidr = true; - - ctx->mmio_err_ff = !!(work.flags & CXL_START_WORK_ERR_FF); - - /* - * Increment the mapped context count for adapter. This also checks - * if adapter_context_lock is taken. - */ - rc = cxl_adapter_context_get(ctx->afu->adapter); - if (rc) { - afu_release_irqs(ctx, ctx); - goto out; - } - - /* - * We grab the PID here and not in the file open to allow for the case - * where a process (master, some daemon, etc) has opened the chardev on - * behalf of another process, so the AFU's mm gets bound to the process - * that performs this ioctl and not the process that opened the file. - * Also we grab the PID of the group leader so that if the task that - * has performed the attach operation exits the mm context of the - * process is still accessible. - */ - ctx->pid = get_task_pid(current, PIDTYPE_PID); - - /* acquire a reference to the task's mm */ - ctx->mm = get_task_mm(current); - - /* ensure this mm_struct can't be freed */ - cxl_context_mm_count_get(ctx); - - if (ctx->mm) { - /* decrement the use count from above */ - mmput(ctx->mm); - /* make TLBIs for this context global */ - mm_context_add_copro(ctx->mm); - } - - /* - * Increment driver use count. Enables global TLBIs for hash - * and callbacks to handle the segment table - */ - cxl_ctx_get(); - - /* - * A barrier is needed to make sure all TLBIs are global - * before we attach and the context starts being used by the - * adapter. - * - * Needed after mm_context_add_copro() for radix and - * cxl_ctx_get() for hash/p8. - * - * The barrier should really be mb(), since it involves a - * device. However, it's only useful when we have local - * vs. global TLBIs, i.e SMP=y. So keep smp_mb(). - */ - smp_mb(); - - trace_cxl_attach(ctx, work.work_element_descriptor, work.num_interrupts, amr); - - if ((rc = cxl_ops->attach_process(ctx, false, work.work_element_descriptor, - amr))) { - afu_release_irqs(ctx, ctx); - cxl_adapter_context_put(ctx->afu->adapter); - put_pid(ctx->pid); - ctx->pid = NULL; - cxl_ctx_put(); - cxl_context_mm_count_put(ctx); - if (ctx->mm) - mm_context_remove_copro(ctx->mm); - goto out; - } - - rc = 0; - if (work.flags & CXL_START_WORK_TID) { - work.tid = ctx->tidr; - if (copy_to_user(uwork, &work, sizeof(work))) - rc = -EFAULT; - } - - ctx->status = STARTED; - -out: - mutex_unlock(&ctx->status_mutex); - return rc; -} - -static long afu_ioctl_process_element(struct cxl_context *ctx, - int __user *upe) -{ - pr_devel("%s: pe: %i\n", __func__, ctx->pe); - - if (copy_to_user(upe, &ctx->external_pe, sizeof(__u32))) - return -EFAULT; - - return 0; -} - -static long afu_ioctl_get_afu_id(struct cxl_context *ctx, - struct cxl_afu_id __user *upafuid) -{ - struct cxl_afu_id afuid = { 0 }; - - afuid.card_id = ctx->afu->adapter->adapter_num; - afuid.afu_offset = ctx->afu->slice; - afuid.afu_mode = ctx->afu->current_mode; - - /* set the flag bit in case the afu is a slave */ - if (ctx->afu->current_mode == CXL_MODE_DIRECTED && !ctx->master) - afuid.flags |= CXL_AFUID_FLAG_SLAVE; - - if (copy_to_user(upafuid, &afuid, sizeof(afuid))) - return -EFAULT; - - return 0; -} - -long afu_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -{ - struct cxl_context *ctx = file->private_data; - - if (ctx->status == CLOSED) - return -EIO; - - if (!cxl_ops->link_ok(ctx->afu->adapter, ctx->afu)) - return -EIO; - - pr_devel("afu_ioctl\n"); - switch (cmd) { - case CXL_IOCTL_START_WORK: - return afu_ioctl_start_work(ctx, (struct cxl_ioctl_start_work __user *)arg); - case CXL_IOCTL_GET_PROCESS_ELEMENT: - return afu_ioctl_process_element(ctx, (__u32 __user *)arg); - case CXL_IOCTL_GET_AFU_ID: - return afu_ioctl_get_afu_id(ctx, (struct cxl_afu_id __user *) - arg); - } - return -EINVAL; -} - -static long afu_compat_ioctl(struct file *file, unsigned int cmd, - unsigned long arg) -{ - return afu_ioctl(file, cmd, arg); -} - -int afu_mmap(struct file *file, struct vm_area_struct *vm) -{ - struct cxl_context *ctx = file->private_data; - - /* AFU must be started before we can MMIO */ - if (ctx->status != STARTED) - return -EIO; - - if (!cxl_ops->link_ok(ctx->afu->adapter, ctx->afu)) - return -EIO; - - return cxl_context_iomap(ctx, vm); -} - -static inline bool ctx_event_pending(struct cxl_context *ctx) -{ - if (ctx->pending_irq || ctx->pending_fault || ctx->pending_afu_err) - return true; - - if (ctx->afu_driver_ops && atomic_read(&ctx->afu_driver_events)) - return true; - - return false; -} - -__poll_t afu_poll(struct file *file, struct poll_table_struct *poll) -{ - struct cxl_context *ctx = file->private_data; - __poll_t mask = 0; - unsigned long flags; - - - poll_wait(file, &ctx->wq, poll); - - pr_devel("afu_poll wait done pe: %i\n", ctx->pe); - - spin_lock_irqsave(&ctx->lock, flags); - if (ctx_event_pending(ctx)) - mask |= EPOLLIN | EPOLLRDNORM; - else if (ctx->status == CLOSED) - /* Only error on closed when there are no futher events pending - */ - mask |= EPOLLERR; - spin_unlock_irqrestore(&ctx->lock, flags); - - pr_devel("afu_poll pe: %i returning %#x\n", ctx->pe, mask); - - return mask; -} - -static ssize_t afu_driver_event_copy(struct cxl_context *ctx, - char __user *buf, - struct cxl_event *event, - struct cxl_event_afu_driver_reserved *pl) -{ - /* Check event */ - if (!pl) { - ctx->afu_driver_ops->event_delivered(ctx, pl, -EINVAL); - return -EFAULT; - } - - /* Check event size */ - event->header.size += pl->data_size; - if (event->header.size > CXL_READ_MIN_SIZE) { - ctx->afu_driver_ops->event_delivered(ctx, pl, -EINVAL); - return -EFAULT; - } - - /* Copy event header */ - if (copy_to_user(buf, event, sizeof(struct cxl_event_header))) { - ctx->afu_driver_ops->event_delivered(ctx, pl, -EFAULT); - return -EFAULT; - } - - /* Copy event data */ - buf += sizeof(struct cxl_event_header); - if (copy_to_user(buf, &pl->data, pl->data_size)) { - ctx->afu_driver_ops->event_delivered(ctx, pl, -EFAULT); - return -EFAULT; - } - - ctx->afu_driver_ops->event_delivered(ctx, pl, 0); /* Success */ - return event->header.size; -} - -ssize_t afu_read(struct file *file, char __user *buf, size_t count, - loff_t *off) -{ - struct cxl_context *ctx = file->private_data; - struct cxl_event_afu_driver_reserved *pl = NULL; - struct cxl_event event; - unsigned long flags; - int rc; - DEFINE_WAIT(wait); - - if (!cxl_ops->link_ok(ctx->afu->adapter, ctx->afu)) - return -EIO; - - if (count < CXL_READ_MIN_SIZE) - return -EINVAL; - - spin_lock_irqsave(&ctx->lock, flags); - - for (;;) { - prepare_to_wait(&ctx->wq, &wait, TASK_INTERRUPTIBLE); - if (ctx_event_pending(ctx) || (ctx->status == CLOSED)) - break; - - if (!cxl_ops->link_ok(ctx->afu->adapter, ctx->afu)) { - rc = -EIO; - goto out; - } - - if (file->f_flags & O_NONBLOCK) { - rc = -EAGAIN; - goto out; - } - - if (signal_pending(current)) { - rc = -ERESTARTSYS; - goto out; - } - - spin_unlock_irqrestore(&ctx->lock, flags); - pr_devel("afu_read going to sleep...\n"); - schedule(); - pr_devel("afu_read woken up\n"); - spin_lock_irqsave(&ctx->lock, flags); - } - - finish_wait(&ctx->wq, &wait); - - memset(&event, 0, sizeof(event)); - event.header.process_element = ctx->pe; - event.header.size = sizeof(struct cxl_event_header); - if (ctx->afu_driver_ops && atomic_read(&ctx->afu_driver_events)) { - pr_devel("afu_read delivering AFU driver specific event\n"); - pl = ctx->afu_driver_ops->fetch_event(ctx); - atomic_dec(&ctx->afu_driver_events); - event.header.type = CXL_EVENT_AFU_DRIVER; - } else if (ctx->pending_irq) { - pr_devel("afu_read delivering AFU interrupt\n"); - event.header.size += sizeof(struct cxl_event_afu_interrupt); - event.header.type = CXL_EVENT_AFU_INTERRUPT; - event.irq.irq = find_first_bit(ctx->irq_bitmap, ctx->irq_count) + 1; - clear_bit(event.irq.irq - 1, ctx->irq_bitmap); - if (bitmap_empty(ctx->irq_bitmap, ctx->irq_count)) - ctx->pending_irq = false; - } else if (ctx->pending_fault) { - pr_devel("afu_read delivering data storage fault\n"); - event.header.size += sizeof(struct cxl_event_data_storage); - event.header.type = CXL_EVENT_DATA_STORAGE; - event.fault.addr = ctx->fault_addr; - event.fault.dsisr = ctx->fault_dsisr; - ctx->pending_fault = false; - } else if (ctx->pending_afu_err) { - pr_devel("afu_read delivering afu error\n"); - event.header.size += sizeof(struct cxl_event_afu_error); - event.header.type = CXL_EVENT_AFU_ERROR; - event.afu_error.error = ctx->afu_err; - ctx->pending_afu_err = false; - } else if (ctx->status == CLOSED) { - pr_devel("afu_read fatal error\n"); - spin_unlock_irqrestore(&ctx->lock, flags); - return -EIO; - } else - WARN(1, "afu_read must be buggy\n"); - - spin_unlock_irqrestore(&ctx->lock, flags); - - if (event.header.type == CXL_EVENT_AFU_DRIVER) - return afu_driver_event_copy(ctx, buf, &event, pl); - - if (copy_to_user(buf, &event, event.header.size)) - return -EFAULT; - return event.header.size; - -out: - finish_wait(&ctx->wq, &wait); - spin_unlock_irqrestore(&ctx->lock, flags); - return rc; -} - -/* - * Note: if this is updated, we need to update api.c to patch the new ones in - * too - */ -const struct file_operations afu_fops = { - .owner = THIS_MODULE, - .open = afu_open, - .poll = afu_poll, - .read = afu_read, - .release = afu_release, - .unlocked_ioctl = afu_ioctl, - .compat_ioctl = afu_compat_ioctl, - .mmap = afu_mmap, -}; - -static const struct file_operations afu_master_fops = { - .owner = THIS_MODULE, - .open = afu_master_open, - .poll = afu_poll, - .read = afu_read, - .release = afu_release, - .unlocked_ioctl = afu_ioctl, - .compat_ioctl = afu_compat_ioctl, - .mmap = afu_mmap, -}; - - -static char *cxl_devnode(const struct device *dev, umode_t *mode) -{ - if (cpu_has_feature(CPU_FTR_HVMODE) && - CXL_DEVT_IS_CARD(dev->devt)) { - /* - * These minor numbers will eventually be used to program the - * PSL and AFUs once we have dynamic reprogramming support - */ - return NULL; - } - return kasprintf(GFP_KERNEL, "cxl/%s", dev_name(dev)); -} - -static const struct class cxl_class = { - .name = "cxl", - .devnode = cxl_devnode, -}; - -static int cxl_add_chardev(struct cxl_afu *afu, dev_t devt, struct cdev *cdev, - struct device **chardev, char *postfix, char *desc, - const struct file_operations *fops) -{ - struct device *dev; - int rc; - - cdev_init(cdev, fops); - rc = cdev_add(cdev, devt, 1); - if (rc) { - dev_err(&afu->dev, "Unable to add %s chardev: %i\n", desc, rc); - return rc; - } - - dev = device_create(&cxl_class, &afu->dev, devt, afu, - "afu%i.%i%s", afu->adapter->adapter_num, afu->slice, postfix); - if (IS_ERR(dev)) { - rc = PTR_ERR(dev); - dev_err(&afu->dev, "Unable to create %s chardev in sysfs: %i\n", desc, rc); - goto err; - } - - *chardev = dev; - - return 0; -err: - cdev_del(cdev); - return rc; -} - -int cxl_chardev_d_afu_add(struct cxl_afu *afu) -{ - return cxl_add_chardev(afu, CXL_AFU_MKDEV_D(afu), &afu->afu_cdev_d, - &afu->chardev_d, "d", "dedicated", - &afu_master_fops); /* Uses master fops */ -} - -int cxl_chardev_m_afu_add(struct cxl_afu *afu) -{ - return cxl_add_chardev(afu, CXL_AFU_MKDEV_M(afu), &afu->afu_cdev_m, - &afu->chardev_m, "m", "master", - &afu_master_fops); -} - -int cxl_chardev_s_afu_add(struct cxl_afu *afu) -{ - return cxl_add_chardev(afu, CXL_AFU_MKDEV_S(afu), &afu->afu_cdev_s, - &afu->chardev_s, "s", "shared", - &afu_fops); -} - -void cxl_chardev_afu_remove(struct cxl_afu *afu) -{ - if (afu->chardev_d) { - cdev_del(&afu->afu_cdev_d); - device_unregister(afu->chardev_d); - afu->chardev_d = NULL; - } - if (afu->chardev_m) { - cdev_del(&afu->afu_cdev_m); - device_unregister(afu->chardev_m); - afu->chardev_m = NULL; - } - if (afu->chardev_s) { - cdev_del(&afu->afu_cdev_s); - device_unregister(afu->chardev_s); - afu->chardev_s = NULL; - } -} - -int cxl_register_afu(struct cxl_afu *afu) -{ - afu->dev.class = &cxl_class; - - return device_register(&afu->dev); -} - -int cxl_register_adapter(struct cxl *adapter) -{ - adapter->dev.class = &cxl_class; - - /* - * Future: When we support dynamically reprogramming the PSL & AFU we - * will expose the interface to do that via a chardev: - * adapter->dev.devt = CXL_CARD_MKDEV(adapter); - */ - - return device_register(&adapter->dev); -} - -dev_t cxl_get_dev(void) -{ - return cxl_dev; -} - -int __init cxl_file_init(void) -{ - int rc; - - /* - * If these change we really need to update API. Either change some - * flags or update API version number CXL_API_VERSION. - */ - BUILD_BUG_ON(CXL_API_VERSION != 3); - BUILD_BUG_ON(sizeof(struct cxl_ioctl_start_work) != 64); - BUILD_BUG_ON(sizeof(struct cxl_event_header) != 8); - BUILD_BUG_ON(sizeof(struct cxl_event_afu_interrupt) != 8); - BUILD_BUG_ON(sizeof(struct cxl_event_data_storage) != 32); - BUILD_BUG_ON(sizeof(struct cxl_event_afu_error) != 16); - - if ((rc = alloc_chrdev_region(&cxl_dev, 0, CXL_NUM_MINORS, "cxl"))) { - pr_err("Unable to allocate CXL major number: %i\n", rc); - return rc; - } - - pr_devel("CXL device allocated, MAJOR %i\n", MAJOR(cxl_dev)); - - rc = class_register(&cxl_class); - if (rc) { - pr_err("Unable to create CXL class\n"); - goto err; - } - - return 0; - -err: - unregister_chrdev_region(cxl_dev, CXL_NUM_MINORS); - return rc; -} - -void cxl_file_exit(void) -{ - unregister_chrdev_region(cxl_dev, CXL_NUM_MINORS); - class_unregister(&cxl_class); -}
diff --git a/drivers/misc/cxl/flash.c b/drivers/misc/cxl/flash.c deleted file mode 100644 index eee9dec..0000000 --- a/drivers/misc/cxl/flash.c +++ /dev/null
@@ -1,538 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -#include <linux/kernel.h> -#include <linux/fs.h> -#include <linux/semaphore.h> -#include <linux/slab.h> -#include <linux/uaccess.h> -#include <linux/of.h> -#include <asm/rtas.h> - -#include "cxl.h" -#include "hcalls.h" - -#define DOWNLOAD_IMAGE 1 -#define VALIDATE_IMAGE 2 - -struct ai_header { - u16 version; - u8 reserved0[6]; - u16 vendor; - u16 device; - u16 subsystem_vendor; - u16 subsystem; - u64 image_offset; - u64 image_length; - u8 reserved1[96]; -}; - -static struct semaphore sem; -static unsigned long *buffer[CXL_AI_MAX_ENTRIES]; -static struct sg_list *le; -static u64 continue_token; -static unsigned int transfer; - -struct update_props_workarea { - __be32 phandle; - __be32 state; - __be64 reserved; - __be32 nprops; -} __packed; - -struct update_nodes_workarea { - __be32 state; - __be64 unit_address; - __be32 reserved; -} __packed; - -#define DEVICE_SCOPE 3 -#define NODE_ACTION_MASK 0xff000000 -#define NODE_COUNT_MASK 0x00ffffff -#define OPCODE_DELETE 0x01000000 -#define OPCODE_UPDATE 0x02000000 -#define OPCODE_ADD 0x03000000 - -static int rcall(int token, char *buf, s32 scope) -{ - int rc; - - spin_lock(&rtas_data_buf_lock); - - memcpy(rtas_data_buf, buf, RTAS_DATA_BUF_SIZE); - rc = rtas_call(token, 2, 1, NULL, rtas_data_buf, scope); - memcpy(buf, rtas_data_buf, RTAS_DATA_BUF_SIZE); - - spin_unlock(&rtas_data_buf_lock); - return rc; -} - -static int update_property(struct device_node *dn, const char *name, - u32 vd, char *value) -{ - struct property *new_prop; - u32 *val; - int rc; - - new_prop = kzalloc(sizeof(*new_prop), GFP_KERNEL); - if (!new_prop) - return -ENOMEM; - - new_prop->name = kstrdup(name, GFP_KERNEL); - if (!new_prop->name) { - kfree(new_prop); - return -ENOMEM; - } - - new_prop->length = vd; - new_prop->value = kzalloc(new_prop->length, GFP_KERNEL); - if (!new_prop->value) { - kfree(new_prop->name); - kfree(new_prop); - return -ENOMEM; - } - memcpy(new_prop->value, value, vd); - - val = (u32 *)new_prop->value; - rc = cxl_update_properties(dn, new_prop); - pr_devel("%pOFn: update property (%s, length: %i, value: %#x)\n", - dn, name, vd, be32_to_cpu(*val)); - - if (rc) { - kfree(new_prop->name); - kfree(new_prop->value); - kfree(new_prop); - } - return rc; -} - -static int update_node(__be32 phandle, s32 scope) -{ - struct update_props_workarea *upwa; - struct device_node *dn; - int i, rc, ret; - char *prop_data; - char *buf; - int token; - u32 nprops; - u32 vd; - - token = rtas_token("ibm,update-properties"); - if (token == RTAS_UNKNOWN_SERVICE) - return -EINVAL; - - buf = kzalloc(RTAS_DATA_BUF_SIZE, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - dn = of_find_node_by_phandle(be32_to_cpu(phandle)); - if (!dn) { - kfree(buf); - return -ENOENT; - } - - upwa = (struct update_props_workarea *)&buf[0]; - upwa->phandle = phandle; - do { - rc = rcall(token, buf, scope); - if (rc < 0) - break; - - prop_data = buf + sizeof(*upwa); - nprops = be32_to_cpu(upwa->nprops); - - if (*prop_data == 0) { - prop_data++; - vd = be32_to_cpu(*(__be32 *)prop_data); - prop_data += vd + sizeof(vd); - nprops--; - } - - for (i = 0; i < nprops; i++) { - char *prop_name; - - prop_name = prop_data; - prop_data += strlen(prop_name) + 1; - vd = be32_to_cpu(*(__be32 *)prop_data); - prop_data += sizeof(vd); - - if ((vd != 0x00000000) && (vd != 0x80000000)) { - ret = update_property(dn, prop_name, vd, - prop_data); - if (ret) - pr_err("cxl: Could not update property %s - %i\n", - prop_name, ret); - - prop_data += vd; - } - } - } while (rc == 1); - - of_node_put(dn); - kfree(buf); - return rc; -} - -static int update_devicetree(struct cxl *adapter, s32 scope) -{ - struct update_nodes_workarea *unwa; - u32 action, node_count; - int token, rc, i; - __be32 *data, phandle; - char *buf; - - token = rtas_token("ibm,update-nodes"); - if (token == RTAS_UNKNOWN_SERVICE) - return -EINVAL; - - buf = kzalloc(RTAS_DATA_BUF_SIZE, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - unwa = (struct update_nodes_workarea *)&buf[0]; - unwa->unit_address = cpu_to_be64(adapter->guest->handle); - do { - rc = rcall(token, buf, scope); - if (rc && rc != 1) - break; - - data = (__be32 *)buf + 4; - while (be32_to_cpu(*data) & NODE_ACTION_MASK) { - action = be32_to_cpu(*data) & NODE_ACTION_MASK; - node_count = be32_to_cpu(*data) & NODE_COUNT_MASK; - pr_devel("device reconfiguration - action: %#x, nodes: %#x\n", - action, node_count); - data++; - - for (i = 0; i < node_count; i++) { - phandle = *data++; - - switch (action) { - case OPCODE_DELETE: - /* nothing to do */ - break; - case OPCODE_UPDATE: - update_node(phandle, scope); - break; - case OPCODE_ADD: - /* nothing to do, just move pointer */ - data++; - break; - } - } - } - } while (rc == 1); - - kfree(buf); - return 0; -} - -static int handle_image(struct cxl *adapter, int operation, - long (*fct)(u64, u64, u64, u64 *), - struct cxl_adapter_image *ai) -{ - size_t mod, s_copy, len_chunk = 0; - struct ai_header *header = NULL; - unsigned int entries = 0, i; - void *dest, *from; - int rc = 0, need_header; - - /* base adapter image header */ - need_header = (ai->flags & CXL_AI_NEED_HEADER); - if (need_header) { - header = kzalloc(sizeof(struct ai_header), GFP_KERNEL); - if (!header) - return -ENOMEM; - header->version = cpu_to_be16(1); - header->vendor = cpu_to_be16(adapter->guest->vendor); - header->device = cpu_to_be16(adapter->guest->device); - header->subsystem_vendor = cpu_to_be16(adapter->guest->subsystem_vendor); - header->subsystem = cpu_to_be16(adapter->guest->subsystem); - header->image_offset = cpu_to_be64(CXL_AI_HEADER_SIZE); - header->image_length = cpu_to_be64(ai->len_image); - } - - /* number of entries in the list */ - len_chunk = ai->len_data; - if (need_header) - len_chunk += CXL_AI_HEADER_SIZE; - - entries = len_chunk / CXL_AI_BUFFER_SIZE; - mod = len_chunk % CXL_AI_BUFFER_SIZE; - if (mod) - entries++; - - if (entries > CXL_AI_MAX_ENTRIES) { - rc = -EINVAL; - goto err; - } - - /* < -- MAX_CHUNK_SIZE = 4096 * 256 = 1048576 bytes --> - * chunk 0 ---------------------------------------------------- - * | header | data | - * ---------------------------------------------------- - * chunk 1 ---------------------------------------------------- - * | data | - * ---------------------------------------------------- - * .... - * chunk n ---------------------------------------------------- - * | data | - * ---------------------------------------------------- - */ - from = (void *) ai->data; - for (i = 0; i < entries; i++) { - dest = buffer[i]; - s_copy = CXL_AI_BUFFER_SIZE; - - if ((need_header) && (i == 0)) { - /* add adapter image header */ - memcpy(buffer[i], header, sizeof(struct ai_header)); - s_copy = CXL_AI_BUFFER_SIZE - CXL_AI_HEADER_SIZE; - dest += CXL_AI_HEADER_SIZE; /* image offset */ - } - if ((i == (entries - 1)) && mod) - s_copy = mod; - - /* copy data */ - if (copy_from_user(dest, from, s_copy)) - goto err; - - /* fill in the list */ - le[i].phys_addr = cpu_to_be64(virt_to_phys(buffer[i])); - le[i].len = cpu_to_be64(CXL_AI_BUFFER_SIZE); - if ((i == (entries - 1)) && mod) - le[i].len = cpu_to_be64(mod); - from += s_copy; - } - pr_devel("%s (op: %i, need header: %i, entries: %i, token: %#llx)\n", - __func__, operation, need_header, entries, continue_token); - - /* - * download/validate the adapter image to the coherent - * platform facility - */ - rc = fct(adapter->guest->handle, virt_to_phys(le), entries, - &continue_token); - if (rc == 0) /* success of download/validation operation */ - continue_token = 0; - -err: - kfree(header); - - return rc; -} - -static int transfer_image(struct cxl *adapter, int operation, - struct cxl_adapter_image *ai) -{ - int rc = 0; - int afu; - - switch (operation) { - case DOWNLOAD_IMAGE: - rc = handle_image(adapter, operation, - &cxl_h_download_adapter_image, ai); - if (rc < 0) { - pr_devel("resetting adapter\n"); - cxl_h_reset_adapter(adapter->guest->handle); - } - return rc; - - case VALIDATE_IMAGE: - rc = handle_image(adapter, operation, - &cxl_h_validate_adapter_image, ai); - if (rc < 0) { - pr_devel("resetting adapter\n"); - cxl_h_reset_adapter(adapter->guest->handle); - return rc; - } - if (rc == 0) { - pr_devel("remove current afu\n"); - for (afu = 0; afu < adapter->slices; afu++) - cxl_guest_remove_afu(adapter->afu[afu]); - - pr_devel("resetting adapter\n"); - cxl_h_reset_adapter(adapter->guest->handle); - - /* The entire image has now been - * downloaded and the validation has - * been successfully performed. - * After that, the partition should call - * ibm,update-nodes and - * ibm,update-properties to receive the - * current configuration - */ - rc = update_devicetree(adapter, DEVICE_SCOPE); - transfer = 1; - } - return rc; - } - - return -EINVAL; -} - -static long ioctl_transfer_image(struct cxl *adapter, int operation, - struct cxl_adapter_image __user *uai) -{ - struct cxl_adapter_image ai; - - pr_devel("%s\n", __func__); - - if (copy_from_user(&ai, uai, sizeof(struct cxl_adapter_image))) - return -EFAULT; - - /* - * Make sure reserved fields and bits are set to 0 - */ - if (ai.reserved1 || ai.reserved2 || ai.reserved3 || ai.reserved4 || - (ai.flags & ~CXL_AI_ALL)) - return -EINVAL; - - return transfer_image(adapter, operation, &ai); -} - -static int device_open(struct inode *inode, struct file *file) -{ - int adapter_num = CXL_DEVT_ADAPTER(inode->i_rdev); - struct cxl *adapter; - int rc = 0, i; - - pr_devel("in %s\n", __func__); - - BUG_ON(sizeof(struct ai_header) != CXL_AI_HEADER_SIZE); - - /* Allows one process to open the device by using a semaphore */ - if (down_interruptible(&sem) != 0) - return -EPERM; - - if (!(adapter = get_cxl_adapter(adapter_num))) { - rc = -ENODEV; - goto err_unlock; - } - - file->private_data = adapter; - continue_token = 0; - transfer = 0; - - for (i = 0; i < CXL_AI_MAX_ENTRIES; i++) - buffer[i] = NULL; - - /* aligned buffer containing list entries which describes up to - * 1 megabyte of data (256 entries of 4096 bytes each) - * Logical real address of buffer 0 - Buffer 0 length in bytes - * Logical real address of buffer 1 - Buffer 1 length in bytes - * Logical real address of buffer 2 - Buffer 2 length in bytes - * .... - * .... - * Logical real address of buffer N - Buffer N length in bytes - */ - le = (struct sg_list *)get_zeroed_page(GFP_KERNEL); - if (!le) { - rc = -ENOMEM; - goto err; - } - - for (i = 0; i < CXL_AI_MAX_ENTRIES; i++) { - buffer[i] = (unsigned long *)get_zeroed_page(GFP_KERNEL); - if (!buffer[i]) { - rc = -ENOMEM; - goto err1; - } - } - - return 0; - -err1: - for (i = 0; i < CXL_AI_MAX_ENTRIES; i++) { - if (buffer[i]) - free_page((unsigned long) buffer[i]); - } - - if (le) - free_page((unsigned long) le); -err: - put_device(&adapter->dev); -err_unlock: - up(&sem); - - return rc; -} - -static long device_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -{ - struct cxl *adapter = file->private_data; - - pr_devel("in %s\n", __func__); - - if (cmd == CXL_IOCTL_DOWNLOAD_IMAGE) - return ioctl_transfer_image(adapter, - DOWNLOAD_IMAGE, - (struct cxl_adapter_image __user *)arg); - else if (cmd == CXL_IOCTL_VALIDATE_IMAGE) - return ioctl_transfer_image(adapter, - VALIDATE_IMAGE, - (struct cxl_adapter_image __user *)arg); - else - return -EINVAL; -} - -static int device_close(struct inode *inode, struct file *file) -{ - struct cxl *adapter = file->private_data; - int i; - - pr_devel("in %s\n", __func__); - - for (i = 0; i < CXL_AI_MAX_ENTRIES; i++) { - if (buffer[i]) - free_page((unsigned long) buffer[i]); - } - - if (le) - free_page((unsigned long) le); - - up(&sem); - put_device(&adapter->dev); - continue_token = 0; - - /* reload the module */ - if (transfer) - cxl_guest_reload_module(adapter); - else { - pr_devel("resetting adapter\n"); - cxl_h_reset_adapter(adapter->guest->handle); - } - - transfer = 0; - return 0; -} - -static const struct file_operations fops = { - .owner = THIS_MODULE, - .open = device_open, - .unlocked_ioctl = device_ioctl, - .compat_ioctl = compat_ptr_ioctl, - .release = device_close, -}; - -void cxl_guest_remove_chardev(struct cxl *adapter) -{ - cdev_del(&adapter->guest->cdev); -} - -int cxl_guest_add_chardev(struct cxl *adapter) -{ - dev_t devt; - int rc; - - devt = MKDEV(MAJOR(cxl_get_dev()), CXL_CARD_MINOR(adapter)); - cdev_init(&adapter->guest->cdev, &fops); - if ((rc = cdev_add(&adapter->guest->cdev, devt, 1))) { - dev_err(&adapter->dev, - "Unable to add chardev on adapter (card%i): %i\n", - adapter->adapter_num, rc); - goto err; - } - adapter->dev.devt = devt; - sema_init(&sem, 1); -err: - return rc; -}
diff --git a/drivers/misc/cxl/guest.c b/drivers/misc/cxl/guest.c deleted file mode 100644 index fb95a2d..0000000 --- a/drivers/misc/cxl/guest.c +++ /dev/null
@@ -1,1208 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Copyright 2015 IBM Corp. - */ - -#include <linux/spinlock.h> -#include <linux/uaccess.h> -#include <linux/delay.h> -#include <linux/irqdomain.h> -#include <linux/platform_device.h> - -#include "cxl.h" -#include "hcalls.h" -#include "trace.h" - -#define CXL_ERROR_DETECTED_EVENT 1 -#define CXL_SLOT_RESET_EVENT 2 -#define CXL_RESUME_EVENT 3 - -static void pci_error_handlers(struct cxl_afu *afu, - int bus_error_event, - pci_channel_state_t state) -{ - struct pci_dev *afu_dev; - struct pci_driver *afu_drv; - const struct pci_error_handlers *err_handler; - - if (afu->phb == NULL) - return; - - list_for_each_entry(afu_dev, &afu->phb->bus->devices, bus_list) { - afu_drv = to_pci_driver(afu_dev->dev.driver); - if (!afu_drv) - continue; - - err_handler = afu_drv->err_handler; - switch (bus_error_event) { - case CXL_ERROR_DETECTED_EVENT: - afu_dev->error_state = state; - - if (err_handler && - err_handler->error_detected) - err_handler->error_detected(afu_dev, state); - break; - case CXL_SLOT_RESET_EVENT: - afu_dev->error_state = state; - - if (err_handler && - err_handler->slot_reset) - err_handler->slot_reset(afu_dev); - break; - case CXL_RESUME_EVENT: - if (err_handler && - err_handler->resume) - err_handler->resume(afu_dev); - break; - } - } -} - -static irqreturn_t guest_handle_psl_slice_error(struct cxl_context *ctx, u64 dsisr, - u64 errstat) -{ - pr_devel("in %s\n", __func__); - dev_crit(&ctx->afu->dev, "PSL ERROR STATUS: 0x%.16llx\n", errstat); - - return cxl_ops->ack_irq(ctx, 0, errstat); -} - -static ssize_t guest_collect_vpd(struct cxl *adapter, struct cxl_afu *afu, - void *buf, size_t len) -{ - unsigned int entries, mod; - unsigned long **vpd_buf = NULL; - struct sg_list *le; - int rc = 0, i, tocopy; - u64 out = 0; - - if (buf == NULL) - return -EINVAL; - - /* number of entries in the list */ - entries = len / SG_BUFFER_SIZE; - mod = len % SG_BUFFER_SIZE; - if (mod) - entries++; - - if (entries > SG_MAX_ENTRIES) { - entries = SG_MAX_ENTRIES; - len = SG_MAX_ENTRIES * SG_BUFFER_SIZE; - mod = 0; - } - - vpd_buf = kcalloc(entries, sizeof(unsigned long *), GFP_KERNEL); - if (!vpd_buf) - return -ENOMEM; - - le = (struct sg_list *)get_zeroed_page(GFP_KERNEL); - if (!le) { - rc = -ENOMEM; - goto err1; - } - - for (i = 0; i < entries; i++) { - vpd_buf[i] = (unsigned long *)get_zeroed_page(GFP_KERNEL); - if (!vpd_buf[i]) { - rc = -ENOMEM; - goto err2; - } - le[i].phys_addr = cpu_to_be64(virt_to_phys(vpd_buf[i])); - le[i].len = cpu_to_be64(SG_BUFFER_SIZE); - if ((i == (entries - 1)) && mod) - le[i].len = cpu_to_be64(mod); - } - - if (adapter) - rc = cxl_h_collect_vpd_adapter(adapter->guest->handle, - virt_to_phys(le), entries, &out); - else - rc = cxl_h_collect_vpd(afu->guest->handle, 0, - virt_to_phys(le), entries, &out); - pr_devel("length of available (entries: %i), vpd: %#llx\n", - entries, out); - - if (!rc) { - /* - * hcall returns in 'out' the size of available VPDs. - * It fills the buffer with as much data as possible. - */ - if (out < len) - len = out; - rc = len; - if (out) { - for (i = 0; i < entries; i++) { - if (len < SG_BUFFER_SIZE) - tocopy = len; - else - tocopy = SG_BUFFER_SIZE; - memcpy(buf, vpd_buf[i], tocopy); - buf += tocopy; - len -= tocopy; - } - } - } -err2: - for (i = 0; i < entries; i++) { - if (vpd_buf[i]) - free_page((unsigned long) vpd_buf[i]); - } - free_page((unsigned long) le); -err1: - kfree(vpd_buf); - return rc; -} - -static int guest_get_irq_info(struct cxl_context *ctx, struct cxl_irq_info *info) -{ - return cxl_h_collect_int_info(ctx->afu->guest->handle, ctx->process_token, info); -} - -static irqreturn_t guest_psl_irq(int irq, void *data) -{ - struct cxl_context *ctx = data; - struct cxl_irq_info irq_info; - int rc; - - pr_devel("%d: received PSL interrupt %i\n", ctx->pe, irq); - rc = guest_get_irq_info(ctx, &irq_info); - if (rc) { - WARN(1, "Unable to get IRQ info: %i\n", rc); - return IRQ_HANDLED; - } - - rc = cxl_irq_psl8(irq, ctx, &irq_info); - return rc; -} - -static int afu_read_error_state(struct cxl_afu *afu, int *state_out) -{ - u64 state; - int rc = 0; - - if (!afu) - return -EIO; - - rc = cxl_h_read_error_state(afu->guest->handle, &state); - if (!rc) { - WARN_ON(state != H_STATE_NORMAL && - state != H_STATE_DISABLE && - state != H_STATE_TEMP_UNAVAILABLE && - state != H_STATE_PERM_UNAVAILABLE); - *state_out = state & 0xffffffff; - } - return rc; -} - -static irqreturn_t guest_slice_irq_err(int irq, void *data) -{ - struct cxl_afu *afu = data; - int rc; - u64 serr, afu_error, dsisr; - - rc = cxl_h_get_fn_error_interrupt(afu->guest->handle, &serr); - if (rc) { - dev_crit(&afu->dev, "Couldn't read PSL_SERR_An: %d\n", rc); - return IRQ_HANDLED; - } - afu_error = cxl_p2n_read(afu, CXL_AFU_ERR_An); - dsisr = cxl_p2n_read(afu, CXL_PSL_DSISR_An); - cxl_afu_decode_psl_serr(afu, serr); - dev_crit(&afu->dev, "AFU_ERR_An: 0x%.16llx\n", afu_error); - dev_crit(&afu->dev, "PSL_DSISR_An: 0x%.16llx\n", dsisr); - - rc = cxl_h_ack_fn_error_interrupt(afu->guest->handle, serr); - if (rc) - dev_crit(&afu->dev, "Couldn't ack slice error interrupt: %d\n", - rc); - - return IRQ_HANDLED; -} - - -static int irq_alloc_range(struct cxl *adapter, int len, int *irq) -{ - int i, n; - struct irq_avail *cur; - - for (i = 0; i < adapter->guest->irq_nranges; i++) { - cur = &adapter->guest->irq_avail[i]; - n = bitmap_find_next_zero_area(cur->bitmap, cur->range, - 0, len, 0); - if (n < cur->range) { - bitmap_set(cur->bitmap, n, len); - *irq = cur->offset + n; - pr_devel("guest: allocate IRQs %#x->%#x\n", - *irq, *irq + len - 1); - - return 0; - } - } - return -ENOSPC; -} - -static int irq_free_range(struct cxl *adapter, int irq, int len) -{ - int i, n; - struct irq_avail *cur; - - if (len == 0) - return -ENOENT; - - for (i = 0; i < adapter->guest->irq_nranges; i++) { - cur = &adapter->guest->irq_avail[i]; - if (irq >= cur->offset && - (irq + len) <= (cur->offset + cur->range)) { - n = irq - cur->offset; - bitmap_clear(cur->bitmap, n, len); - pr_devel("guest: release IRQs %#x->%#x\n", - irq, irq + len - 1); - return 0; - } - } - return -ENOENT; -} - -static int guest_reset(struct cxl *adapter) -{ - struct cxl_afu *afu = NULL; - int i, rc; - - pr_devel("Adapter reset request\n"); - spin_lock(&adapter->afu_list_lock); - for (i = 0; i < adapter->slices; i++) { - if ((afu = adapter->afu[i])) { - pci_error_handlers(afu, CXL_ERROR_DETECTED_EVENT, - pci_channel_io_frozen); - cxl_context_detach_all(afu); - } - } - - rc = cxl_h_reset_adapter(adapter->guest->handle); - for (i = 0; i < adapter->slices; i++) { - if (!rc && (afu = adapter->afu[i])) { - pci_error_handlers(afu, CXL_SLOT_RESET_EVENT, - pci_channel_io_normal); - pci_error_handlers(afu, CXL_RESUME_EVENT, 0); - } - } - spin_unlock(&adapter->afu_list_lock); - return rc; -} - -static int guest_alloc_one_irq(struct cxl *adapter) -{ - int irq; - - spin_lock(&adapter->guest->irq_alloc_lock); - if (irq_alloc_range(adapter, 1, &irq)) - irq = -ENOSPC; - spin_unlock(&adapter->guest->irq_alloc_lock); - return irq; -} - -static void guest_release_one_irq(struct cxl *adapter, int irq) -{ - spin_lock(&adapter->guest->irq_alloc_lock); - irq_free_range(adapter, irq, 1); - spin_unlock(&adapter->guest->irq_alloc_lock); -} - -static int guest_alloc_irq_ranges(struct cxl_irq_ranges *irqs, - struct cxl *adapter, unsigned int num) -{ - int i, try, irq; - - memset(irqs, 0, sizeof(struct cxl_irq_ranges)); - - spin_lock(&adapter->guest->irq_alloc_lock); - for (i = 0; i < CXL_IRQ_RANGES && num; i++) { - try = num; - while (try) { - if (irq_alloc_range(adapter, try, &irq) == 0) - break; - try /= 2; - } - if (!try) - goto error; - irqs->offset[i] = irq; - irqs->range[i] = try; - num -= try; - } - if (num) - goto error; - spin_unlock(&adapter->guest->irq_alloc_lock); - return 0; - -error: - for (i = 0; i < CXL_IRQ_RANGES; i++) - irq_free_range(adapter, irqs->offset[i], irqs->range[i]); - spin_unlock(&adapter->guest->irq_alloc_lock); - return -ENOSPC; -} - -static void guest_release_irq_ranges(struct cxl_irq_ranges *irqs, - struct cxl *adapter) -{ - int i; - - spin_lock(&adapter->guest->irq_alloc_lock); - for (i = 0; i < CXL_IRQ_RANGES; i++) - irq_free_range(adapter, irqs->offset[i], irqs->range[i]); - spin_unlock(&adapter->guest->irq_alloc_lock); -} - -static int guest_register_serr_irq(struct cxl_afu *afu) -{ - afu->err_irq_name = kasprintf(GFP_KERNEL, "cxl-%s-err", - dev_name(&afu->dev)); - if (!afu->err_irq_name) - return -ENOMEM; - - if (!(afu->serr_virq = cxl_map_irq(afu->adapter, afu->serr_hwirq, - guest_slice_irq_err, afu, afu->err_irq_name))) { - kfree(afu->err_irq_name); - afu->err_irq_name = NULL; - return -ENOMEM; - } - - return 0; -} - -static void guest_release_serr_irq(struct cxl_afu *afu) -{ - cxl_unmap_irq(afu->serr_virq, afu); - cxl_ops->release_one_irq(afu->adapter, afu->serr_hwirq); - kfree(afu->err_irq_name); -} - -static int guest_ack_irq(struct cxl_context *ctx, u64 tfc, u64 psl_reset_mask) -{ - return cxl_h_control_faults(ctx->afu->guest->handle, ctx->process_token, - tfc >> 32, (psl_reset_mask != 0)); -} - -static void disable_afu_irqs(struct cxl_context *ctx) -{ - irq_hw_number_t hwirq; - unsigned int virq; - int r, i; - - pr_devel("Disabling AFU(%d) interrupts\n", ctx->afu->slice); - for (r = 0; r < CXL_IRQ_RANGES; r++) { - hwirq = ctx->irqs.offset[r]; - for (i = 0; i < ctx->irqs.range[r]; hwirq++, i++) { - virq = irq_find_mapping(NULL, hwirq); - disable_irq(virq); - } - } -} - -static void enable_afu_irqs(struct cxl_context *ctx) -{ - irq_hw_number_t hwirq; - unsigned int virq; - int r, i; - - pr_devel("Enabling AFU(%d) interrupts\n", ctx->afu->slice); - for (r = 0; r < CXL_IRQ_RANGES; r++) { - hwirq = ctx->irqs.offset[r]; - for (i = 0; i < ctx->irqs.range[r]; hwirq++, i++) { - virq = irq_find_mapping(NULL, hwirq); - enable_irq(virq); - } - } -} - -static int _guest_afu_cr_readXX(int sz, struct cxl_afu *afu, int cr_idx, - u64 offset, u64 *val) -{ - unsigned long cr; - char c; - int rc = 0; - - if (afu->crs_len < sz) - return -ENOENT; - - if (unlikely(offset >= afu->crs_len)) - return -ERANGE; - - cr = get_zeroed_page(GFP_KERNEL); - if (!cr) - return -ENOMEM; - - rc = cxl_h_get_config(afu->guest->handle, cr_idx, offset, - virt_to_phys((void *)cr), sz); - if (rc) - goto err; - - switch (sz) { - case 1: - c = *((char *) cr); - *val = c; - break; - case 2: - *val = in_le16((u16 *)cr); - break; - case 4: - *val = in_le32((unsigned *)cr); - break; - case 8: - *val = in_le64((u64 *)cr); - break; - default: - WARN_ON(1); - } -err: - free_page(cr); - return rc; -} - -static int guest_afu_cr_read32(struct cxl_afu *afu, int cr_idx, u64 offset, - u32 *out) -{ - int rc; - u64 val; - - rc = _guest_afu_cr_readXX(4, afu, cr_idx, offset, &val); - if (!rc) - *out = (u32) val; - return rc; -} - -static int guest_afu_cr_read16(struct cxl_afu *afu, int cr_idx, u64 offset, - u16 *out) -{ - int rc; - u64 val; - - rc = _guest_afu_cr_readXX(2, afu, cr_idx, offset, &val); - if (!rc) - *out = (u16) val; - return rc; -} - -static int guest_afu_cr_read8(struct cxl_afu *afu, int cr_idx, u64 offset, - u8 *out) -{ - int rc; - u64 val; - - rc = _guest_afu_cr_readXX(1, afu, cr_idx, offset, &val); - if (!rc) - *out = (u8) val; - return rc; -} - -static int guest_afu_cr_read64(struct cxl_afu *afu, int cr_idx, u64 offset, - u64 *out) -{ - return _guest_afu_cr_readXX(8, afu, cr_idx, offset, out); -} - -static int guest_afu_cr_write32(struct cxl_afu *afu, int cr, u64 off, u32 in) -{ - /* config record is not writable from guest */ - return -EPERM; -} - -static int guest_afu_cr_write16(struct cxl_afu *afu, int cr, u64 off, u16 in) -{ - /* config record is not writable from guest */ - return -EPERM; -} - -static int guest_afu_cr_write8(struct cxl_afu *afu, int cr, u64 off, u8 in) -{ - /* config record is not writable from guest */ - return -EPERM; -} - -static int attach_afu_directed(struct cxl_context *ctx, u64 wed, u64 amr) -{ - struct cxl_process_element_hcall *elem; - struct cxl *adapter = ctx->afu->adapter; - const struct cred *cred; - u32 pid, idx; - int rc, r, i; - u64 mmio_addr, mmio_size; - __be64 flags = 0; - - /* Must be 8 byte aligned and cannot cross a 4096 byte boundary */ - if (!(elem = (struct cxl_process_element_hcall *) - get_zeroed_page(GFP_KERNEL))) - return -ENOMEM; - - elem->version = cpu_to_be64(CXL_PROCESS_ELEMENT_VERSION); - if (ctx->kernel) { - pid = 0; - flags |= CXL_PE_TRANSLATION_ENABLED; - flags |= CXL_PE_PRIVILEGED_PROCESS; - if (mfmsr() & MSR_SF) - flags |= CXL_PE_64_BIT; - } else { - pid = current->pid; - flags |= CXL_PE_PROBLEM_STATE; - flags |= CXL_PE_TRANSLATION_ENABLED; - if (!test_tsk_thread_flag(current, TIF_32BIT)) - flags |= CXL_PE_64_BIT; - cred = get_current_cred(); - if (uid_eq(cred->euid, GLOBAL_ROOT_UID)) - flags |= CXL_PE_PRIVILEGED_PROCESS; - put_cred(cred); - } - elem->flags = cpu_to_be64(flags); - elem->common.tid = cpu_to_be32(0); /* Unused */ - elem->common.pid = cpu_to_be32(pid); - elem->common.csrp = cpu_to_be64(0); /* disable */ - elem->common.u.psl8.aurp0 = cpu_to_be64(0); /* disable */ - elem->common.u.psl8.aurp1 = cpu_to_be64(0); /* disable */ - - cxl_prefault(ctx, wed); - - elem->common.u.psl8.sstp0 = cpu_to_be64(ctx->sstp0); - elem->common.u.psl8.sstp1 = cpu_to_be64(ctx->sstp1); - - /* - * Ensure we have at least one interrupt allocated to take faults for - * kernel contexts that may not have allocated any AFU IRQs at all: - */ - if (ctx->irqs.range[0] == 0) { - rc = afu_register_irqs(ctx, 0); - if (rc) - goto out_free; - } - - for (r = 0; r < CXL_IRQ_RANGES; r++) { - for (i = 0; i < ctx->irqs.range[r]; i++) { - if (r == 0 && i == 0) { - elem->pslVirtualIsn = cpu_to_be32(ctx->irqs.offset[0]); - } else { - idx = ctx->irqs.offset[r] + i - adapter->guest->irq_base_offset; - elem->applicationVirtualIsnBitmap[idx / 8] |= 0x80 >> (idx % 8); - } - } - } - elem->common.amr = cpu_to_be64(amr); - elem->common.wed = cpu_to_be64(wed); - - disable_afu_irqs(ctx); - - rc = cxl_h_attach_process(ctx->afu->guest->handle, elem, - &ctx->process_token, &mmio_addr, &mmio_size); - if (rc == H_SUCCESS) { - if (ctx->master || !ctx->afu->pp_psa) { - ctx->psn_phys = ctx->afu->psn_phys; - ctx->psn_size = ctx->afu->adapter->ps_size; - } else { - ctx->psn_phys = mmio_addr; - ctx->psn_size = mmio_size; - } - if (ctx->afu->pp_psa && mmio_size && - ctx->afu->pp_size == 0) { - /* - * There's no property in the device tree to read the - * pp_size. We only find out at the 1st attach. - * Compared to bare-metal, it is too late and we - * should really lock here. However, on powerVM, - * pp_size is really only used to display in /sys. - * Being discussed with pHyp for their next release. - */ - ctx->afu->pp_size = mmio_size; - } - /* from PAPR: process element is bytes 4-7 of process token */ - ctx->external_pe = ctx->process_token & 0xFFFFFFFF; - pr_devel("CXL pe=%i is known as %i for pHyp, mmio_size=%#llx", - ctx->pe, ctx->external_pe, ctx->psn_size); - ctx->pe_inserted = true; - enable_afu_irqs(ctx); - } - -out_free: - free_page((u64)elem); - return rc; -} - -static int guest_attach_process(struct cxl_context *ctx, bool kernel, u64 wed, u64 amr) -{ - pr_devel("in %s\n", __func__); - - ctx->kernel = kernel; - if (ctx->afu->current_mode == CXL_MODE_DIRECTED) - return attach_afu_directed(ctx, wed, amr); - - /* dedicated mode not supported on FW840 */ - - return -EINVAL; -} - -static int detach_afu_directed(struct cxl_context *ctx) -{ - if (!ctx->pe_inserted) - return 0; - if (cxl_h_detach_process(ctx->afu->guest->handle, ctx->process_token)) - return -1; - return 0; -} - -static int guest_detach_process(struct cxl_context *ctx) -{ - pr_devel("in %s\n", __func__); - trace_cxl_detach(ctx); - - if (!cxl_ops->link_ok(ctx->afu->adapter, ctx->afu)) - return -EIO; - - if (ctx->afu->current_mode == CXL_MODE_DIRECTED) - return detach_afu_directed(ctx); - - return -EINVAL; -} - -static void guest_release_afu(struct device *dev) -{ - struct cxl_afu *afu = to_cxl_afu(dev); - - pr_devel("%s\n", __func__); - - idr_destroy(&afu->contexts_idr); - - kfree(afu->guest); - kfree(afu); -} - -ssize_t cxl_guest_read_afu_vpd(struct cxl_afu *afu, void *buf, size_t len) -{ - return guest_collect_vpd(NULL, afu, buf, len); -} - -#define ERR_BUFF_MAX_COPY_SIZE PAGE_SIZE -static ssize_t guest_afu_read_err_buffer(struct cxl_afu *afu, char *buf, - loff_t off, size_t count) -{ - void *tbuf = NULL; - int rc = 0; - - tbuf = (void *) get_zeroed_page(GFP_KERNEL); - if (!tbuf) - return -ENOMEM; - - rc = cxl_h_get_afu_err(afu->guest->handle, - off & 0x7, - virt_to_phys(tbuf), - count); - if (rc) - goto err; - - if (count > ERR_BUFF_MAX_COPY_SIZE) - count = ERR_BUFF_MAX_COPY_SIZE - (off & 0x7); - memcpy(buf, tbuf, count); -err: - free_page((u64)tbuf); - - return rc; -} - -static int guest_afu_check_and_enable(struct cxl_afu *afu) -{ - return 0; -} - -static bool guest_support_attributes(const char *attr_name, - enum cxl_attrs type) -{ - switch (type) { - case CXL_ADAPTER_ATTRS: - if ((strcmp(attr_name, "base_image") == 0) || - (strcmp(attr_name, "load_image_on_perst") == 0) || - (strcmp(attr_name, "perst_reloads_same_image") == 0) || - (strcmp(attr_name, "image_loaded") == 0)) - return false; - break; - case CXL_AFU_MASTER_ATTRS: - if ((strcmp(attr_name, "pp_mmio_off") == 0)) - return false; - break; - case CXL_AFU_ATTRS: - break; - default: - break; - } - - return true; -} - -static int activate_afu_directed(struct cxl_afu *afu) -{ - int rc; - - dev_info(&afu->dev, "Activating AFU(%d) directed mode\n", afu->slice); - - afu->current_mode = CXL_MODE_DIRECTED; - - afu->num_procs = afu->max_procs_virtualised; - - if ((rc = cxl_chardev_m_afu_add(afu))) - return rc; - - if ((rc = cxl_sysfs_afu_m_add(afu))) - goto err; - - if ((rc = cxl_chardev_s_afu_add(afu))) - goto err1; - - return 0; -err1: - cxl_sysfs_afu_m_remove(afu); -err: - cxl_chardev_afu_remove(afu); - return rc; -} - -static int guest_afu_activate_mode(struct cxl_afu *afu, int mode) -{ - if (!mode) - return 0; - if (!(mode & afu->modes_supported)) - return -EINVAL; - - if (mode == CXL_MODE_DIRECTED) - return activate_afu_directed(afu); - - if (mode == CXL_MODE_DEDICATED) - dev_err(&afu->dev, "Dedicated mode not supported\n"); - - return -EINVAL; -} - -static int deactivate_afu_directed(struct cxl_afu *afu) -{ - dev_info(&afu->dev, "Deactivating AFU(%d) directed mode\n", afu->slice); - - afu->current_mode = 0; - afu->num_procs = 0; - - cxl_sysfs_afu_m_remove(afu); - cxl_chardev_afu_remove(afu); - - cxl_ops->afu_reset(afu); - - return 0; -} - -static int guest_afu_deactivate_mode(struct cxl_afu *afu, int mode) -{ - if (!mode) - return 0; - if (!(mode & afu->modes_supported)) - return -EINVAL; - - if (mode == CXL_MODE_DIRECTED) - return deactivate_afu_directed(afu); - return 0; -} - -static int guest_afu_reset(struct cxl_afu *afu) -{ - pr_devel("AFU(%d) reset request\n", afu->slice); - return cxl_h_reset_afu(afu->guest->handle); -} - -static int guest_map_slice_regs(struct cxl_afu *afu) -{ - if (!(afu->p2n_mmio = ioremap(afu->guest->p2n_phys, afu->guest->p2n_size))) { - dev_err(&afu->dev, "Error mapping AFU(%d) MMIO regions\n", - afu->slice); - return -ENOMEM; - } - return 0; -} - -static void guest_unmap_slice_regs(struct cxl_afu *afu) -{ - if (afu->p2n_mmio) - iounmap(afu->p2n_mmio); -} - -static int afu_update_state(struct cxl_afu *afu) -{ - int rc, cur_state; - - rc = afu_read_error_state(afu, &cur_state); - if (rc) - return rc; - - if (afu->guest->previous_state == cur_state) - return 0; - - pr_devel("AFU(%d) update state to %#x\n", afu->slice, cur_state); - - switch (cur_state) { - case H_STATE_NORMAL: - afu->guest->previous_state = cur_state; - break; - - case H_STATE_DISABLE: - pci_error_handlers(afu, CXL_ERROR_DETECTED_EVENT, - pci_channel_io_frozen); - - cxl_context_detach_all(afu); - if ((rc = cxl_ops->afu_reset(afu))) - pr_devel("reset hcall failed %d\n", rc); - - rc = afu_read_error_state(afu, &cur_state); - if (!rc && cur_state == H_STATE_NORMAL) { - pci_error_handlers(afu, CXL_SLOT_RESET_EVENT, - pci_channel_io_normal); - pci_error_handlers(afu, CXL_RESUME_EVENT, 0); - } - afu->guest->previous_state = 0; - break; - - case H_STATE_TEMP_UNAVAILABLE: - afu->guest->previous_state = cur_state; - break; - - case H_STATE_PERM_UNAVAILABLE: - dev_err(&afu->dev, "AFU is in permanent error state\n"); - pci_error_handlers(afu, CXL_ERROR_DETECTED_EVENT, - pci_channel_io_perm_failure); - afu->guest->previous_state = cur_state; - break; - - default: - pr_err("Unexpected AFU(%d) error state: %#x\n", - afu->slice, cur_state); - return -EINVAL; - } - - return rc; -} - -static void afu_handle_errstate(struct work_struct *work) -{ - struct cxl_afu_guest *afu_guest = - container_of(to_delayed_work(work), struct cxl_afu_guest, work_err); - - if (!afu_update_state(afu_guest->parent) && - afu_guest->previous_state == H_STATE_PERM_UNAVAILABLE) - return; - - if (afu_guest->handle_err) - schedule_delayed_work(&afu_guest->work_err, - msecs_to_jiffies(3000)); -} - -static bool guest_link_ok(struct cxl *cxl, struct cxl_afu *afu) -{ - int state; - - if (afu && (!afu_read_error_state(afu, &state))) { - if (state == H_STATE_NORMAL) - return true; - } - - return false; -} - -static int afu_properties_look_ok(struct cxl_afu *afu) -{ - if (afu->pp_irqs < 0) { - dev_err(&afu->dev, "Unexpected per-process minimum interrupt value\n"); - return -EINVAL; - } - - if (afu->max_procs_virtualised < 1) { - dev_err(&afu->dev, "Unexpected max number of processes virtualised value\n"); - return -EINVAL; - } - - return 0; -} - -int cxl_guest_init_afu(struct cxl *adapter, int slice, struct device_node *afu_np) -{ - struct cxl_afu *afu; - bool free = true; - int rc; - - pr_devel("in %s - AFU(%d)\n", __func__, slice); - if (!(afu = cxl_alloc_afu(adapter, slice))) - return -ENOMEM; - - if (!(afu->guest = kzalloc(sizeof(struct cxl_afu_guest), GFP_KERNEL))) { - kfree(afu); - return -ENOMEM; - } - - if ((rc = dev_set_name(&afu->dev, "afu%i.%i", - adapter->adapter_num, - slice))) - goto err1; - - adapter->slices++; - - if ((rc = cxl_of_read_afu_handle(afu, afu_np))) - goto err1; - - if ((rc = cxl_ops->afu_reset(afu))) - goto err1; - - if ((rc = cxl_of_read_afu_properties(afu, afu_np))) - goto err1; - - if ((rc = afu_properties_look_ok(afu))) - goto err1; - - if ((rc = guest_map_slice_regs(afu))) - goto err1; - - if ((rc = guest_register_serr_irq(afu))) - goto err2; - - /* - * After we call this function we must not free the afu directly, even - * if it returns an error! - */ - if ((rc = cxl_register_afu(afu))) - goto err_put_dev; - - if ((rc = cxl_sysfs_afu_add(afu))) - goto err_del_dev; - - /* - * pHyp doesn't expose the programming models supported by the - * AFU. pHyp currently only supports directed mode. If it adds - * dedicated mode later, this version of cxl has no way to - * detect it. So we'll initialize the driver, but the first - * attach will fail. - * Being discussed with pHyp to do better (likely new property) - */ - if (afu->max_procs_virtualised == 1) - afu->modes_supported = CXL_MODE_DEDICATED; - else - afu->modes_supported = CXL_MODE_DIRECTED; - - if ((rc = cxl_afu_select_best_mode(afu))) - goto err_remove_sysfs; - - adapter->afu[afu->slice] = afu; - - afu->enabled = true; - - /* - * wake up the cpu periodically to check the state - * of the AFU using "afu" stored in the guest structure. - */ - afu->guest->parent = afu; - afu->guest->handle_err = true; - INIT_DELAYED_WORK(&afu->guest->work_err, afu_handle_errstate); - schedule_delayed_work(&afu->guest->work_err, msecs_to_jiffies(1000)); - - if ((rc = cxl_pci_vphb_add(afu))) - dev_info(&afu->dev, "Can't register vPHB\n"); - - return 0; - -err_remove_sysfs: - cxl_sysfs_afu_remove(afu); -err_del_dev: - device_del(&afu->dev); -err_put_dev: - put_device(&afu->dev); - free = false; - guest_release_serr_irq(afu); -err2: - guest_unmap_slice_regs(afu); -err1: - if (free) { - kfree(afu->guest); - kfree(afu); - } - return rc; -} - -void cxl_guest_remove_afu(struct cxl_afu *afu) -{ - if (!afu) - return; - - /* flush and stop pending job */ - afu->guest->handle_err = false; - flush_delayed_work(&afu->guest->work_err); - - cxl_pci_vphb_remove(afu); - cxl_sysfs_afu_remove(afu); - - spin_lock(&afu->adapter->afu_list_lock); - afu->adapter->afu[afu->slice] = NULL; - spin_unlock(&afu->adapter->afu_list_lock); - - cxl_context_detach_all(afu); - cxl_ops->afu_deactivate_mode(afu, afu->current_mode); - guest_release_serr_irq(afu); - guest_unmap_slice_regs(afu); - - device_unregister(&afu->dev); -} - -static void free_adapter(struct cxl *adapter) -{ - struct irq_avail *cur; - int i; - - if (adapter->guest) { - if (adapter->guest->irq_avail) { - for (i = 0; i < adapter->guest->irq_nranges; i++) { - cur = &adapter->guest->irq_avail[i]; - bitmap_free(cur->bitmap); - } - kfree(adapter->guest->irq_avail); - } - kfree(adapter->guest->status); - kfree(adapter->guest); - } - cxl_remove_adapter_nr(adapter); - kfree(adapter); -} - -static int properties_look_ok(struct cxl *adapter) -{ - /* The absence of this property means that the operational - * status is unknown or okay - */ - if (strlen(adapter->guest->status) && - strcmp(adapter->guest->status, "okay")) { - pr_err("ABORTING:Bad operational status of the device\n"); - return -EINVAL; - } - - return 0; -} - -ssize_t cxl_guest_read_adapter_vpd(struct cxl *adapter, void *buf, size_t len) -{ - return guest_collect_vpd(adapter, NULL, buf, len); -} - -void cxl_guest_remove_adapter(struct cxl *adapter) -{ - pr_devel("in %s\n", __func__); - - cxl_sysfs_adapter_remove(adapter); - - cxl_guest_remove_chardev(adapter); - device_unregister(&adapter->dev); -} - -static void release_adapter(struct device *dev) -{ - free_adapter(to_cxl_adapter(dev)); -} - -struct cxl *cxl_guest_init_adapter(struct device_node *np, struct platform_device *pdev) -{ - struct cxl *adapter; - bool free = true; - int rc; - - if (!(adapter = cxl_alloc_adapter())) - return ERR_PTR(-ENOMEM); - - if (!(adapter->guest = kzalloc(sizeof(struct cxl_guest), GFP_KERNEL))) { - free_adapter(adapter); - return ERR_PTR(-ENOMEM); - } - - adapter->slices = 0; - adapter->guest->pdev = pdev; - adapter->dev.parent = &pdev->dev; - adapter->dev.release = release_adapter; - dev_set_drvdata(&pdev->dev, adapter); - - /* - * Hypervisor controls PSL timebase initialization (p1 register). - * On FW840, PSL is initialized. - */ - adapter->psl_timebase_synced = true; - - if ((rc = cxl_of_read_adapter_handle(adapter, np))) - goto err1; - - if ((rc = cxl_of_read_adapter_properties(adapter, np))) - goto err1; - - if ((rc = properties_look_ok(adapter))) - goto err1; - - if ((rc = cxl_guest_add_chardev(adapter))) - goto err1; - - /* - * After we call this function we must not free the adapter directly, - * even if it returns an error! - */ - if ((rc = cxl_register_adapter(adapter))) - goto err_put_dev; - - if ((rc = cxl_sysfs_adapter_add(adapter))) - goto err_del_dev; - - /* release the context lock as the adapter is configured */ - cxl_adapter_context_unlock(adapter); - - return adapter; - -err_del_dev: - device_del(&adapter->dev); -err_put_dev: - put_device(&adapter->dev); - free = false; - cxl_guest_remove_chardev(adapter); -err1: - if (free) - free_adapter(adapter); - return ERR_PTR(rc); -} - -void cxl_guest_reload_module(struct cxl *adapter) -{ - struct platform_device *pdev; - - pdev = adapter->guest->pdev; - cxl_guest_remove_adapter(adapter); - - cxl_of_probe(pdev); -} - -const struct cxl_backend_ops cxl_guest_ops = { - .module = THIS_MODULE, - .adapter_reset = guest_reset, - .alloc_one_irq = guest_alloc_one_irq, - .release_one_irq = guest_release_one_irq, - .alloc_irq_ranges = guest_alloc_irq_ranges, - .release_irq_ranges = guest_release_irq_ranges, - .setup_irq = NULL, - .handle_psl_slice_error = guest_handle_psl_slice_error, - .psl_interrupt = guest_psl_irq, - .ack_irq = guest_ack_irq, - .attach_process = guest_attach_process, - .detach_process = guest_detach_process, - .update_ivtes = NULL, - .support_attributes = guest_support_attributes, - .link_ok = guest_link_ok, - .release_afu = guest_release_afu, - .afu_read_err_buffer = guest_afu_read_err_buffer, - .afu_check_and_enable = guest_afu_check_and_enable, - .afu_activate_mode = guest_afu_activate_mode, - .afu_deactivate_mode = guest_afu_deactivate_mode, - .afu_reset = guest_afu_reset, - .afu_cr_read8 = guest_afu_cr_read8, - .afu_cr_read16 = guest_afu_cr_read16, - .afu_cr_read32 = guest_afu_cr_read32, - .afu_cr_read64 = guest_afu_cr_read64, - .afu_cr_write8 = guest_afu_cr_write8, - .afu_cr_write16 = guest_afu_cr_write16, - .afu_cr_write32 = guest_afu_cr_write32, - .read_adapter_vpd = cxl_guest_read_adapter_vpd, -};
diff --git a/drivers/misc/cxl/hcalls.c b/drivers/misc/cxl/hcalls.c deleted file mode 100644 index aba5e20..0000000 --- a/drivers/misc/cxl/hcalls.c +++ /dev/null
@@ -1,643 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Copyright 2015 IBM Corp. - */ - - -#include <linux/compiler.h> -#include <linux/types.h> -#include <linux/delay.h> -#include <asm/byteorder.h> -#include "hcalls.h" -#include "trace.h" - -#define CXL_HCALL_TIMEOUT 60000 -#define CXL_HCALL_TIMEOUT_DOWNLOAD 120000 - -#define H_ATTACH_CA_PROCESS 0x344 -#define H_CONTROL_CA_FUNCTION 0x348 -#define H_DETACH_CA_PROCESS 0x34C -#define H_COLLECT_CA_INT_INFO 0x350 -#define H_CONTROL_CA_FAULTS 0x354 -#define H_DOWNLOAD_CA_FUNCTION 0x35C -#define H_DOWNLOAD_CA_FACILITY 0x364 -#define H_CONTROL_CA_FACILITY 0x368 - -#define H_CONTROL_CA_FUNCTION_RESET 1 /* perform a reset */ -#define H_CONTROL_CA_FUNCTION_SUSPEND_PROCESS 2 /* suspend a process from being executed */ -#define H_CONTROL_CA_FUNCTION_RESUME_PROCESS 3 /* resume a process to be executed */ -#define H_CONTROL_CA_FUNCTION_READ_ERR_STATE 4 /* read the error state */ -#define H_CONTROL_CA_FUNCTION_GET_AFU_ERR 5 /* collect the AFU error buffer */ -#define H_CONTROL_CA_FUNCTION_GET_CONFIG 6 /* collect configuration record */ -#define H_CONTROL_CA_FUNCTION_GET_DOWNLOAD_STATE 7 /* query to return download status */ -#define H_CONTROL_CA_FUNCTION_TERMINATE_PROCESS 8 /* terminate the process before completion */ -#define H_CONTROL_CA_FUNCTION_COLLECT_VPD 9 /* collect VPD */ -#define H_CONTROL_CA_FUNCTION_GET_FUNCTION_ERR_INT 11 /* read the function-wide error data based on an interrupt */ -#define H_CONTROL_CA_FUNCTION_ACK_FUNCTION_ERR_INT 12 /* acknowledge function-wide error data based on an interrupt */ -#define H_CONTROL_CA_FUNCTION_GET_ERROR_LOG 13 /* retrieve the Platform Log ID (PLID) of an error log */ - -#define H_CONTROL_CA_FAULTS_RESPOND_PSL 1 -#define H_CONTROL_CA_FAULTS_RESPOND_AFU 2 - -#define H_CONTROL_CA_FACILITY_RESET 1 /* perform a reset */ -#define H_CONTROL_CA_FACILITY_COLLECT_VPD 2 /* collect VPD */ - -#define H_DOWNLOAD_CA_FACILITY_DOWNLOAD 1 /* download adapter image */ -#define H_DOWNLOAD_CA_FACILITY_VALIDATE 2 /* validate adapter image */ - - -#define _CXL_LOOP_HCALL(call, rc, retbuf, fn, ...) \ - { \ - unsigned int delay, total_delay = 0; \ - u64 token = 0; \ - \ - memset(retbuf, 0, sizeof(retbuf)); \ - while (1) { \ - rc = call(fn, retbuf, __VA_ARGS__, token); \ - token = retbuf[0]; \ - if (rc != H_BUSY && !H_IS_LONG_BUSY(rc)) \ - break; \ - \ - if (rc == H_BUSY) \ - delay = 10; \ - else \ - delay = get_longbusy_msecs(rc); \ - \ - total_delay += delay; \ - if (total_delay > CXL_HCALL_TIMEOUT) { \ - WARN(1, "Warning: Giving up waiting for CXL hcall " \ - "%#x after %u msec\n", fn, total_delay); \ - rc = H_BUSY; \ - break; \ - } \ - msleep(delay); \ - } \ - } -#define CXL_H_WAIT_UNTIL_DONE(...) _CXL_LOOP_HCALL(plpar_hcall, __VA_ARGS__) -#define CXL_H9_WAIT_UNTIL_DONE(...) _CXL_LOOP_HCALL(plpar_hcall9, __VA_ARGS__) - -#define _PRINT_MSG(rc, format, ...) \ - { \ - if ((rc != H_SUCCESS) && (rc != H_CONTINUE)) \ - pr_err(format, __VA_ARGS__); \ - else \ - pr_devel(format, __VA_ARGS__); \ - } \ - - -static char *afu_op_names[] = { - "UNKNOWN_OP", /* 0 undefined */ - "RESET", /* 1 */ - "SUSPEND_PROCESS", /* 2 */ - "RESUME_PROCESS", /* 3 */ - "READ_ERR_STATE", /* 4 */ - "GET_AFU_ERR", /* 5 */ - "GET_CONFIG", /* 6 */ - "GET_DOWNLOAD_STATE", /* 7 */ - "TERMINATE_PROCESS", /* 8 */ - "COLLECT_VPD", /* 9 */ - "UNKNOWN_OP", /* 10 undefined */ - "GET_FUNCTION_ERR_INT", /* 11 */ - "ACK_FUNCTION_ERR_INT", /* 12 */ - "GET_ERROR_LOG", /* 13 */ -}; - -static char *control_adapter_op_names[] = { - "UNKNOWN_OP", /* 0 undefined */ - "RESET", /* 1 */ - "COLLECT_VPD", /* 2 */ -}; - -static char *download_op_names[] = { - "UNKNOWN_OP", /* 0 undefined */ - "DOWNLOAD", /* 1 */ - "VALIDATE", /* 2 */ -}; - -static char *op_str(unsigned int op, char *name_array[], int array_len) -{ - if (op >= array_len) - return "UNKNOWN_OP"; - return name_array[op]; -} - -#define OP_STR(op, name_array) op_str(op, name_array, ARRAY_SIZE(name_array)) - -#define OP_STR_AFU(op) OP_STR(op, afu_op_names) -#define OP_STR_CONTROL_ADAPTER(op) OP_STR(op, control_adapter_op_names) -#define OP_STR_DOWNLOAD_ADAPTER(op) OP_STR(op, download_op_names) - - -long cxl_h_attach_process(u64 unit_address, - struct cxl_process_element_hcall *element, - u64 *process_token, u64 *mmio_addr, u64 *mmio_size) -{ - unsigned long retbuf[PLPAR_HCALL_BUFSIZE]; - long rc; - - CXL_H_WAIT_UNTIL_DONE(rc, retbuf, H_ATTACH_CA_PROCESS, unit_address, virt_to_phys(element)); - _PRINT_MSG(rc, "cxl_h_attach_process(%#.16llx, %#.16lx): %li\n", - unit_address, virt_to_phys(element), rc); - trace_cxl_hcall_attach(unit_address, virt_to_phys(element), retbuf[0], retbuf[1], retbuf[2], rc); - - pr_devel("token: 0x%.8lx mmio_addr: 0x%lx mmio_size: 0x%lx\nProcess Element Structure:\n", - retbuf[0], retbuf[1], retbuf[2]); - cxl_dump_debug_buffer(element, sizeof(*element)); - - switch (rc) { - case H_SUCCESS: /* The process info is attached to the coherent platform function */ - *process_token = retbuf[0]; - if (mmio_addr) - *mmio_addr = retbuf[1]; - if (mmio_size) - *mmio_size = retbuf[2]; - return 0; - case H_PARAMETER: /* An incorrect parameter was supplied. */ - case H_FUNCTION: /* The function is not supported. */ - return -EINVAL; - case H_AUTHORITY: /* The partition does not have authority to perform this hcall */ - case H_RESOURCE: /* The coherent platform function does not have enough additional resource to attach the process */ - case H_HARDWARE: /* A hardware event prevented the attach operation */ - case H_STATE: /* The coherent platform function is not in a valid state */ - case H_BUSY: - return -EBUSY; - default: - WARN(1, "Unexpected return code: %lx", rc); - return -EINVAL; - } -} - -/* - * cxl_h_detach_process - Detach a process element from a coherent - * platform function. - */ -long cxl_h_detach_process(u64 unit_address, u64 process_token) -{ - unsigned long retbuf[PLPAR_HCALL_BUFSIZE]; - long rc; - - CXL_H_WAIT_UNTIL_DONE(rc, retbuf, H_DETACH_CA_PROCESS, unit_address, process_token); - _PRINT_MSG(rc, "cxl_h_detach_process(%#.16llx, 0x%.8llx): %li\n", unit_address, process_token, rc); - trace_cxl_hcall_detach(unit_address, process_token, rc); - - switch (rc) { - case H_SUCCESS: /* The process was detached from the coherent platform function */ - return 0; - case H_PARAMETER: /* An incorrect parameter was supplied. */ - return -EINVAL; - case H_AUTHORITY: /* The partition does not have authority to perform this hcall */ - case H_RESOURCE: /* The function has page table mappings for MMIO */ - case H_HARDWARE: /* A hardware event prevented the detach operation */ - case H_STATE: /* The coherent platform function is not in a valid state */ - case H_BUSY: - return -EBUSY; - default: - WARN(1, "Unexpected return code: %lx", rc); - return -EINVAL; - } -} - -/* - * cxl_h_control_function - This H_CONTROL_CA_FUNCTION hypervisor call allows - * the partition to manipulate or query - * certain coherent platform function behaviors. - */ -static long cxl_h_control_function(u64 unit_address, u64 op, - u64 p1, u64 p2, u64 p3, u64 p4, u64 *out) -{ - unsigned long retbuf[PLPAR_HCALL9_BUFSIZE]; - long rc; - - CXL_H9_WAIT_UNTIL_DONE(rc, retbuf, H_CONTROL_CA_FUNCTION, unit_address, op, p1, p2, p3, p4); - _PRINT_MSG(rc, "cxl_h_control_function(%#.16llx, %s(%#llx, %#llx, %#llx, %#llx, R4: %#lx)): %li\n", - unit_address, OP_STR_AFU(op), p1, p2, p3, p4, retbuf[0], rc); - trace_cxl_hcall_control_function(unit_address, OP_STR_AFU(op), p1, p2, p3, p4, retbuf[0], rc); - - switch (rc) { - case H_SUCCESS: /* The operation is completed for the coherent platform function */ - if ((op == H_CONTROL_CA_FUNCTION_GET_FUNCTION_ERR_INT || - op == H_CONTROL_CA_FUNCTION_READ_ERR_STATE || - op == H_CONTROL_CA_FUNCTION_COLLECT_VPD)) - *out = retbuf[0]; - return 0; - case H_PARAMETER: /* An incorrect parameter was supplied. */ - case H_FUNCTION: /* The function is not supported. */ - case H_NOT_FOUND: /* The operation supplied was not valid */ - case H_NOT_AVAILABLE: /* The operation cannot be performed because the AFU has not been downloaded */ - case H_SG_LIST: /* An block list entry was invalid */ - return -EINVAL; - case H_AUTHORITY: /* The partition does not have authority to perform this hcall */ - case H_RESOURCE: /* The function has page table mappings for MMIO */ - case H_HARDWARE: /* A hardware event prevented the attach operation */ - case H_STATE: /* The coherent platform function is not in a valid state */ - case H_BUSY: - return -EBUSY; - default: - WARN(1, "Unexpected return code: %lx", rc); - return -EINVAL; - } -} - -/* - * cxl_h_reset_afu - Perform a reset to the coherent platform function. - */ -long cxl_h_reset_afu(u64 unit_address) -{ - return cxl_h_control_function(unit_address, - H_CONTROL_CA_FUNCTION_RESET, - 0, 0, 0, 0, - NULL); -} - -/* - * cxl_h_suspend_process - Suspend a process from being executed - * Parameter1 = process-token as returned from H_ATTACH_CA_PROCESS when - * process was attached. - */ -long cxl_h_suspend_process(u64 unit_address, u64 process_token) -{ - return cxl_h_control_function(unit_address, - H_CONTROL_CA_FUNCTION_SUSPEND_PROCESS, - process_token, 0, 0, 0, - NULL); -} - -/* - * cxl_h_resume_process - Resume a process to be executed - * Parameter1 = process-token as returned from H_ATTACH_CA_PROCESS when - * process was attached. - */ -long cxl_h_resume_process(u64 unit_address, u64 process_token) -{ - return cxl_h_control_function(unit_address, - H_CONTROL_CA_FUNCTION_RESUME_PROCESS, - process_token, 0, 0, 0, - NULL); -} - -/* - * cxl_h_read_error_state - Checks the error state of the coherent - * platform function. - * R4 contains the error state - */ -long cxl_h_read_error_state(u64 unit_address, u64 *state) -{ - return cxl_h_control_function(unit_address, - H_CONTROL_CA_FUNCTION_READ_ERR_STATE, - 0, 0, 0, 0, - state); -} - -/* - * cxl_h_get_afu_err - collect the AFU error buffer - * Parameter1 = byte offset into error buffer to retrieve, valid values - * are between 0 and (ibm,error-buffer-size - 1) - * Parameter2 = 4K aligned real address of error buffer, to be filled in - * Parameter3 = length of error buffer, valid values are 4K or less - */ -long cxl_h_get_afu_err(u64 unit_address, u64 offset, - u64 buf_address, u64 len) -{ - return cxl_h_control_function(unit_address, - H_CONTROL_CA_FUNCTION_GET_AFU_ERR, - offset, buf_address, len, 0, - NULL); -} - -/* - * cxl_h_get_config - collect configuration record for the - * coherent platform function - * Parameter1 = # of configuration record to retrieve, valid values are - * between 0 and (ibm,#config-records - 1) - * Parameter2 = byte offset into configuration record to retrieve, - * valid values are between 0 and (ibm,config-record-size - 1) - * Parameter3 = 4K aligned real address of configuration record buffer, - * to be filled in - * Parameter4 = length of configuration buffer, valid values are 4K or less - */ -long cxl_h_get_config(u64 unit_address, u64 cr_num, u64 offset, - u64 buf_address, u64 len) -{ - return cxl_h_control_function(unit_address, - H_CONTROL_CA_FUNCTION_GET_CONFIG, - cr_num, offset, buf_address, len, - NULL); -} - -/* - * cxl_h_terminate_process - Terminate the process before completion - * Parameter1 = process-token as returned from H_ATTACH_CA_PROCESS when - * process was attached. - */ -long cxl_h_terminate_process(u64 unit_address, u64 process_token) -{ - return cxl_h_control_function(unit_address, - H_CONTROL_CA_FUNCTION_TERMINATE_PROCESS, - process_token, 0, 0, 0, - NULL); -} - -/* - * cxl_h_collect_vpd - Collect VPD for the coherent platform function. - * Parameter1 = # of VPD record to retrieve, valid values are between 0 - * and (ibm,#config-records - 1). - * Parameter2 = 4K naturally aligned real buffer containing block - * list entries - * Parameter3 = number of block list entries in the block list, valid - * values are between 0 and 256 - */ -long cxl_h_collect_vpd(u64 unit_address, u64 record, u64 list_address, - u64 num, u64 *out) -{ - return cxl_h_control_function(unit_address, - H_CONTROL_CA_FUNCTION_COLLECT_VPD, - record, list_address, num, 0, - out); -} - -/* - * cxl_h_get_fn_error_interrupt - Read the function-wide error data based on an interrupt - */ -long cxl_h_get_fn_error_interrupt(u64 unit_address, u64 *reg) -{ - return cxl_h_control_function(unit_address, - H_CONTROL_CA_FUNCTION_GET_FUNCTION_ERR_INT, - 0, 0, 0, 0, reg); -} - -/* - * cxl_h_ack_fn_error_interrupt - Acknowledge function-wide error data - * based on an interrupt - * Parameter1 = value to write to the function-wide error interrupt register - */ -long cxl_h_ack_fn_error_interrupt(u64 unit_address, u64 value) -{ - return cxl_h_control_function(unit_address, - H_CONTROL_CA_FUNCTION_ACK_FUNCTION_ERR_INT, - value, 0, 0, 0, - NULL); -} - -/* - * cxl_h_get_error_log - Retrieve the Platform Log ID (PLID) of - * an error log - */ -long cxl_h_get_error_log(u64 unit_address, u64 value) -{ - return cxl_h_control_function(unit_address, - H_CONTROL_CA_FUNCTION_GET_ERROR_LOG, - 0, 0, 0, 0, - NULL); -} - -/* - * cxl_h_collect_int_info - Collect interrupt info about a coherent - * platform function after an interrupt occurred. - */ -long cxl_h_collect_int_info(u64 unit_address, u64 process_token, - struct cxl_irq_info *info) -{ - long rc; - - BUG_ON(sizeof(*info) != sizeof(unsigned long[PLPAR_HCALL9_BUFSIZE])); - - rc = plpar_hcall9(H_COLLECT_CA_INT_INFO, (unsigned long *) info, - unit_address, process_token); - _PRINT_MSG(rc, "cxl_h_collect_int_info(%#.16llx, 0x%llx): %li\n", - unit_address, process_token, rc); - trace_cxl_hcall_collect_int_info(unit_address, process_token, rc); - - switch (rc) { - case H_SUCCESS: /* The interrupt info is returned in return registers. */ - pr_devel("dsisr:%#llx, dar:%#llx, dsr:%#llx, pid_tid:%#llx, afu_err:%#llx, errstat:%#llx\n", - info->dsisr, info->dar, info->dsr, info->reserved, - info->afu_err, info->errstat); - return 0; - case H_PARAMETER: /* An incorrect parameter was supplied. */ - return -EINVAL; - case H_AUTHORITY: /* The partition does not have authority to perform this hcall. */ - case H_HARDWARE: /* A hardware event prevented the collection of the interrupt info.*/ - case H_STATE: /* The coherent platform function is not in a valid state to collect interrupt info. */ - return -EBUSY; - default: - WARN(1, "Unexpected return code: %lx", rc); - return -EINVAL; - } -} - -/* - * cxl_h_control_faults - Control the operation of a coherent platform - * function after a fault occurs. - * - * Parameters - * control-mask: value to control the faults - * looks like PSL_TFC_An shifted >> 32 - * reset-mask: mask to control reset of function faults - * Set reset_mask = 1 to reset PSL errors - */ -long cxl_h_control_faults(u64 unit_address, u64 process_token, - u64 control_mask, u64 reset_mask) -{ - unsigned long retbuf[PLPAR_HCALL_BUFSIZE]; - long rc; - - memset(retbuf, 0, sizeof(retbuf)); - - rc = plpar_hcall(H_CONTROL_CA_FAULTS, retbuf, unit_address, - H_CONTROL_CA_FAULTS_RESPOND_PSL, process_token, - control_mask, reset_mask); - _PRINT_MSG(rc, "cxl_h_control_faults(%#.16llx, 0x%llx, %#llx, %#llx): %li (%#lx)\n", - unit_address, process_token, control_mask, reset_mask, - rc, retbuf[0]); - trace_cxl_hcall_control_faults(unit_address, process_token, - control_mask, reset_mask, retbuf[0], rc); - - switch (rc) { - case H_SUCCESS: /* Faults were successfully controlled for the function. */ - return 0; - case H_PARAMETER: /* An incorrect parameter was supplied. */ - return -EINVAL; - case H_HARDWARE: /* A hardware event prevented the control of faults. */ - case H_STATE: /* The function was in an invalid state. */ - case H_AUTHORITY: /* The partition does not have authority to perform this hcall; the coherent platform facilities may need to be licensed. */ - return -EBUSY; - case H_FUNCTION: /* The function is not supported */ - case H_NOT_FOUND: /* The operation supplied was not valid */ - return -EINVAL; - default: - WARN(1, "Unexpected return code: %lx", rc); - return -EINVAL; - } -} - -/* - * cxl_h_control_facility - This H_CONTROL_CA_FACILITY hypervisor call - * allows the partition to manipulate or query - * certain coherent platform facility behaviors. - */ -static long cxl_h_control_facility(u64 unit_address, u64 op, - u64 p1, u64 p2, u64 p3, u64 p4, u64 *out) -{ - unsigned long retbuf[PLPAR_HCALL9_BUFSIZE]; - long rc; - - CXL_H9_WAIT_UNTIL_DONE(rc, retbuf, H_CONTROL_CA_FACILITY, unit_address, op, p1, p2, p3, p4); - _PRINT_MSG(rc, "cxl_h_control_facility(%#.16llx, %s(%#llx, %#llx, %#llx, %#llx, R4: %#lx)): %li\n", - unit_address, OP_STR_CONTROL_ADAPTER(op), p1, p2, p3, p4, retbuf[0], rc); - trace_cxl_hcall_control_facility(unit_address, OP_STR_CONTROL_ADAPTER(op), p1, p2, p3, p4, retbuf[0], rc); - - switch (rc) { - case H_SUCCESS: /* The operation is completed for the coherent platform facility */ - if (op == H_CONTROL_CA_FACILITY_COLLECT_VPD) - *out = retbuf[0]; - return 0; - case H_PARAMETER: /* An incorrect parameter was supplied. */ - case H_FUNCTION: /* The function is not supported. */ - case H_NOT_FOUND: /* The operation supplied was not valid */ - case H_NOT_AVAILABLE: /* The operation cannot be performed because the AFU has not been downloaded */ - case H_SG_LIST: /* An block list entry was invalid */ - return -EINVAL; - case H_AUTHORITY: /* The partition does not have authority to perform this hcall */ - case H_RESOURCE: /* The function has page table mappings for MMIO */ - case H_HARDWARE: /* A hardware event prevented the attach operation */ - case H_STATE: /* The coherent platform facility is not in a valid state */ - case H_BUSY: - return -EBUSY; - default: - WARN(1, "Unexpected return code: %lx", rc); - return -EINVAL; - } -} - -/* - * cxl_h_reset_adapter - Perform a reset to the coherent platform facility. - */ -long cxl_h_reset_adapter(u64 unit_address) -{ - return cxl_h_control_facility(unit_address, - H_CONTROL_CA_FACILITY_RESET, - 0, 0, 0, 0, - NULL); -} - -/* - * cxl_h_collect_vpd - Collect VPD for the coherent platform function. - * Parameter1 = 4K naturally aligned real buffer containing block - * list entries - * Parameter2 = number of block list entries in the block list, valid - * values are between 0 and 256 - */ -long cxl_h_collect_vpd_adapter(u64 unit_address, u64 list_address, - u64 num, u64 *out) -{ - return cxl_h_control_facility(unit_address, - H_CONTROL_CA_FACILITY_COLLECT_VPD, - list_address, num, 0, 0, - out); -} - -/* - * cxl_h_download_facility - This H_DOWNLOAD_CA_FACILITY - * hypervisor call provide platform support for - * downloading a base adapter image to the coherent - * platform facility, and for validating the entire - * image after the download. - * Parameters - * op: operation to perform to the coherent platform function - * Download: operation = 1, the base image in the coherent platform - * facility is first erased, and then - * programmed using the image supplied - * in the scatter/gather list. - * Validate: operation = 2, the base image in the coherent platform - * facility is compared with the image - * supplied in the scatter/gather list. - * list_address: 4K naturally aligned real buffer containing - * scatter/gather list entries. - * num: number of block list entries in the scatter/gather list. - */ -static long cxl_h_download_facility(u64 unit_address, u64 op, - u64 list_address, u64 num, - u64 *out) -{ - unsigned long retbuf[PLPAR_HCALL_BUFSIZE]; - unsigned int delay, total_delay = 0; - u64 token = 0; - long rc; - - if (*out != 0) - token = *out; - - memset(retbuf, 0, sizeof(retbuf)); - while (1) { - rc = plpar_hcall(H_DOWNLOAD_CA_FACILITY, retbuf, - unit_address, op, list_address, num, - token); - token = retbuf[0]; - if (rc != H_BUSY && !H_IS_LONG_BUSY(rc)) - break; - - if (rc != H_BUSY) { - delay = get_longbusy_msecs(rc); - total_delay += delay; - if (total_delay > CXL_HCALL_TIMEOUT_DOWNLOAD) { - WARN(1, "Warning: Giving up waiting for CXL hcall " - "%#x after %u msec\n", - H_DOWNLOAD_CA_FACILITY, total_delay); - rc = H_BUSY; - break; - } - msleep(delay); - } - } - _PRINT_MSG(rc, "cxl_h_download_facility(%#.16llx, %s(%#llx, %#llx), %#lx): %li\n", - unit_address, OP_STR_DOWNLOAD_ADAPTER(op), list_address, num, retbuf[0], rc); - trace_cxl_hcall_download_facility(unit_address, OP_STR_DOWNLOAD_ADAPTER(op), list_address, num, retbuf[0], rc); - - switch (rc) { - case H_SUCCESS: /* The operation is completed for the coherent platform facility */ - return 0; - case H_PARAMETER: /* An incorrect parameter was supplied */ - case H_FUNCTION: /* The function is not supported. */ - case H_SG_LIST: /* An block list entry was invalid */ - case H_BAD_DATA: /* Image verification failed */ - return -EINVAL; - case H_AUTHORITY: /* The partition does not have authority to perform this hcall */ - case H_RESOURCE: /* The function has page table mappings for MMIO */ - case H_HARDWARE: /* A hardware event prevented the attach operation */ - case H_STATE: /* The coherent platform facility is not in a valid state */ - case H_BUSY: - return -EBUSY; - case H_CONTINUE: - *out = retbuf[0]; - return 1; /* More data is needed for the complete image */ - default: - WARN(1, "Unexpected return code: %lx", rc); - return -EINVAL; - } -} - -/* - * cxl_h_download_adapter_image - Download the base image to the coherent - * platform facility. - */ -long cxl_h_download_adapter_image(u64 unit_address, - u64 list_address, u64 num, - u64 *out) -{ - return cxl_h_download_facility(unit_address, - H_DOWNLOAD_CA_FACILITY_DOWNLOAD, - list_address, num, out); -} - -/* - * cxl_h_validate_adapter_image - Validate the base image in the coherent - * platform facility. - */ -long cxl_h_validate_adapter_image(u64 unit_address, - u64 list_address, u64 num, - u64 *out) -{ - return cxl_h_download_facility(unit_address, - H_DOWNLOAD_CA_FACILITY_VALIDATE, - list_address, num, out); -}
diff --git a/drivers/misc/cxl/hcalls.h b/drivers/misc/cxl/hcalls.h deleted file mode 100644 index d200465..0000000 --- a/drivers/misc/cxl/hcalls.h +++ /dev/null
@@ -1,200 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * Copyright 2015 IBM Corp. - */ - -#ifndef _HCALLS_H -#define _HCALLS_H - -#include <linux/types.h> -#include <asm/byteorder.h> -#include <asm/hvcall.h> -#include "cxl.h" - -#define SG_BUFFER_SIZE 4096 -#define SG_MAX_ENTRIES 256 - -struct sg_list { - u64 phys_addr; - u64 len; -}; - -/* - * This is straight out of PAPR, but replacing some of the compound fields with - * a single field, where they were identical to the register layout. - * - * The 'flags' parameter regroups the various bit-fields - */ -#define CXL_PE_CSRP_VALID (1ULL << 63) -#define CXL_PE_PROBLEM_STATE (1ULL << 62) -#define CXL_PE_SECONDARY_SEGMENT_TBL_SRCH (1ULL << 61) -#define CXL_PE_TAGS_ACTIVE (1ULL << 60) -#define CXL_PE_USER_STATE (1ULL << 59) -#define CXL_PE_TRANSLATION_ENABLED (1ULL << 58) -#define CXL_PE_64_BIT (1ULL << 57) -#define CXL_PE_PRIVILEGED_PROCESS (1ULL << 56) - -#define CXL_PROCESS_ELEMENT_VERSION 1 -struct cxl_process_element_hcall { - __be64 version; - __be64 flags; - u8 reserved0[12]; - __be32 pslVirtualIsn; - u8 applicationVirtualIsnBitmap[256]; - u8 reserved1[144]; - struct cxl_process_element_common common; - u8 reserved4[12]; -} __packed; - -#define H_STATE_NORMAL 1 -#define H_STATE_DISABLE 2 -#define H_STATE_TEMP_UNAVAILABLE 3 -#define H_STATE_PERM_UNAVAILABLE 4 - -/* NOTE: element must be a logical real address, and must be pinned */ -long cxl_h_attach_process(u64 unit_address, struct cxl_process_element_hcall *element, - u64 *process_token, u64 *mmio_addr, u64 *mmio_size); - -/** - * cxl_h_detach_process - Detach a process element from a coherent - * platform function. - */ -long cxl_h_detach_process(u64 unit_address, u64 process_token); - -/** - * cxl_h_reset_afu - Perform a reset to the coherent platform function. - */ -long cxl_h_reset_afu(u64 unit_address); - -/** - * cxl_h_suspend_process - Suspend a process from being executed - * Parameter1 = process-token as returned from H_ATTACH_CA_PROCESS when - * process was attached. - */ -long cxl_h_suspend_process(u64 unit_address, u64 process_token); - -/** - * cxl_h_resume_process - Resume a process to be executed - * Parameter1 = process-token as returned from H_ATTACH_CA_PROCESS when - * process was attached. - */ -long cxl_h_resume_process(u64 unit_address, u64 process_token); - -/** - * cxl_h_read_error_state - Reads the error state of the coherent - * platform function. - * R4 contains the error state - */ -long cxl_h_read_error_state(u64 unit_address, u64 *state); - -/** - * cxl_h_get_afu_err - collect the AFU error buffer - * Parameter1 = byte offset into error buffer to retrieve, valid values - * are between 0 and (ibm,error-buffer-size - 1) - * Parameter2 = 4K aligned real address of error buffer, to be filled in - * Parameter3 = length of error buffer, valid values are 4K or less - */ -long cxl_h_get_afu_err(u64 unit_address, u64 offset, u64 buf_address, u64 len); - -/** - * cxl_h_get_config - collect configuration record for the - * coherent platform function - * Parameter1 = # of configuration record to retrieve, valid values are - * between 0 and (ibm,#config-records - 1) - * Parameter2 = byte offset into configuration record to retrieve, - * valid values are between 0 and (ibm,config-record-size - 1) - * Parameter3 = 4K aligned real address of configuration record buffer, - * to be filled in - * Parameter4 = length of configuration buffer, valid values are 4K or less - */ -long cxl_h_get_config(u64 unit_address, u64 cr_num, u64 offset, - u64 buf_address, u64 len); - -/** - * cxl_h_terminate_process - Terminate the process before completion - * Parameter1 = process-token as returned from H_ATTACH_CA_PROCESS when - * process was attached. - */ -long cxl_h_terminate_process(u64 unit_address, u64 process_token); - -/** - * cxl_h_collect_vpd - Collect VPD for the coherent platform function. - * Parameter1 = # of VPD record to retrieve, valid values are between 0 - * and (ibm,#config-records - 1). - * Parameter2 = 4K naturally aligned real buffer containing block - * list entries - * Parameter3 = number of block list entries in the block list, valid - * values are between 0 and 256 - */ -long cxl_h_collect_vpd(u64 unit_address, u64 record, u64 list_address, - u64 num, u64 *out); - -/** - * cxl_h_get_fn_error_interrupt - Read the function-wide error data based on an interrupt - */ -long cxl_h_get_fn_error_interrupt(u64 unit_address, u64 *reg); - -/** - * cxl_h_ack_fn_error_interrupt - Acknowledge function-wide error data - * based on an interrupt - * Parameter1 = value to write to the function-wide error interrupt register - */ -long cxl_h_ack_fn_error_interrupt(u64 unit_address, u64 value); - -/** - * cxl_h_get_error_log - Retrieve the Platform Log ID (PLID) of - * an error log - */ -long cxl_h_get_error_log(u64 unit_address, u64 value); - -/** - * cxl_h_collect_int_info - Collect interrupt info about a coherent - * platform function after an interrupt occurred. - */ -long cxl_h_collect_int_info(u64 unit_address, u64 process_token, - struct cxl_irq_info *info); - -/** - * cxl_h_control_faults - Control the operation of a coherent platform - * function after a fault occurs. - * - * Parameters - * control-mask: value to control the faults - * looks like PSL_TFC_An shifted >> 32 - * reset-mask: mask to control reset of function faults - * Set reset_mask = 1 to reset PSL errors - */ -long cxl_h_control_faults(u64 unit_address, u64 process_token, - u64 control_mask, u64 reset_mask); - -/** - * cxl_h_reset_adapter - Perform a reset to the coherent platform facility. - */ -long cxl_h_reset_adapter(u64 unit_address); - -/** - * cxl_h_collect_vpd - Collect VPD for the coherent platform function. - * Parameter1 = 4K naturally aligned real buffer containing block - * list entries - * Parameter2 = number of block list entries in the block list, valid - * values are between 0 and 256 - */ -long cxl_h_collect_vpd_adapter(u64 unit_address, u64 list_address, - u64 num, u64 *out); - -/** - * cxl_h_download_adapter_image - Download the base image to the coherent - * platform facility. - */ -long cxl_h_download_adapter_image(u64 unit_address, - u64 list_address, u64 num, - u64 *out); - -/** - * cxl_h_validate_adapter_image - Validate the base image in the coherent - * platform facility. - */ -long cxl_h_validate_adapter_image(u64 unit_address, - u64 list_address, u64 num, - u64 *out); -#endif /* _HCALLS_H */
diff --git a/drivers/misc/cxl/irq.c b/drivers/misc/cxl/irq.c deleted file mode 100644 index b730e02..0000000 --- a/drivers/misc/cxl/irq.c +++ /dev/null
@@ -1,450 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Copyright 2014 IBM Corp. - */ - -#include <linux/interrupt.h> -#include <linux/irqdomain.h> -#include <linux/workqueue.h> -#include <linux/sched.h> -#include <linux/wait.h> -#include <linux/slab.h> -#include <linux/pid.h> -#include <asm/cputable.h> -#include <misc/cxl-base.h> - -#include "cxl.h" -#include "trace.h" - -static int afu_irq_range_start(void) -{ - if (cpu_has_feature(CPU_FTR_HVMODE)) - return 1; - return 0; -} - -static irqreturn_t schedule_cxl_fault(struct cxl_context *ctx, u64 dsisr, u64 dar) -{ - ctx->dsisr = dsisr; - ctx->dar = dar; - schedule_work(&ctx->fault_work); - return IRQ_HANDLED; -} - -irqreturn_t cxl_irq_psl9(int irq, struct cxl_context *ctx, struct cxl_irq_info *irq_info) -{ - u64 dsisr, dar; - - dsisr = irq_info->dsisr; - dar = irq_info->dar; - - trace_cxl_psl9_irq(ctx, irq, dsisr, dar); - - pr_devel("CXL interrupt %i for afu pe: %i DSISR: %#llx DAR: %#llx\n", irq, ctx->pe, dsisr, dar); - - if (dsisr & CXL_PSL9_DSISR_An_TF) { - pr_devel("CXL interrupt: Scheduling translation fault handling for later (pe: %i)\n", ctx->pe); - return schedule_cxl_fault(ctx, dsisr, dar); - } - - if (dsisr & CXL_PSL9_DSISR_An_PE) - return cxl_ops->handle_psl_slice_error(ctx, dsisr, - irq_info->errstat); - if (dsisr & CXL_PSL9_DSISR_An_AE) { - pr_devel("CXL interrupt: AFU Error 0x%016llx\n", irq_info->afu_err); - - if (ctx->pending_afu_err) { - /* - * This shouldn't happen - the PSL treats these errors - * as fatal and will have reset the AFU, so there's not - * much point buffering multiple AFU errors. - * OTOH if we DO ever see a storm of these come in it's - * probably best that we log them somewhere: - */ - dev_err_ratelimited(&ctx->afu->dev, "CXL AFU Error undelivered to pe %i: 0x%016llx\n", - ctx->pe, irq_info->afu_err); - } else { - spin_lock(&ctx->lock); - ctx->afu_err = irq_info->afu_err; - ctx->pending_afu_err = 1; - spin_unlock(&ctx->lock); - - wake_up_all(&ctx->wq); - } - - cxl_ops->ack_irq(ctx, CXL_PSL_TFC_An_A, 0); - return IRQ_HANDLED; - } - if (dsisr & CXL_PSL9_DSISR_An_OC) - pr_devel("CXL interrupt: OS Context Warning\n"); - - WARN(1, "Unhandled CXL PSL IRQ\n"); - return IRQ_HANDLED; -} - -irqreturn_t cxl_irq_psl8(int irq, struct cxl_context *ctx, struct cxl_irq_info *irq_info) -{ - u64 dsisr, dar; - - dsisr = irq_info->dsisr; - dar = irq_info->dar; - - trace_cxl_psl_irq(ctx, irq, dsisr, dar); - - pr_devel("CXL interrupt %i for afu pe: %i DSISR: %#llx DAR: %#llx\n", irq, ctx->pe, dsisr, dar); - - if (dsisr & CXL_PSL_DSISR_An_DS) { - /* - * We don't inherently need to sleep to handle this, but we do - * need to get a ref to the task's mm, which we can't do from - * irq context without the potential for a deadlock since it - * takes the task_lock. An alternate option would be to keep a - * reference to the task's mm the entire time it has cxl open, - * but to do that we need to solve the issue where we hold a - * ref to the mm, but the mm can hold a ref to the fd after an - * mmap preventing anything from being cleaned up. - */ - pr_devel("Scheduling segment miss handling for later pe: %i\n", ctx->pe); - return schedule_cxl_fault(ctx, dsisr, dar); - } - - if (dsisr & CXL_PSL_DSISR_An_M) - pr_devel("CXL interrupt: PTE not found\n"); - if (dsisr & CXL_PSL_DSISR_An_P) - pr_devel("CXL interrupt: Storage protection violation\n"); - if (dsisr & CXL_PSL_DSISR_An_A) - pr_devel("CXL interrupt: AFU lock access to write through or cache inhibited storage\n"); - if (dsisr & CXL_PSL_DSISR_An_S) - pr_devel("CXL interrupt: Access was afu_wr or afu_zero\n"); - if (dsisr & CXL_PSL_DSISR_An_K) - pr_devel("CXL interrupt: Access not permitted by virtual page class key protection\n"); - - if (dsisr & CXL_PSL_DSISR_An_DM) { - /* - * In some cases we might be able to handle the fault - * immediately if hash_page would succeed, but we still need - * the task's mm, which as above we can't get without a lock - */ - pr_devel("Scheduling page fault handling for later pe: %i\n", ctx->pe); - return schedule_cxl_fault(ctx, dsisr, dar); - } - if (dsisr & CXL_PSL_DSISR_An_ST) - WARN(1, "CXL interrupt: Segment Table PTE not found\n"); - if (dsisr & CXL_PSL_DSISR_An_UR) - pr_devel("CXL interrupt: AURP PTE not found\n"); - if (dsisr & CXL_PSL_DSISR_An_PE) - return cxl_ops->handle_psl_slice_error(ctx, dsisr, - irq_info->errstat); - if (dsisr & CXL_PSL_DSISR_An_AE) { - pr_devel("CXL interrupt: AFU Error 0x%016llx\n", irq_info->afu_err); - - if (ctx->pending_afu_err) { - /* - * This shouldn't happen - the PSL treats these errors - * as fatal and will have reset the AFU, so there's not - * much point buffering multiple AFU errors. - * OTOH if we DO ever see a storm of these come in it's - * probably best that we log them somewhere: - */ - dev_err_ratelimited(&ctx->afu->dev, "CXL AFU Error " - "undelivered to pe %i: 0x%016llx\n", - ctx->pe, irq_info->afu_err); - } else { - spin_lock(&ctx->lock); - ctx->afu_err = irq_info->afu_err; - ctx->pending_afu_err = true; - spin_unlock(&ctx->lock); - - wake_up_all(&ctx->wq); - } - - cxl_ops->ack_irq(ctx, CXL_PSL_TFC_An_A, 0); - return IRQ_HANDLED; - } - if (dsisr & CXL_PSL_DSISR_An_OC) - pr_devel("CXL interrupt: OS Context Warning\n"); - - WARN(1, "Unhandled CXL PSL IRQ\n"); - return IRQ_HANDLED; -} - -static irqreturn_t cxl_irq_afu(int irq, void *data) -{ - struct cxl_context *ctx = data; - irq_hw_number_t hwirq = irqd_to_hwirq(irq_get_irq_data(irq)); - int irq_off, afu_irq = 0; - __u16 range; - int r; - - /* - * Look for the interrupt number. - * On bare-metal, we know range 0 only contains the PSL - * interrupt so we could start counting at range 1 and initialize - * afu_irq at 1. - * In a guest, range 0 also contains AFU interrupts, so it must - * be counted for. Therefore we initialize afu_irq at 0 to take into - * account the PSL interrupt. - * - * For code-readability, it just seems easier to go over all - * the ranges on bare-metal and guest. The end result is the same. - */ - for (r = 0; r < CXL_IRQ_RANGES; r++) { - irq_off = hwirq - ctx->irqs.offset[r]; - range = ctx->irqs.range[r]; - if (irq_off >= 0 && irq_off < range) { - afu_irq += irq_off; - break; - } - afu_irq += range; - } - if (unlikely(r >= CXL_IRQ_RANGES)) { - WARN(1, "Received AFU IRQ out of range for pe %i (virq %i hwirq %lx)\n", - ctx->pe, irq, hwirq); - return IRQ_HANDLED; - } - - trace_cxl_afu_irq(ctx, afu_irq, irq, hwirq); - pr_devel("Received AFU interrupt %i for pe: %i (virq %i hwirq %lx)\n", - afu_irq, ctx->pe, irq, hwirq); - - if (unlikely(!ctx->irq_bitmap)) { - WARN(1, "Received AFU IRQ for context with no IRQ bitmap\n"); - return IRQ_HANDLED; - } - spin_lock(&ctx->lock); - set_bit(afu_irq - 1, ctx->irq_bitmap); - ctx->pending_irq = true; - spin_unlock(&ctx->lock); - - wake_up_all(&ctx->wq); - - return IRQ_HANDLED; -} - -unsigned int cxl_map_irq(struct cxl *adapter, irq_hw_number_t hwirq, - irq_handler_t handler, void *cookie, const char *name) -{ - unsigned int virq; - int result; - - /* IRQ Domain? */ - virq = irq_create_mapping(NULL, hwirq); - if (!virq) { - dev_warn(&adapter->dev, "cxl_map_irq: irq_create_mapping failed\n"); - return 0; - } - - if (cxl_ops->setup_irq) - cxl_ops->setup_irq(adapter, hwirq, virq); - - pr_devel("hwirq %#lx mapped to virq %u\n", hwirq, virq); - - result = request_irq(virq, handler, 0, name, cookie); - if (result) { - dev_warn(&adapter->dev, "cxl_map_irq: request_irq failed: %i\n", result); - return 0; - } - - return virq; -} - -void cxl_unmap_irq(unsigned int virq, void *cookie) -{ - free_irq(virq, cookie); -} - -int cxl_register_one_irq(struct cxl *adapter, - irq_handler_t handler, - void *cookie, - irq_hw_number_t *dest_hwirq, - unsigned int *dest_virq, - const char *name) -{ - int hwirq, virq; - - if ((hwirq = cxl_ops->alloc_one_irq(adapter)) < 0) - return hwirq; - - if (!(virq = cxl_map_irq(adapter, hwirq, handler, cookie, name))) - goto err; - - *dest_hwirq = hwirq; - *dest_virq = virq; - - return 0; - -err: - cxl_ops->release_one_irq(adapter, hwirq); - return -ENOMEM; -} - -void afu_irq_name_free(struct cxl_context *ctx) -{ - struct cxl_irq_name *irq_name, *tmp; - - list_for_each_entry_safe(irq_name, tmp, &ctx->irq_names, list) { - kfree(irq_name->name); - list_del(&irq_name->list); - kfree(irq_name); - } -} - -int afu_allocate_irqs(struct cxl_context *ctx, u32 count) -{ - int rc, r, i, j = 1; - struct cxl_irq_name *irq_name; - int alloc_count; - - /* - * In native mode, range 0 is reserved for the multiplexed - * PSL interrupt. It has been allocated when the AFU was initialized. - * - * In a guest, the PSL interrupt is not mutliplexed, but per-context, - * and is the first interrupt from range 0. It still needs to be - * allocated, so bump the count by one. - */ - if (cpu_has_feature(CPU_FTR_HVMODE)) - alloc_count = count; - else - alloc_count = count + 1; - - if ((rc = cxl_ops->alloc_irq_ranges(&ctx->irqs, ctx->afu->adapter, - alloc_count))) - return rc; - - if (cpu_has_feature(CPU_FTR_HVMODE)) { - /* Multiplexed PSL Interrupt */ - ctx->irqs.offset[0] = ctx->afu->native->psl_hwirq; - ctx->irqs.range[0] = 1; - } - - ctx->irq_count = count; - ctx->irq_bitmap = bitmap_zalloc(count, GFP_KERNEL); - if (!ctx->irq_bitmap) - goto out; - - /* - * Allocate names first. If any fail, bail out before allocating - * actual hardware IRQs. - */ - for (r = afu_irq_range_start(); r < CXL_IRQ_RANGES; r++) { - for (i = 0; i < ctx->irqs.range[r]; i++) { - irq_name = kmalloc(sizeof(struct cxl_irq_name), - GFP_KERNEL); - if (!irq_name) - goto out; - irq_name->name = kasprintf(GFP_KERNEL, "cxl-%s-pe%i-%i", - dev_name(&ctx->afu->dev), - ctx->pe, j); - if (!irq_name->name) { - kfree(irq_name); - goto out; - } - /* Add to tail so next look get the correct order */ - list_add_tail(&irq_name->list, &ctx->irq_names); - j++; - } - } - return 0; - -out: - cxl_ops->release_irq_ranges(&ctx->irqs, ctx->afu->adapter); - bitmap_free(ctx->irq_bitmap); - afu_irq_name_free(ctx); - return -ENOMEM; -} - -static void afu_register_hwirqs(struct cxl_context *ctx) -{ - irq_hw_number_t hwirq; - struct cxl_irq_name *irq_name; - int r, i; - irqreturn_t (*handler)(int irq, void *data); - - /* We've allocated all memory now, so let's do the irq allocations */ - irq_name = list_first_entry(&ctx->irq_names, struct cxl_irq_name, list); - for (r = afu_irq_range_start(); r < CXL_IRQ_RANGES; r++) { - hwirq = ctx->irqs.offset[r]; - for (i = 0; i < ctx->irqs.range[r]; hwirq++, i++) { - if (r == 0 && i == 0) - /* - * The very first interrupt of range 0 is - * always the PSL interrupt, but we only - * need to connect a handler for guests, - * because there's one PSL interrupt per - * context. - * On bare-metal, the PSL interrupt is - * multiplexed and was setup when the AFU - * was configured. - */ - handler = cxl_ops->psl_interrupt; - else - handler = cxl_irq_afu; - cxl_map_irq(ctx->afu->adapter, hwirq, handler, ctx, - irq_name->name); - irq_name = list_next_entry(irq_name, list); - } - } -} - -int afu_register_irqs(struct cxl_context *ctx, u32 count) -{ - int rc; - - rc = afu_allocate_irqs(ctx, count); - if (rc) - return rc; - - afu_register_hwirqs(ctx); - return 0; -} - -void afu_release_irqs(struct cxl_context *ctx, void *cookie) -{ - irq_hw_number_t hwirq; - unsigned int virq; - int r, i; - - for (r = afu_irq_range_start(); r < CXL_IRQ_RANGES; r++) { - hwirq = ctx->irqs.offset[r]; - for (i = 0; i < ctx->irqs.range[r]; hwirq++, i++) { - virq = irq_find_mapping(NULL, hwirq); - if (virq) - cxl_unmap_irq(virq, cookie); - } - } - - afu_irq_name_free(ctx); - cxl_ops->release_irq_ranges(&ctx->irqs, ctx->afu->adapter); - - ctx->irq_count = 0; -} - -void cxl_afu_decode_psl_serr(struct cxl_afu *afu, u64 serr) -{ - dev_crit(&afu->dev, - "PSL Slice error received. Check AFU for root cause.\n"); - dev_crit(&afu->dev, "PSL_SERR_An: 0x%016llx\n", serr); - if (serr & CXL_PSL_SERR_An_afuto) - dev_crit(&afu->dev, "AFU MMIO Timeout\n"); - if (serr & CXL_PSL_SERR_An_afudis) - dev_crit(&afu->dev, - "MMIO targeted Accelerator that was not enabled\n"); - if (serr & CXL_PSL_SERR_An_afuov) - dev_crit(&afu->dev, "AFU CTAG Overflow\n"); - if (serr & CXL_PSL_SERR_An_badsrc) - dev_crit(&afu->dev, "Bad Interrupt Source\n"); - if (serr & CXL_PSL_SERR_An_badctx) - dev_crit(&afu->dev, "Bad Context Handle\n"); - if (serr & CXL_PSL_SERR_An_llcmdis) - dev_crit(&afu->dev, "LLCMD to Disabled AFU\n"); - if (serr & CXL_PSL_SERR_An_llcmdto) - dev_crit(&afu->dev, "LLCMD Timeout to AFU\n"); - if (serr & CXL_PSL_SERR_An_afupar) - dev_crit(&afu->dev, "AFU MMIO Parity Error\n"); - if (serr & CXL_PSL_SERR_An_afudup) - dev_crit(&afu->dev, "AFU MMIO Duplicate CTAG Error\n"); - if (serr & CXL_PSL_SERR_An_AE) - dev_crit(&afu->dev, - "AFU asserted JDONE with JERROR in AFU Directed Mode\n"); -}
diff --git a/drivers/misc/cxl/main.c b/drivers/misc/cxl/main.c deleted file mode 100644 index c1fbf6f..0000000 --- a/drivers/misc/cxl/main.c +++ /dev/null
@@ -1,383 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Copyright 2014 IBM Corp. - */ - -#include <linux/spinlock.h> -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/device.h> -#include <linux/mutex.h> -#include <linux/init.h> -#include <linux/list.h> -#include <linux/mm.h> -#include <linux/of.h> -#include <linux/slab.h> -#include <linux/idr.h> -#include <linux/pci.h> -#include <linux/platform_device.h> -#include <linux/sched/task.h> - -#include <asm/cputable.h> -#include <asm/mmu.h> -#include <misc/cxl-base.h> - -#include "cxl.h" -#include "trace.h" - -static DEFINE_SPINLOCK(adapter_idr_lock); -static DEFINE_IDR(cxl_adapter_idr); - -uint cxl_verbose; -module_param_named(verbose, cxl_verbose, uint, 0600); -MODULE_PARM_DESC(verbose, "Enable verbose dmesg output"); - -const struct cxl_backend_ops *cxl_ops; - -int cxl_afu_slbia(struct cxl_afu *afu) -{ - unsigned long timeout = jiffies + (HZ * CXL_TIMEOUT); - - pr_devel("cxl_afu_slbia issuing SLBIA command\n"); - cxl_p2n_write(afu, CXL_SLBIA_An, CXL_TLB_SLB_IQ_ALL); - while (cxl_p2n_read(afu, CXL_SLBIA_An) & CXL_TLB_SLB_P) { - if (time_after_eq(jiffies, timeout)) { - dev_warn(&afu->dev, "WARNING: CXL AFU SLBIA timed out!\n"); - return -EBUSY; - } - /* If the adapter has gone down, we can assume that we - * will PERST it and that will invalidate everything. - */ - if (!cxl_ops->link_ok(afu->adapter, afu)) - return -EIO; - cpu_relax(); - } - return 0; -} - -static inline void _cxl_slbia(struct cxl_context *ctx, struct mm_struct *mm) -{ - unsigned long flags; - - if (ctx->mm != mm) - return; - - pr_devel("%s matched mm - card: %i afu: %i pe: %i\n", __func__, - ctx->afu->adapter->adapter_num, ctx->afu->slice, ctx->pe); - - spin_lock_irqsave(&ctx->sste_lock, flags); - trace_cxl_slbia(ctx); - memset(ctx->sstp, 0, ctx->sst_size); - spin_unlock_irqrestore(&ctx->sste_lock, flags); - mb(); - cxl_afu_slbia(ctx->afu); -} - -static inline void cxl_slbia_core(struct mm_struct *mm) -{ - struct cxl *adapter; - struct cxl_afu *afu; - struct cxl_context *ctx; - int card, slice, id; - - pr_devel("%s called\n", __func__); - - spin_lock(&adapter_idr_lock); - idr_for_each_entry(&cxl_adapter_idr, adapter, card) { - /* XXX: Make this lookup faster with link from mm to ctx */ - spin_lock(&adapter->afu_list_lock); - for (slice = 0; slice < adapter->slices; slice++) { - afu = adapter->afu[slice]; - if (!afu || !afu->enabled) - continue; - rcu_read_lock(); - idr_for_each_entry(&afu->contexts_idr, ctx, id) - _cxl_slbia(ctx, mm); - rcu_read_unlock(); - } - spin_unlock(&adapter->afu_list_lock); - } - spin_unlock(&adapter_idr_lock); -} - -static struct cxl_calls cxl_calls = { - .cxl_slbia = cxl_slbia_core, - .owner = THIS_MODULE, -}; - -int cxl_alloc_sst(struct cxl_context *ctx) -{ - unsigned long vsid; - u64 ea_mask, size, sstp0, sstp1; - - sstp0 = 0; - sstp1 = 0; - - ctx->sst_size = PAGE_SIZE; - ctx->sst_lru = 0; - ctx->sstp = (struct cxl_sste *)get_zeroed_page(GFP_KERNEL); - if (!ctx->sstp) { - pr_err("cxl_alloc_sst: Unable to allocate segment table\n"); - return -ENOMEM; - } - pr_devel("SSTP allocated at 0x%p\n", ctx->sstp); - - vsid = get_kernel_vsid((u64)ctx->sstp, mmu_kernel_ssize) << 12; - - sstp0 |= (u64)mmu_kernel_ssize << CXL_SSTP0_An_B_SHIFT; - sstp0 |= (SLB_VSID_KERNEL | mmu_psize_defs[mmu_linear_psize].sllp) << 50; - - size = (((u64)ctx->sst_size >> 8) - 1) << CXL_SSTP0_An_SegTableSize_SHIFT; - if (unlikely(size & ~CXL_SSTP0_An_SegTableSize_MASK)) { - WARN(1, "Impossible segment table size\n"); - return -EINVAL; - } - sstp0 |= size; - - if (mmu_kernel_ssize == MMU_SEGSIZE_256M) - ea_mask = 0xfffff00ULL; - else - ea_mask = 0xffffffff00ULL; - - sstp0 |= vsid >> (50-14); /* Top 14 bits of VSID */ - sstp1 |= (vsid << (64-(50-14))) & ~ea_mask; - sstp1 |= (u64)ctx->sstp & ea_mask; - sstp1 |= CXL_SSTP1_An_V; - - pr_devel("Looked up %#llx: slbfee. %#llx (ssize: %x, vsid: %#lx), copied to SSTP0: %#llx, SSTP1: %#llx\n", - (u64)ctx->sstp, (u64)ctx->sstp & ESID_MASK, mmu_kernel_ssize, vsid, sstp0, sstp1); - - /* Store calculated sstp hardware points for use later */ - ctx->sstp0 = sstp0; - ctx->sstp1 = sstp1; - - return 0; -} - -/* print buffer content as integers when debugging */ -void cxl_dump_debug_buffer(void *buf, size_t buf_len) -{ -#ifdef DEBUG - int i, *ptr; - - /* - * We want to regroup up to 4 integers per line, which means they - * need to be in the same pr_devel() statement - */ - ptr = (int *) buf; - for (i = 0; i * 4 < buf_len; i += 4) { - if ((i + 3) * 4 < buf_len) - pr_devel("%.8x %.8x %.8x %.8x\n", ptr[i], ptr[i + 1], - ptr[i + 2], ptr[i + 3]); - else if ((i + 2) * 4 < buf_len) - pr_devel("%.8x %.8x %.8x\n", ptr[i], ptr[i + 1], - ptr[i + 2]); - else if ((i + 1) * 4 < buf_len) - pr_devel("%.8x %.8x\n", ptr[i], ptr[i + 1]); - else - pr_devel("%.8x\n", ptr[i]); - } -#endif /* DEBUG */ -} - -/* Find a CXL adapter by it's number and increase it's refcount */ -struct cxl *get_cxl_adapter(int num) -{ - struct cxl *adapter; - - spin_lock(&adapter_idr_lock); - if ((adapter = idr_find(&cxl_adapter_idr, num))) - get_device(&adapter->dev); - spin_unlock(&adapter_idr_lock); - - return adapter; -} - -static int cxl_alloc_adapter_nr(struct cxl *adapter) -{ - int i; - - idr_preload(GFP_KERNEL); - spin_lock(&adapter_idr_lock); - i = idr_alloc(&cxl_adapter_idr, adapter, 0, 0, GFP_NOWAIT); - spin_unlock(&adapter_idr_lock); - idr_preload_end(); - if (i < 0) - return i; - - adapter->adapter_num = i; - - return 0; -} - -void cxl_remove_adapter_nr(struct cxl *adapter) -{ - idr_remove(&cxl_adapter_idr, adapter->adapter_num); -} - -struct cxl *cxl_alloc_adapter(void) -{ - struct cxl *adapter; - - if (!(adapter = kzalloc(sizeof(struct cxl), GFP_KERNEL))) - return NULL; - - spin_lock_init(&adapter->afu_list_lock); - - if (cxl_alloc_adapter_nr(adapter)) - goto err1; - - if (dev_set_name(&adapter->dev, "card%i", adapter->adapter_num)) - goto err2; - - /* start with context lock taken */ - atomic_set(&adapter->contexts_num, -1); - - return adapter; -err2: - cxl_remove_adapter_nr(adapter); -err1: - kfree(adapter); - return NULL; -} - -struct cxl_afu *cxl_alloc_afu(struct cxl *adapter, int slice) -{ - struct cxl_afu *afu; - - if (!(afu = kzalloc(sizeof(struct cxl_afu), GFP_KERNEL))) - return NULL; - - afu->adapter = adapter; - afu->dev.parent = &adapter->dev; - afu->dev.release = cxl_ops->release_afu; - afu->slice = slice; - idr_init(&afu->contexts_idr); - mutex_init(&afu->contexts_lock); - spin_lock_init(&afu->afu_cntl_lock); - atomic_set(&afu->configured_state, -1); - afu->prefault_mode = CXL_PREFAULT_NONE; - afu->irqs_max = afu->adapter->user_irqs; - - return afu; -} - -int cxl_afu_select_best_mode(struct cxl_afu *afu) -{ - if (afu->modes_supported & CXL_MODE_DIRECTED) - return cxl_ops->afu_activate_mode(afu, CXL_MODE_DIRECTED); - - if (afu->modes_supported & CXL_MODE_DEDICATED) - return cxl_ops->afu_activate_mode(afu, CXL_MODE_DEDICATED); - - dev_warn(&afu->dev, "No supported programming modes available\n"); - /* We don't fail this so the user can inspect sysfs */ - return 0; -} - -int cxl_adapter_context_get(struct cxl *adapter) -{ - int rc; - - rc = atomic_inc_unless_negative(&adapter->contexts_num); - return rc ? 0 : -EBUSY; -} - -void cxl_adapter_context_put(struct cxl *adapter) -{ - atomic_dec_if_positive(&adapter->contexts_num); -} - -int cxl_adapter_context_lock(struct cxl *adapter) -{ - int rc; - /* no active contexts -> contexts_num == 0 */ - rc = atomic_cmpxchg(&adapter->contexts_num, 0, -1); - return rc ? -EBUSY : 0; -} - -void cxl_adapter_context_unlock(struct cxl *adapter) -{ - int val = atomic_cmpxchg(&adapter->contexts_num, -1, 0); - - /* - * contexts lock taken -> contexts_num == -1 - * If not true then show a warning and force reset the lock. - * This will happen when context_unlock was requested without - * doing a context_lock. - */ - if (val != -1) { - atomic_set(&adapter->contexts_num, 0); - WARN(1, "Adapter context unlocked with %d active contexts", - val); - } -} - -static int __init init_cxl(void) -{ - int rc = 0; - - if (!tlbie_capable) - return -EINVAL; - - if ((rc = cxl_file_init())) - return rc; - - cxl_debugfs_init(); - - /* - * we don't register the callback on P9. slb callack is only - * used for the PSL8 MMU and CX4. - */ - if (cxl_is_power8()) { - rc = register_cxl_calls(&cxl_calls); - if (rc) - goto err; - } - - if (cpu_has_feature(CPU_FTR_HVMODE)) { - cxl_ops = &cxl_native_ops; - rc = pci_register_driver(&cxl_pci_driver); - } -#ifdef CONFIG_PPC_PSERIES - else { - cxl_ops = &cxl_guest_ops; - rc = platform_driver_register(&cxl_of_driver); - } -#endif - if (rc) - goto err1; - - return 0; -err1: - if (cxl_is_power8()) - unregister_cxl_calls(&cxl_calls); -err: - cxl_debugfs_exit(); - cxl_file_exit(); - - return rc; -} - -static void exit_cxl(void) -{ - if (cpu_has_feature(CPU_FTR_HVMODE)) - pci_unregister_driver(&cxl_pci_driver); -#ifdef CONFIG_PPC_PSERIES - else - platform_driver_unregister(&cxl_of_driver); -#endif - - cxl_debugfs_exit(); - cxl_file_exit(); - if (cxl_is_power8()) - unregister_cxl_calls(&cxl_calls); - idr_destroy(&cxl_adapter_idr); -} - -module_init(init_cxl); -module_exit(exit_cxl); - -MODULE_DESCRIPTION("IBM Coherent Accelerator"); -MODULE_AUTHOR("Ian Munsie <imunsie@au1.ibm.com>"); -MODULE_LICENSE("GPL");
diff --git a/drivers/misc/cxl/native.c b/drivers/misc/cxl/native.c deleted file mode 100644 index fbe16a6..0000000 --- a/drivers/misc/cxl/native.c +++ /dev/null
@@ -1,1592 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Copyright 2014 IBM Corp. - */ - -#include <linux/spinlock.h> -#include <linux/sched.h> -#include <linux/sched/clock.h> -#include <linux/slab.h> -#include <linux/mutex.h> -#include <linux/mm.h> -#include <linux/uaccess.h> -#include <linux/delay.h> -#include <linux/irqdomain.h> -#include <asm/synch.h> -#include <asm/switch_to.h> -#include <misc/cxl-base.h> - -#include "cxl.h" -#include "trace.h" - -static int afu_control(struct cxl_afu *afu, u64 command, u64 clear, - u64 result, u64 mask, bool enabled) -{ - u64 AFU_Cntl; - unsigned long timeout = jiffies + (HZ * CXL_TIMEOUT); - int rc = 0; - - spin_lock(&afu->afu_cntl_lock); - pr_devel("AFU command starting: %llx\n", command); - - trace_cxl_afu_ctrl(afu, command); - - AFU_Cntl = cxl_p2n_read(afu, CXL_AFU_Cntl_An); - cxl_p2n_write(afu, CXL_AFU_Cntl_An, (AFU_Cntl & ~clear) | command); - - AFU_Cntl = cxl_p2n_read(afu, CXL_AFU_Cntl_An); - while ((AFU_Cntl & mask) != result) { - if (time_after_eq(jiffies, timeout)) { - dev_warn(&afu->dev, "WARNING: AFU control timed out!\n"); - rc = -EBUSY; - goto out; - } - - if (!cxl_ops->link_ok(afu->adapter, afu)) { - afu->enabled = enabled; - rc = -EIO; - goto out; - } - - pr_devel_ratelimited("AFU control... (0x%016llx)\n", - AFU_Cntl | command); - cpu_relax(); - AFU_Cntl = cxl_p2n_read(afu, CXL_AFU_Cntl_An); - } - - if (AFU_Cntl & CXL_AFU_Cntl_An_RA) { - /* - * Workaround for a bug in the XSL used in the Mellanox CX4 - * that fails to clear the RA bit after an AFU reset, - * preventing subsequent AFU resets from working. - */ - cxl_p2n_write(afu, CXL_AFU_Cntl_An, AFU_Cntl & ~CXL_AFU_Cntl_An_RA); - } - - pr_devel("AFU command complete: %llx\n", command); - afu->enabled = enabled; -out: - trace_cxl_afu_ctrl_done(afu, command, rc); - spin_unlock(&afu->afu_cntl_lock); - - return rc; -} - -static int afu_enable(struct cxl_afu *afu) -{ - pr_devel("AFU enable request\n"); - - return afu_control(afu, CXL_AFU_Cntl_An_E, 0, - CXL_AFU_Cntl_An_ES_Enabled, - CXL_AFU_Cntl_An_ES_MASK, true); -} - -int cxl_afu_disable(struct cxl_afu *afu) -{ - pr_devel("AFU disable request\n"); - - return afu_control(afu, 0, CXL_AFU_Cntl_An_E, - CXL_AFU_Cntl_An_ES_Disabled, - CXL_AFU_Cntl_An_ES_MASK, false); -} - -/* This will disable as well as reset */ -static int native_afu_reset(struct cxl_afu *afu) -{ - int rc; - u64 serr; - - pr_devel("AFU reset request\n"); - - rc = afu_control(afu, CXL_AFU_Cntl_An_RA, 0, - CXL_AFU_Cntl_An_RS_Complete | CXL_AFU_Cntl_An_ES_Disabled, - CXL_AFU_Cntl_An_RS_MASK | CXL_AFU_Cntl_An_ES_MASK, - false); - - /* - * Re-enable any masked interrupts when the AFU is not - * activated to avoid side effects after attaching a process - * in dedicated mode. - */ - if (afu->current_mode == 0) { - serr = cxl_p1n_read(afu, CXL_PSL_SERR_An); - serr &= ~CXL_PSL_SERR_An_IRQ_MASKS; - cxl_p1n_write(afu, CXL_PSL_SERR_An, serr); - } - - return rc; -} - -static int native_afu_check_and_enable(struct cxl_afu *afu) -{ - if (!cxl_ops->link_ok(afu->adapter, afu)) { - WARN(1, "Refusing to enable afu while link down!\n"); - return -EIO; - } - if (afu->enabled) - return 0; - return afu_enable(afu); -} - -int cxl_psl_purge(struct cxl_afu *afu) -{ - u64 PSL_CNTL = cxl_p1n_read(afu, CXL_PSL_SCNTL_An); - u64 AFU_Cntl = cxl_p2n_read(afu, CXL_AFU_Cntl_An); - u64 dsisr, dar; - u64 start, end; - u64 trans_fault = 0x0ULL; - unsigned long timeout = jiffies + (HZ * CXL_TIMEOUT); - int rc = 0; - - trace_cxl_psl_ctrl(afu, CXL_PSL_SCNTL_An_Pc); - - pr_devel("PSL purge request\n"); - - if (cxl_is_power8()) - trans_fault = CXL_PSL_DSISR_TRANS; - if (cxl_is_power9()) - trans_fault = CXL_PSL9_DSISR_An_TF; - - if (!cxl_ops->link_ok(afu->adapter, afu)) { - dev_warn(&afu->dev, "PSL Purge called with link down, ignoring\n"); - rc = -EIO; - goto out; - } - - if ((AFU_Cntl & CXL_AFU_Cntl_An_ES_MASK) != CXL_AFU_Cntl_An_ES_Disabled) { - WARN(1, "psl_purge request while AFU not disabled!\n"); - cxl_afu_disable(afu); - } - - cxl_p1n_write(afu, CXL_PSL_SCNTL_An, - PSL_CNTL | CXL_PSL_SCNTL_An_Pc); - start = local_clock(); - PSL_CNTL = cxl_p1n_read(afu, CXL_PSL_SCNTL_An); - while ((PSL_CNTL & CXL_PSL_SCNTL_An_Ps_MASK) - == CXL_PSL_SCNTL_An_Ps_Pending) { - if (time_after_eq(jiffies, timeout)) { - dev_warn(&afu->dev, "WARNING: PSL Purge timed out!\n"); - rc = -EBUSY; - goto out; - } - if (!cxl_ops->link_ok(afu->adapter, afu)) { - rc = -EIO; - goto out; - } - - dsisr = cxl_p2n_read(afu, CXL_PSL_DSISR_An); - pr_devel_ratelimited("PSL purging... PSL_CNTL: 0x%016llx PSL_DSISR: 0x%016llx\n", - PSL_CNTL, dsisr); - - if (dsisr & trans_fault) { - dar = cxl_p2n_read(afu, CXL_PSL_DAR_An); - dev_notice(&afu->dev, "PSL purge terminating pending translation, DSISR: 0x%016llx, DAR: 0x%016llx\n", - dsisr, dar); - cxl_p2n_write(afu, CXL_PSL_TFC_An, CXL_PSL_TFC_An_AE); - } else if (dsisr) { - dev_notice(&afu->dev, "PSL purge acknowledging pending non-translation fault, DSISR: 0x%016llx\n", - dsisr); - cxl_p2n_write(afu, CXL_PSL_TFC_An, CXL_PSL_TFC_An_A); - } else { - cpu_relax(); - } - PSL_CNTL = cxl_p1n_read(afu, CXL_PSL_SCNTL_An); - } - end = local_clock(); - pr_devel("PSL purged in %lld ns\n", end - start); - - cxl_p1n_write(afu, CXL_PSL_SCNTL_An, - PSL_CNTL & ~CXL_PSL_SCNTL_An_Pc); -out: - trace_cxl_psl_ctrl_done(afu, CXL_PSL_SCNTL_An_Pc, rc); - return rc; -} - -static int spa_max_procs(int spa_size) -{ - /* - * From the CAIA: - * end_of_SPA_area = SPA_Base + ((n+4) * 128) + (( ((n*8) + 127) >> 7) * 128) + 255 - * Most of that junk is really just an overly-complicated way of saying - * the last 256 bytes are __aligned(128), so it's really: - * end_of_SPA_area = end_of_PSL_queue_area + __aligned(128) 255 - * and - * end_of_PSL_queue_area = SPA_Base + ((n+4) * 128) + (n*8) - 1 - * so - * sizeof(SPA) = ((n+4) * 128) + (n*8) + __aligned(128) 256 - * Ignore the alignment (which is safe in this case as long as we are - * careful with our rounding) and solve for n: - */ - return ((spa_size / 8) - 96) / 17; -} - -static int cxl_alloc_spa(struct cxl_afu *afu, int mode) -{ - unsigned spa_size; - - /* Work out how many pages to allocate */ - afu->native->spa_order = -1; - do { - afu->native->spa_order++; - spa_size = (1 << afu->native->spa_order) * PAGE_SIZE; - - if (spa_size > 0x100000) { - dev_warn(&afu->dev, "num_of_processes too large for the SPA, limiting to %i (0x%x)\n", - afu->native->spa_max_procs, afu->native->spa_size); - if (mode != CXL_MODE_DEDICATED) - afu->num_procs = afu->native->spa_max_procs; - break; - } - - afu->native->spa_size = spa_size; - afu->native->spa_max_procs = spa_max_procs(afu->native->spa_size); - } while (afu->native->spa_max_procs < afu->num_procs); - - if (!(afu->native->spa = (struct cxl_process_element *) - __get_free_pages(GFP_KERNEL | __GFP_ZERO, afu->native->spa_order))) { - pr_err("cxl_alloc_spa: Unable to allocate scheduled process area\n"); - return -ENOMEM; - } - pr_devel("spa pages: %i afu->spa_max_procs: %i afu->num_procs: %i\n", - 1<<afu->native->spa_order, afu->native->spa_max_procs, afu->num_procs); - - return 0; -} - -static void attach_spa(struct cxl_afu *afu) -{ - u64 spap; - - afu->native->sw_command_status = (__be64 *)((char *)afu->native->spa + - ((afu->native->spa_max_procs + 3) * 128)); - - spap = virt_to_phys(afu->native->spa) & CXL_PSL_SPAP_Addr; - spap |= ((afu->native->spa_size >> (12 - CXL_PSL_SPAP_Size_Shift)) - 1) & CXL_PSL_SPAP_Size; - spap |= CXL_PSL_SPAP_V; - pr_devel("cxl: SPA allocated at 0x%p. Max processes: %i, sw_command_status: 0x%p CXL_PSL_SPAP_An=0x%016llx\n", - afu->native->spa, afu->native->spa_max_procs, - afu->native->sw_command_status, spap); - cxl_p1n_write(afu, CXL_PSL_SPAP_An, spap); -} - -void cxl_release_spa(struct cxl_afu *afu) -{ - if (afu->native->spa) { - free_pages((unsigned long) afu->native->spa, - afu->native->spa_order); - afu->native->spa = NULL; - } -} - -/* - * Invalidation of all ERAT entries is no longer required by CAIA2. Use - * only for debug. - */ -int cxl_invalidate_all_psl9(struct cxl *adapter) -{ - unsigned long timeout = jiffies + (HZ * CXL_TIMEOUT); - u64 ierat; - - pr_devel("CXL adapter - invalidation of all ERAT entries\n"); - - /* Invalidates all ERAT entries for Radix or HPT */ - ierat = CXL_XSL9_IERAT_IALL; - if (radix_enabled()) - ierat |= CXL_XSL9_IERAT_INVR; - cxl_p1_write(adapter, CXL_XSL9_IERAT, ierat); - - while (cxl_p1_read(adapter, CXL_XSL9_IERAT) & CXL_XSL9_IERAT_IINPROG) { - if (time_after_eq(jiffies, timeout)) { - dev_warn(&adapter->dev, - "WARNING: CXL adapter invalidation of all ERAT entries timed out!\n"); - return -EBUSY; - } - if (!cxl_ops->link_ok(adapter, NULL)) - return -EIO; - cpu_relax(); - } - return 0; -} - -int cxl_invalidate_all_psl8(struct cxl *adapter) -{ - unsigned long timeout = jiffies + (HZ * CXL_TIMEOUT); - - pr_devel("CXL adapter wide TLBIA & SLBIA\n"); - - cxl_p1_write(adapter, CXL_PSL_AFUSEL, CXL_PSL_AFUSEL_A); - - cxl_p1_write(adapter, CXL_PSL_TLBIA, CXL_TLB_SLB_IQ_ALL); - while (cxl_p1_read(adapter, CXL_PSL_TLBIA) & CXL_TLB_SLB_P) { - if (time_after_eq(jiffies, timeout)) { - dev_warn(&adapter->dev, "WARNING: CXL adapter wide TLBIA timed out!\n"); - return -EBUSY; - } - if (!cxl_ops->link_ok(adapter, NULL)) - return -EIO; - cpu_relax(); - } - - cxl_p1_write(adapter, CXL_PSL_SLBIA, CXL_TLB_SLB_IQ_ALL); - while (cxl_p1_read(adapter, CXL_PSL_SLBIA) & CXL_TLB_SLB_P) { - if (time_after_eq(jiffies, timeout)) { - dev_warn(&adapter->dev, "WARNING: CXL adapter wide SLBIA timed out!\n"); - return -EBUSY; - } - if (!cxl_ops->link_ok(adapter, NULL)) - return -EIO; - cpu_relax(); - } - return 0; -} - -int cxl_data_cache_flush(struct cxl *adapter) -{ - u64 reg; - unsigned long timeout = jiffies + (HZ * CXL_TIMEOUT); - - /* - * Do a datacache flush only if datacache is available. - * In case of PSL9D datacache absent hence flush operation. - * would timeout. - */ - if (adapter->native->no_data_cache) { - pr_devel("No PSL data cache. Ignoring cache flush req.\n"); - return 0; - } - - pr_devel("Flushing data cache\n"); - reg = cxl_p1_read(adapter, CXL_PSL_Control); - reg |= CXL_PSL_Control_Fr; - cxl_p1_write(adapter, CXL_PSL_Control, reg); - - reg = cxl_p1_read(adapter, CXL_PSL_Control); - while ((reg & CXL_PSL_Control_Fs_MASK) != CXL_PSL_Control_Fs_Complete) { - if (time_after_eq(jiffies, timeout)) { - dev_warn(&adapter->dev, "WARNING: cache flush timed out!\n"); - return -EBUSY; - } - - if (!cxl_ops->link_ok(adapter, NULL)) { - dev_warn(&adapter->dev, "WARNING: link down when flushing cache\n"); - return -EIO; - } - cpu_relax(); - reg = cxl_p1_read(adapter, CXL_PSL_Control); - } - - reg &= ~CXL_PSL_Control_Fr; - cxl_p1_write(adapter, CXL_PSL_Control, reg); - return 0; -} - -static int cxl_write_sstp(struct cxl_afu *afu, u64 sstp0, u64 sstp1) -{ - int rc; - - /* 1. Disable SSTP by writing 0 to SSTP1[V] */ - cxl_p2n_write(afu, CXL_SSTP1_An, 0); - - /* 2. Invalidate all SLB entries */ - if ((rc = cxl_afu_slbia(afu))) - return rc; - - /* 3. Set SSTP0_An */ - cxl_p2n_write(afu, CXL_SSTP0_An, sstp0); - - /* 4. Set SSTP1_An */ - cxl_p2n_write(afu, CXL_SSTP1_An, sstp1); - - return 0; -} - -/* Using per slice version may improve performance here. (ie. SLBIA_An) */ -static void slb_invalid(struct cxl_context *ctx) -{ - struct cxl *adapter = ctx->afu->adapter; - u64 slbia; - - WARN_ON(!mutex_is_locked(&ctx->afu->native->spa_mutex)); - - cxl_p1_write(adapter, CXL_PSL_LBISEL, - ((u64)be32_to_cpu(ctx->elem->common.pid) << 32) | - be32_to_cpu(ctx->elem->lpid)); - cxl_p1_write(adapter, CXL_PSL_SLBIA, CXL_TLB_SLB_IQ_LPIDPID); - - while (1) { - if (!cxl_ops->link_ok(adapter, NULL)) - break; - slbia = cxl_p1_read(adapter, CXL_PSL_SLBIA); - if (!(slbia & CXL_TLB_SLB_P)) - break; - cpu_relax(); - } -} - -static int do_process_element_cmd(struct cxl_context *ctx, - u64 cmd, u64 pe_state) -{ - u64 state; - unsigned long timeout = jiffies + (HZ * CXL_TIMEOUT); - int rc = 0; - - trace_cxl_llcmd(ctx, cmd); - - WARN_ON(!ctx->afu->enabled); - - ctx->elem->software_state = cpu_to_be32(pe_state); - smp_wmb(); - *(ctx->afu->native->sw_command_status) = cpu_to_be64(cmd | 0 | ctx->pe); - smp_mb(); - cxl_p1n_write(ctx->afu, CXL_PSL_LLCMD_An, cmd | ctx->pe); - while (1) { - if (time_after_eq(jiffies, timeout)) { - dev_warn(&ctx->afu->dev, "WARNING: Process Element Command timed out!\n"); - rc = -EBUSY; - goto out; - } - if (!cxl_ops->link_ok(ctx->afu->adapter, ctx->afu)) { - dev_warn(&ctx->afu->dev, "WARNING: Device link down, aborting Process Element Command!\n"); - rc = -EIO; - goto out; - } - state = be64_to_cpup(ctx->afu->native->sw_command_status); - if (state == ~0ULL) { - pr_err("cxl: Error adding process element to AFU\n"); - rc = -1; - goto out; - } - if ((state & (CXL_SPA_SW_CMD_MASK | CXL_SPA_SW_STATE_MASK | CXL_SPA_SW_LINK_MASK)) == - (cmd | (cmd >> 16) | ctx->pe)) - break; - /* - * The command won't finish in the PSL if there are - * outstanding DSIs. Hence we need to yield here in - * case there are outstanding DSIs that we need to - * service. Tuning possiblity: we could wait for a - * while before sched - */ - schedule(); - - } -out: - trace_cxl_llcmd_done(ctx, cmd, rc); - return rc; -} - -static int add_process_element(struct cxl_context *ctx) -{ - int rc = 0; - - mutex_lock(&ctx->afu->native->spa_mutex); - pr_devel("%s Adding pe: %i started\n", __func__, ctx->pe); - if (!(rc = do_process_element_cmd(ctx, CXL_SPA_SW_CMD_ADD, CXL_PE_SOFTWARE_STATE_V))) - ctx->pe_inserted = true; - pr_devel("%s Adding pe: %i finished\n", __func__, ctx->pe); - mutex_unlock(&ctx->afu->native->spa_mutex); - return rc; -} - -static int terminate_process_element(struct cxl_context *ctx) -{ - int rc = 0; - - /* fast path terminate if it's already invalid */ - if (!(ctx->elem->software_state & cpu_to_be32(CXL_PE_SOFTWARE_STATE_V))) - return rc; - - mutex_lock(&ctx->afu->native->spa_mutex); - pr_devel("%s Terminate pe: %i started\n", __func__, ctx->pe); - /* We could be asked to terminate when the hw is down. That - * should always succeed: it's not running if the hw has gone - * away and is being reset. - */ - if (cxl_ops->link_ok(ctx->afu->adapter, ctx->afu)) - rc = do_process_element_cmd(ctx, CXL_SPA_SW_CMD_TERMINATE, - CXL_PE_SOFTWARE_STATE_V | CXL_PE_SOFTWARE_STATE_T); - ctx->elem->software_state = 0; /* Remove Valid bit */ - pr_devel("%s Terminate pe: %i finished\n", __func__, ctx->pe); - mutex_unlock(&ctx->afu->native->spa_mutex); - return rc; -} - -static int remove_process_element(struct cxl_context *ctx) -{ - int rc = 0; - - mutex_lock(&ctx->afu->native->spa_mutex); - pr_devel("%s Remove pe: %i started\n", __func__, ctx->pe); - - /* We could be asked to remove when the hw is down. Again, if - * the hw is down, the PE is gone, so we succeed. - */ - if (cxl_ops->link_ok(ctx->afu->adapter, ctx->afu)) - rc = do_process_element_cmd(ctx, CXL_SPA_SW_CMD_REMOVE, 0); - - if (!rc) - ctx->pe_inserted = false; - if (cxl_is_power8()) - slb_invalid(ctx); - pr_devel("%s Remove pe: %i finished\n", __func__, ctx->pe); - mutex_unlock(&ctx->afu->native->spa_mutex); - - return rc; -} - -void cxl_assign_psn_space(struct cxl_context *ctx) -{ - if (!ctx->afu->pp_size || ctx->master) { - ctx->psn_phys = ctx->afu->psn_phys; - ctx->psn_size = ctx->afu->adapter->ps_size; - } else { - ctx->psn_phys = ctx->afu->psn_phys + - (ctx->afu->native->pp_offset + ctx->afu->pp_size * ctx->pe); - ctx->psn_size = ctx->afu->pp_size; - } -} - -static int activate_afu_directed(struct cxl_afu *afu) -{ - int rc; - - dev_info(&afu->dev, "Activating AFU directed mode\n"); - - afu->num_procs = afu->max_procs_virtualised; - if (afu->native->spa == NULL) { - if (cxl_alloc_spa(afu, CXL_MODE_DIRECTED)) - return -ENOMEM; - } - attach_spa(afu); - - cxl_p1n_write(afu, CXL_PSL_SCNTL_An, CXL_PSL_SCNTL_An_PM_AFU); - if (cxl_is_power8()) - cxl_p1n_write(afu, CXL_PSL_AMOR_An, 0xFFFFFFFFFFFFFFFFULL); - cxl_p1n_write(afu, CXL_PSL_ID_An, CXL_PSL_ID_An_F | CXL_PSL_ID_An_L); - - afu->current_mode = CXL_MODE_DIRECTED; - - if ((rc = cxl_chardev_m_afu_add(afu))) - return rc; - - if ((rc = cxl_sysfs_afu_m_add(afu))) - goto err; - - if ((rc = cxl_chardev_s_afu_add(afu))) - goto err1; - - return 0; -err1: - cxl_sysfs_afu_m_remove(afu); -err: - cxl_chardev_afu_remove(afu); - return rc; -} - -#ifdef CONFIG_CPU_LITTLE_ENDIAN -#define set_endian(sr) ((sr) |= CXL_PSL_SR_An_LE) -#else -#define set_endian(sr) ((sr) &= ~(CXL_PSL_SR_An_LE)) -#endif - -u64 cxl_calculate_sr(bool master, bool kernel, bool real_mode, bool p9) -{ - u64 sr = 0; - - set_endian(sr); - if (master) - sr |= CXL_PSL_SR_An_MP; - if (mfspr(SPRN_LPCR) & LPCR_TC) - sr |= CXL_PSL_SR_An_TC; - - if (kernel) { - if (!real_mode) - sr |= CXL_PSL_SR_An_R; - sr |= (mfmsr() & MSR_SF) | CXL_PSL_SR_An_HV; - } else { - sr |= CXL_PSL_SR_An_PR | CXL_PSL_SR_An_R; - if (radix_enabled()) - sr |= CXL_PSL_SR_An_HV; - else - sr &= ~(CXL_PSL_SR_An_HV); - if (!test_tsk_thread_flag(current, TIF_32BIT)) - sr |= CXL_PSL_SR_An_SF; - } - if (p9) { - if (radix_enabled()) - sr |= CXL_PSL_SR_An_XLAT_ror; - else - sr |= CXL_PSL_SR_An_XLAT_hpt; - } - return sr; -} - -static u64 calculate_sr(struct cxl_context *ctx) -{ - return cxl_calculate_sr(ctx->master, ctx->kernel, false, - cxl_is_power9()); -} - -static void update_ivtes_directed(struct cxl_context *ctx) -{ - bool need_update = (ctx->status == STARTED); - int r; - - if (need_update) { - WARN_ON(terminate_process_element(ctx)); - WARN_ON(remove_process_element(ctx)); - } - - for (r = 0; r < CXL_IRQ_RANGES; r++) { - ctx->elem->ivte_offsets[r] = cpu_to_be16(ctx->irqs.offset[r]); - ctx->elem->ivte_ranges[r] = cpu_to_be16(ctx->irqs.range[r]); - } - - /* - * Theoretically we could use the update llcmd, instead of a - * terminate/remove/add (or if an atomic update was required we could - * do a suspend/update/resume), however it seems there might be issues - * with the update llcmd on some cards (including those using an XSL on - * an ASIC) so for now it's safest to go with the commands that are - * known to work. In the future if we come across a situation where the - * card may be performing transactions using the same PE while we are - * doing this update we might need to revisit this. - */ - if (need_update) - WARN_ON(add_process_element(ctx)); -} - -static int process_element_entry_psl9(struct cxl_context *ctx, u64 wed, u64 amr) -{ - u32 pid; - int rc; - - cxl_assign_psn_space(ctx); - - ctx->elem->ctxtime = 0; /* disable */ - ctx->elem->lpid = cpu_to_be32(mfspr(SPRN_LPID)); - ctx->elem->haurp = 0; /* disable */ - - if (ctx->kernel) - pid = 0; - else { - if (ctx->mm == NULL) { - pr_devel("%s: unable to get mm for pe=%d pid=%i\n", - __func__, ctx->pe, pid_nr(ctx->pid)); - return -EINVAL; - } - pid = ctx->mm->context.id; - } - - /* Assign a unique TIDR (thread id) for the current thread */ - if (!(ctx->tidr) && (ctx->assign_tidr)) { - rc = set_thread_tidr(current); - if (rc) - return -ENODEV; - ctx->tidr = current->thread.tidr; - pr_devel("%s: current tidr: %d\n", __func__, ctx->tidr); - } - - ctx->elem->common.tid = cpu_to_be32(ctx->tidr); - ctx->elem->common.pid = cpu_to_be32(pid); - - ctx->elem->sr = cpu_to_be64(calculate_sr(ctx)); - - ctx->elem->common.csrp = 0; /* disable */ - - cxl_prefault(ctx, wed); - - /* - * Ensure we have the multiplexed PSL interrupt set up to take faults - * for kernel contexts that may not have allocated any AFU IRQs at all: - */ - if (ctx->irqs.range[0] == 0) { - ctx->irqs.offset[0] = ctx->afu->native->psl_hwirq; - ctx->irqs.range[0] = 1; - } - - ctx->elem->common.amr = cpu_to_be64(amr); - ctx->elem->common.wed = cpu_to_be64(wed); - - return 0; -} - -int cxl_attach_afu_directed_psl9(struct cxl_context *ctx, u64 wed, u64 amr) -{ - int result; - - /* fill the process element entry */ - result = process_element_entry_psl9(ctx, wed, amr); - if (result) - return result; - - update_ivtes_directed(ctx); - - /* first guy needs to enable */ - result = cxl_ops->afu_check_and_enable(ctx->afu); - if (result) - return result; - - return add_process_element(ctx); -} - -int cxl_attach_afu_directed_psl8(struct cxl_context *ctx, u64 wed, u64 amr) -{ - u32 pid; - int result; - - cxl_assign_psn_space(ctx); - - ctx->elem->ctxtime = 0; /* disable */ - ctx->elem->lpid = cpu_to_be32(mfspr(SPRN_LPID)); - ctx->elem->haurp = 0; /* disable */ - ctx->elem->u.sdr = cpu_to_be64(mfspr(SPRN_SDR1)); - - pid = current->pid; - if (ctx->kernel) - pid = 0; - ctx->elem->common.tid = 0; - ctx->elem->common.pid = cpu_to_be32(pid); - - ctx->elem->sr = cpu_to_be64(calculate_sr(ctx)); - - ctx->elem->common.csrp = 0; /* disable */ - ctx->elem->common.u.psl8.aurp0 = 0; /* disable */ - ctx->elem->common.u.psl8.aurp1 = 0; /* disable */ - - cxl_prefault(ctx, wed); - - ctx->elem->common.u.psl8.sstp0 = cpu_to_be64(ctx->sstp0); - ctx->elem->common.u.psl8.sstp1 = cpu_to_be64(ctx->sstp1); - - /* - * Ensure we have the multiplexed PSL interrupt set up to take faults - * for kernel contexts that may not have allocated any AFU IRQs at all: - */ - if (ctx->irqs.range[0] == 0) { - ctx->irqs.offset[0] = ctx->afu->native->psl_hwirq; - ctx->irqs.range[0] = 1; - } - - update_ivtes_directed(ctx); - - ctx->elem->common.amr = cpu_to_be64(amr); - ctx->elem->common.wed = cpu_to_be64(wed); - - /* first guy needs to enable */ - if ((result = cxl_ops->afu_check_and_enable(ctx->afu))) - return result; - - return add_process_element(ctx); -} - -static int deactivate_afu_directed(struct cxl_afu *afu) -{ - dev_info(&afu->dev, "Deactivating AFU directed mode\n"); - - afu->current_mode = 0; - afu->num_procs = 0; - - cxl_sysfs_afu_m_remove(afu); - cxl_chardev_afu_remove(afu); - - /* - * The CAIA section 2.2.1 indicates that the procedure for starting and - * stopping an AFU in AFU directed mode is AFU specific, which is not - * ideal since this code is generic and with one exception has no - * knowledge of the AFU. This is in contrast to the procedure for - * disabling a dedicated process AFU, which is documented to just - * require a reset. The architecture does indicate that both an AFU - * reset and an AFU disable should result in the AFU being disabled and - * we do both followed by a PSL purge for safety. - * - * Notably we used to have some issues with the disable sequence on PSL - * cards, which is why we ended up using this heavy weight procedure in - * the first place, however a bug was discovered that had rendered the - * disable operation ineffective, so it is conceivable that was the - * sole explanation for those difficulties. Careful regression testing - * is recommended if anyone attempts to remove or reorder these - * operations. - * - * The XSL on the Mellanox CX4 behaves a little differently from the - * PSL based cards and will time out an AFU reset if the AFU is still - * enabled. That card is special in that we do have a means to identify - * it from this code, so in that case we skip the reset and just use a - * disable/purge to avoid the timeout and corresponding noise in the - * kernel log. - */ - if (afu->adapter->native->sl_ops->needs_reset_before_disable) - cxl_ops->afu_reset(afu); - cxl_afu_disable(afu); - cxl_psl_purge(afu); - - return 0; -} - -int cxl_activate_dedicated_process_psl9(struct cxl_afu *afu) -{ - dev_info(&afu->dev, "Activating dedicated process mode\n"); - - /* - * If XSL is set to dedicated mode (Set in PSL_SCNTL reg), the - * XSL and AFU are programmed to work with a single context. - * The context information should be configured in the SPA area - * index 0 (so PSL_SPAP must be configured before enabling the - * AFU). - */ - afu->num_procs = 1; - if (afu->native->spa == NULL) { - if (cxl_alloc_spa(afu, CXL_MODE_DEDICATED)) - return -ENOMEM; - } - attach_spa(afu); - - cxl_p1n_write(afu, CXL_PSL_SCNTL_An, CXL_PSL_SCNTL_An_PM_Process); - cxl_p1n_write(afu, CXL_PSL_ID_An, CXL_PSL_ID_An_F | CXL_PSL_ID_An_L); - - afu->current_mode = CXL_MODE_DEDICATED; - - return cxl_chardev_d_afu_add(afu); -} - -int cxl_activate_dedicated_process_psl8(struct cxl_afu *afu) -{ - dev_info(&afu->dev, "Activating dedicated process mode\n"); - - cxl_p1n_write(afu, CXL_PSL_SCNTL_An, CXL_PSL_SCNTL_An_PM_Process); - - cxl_p1n_write(afu, CXL_PSL_CtxTime_An, 0); /* disable */ - cxl_p1n_write(afu, CXL_PSL_SPAP_An, 0); /* disable */ - cxl_p1n_write(afu, CXL_PSL_AMOR_An, 0xFFFFFFFFFFFFFFFFULL); - cxl_p1n_write(afu, CXL_PSL_LPID_An, mfspr(SPRN_LPID)); - cxl_p1n_write(afu, CXL_HAURP_An, 0); /* disable */ - cxl_p1n_write(afu, CXL_PSL_SDR_An, mfspr(SPRN_SDR1)); - - cxl_p2n_write(afu, CXL_CSRP_An, 0); /* disable */ - cxl_p2n_write(afu, CXL_AURP0_An, 0); /* disable */ - cxl_p2n_write(afu, CXL_AURP1_An, 0); /* disable */ - - afu->current_mode = CXL_MODE_DEDICATED; - afu->num_procs = 1; - - return cxl_chardev_d_afu_add(afu); -} - -void cxl_update_dedicated_ivtes_psl9(struct cxl_context *ctx) -{ - int r; - - for (r = 0; r < CXL_IRQ_RANGES; r++) { - ctx->elem->ivte_offsets[r] = cpu_to_be16(ctx->irqs.offset[r]); - ctx->elem->ivte_ranges[r] = cpu_to_be16(ctx->irqs.range[r]); - } -} - -void cxl_update_dedicated_ivtes_psl8(struct cxl_context *ctx) -{ - struct cxl_afu *afu = ctx->afu; - - cxl_p1n_write(afu, CXL_PSL_IVTE_Offset_An, - (((u64)ctx->irqs.offset[0] & 0xffff) << 48) | - (((u64)ctx->irqs.offset[1] & 0xffff) << 32) | - (((u64)ctx->irqs.offset[2] & 0xffff) << 16) | - ((u64)ctx->irqs.offset[3] & 0xffff)); - cxl_p1n_write(afu, CXL_PSL_IVTE_Limit_An, (u64) - (((u64)ctx->irqs.range[0] & 0xffff) << 48) | - (((u64)ctx->irqs.range[1] & 0xffff) << 32) | - (((u64)ctx->irqs.range[2] & 0xffff) << 16) | - ((u64)ctx->irqs.range[3] & 0xffff)); -} - -int cxl_attach_dedicated_process_psl9(struct cxl_context *ctx, u64 wed, u64 amr) -{ - struct cxl_afu *afu = ctx->afu; - int result; - - /* fill the process element entry */ - result = process_element_entry_psl9(ctx, wed, amr); - if (result) - return result; - - if (ctx->afu->adapter->native->sl_ops->update_dedicated_ivtes) - afu->adapter->native->sl_ops->update_dedicated_ivtes(ctx); - - ctx->elem->software_state = cpu_to_be32(CXL_PE_SOFTWARE_STATE_V); - /* - * Ideally we should do a wmb() here to make sure the changes to the - * PE are visible to the card before we call afu_enable. - * On ppc64 though all mmios are preceded by a 'sync' instruction hence - * we dont dont need one here. - */ - - result = cxl_ops->afu_reset(afu); - if (result) - return result; - - return afu_enable(afu); -} - -int cxl_attach_dedicated_process_psl8(struct cxl_context *ctx, u64 wed, u64 amr) -{ - struct cxl_afu *afu = ctx->afu; - u64 pid; - int rc; - - pid = (u64)current->pid << 32; - if (ctx->kernel) - pid = 0; - cxl_p2n_write(afu, CXL_PSL_PID_TID_An, pid); - - cxl_p1n_write(afu, CXL_PSL_SR_An, calculate_sr(ctx)); - - if ((rc = cxl_write_sstp(afu, ctx->sstp0, ctx->sstp1))) - return rc; - - cxl_prefault(ctx, wed); - - if (ctx->afu->adapter->native->sl_ops->update_dedicated_ivtes) - afu->adapter->native->sl_ops->update_dedicated_ivtes(ctx); - - cxl_p2n_write(afu, CXL_PSL_AMR_An, amr); - - /* master only context for dedicated */ - cxl_assign_psn_space(ctx); - - if ((rc = cxl_ops->afu_reset(afu))) - return rc; - - cxl_p2n_write(afu, CXL_PSL_WED_An, wed); - - return afu_enable(afu); -} - -static int deactivate_dedicated_process(struct cxl_afu *afu) -{ - dev_info(&afu->dev, "Deactivating dedicated process mode\n"); - - afu->current_mode = 0; - afu->num_procs = 0; - - cxl_chardev_afu_remove(afu); - - return 0; -} - -static int native_afu_deactivate_mode(struct cxl_afu *afu, int mode) -{ - if (mode == CXL_MODE_DIRECTED) - return deactivate_afu_directed(afu); - if (mode == CXL_MODE_DEDICATED) - return deactivate_dedicated_process(afu); - return 0; -} - -static int native_afu_activate_mode(struct cxl_afu *afu, int mode) -{ - if (!mode) - return 0; - if (!(mode & afu->modes_supported)) - return -EINVAL; - - if (!cxl_ops->link_ok(afu->adapter, afu)) { - WARN(1, "Device link is down, refusing to activate!\n"); - return -EIO; - } - - if (mode == CXL_MODE_DIRECTED) - return activate_afu_directed(afu); - if ((mode == CXL_MODE_DEDICATED) && - (afu->adapter->native->sl_ops->activate_dedicated_process)) - return afu->adapter->native->sl_ops->activate_dedicated_process(afu); - - return -EINVAL; -} - -static int native_attach_process(struct cxl_context *ctx, bool kernel, - u64 wed, u64 amr) -{ - if (!cxl_ops->link_ok(ctx->afu->adapter, ctx->afu)) { - WARN(1, "Device link is down, refusing to attach process!\n"); - return -EIO; - } - - ctx->kernel = kernel; - if ((ctx->afu->current_mode == CXL_MODE_DIRECTED) && - (ctx->afu->adapter->native->sl_ops->attach_afu_directed)) - return ctx->afu->adapter->native->sl_ops->attach_afu_directed(ctx, wed, amr); - - if ((ctx->afu->current_mode == CXL_MODE_DEDICATED) && - (ctx->afu->adapter->native->sl_ops->attach_dedicated_process)) - return ctx->afu->adapter->native->sl_ops->attach_dedicated_process(ctx, wed, amr); - - return -EINVAL; -} - -static inline int detach_process_native_dedicated(struct cxl_context *ctx) -{ - /* - * The CAIA section 2.1.1 indicates that we need to do an AFU reset to - * stop the AFU in dedicated mode (we therefore do not make that - * optional like we do in the afu directed path). It does not indicate - * that we need to do an explicit disable (which should occur - * implicitly as part of the reset) or purge, but we do these as well - * to be on the safe side. - * - * Notably we used to have some issues with the disable sequence - * (before the sequence was spelled out in the architecture) which is - * why we were so heavy weight in the first place, however a bug was - * discovered that had rendered the disable operation ineffective, so - * it is conceivable that was the sole explanation for those - * difficulties. Point is, we should be careful and do some regression - * testing if we ever attempt to remove any part of this procedure. - */ - cxl_ops->afu_reset(ctx->afu); - cxl_afu_disable(ctx->afu); - cxl_psl_purge(ctx->afu); - return 0; -} - -static void native_update_ivtes(struct cxl_context *ctx) -{ - if (ctx->afu->current_mode == CXL_MODE_DIRECTED) - return update_ivtes_directed(ctx); - if ((ctx->afu->current_mode == CXL_MODE_DEDICATED) && - (ctx->afu->adapter->native->sl_ops->update_dedicated_ivtes)) - return ctx->afu->adapter->native->sl_ops->update_dedicated_ivtes(ctx); - WARN(1, "native_update_ivtes: Bad mode\n"); -} - -static inline int detach_process_native_afu_directed(struct cxl_context *ctx) -{ - if (!ctx->pe_inserted) - return 0; - if (terminate_process_element(ctx)) - return -1; - if (remove_process_element(ctx)) - return -1; - - return 0; -} - -static int native_detach_process(struct cxl_context *ctx) -{ - trace_cxl_detach(ctx); - - if (ctx->afu->current_mode == CXL_MODE_DEDICATED) - return detach_process_native_dedicated(ctx); - - return detach_process_native_afu_directed(ctx); -} - -static int native_get_irq_info(struct cxl_afu *afu, struct cxl_irq_info *info) -{ - /* If the adapter has gone away, we can't get any meaningful - * information. - */ - if (!cxl_ops->link_ok(afu->adapter, afu)) - return -EIO; - - info->dsisr = cxl_p2n_read(afu, CXL_PSL_DSISR_An); - info->dar = cxl_p2n_read(afu, CXL_PSL_DAR_An); - if (cxl_is_power8()) - info->dsr = cxl_p2n_read(afu, CXL_PSL_DSR_An); - info->afu_err = cxl_p2n_read(afu, CXL_AFU_ERR_An); - info->errstat = cxl_p2n_read(afu, CXL_PSL_ErrStat_An); - info->proc_handle = 0; - - return 0; -} - -void cxl_native_irq_dump_regs_psl9(struct cxl_context *ctx) -{ - u64 fir1, serr; - - fir1 = cxl_p1_read(ctx->afu->adapter, CXL_PSL9_FIR1); - - dev_crit(&ctx->afu->dev, "PSL_FIR1: 0x%016llx\n", fir1); - if (ctx->afu->adapter->native->sl_ops->register_serr_irq) { - serr = cxl_p1n_read(ctx->afu, CXL_PSL_SERR_An); - cxl_afu_decode_psl_serr(ctx->afu, serr); - } -} - -void cxl_native_irq_dump_regs_psl8(struct cxl_context *ctx) -{ - u64 fir1, fir2, fir_slice, serr, afu_debug; - - fir1 = cxl_p1_read(ctx->afu->adapter, CXL_PSL_FIR1); - fir2 = cxl_p1_read(ctx->afu->adapter, CXL_PSL_FIR2); - fir_slice = cxl_p1n_read(ctx->afu, CXL_PSL_FIR_SLICE_An); - afu_debug = cxl_p1n_read(ctx->afu, CXL_AFU_DEBUG_An); - - dev_crit(&ctx->afu->dev, "PSL_FIR1: 0x%016llx\n", fir1); - dev_crit(&ctx->afu->dev, "PSL_FIR2: 0x%016llx\n", fir2); - if (ctx->afu->adapter->native->sl_ops->register_serr_irq) { - serr = cxl_p1n_read(ctx->afu, CXL_PSL_SERR_An); - cxl_afu_decode_psl_serr(ctx->afu, serr); - } - dev_crit(&ctx->afu->dev, "PSL_FIR_SLICE_An: 0x%016llx\n", fir_slice); - dev_crit(&ctx->afu->dev, "CXL_PSL_AFU_DEBUG_An: 0x%016llx\n", afu_debug); -} - -static irqreturn_t native_handle_psl_slice_error(struct cxl_context *ctx, - u64 dsisr, u64 errstat) -{ - - dev_crit(&ctx->afu->dev, "PSL ERROR STATUS: 0x%016llx\n", errstat); - - if (ctx->afu->adapter->native->sl_ops->psl_irq_dump_registers) - ctx->afu->adapter->native->sl_ops->psl_irq_dump_registers(ctx); - - if (ctx->afu->adapter->native->sl_ops->debugfs_stop_trace) { - dev_crit(&ctx->afu->dev, "STOPPING CXL TRACE\n"); - ctx->afu->adapter->native->sl_ops->debugfs_stop_trace(ctx->afu->adapter); - } - - return cxl_ops->ack_irq(ctx, 0, errstat); -} - -static bool cxl_is_translation_fault(struct cxl_afu *afu, u64 dsisr) -{ - if ((cxl_is_power8()) && (dsisr & CXL_PSL_DSISR_TRANS)) - return true; - - if ((cxl_is_power9()) && (dsisr & CXL_PSL9_DSISR_An_TF)) - return true; - - return false; -} - -irqreturn_t cxl_fail_irq_psl(struct cxl_afu *afu, struct cxl_irq_info *irq_info) -{ - if (cxl_is_translation_fault(afu, irq_info->dsisr)) - cxl_p2n_write(afu, CXL_PSL_TFC_An, CXL_PSL_TFC_An_AE); - else - cxl_p2n_write(afu, CXL_PSL_TFC_An, CXL_PSL_TFC_An_A); - - return IRQ_HANDLED; -} - -static irqreturn_t native_irq_multiplexed(int irq, void *data) -{ - struct cxl_afu *afu = data; - struct cxl_context *ctx; - struct cxl_irq_info irq_info; - u64 phreg = cxl_p2n_read(afu, CXL_PSL_PEHandle_An); - int ph, ret = IRQ_HANDLED, res; - - /* check if eeh kicked in while the interrupt was in flight */ - if (unlikely(phreg == ~0ULL)) { - dev_warn(&afu->dev, - "Ignoring slice interrupt(%d) due to fenced card", - irq); - return IRQ_HANDLED; - } - /* Mask the pe-handle from register value */ - ph = phreg & 0xffff; - if ((res = native_get_irq_info(afu, &irq_info))) { - WARN(1, "Unable to get CXL IRQ Info: %i\n", res); - if (afu->adapter->native->sl_ops->fail_irq) - return afu->adapter->native->sl_ops->fail_irq(afu, &irq_info); - return ret; - } - - rcu_read_lock(); - ctx = idr_find(&afu->contexts_idr, ph); - if (ctx) { - if (afu->adapter->native->sl_ops->handle_interrupt) - ret = afu->adapter->native->sl_ops->handle_interrupt(irq, ctx, &irq_info); - rcu_read_unlock(); - return ret; - } - rcu_read_unlock(); - - WARN(1, "Unable to demultiplex CXL PSL IRQ for PE %i DSISR %016llx DAR" - " %016llx\n(Possible AFU HW issue - was a term/remove acked" - " with outstanding transactions?)\n", ph, irq_info.dsisr, - irq_info.dar); - if (afu->adapter->native->sl_ops->fail_irq) - ret = afu->adapter->native->sl_ops->fail_irq(afu, &irq_info); - return ret; -} - -static void native_irq_wait(struct cxl_context *ctx) -{ - u64 dsisr; - int timeout = 1000; - int ph; - - /* - * Wait until no further interrupts are presented by the PSL - * for this context. - */ - while (timeout--) { - ph = cxl_p2n_read(ctx->afu, CXL_PSL_PEHandle_An) & 0xffff; - if (ph != ctx->pe) - return; - dsisr = cxl_p2n_read(ctx->afu, CXL_PSL_DSISR_An); - if (cxl_is_power8() && - ((dsisr & CXL_PSL_DSISR_PENDING) == 0)) - return; - if (cxl_is_power9() && - ((dsisr & CXL_PSL9_DSISR_PENDING) == 0)) - return; - /* - * We are waiting for the workqueue to process our - * irq, so need to let that run here. - */ - msleep(1); - } - - dev_warn(&ctx->afu->dev, "WARNING: waiting on DSI for PE %i" - " DSISR %016llx!\n", ph, dsisr); - return; -} - -static irqreturn_t native_slice_irq_err(int irq, void *data) -{ - struct cxl_afu *afu = data; - u64 errstat, serr, afu_error, dsisr; - u64 fir_slice, afu_debug, irq_mask; - - /* - * slice err interrupt is only used with full PSL (no XSL) - */ - serr = cxl_p1n_read(afu, CXL_PSL_SERR_An); - errstat = cxl_p2n_read(afu, CXL_PSL_ErrStat_An); - afu_error = cxl_p2n_read(afu, CXL_AFU_ERR_An); - dsisr = cxl_p2n_read(afu, CXL_PSL_DSISR_An); - cxl_afu_decode_psl_serr(afu, serr); - - if (cxl_is_power8()) { - fir_slice = cxl_p1n_read(afu, CXL_PSL_FIR_SLICE_An); - afu_debug = cxl_p1n_read(afu, CXL_AFU_DEBUG_An); - dev_crit(&afu->dev, "PSL_FIR_SLICE_An: 0x%016llx\n", fir_slice); - dev_crit(&afu->dev, "CXL_PSL_AFU_DEBUG_An: 0x%016llx\n", afu_debug); - } - dev_crit(&afu->dev, "CXL_PSL_ErrStat_An: 0x%016llx\n", errstat); - dev_crit(&afu->dev, "AFU_ERR_An: 0x%.16llx\n", afu_error); - dev_crit(&afu->dev, "PSL_DSISR_An: 0x%.16llx\n", dsisr); - - /* mask off the IRQ so it won't retrigger until the AFU is reset */ - irq_mask = (serr & CXL_PSL_SERR_An_IRQS) >> 32; - serr |= irq_mask; - cxl_p1n_write(afu, CXL_PSL_SERR_An, serr); - dev_info(&afu->dev, "Further such interrupts will be masked until the AFU is reset\n"); - - return IRQ_HANDLED; -} - -void cxl_native_err_irq_dump_regs_psl9(struct cxl *adapter) -{ - u64 fir1; - - fir1 = cxl_p1_read(adapter, CXL_PSL9_FIR1); - dev_crit(&adapter->dev, "PSL_FIR: 0x%016llx\n", fir1); -} - -void cxl_native_err_irq_dump_regs_psl8(struct cxl *adapter) -{ - u64 fir1, fir2; - - fir1 = cxl_p1_read(adapter, CXL_PSL_FIR1); - fir2 = cxl_p1_read(adapter, CXL_PSL_FIR2); - dev_crit(&adapter->dev, - "PSL_FIR1: 0x%016llx\nPSL_FIR2: 0x%016llx\n", - fir1, fir2); -} - -static irqreturn_t native_irq_err(int irq, void *data) -{ - struct cxl *adapter = data; - u64 err_ivte; - - WARN(1, "CXL ERROR interrupt %i\n", irq); - - err_ivte = cxl_p1_read(adapter, CXL_PSL_ErrIVTE); - dev_crit(&adapter->dev, "PSL_ErrIVTE: 0x%016llx\n", err_ivte); - - if (adapter->native->sl_ops->debugfs_stop_trace) { - dev_crit(&adapter->dev, "STOPPING CXL TRACE\n"); - adapter->native->sl_ops->debugfs_stop_trace(adapter); - } - - if (adapter->native->sl_ops->err_irq_dump_registers) - adapter->native->sl_ops->err_irq_dump_registers(adapter); - - return IRQ_HANDLED; -} - -int cxl_native_register_psl_err_irq(struct cxl *adapter) -{ - int rc; - - adapter->irq_name = kasprintf(GFP_KERNEL, "cxl-%s-err", - dev_name(&adapter->dev)); - if (!adapter->irq_name) - return -ENOMEM; - - if ((rc = cxl_register_one_irq(adapter, native_irq_err, adapter, - &adapter->native->err_hwirq, - &adapter->native->err_virq, - adapter->irq_name))) { - kfree(adapter->irq_name); - adapter->irq_name = NULL; - return rc; - } - - cxl_p1_write(adapter, CXL_PSL_ErrIVTE, adapter->native->err_hwirq & 0xffff); - - return 0; -} - -void cxl_native_release_psl_err_irq(struct cxl *adapter) -{ - if (adapter->native->err_virq == 0 || - adapter->native->err_virq != - irq_find_mapping(NULL, adapter->native->err_hwirq)) - return; - - cxl_p1_write(adapter, CXL_PSL_ErrIVTE, 0x0000000000000000); - cxl_unmap_irq(adapter->native->err_virq, adapter); - cxl_ops->release_one_irq(adapter, adapter->native->err_hwirq); - kfree(adapter->irq_name); - adapter->native->err_virq = 0; -} - -int cxl_native_register_serr_irq(struct cxl_afu *afu) -{ - u64 serr; - int rc; - - afu->err_irq_name = kasprintf(GFP_KERNEL, "cxl-%s-err", - dev_name(&afu->dev)); - if (!afu->err_irq_name) - return -ENOMEM; - - if ((rc = cxl_register_one_irq(afu->adapter, native_slice_irq_err, afu, - &afu->serr_hwirq, - &afu->serr_virq, afu->err_irq_name))) { - kfree(afu->err_irq_name); - afu->err_irq_name = NULL; - return rc; - } - - serr = cxl_p1n_read(afu, CXL_PSL_SERR_An); - if (cxl_is_power8()) - serr = (serr & 0x00ffffffffff0000ULL) | (afu->serr_hwirq & 0xffff); - if (cxl_is_power9()) { - /* - * By default, all errors are masked. So don't set all masks. - * Slice errors will be transfered. - */ - serr = (serr & ~0xff0000007fffffffULL) | (afu->serr_hwirq & 0xffff); - } - cxl_p1n_write(afu, CXL_PSL_SERR_An, serr); - - return 0; -} - -void cxl_native_release_serr_irq(struct cxl_afu *afu) -{ - if (afu->serr_virq == 0 || - afu->serr_virq != irq_find_mapping(NULL, afu->serr_hwirq)) - return; - - cxl_p1n_write(afu, CXL_PSL_SERR_An, 0x0000000000000000); - cxl_unmap_irq(afu->serr_virq, afu); - cxl_ops->release_one_irq(afu->adapter, afu->serr_hwirq); - kfree(afu->err_irq_name); - afu->serr_virq = 0; -} - -int cxl_native_register_psl_irq(struct cxl_afu *afu) -{ - int rc; - - afu->psl_irq_name = kasprintf(GFP_KERNEL, "cxl-%s", - dev_name(&afu->dev)); - if (!afu->psl_irq_name) - return -ENOMEM; - - if ((rc = cxl_register_one_irq(afu->adapter, native_irq_multiplexed, - afu, &afu->native->psl_hwirq, &afu->native->psl_virq, - afu->psl_irq_name))) { - kfree(afu->psl_irq_name); - afu->psl_irq_name = NULL; - } - return rc; -} - -void cxl_native_release_psl_irq(struct cxl_afu *afu) -{ - if (afu->native->psl_virq == 0 || - afu->native->psl_virq != - irq_find_mapping(NULL, afu->native->psl_hwirq)) - return; - - cxl_unmap_irq(afu->native->psl_virq, afu); - cxl_ops->release_one_irq(afu->adapter, afu->native->psl_hwirq); - kfree(afu->psl_irq_name); - afu->native->psl_virq = 0; -} - -static void recover_psl_err(struct cxl_afu *afu, u64 errstat) -{ - u64 dsisr; - - pr_devel("RECOVERING FROM PSL ERROR... (0x%016llx)\n", errstat); - - /* Clear PSL_DSISR[PE] */ - dsisr = cxl_p2n_read(afu, CXL_PSL_DSISR_An); - cxl_p2n_write(afu, CXL_PSL_DSISR_An, dsisr & ~CXL_PSL_DSISR_An_PE); - - /* Write 1s to clear error status bits */ - cxl_p2n_write(afu, CXL_PSL_ErrStat_An, errstat); -} - -static int native_ack_irq(struct cxl_context *ctx, u64 tfc, u64 psl_reset_mask) -{ - trace_cxl_psl_irq_ack(ctx, tfc); - if (tfc) - cxl_p2n_write(ctx->afu, CXL_PSL_TFC_An, tfc); - if (psl_reset_mask) - recover_psl_err(ctx->afu, psl_reset_mask); - - return 0; -} - -int cxl_check_error(struct cxl_afu *afu) -{ - return (cxl_p1n_read(afu, CXL_PSL_SCNTL_An) == ~0ULL); -} - -static bool native_support_attributes(const char *attr_name, - enum cxl_attrs type) -{ - return true; -} - -static int native_afu_cr_read64(struct cxl_afu *afu, int cr, u64 off, u64 *out) -{ - if (unlikely(!cxl_ops->link_ok(afu->adapter, afu))) - return -EIO; - if (unlikely(off >= afu->crs_len)) - return -ERANGE; - *out = in_le64(afu->native->afu_desc_mmio + afu->crs_offset + - (cr * afu->crs_len) + off); - return 0; -} - -static int native_afu_cr_read32(struct cxl_afu *afu, int cr, u64 off, u32 *out) -{ - if (unlikely(!cxl_ops->link_ok(afu->adapter, afu))) - return -EIO; - if (unlikely(off >= afu->crs_len)) - return -ERANGE; - *out = in_le32(afu->native->afu_desc_mmio + afu->crs_offset + - (cr * afu->crs_len) + off); - return 0; -} - -static int native_afu_cr_read16(struct cxl_afu *afu, int cr, u64 off, u16 *out) -{ - u64 aligned_off = off & ~0x3L; - u32 val; - int rc; - - rc = native_afu_cr_read32(afu, cr, aligned_off, &val); - if (!rc) - *out = (val >> ((off & 0x3) * 8)) & 0xffff; - return rc; -} - -static int native_afu_cr_read8(struct cxl_afu *afu, int cr, u64 off, u8 *out) -{ - u64 aligned_off = off & ~0x3L; - u32 val; - int rc; - - rc = native_afu_cr_read32(afu, cr, aligned_off, &val); - if (!rc) - *out = (val >> ((off & 0x3) * 8)) & 0xff; - return rc; -} - -static int native_afu_cr_write32(struct cxl_afu *afu, int cr, u64 off, u32 in) -{ - if (unlikely(!cxl_ops->link_ok(afu->adapter, afu))) - return -EIO; - if (unlikely(off >= afu->crs_len)) - return -ERANGE; - out_le32(afu->native->afu_desc_mmio + afu->crs_offset + - (cr * afu->crs_len) + off, in); - return 0; -} - -static int native_afu_cr_write16(struct cxl_afu *afu, int cr, u64 off, u16 in) -{ - u64 aligned_off = off & ~0x3L; - u32 val32, mask, shift; - int rc; - - rc = native_afu_cr_read32(afu, cr, aligned_off, &val32); - if (rc) - return rc; - shift = (off & 0x3) * 8; - WARN_ON(shift == 24); - mask = 0xffff << shift; - val32 = (val32 & ~mask) | (in << shift); - - rc = native_afu_cr_write32(afu, cr, aligned_off, val32); - return rc; -} - -static int native_afu_cr_write8(struct cxl_afu *afu, int cr, u64 off, u8 in) -{ - u64 aligned_off = off & ~0x3L; - u32 val32, mask, shift; - int rc; - - rc = native_afu_cr_read32(afu, cr, aligned_off, &val32); - if (rc) - return rc; - shift = (off & 0x3) * 8; - mask = 0xff << shift; - val32 = (val32 & ~mask) | (in << shift); - - rc = native_afu_cr_write32(afu, cr, aligned_off, val32); - return rc; -} - -const struct cxl_backend_ops cxl_native_ops = { - .module = THIS_MODULE, - .adapter_reset = cxl_pci_reset, - .alloc_one_irq = cxl_pci_alloc_one_irq, - .release_one_irq = cxl_pci_release_one_irq, - .alloc_irq_ranges = cxl_pci_alloc_irq_ranges, - .release_irq_ranges = cxl_pci_release_irq_ranges, - .setup_irq = cxl_pci_setup_irq, - .handle_psl_slice_error = native_handle_psl_slice_error, - .psl_interrupt = NULL, - .ack_irq = native_ack_irq, - .irq_wait = native_irq_wait, - .attach_process = native_attach_process, - .detach_process = native_detach_process, - .update_ivtes = native_update_ivtes, - .support_attributes = native_support_attributes, - .link_ok = cxl_adapter_link_ok, - .release_afu = cxl_pci_release_afu, - .afu_read_err_buffer = cxl_pci_afu_read_err_buffer, - .afu_check_and_enable = native_afu_check_and_enable, - .afu_activate_mode = native_afu_activate_mode, - .afu_deactivate_mode = native_afu_deactivate_mode, - .afu_reset = native_afu_reset, - .afu_cr_read8 = native_afu_cr_read8, - .afu_cr_read16 = native_afu_cr_read16, - .afu_cr_read32 = native_afu_cr_read32, - .afu_cr_read64 = native_afu_cr_read64, - .afu_cr_write8 = native_afu_cr_write8, - .afu_cr_write16 = native_afu_cr_write16, - .afu_cr_write32 = native_afu_cr_write32, - .read_adapter_vpd = cxl_pci_read_adapter_vpd, -};
diff --git a/drivers/misc/cxl/of.c b/drivers/misc/cxl/of.c deleted file mode 100644 index e26ee85..0000000 --- a/drivers/misc/cxl/of.c +++ /dev/null
@@ -1,346 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Copyright 2015 IBM Corp. - */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/platform_device.h> -#include <linux/slab.h> -#include <linux/of.h> -#include <linux/of_address.h> -#include <linux/of_platform.h> - -#include "cxl.h" - -static int read_phys_addr(struct device_node *np, char *prop_name, - struct cxl_afu *afu) -{ - int i, len, entry_size, naddr, nsize, type; - u64 addr, size; - const __be32 *prop; - - naddr = of_n_addr_cells(np); - nsize = of_n_size_cells(np); - - prop = of_get_property(np, prop_name, &len); - if (prop) { - entry_size = naddr + nsize; - for (i = 0; i < (len / 4); i += entry_size, prop += entry_size) { - type = be32_to_cpu(prop[0]); - addr = of_read_number(prop, naddr); - size = of_read_number(&prop[naddr], nsize); - switch (type) { - case 0: /* unit address */ - afu->guest->handle = addr; - break; - case 1: /* p2 area */ - afu->guest->p2n_phys += addr; - afu->guest->p2n_size = size; - break; - case 2: /* problem state area */ - afu->psn_phys += addr; - afu->adapter->ps_size = size; - break; - default: - pr_err("Invalid address type %d found in %s property of AFU\n", - type, prop_name); - return -EINVAL; - } - } - } - return 0; -} - -static int read_vpd(struct cxl *adapter, struct cxl_afu *afu) -{ - char vpd[256]; - int rc; - size_t len = sizeof(vpd); - - memset(vpd, 0, len); - - if (adapter) - rc = cxl_guest_read_adapter_vpd(adapter, vpd, len); - else - rc = cxl_guest_read_afu_vpd(afu, vpd, len); - - if (rc > 0) { - cxl_dump_debug_buffer(vpd, rc); - rc = 0; - } - return rc; -} - -int cxl_of_read_afu_handle(struct cxl_afu *afu, struct device_node *afu_np) -{ - return of_property_read_reg(afu_np, 0, &afu->guest->handle, NULL); -} - -int cxl_of_read_afu_properties(struct cxl_afu *afu, struct device_node *np) -{ - int i, rc; - u16 device_id, vendor_id; - u32 val = 0, class_code; - - /* Properties are read in the same order as listed in PAPR */ - - rc = read_phys_addr(np, "reg", afu); - if (rc) - return rc; - - rc = read_phys_addr(np, "assigned-addresses", afu); - if (rc) - return rc; - - if (afu->psn_phys == 0) - afu->psa = false; - else - afu->psa = true; - - of_property_read_u32(np, "ibm,#processes", &afu->max_procs_virtualised); - - if (cxl_verbose) - read_vpd(NULL, afu); - - of_property_read_u32(np, "ibm,max-ints-per-process", &afu->guest->max_ints); - afu->irqs_max = afu->guest->max_ints; - - if (!of_property_read_u32(np, "ibm,min-ints-per-process", &afu->pp_irqs)) { - /* One extra interrupt for the PSL interrupt is already - * included. Remove it now to keep only AFU interrupts and - * match the native case. - */ - afu->pp_irqs--; - } - - of_property_read_u64(np, "ibm,error-buffer-size", &afu->eb_len); - afu->eb_offset = 0; - - of_property_read_u64(np, "ibm,config-record-size", &afu->crs_len); - afu->crs_offset = 0; - - of_property_read_u32(np, "ibm,#config-records", &afu->crs_num); - - if (cxl_verbose) { - for (i = 0; i < afu->crs_num; i++) { - rc = cxl_ops->afu_cr_read16(afu, i, PCI_DEVICE_ID, - &device_id); - if (!rc) - pr_info("record %d - device-id: %#x\n", - i, device_id); - rc = cxl_ops->afu_cr_read16(afu, i, PCI_VENDOR_ID, - &vendor_id); - if (!rc) - pr_info("record %d - vendor-id: %#x\n", - i, vendor_id); - rc = cxl_ops->afu_cr_read32(afu, i, PCI_CLASS_REVISION, - &class_code); - if (!rc) { - class_code >>= 8; - pr_info("record %d - class-code: %#x\n", - i, class_code); - } - } - } - /* - * if "ibm,process-mmio" doesn't exist then per-process mmio is - * not supported - */ - val = 0; - if (!of_property_read_u32(np, "ibm,process-mmio", &val) && val == 1) - afu->pp_psa = true; - else - afu->pp_psa = false; - - if (!of_property_read_u32(np, "ibm,function-error-interrupt", &val)) - afu->serr_hwirq = val; - - pr_devel("AFU handle: %#llx\n", afu->guest->handle); - pr_devel("p2n_phys: %#llx (size %#llx)\n", - afu->guest->p2n_phys, afu->guest->p2n_size); - pr_devel("psn_phys: %#llx (size %#llx)\n", - afu->psn_phys, afu->adapter->ps_size); - pr_devel("Max number of processes virtualised=%i\n", - afu->max_procs_virtualised); - pr_devel("Per-process irqs min=%i, max=%i\n", afu->pp_irqs, - afu->irqs_max); - pr_devel("Slice error interrupt=%#lx\n", afu->serr_hwirq); - - return 0; -} - -static int read_adapter_irq_config(struct cxl *adapter, struct device_node *np) -{ - const __be32 *ranges; - int len, nranges, i; - struct irq_avail *cur; - - ranges = of_get_property(np, "interrupt-ranges", &len); - if (ranges == NULL || len < (2 * sizeof(int))) - return -EINVAL; - - /* - * encoded array of two cells per entry, each cell encoded as - * with encode-int - */ - nranges = len / (2 * sizeof(int)); - if (nranges == 0 || (nranges * 2 * sizeof(int)) != len) - return -EINVAL; - - adapter->guest->irq_avail = kcalloc(nranges, sizeof(struct irq_avail), - GFP_KERNEL); - if (adapter->guest->irq_avail == NULL) - return -ENOMEM; - - adapter->guest->irq_base_offset = be32_to_cpu(ranges[0]); - for (i = 0; i < nranges; i++) { - cur = &adapter->guest->irq_avail[i]; - cur->offset = be32_to_cpu(ranges[i * 2]); - cur->range = be32_to_cpu(ranges[i * 2 + 1]); - cur->bitmap = bitmap_zalloc(cur->range, GFP_KERNEL); - if (cur->bitmap == NULL) - goto err; - if (cur->offset < adapter->guest->irq_base_offset) - adapter->guest->irq_base_offset = cur->offset; - if (cxl_verbose) - pr_info("available IRQ range: %#lx-%#lx (%lu)\n", - cur->offset, cur->offset + cur->range - 1, - cur->range); - } - adapter->guest->irq_nranges = nranges; - spin_lock_init(&adapter->guest->irq_alloc_lock); - - return 0; -err: - for (i--; i >= 0; i--) { - cur = &adapter->guest->irq_avail[i]; - bitmap_free(cur->bitmap); - } - kfree(adapter->guest->irq_avail); - adapter->guest->irq_avail = NULL; - return -ENOMEM; -} - -int cxl_of_read_adapter_handle(struct cxl *adapter, struct device_node *np) -{ - return of_property_read_reg(np, 0, &adapter->guest->handle, NULL); -} - -int cxl_of_read_adapter_properties(struct cxl *adapter, struct device_node *np) -{ - int rc; - const char *p; - u32 val = 0; - - /* Properties are read in the same order as listed in PAPR */ - - if ((rc = read_adapter_irq_config(adapter, np))) - return rc; - - if (!of_property_read_u32(np, "ibm,caia-version", &val)) { - adapter->caia_major = (val & 0xFF00) >> 8; - adapter->caia_minor = val & 0xFF; - } - - if (!of_property_read_u32(np, "ibm,psl-revision", &val)) - adapter->psl_rev = val; - - if (!of_property_read_string(np, "status", &p)) { - adapter->guest->status = kasprintf(GFP_KERNEL, "%s", p); - if (adapter->guest->status == NULL) - return -ENOMEM; - } - - if (!of_property_read_u32(np, "vendor-id", &val)) - adapter->guest->vendor = val; - - if (!of_property_read_u32(np, "device-id", &val)) - adapter->guest->device = val; - - if (!of_property_read_u32(np, "subsystem-vendor-id", &val)) - adapter->guest->subsystem_vendor = val; - - if (!of_property_read_u32(np, "subsystem-id", &val)) - adapter->guest->subsystem = val; - - if (cxl_verbose) - read_vpd(adapter, NULL); - - return 0; -} - -static void cxl_of_remove(struct platform_device *pdev) -{ - struct cxl *adapter; - int afu; - - adapter = dev_get_drvdata(&pdev->dev); - for (afu = 0; afu < adapter->slices; afu++) - cxl_guest_remove_afu(adapter->afu[afu]); - - cxl_guest_remove_adapter(adapter); -} - -static void cxl_of_shutdown(struct platform_device *pdev) -{ - cxl_of_remove(pdev); -} - -int cxl_of_probe(struct platform_device *pdev) -{ - struct device_node *np = NULL; - struct device_node *afu_np = NULL; - struct cxl *adapter = NULL; - int ret; - int slice = 0, slice_ok = 0; - - dev_err_once(&pdev->dev, "DEPRECATION: cxl is deprecated and will be removed in a future kernel release\n"); - - pr_devel("in %s\n", __func__); - - np = pdev->dev.of_node; - if (np == NULL) - return -ENODEV; - - /* init adapter */ - adapter = cxl_guest_init_adapter(np, pdev); - if (IS_ERR(adapter)) { - dev_err(&pdev->dev, "guest_init_adapter failed: %li\n", PTR_ERR(adapter)); - return PTR_ERR(adapter); - } - - /* init afu */ - for_each_child_of_node(np, afu_np) { - if ((ret = cxl_guest_init_afu(adapter, slice, afu_np))) - dev_err(&pdev->dev, "AFU %i failed to initialise: %i\n", - slice, ret); - else - slice_ok++; - slice++; - } - - if (slice_ok == 0) { - dev_info(&pdev->dev, "No active AFU"); - adapter->slices = 0; - } - - return 0; -} - -static const struct of_device_id cxl_of_match[] = { - { .compatible = "ibm,coherent-platform-facility",}, - {}, -}; -MODULE_DEVICE_TABLE(of, cxl_of_match); - -struct platform_driver cxl_of_driver = { - .driver = { - .name = "cxl_of", - .of_match_table = cxl_of_match, - .owner = THIS_MODULE - }, - .probe = cxl_of_probe, - .remove = cxl_of_remove, - .shutdown = cxl_of_shutdown, -};
diff --git a/drivers/misc/cxl/pci.c b/drivers/misc/cxl/pci.c deleted file mode 100644 index 92bf7c5..0000000 --- a/drivers/misc/cxl/pci.c +++ /dev/null
@@ -1,2103 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Copyright 2014 IBM Corp. - */ - -#include <linux/pci_regs.h> -#include <linux/pci_ids.h> -#include <linux/device.h> -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/sort.h> -#include <linux/pci.h> -#include <linux/of.h> -#include <linux/delay.h> -#include <asm/opal.h> -#include <asm/msi_bitmap.h> -#include <asm/pnv-pci.h> -#include <asm/io.h> -#include <asm/reg.h> - -#include "cxl.h" -#include <misc/cxl.h> - - -#define CXL_PCI_VSEC_ID 0x1280 -#define CXL_VSEC_MIN_SIZE 0x80 - -#define CXL_READ_VSEC_LENGTH(dev, vsec, dest) \ - { \ - pci_read_config_word(dev, vsec + 0x6, dest); \ - *dest >>= 4; \ - } -#define CXL_READ_VSEC_NAFUS(dev, vsec, dest) \ - pci_read_config_byte(dev, vsec + 0x8, dest) - -#define CXL_READ_VSEC_STATUS(dev, vsec, dest) \ - pci_read_config_byte(dev, vsec + 0x9, dest) -#define CXL_STATUS_SECOND_PORT 0x80 -#define CXL_STATUS_MSI_X_FULL 0x40 -#define CXL_STATUS_MSI_X_SINGLE 0x20 -#define CXL_STATUS_FLASH_RW 0x08 -#define CXL_STATUS_FLASH_RO 0x04 -#define CXL_STATUS_LOADABLE_AFU 0x02 -#define CXL_STATUS_LOADABLE_PSL 0x01 -/* If we see these features we won't try to use the card */ -#define CXL_UNSUPPORTED_FEATURES \ - (CXL_STATUS_MSI_X_FULL | CXL_STATUS_MSI_X_SINGLE) - -#define CXL_READ_VSEC_MODE_CONTROL(dev, vsec, dest) \ - pci_read_config_byte(dev, vsec + 0xa, dest) -#define CXL_WRITE_VSEC_MODE_CONTROL(dev, vsec, val) \ - pci_write_config_byte(dev, vsec + 0xa, val) -#define CXL_VSEC_PROTOCOL_MASK 0xe0 -#define CXL_VSEC_PROTOCOL_1024TB 0x80 -#define CXL_VSEC_PROTOCOL_512TB 0x40 -#define CXL_VSEC_PROTOCOL_256TB 0x20 /* Power 8/9 uses this */ -#define CXL_VSEC_PROTOCOL_ENABLE 0x01 - -#define CXL_READ_VSEC_PSL_REVISION(dev, vsec, dest) \ - pci_read_config_word(dev, vsec + 0xc, dest) -#define CXL_READ_VSEC_CAIA_MINOR(dev, vsec, dest) \ - pci_read_config_byte(dev, vsec + 0xe, dest) -#define CXL_READ_VSEC_CAIA_MAJOR(dev, vsec, dest) \ - pci_read_config_byte(dev, vsec + 0xf, dest) -#define CXL_READ_VSEC_BASE_IMAGE(dev, vsec, dest) \ - pci_read_config_word(dev, vsec + 0x10, dest) - -#define CXL_READ_VSEC_IMAGE_STATE(dev, vsec, dest) \ - pci_read_config_byte(dev, vsec + 0x13, dest) -#define CXL_WRITE_VSEC_IMAGE_STATE(dev, vsec, val) \ - pci_write_config_byte(dev, vsec + 0x13, val) -#define CXL_VSEC_USER_IMAGE_LOADED 0x80 /* RO */ -#define CXL_VSEC_PERST_LOADS_IMAGE 0x20 /* RW */ -#define CXL_VSEC_PERST_SELECT_USER 0x10 /* RW */ - -#define CXL_READ_VSEC_AFU_DESC_OFF(dev, vsec, dest) \ - pci_read_config_dword(dev, vsec + 0x20, dest) -#define CXL_READ_VSEC_AFU_DESC_SIZE(dev, vsec, dest) \ - pci_read_config_dword(dev, vsec + 0x24, dest) -#define CXL_READ_VSEC_PS_OFF(dev, vsec, dest) \ - pci_read_config_dword(dev, vsec + 0x28, dest) -#define CXL_READ_VSEC_PS_SIZE(dev, vsec, dest) \ - pci_read_config_dword(dev, vsec + 0x2c, dest) - - -/* This works a little different than the p1/p2 register accesses to make it - * easier to pull out individual fields */ -#define AFUD_READ(afu, off) in_be64(afu->native->afu_desc_mmio + off) -#define AFUD_READ_LE(afu, off) in_le64(afu->native->afu_desc_mmio + off) -#define EXTRACT_PPC_BIT(val, bit) (!!(val & PPC_BIT(bit))) -#define EXTRACT_PPC_BITS(val, bs, be) ((val & PPC_BITMASK(bs, be)) >> PPC_BITLSHIFT(be)) - -#define AFUD_READ_INFO(afu) AFUD_READ(afu, 0x0) -#define AFUD_NUM_INTS_PER_PROC(val) EXTRACT_PPC_BITS(val, 0, 15) -#define AFUD_NUM_PROCS(val) EXTRACT_PPC_BITS(val, 16, 31) -#define AFUD_NUM_CRS(val) EXTRACT_PPC_BITS(val, 32, 47) -#define AFUD_MULTIMODE(val) EXTRACT_PPC_BIT(val, 48) -#define AFUD_PUSH_BLOCK_TRANSFER(val) EXTRACT_PPC_BIT(val, 55) -#define AFUD_DEDICATED_PROCESS(val) EXTRACT_PPC_BIT(val, 59) -#define AFUD_AFU_DIRECTED(val) EXTRACT_PPC_BIT(val, 61) -#define AFUD_TIME_SLICED(val) EXTRACT_PPC_BIT(val, 63) -#define AFUD_READ_CR(afu) AFUD_READ(afu, 0x20) -#define AFUD_CR_LEN(val) EXTRACT_PPC_BITS(val, 8, 63) -#define AFUD_READ_CR_OFF(afu) AFUD_READ(afu, 0x28) -#define AFUD_READ_PPPSA(afu) AFUD_READ(afu, 0x30) -#define AFUD_PPPSA_PP(val) EXTRACT_PPC_BIT(val, 6) -#define AFUD_PPPSA_PSA(val) EXTRACT_PPC_BIT(val, 7) -#define AFUD_PPPSA_LEN(val) EXTRACT_PPC_BITS(val, 8, 63) -#define AFUD_READ_PPPSA_OFF(afu) AFUD_READ(afu, 0x38) -#define AFUD_READ_EB(afu) AFUD_READ(afu, 0x40) -#define AFUD_EB_LEN(val) EXTRACT_PPC_BITS(val, 8, 63) -#define AFUD_READ_EB_OFF(afu) AFUD_READ(afu, 0x48) - -static const struct pci_device_id cxl_pci_tbl[] = { - { PCI_DEVICE(PCI_VENDOR_ID_IBM, 0x0477), }, - { PCI_DEVICE(PCI_VENDOR_ID_IBM, 0x044b), }, - { PCI_DEVICE(PCI_VENDOR_ID_IBM, 0x04cf), }, - { PCI_DEVICE(PCI_VENDOR_ID_IBM, 0x0601), }, - { PCI_DEVICE(PCI_VENDOR_ID_IBM, 0x0623), }, - { PCI_DEVICE(PCI_VENDOR_ID_IBM, 0x0628), }, - { } -}; -MODULE_DEVICE_TABLE(pci, cxl_pci_tbl); - - -/* - * Mostly using these wrappers to avoid confusion: - * priv 1 is BAR2, while priv 2 is BAR0 - */ -static inline resource_size_t p1_base(struct pci_dev *dev) -{ - return pci_resource_start(dev, 2); -} - -static inline resource_size_t p1_size(struct pci_dev *dev) -{ - return pci_resource_len(dev, 2); -} - -static inline resource_size_t p2_base(struct pci_dev *dev) -{ - return pci_resource_start(dev, 0); -} - -static inline resource_size_t p2_size(struct pci_dev *dev) -{ - return pci_resource_len(dev, 0); -} - -static int find_cxl_vsec(struct pci_dev *dev) -{ - return pci_find_vsec_capability(dev, PCI_VENDOR_ID_IBM, CXL_PCI_VSEC_ID); -} - -static void dump_cxl_config_space(struct pci_dev *dev) -{ - int vsec; - u32 val; - - dev_info(&dev->dev, "dump_cxl_config_space\n"); - - pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &val); - dev_info(&dev->dev, "BAR0: %#.8x\n", val); - pci_read_config_dword(dev, PCI_BASE_ADDRESS_1, &val); - dev_info(&dev->dev, "BAR1: %#.8x\n", val); - pci_read_config_dword(dev, PCI_BASE_ADDRESS_2, &val); - dev_info(&dev->dev, "BAR2: %#.8x\n", val); - pci_read_config_dword(dev, PCI_BASE_ADDRESS_3, &val); - dev_info(&dev->dev, "BAR3: %#.8x\n", val); - pci_read_config_dword(dev, PCI_BASE_ADDRESS_4, &val); - dev_info(&dev->dev, "BAR4: %#.8x\n", val); - pci_read_config_dword(dev, PCI_BASE_ADDRESS_5, &val); - dev_info(&dev->dev, "BAR5: %#.8x\n", val); - - dev_info(&dev->dev, "p1 regs: %#llx, len: %#llx\n", - p1_base(dev), p1_size(dev)); - dev_info(&dev->dev, "p2 regs: %#llx, len: %#llx\n", - p2_base(dev), p2_size(dev)); - dev_info(&dev->dev, "BAR 4/5: %#llx, len: %#llx\n", - pci_resource_start(dev, 4), pci_resource_len(dev, 4)); - - if (!(vsec = find_cxl_vsec(dev))) - return; - -#define show_reg(name, what) \ - dev_info(&dev->dev, "cxl vsec: %30s: %#x\n", name, what) - - pci_read_config_dword(dev, vsec + 0x0, &val); - show_reg("Cap ID", (val >> 0) & 0xffff); - show_reg("Cap Ver", (val >> 16) & 0xf); - show_reg("Next Cap Ptr", (val >> 20) & 0xfff); - pci_read_config_dword(dev, vsec + 0x4, &val); - show_reg("VSEC ID", (val >> 0) & 0xffff); - show_reg("VSEC Rev", (val >> 16) & 0xf); - show_reg("VSEC Length", (val >> 20) & 0xfff); - pci_read_config_dword(dev, vsec + 0x8, &val); - show_reg("Num AFUs", (val >> 0) & 0xff); - show_reg("Status", (val >> 8) & 0xff); - show_reg("Mode Control", (val >> 16) & 0xff); - show_reg("Reserved", (val >> 24) & 0xff); - pci_read_config_dword(dev, vsec + 0xc, &val); - show_reg("PSL Rev", (val >> 0) & 0xffff); - show_reg("CAIA Ver", (val >> 16) & 0xffff); - pci_read_config_dword(dev, vsec + 0x10, &val); - show_reg("Base Image Rev", (val >> 0) & 0xffff); - show_reg("Reserved", (val >> 16) & 0x0fff); - show_reg("Image Control", (val >> 28) & 0x3); - show_reg("Reserved", (val >> 30) & 0x1); - show_reg("Image Loaded", (val >> 31) & 0x1); - - pci_read_config_dword(dev, vsec + 0x14, &val); - show_reg("Reserved", val); - pci_read_config_dword(dev, vsec + 0x18, &val); - show_reg("Reserved", val); - pci_read_config_dword(dev, vsec + 0x1c, &val); - show_reg("Reserved", val); - - pci_read_config_dword(dev, vsec + 0x20, &val); - show_reg("AFU Descriptor Offset", val); - pci_read_config_dword(dev, vsec + 0x24, &val); - show_reg("AFU Descriptor Size", val); - pci_read_config_dword(dev, vsec + 0x28, &val); - show_reg("Problem State Offset", val); - pci_read_config_dword(dev, vsec + 0x2c, &val); - show_reg("Problem State Size", val); - - pci_read_config_dword(dev, vsec + 0x30, &val); - show_reg("Reserved", val); - pci_read_config_dword(dev, vsec + 0x34, &val); - show_reg("Reserved", val); - pci_read_config_dword(dev, vsec + 0x38, &val); - show_reg("Reserved", val); - pci_read_config_dword(dev, vsec + 0x3c, &val); - show_reg("Reserved", val); - - pci_read_config_dword(dev, vsec + 0x40, &val); - show_reg("PSL Programming Port", val); - pci_read_config_dword(dev, vsec + 0x44, &val); - show_reg("PSL Programming Control", val); - - pci_read_config_dword(dev, vsec + 0x48, &val); - show_reg("Reserved", val); - pci_read_config_dword(dev, vsec + 0x4c, &val); - show_reg("Reserved", val); - - pci_read_config_dword(dev, vsec + 0x50, &val); - show_reg("Flash Address Register", val); - pci_read_config_dword(dev, vsec + 0x54, &val); - show_reg("Flash Size Register", val); - pci_read_config_dword(dev, vsec + 0x58, &val); - show_reg("Flash Status/Control Register", val); - pci_read_config_dword(dev, vsec + 0x58, &val); - show_reg("Flash Data Port", val); - -#undef show_reg -} - -static void dump_afu_descriptor(struct cxl_afu *afu) -{ - u64 val, afu_cr_num, afu_cr_off, afu_cr_len; - int i; - -#define show_reg(name, what) \ - dev_info(&afu->dev, "afu desc: %30s: %#llx\n", name, what) - - val = AFUD_READ_INFO(afu); - show_reg("num_ints_per_process", AFUD_NUM_INTS_PER_PROC(val)); - show_reg("num_of_processes", AFUD_NUM_PROCS(val)); - show_reg("num_of_afu_CRs", AFUD_NUM_CRS(val)); - show_reg("req_prog_mode", val & 0xffffULL); - afu_cr_num = AFUD_NUM_CRS(val); - - val = AFUD_READ(afu, 0x8); - show_reg("Reserved", val); - val = AFUD_READ(afu, 0x10); - show_reg("Reserved", val); - val = AFUD_READ(afu, 0x18); - show_reg("Reserved", val); - - val = AFUD_READ_CR(afu); - show_reg("Reserved", (val >> (63-7)) & 0xff); - show_reg("AFU_CR_len", AFUD_CR_LEN(val)); - afu_cr_len = AFUD_CR_LEN(val) * 256; - - val = AFUD_READ_CR_OFF(afu); - afu_cr_off = val; - show_reg("AFU_CR_offset", val); - - val = AFUD_READ_PPPSA(afu); - show_reg("PerProcessPSA_control", (val >> (63-7)) & 0xff); - show_reg("PerProcessPSA Length", AFUD_PPPSA_LEN(val)); - - val = AFUD_READ_PPPSA_OFF(afu); - show_reg("PerProcessPSA_offset", val); - - val = AFUD_READ_EB(afu); - show_reg("Reserved", (val >> (63-7)) & 0xff); - show_reg("AFU_EB_len", AFUD_EB_LEN(val)); - - val = AFUD_READ_EB_OFF(afu); - show_reg("AFU_EB_offset", val); - - for (i = 0; i < afu_cr_num; i++) { - val = AFUD_READ_LE(afu, afu_cr_off + i * afu_cr_len); - show_reg("CR Vendor", val & 0xffff); - show_reg("CR Device", (val >> 16) & 0xffff); - } -#undef show_reg -} - -#define P8_CAPP_UNIT0_ID 0xBA -#define P8_CAPP_UNIT1_ID 0XBE -#define P9_CAPP_UNIT0_ID 0xC0 -#define P9_CAPP_UNIT1_ID 0xE0 - -static int get_phb_index(struct device_node *np, u32 *phb_index) -{ - if (of_property_read_u32(np, "ibm,phb-index", phb_index)) - return -ENODEV; - return 0; -} - -static u64 get_capp_unit_id(struct device_node *np, u32 phb_index) -{ - /* - * POWER 8: - * - For chips other than POWER8NVL, we only have CAPP 0, - * irrespective of which PHB is used. - * - For POWER8NVL, assume CAPP 0 is attached to PHB0 and - * CAPP 1 is attached to PHB1. - */ - if (cxl_is_power8()) { - if (!pvr_version_is(PVR_POWER8NVL)) - return P8_CAPP_UNIT0_ID; - - if (phb_index == 0) - return P8_CAPP_UNIT0_ID; - - if (phb_index == 1) - return P8_CAPP_UNIT1_ID; - } - - /* - * POWER 9: - * PEC0 (PHB0). Capp ID = CAPP0 (0b1100_0000) - * PEC1 (PHB1 - PHB2). No capi mode - * PEC2 (PHB3 - PHB4 - PHB5): Capi mode on PHB3 only. Capp ID = CAPP1 (0b1110_0000) - */ - if (cxl_is_power9()) { - if (phb_index == 0) - return P9_CAPP_UNIT0_ID; - - if (phb_index == 3) - return P9_CAPP_UNIT1_ID; - } - - return 0; -} - -int cxl_calc_capp_routing(struct pci_dev *dev, u64 *chipid, - u32 *phb_index, u64 *capp_unit_id) -{ - int rc; - struct device_node *np; - u32 id; - - if (!(np = pnv_pci_get_phb_node(dev))) - return -ENODEV; - - while (np && of_property_read_u32(np, "ibm,chip-id", &id)) - np = of_get_next_parent(np); - if (!np) - return -ENODEV; - - *chipid = id; - - rc = get_phb_index(np, phb_index); - if (rc) { - pr_err("cxl: invalid phb index\n"); - of_node_put(np); - return rc; - } - - *capp_unit_id = get_capp_unit_id(np, *phb_index); - of_node_put(np); - if (!*capp_unit_id) { - pr_err("cxl: No capp unit found for PHB[%lld,%d]. Make sure the adapter is on a capi-compatible slot\n", - *chipid, *phb_index); - return -ENODEV; - } - - return 0; -} - -static DEFINE_MUTEX(indications_mutex); - -static int get_phb_indications(struct pci_dev *dev, u64 *capiind, u64 *asnind, - u64 *nbwind) -{ - static u32 val[3]; - struct device_node *np; - - mutex_lock(&indications_mutex); - if (!val[0]) { - if (!(np = pnv_pci_get_phb_node(dev))) { - mutex_unlock(&indications_mutex); - return -ENODEV; - } - - if (of_property_read_u32_array(np, "ibm,phb-indications", val, 3)) { - val[2] = 0x0300UL; /* legacy values */ - val[1] = 0x0400UL; - val[0] = 0x0200UL; - } - of_node_put(np); - } - *capiind = val[0]; - *asnind = val[1]; - *nbwind = val[2]; - mutex_unlock(&indications_mutex); - return 0; -} - -int cxl_get_xsl9_dsnctl(struct pci_dev *dev, u64 capp_unit_id, u64 *reg) -{ - u64 xsl_dsnctl; - u64 capiind, asnind, nbwind; - - /* - * CAPI Identifier bits [0:7] - * bit 61:60 MSI bits --> 0 - * bit 59 TVT selector --> 0 - */ - if (get_phb_indications(dev, &capiind, &asnind, &nbwind)) - return -ENODEV; - - /* - * Tell XSL where to route data to. - * The field chipid should match the PHB CAPI_CMPM register - */ - xsl_dsnctl = (capiind << (63-15)); /* Bit 57 */ - xsl_dsnctl |= (capp_unit_id << (63-15)); - - /* nMMU_ID Defaults to: b’000001001’*/ - xsl_dsnctl |= ((u64)0x09 << (63-28)); - - /* - * Used to identify CAPI packets which should be sorted into - * the Non-Blocking queues by the PHB. This field should match - * the PHB PBL_NBW_CMPM register - * nbwind=0x03, bits [57:58], must include capi indicator. - * Not supported on P9 DD1. - */ - xsl_dsnctl |= (nbwind << (63-55)); - - /* - * Upper 16b address bits of ASB_Notify messages sent to the - * system. Need to match the PHB’s ASN Compare/Mask Register. - * Not supported on P9 DD1. - */ - xsl_dsnctl |= asnind; - - *reg = xsl_dsnctl; - return 0; -} - -static int init_implementation_adapter_regs_psl9(struct cxl *adapter, - struct pci_dev *dev) -{ - u64 xsl_dsnctl, psl_fircntl; - u64 chipid; - u32 phb_index; - u64 capp_unit_id; - u64 psl_debug; - int rc; - - rc = cxl_calc_capp_routing(dev, &chipid, &phb_index, &capp_unit_id); - if (rc) - return rc; - - rc = cxl_get_xsl9_dsnctl(dev, capp_unit_id, &xsl_dsnctl); - if (rc) - return rc; - - cxl_p1_write(adapter, CXL_XSL9_DSNCTL, xsl_dsnctl); - - /* Set fir_cntl to recommended value for production env */ - psl_fircntl = (0x2ULL << (63-3)); /* ce_report */ - psl_fircntl |= (0x1ULL << (63-6)); /* FIR_report */ - psl_fircntl |= 0x1ULL; /* ce_thresh */ - cxl_p1_write(adapter, CXL_PSL9_FIR_CNTL, psl_fircntl); - - /* Setup the PSL to transmit packets on the PCIe before the - * CAPP is enabled. Make sure that CAPP virtual machines are disabled - */ - cxl_p1_write(adapter, CXL_PSL9_DSNDCTL, 0x0001001000012A10ULL); - - /* - * A response to an ASB_Notify request is returned by the - * system as an MMIO write to the address defined in - * the PSL_TNR_ADDR register. - * keep the Reset Value: 0x00020000E0000000 - */ - - /* Enable XSL rty limit */ - cxl_p1_write(adapter, CXL_XSL9_DEF, 0x51F8000000000005ULL); - - /* Change XSL_INV dummy read threshold */ - cxl_p1_write(adapter, CXL_XSL9_INV, 0x0000040007FFC200ULL); - - if (phb_index == 3) { - /* disable machines 31-47 and 20-27 for DMA */ - cxl_p1_write(adapter, CXL_PSL9_APCDEDTYPE, 0x40000FF3FFFF0000ULL); - } - - /* Snoop machines */ - cxl_p1_write(adapter, CXL_PSL9_APCDEDALLOC, 0x800F000200000000ULL); - - /* Enable NORST and DD2 features */ - cxl_p1_write(adapter, CXL_PSL9_DEBUG, 0xC000000000000000ULL); - - /* - * Check if PSL has data-cache. We need to flush adapter datacache - * when as its about to be removed. - */ - psl_debug = cxl_p1_read(adapter, CXL_PSL9_DEBUG); - if (psl_debug & CXL_PSL_DEBUG_CDC) { - dev_dbg(&dev->dev, "No data-cache present\n"); - adapter->native->no_data_cache = true; - } - - return 0; -} - -static int init_implementation_adapter_regs_psl8(struct cxl *adapter, struct pci_dev *dev) -{ - u64 psl_dsnctl, psl_fircntl; - u64 chipid; - u32 phb_index; - u64 capp_unit_id; - int rc; - - rc = cxl_calc_capp_routing(dev, &chipid, &phb_index, &capp_unit_id); - if (rc) - return rc; - - psl_dsnctl = 0x0000900000000000ULL; /* pteupd ttype, scdone */ - psl_dsnctl |= (0x2ULL << (63-38)); /* MMIO hang pulse: 256 us */ - /* Tell PSL where to route data to */ - psl_dsnctl |= (chipid << (63-5)); - psl_dsnctl |= (capp_unit_id << (63-13)); - - cxl_p1_write(adapter, CXL_PSL_DSNDCTL, psl_dsnctl); - cxl_p1_write(adapter, CXL_PSL_RESLCKTO, 0x20000000200ULL); - /* snoop write mask */ - cxl_p1_write(adapter, CXL_PSL_SNWRALLOC, 0x00000000FFFFFFFFULL); - /* set fir_cntl to recommended value for production env */ - psl_fircntl = (0x2ULL << (63-3)); /* ce_report */ - psl_fircntl |= (0x1ULL << (63-6)); /* FIR_report */ - psl_fircntl |= 0x1ULL; /* ce_thresh */ - cxl_p1_write(adapter, CXL_PSL_FIR_CNTL, psl_fircntl); - /* for debugging with trace arrays */ - cxl_p1_write(adapter, CXL_PSL_TRACE, 0x0000FF7C00000000ULL); - - return 0; -} - -/* PSL */ -#define TBSYNC_CAL(n) (((u64)n & 0x7) << (63-3)) -#define TBSYNC_CNT(n) (((u64)n & 0x7) << (63-6)) -/* For the PSL this is a multiple for 0 < n <= 7: */ -#define PSL_2048_250MHZ_CYCLES 1 - -static void write_timebase_ctrl_psl8(struct cxl *adapter) -{ - cxl_p1_write(adapter, CXL_PSL_TB_CTLSTAT, - TBSYNC_CNT(2 * PSL_2048_250MHZ_CYCLES)); -} - -static u64 timebase_read_psl9(struct cxl *adapter) -{ - return cxl_p1_read(adapter, CXL_PSL9_Timebase); -} - -static u64 timebase_read_psl8(struct cxl *adapter) -{ - return cxl_p1_read(adapter, CXL_PSL_Timebase); -} - -static void cxl_setup_psl_timebase(struct cxl *adapter, struct pci_dev *dev) -{ - struct device_node *np; - - adapter->psl_timebase_synced = false; - - if (!(np = pnv_pci_get_phb_node(dev))) - return; - - /* Do not fail when CAPP timebase sync is not supported by OPAL */ - of_node_get(np); - if (!of_property_present(np, "ibm,capp-timebase-sync")) { - of_node_put(np); - dev_info(&dev->dev, "PSL timebase inactive: OPAL support missing\n"); - return; - } - of_node_put(np); - - /* - * Setup PSL Timebase Control and Status register - * with the recommended Timebase Sync Count value - */ - if (adapter->native->sl_ops->write_timebase_ctrl) - adapter->native->sl_ops->write_timebase_ctrl(adapter); - - /* Enable PSL Timebase */ - cxl_p1_write(adapter, CXL_PSL_Control, 0x0000000000000000); - cxl_p1_write(adapter, CXL_PSL_Control, CXL_PSL_Control_tb); - - return; -} - -static int init_implementation_afu_regs_psl9(struct cxl_afu *afu) -{ - return 0; -} - -static int init_implementation_afu_regs_psl8(struct cxl_afu *afu) -{ - /* read/write masks for this slice */ - cxl_p1n_write(afu, CXL_PSL_APCALLOC_A, 0xFFFFFFFEFEFEFEFEULL); - /* APC read/write masks for this slice */ - cxl_p1n_write(afu, CXL_PSL_COALLOC_A, 0xFF000000FEFEFEFEULL); - /* for debugging with trace arrays */ - cxl_p1n_write(afu, CXL_PSL_SLICE_TRACE, 0x0000FFFF00000000ULL); - cxl_p1n_write(afu, CXL_PSL_RXCTL_A, CXL_PSL_RXCTL_AFUHP_4S); - - return 0; -} - -int cxl_pci_setup_irq(struct cxl *adapter, unsigned int hwirq, - unsigned int virq) -{ - struct pci_dev *dev = to_pci_dev(adapter->dev.parent); - - return pnv_cxl_ioda_msi_setup(dev, hwirq, virq); -} - -int cxl_update_image_control(struct cxl *adapter) -{ - struct pci_dev *dev = to_pci_dev(adapter->dev.parent); - int rc; - int vsec; - u8 image_state; - - if (!(vsec = find_cxl_vsec(dev))) { - dev_err(&dev->dev, "ABORTING: CXL VSEC not found!\n"); - return -ENODEV; - } - - if ((rc = CXL_READ_VSEC_IMAGE_STATE(dev, vsec, &image_state))) { - dev_err(&dev->dev, "failed to read image state: %i\n", rc); - return rc; - } - - if (adapter->perst_loads_image) - image_state |= CXL_VSEC_PERST_LOADS_IMAGE; - else - image_state &= ~CXL_VSEC_PERST_LOADS_IMAGE; - - if (adapter->perst_select_user) - image_state |= CXL_VSEC_PERST_SELECT_USER; - else - image_state &= ~CXL_VSEC_PERST_SELECT_USER; - - if ((rc = CXL_WRITE_VSEC_IMAGE_STATE(dev, vsec, image_state))) { - dev_err(&dev->dev, "failed to update image control: %i\n", rc); - return rc; - } - - return 0; -} - -int cxl_pci_alloc_one_irq(struct cxl *adapter) -{ - struct pci_dev *dev = to_pci_dev(adapter->dev.parent); - - return pnv_cxl_alloc_hwirqs(dev, 1); -} - -void cxl_pci_release_one_irq(struct cxl *adapter, int hwirq) -{ - struct pci_dev *dev = to_pci_dev(adapter->dev.parent); - - return pnv_cxl_release_hwirqs(dev, hwirq, 1); -} - -int cxl_pci_alloc_irq_ranges(struct cxl_irq_ranges *irqs, - struct cxl *adapter, unsigned int num) -{ - struct pci_dev *dev = to_pci_dev(adapter->dev.parent); - - return pnv_cxl_alloc_hwirq_ranges(irqs, dev, num); -} - -void cxl_pci_release_irq_ranges(struct cxl_irq_ranges *irqs, - struct cxl *adapter) -{ - struct pci_dev *dev = to_pci_dev(adapter->dev.parent); - - pnv_cxl_release_hwirq_ranges(irqs, dev); -} - -static int setup_cxl_bars(struct pci_dev *dev) -{ - /* Safety check in case we get backported to < 3.17 without M64 */ - if ((p1_base(dev) < 0x100000000ULL) || - (p2_base(dev) < 0x100000000ULL)) { - dev_err(&dev->dev, "ABORTING: M32 BAR assignment incompatible with CXL\n"); - return -ENODEV; - } - - /* - * BAR 4/5 has a special meaning for CXL and must be programmed with a - * special value corresponding to the CXL protocol address range. - * For POWER 8/9 that means bits 48:49 must be set to 10 - */ - pci_write_config_dword(dev, PCI_BASE_ADDRESS_4, 0x00000000); - pci_write_config_dword(dev, PCI_BASE_ADDRESS_5, 0x00020000); - - return 0; -} - -/* pciex node: ibm,opal-m64-window = <0x3d058 0x0 0x3d058 0x0 0x8 0x0>; */ -static int switch_card_to_cxl(struct pci_dev *dev) -{ - int vsec; - u8 val; - int rc; - - dev_info(&dev->dev, "switch card to CXL\n"); - - if (!(vsec = find_cxl_vsec(dev))) { - dev_err(&dev->dev, "ABORTING: CXL VSEC not found!\n"); - return -ENODEV; - } - - if ((rc = CXL_READ_VSEC_MODE_CONTROL(dev, vsec, &val))) { - dev_err(&dev->dev, "failed to read current mode control: %i", rc); - return rc; - } - val &= ~CXL_VSEC_PROTOCOL_MASK; - val |= CXL_VSEC_PROTOCOL_256TB | CXL_VSEC_PROTOCOL_ENABLE; - if ((rc = CXL_WRITE_VSEC_MODE_CONTROL(dev, vsec, val))) { - dev_err(&dev->dev, "failed to enable CXL protocol: %i", rc); - return rc; - } - /* - * The CAIA spec (v0.12 11.6 Bi-modal Device Support) states - * we must wait 100ms after this mode switch before touching - * PCIe config space. - */ - msleep(100); - - return 0; -} - -static int pci_map_slice_regs(struct cxl_afu *afu, struct cxl *adapter, struct pci_dev *dev) -{ - u64 p1n_base, p2n_base, afu_desc; - const u64 p1n_size = 0x100; - const u64 p2n_size = 0x1000; - - p1n_base = p1_base(dev) + 0x10000 + (afu->slice * p1n_size); - p2n_base = p2_base(dev) + (afu->slice * p2n_size); - afu->psn_phys = p2_base(dev) + (adapter->native->ps_off + (afu->slice * adapter->ps_size)); - afu_desc = p2_base(dev) + adapter->native->afu_desc_off + (afu->slice * adapter->native->afu_desc_size); - - if (!(afu->native->p1n_mmio = ioremap(p1n_base, p1n_size))) - goto err; - if (!(afu->p2n_mmio = ioremap(p2n_base, p2n_size))) - goto err1; - if (afu_desc) { - if (!(afu->native->afu_desc_mmio = ioremap(afu_desc, adapter->native->afu_desc_size))) - goto err2; - } - - return 0; -err2: - iounmap(afu->p2n_mmio); -err1: - iounmap(afu->native->p1n_mmio); -err: - dev_err(&afu->dev, "Error mapping AFU MMIO regions\n"); - return -ENOMEM; -} - -static void pci_unmap_slice_regs(struct cxl_afu *afu) -{ - if (afu->p2n_mmio) { - iounmap(afu->p2n_mmio); - afu->p2n_mmio = NULL; - } - if (afu->native->p1n_mmio) { - iounmap(afu->native->p1n_mmio); - afu->native->p1n_mmio = NULL; - } - if (afu->native->afu_desc_mmio) { - iounmap(afu->native->afu_desc_mmio); - afu->native->afu_desc_mmio = NULL; - } -} - -void cxl_pci_release_afu(struct device *dev) -{ - struct cxl_afu *afu = to_cxl_afu(dev); - - pr_devel("%s\n", __func__); - - idr_destroy(&afu->contexts_idr); - cxl_release_spa(afu); - - kfree(afu->native); - kfree(afu); -} - -/* Expects AFU struct to have recently been zeroed out */ -static int cxl_read_afu_descriptor(struct cxl_afu *afu) -{ - u64 val; - - val = AFUD_READ_INFO(afu); - afu->pp_irqs = AFUD_NUM_INTS_PER_PROC(val); - afu->max_procs_virtualised = AFUD_NUM_PROCS(val); - afu->crs_num = AFUD_NUM_CRS(val); - - if (AFUD_AFU_DIRECTED(val)) - afu->modes_supported |= CXL_MODE_DIRECTED; - if (AFUD_DEDICATED_PROCESS(val)) - afu->modes_supported |= CXL_MODE_DEDICATED; - if (AFUD_TIME_SLICED(val)) - afu->modes_supported |= CXL_MODE_TIME_SLICED; - - val = AFUD_READ_PPPSA(afu); - afu->pp_size = AFUD_PPPSA_LEN(val) * 4096; - afu->psa = AFUD_PPPSA_PSA(val); - if ((afu->pp_psa = AFUD_PPPSA_PP(val))) - afu->native->pp_offset = AFUD_READ_PPPSA_OFF(afu); - - val = AFUD_READ_CR(afu); - afu->crs_len = AFUD_CR_LEN(val) * 256; - afu->crs_offset = AFUD_READ_CR_OFF(afu); - - - /* eb_len is in multiple of 4K */ - afu->eb_len = AFUD_EB_LEN(AFUD_READ_EB(afu)) * 4096; - afu->eb_offset = AFUD_READ_EB_OFF(afu); - - /* eb_off is 4K aligned so lower 12 bits are always zero */ - if (EXTRACT_PPC_BITS(afu->eb_offset, 0, 11) != 0) { - dev_warn(&afu->dev, - "Invalid AFU error buffer offset %Lx\n", - afu->eb_offset); - dev_info(&afu->dev, - "Ignoring AFU error buffer in the descriptor\n"); - /* indicate that no afu buffer exists */ - afu->eb_len = 0; - } - - return 0; -} - -static int cxl_afu_descriptor_looks_ok(struct cxl_afu *afu) -{ - int i, rc; - u32 val; - - if (afu->psa && afu->adapter->ps_size < - (afu->native->pp_offset + afu->pp_size*afu->max_procs_virtualised)) { - dev_err(&afu->dev, "per-process PSA can't fit inside the PSA!\n"); - return -ENODEV; - } - - if (afu->pp_psa && (afu->pp_size < PAGE_SIZE)) - dev_warn(&afu->dev, "AFU uses pp_size(%#016llx) < PAGE_SIZE per-process PSA!\n", afu->pp_size); - - for (i = 0; i < afu->crs_num; i++) { - rc = cxl_ops->afu_cr_read32(afu, i, 0, &val); - if (rc || val == 0) { - dev_err(&afu->dev, "ABORTING: AFU configuration record %i is invalid\n", i); - return -EINVAL; - } - } - - if ((afu->modes_supported & ~CXL_MODE_DEDICATED) && afu->max_procs_virtualised == 0) { - /* - * We could also check this for the dedicated process model - * since the architecture indicates it should be set to 1, but - * in that case we ignore the value and I'd rather not risk - * breaking any existing dedicated process AFUs that left it as - * 0 (not that I'm aware of any). It is clearly an error for an - * AFU directed AFU to set this to 0, and would have previously - * triggered a bug resulting in the maximum not being enforced - * at all since idr_alloc treats 0 as no maximum. - */ - dev_err(&afu->dev, "AFU does not support any processes\n"); - return -EINVAL; - } - - return 0; -} - -static int sanitise_afu_regs_psl9(struct cxl_afu *afu) -{ - u64 reg; - - /* - * Clear out any regs that contain either an IVTE or address or may be - * waiting on an acknowledgment to try to be a bit safer as we bring - * it online - */ - reg = cxl_p2n_read(afu, CXL_AFU_Cntl_An); - if ((reg & CXL_AFU_Cntl_An_ES_MASK) != CXL_AFU_Cntl_An_ES_Disabled) { - dev_warn(&afu->dev, "WARNING: AFU was not disabled: %#016llx\n", reg); - if (cxl_ops->afu_reset(afu)) - return -EIO; - if (cxl_afu_disable(afu)) - return -EIO; - if (cxl_psl_purge(afu)) - return -EIO; - } - cxl_p1n_write(afu, CXL_PSL_SPAP_An, 0x0000000000000000); - cxl_p1n_write(afu, CXL_PSL_AMBAR_An, 0x0000000000000000); - reg = cxl_p2n_read(afu, CXL_PSL_DSISR_An); - if (reg) { - dev_warn(&afu->dev, "AFU had pending DSISR: %#016llx\n", reg); - if (reg & CXL_PSL9_DSISR_An_TF) - cxl_p2n_write(afu, CXL_PSL_TFC_An, CXL_PSL_TFC_An_AE); - else - cxl_p2n_write(afu, CXL_PSL_TFC_An, CXL_PSL_TFC_An_A); - } - if (afu->adapter->native->sl_ops->register_serr_irq) { - reg = cxl_p1n_read(afu, CXL_PSL_SERR_An); - if (reg) { - if (reg & ~0x000000007fffffff) - dev_warn(&afu->dev, "AFU had pending SERR: %#016llx\n", reg); - cxl_p1n_write(afu, CXL_PSL_SERR_An, reg & ~0xffff); - } - } - reg = cxl_p2n_read(afu, CXL_PSL_ErrStat_An); - if (reg) { - dev_warn(&afu->dev, "AFU had pending error status: %#016llx\n", reg); - cxl_p2n_write(afu, CXL_PSL_ErrStat_An, reg); - } - - return 0; -} - -static int sanitise_afu_regs_psl8(struct cxl_afu *afu) -{ - u64 reg; - - /* - * Clear out any regs that contain either an IVTE or address or may be - * waiting on an acknowledgement to try to be a bit safer as we bring - * it online - */ - reg = cxl_p2n_read(afu, CXL_AFU_Cntl_An); - if ((reg & CXL_AFU_Cntl_An_ES_MASK) != CXL_AFU_Cntl_An_ES_Disabled) { - dev_warn(&afu->dev, "WARNING: AFU was not disabled: %#016llx\n", reg); - if (cxl_ops->afu_reset(afu)) - return -EIO; - if (cxl_afu_disable(afu)) - return -EIO; - if (cxl_psl_purge(afu)) - return -EIO; - } - cxl_p1n_write(afu, CXL_PSL_SPAP_An, 0x0000000000000000); - cxl_p1n_write(afu, CXL_PSL_IVTE_Limit_An, 0x0000000000000000); - cxl_p1n_write(afu, CXL_PSL_IVTE_Offset_An, 0x0000000000000000); - cxl_p1n_write(afu, CXL_PSL_AMBAR_An, 0x0000000000000000); - cxl_p1n_write(afu, CXL_PSL_SPOffset_An, 0x0000000000000000); - cxl_p1n_write(afu, CXL_HAURP_An, 0x0000000000000000); - cxl_p2n_write(afu, CXL_CSRP_An, 0x0000000000000000); - cxl_p2n_write(afu, CXL_AURP1_An, 0x0000000000000000); - cxl_p2n_write(afu, CXL_AURP0_An, 0x0000000000000000); - cxl_p2n_write(afu, CXL_SSTP1_An, 0x0000000000000000); - cxl_p2n_write(afu, CXL_SSTP0_An, 0x0000000000000000); - reg = cxl_p2n_read(afu, CXL_PSL_DSISR_An); - if (reg) { - dev_warn(&afu->dev, "AFU had pending DSISR: %#016llx\n", reg); - if (reg & CXL_PSL_DSISR_TRANS) - cxl_p2n_write(afu, CXL_PSL_TFC_An, CXL_PSL_TFC_An_AE); - else - cxl_p2n_write(afu, CXL_PSL_TFC_An, CXL_PSL_TFC_An_A); - } - if (afu->adapter->native->sl_ops->register_serr_irq) { - reg = cxl_p1n_read(afu, CXL_PSL_SERR_An); - if (reg) { - if (reg & ~0xffff) - dev_warn(&afu->dev, "AFU had pending SERR: %#016llx\n", reg); - cxl_p1n_write(afu, CXL_PSL_SERR_An, reg & ~0xffff); - } - } - reg = cxl_p2n_read(afu, CXL_PSL_ErrStat_An); - if (reg) { - dev_warn(&afu->dev, "AFU had pending error status: %#016llx\n", reg); - cxl_p2n_write(afu, CXL_PSL_ErrStat_An, reg); - } - - return 0; -} - -#define ERR_BUFF_MAX_COPY_SIZE PAGE_SIZE -/* - * afu_eb_read: - * Called from sysfs and reads the afu error info buffer. The h/w only supports - * 4/8 bytes aligned access. So in case the requested offset/count arent 8 byte - * aligned the function uses a bounce buffer which can be max PAGE_SIZE. - */ -ssize_t cxl_pci_afu_read_err_buffer(struct cxl_afu *afu, char *buf, - loff_t off, size_t count) -{ - loff_t aligned_start, aligned_end; - size_t aligned_length; - void *tbuf; - const void __iomem *ebuf = afu->native->afu_desc_mmio + afu->eb_offset; - - if (count == 0 || off < 0 || (size_t)off >= afu->eb_len) - return 0; - - /* calculate aligned read window */ - count = min((size_t)(afu->eb_len - off), count); - aligned_start = round_down(off, 8); - aligned_end = round_up(off + count, 8); - aligned_length = aligned_end - aligned_start; - - /* max we can copy in one read is PAGE_SIZE */ - if (aligned_length > ERR_BUFF_MAX_COPY_SIZE) { - aligned_length = ERR_BUFF_MAX_COPY_SIZE; - count = ERR_BUFF_MAX_COPY_SIZE - (off & 0x7); - } - - /* use bounce buffer for copy */ - tbuf = (void *)__get_free_page(GFP_KERNEL); - if (!tbuf) - return -ENOMEM; - - /* perform aligned read from the mmio region */ - memcpy_fromio(tbuf, ebuf + aligned_start, aligned_length); - memcpy(buf, tbuf + (off & 0x7), count); - - free_page((unsigned long)tbuf); - - return count; -} - -static int pci_configure_afu(struct cxl_afu *afu, struct cxl *adapter, struct pci_dev *dev) -{ - int rc; - - if ((rc = pci_map_slice_regs(afu, adapter, dev))) - return rc; - - if (adapter->native->sl_ops->sanitise_afu_regs) { - rc = adapter->native->sl_ops->sanitise_afu_regs(afu); - if (rc) - goto err1; - } - - /* We need to reset the AFU before we can read the AFU descriptor */ - if ((rc = cxl_ops->afu_reset(afu))) - goto err1; - - if (cxl_verbose) - dump_afu_descriptor(afu); - - if ((rc = cxl_read_afu_descriptor(afu))) - goto err1; - - if ((rc = cxl_afu_descriptor_looks_ok(afu))) - goto err1; - - if (adapter->native->sl_ops->afu_regs_init) - if ((rc = adapter->native->sl_ops->afu_regs_init(afu))) - goto err1; - - if (adapter->native->sl_ops->register_serr_irq) - if ((rc = adapter->native->sl_ops->register_serr_irq(afu))) - goto err1; - - if ((rc = cxl_native_register_psl_irq(afu))) - goto err2; - - atomic_set(&afu->configured_state, 0); - return 0; - -err2: - if (adapter->native->sl_ops->release_serr_irq) - adapter->native->sl_ops->release_serr_irq(afu); -err1: - pci_unmap_slice_regs(afu); - return rc; -} - -static void pci_deconfigure_afu(struct cxl_afu *afu) -{ - /* - * It's okay to deconfigure when AFU is already locked, otherwise wait - * until there are no readers - */ - if (atomic_read(&afu->configured_state) != -1) { - while (atomic_cmpxchg(&afu->configured_state, 0, -1) != -1) - schedule(); - } - cxl_native_release_psl_irq(afu); - if (afu->adapter->native->sl_ops->release_serr_irq) - afu->adapter->native->sl_ops->release_serr_irq(afu); - pci_unmap_slice_regs(afu); -} - -static int pci_init_afu(struct cxl *adapter, int slice, struct pci_dev *dev) -{ - struct cxl_afu *afu; - int rc = -ENOMEM; - - afu = cxl_alloc_afu(adapter, slice); - if (!afu) - return -ENOMEM; - - afu->native = kzalloc(sizeof(struct cxl_afu_native), GFP_KERNEL); - if (!afu->native) - goto err_free_afu; - - mutex_init(&afu->native->spa_mutex); - - rc = dev_set_name(&afu->dev, "afu%i.%i", adapter->adapter_num, slice); - if (rc) - goto err_free_native; - - rc = pci_configure_afu(afu, adapter, dev); - if (rc) - goto err_free_native; - - /* Don't care if this fails */ - cxl_debugfs_afu_add(afu); - - /* - * After we call this function we must not free the afu directly, even - * if it returns an error! - */ - if ((rc = cxl_register_afu(afu))) - goto err_put_dev; - - if ((rc = cxl_sysfs_afu_add(afu))) - goto err_del_dev; - - adapter->afu[afu->slice] = afu; - - if ((rc = cxl_pci_vphb_add(afu))) - dev_info(&afu->dev, "Can't register vPHB\n"); - - return 0; - -err_del_dev: - device_del(&afu->dev); -err_put_dev: - pci_deconfigure_afu(afu); - cxl_debugfs_afu_remove(afu); - put_device(&afu->dev); - return rc; - -err_free_native: - kfree(afu->native); -err_free_afu: - kfree(afu); - return rc; - -} - -static void cxl_pci_remove_afu(struct cxl_afu *afu) -{ - pr_devel("%s\n", __func__); - - if (!afu) - return; - - cxl_pci_vphb_remove(afu); - cxl_sysfs_afu_remove(afu); - cxl_debugfs_afu_remove(afu); - - spin_lock(&afu->adapter->afu_list_lock); - afu->adapter->afu[afu->slice] = NULL; - spin_unlock(&afu->adapter->afu_list_lock); - - cxl_context_detach_all(afu); - cxl_ops->afu_deactivate_mode(afu, afu->current_mode); - - pci_deconfigure_afu(afu); - device_unregister(&afu->dev); -} - -int cxl_pci_reset(struct cxl *adapter) -{ - struct pci_dev *dev = to_pci_dev(adapter->dev.parent); - int rc; - - if (adapter->perst_same_image) { - dev_warn(&dev->dev, - "cxl: refusing to reset/reflash when perst_reloads_same_image is set.\n"); - return -EINVAL; - } - - dev_info(&dev->dev, "CXL reset\n"); - - /* - * The adapter is about to be reset, so ignore errors. - */ - cxl_data_cache_flush(adapter); - - /* pcie_warm_reset requests a fundamental pci reset which includes a - * PERST assert/deassert. PERST triggers a loading of the image - * if "user" or "factory" is selected in sysfs */ - if ((rc = pci_set_pcie_reset_state(dev, pcie_warm_reset))) { - dev_err(&dev->dev, "cxl: pcie_warm_reset failed\n"); - return rc; - } - - return rc; -} - -static int cxl_map_adapter_regs(struct cxl *adapter, struct pci_dev *dev) -{ - if (pci_request_region(dev, 2, "priv 2 regs")) - goto err1; - if (pci_request_region(dev, 0, "priv 1 regs")) - goto err2; - - pr_devel("cxl_map_adapter_regs: p1: %#016llx %#llx, p2: %#016llx %#llx", - p1_base(dev), p1_size(dev), p2_base(dev), p2_size(dev)); - - if (!(adapter->native->p1_mmio = ioremap(p1_base(dev), p1_size(dev)))) - goto err3; - - if (!(adapter->native->p2_mmio = ioremap(p2_base(dev), p2_size(dev)))) - goto err4; - - return 0; - -err4: - iounmap(adapter->native->p1_mmio); - adapter->native->p1_mmio = NULL; -err3: - pci_release_region(dev, 0); -err2: - pci_release_region(dev, 2); -err1: - return -ENOMEM; -} - -static void cxl_unmap_adapter_regs(struct cxl *adapter) -{ - if (adapter->native->p1_mmio) { - iounmap(adapter->native->p1_mmio); - adapter->native->p1_mmio = NULL; - pci_release_region(to_pci_dev(adapter->dev.parent), 2); - } - if (adapter->native->p2_mmio) { - iounmap(adapter->native->p2_mmio); - adapter->native->p2_mmio = NULL; - pci_release_region(to_pci_dev(adapter->dev.parent), 0); - } -} - -static int cxl_read_vsec(struct cxl *adapter, struct pci_dev *dev) -{ - int vsec; - u32 afu_desc_off, afu_desc_size; - u32 ps_off, ps_size; - u16 vseclen; - u8 image_state; - - if (!(vsec = find_cxl_vsec(dev))) { - dev_err(&dev->dev, "ABORTING: CXL VSEC not found!\n"); - return -ENODEV; - } - - CXL_READ_VSEC_LENGTH(dev, vsec, &vseclen); - if (vseclen < CXL_VSEC_MIN_SIZE) { - dev_err(&dev->dev, "ABORTING: CXL VSEC too short\n"); - return -EINVAL; - } - - CXL_READ_VSEC_STATUS(dev, vsec, &adapter->vsec_status); - CXL_READ_VSEC_PSL_REVISION(dev, vsec, &adapter->psl_rev); - CXL_READ_VSEC_CAIA_MAJOR(dev, vsec, &adapter->caia_major); - CXL_READ_VSEC_CAIA_MINOR(dev, vsec, &adapter->caia_minor); - CXL_READ_VSEC_BASE_IMAGE(dev, vsec, &adapter->base_image); - CXL_READ_VSEC_IMAGE_STATE(dev, vsec, &image_state); - adapter->user_image_loaded = !!(image_state & CXL_VSEC_USER_IMAGE_LOADED); - adapter->perst_select_user = !!(image_state & CXL_VSEC_USER_IMAGE_LOADED); - adapter->perst_loads_image = !!(image_state & CXL_VSEC_PERST_LOADS_IMAGE); - - CXL_READ_VSEC_NAFUS(dev, vsec, &adapter->slices); - CXL_READ_VSEC_AFU_DESC_OFF(dev, vsec, &afu_desc_off); - CXL_READ_VSEC_AFU_DESC_SIZE(dev, vsec, &afu_desc_size); - CXL_READ_VSEC_PS_OFF(dev, vsec, &ps_off); - CXL_READ_VSEC_PS_SIZE(dev, vsec, &ps_size); - - /* Convert everything to bytes, because there is NO WAY I'd look at the - * code a month later and forget what units these are in ;-) */ - adapter->native->ps_off = ps_off * 64 * 1024; - adapter->ps_size = ps_size * 64 * 1024; - adapter->native->afu_desc_off = afu_desc_off * 64 * 1024; - adapter->native->afu_desc_size = afu_desc_size * 64 * 1024; - - /* Total IRQs - 1 PSL ERROR - #AFU*(1 slice error + 1 DSI) */ - adapter->user_irqs = pnv_cxl_get_irq_count(dev) - 1 - 2*adapter->slices; - - return 0; -} - -/* - * Workaround a PCIe Host Bridge defect on some cards, that can cause - * malformed Transaction Layer Packet (TLP) errors to be erroneously - * reported. Mask this error in the Uncorrectable Error Mask Register. - * - * The upper nibble of the PSL revision is used to distinguish between - * different cards. The affected ones have it set to 0. - */ -static void cxl_fixup_malformed_tlp(struct cxl *adapter, struct pci_dev *dev) -{ - int aer; - u32 data; - - if (adapter->psl_rev & 0xf000) - return; - if (!(aer = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR))) - return; - pci_read_config_dword(dev, aer + PCI_ERR_UNCOR_MASK, &data); - if (data & PCI_ERR_UNC_MALF_TLP) - if (data & PCI_ERR_UNC_INTN) - return; - data |= PCI_ERR_UNC_MALF_TLP; - data |= PCI_ERR_UNC_INTN; - pci_write_config_dword(dev, aer + PCI_ERR_UNCOR_MASK, data); -} - -static bool cxl_compatible_caia_version(struct cxl *adapter) -{ - if (cxl_is_power8() && (adapter->caia_major == 1)) - return true; - - if (cxl_is_power9() && (adapter->caia_major == 2)) - return true; - - return false; -} - -static int cxl_vsec_looks_ok(struct cxl *adapter, struct pci_dev *dev) -{ - if (adapter->vsec_status & CXL_STATUS_SECOND_PORT) - return -EBUSY; - - if (adapter->vsec_status & CXL_UNSUPPORTED_FEATURES) { - dev_err(&dev->dev, "ABORTING: CXL requires unsupported features\n"); - return -EINVAL; - } - - if (!cxl_compatible_caia_version(adapter)) { - dev_info(&dev->dev, "Ignoring card. PSL type is not supported (caia version: %d)\n", - adapter->caia_major); - return -ENODEV; - } - - if (!adapter->slices) { - /* Once we support dynamic reprogramming we can use the card if - * it supports loadable AFUs */ - dev_err(&dev->dev, "ABORTING: Device has no AFUs\n"); - return -EINVAL; - } - - if (!adapter->native->afu_desc_off || !adapter->native->afu_desc_size) { - dev_err(&dev->dev, "ABORTING: VSEC shows no AFU descriptors\n"); - return -EINVAL; - } - - if (adapter->ps_size > p2_size(dev) - adapter->native->ps_off) { - dev_err(&dev->dev, "ABORTING: Problem state size larger than " - "available in BAR2: 0x%llx > 0x%llx\n", - adapter->ps_size, p2_size(dev) - adapter->native->ps_off); - return -EINVAL; - } - - return 0; -} - -ssize_t cxl_pci_read_adapter_vpd(struct cxl *adapter, void *buf, size_t len) -{ - return pci_read_vpd(to_pci_dev(adapter->dev.parent), 0, len, buf); -} - -static void cxl_release_adapter(struct device *dev) -{ - struct cxl *adapter = to_cxl_adapter(dev); - - pr_devel("cxl_release_adapter\n"); - - cxl_remove_adapter_nr(adapter); - - kfree(adapter->native); - kfree(adapter); -} - -#define CXL_PSL_ErrIVTE_tberror (0x1ull << (63-31)) - -static int sanitise_adapter_regs(struct cxl *adapter) -{ - int rc = 0; - - /* Clear PSL tberror bit by writing 1 to it */ - cxl_p1_write(adapter, CXL_PSL_ErrIVTE, CXL_PSL_ErrIVTE_tberror); - - if (adapter->native->sl_ops->invalidate_all) { - /* do not invalidate ERAT entries when not reloading on PERST */ - if (cxl_is_power9() && (adapter->perst_loads_image)) - return 0; - rc = adapter->native->sl_ops->invalidate_all(adapter); - } - - return rc; -} - -/* This should contain *only* operations that can safely be done in - * both creation and recovery. - */ -static int cxl_configure_adapter(struct cxl *adapter, struct pci_dev *dev) -{ - int rc; - - adapter->dev.parent = &dev->dev; - adapter->dev.release = cxl_release_adapter; - pci_set_drvdata(dev, adapter); - - rc = pci_enable_device(dev); - if (rc) { - dev_err(&dev->dev, "pci_enable_device failed: %i\n", rc); - return rc; - } - - if ((rc = cxl_read_vsec(adapter, dev))) - return rc; - - if ((rc = cxl_vsec_looks_ok(adapter, dev))) - return rc; - - cxl_fixup_malformed_tlp(adapter, dev); - - if ((rc = setup_cxl_bars(dev))) - return rc; - - if ((rc = switch_card_to_cxl(dev))) - return rc; - - if ((rc = cxl_update_image_control(adapter))) - return rc; - - if ((rc = cxl_map_adapter_regs(adapter, dev))) - return rc; - - if ((rc = sanitise_adapter_regs(adapter))) - goto err; - - if ((rc = adapter->native->sl_ops->adapter_regs_init(adapter, dev))) - goto err; - - /* Required for devices using CAPP DMA mode, harmless for others */ - pci_set_master(dev); - - adapter->tunneled_ops_supported = false; - - if (cxl_is_power9()) { - if (pnv_pci_set_tunnel_bar(dev, 0x00020000E0000000ull, 1)) - dev_info(&dev->dev, "Tunneled operations unsupported\n"); - else - adapter->tunneled_ops_supported = true; - } - - if ((rc = pnv_phb_to_cxl_mode(dev, adapter->native->sl_ops->capi_mode))) - goto err; - - /* If recovery happened, the last step is to turn on snooping. - * In the non-recovery case this has no effect */ - if ((rc = pnv_phb_to_cxl_mode(dev, OPAL_PHB_CAPI_MODE_SNOOP_ON))) - goto err; - - /* Ignore error, adapter init is not dependant on timebase sync */ - cxl_setup_psl_timebase(adapter, dev); - - if ((rc = cxl_native_register_psl_err_irq(adapter))) - goto err; - - return 0; - -err: - cxl_unmap_adapter_regs(adapter); - return rc; - -} - -static void cxl_deconfigure_adapter(struct cxl *adapter) -{ - struct pci_dev *pdev = to_pci_dev(adapter->dev.parent); - - if (cxl_is_power9()) - pnv_pci_set_tunnel_bar(pdev, 0x00020000E0000000ull, 0); - - cxl_native_release_psl_err_irq(adapter); - cxl_unmap_adapter_regs(adapter); - - pci_disable_device(pdev); -} - -static void cxl_stop_trace_psl9(struct cxl *adapter) -{ - int traceid; - u64 trace_state, trace_mask; - struct pci_dev *dev = to_pci_dev(adapter->dev.parent); - - /* read each tracearray state and issue mmio to stop them is needed */ - for (traceid = 0; traceid <= CXL_PSL9_TRACEID_MAX; ++traceid) { - trace_state = cxl_p1_read(adapter, CXL_PSL9_CTCCFG); - trace_mask = (0x3ULL << (62 - traceid * 2)); - trace_state = (trace_state & trace_mask) >> (62 - traceid * 2); - dev_dbg(&dev->dev, "cxl: Traceid-%d trace_state=0x%0llX\n", - traceid, trace_state); - - /* issue mmio if the trace array isn't in FIN state */ - if (trace_state != CXL_PSL9_TRACESTATE_FIN) - cxl_p1_write(adapter, CXL_PSL9_TRACECFG, - 0x8400000000000000ULL | traceid); - } -} - -static void cxl_stop_trace_psl8(struct cxl *adapter) -{ - int slice; - - /* Stop the trace */ - cxl_p1_write(adapter, CXL_PSL_TRACE, 0x8000000000000017LL); - - /* Stop the slice traces */ - spin_lock(&adapter->afu_list_lock); - for (slice = 0; slice < adapter->slices; slice++) { - if (adapter->afu[slice]) - cxl_p1n_write(adapter->afu[slice], CXL_PSL_SLICE_TRACE, - 0x8000000000000000LL); - } - spin_unlock(&adapter->afu_list_lock); -} - -static const struct cxl_service_layer_ops psl9_ops = { - .adapter_regs_init = init_implementation_adapter_regs_psl9, - .invalidate_all = cxl_invalidate_all_psl9, - .afu_regs_init = init_implementation_afu_regs_psl9, - .sanitise_afu_regs = sanitise_afu_regs_psl9, - .register_serr_irq = cxl_native_register_serr_irq, - .release_serr_irq = cxl_native_release_serr_irq, - .handle_interrupt = cxl_irq_psl9, - .fail_irq = cxl_fail_irq_psl, - .activate_dedicated_process = cxl_activate_dedicated_process_psl9, - .attach_afu_directed = cxl_attach_afu_directed_psl9, - .attach_dedicated_process = cxl_attach_dedicated_process_psl9, - .update_dedicated_ivtes = cxl_update_dedicated_ivtes_psl9, - .debugfs_add_adapter_regs = cxl_debugfs_add_adapter_regs_psl9, - .debugfs_add_afu_regs = cxl_debugfs_add_afu_regs_psl9, - .psl_irq_dump_registers = cxl_native_irq_dump_regs_psl9, - .err_irq_dump_registers = cxl_native_err_irq_dump_regs_psl9, - .debugfs_stop_trace = cxl_stop_trace_psl9, - .timebase_read = timebase_read_psl9, - .capi_mode = OPAL_PHB_CAPI_MODE_CAPI, - .needs_reset_before_disable = true, -}; - -static const struct cxl_service_layer_ops psl8_ops = { - .adapter_regs_init = init_implementation_adapter_regs_psl8, - .invalidate_all = cxl_invalidate_all_psl8, - .afu_regs_init = init_implementation_afu_regs_psl8, - .sanitise_afu_regs = sanitise_afu_regs_psl8, - .register_serr_irq = cxl_native_register_serr_irq, - .release_serr_irq = cxl_native_release_serr_irq, - .handle_interrupt = cxl_irq_psl8, - .fail_irq = cxl_fail_irq_psl, - .activate_dedicated_process = cxl_activate_dedicated_process_psl8, - .attach_afu_directed = cxl_attach_afu_directed_psl8, - .attach_dedicated_process = cxl_attach_dedicated_process_psl8, - .update_dedicated_ivtes = cxl_update_dedicated_ivtes_psl8, - .debugfs_add_adapter_regs = cxl_debugfs_add_adapter_regs_psl8, - .debugfs_add_afu_regs = cxl_debugfs_add_afu_regs_psl8, - .psl_irq_dump_registers = cxl_native_irq_dump_regs_psl8, - .err_irq_dump_registers = cxl_native_err_irq_dump_regs_psl8, - .debugfs_stop_trace = cxl_stop_trace_psl8, - .write_timebase_ctrl = write_timebase_ctrl_psl8, - .timebase_read = timebase_read_psl8, - .capi_mode = OPAL_PHB_CAPI_MODE_CAPI, - .needs_reset_before_disable = true, -}; - -static void set_sl_ops(struct cxl *adapter, struct pci_dev *dev) -{ - if (cxl_is_power8()) { - dev_info(&dev->dev, "Device uses a PSL8\n"); - adapter->native->sl_ops = &psl8_ops; - } else { - dev_info(&dev->dev, "Device uses a PSL9\n"); - adapter->native->sl_ops = &psl9_ops; - } -} - - -static struct cxl *cxl_pci_init_adapter(struct pci_dev *dev) -{ - struct cxl *adapter; - int rc; - - adapter = cxl_alloc_adapter(); - if (!adapter) - return ERR_PTR(-ENOMEM); - - adapter->native = kzalloc(sizeof(struct cxl_native), GFP_KERNEL); - if (!adapter->native) { - rc = -ENOMEM; - goto err_release; - } - - set_sl_ops(adapter, dev); - - /* Set defaults for parameters which need to persist over - * configure/reconfigure - */ - adapter->perst_loads_image = true; - adapter->perst_same_image = false; - - rc = cxl_configure_adapter(adapter, dev); - if (rc) { - pci_disable_device(dev); - goto err_release; - } - - /* Don't care if this one fails: */ - cxl_debugfs_adapter_add(adapter); - - /* - * After we call this function we must not free the adapter directly, - * even if it returns an error! - */ - if ((rc = cxl_register_adapter(adapter))) - goto err_put_dev; - - if ((rc = cxl_sysfs_adapter_add(adapter))) - goto err_del_dev; - - /* Release the context lock as adapter is configured */ - cxl_adapter_context_unlock(adapter); - - return adapter; - -err_del_dev: - device_del(&adapter->dev); -err_put_dev: - /* This should mirror cxl_remove_adapter, except without the - * sysfs parts - */ - cxl_debugfs_adapter_remove(adapter); - cxl_deconfigure_adapter(adapter); - put_device(&adapter->dev); - return ERR_PTR(rc); - -err_release: - cxl_release_adapter(&adapter->dev); - return ERR_PTR(rc); -} - -static void cxl_pci_remove_adapter(struct cxl *adapter) -{ - pr_devel("cxl_remove_adapter\n"); - - cxl_sysfs_adapter_remove(adapter); - cxl_debugfs_adapter_remove(adapter); - - /* - * Flush adapter datacache as its about to be removed. - */ - cxl_data_cache_flush(adapter); - - cxl_deconfigure_adapter(adapter); - - device_unregister(&adapter->dev); -} - -#define CXL_MAX_PCIEX_PARENT 2 - -int cxl_slot_is_switched(struct pci_dev *dev) -{ - struct device_node *np; - int depth = 0; - - if (!(np = pci_device_to_OF_node(dev))) { - pr_err("cxl: np = NULL\n"); - return -ENODEV; - } - of_node_get(np); - while (np) { - np = of_get_next_parent(np); - if (!of_node_is_type(np, "pciex")) - break; - depth++; - } - of_node_put(np); - return (depth > CXL_MAX_PCIEX_PARENT); -} - -static int cxl_probe(struct pci_dev *dev, const struct pci_device_id *id) -{ - struct cxl *adapter; - int slice; - int rc; - - dev_err_once(&dev->dev, "DEPRECATED: cxl is deprecated and will be removed in a future kernel release\n"); - - if (cxl_pci_is_vphb_device(dev)) { - dev_dbg(&dev->dev, "cxl_init_adapter: Ignoring cxl vphb device\n"); - return -ENODEV; - } - - if (cxl_slot_is_switched(dev)) { - dev_info(&dev->dev, "Ignoring card on incompatible PCI slot\n"); - return -ENODEV; - } - - if (cxl_is_power9() && !radix_enabled()) { - dev_info(&dev->dev, "Only Radix mode supported\n"); - return -ENODEV; - } - - if (cxl_verbose) - dump_cxl_config_space(dev); - - adapter = cxl_pci_init_adapter(dev); - if (IS_ERR(adapter)) { - dev_err(&dev->dev, "cxl_init_adapter failed: %li\n", PTR_ERR(adapter)); - return PTR_ERR(adapter); - } - - for (slice = 0; slice < adapter->slices; slice++) { - if ((rc = pci_init_afu(adapter, slice, dev))) { - dev_err(&dev->dev, "AFU %i failed to initialise: %i\n", slice, rc); - continue; - } - - rc = cxl_afu_select_best_mode(adapter->afu[slice]); - if (rc) - dev_err(&dev->dev, "AFU %i failed to start: %i\n", slice, rc); - } - - return 0; -} - -static void cxl_remove(struct pci_dev *dev) -{ - struct cxl *adapter = pci_get_drvdata(dev); - struct cxl_afu *afu; - int i; - - /* - * Lock to prevent someone grabbing a ref through the adapter list as - * we are removing it - */ - for (i = 0; i < adapter->slices; i++) { - afu = adapter->afu[i]; - cxl_pci_remove_afu(afu); - } - cxl_pci_remove_adapter(adapter); -} - -static pci_ers_result_t cxl_vphb_error_detected(struct cxl_afu *afu, - pci_channel_state_t state) -{ - struct pci_dev *afu_dev; - struct pci_driver *afu_drv; - const struct pci_error_handlers *err_handler; - pci_ers_result_t result = PCI_ERS_RESULT_NEED_RESET; - pci_ers_result_t afu_result = PCI_ERS_RESULT_NEED_RESET; - - /* There should only be one entry, but go through the list - * anyway - */ - if (afu == NULL || afu->phb == NULL) - return result; - - list_for_each_entry(afu_dev, &afu->phb->bus->devices, bus_list) { - afu_drv = to_pci_driver(afu_dev->dev.driver); - if (!afu_drv) - continue; - - afu_dev->error_state = state; - - err_handler = afu_drv->err_handler; - if (err_handler) - afu_result = err_handler->error_detected(afu_dev, - state); - /* Disconnect trumps all, NONE trumps NEED_RESET */ - if (afu_result == PCI_ERS_RESULT_DISCONNECT) - result = PCI_ERS_RESULT_DISCONNECT; - else if ((afu_result == PCI_ERS_RESULT_NONE) && - (result == PCI_ERS_RESULT_NEED_RESET)) - result = PCI_ERS_RESULT_NONE; - } - return result; -} - -static pci_ers_result_t cxl_pci_error_detected(struct pci_dev *pdev, - pci_channel_state_t state) -{ - struct cxl *adapter = pci_get_drvdata(pdev); - struct cxl_afu *afu; - pci_ers_result_t result = PCI_ERS_RESULT_NEED_RESET; - pci_ers_result_t afu_result = PCI_ERS_RESULT_NEED_RESET; - int i; - - /* At this point, we could still have an interrupt pending. - * Let's try to get them out of the way before they do - * anything we don't like. - */ - schedule(); - - /* If we're permanently dead, give up. */ - if (state == pci_channel_io_perm_failure) { - spin_lock(&adapter->afu_list_lock); - for (i = 0; i < adapter->slices; i++) { - afu = adapter->afu[i]; - /* - * Tell the AFU drivers; but we don't care what they - * say, we're going away. - */ - cxl_vphb_error_detected(afu, state); - } - spin_unlock(&adapter->afu_list_lock); - return PCI_ERS_RESULT_DISCONNECT; - } - - /* Are we reflashing? - * - * If we reflash, we could come back as something entirely - * different, including a non-CAPI card. As such, by default - * we don't participate in the process. We'll be unbound and - * the slot re-probed. (TODO: check EEH doesn't blindly rebind - * us!) - * - * However, this isn't the entire story: for reliablity - * reasons, we usually want to reflash the FPGA on PERST in - * order to get back to a more reliable known-good state. - * - * This causes us a bit of a problem: if we reflash we can't - * trust that we'll come back the same - we could have a new - * image and been PERSTed in order to load that - * image. However, most of the time we actually *will* come - * back the same - for example a regular EEH event. - * - * Therefore, we allow the user to assert that the image is - * indeed the same and that we should continue on into EEH - * anyway. - */ - if (adapter->perst_loads_image && !adapter->perst_same_image) { - /* TODO take the PHB out of CXL mode */ - dev_info(&pdev->dev, "reflashing, so opting out of EEH!\n"); - return PCI_ERS_RESULT_NONE; - } - - /* - * At this point, we want to try to recover. We'll always - * need a complete slot reset: we don't trust any other reset. - * - * Now, we go through each AFU: - * - We send the driver, if bound, an error_detected callback. - * We expect it to clean up, but it can also tell us to give - * up and permanently detach the card. To simplify things, if - * any bound AFU driver doesn't support EEH, we give up on EEH. - * - * - We detach all contexts associated with the AFU. This - * does not free them, but puts them into a CLOSED state - * which causes any the associated files to return useful - * errors to userland. It also unmaps, but does not free, - * any IRQs. - * - * - We clean up our side: releasing and unmapping resources we hold - * so we can wire them up again when the hardware comes back up. - * - * Driver authors should note: - * - * - Any contexts you create in your kernel driver (except - * those associated with anonymous file descriptors) are - * your responsibility to free and recreate. Likewise with - * any attached resources. - * - * - We will take responsibility for re-initialising the - * device context (the one set up for you in - * cxl_pci_enable_device_hook and accessed through - * cxl_get_context). If you've attached IRQs or other - * resources to it, they remains yours to free. - * - * You can call the same functions to release resources as you - * normally would: we make sure that these functions continue - * to work when the hardware is down. - * - * Two examples: - * - * 1) If you normally free all your resources at the end of - * each request, or if you use anonymous FDs, your - * error_detected callback can simply set a flag to tell - * your driver not to start any new calls. You can then - * clear the flag in the resume callback. - * - * 2) If you normally allocate your resources on startup: - * * Set a flag in error_detected as above. - * * Let CXL detach your contexts. - * * In slot_reset, free the old resources and allocate new ones. - * * In resume, clear the flag to allow things to start. - */ - - /* Make sure no one else changes the afu list */ - spin_lock(&adapter->afu_list_lock); - - for (i = 0; i < adapter->slices; i++) { - afu = adapter->afu[i]; - - if (afu == NULL) - continue; - - afu_result = cxl_vphb_error_detected(afu, state); - cxl_context_detach_all(afu); - cxl_ops->afu_deactivate_mode(afu, afu->current_mode); - pci_deconfigure_afu(afu); - - /* Disconnect trumps all, NONE trumps NEED_RESET */ - if (afu_result == PCI_ERS_RESULT_DISCONNECT) - result = PCI_ERS_RESULT_DISCONNECT; - else if ((afu_result == PCI_ERS_RESULT_NONE) && - (result == PCI_ERS_RESULT_NEED_RESET)) - result = PCI_ERS_RESULT_NONE; - } - spin_unlock(&adapter->afu_list_lock); - - /* should take the context lock here */ - if (cxl_adapter_context_lock(adapter) != 0) - dev_warn(&adapter->dev, - "Couldn't take context lock with %d active-contexts\n", - atomic_read(&adapter->contexts_num)); - - cxl_deconfigure_adapter(adapter); - - return result; -} - -static pci_ers_result_t cxl_pci_slot_reset(struct pci_dev *pdev) -{ - struct cxl *adapter = pci_get_drvdata(pdev); - struct cxl_afu *afu; - struct cxl_context *ctx; - struct pci_dev *afu_dev; - struct pci_driver *afu_drv; - const struct pci_error_handlers *err_handler; - pci_ers_result_t afu_result = PCI_ERS_RESULT_RECOVERED; - pci_ers_result_t result = PCI_ERS_RESULT_RECOVERED; - int i; - - if (cxl_configure_adapter(adapter, pdev)) - goto err; - - /* - * Unlock context activation for the adapter. Ideally this should be - * done in cxl_pci_resume but cxlflash module tries to activate the - * master context as part of slot_reset callback. - */ - cxl_adapter_context_unlock(adapter); - - spin_lock(&adapter->afu_list_lock); - for (i = 0; i < adapter->slices; i++) { - afu = adapter->afu[i]; - - if (afu == NULL) - continue; - - if (pci_configure_afu(afu, adapter, pdev)) - goto err_unlock; - - if (cxl_afu_select_best_mode(afu)) - goto err_unlock; - - if (afu->phb == NULL) - continue; - - list_for_each_entry(afu_dev, &afu->phb->bus->devices, bus_list) { - /* Reset the device context. - * TODO: make this less disruptive - */ - ctx = cxl_get_context(afu_dev); - - if (ctx && cxl_release_context(ctx)) - goto err_unlock; - - ctx = cxl_dev_context_init(afu_dev); - if (IS_ERR(ctx)) - goto err_unlock; - - afu_dev->dev.archdata.cxl_ctx = ctx; - - if (cxl_ops->afu_check_and_enable(afu)) - goto err_unlock; - - afu_dev->error_state = pci_channel_io_normal; - - /* If there's a driver attached, allow it to - * chime in on recovery. Drivers should check - * if everything has come back OK, but - * shouldn't start new work until we call - * their resume function. - */ - afu_drv = to_pci_driver(afu_dev->dev.driver); - if (!afu_drv) - continue; - - err_handler = afu_drv->err_handler; - if (err_handler && err_handler->slot_reset) - afu_result = err_handler->slot_reset(afu_dev); - - if (afu_result == PCI_ERS_RESULT_DISCONNECT) - result = PCI_ERS_RESULT_DISCONNECT; - } - } - - spin_unlock(&adapter->afu_list_lock); - return result; - -err_unlock: - spin_unlock(&adapter->afu_list_lock); - -err: - /* All the bits that happen in both error_detected and cxl_remove - * should be idempotent, so we don't need to worry about leaving a mix - * of unconfigured and reconfigured resources. - */ - dev_err(&pdev->dev, "EEH recovery failed. Asking to be disconnected.\n"); - return PCI_ERS_RESULT_DISCONNECT; -} - -static void cxl_pci_resume(struct pci_dev *pdev) -{ - struct cxl *adapter = pci_get_drvdata(pdev); - struct cxl_afu *afu; - struct pci_dev *afu_dev; - struct pci_driver *afu_drv; - const struct pci_error_handlers *err_handler; - int i; - - /* Everything is back now. Drivers should restart work now. - * This is not the place to be checking if everything came back up - * properly, because there's no return value: do that in slot_reset. - */ - spin_lock(&adapter->afu_list_lock); - for (i = 0; i < adapter->slices; i++) { - afu = adapter->afu[i]; - - if (afu == NULL || afu->phb == NULL) - continue; - - list_for_each_entry(afu_dev, &afu->phb->bus->devices, bus_list) { - afu_drv = to_pci_driver(afu_dev->dev.driver); - if (!afu_drv) - continue; - - err_handler = afu_drv->err_handler; - if (err_handler && err_handler->resume) - err_handler->resume(afu_dev); - } - } - spin_unlock(&adapter->afu_list_lock); -} - -static const struct pci_error_handlers cxl_err_handler = { - .error_detected = cxl_pci_error_detected, - .slot_reset = cxl_pci_slot_reset, - .resume = cxl_pci_resume, -}; - -struct pci_driver cxl_pci_driver = { - .name = "cxl-pci", - .id_table = cxl_pci_tbl, - .probe = cxl_probe, - .remove = cxl_remove, - .shutdown = cxl_remove, - .err_handler = &cxl_err_handler, -};
diff --git a/drivers/misc/cxl/sysfs.c b/drivers/misc/cxl/sysfs.c deleted file mode 100644 index b1fc644..0000000 --- a/drivers/misc/cxl/sysfs.c +++ /dev/null
@@ -1,771 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Copyright 2014 IBM Corp. - */ - -#include <linux/kernel.h> -#include <linux/device.h> -#include <linux/sysfs.h> -#include <linux/pci_regs.h> - -#include "cxl.h" - -#define to_afu_chardev_m(d) dev_get_drvdata(d) - -/********* Adapter attributes **********************************************/ - -static ssize_t caia_version_show(struct device *device, - struct device_attribute *attr, - char *buf) -{ - struct cxl *adapter = to_cxl_adapter(device); - - return scnprintf(buf, PAGE_SIZE, "%i.%i\n", adapter->caia_major, - adapter->caia_minor); -} - -static ssize_t psl_revision_show(struct device *device, - struct device_attribute *attr, - char *buf) -{ - struct cxl *adapter = to_cxl_adapter(device); - - return scnprintf(buf, PAGE_SIZE, "%i\n", adapter->psl_rev); -} - -static ssize_t base_image_show(struct device *device, - struct device_attribute *attr, - char *buf) -{ - struct cxl *adapter = to_cxl_adapter(device); - - return scnprintf(buf, PAGE_SIZE, "%i\n", adapter->base_image); -} - -static ssize_t image_loaded_show(struct device *device, - struct device_attribute *attr, - char *buf) -{ - struct cxl *adapter = to_cxl_adapter(device); - - if (adapter->user_image_loaded) - return scnprintf(buf, PAGE_SIZE, "user\n"); - return scnprintf(buf, PAGE_SIZE, "factory\n"); -} - -static ssize_t psl_timebase_synced_show(struct device *device, - struct device_attribute *attr, - char *buf) -{ - struct cxl *adapter = to_cxl_adapter(device); - u64 psl_tb, delta; - - /* Recompute the status only in native mode */ - if (cpu_has_feature(CPU_FTR_HVMODE)) { - psl_tb = adapter->native->sl_ops->timebase_read(adapter); - delta = abs(mftb() - psl_tb); - - /* CORE TB and PSL TB difference <= 16usecs ? */ - adapter->psl_timebase_synced = (tb_to_ns(delta) < 16000) ? true : false; - pr_devel("PSL timebase %s - delta: 0x%016llx\n", - (tb_to_ns(delta) < 16000) ? "synchronized" : - "not synchronized", tb_to_ns(delta)); - } - return scnprintf(buf, PAGE_SIZE, "%i\n", adapter->psl_timebase_synced); -} - -static ssize_t tunneled_ops_supported_show(struct device *device, - struct device_attribute *attr, - char *buf) -{ - struct cxl *adapter = to_cxl_adapter(device); - - return scnprintf(buf, PAGE_SIZE, "%i\n", adapter->tunneled_ops_supported); -} - -static ssize_t reset_adapter_store(struct device *device, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct cxl *adapter = to_cxl_adapter(device); - int rc; - int val; - - rc = sscanf(buf, "%i", &val); - if ((rc != 1) || (val != 1 && val != -1)) - return -EINVAL; - - /* - * See if we can lock the context mapping that's only allowed - * when there are no contexts attached to the adapter. Once - * taken this will also prevent any context from getting activated. - */ - if (val == 1) { - rc = cxl_adapter_context_lock(adapter); - if (rc) - goto out; - - rc = cxl_ops->adapter_reset(adapter); - /* In case reset failed release context lock */ - if (rc) - cxl_adapter_context_unlock(adapter); - - } else if (val == -1) { - /* Perform a forced adapter reset */ - rc = cxl_ops->adapter_reset(adapter); - } - -out: - return rc ? rc : count; -} - -static ssize_t load_image_on_perst_show(struct device *device, - struct device_attribute *attr, - char *buf) -{ - struct cxl *adapter = to_cxl_adapter(device); - - if (!adapter->perst_loads_image) - return scnprintf(buf, PAGE_SIZE, "none\n"); - - if (adapter->perst_select_user) - return scnprintf(buf, PAGE_SIZE, "user\n"); - return scnprintf(buf, PAGE_SIZE, "factory\n"); -} - -static ssize_t load_image_on_perst_store(struct device *device, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct cxl *adapter = to_cxl_adapter(device); - int rc; - - if (!strncmp(buf, "none", 4)) - adapter->perst_loads_image = false; - else if (!strncmp(buf, "user", 4)) { - adapter->perst_select_user = true; - adapter->perst_loads_image = true; - } else if (!strncmp(buf, "factory", 7)) { - adapter->perst_select_user = false; - adapter->perst_loads_image = true; - } else - return -EINVAL; - - if ((rc = cxl_update_image_control(adapter))) - return rc; - - return count; -} - -static ssize_t perst_reloads_same_image_show(struct device *device, - struct device_attribute *attr, - char *buf) -{ - struct cxl *adapter = to_cxl_adapter(device); - - return scnprintf(buf, PAGE_SIZE, "%i\n", adapter->perst_same_image); -} - -static ssize_t perst_reloads_same_image_store(struct device *device, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct cxl *adapter = to_cxl_adapter(device); - int rc; - int val; - - rc = sscanf(buf, "%i", &val); - if ((rc != 1) || !(val == 1 || val == 0)) - return -EINVAL; - - adapter->perst_same_image = (val == 1); - return count; -} - -static struct device_attribute adapter_attrs[] = { - __ATTR_RO(caia_version), - __ATTR_RO(psl_revision), - __ATTR_RO(base_image), - __ATTR_RO(image_loaded), - __ATTR_RO(psl_timebase_synced), - __ATTR_RO(tunneled_ops_supported), - __ATTR_RW(load_image_on_perst), - __ATTR_RW(perst_reloads_same_image), - __ATTR(reset, S_IWUSR, NULL, reset_adapter_store), -}; - - -/********* AFU master specific attributes **********************************/ - -static ssize_t mmio_size_show_master(struct device *device, - struct device_attribute *attr, - char *buf) -{ - struct cxl_afu *afu = to_afu_chardev_m(device); - - return scnprintf(buf, PAGE_SIZE, "%llu\n", afu->adapter->ps_size); -} - -static ssize_t pp_mmio_off_show(struct device *device, - struct device_attribute *attr, - char *buf) -{ - struct cxl_afu *afu = to_afu_chardev_m(device); - - return scnprintf(buf, PAGE_SIZE, "%llu\n", afu->native->pp_offset); -} - -static ssize_t pp_mmio_len_show(struct device *device, - struct device_attribute *attr, - char *buf) -{ - struct cxl_afu *afu = to_afu_chardev_m(device); - - return scnprintf(buf, PAGE_SIZE, "%llu\n", afu->pp_size); -} - -static struct device_attribute afu_master_attrs[] = { - __ATTR(mmio_size, S_IRUGO, mmio_size_show_master, NULL), - __ATTR_RO(pp_mmio_off), - __ATTR_RO(pp_mmio_len), -}; - - -/********* AFU attributes **************************************************/ - -static ssize_t mmio_size_show(struct device *device, - struct device_attribute *attr, - char *buf) -{ - struct cxl_afu *afu = to_cxl_afu(device); - - if (afu->pp_size) - return scnprintf(buf, PAGE_SIZE, "%llu\n", afu->pp_size); - return scnprintf(buf, PAGE_SIZE, "%llu\n", afu->adapter->ps_size); -} - -static ssize_t reset_store_afu(struct device *device, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct cxl_afu *afu = to_cxl_afu(device); - int rc; - - /* Not safe to reset if it is currently in use */ - mutex_lock(&afu->contexts_lock); - if (!idr_is_empty(&afu->contexts_idr)) { - rc = -EBUSY; - goto err; - } - - if ((rc = cxl_ops->afu_reset(afu))) - goto err; - - rc = count; -err: - mutex_unlock(&afu->contexts_lock); - return rc; -} - -static ssize_t irqs_min_show(struct device *device, - struct device_attribute *attr, - char *buf) -{ - struct cxl_afu *afu = to_cxl_afu(device); - - return scnprintf(buf, PAGE_SIZE, "%i\n", afu->pp_irqs); -} - -static ssize_t irqs_max_show(struct device *device, - struct device_attribute *attr, - char *buf) -{ - struct cxl_afu *afu = to_cxl_afu(device); - - return scnprintf(buf, PAGE_SIZE, "%i\n", afu->irqs_max); -} - -static ssize_t irqs_max_store(struct device *device, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct cxl_afu *afu = to_cxl_afu(device); - ssize_t ret; - int irqs_max; - - ret = sscanf(buf, "%i", &irqs_max); - if (ret != 1) - return -EINVAL; - - if (irqs_max < afu->pp_irqs) - return -EINVAL; - - if (cpu_has_feature(CPU_FTR_HVMODE)) { - if (irqs_max > afu->adapter->user_irqs) - return -EINVAL; - } else { - /* pHyp sets a per-AFU limit */ - if (irqs_max > afu->guest->max_ints) - return -EINVAL; - } - - afu->irqs_max = irqs_max; - return count; -} - -static ssize_t modes_supported_show(struct device *device, - struct device_attribute *attr, char *buf) -{ - struct cxl_afu *afu = to_cxl_afu(device); - char *p = buf, *end = buf + PAGE_SIZE; - - if (afu->modes_supported & CXL_MODE_DEDICATED) - p += scnprintf(p, end - p, "dedicated_process\n"); - if (afu->modes_supported & CXL_MODE_DIRECTED) - p += scnprintf(p, end - p, "afu_directed\n"); - return (p - buf); -} - -static ssize_t prefault_mode_show(struct device *device, - struct device_attribute *attr, - char *buf) -{ - struct cxl_afu *afu = to_cxl_afu(device); - - switch (afu->prefault_mode) { - case CXL_PREFAULT_WED: - return scnprintf(buf, PAGE_SIZE, "work_element_descriptor\n"); - case CXL_PREFAULT_ALL: - return scnprintf(buf, PAGE_SIZE, "all\n"); - default: - return scnprintf(buf, PAGE_SIZE, "none\n"); - } -} - -static ssize_t prefault_mode_store(struct device *device, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct cxl_afu *afu = to_cxl_afu(device); - enum prefault_modes mode = -1; - - if (!strncmp(buf, "none", 4)) - mode = CXL_PREFAULT_NONE; - else { - if (!radix_enabled()) { - - /* only allowed when not in radix mode */ - if (!strncmp(buf, "work_element_descriptor", 23)) - mode = CXL_PREFAULT_WED; - if (!strncmp(buf, "all", 3)) - mode = CXL_PREFAULT_ALL; - } else { - dev_err(device, "Cannot prefault with radix enabled\n"); - } - } - - if (mode == -1) - return -EINVAL; - - afu->prefault_mode = mode; - return count; -} - -static ssize_t mode_show(struct device *device, - struct device_attribute *attr, - char *buf) -{ - struct cxl_afu *afu = to_cxl_afu(device); - - if (afu->current_mode == CXL_MODE_DEDICATED) - return scnprintf(buf, PAGE_SIZE, "dedicated_process\n"); - if (afu->current_mode == CXL_MODE_DIRECTED) - return scnprintf(buf, PAGE_SIZE, "afu_directed\n"); - return scnprintf(buf, PAGE_SIZE, "none\n"); -} - -static ssize_t mode_store(struct device *device, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct cxl_afu *afu = to_cxl_afu(device); - int old_mode, mode = -1; - int rc = -EBUSY; - - /* can't change this if we have a user */ - mutex_lock(&afu->contexts_lock); - if (!idr_is_empty(&afu->contexts_idr)) - goto err; - - if (!strncmp(buf, "dedicated_process", 17)) - mode = CXL_MODE_DEDICATED; - if (!strncmp(buf, "afu_directed", 12)) - mode = CXL_MODE_DIRECTED; - if (!strncmp(buf, "none", 4)) - mode = 0; - - if (mode == -1) { - rc = -EINVAL; - goto err; - } - - /* - * afu_deactivate_mode needs to be done outside the lock, prevent - * other contexts coming in before we are ready: - */ - old_mode = afu->current_mode; - afu->current_mode = 0; - afu->num_procs = 0; - - mutex_unlock(&afu->contexts_lock); - - if ((rc = cxl_ops->afu_deactivate_mode(afu, old_mode))) - return rc; - if ((rc = cxl_ops->afu_activate_mode(afu, mode))) - return rc; - - return count; -err: - mutex_unlock(&afu->contexts_lock); - return rc; -} - -static ssize_t api_version_show(struct device *device, - struct device_attribute *attr, - char *buf) -{ - return scnprintf(buf, PAGE_SIZE, "%i\n", CXL_API_VERSION); -} - -static ssize_t api_version_compatible_show(struct device *device, - struct device_attribute *attr, - char *buf) -{ - return scnprintf(buf, PAGE_SIZE, "%i\n", CXL_API_VERSION_COMPATIBLE); -} - -static ssize_t afu_eb_read(struct file *filp, struct kobject *kobj, - const struct bin_attribute *bin_attr, char *buf, - loff_t off, size_t count) -{ - struct cxl_afu *afu = to_cxl_afu(kobj_to_dev(kobj)); - - return cxl_ops->afu_read_err_buffer(afu, buf, off, count); -} - -static struct device_attribute afu_attrs[] = { - __ATTR_RO(mmio_size), - __ATTR_RO(irqs_min), - __ATTR_RW(irqs_max), - __ATTR_RO(modes_supported), - __ATTR_RW(mode), - __ATTR_RW(prefault_mode), - __ATTR_RO(api_version), - __ATTR_RO(api_version_compatible), - __ATTR(reset, S_IWUSR, NULL, reset_store_afu), -}; - -int cxl_sysfs_adapter_add(struct cxl *adapter) -{ - struct device_attribute *dev_attr; - int i, rc; - - for (i = 0; i < ARRAY_SIZE(adapter_attrs); i++) { - dev_attr = &adapter_attrs[i]; - if (cxl_ops->support_attributes(dev_attr->attr.name, - CXL_ADAPTER_ATTRS)) { - if ((rc = device_create_file(&adapter->dev, dev_attr))) - goto err; - } - } - return 0; -err: - for (i--; i >= 0; i--) { - dev_attr = &adapter_attrs[i]; - if (cxl_ops->support_attributes(dev_attr->attr.name, - CXL_ADAPTER_ATTRS)) - device_remove_file(&adapter->dev, dev_attr); - } - return rc; -} - -void cxl_sysfs_adapter_remove(struct cxl *adapter) -{ - struct device_attribute *dev_attr; - int i; - - for (i = 0; i < ARRAY_SIZE(adapter_attrs); i++) { - dev_attr = &adapter_attrs[i]; - if (cxl_ops->support_attributes(dev_attr->attr.name, - CXL_ADAPTER_ATTRS)) - device_remove_file(&adapter->dev, dev_attr); - } -} - -struct afu_config_record { - struct kobject kobj; - struct bin_attribute config_attr; - struct list_head list; - int cr; - u16 device; - u16 vendor; - u32 class; -}; - -#define to_cr(obj) container_of(obj, struct afu_config_record, kobj) - -static ssize_t vendor_show(struct kobject *kobj, - struct kobj_attribute *attr, char *buf) -{ - struct afu_config_record *cr = to_cr(kobj); - - return scnprintf(buf, PAGE_SIZE, "0x%.4x\n", cr->vendor); -} - -static ssize_t device_show(struct kobject *kobj, - struct kobj_attribute *attr, char *buf) -{ - struct afu_config_record *cr = to_cr(kobj); - - return scnprintf(buf, PAGE_SIZE, "0x%.4x\n", cr->device); -} - -static ssize_t class_show(struct kobject *kobj, - struct kobj_attribute *attr, char *buf) -{ - struct afu_config_record *cr = to_cr(kobj); - - return scnprintf(buf, PAGE_SIZE, "0x%.6x\n", cr->class); -} - -static ssize_t afu_read_config(struct file *filp, struct kobject *kobj, - const struct bin_attribute *bin_attr, char *buf, - loff_t off, size_t count) -{ - struct afu_config_record *cr = to_cr(kobj); - struct cxl_afu *afu = to_cxl_afu(kobj_to_dev(kobj->parent)); - - u64 i, j, val, rc; - - for (i = 0; i < count;) { - rc = cxl_ops->afu_cr_read64(afu, cr->cr, off & ~0x7, &val); - if (rc) - val = ~0ULL; - for (j = off & 0x7; j < 8 && i < count; i++, j++, off++) - buf[i] = (val >> (j * 8)) & 0xff; - } - - return count; -} - -static struct kobj_attribute vendor_attribute = - __ATTR_RO(vendor); -static struct kobj_attribute device_attribute = - __ATTR_RO(device); -static struct kobj_attribute class_attribute = - __ATTR_RO(class); - -static struct attribute *afu_cr_attrs[] = { - &vendor_attribute.attr, - &device_attribute.attr, - &class_attribute.attr, - NULL, -}; -ATTRIBUTE_GROUPS(afu_cr); - -static void release_afu_config_record(struct kobject *kobj) -{ - struct afu_config_record *cr = to_cr(kobj); - - kfree(cr); -} - -static const struct kobj_type afu_config_record_type = { - .sysfs_ops = &kobj_sysfs_ops, - .release = release_afu_config_record, - .default_groups = afu_cr_groups, -}; - -static struct afu_config_record *cxl_sysfs_afu_new_cr(struct cxl_afu *afu, int cr_idx) -{ - struct afu_config_record *cr; - int rc; - - cr = kzalloc(sizeof(struct afu_config_record), GFP_KERNEL); - if (!cr) - return ERR_PTR(-ENOMEM); - - cr->cr = cr_idx; - - rc = cxl_ops->afu_cr_read16(afu, cr_idx, PCI_DEVICE_ID, &cr->device); - if (rc) - goto err; - rc = cxl_ops->afu_cr_read16(afu, cr_idx, PCI_VENDOR_ID, &cr->vendor); - if (rc) - goto err; - rc = cxl_ops->afu_cr_read32(afu, cr_idx, PCI_CLASS_REVISION, &cr->class); - if (rc) - goto err; - cr->class >>= 8; - - /* - * Export raw AFU PCIe like config record. For now this is read only by - * root - we can expand that later to be readable by non-root and maybe - * even writable provided we have a good use-case. Once we support - * exposing AFUs through a virtual PHB they will get that for free from - * Linux' PCI infrastructure, but until then it's not clear that we - * need it for anything since the main use case is just identifying - * AFUs, which can be done via the vendor, device and class attributes. - */ - sysfs_bin_attr_init(&cr->config_attr); - cr->config_attr.attr.name = "config"; - cr->config_attr.attr.mode = S_IRUSR; - cr->config_attr.size = afu->crs_len; - cr->config_attr.read_new = afu_read_config; - - rc = kobject_init_and_add(&cr->kobj, &afu_config_record_type, - &afu->dev.kobj, "cr%i", cr->cr); - if (rc) - goto err1; - - rc = sysfs_create_bin_file(&cr->kobj, &cr->config_attr); - if (rc) - goto err1; - - rc = kobject_uevent(&cr->kobj, KOBJ_ADD); - if (rc) - goto err2; - - return cr; -err2: - sysfs_remove_bin_file(&cr->kobj, &cr->config_attr); -err1: - kobject_put(&cr->kobj); - return ERR_PTR(rc); -err: - kfree(cr); - return ERR_PTR(rc); -} - -void cxl_sysfs_afu_remove(struct cxl_afu *afu) -{ - struct device_attribute *dev_attr; - struct afu_config_record *cr, *tmp; - int i; - - /* remove the err buffer bin attribute */ - if (afu->eb_len) - device_remove_bin_file(&afu->dev, &afu->attr_eb); - - for (i = 0; i < ARRAY_SIZE(afu_attrs); i++) { - dev_attr = &afu_attrs[i]; - if (cxl_ops->support_attributes(dev_attr->attr.name, - CXL_AFU_ATTRS)) - device_remove_file(&afu->dev, &afu_attrs[i]); - } - - list_for_each_entry_safe(cr, tmp, &afu->crs, list) { - sysfs_remove_bin_file(&cr->kobj, &cr->config_attr); - kobject_put(&cr->kobj); - } -} - -int cxl_sysfs_afu_add(struct cxl_afu *afu) -{ - struct device_attribute *dev_attr; - struct afu_config_record *cr; - int i, rc; - - INIT_LIST_HEAD(&afu->crs); - - for (i = 0; i < ARRAY_SIZE(afu_attrs); i++) { - dev_attr = &afu_attrs[i]; - if (cxl_ops->support_attributes(dev_attr->attr.name, - CXL_AFU_ATTRS)) { - if ((rc = device_create_file(&afu->dev, &afu_attrs[i]))) - goto err; - } - } - - /* conditionally create the add the binary file for error info buffer */ - if (afu->eb_len) { - sysfs_attr_init(&afu->attr_eb.attr); - - afu->attr_eb.attr.name = "afu_err_buff"; - afu->attr_eb.attr.mode = S_IRUGO; - afu->attr_eb.size = afu->eb_len; - afu->attr_eb.read_new = afu_eb_read; - - rc = device_create_bin_file(&afu->dev, &afu->attr_eb); - if (rc) { - dev_err(&afu->dev, - "Unable to create eb attr for the afu. Err(%d)\n", - rc); - goto err; - } - } - - for (i = 0; i < afu->crs_num; i++) { - cr = cxl_sysfs_afu_new_cr(afu, i); - if (IS_ERR(cr)) { - rc = PTR_ERR(cr); - goto err1; - } - list_add(&cr->list, &afu->crs); - } - - return 0; - -err1: - cxl_sysfs_afu_remove(afu); - return rc; -err: - /* reset the eb_len as we havent created the bin attr */ - afu->eb_len = 0; - - for (i--; i >= 0; i--) { - dev_attr = &afu_attrs[i]; - if (cxl_ops->support_attributes(dev_attr->attr.name, - CXL_AFU_ATTRS)) - device_remove_file(&afu->dev, &afu_attrs[i]); - } - return rc; -} - -int cxl_sysfs_afu_m_add(struct cxl_afu *afu) -{ - struct device_attribute *dev_attr; - int i, rc; - - for (i = 0; i < ARRAY_SIZE(afu_master_attrs); i++) { - dev_attr = &afu_master_attrs[i]; - if (cxl_ops->support_attributes(dev_attr->attr.name, - CXL_AFU_MASTER_ATTRS)) { - if ((rc = device_create_file(afu->chardev_m, &afu_master_attrs[i]))) - goto err; - } - } - - return 0; - -err: - for (i--; i >= 0; i--) { - dev_attr = &afu_master_attrs[i]; - if (cxl_ops->support_attributes(dev_attr->attr.name, - CXL_AFU_MASTER_ATTRS)) - device_remove_file(afu->chardev_m, &afu_master_attrs[i]); - } - return rc; -} - -void cxl_sysfs_afu_m_remove(struct cxl_afu *afu) -{ - struct device_attribute *dev_attr; - int i; - - for (i = 0; i < ARRAY_SIZE(afu_master_attrs); i++) { - dev_attr = &afu_master_attrs[i]; - if (cxl_ops->support_attributes(dev_attr->attr.name, - CXL_AFU_MASTER_ATTRS)) - device_remove_file(afu->chardev_m, &afu_master_attrs[i]); - } -}
diff --git a/drivers/misc/cxl/trace.c b/drivers/misc/cxl/trace.c deleted file mode 100644 index 86f654b..0000000 --- a/drivers/misc/cxl/trace.c +++ /dev/null
@@ -1,9 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Copyright 2015 IBM Corp. - */ - -#ifndef __CHECKER__ -#define CREATE_TRACE_POINTS -#include "trace.h" -#endif
diff --git a/drivers/misc/cxl/trace.h b/drivers/misc/cxl/trace.h deleted file mode 100644 index c474157..0000000 --- a/drivers/misc/cxl/trace.h +++ /dev/null
@@ -1,691 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * Copyright 2015 IBM Corp. - */ - -#undef TRACE_SYSTEM -#define TRACE_SYSTEM cxl - -#if !defined(_CXL_TRACE_H) || defined(TRACE_HEADER_MULTI_READ) -#define _CXL_TRACE_H - -#include <linux/tracepoint.h> - -#include "cxl.h" - -#define dsisr_psl9_flags(flags) \ - __print_flags(flags, "|", \ - { CXL_PSL9_DSISR_An_CO_MASK, "FR" }, \ - { CXL_PSL9_DSISR_An_TF, "TF" }, \ - { CXL_PSL9_DSISR_An_PE, "PE" }, \ - { CXL_PSL9_DSISR_An_AE, "AE" }, \ - { CXL_PSL9_DSISR_An_OC, "OC" }, \ - { CXL_PSL9_DSISR_An_S, "S" }) - -#define DSISR_FLAGS \ - { CXL_PSL_DSISR_An_DS, "DS" }, \ - { CXL_PSL_DSISR_An_DM, "DM" }, \ - { CXL_PSL_DSISR_An_ST, "ST" }, \ - { CXL_PSL_DSISR_An_UR, "UR" }, \ - { CXL_PSL_DSISR_An_PE, "PE" }, \ - { CXL_PSL_DSISR_An_AE, "AE" }, \ - { CXL_PSL_DSISR_An_OC, "OC" }, \ - { CXL_PSL_DSISR_An_M, "M" }, \ - { CXL_PSL_DSISR_An_P, "P" }, \ - { CXL_PSL_DSISR_An_A, "A" }, \ - { CXL_PSL_DSISR_An_S, "S" }, \ - { CXL_PSL_DSISR_An_K, "K" } - -#define TFC_FLAGS \ - { CXL_PSL_TFC_An_A, "A" }, \ - { CXL_PSL_TFC_An_C, "C" }, \ - { CXL_PSL_TFC_An_AE, "AE" }, \ - { CXL_PSL_TFC_An_R, "R" } - -#define LLCMD_NAMES \ - { CXL_SPA_SW_CMD_TERMINATE, "TERMINATE" }, \ - { CXL_SPA_SW_CMD_REMOVE, "REMOVE" }, \ - { CXL_SPA_SW_CMD_SUSPEND, "SUSPEND" }, \ - { CXL_SPA_SW_CMD_RESUME, "RESUME" }, \ - { CXL_SPA_SW_CMD_ADD, "ADD" }, \ - { CXL_SPA_SW_CMD_UPDATE, "UPDATE" } - -#define AFU_COMMANDS \ - { 0, "DISABLE" }, \ - { CXL_AFU_Cntl_An_E, "ENABLE" }, \ - { CXL_AFU_Cntl_An_RA, "RESET" } - -#define PSL_COMMANDS \ - { CXL_PSL_SCNTL_An_Pc, "PURGE" }, \ - { CXL_PSL_SCNTL_An_Sc, "SUSPEND" } - - -DECLARE_EVENT_CLASS(cxl_pe_class, - TP_PROTO(struct cxl_context *ctx), - - TP_ARGS(ctx), - - TP_STRUCT__entry( - __field(u8, card) - __field(u8, afu) - __field(u16, pe) - ), - - TP_fast_assign( - __entry->card = ctx->afu->adapter->adapter_num; - __entry->afu = ctx->afu->slice; - __entry->pe = ctx->pe; - ), - - TP_printk("afu%i.%i pe=%i", - __entry->card, - __entry->afu, - __entry->pe - ) -); - - -TRACE_EVENT(cxl_attach, - TP_PROTO(struct cxl_context *ctx, u64 wed, s16 num_interrupts, u64 amr), - - TP_ARGS(ctx, wed, num_interrupts, amr), - - TP_STRUCT__entry( - __field(u8, card) - __field(u8, afu) - __field(u16, pe) - __field(pid_t, pid) - __field(u64, wed) - __field(u64, amr) - __field(s16, num_interrupts) - ), - - TP_fast_assign( - __entry->card = ctx->afu->adapter->adapter_num; - __entry->afu = ctx->afu->slice; - __entry->pe = ctx->pe; - __entry->pid = pid_nr(ctx->pid); - __entry->wed = wed; - __entry->amr = amr; - __entry->num_interrupts = num_interrupts; - ), - - TP_printk("afu%i.%i pid=%i pe=%i wed=0x%016llx irqs=%i amr=0x%llx", - __entry->card, - __entry->afu, - __entry->pid, - __entry->pe, - __entry->wed, - __entry->num_interrupts, - __entry->amr - ) -); - -DEFINE_EVENT(cxl_pe_class, cxl_detach, - TP_PROTO(struct cxl_context *ctx), - TP_ARGS(ctx) -); - -TRACE_EVENT(cxl_afu_irq, - TP_PROTO(struct cxl_context *ctx, int afu_irq, int virq, irq_hw_number_t hwirq), - - TP_ARGS(ctx, afu_irq, virq, hwirq), - - TP_STRUCT__entry( - __field(u8, card) - __field(u8, afu) - __field(u16, pe) - __field(u16, afu_irq) - __field(int, virq) - __field(irq_hw_number_t, hwirq) - ), - - TP_fast_assign( - __entry->card = ctx->afu->adapter->adapter_num; - __entry->afu = ctx->afu->slice; - __entry->pe = ctx->pe; - __entry->afu_irq = afu_irq; - __entry->virq = virq; - __entry->hwirq = hwirq; - ), - - TP_printk("afu%i.%i pe=%i afu_irq=%i virq=%i hwirq=0x%lx", - __entry->card, - __entry->afu, - __entry->pe, - __entry->afu_irq, - __entry->virq, - __entry->hwirq - ) -); - -TRACE_EVENT(cxl_psl9_irq, - TP_PROTO(struct cxl_context *ctx, int irq, u64 dsisr, u64 dar), - - TP_ARGS(ctx, irq, dsisr, dar), - - TP_STRUCT__entry( - __field(u8, card) - __field(u8, afu) - __field(u16, pe) - __field(int, irq) - __field(u64, dsisr) - __field(u64, dar) - ), - - TP_fast_assign( - __entry->card = ctx->afu->adapter->adapter_num; - __entry->afu = ctx->afu->slice; - __entry->pe = ctx->pe; - __entry->irq = irq; - __entry->dsisr = dsisr; - __entry->dar = dar; - ), - - TP_printk("afu%i.%i pe=%i irq=%i dsisr=0x%016llx dsisr=%s dar=0x%016llx", - __entry->card, - __entry->afu, - __entry->pe, - __entry->irq, - __entry->dsisr, - dsisr_psl9_flags(__entry->dsisr), - __entry->dar - ) -); - -TRACE_EVENT(cxl_psl_irq, - TP_PROTO(struct cxl_context *ctx, int irq, u64 dsisr, u64 dar), - - TP_ARGS(ctx, irq, dsisr, dar), - - TP_STRUCT__entry( - __field(u8, card) - __field(u8, afu) - __field(u16, pe) - __field(int, irq) - __field(u64, dsisr) - __field(u64, dar) - ), - - TP_fast_assign( - __entry->card = ctx->afu->adapter->adapter_num; - __entry->afu = ctx->afu->slice; - __entry->pe = ctx->pe; - __entry->irq = irq; - __entry->dsisr = dsisr; - __entry->dar = dar; - ), - - TP_printk("afu%i.%i pe=%i irq=%i dsisr=%s dar=0x%016llx", - __entry->card, - __entry->afu, - __entry->pe, - __entry->irq, - __print_flags(__entry->dsisr, "|", DSISR_FLAGS), - __entry->dar - ) -); - -TRACE_EVENT(cxl_psl_irq_ack, - TP_PROTO(struct cxl_context *ctx, u64 tfc), - - TP_ARGS(ctx, tfc), - - TP_STRUCT__entry( - __field(u8, card) - __field(u8, afu) - __field(u16, pe) - __field(u64, tfc) - ), - - TP_fast_assign( - __entry->card = ctx->afu->adapter->adapter_num; - __entry->afu = ctx->afu->slice; - __entry->pe = ctx->pe; - __entry->tfc = tfc; - ), - - TP_printk("afu%i.%i pe=%i tfc=%s", - __entry->card, - __entry->afu, - __entry->pe, - __print_flags(__entry->tfc, "|", TFC_FLAGS) - ) -); - -TRACE_EVENT(cxl_ste_miss, - TP_PROTO(struct cxl_context *ctx, u64 dar), - - TP_ARGS(ctx, dar), - - TP_STRUCT__entry( - __field(u8, card) - __field(u8, afu) - __field(u16, pe) - __field(u64, dar) - ), - - TP_fast_assign( - __entry->card = ctx->afu->adapter->adapter_num; - __entry->afu = ctx->afu->slice; - __entry->pe = ctx->pe; - __entry->dar = dar; - ), - - TP_printk("afu%i.%i pe=%i dar=0x%016llx", - __entry->card, - __entry->afu, - __entry->pe, - __entry->dar - ) -); - -TRACE_EVENT(cxl_ste_write, - TP_PROTO(struct cxl_context *ctx, unsigned int idx, u64 e, u64 v), - - TP_ARGS(ctx, idx, e, v), - - TP_STRUCT__entry( - __field(u8, card) - __field(u8, afu) - __field(u16, pe) - __field(unsigned int, idx) - __field(u64, e) - __field(u64, v) - ), - - TP_fast_assign( - __entry->card = ctx->afu->adapter->adapter_num; - __entry->afu = ctx->afu->slice; - __entry->pe = ctx->pe; - __entry->idx = idx; - __entry->e = e; - __entry->v = v; - ), - - TP_printk("afu%i.%i pe=%i SSTE[%i] E=0x%016llx V=0x%016llx", - __entry->card, - __entry->afu, - __entry->pe, - __entry->idx, - __entry->e, - __entry->v - ) -); - -TRACE_EVENT(cxl_pte_miss, - TP_PROTO(struct cxl_context *ctx, u64 dsisr, u64 dar), - - TP_ARGS(ctx, dsisr, dar), - - TP_STRUCT__entry( - __field(u8, card) - __field(u8, afu) - __field(u16, pe) - __field(u64, dsisr) - __field(u64, dar) - ), - - TP_fast_assign( - __entry->card = ctx->afu->adapter->adapter_num; - __entry->afu = ctx->afu->slice; - __entry->pe = ctx->pe; - __entry->dsisr = dsisr; - __entry->dar = dar; - ), - - TP_printk("afu%i.%i pe=%i dsisr=%s dar=0x%016llx", - __entry->card, - __entry->afu, - __entry->pe, - __print_flags(__entry->dsisr, "|", DSISR_FLAGS), - __entry->dar - ) -); - -TRACE_EVENT(cxl_llcmd, - TP_PROTO(struct cxl_context *ctx, u64 cmd), - - TP_ARGS(ctx, cmd), - - TP_STRUCT__entry( - __field(u8, card) - __field(u8, afu) - __field(u16, pe) - __field(u64, cmd) - ), - - TP_fast_assign( - __entry->card = ctx->afu->adapter->adapter_num; - __entry->afu = ctx->afu->slice; - __entry->pe = ctx->pe; - __entry->cmd = cmd; - ), - - TP_printk("afu%i.%i pe=%i cmd=%s", - __entry->card, - __entry->afu, - __entry->pe, - __print_symbolic_u64(__entry->cmd, LLCMD_NAMES) - ) -); - -TRACE_EVENT(cxl_llcmd_done, - TP_PROTO(struct cxl_context *ctx, u64 cmd, int rc), - - TP_ARGS(ctx, cmd, rc), - - TP_STRUCT__entry( - __field(u8, card) - __field(u8, afu) - __field(u16, pe) - __field(u64, cmd) - __field(int, rc) - ), - - TP_fast_assign( - __entry->card = ctx->afu->adapter->adapter_num; - __entry->afu = ctx->afu->slice; - __entry->pe = ctx->pe; - __entry->rc = rc; - __entry->cmd = cmd; - ), - - TP_printk("afu%i.%i pe=%i cmd=%s rc=%i", - __entry->card, - __entry->afu, - __entry->pe, - __print_symbolic_u64(__entry->cmd, LLCMD_NAMES), - __entry->rc - ) -); - -DECLARE_EVENT_CLASS(cxl_afu_psl_ctrl, - TP_PROTO(struct cxl_afu *afu, u64 cmd), - - TP_ARGS(afu, cmd), - - TP_STRUCT__entry( - __field(u8, card) - __field(u8, afu) - __field(u64, cmd) - ), - - TP_fast_assign( - __entry->card = afu->adapter->adapter_num; - __entry->afu = afu->slice; - __entry->cmd = cmd; - ), - - TP_printk("afu%i.%i cmd=%s", - __entry->card, - __entry->afu, - __print_symbolic_u64(__entry->cmd, AFU_COMMANDS) - ) -); - -DECLARE_EVENT_CLASS(cxl_afu_psl_ctrl_done, - TP_PROTO(struct cxl_afu *afu, u64 cmd, int rc), - - TP_ARGS(afu, cmd, rc), - - TP_STRUCT__entry( - __field(u8, card) - __field(u8, afu) - __field(u64, cmd) - __field(int, rc) - ), - - TP_fast_assign( - __entry->card = afu->adapter->adapter_num; - __entry->afu = afu->slice; - __entry->rc = rc; - __entry->cmd = cmd; - ), - - TP_printk("afu%i.%i cmd=%s rc=%i", - __entry->card, - __entry->afu, - __print_symbolic_u64(__entry->cmd, AFU_COMMANDS), - __entry->rc - ) -); - -DEFINE_EVENT(cxl_afu_psl_ctrl, cxl_afu_ctrl, - TP_PROTO(struct cxl_afu *afu, u64 cmd), - TP_ARGS(afu, cmd) -); - -DEFINE_EVENT(cxl_afu_psl_ctrl_done, cxl_afu_ctrl_done, - TP_PROTO(struct cxl_afu *afu, u64 cmd, int rc), - TP_ARGS(afu, cmd, rc) -); - -DEFINE_EVENT_PRINT(cxl_afu_psl_ctrl, cxl_psl_ctrl, - TP_PROTO(struct cxl_afu *afu, u64 cmd), - TP_ARGS(afu, cmd), - - TP_printk("psl%i.%i cmd=%s", - __entry->card, - __entry->afu, - __print_symbolic_u64(__entry->cmd, PSL_COMMANDS) - ) -); - -DEFINE_EVENT_PRINT(cxl_afu_psl_ctrl_done, cxl_psl_ctrl_done, - TP_PROTO(struct cxl_afu *afu, u64 cmd, int rc), - TP_ARGS(afu, cmd, rc), - - TP_printk("psl%i.%i cmd=%s rc=%i", - __entry->card, - __entry->afu, - __print_symbolic_u64(__entry->cmd, PSL_COMMANDS), - __entry->rc - ) -); - -DEFINE_EVENT(cxl_pe_class, cxl_slbia, - TP_PROTO(struct cxl_context *ctx), - TP_ARGS(ctx) -); - -TRACE_EVENT(cxl_hcall, - TP_PROTO(u64 unit_address, u64 process_token, long rc), - - TP_ARGS(unit_address, process_token, rc), - - TP_STRUCT__entry( - __field(u64, unit_address) - __field(u64, process_token) - __field(long, rc) - ), - - TP_fast_assign( - __entry->unit_address = unit_address; - __entry->process_token = process_token; - __entry->rc = rc; - ), - - TP_printk("unit_address=0x%016llx process_token=0x%016llx rc=%li", - __entry->unit_address, - __entry->process_token, - __entry->rc - ) -); - -TRACE_EVENT(cxl_hcall_control, - TP_PROTO(u64 unit_address, char *fct, u64 p1, u64 p2, u64 p3, - u64 p4, unsigned long r4, long rc), - - TP_ARGS(unit_address, fct, p1, p2, p3, p4, r4, rc), - - TP_STRUCT__entry( - __field(u64, unit_address) - __field(char *, fct) - __field(u64, p1) - __field(u64, p2) - __field(u64, p3) - __field(u64, p4) - __field(unsigned long, r4) - __field(long, rc) - ), - - TP_fast_assign( - __entry->unit_address = unit_address; - __entry->fct = fct; - __entry->p1 = p1; - __entry->p2 = p2; - __entry->p3 = p3; - __entry->p4 = p4; - __entry->r4 = r4; - __entry->rc = rc; - ), - - TP_printk("unit_address=%#.16llx %s(%#llx, %#llx, %#llx, %#llx, R4: %#lx)): %li", - __entry->unit_address, - __entry->fct, - __entry->p1, - __entry->p2, - __entry->p3, - __entry->p4, - __entry->r4, - __entry->rc - ) -); - -TRACE_EVENT(cxl_hcall_attach, - TP_PROTO(u64 unit_address, u64 phys_addr, unsigned long process_token, - unsigned long mmio_addr, unsigned long mmio_size, long rc), - - TP_ARGS(unit_address, phys_addr, process_token, - mmio_addr, mmio_size, rc), - - TP_STRUCT__entry( - __field(u64, unit_address) - __field(u64, phys_addr) - __field(unsigned long, process_token) - __field(unsigned long, mmio_addr) - __field(unsigned long, mmio_size) - __field(long, rc) - ), - - TP_fast_assign( - __entry->unit_address = unit_address; - __entry->phys_addr = phys_addr; - __entry->process_token = process_token; - __entry->mmio_addr = mmio_addr; - __entry->mmio_size = mmio_size; - __entry->rc = rc; - ), - - TP_printk("unit_address=0x%016llx phys_addr=0x%016llx " - "token=0x%.8lx mmio_addr=0x%lx mmio_size=0x%lx rc=%li", - __entry->unit_address, - __entry->phys_addr, - __entry->process_token, - __entry->mmio_addr, - __entry->mmio_size, - __entry->rc - ) -); - -DEFINE_EVENT(cxl_hcall, cxl_hcall_detach, - TP_PROTO(u64 unit_address, u64 process_token, long rc), - TP_ARGS(unit_address, process_token, rc) -); - -DEFINE_EVENT(cxl_hcall_control, cxl_hcall_control_function, - TP_PROTO(u64 unit_address, char *fct, u64 p1, u64 p2, u64 p3, - u64 p4, unsigned long r4, long rc), - TP_ARGS(unit_address, fct, p1, p2, p3, p4, r4, rc) -); - -DEFINE_EVENT(cxl_hcall, cxl_hcall_collect_int_info, - TP_PROTO(u64 unit_address, u64 process_token, long rc), - TP_ARGS(unit_address, process_token, rc) -); - -TRACE_EVENT(cxl_hcall_control_faults, - TP_PROTO(u64 unit_address, u64 process_token, - u64 control_mask, u64 reset_mask, unsigned long r4, - long rc), - - TP_ARGS(unit_address, process_token, - control_mask, reset_mask, r4, rc), - - TP_STRUCT__entry( - __field(u64, unit_address) - __field(u64, process_token) - __field(u64, control_mask) - __field(u64, reset_mask) - __field(unsigned long, r4) - __field(long, rc) - ), - - TP_fast_assign( - __entry->unit_address = unit_address; - __entry->process_token = process_token; - __entry->control_mask = control_mask; - __entry->reset_mask = reset_mask; - __entry->r4 = r4; - __entry->rc = rc; - ), - - TP_printk("unit_address=0x%016llx process_token=0x%llx " - "control_mask=%#llx reset_mask=%#llx r4=%#lx rc=%li", - __entry->unit_address, - __entry->process_token, - __entry->control_mask, - __entry->reset_mask, - __entry->r4, - __entry->rc - ) -); - -DEFINE_EVENT(cxl_hcall_control, cxl_hcall_control_facility, - TP_PROTO(u64 unit_address, char *fct, u64 p1, u64 p2, u64 p3, - u64 p4, unsigned long r4, long rc), - TP_ARGS(unit_address, fct, p1, p2, p3, p4, r4, rc) -); - -TRACE_EVENT(cxl_hcall_download_facility, - TP_PROTO(u64 unit_address, char *fct, u64 list_address, u64 num, - unsigned long r4, long rc), - - TP_ARGS(unit_address, fct, list_address, num, r4, rc), - - TP_STRUCT__entry( - __field(u64, unit_address) - __field(char *, fct) - __field(u64, list_address) - __field(u64, num) - __field(unsigned long, r4) - __field(long, rc) - ), - - TP_fast_assign( - __entry->unit_address = unit_address; - __entry->fct = fct; - __entry->list_address = list_address; - __entry->num = num; - __entry->r4 = r4; - __entry->rc = rc; - ), - - TP_printk("%#.16llx, %s(%#llx, %#llx), %#lx): %li", - __entry->unit_address, - __entry->fct, - __entry->list_address, - __entry->num, - __entry->r4, - __entry->rc - ) -); - -#endif /* _CXL_TRACE_H */ - -/* This part must be outside protection */ -#undef TRACE_INCLUDE_PATH -#define TRACE_INCLUDE_PATH . -#define TRACE_INCLUDE_FILE trace -#include <trace/define_trace.h>
diff --git a/drivers/misc/cxl/vphb.c b/drivers/misc/cxl/vphb.c deleted file mode 100644 index 6332db8..0000000 --- a/drivers/misc/cxl/vphb.c +++ /dev/null
@@ -1,309 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Copyright 2014 IBM Corp. - */ - -#include <linux/pci.h> -#include <misc/cxl.h> -#include "cxl.h" - -static int cxl_pci_probe_mode(struct pci_bus *bus) -{ - return PCI_PROBE_NORMAL; -} - -static int cxl_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) -{ - return -ENODEV; -} - -static void cxl_teardown_msi_irqs(struct pci_dev *pdev) -{ - /* - * MSI should never be set but need still need to provide this call - * back. - */ -} - -static bool cxl_pci_enable_device_hook(struct pci_dev *dev) -{ - struct pci_controller *phb; - struct cxl_afu *afu; - struct cxl_context *ctx; - - phb = pci_bus_to_host(dev->bus); - afu = (struct cxl_afu *)phb->private_data; - - if (!cxl_ops->link_ok(afu->adapter, afu)) { - dev_warn(&dev->dev, "%s: Device link is down, refusing to enable AFU\n", __func__); - return false; - } - - dev->dev.archdata.dma_offset = PAGE_OFFSET; - - /* - * Allocate a context to do cxl things too. If we eventually do real - * DMA ops, we'll need a default context to attach them to - */ - ctx = cxl_dev_context_init(dev); - if (IS_ERR(ctx)) - return false; - dev->dev.archdata.cxl_ctx = ctx; - - return (cxl_ops->afu_check_and_enable(afu) == 0); -} - -static void cxl_pci_disable_device(struct pci_dev *dev) -{ - struct cxl_context *ctx = cxl_get_context(dev); - - if (ctx) { - if (ctx->status == STARTED) { - dev_err(&dev->dev, "Default context started\n"); - return; - } - dev->dev.archdata.cxl_ctx = NULL; - cxl_release_context(ctx); - } -} - -static void cxl_pci_reset_secondary_bus(struct pci_dev *dev) -{ - /* Should we do an AFU reset here ? */ -} - -static int cxl_pcie_cfg_record(u8 bus, u8 devfn) -{ - return (bus << 8) + devfn; -} - -static inline struct cxl_afu *pci_bus_to_afu(struct pci_bus *bus) -{ - struct pci_controller *phb = bus ? pci_bus_to_host(bus) : NULL; - - return phb ? phb->private_data : NULL; -} - -static void cxl_afu_configured_put(struct cxl_afu *afu) -{ - atomic_dec_if_positive(&afu->configured_state); -} - -static bool cxl_afu_configured_get(struct cxl_afu *afu) -{ - return atomic_inc_unless_negative(&afu->configured_state); -} - -static inline int cxl_pcie_config_info(struct pci_bus *bus, unsigned int devfn, - struct cxl_afu *afu, int *_record) -{ - int record; - - record = cxl_pcie_cfg_record(bus->number, devfn); - if (record > afu->crs_num) - return PCIBIOS_DEVICE_NOT_FOUND; - - *_record = record; - return 0; -} - -static int cxl_pcie_read_config(struct pci_bus *bus, unsigned int devfn, - int offset, int len, u32 *val) -{ - int rc, record; - struct cxl_afu *afu; - u8 val8; - u16 val16; - u32 val32; - - afu = pci_bus_to_afu(bus); - /* Grab a reader lock on afu. */ - if (afu == NULL || !cxl_afu_configured_get(afu)) - return PCIBIOS_DEVICE_NOT_FOUND; - - rc = cxl_pcie_config_info(bus, devfn, afu, &record); - if (rc) - goto out; - - switch (len) { - case 1: - rc = cxl_ops->afu_cr_read8(afu, record, offset, &val8); - *val = val8; - break; - case 2: - rc = cxl_ops->afu_cr_read16(afu, record, offset, &val16); - *val = val16; - break; - case 4: - rc = cxl_ops->afu_cr_read32(afu, record, offset, &val32); - *val = val32; - break; - default: - WARN_ON(1); - } - -out: - cxl_afu_configured_put(afu); - return rc ? PCIBIOS_DEVICE_NOT_FOUND : 0; -} - -static int cxl_pcie_write_config(struct pci_bus *bus, unsigned int devfn, - int offset, int len, u32 val) -{ - int rc, record; - struct cxl_afu *afu; - - afu = pci_bus_to_afu(bus); - /* Grab a reader lock on afu. */ - if (afu == NULL || !cxl_afu_configured_get(afu)) - return PCIBIOS_DEVICE_NOT_FOUND; - - rc = cxl_pcie_config_info(bus, devfn, afu, &record); - if (rc) - goto out; - - switch (len) { - case 1: - rc = cxl_ops->afu_cr_write8(afu, record, offset, val & 0xff); - break; - case 2: - rc = cxl_ops->afu_cr_write16(afu, record, offset, val & 0xffff); - break; - case 4: - rc = cxl_ops->afu_cr_write32(afu, record, offset, val); - break; - default: - WARN_ON(1); - } - -out: - cxl_afu_configured_put(afu); - return rc ? PCIBIOS_SET_FAILED : 0; -} - -static struct pci_ops cxl_pcie_pci_ops = -{ - .read = cxl_pcie_read_config, - .write = cxl_pcie_write_config, -}; - - -static struct pci_controller_ops cxl_pci_controller_ops = -{ - .probe_mode = cxl_pci_probe_mode, - .enable_device_hook = cxl_pci_enable_device_hook, - .disable_device = cxl_pci_disable_device, - .release_device = cxl_pci_disable_device, - .reset_secondary_bus = cxl_pci_reset_secondary_bus, - .setup_msi_irqs = cxl_setup_msi_irqs, - .teardown_msi_irqs = cxl_teardown_msi_irqs, -}; - -int cxl_pci_vphb_add(struct cxl_afu *afu) -{ - struct pci_controller *phb; - struct device_node *vphb_dn; - struct device *parent; - - /* - * If there are no AFU configuration records we won't have anything to - * expose under the vPHB, so skip creating one, returning success since - * this is still a valid case. This will also opt us out of EEH - * handling since we won't have anything special to do if there are no - * kernel drivers attached to the vPHB, and EEH handling is not yet - * supported in the peer model. - */ - if (!afu->crs_num) - return 0; - - /* The parent device is the adapter. Reuse the device node of - * the adapter. - * We don't seem to care what device node is used for the vPHB, - * but tools such as lsvpd walk up the device parents looking - * for a valid location code, so we might as well show devices - * attached to the adapter as being located on that adapter. - */ - parent = afu->adapter->dev.parent; - vphb_dn = parent->of_node; - - /* Alloc and setup PHB data structure */ - phb = pcibios_alloc_controller(vphb_dn); - if (!phb) - return -ENODEV; - - /* Setup parent in sysfs */ - phb->parent = parent; - - /* Setup the PHB using arch provided callback */ - phb->ops = &cxl_pcie_pci_ops; - phb->cfg_addr = NULL; - phb->cfg_data = NULL; - phb->private_data = afu; - phb->controller_ops = cxl_pci_controller_ops; - - /* Scan the bus */ - pcibios_scan_phb(phb); - if (phb->bus == NULL) - return -ENXIO; - - /* Set release hook on root bus */ - pci_set_host_bridge_release(to_pci_host_bridge(phb->bus->bridge), - pcibios_free_controller_deferred, - (void *) phb); - - /* Claim resources. This might need some rework as well depending - * whether we are doing probe-only or not, like assigning unassigned - * resources etc... - */ - pcibios_claim_one_bus(phb->bus); - - /* Add probed PCI devices to the device model */ - pci_bus_add_devices(phb->bus); - - afu->phb = phb; - - return 0; -} - -void cxl_pci_vphb_remove(struct cxl_afu *afu) -{ - struct pci_controller *phb; - - /* If there is no configuration record we won't have one of these */ - if (!afu || !afu->phb) - return; - - phb = afu->phb; - afu->phb = NULL; - - pci_remove_root_bus(phb->bus); - /* - * We don't free phb here - that's handled by - * pcibios_free_controller_deferred() - */ -} - -bool cxl_pci_is_vphb_device(struct pci_dev *dev) -{ - struct pci_controller *phb; - - phb = pci_bus_to_host(dev->bus); - - return (phb->ops == &cxl_pcie_pci_ops); -} - -struct cxl_afu *cxl_pci_to_afu(struct pci_dev *dev) -{ - struct pci_controller *phb; - - phb = pci_bus_to_host(dev->bus); - - return (struct cxl_afu *)phb->private_data; -} -EXPORT_SYMBOL_GPL(cxl_pci_to_afu); - -unsigned int cxl_pci_to_cfg_record(struct pci_dev *dev) -{ - return cxl_pcie_cfg_record(dev->bus->number, dev->devfn); -} -EXPORT_SYMBOL_GPL(cxl_pci_to_cfg_record);
diff --git a/drivers/misc/lkdtm/perms.c b/drivers/misc/lkdtm/perms.c index 5b861db..6c24426 100644 --- a/drivers/misc/lkdtm/perms.c +++ b/drivers/misc/lkdtm/perms.c
@@ -29,6 +29,13 @@ static const unsigned long rodata = 0xAA55AA55; static unsigned long ro_after_init __ro_after_init = 0x55AA5500; /* + * This is a pointer to do_nothing() which is initialized at runtime rather + * than build time to avoid objtool IBT validation warnings caused by an + * inlined unrolled memcpy() in execute_location(). + */ +static void __ro_after_init *do_nothing_ptr; + +/* * This just returns to the caller. It is designed to be copied into * non-executable memory regions. */ @@ -65,13 +72,12 @@ static noinline __nocfi void execute_location(void *dst, bool write) { void (*func)(void); func_desc_t fdesc; - void *do_nothing_text = dereference_function_descriptor(do_nothing); - pr_info("attempting ok execution at %px\n", do_nothing_text); + pr_info("attempting ok execution at %px\n", do_nothing_ptr); do_nothing(); if (write == CODE_WRITE) { - memcpy(dst, do_nothing_text, EXEC_SIZE); + memcpy(dst, do_nothing_ptr, EXEC_SIZE); flush_icache_range((unsigned long)dst, (unsigned long)dst + EXEC_SIZE); } @@ -267,6 +273,8 @@ static void lkdtm_ACCESS_NULL(void) void __init lkdtm_perms_init(void) { + do_nothing_ptr = dereference_function_descriptor(do_nothing); + /* Make sure we can write to __ro_after_init values during __init */ ro_after_init |= 0xAA; }
diff --git a/drivers/misc/sgi-xp/xpc_main.c b/drivers/misc/sgi-xp/xpc_main.c index 7a3c343..697a008 100644 --- a/drivers/misc/sgi-xp/xpc_main.c +++ b/drivers/misc/sgi-xp/xpc_main.c
@@ -202,7 +202,7 @@ xpc_start_hb_beater(void) static void xpc_stop_hb_beater(void) { - del_timer_sync(&xpc_hb_timer); + timer_delete_sync(&xpc_hb_timer); xpc_arch_ops.heartbeat_exit(); }
diff --git a/drivers/misc/sgi-xp/xpc_partition.c b/drivers/misc/sgi-xp/xpc_partition.c index 1999d02..d046701 100644 --- a/drivers/misc/sgi-xp/xpc_partition.c +++ b/drivers/misc/sgi-xp/xpc_partition.c
@@ -291,7 +291,7 @@ static int __xpc_partition_disengaged(struct xpc_partition *part, /* Cancel the timer function if not called from it */ if (!from_timer) - del_timer_sync(&part->disengage_timer); + timer_delete_sync(&part->disengage_timer); DBUG_ON(part->act_state != XPC_P_AS_DEACTIVATING && part->act_state != XPC_P_AS_INACTIVE);
diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c index bdb2299..dacb5bd 100644 --- a/drivers/mmc/core/host.c +++ b/drivers/mmc/core/host.c
@@ -147,13 +147,13 @@ void mmc_retune_disable(struct mmc_host *host) { mmc_retune_unpause(host); host->can_retune = 0; - del_timer_sync(&host->retune_timer); + timer_delete_sync(&host->retune_timer); mmc_retune_clear(host); } void mmc_retune_timer_stop(struct mmc_host *host) { - del_timer_sync(&host->retune_timer); + timer_delete_sync(&host->retune_timer); } EXPORT_SYMBOL(mmc_retune_timer_stop);
diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index 24fffc7..14e981b 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c
@@ -1592,7 +1592,7 @@ static void atmci_request_end(struct atmel_mci *host, struct mmc_request *mrq) WARN_ON(host->cmd || host->data); - del_timer(&host->timer); + timer_delete(&host->timer); /* * Update the MMC clock rate if necessary. This may be @@ -2357,7 +2357,7 @@ static void atmci_cleanup_slot(struct atmel_mci_slot *slot, if (slot->detect_pin) { free_irq(gpiod_to_irq(slot->detect_pin), slot); - del_timer_sync(&slot->detect_timer); + timer_delete_sync(&slot->detect_timer); } slot->host->slot[id] = NULL; @@ -2585,7 +2585,7 @@ static int atmci_probe(struct platform_device *pdev) pm_runtime_disable(dev); pm_runtime_put_noidle(dev); - del_timer_sync(&host->timer); + timer_delete_sync(&host->timer); if (!IS_ERR(host->dma.chan)) dma_release_channel(host->dma.chan); err_dma_probe_defer: @@ -2613,7 +2613,7 @@ static void atmci_remove(struct platform_device *pdev) atmci_writel(host, ATMCI_CR, ATMCI_CR_MCIDIS); atmci_readl(host, ATMCI_SR); - del_timer_sync(&host->timer); + timer_delete_sync(&host->timer); if (!IS_ERR(host->dma.chan)) dma_release_channel(host->dma.chan);
diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index bb596d1..5782900 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c
@@ -2040,10 +2040,10 @@ static bool dw_mci_clear_pending_cmd_complete(struct dw_mci *host) * Really be certain that the timer has stopped. This is a bit of * paranoia and could only really happen if we had really bad * interrupt latency and the interrupt routine and timeout were - * running concurrently so that the del_timer() in the interrupt + * running concurrently so that the timer_delete() in the interrupt * handler couldn't run. */ - WARN_ON(del_timer_sync(&host->cto_timer)); + WARN_ON(timer_delete_sync(&host->cto_timer)); clear_bit(EVENT_CMD_COMPLETE, &host->pending_events); return true; @@ -2055,7 +2055,7 @@ static bool dw_mci_clear_pending_data_complete(struct dw_mci *host) return false; /* Extra paranoia just like dw_mci_clear_pending_cmd_complete() */ - WARN_ON(del_timer_sync(&host->dto_timer)); + WARN_ON(timer_delete_sync(&host->dto_timer)); clear_bit(EVENT_DATA_COMPLETE, &host->pending_events); return true; @@ -2788,7 +2788,7 @@ static void dw_mci_write_data_pio(struct dw_mci *host) static void dw_mci_cmd_interrupt(struct dw_mci *host, u32 status) { - del_timer(&host->cto_timer); + timer_delete(&host->cto_timer); if (!host->cmd_status) host->cmd_status = status; @@ -2832,13 +2832,13 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id) dw_mci_cmd_interrupt(host, pending); spin_unlock(&host->irq_lock); - del_timer(&host->cmd11_timer); + timer_delete(&host->cmd11_timer); } if (pending & DW_MCI_CMD_ERROR_FLAGS) { spin_lock(&host->irq_lock); - del_timer(&host->cto_timer); + timer_delete(&host->cto_timer); mci_writel(host, RINTSTS, DW_MCI_CMD_ERROR_FLAGS); host->cmd_status = pending; smp_wmb(); /* drain writebuffer */ @@ -2851,7 +2851,7 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id) spin_lock(&host->irq_lock); if (host->quirks & DW_MMC_QUIRK_EXTENDED_TMOUT) - del_timer(&host->dto_timer); + timer_delete(&host->dto_timer); /* if there is an error report DATA_ERROR */ mci_writel(host, RINTSTS, DW_MCI_DATA_ERROR_FLAGS); @@ -2872,7 +2872,7 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id) if (pending & SDMMC_INT_DATA_OVER) { spin_lock(&host->irq_lock); - del_timer(&host->dto_timer); + timer_delete(&host->dto_timer); mci_writel(host, RINTSTS, SDMMC_INT_DATA_OVER); if (!host->data_status)
diff --git a/drivers/mmc/host/jz4740_mmc.c b/drivers/mmc/host/jz4740_mmc.c index 596012d..bd1662e 100644 --- a/drivers/mmc/host/jz4740_mmc.c +++ b/drivers/mmc/host/jz4740_mmc.c
@@ -862,7 +862,7 @@ static irqreturn_t jz_mmc_irq(int irq, void *devid) if (host->req && cmd && irq_reg) { if (test_and_clear_bit(0, &host->waiting)) { - del_timer(&host->timeout_timer); + timer_delete(&host->timeout_timer); if (status & JZ_MMC_STATUS_TIMEOUT_RES) { cmd->error = -ETIMEDOUT; @@ -1162,7 +1162,7 @@ static void jz4740_mmc_remove(struct platform_device *pdev) { struct jz4740_mmc_host *host = platform_get_drvdata(pdev); - del_timer_sync(&host->timeout_timer); + timer_delete_sync(&host->timeout_timer); jz4740_mmc_set_irq_enabled(host, 0xff, false); jz4740_mmc_reset(host);
diff --git a/drivers/mmc/host/meson-mx-sdio.c b/drivers/mmc/host/meson-mx-sdio.c index ad35180..e0ae5a0 100644 --- a/drivers/mmc/host/meson-mx-sdio.c +++ b/drivers/mmc/host/meson-mx-sdio.c
@@ -446,7 +446,7 @@ static irqreturn_t meson_mx_mmc_irq_thread(int irq, void *irq_data) if (WARN_ON(!cmd)) return IRQ_HANDLED; - del_timer_sync(&host->cmd_timeout); + timer_delete_sync(&host->cmd_timeout); if (cmd->data) { dma_unmap_sg(mmc_dev(host->mmc), cmd->data->sg, @@ -733,7 +733,7 @@ static void meson_mx_mmc_remove(struct platform_device *pdev) struct meson_mx_mmc_host *host = platform_get_drvdata(pdev); struct device *slot_dev = mmc_dev(host->mmc); - del_timer_sync(&host->cmd_timeout); + timer_delete_sync(&host->cmd_timeout); mmc_remove_host(host->mmc);
diff --git a/drivers/mmc/host/mvsdio.c b/drivers/mmc/host/mvsdio.c index b92f3ba..912ffac 100644 --- a/drivers/mmc/host/mvsdio.c +++ b/drivers/mmc/host/mvsdio.c
@@ -464,7 +464,7 @@ static irqreturn_t mvsd_irq(int irq, void *dev) struct mmc_command *cmd = mrq->cmd; u32 err_status = 0; - del_timer(&host->timer); + timer_delete(&host->timer); host->mrq = NULL; host->intr_en &= MVSD_NOR_CARD_INT; @@ -803,7 +803,7 @@ static void mvsd_remove(struct platform_device *pdev) struct mvsd_host *host = mmc_priv(mmc); mmc_remove_host(mmc); - del_timer_sync(&host->timer); + timer_delete_sync(&host->timer); mvsd_power_down(host); if (!IS_ERR(host->clk))
diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c index 0a9affd..95d8d40a 100644 --- a/drivers/mmc/host/mxcmmc.c +++ b/drivers/mmc/host/mxcmmc.c
@@ -352,7 +352,7 @@ static void mxcmci_dma_callback(void *data) struct mxcmci_host *host = data; u32 stat; - del_timer(&host->watchdog); + timer_delete(&host->watchdog); stat = mxcmci_readl(host, MMC_REG_STATUS); @@ -737,7 +737,7 @@ static irqreturn_t mxcmci_irq(int irq, void *devid) mxcmci_cmd_done(host, stat); if (mxcmci_use_dma(host) && (stat & STATUS_WRITE_OP_DONE)) { - del_timer(&host->watchdog); + timer_delete(&host->watchdog); mxcmci_data_done(host, stat); }
diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c index 3cdb2fc..c50617d 100644 --- a/drivers/mmc/host/omap.c +++ b/drivers/mmc/host/omap.c
@@ -214,7 +214,7 @@ static void mmc_omap_select_slot(struct mmc_omap_slot *slot, int claimed) host->mmc = slot->mmc; spin_unlock_irqrestore(&host->slot_lock, flags); no_claim: - del_timer(&host->clk_timer); + timer_delete(&host->clk_timer); if (host->current_slot != slot || !claimed) mmc_omap_fclk_offdelay(host->current_slot); @@ -273,7 +273,7 @@ static void mmc_omap_release_slot(struct mmc_omap_slot *slot, int clk_enabled) /* Keeps clock running for at least 8 cycles on valid freq */ mod_timer(&host->clk_timer, jiffies + HZ/10); else { - del_timer(&host->clk_timer); + timer_delete(&host->clk_timer); mmc_omap_fclk_offdelay(slot); mmc_omap_fclk_enable(host, 0); } @@ -564,7 +564,7 @@ mmc_omap_cmd_done(struct mmc_omap_host *host, struct mmc_command *cmd) { host->cmd = NULL; - del_timer(&host->cmd_abort_timer); + timer_delete(&host->cmd_abort_timer); if (cmd->flags & MMC_RSP_PRESENT) { if (cmd->flags & MMC_RSP_136) { @@ -836,7 +836,7 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id) } if (cmd_error && host->data) { - del_timer(&host->cmd_abort_timer); + timer_delete(&host->cmd_abort_timer); host->abort = 1; OMAP_MMC_WRITE(host, IE, 0); disable_irq_nosync(host->irq); @@ -1365,7 +1365,7 @@ static void mmc_omap_remove_slot(struct mmc_omap_slot *slot) device_remove_file(&mmc->class_dev, &dev_attr_cover_switch); cancel_work_sync(&slot->cover_bh_work); - del_timer_sync(&slot->cover_timer); + timer_delete_sync(&slot->cover_timer); flush_workqueue(slot->host->mmc_omap_wq); mmc_remove_host(mmc);
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 5f91b44..5f78be7 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c
@@ -517,9 +517,9 @@ EXPORT_SYMBOL_GPL(sdhci_mod_timer); static void sdhci_del_timer(struct sdhci_host *host, struct mmc_request *mrq) { if (sdhci_data_line_cmd(mrq->cmd)) - del_timer(&host->data_timer); + timer_delete(&host->data_timer); else - del_timer(&host->timer); + timer_delete(&host->timer); } static inline bool sdhci_has_requests(struct sdhci_host *host) @@ -4976,8 +4976,8 @@ void sdhci_remove_host(struct sdhci_host *host, int dead) sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE); free_irq(host->irq, host); - del_timer_sync(&host->timer); - del_timer_sync(&host->data_timer); + timer_delete_sync(&host->timer); + timer_delete_sync(&host->data_timer); destroy_workqueue(host->complete_wq);
diff --git a/drivers/mmc/host/tifm_sd.c b/drivers/mmc/host/tifm_sd.c index aea14bf..713223f 100644 --- a/drivers/mmc/host/tifm_sd.c +++ b/drivers/mmc/host/tifm_sd.c
@@ -735,7 +735,7 @@ static void tifm_sd_end_cmd(struct work_struct *t) spin_lock_irqsave(&sock->lock, flags); - del_timer(&host->timer); + timer_delete(&host->timer); mrq = host->req; host->req = NULL;
diff --git a/drivers/mmc/host/via-sdmmc.c b/drivers/mmc/host/via-sdmmc.c index f774571..909d80a 100644 --- a/drivers/mmc/host/via-sdmmc.c +++ b/drivers/mmc/host/via-sdmmc.c
@@ -971,7 +971,7 @@ static void via_sdc_finish_bh_work(struct work_struct *t) spin_lock_irqsave(&host->lock, flags); - del_timer(&host->timer); + timer_delete(&host->timer); mrq = host->mrq; host->mrq = NULL; host->cmd = NULL; @@ -1202,7 +1202,7 @@ static void via_sd_remove(struct pci_dev *pcidev) free_irq(pcidev->irq, sdhost); - del_timer_sync(&sdhost->timer); + timer_delete_sync(&sdhost->timer); cancel_work_sync(&sdhost->finish_bh_work);
diff --git a/drivers/mmc/host/vub300.c b/drivers/mmc/host/vub300.c index fd67c06..dd71e5b 100644 --- a/drivers/mmc/host/vub300.c +++ b/drivers/mmc/host/vub300.c
@@ -1452,7 +1452,7 @@ static int __command_read_data(struct vub300_mmc_host *vub300, (linear_length / 16384)); add_timer(&vub300->sg_transfer_timer); usb_sg_wait(&vub300->sg_request); - del_timer(&vub300->sg_transfer_timer); + timer_delete(&vub300->sg_transfer_timer); if (vub300->sg_request.status < 0) { cmd->error = vub300->sg_request.status; data->bytes_xfered = 0; @@ -1572,7 +1572,7 @@ static int __command_write_data(struct vub300_mmc_host *vub300, if (cmd->error) { data->bytes_xfered = 0; } else { - del_timer(&vub300->sg_transfer_timer); + timer_delete(&vub300->sg_transfer_timer); if (vub300->sg_request.status < 0) { cmd->error = vub300->sg_request.status; data->bytes_xfered = 0; @@ -2339,7 +2339,7 @@ static int vub300_probe(struct usb_interface *interface, return 0; error6: - del_timer_sync(&vub300->inactivity_timer); + timer_delete_sync(&vub300->inactivity_timer); error5: mmc_free_host(mmc); /*
diff --git a/drivers/mmc/host/wbsd.c b/drivers/mmc/host/wbsd.c index 8b268e8..d5974b3 100644 --- a/drivers/mmc/host/wbsd.c +++ b/drivers/mmc/host/wbsd.c
@@ -1261,7 +1261,7 @@ static void wbsd_free_mmc(struct device *dev) host = mmc_priv(mmc); BUG_ON(host == NULL); - del_timer_sync(&host->ignore_timer); + timer_delete_sync(&host->ignore_timer); mmc_free_host(mmc); }
diff --git a/drivers/most/most_usb.c b/drivers/most/most_usb.c index 485d5ca..2199ba8 100644 --- a/drivers/most/most_usb.c +++ b/drivers/most/most_usb.c
@@ -257,7 +257,7 @@ static int hdm_poison_channel(struct most_interface *iface, int channel) mdev->padding_active[channel] = false; if (mdev->conf[channel].data_type == MOST_CH_ASYNC) { - del_timer_sync(&mdev->link_stat_timer); + timer_delete_sync(&mdev->link_stat_timer); cancel_work_sync(&mdev->poll_work_obj); } mutex_unlock(&mdev->io_mutex); @@ -1115,7 +1115,7 @@ static void hdm_disconnect(struct usb_interface *interface) mdev->usb_device = NULL; mutex_unlock(&mdev->io_mutex); - del_timer_sync(&mdev->link_stat_timer); + timer_delete_sync(&mdev->link_stat_timer); cancel_work_sync(&mdev->poll_work_obj); if (mdev->dci)
diff --git a/drivers/mtd/sm_ftl.c b/drivers/mtd/sm_ftl.c index b5b3c4c..d28d4f1 100644 --- a/drivers/mtd/sm_ftl.c +++ b/drivers/mtd/sm_ftl.c
@@ -1067,7 +1067,7 @@ static int sm_write(struct mtd_blktrans_dev *dev, sm_break_offset(ftl, sec_no << 9, &zone_num, &block, &boffset); /* No need in flush thread running now */ - del_timer(&ftl->timer); + timer_delete(&ftl->timer); mutex_lock(&ftl->mutex); zone = sm_get_zone(ftl, zone_num); @@ -1111,7 +1111,7 @@ static void sm_release(struct mtd_blktrans_dev *dev) { struct sm_ftl *ftl = dev->priv; - del_timer_sync(&ftl->timer); + timer_delete_sync(&ftl->timer); cancel_work_sync(&ftl->flush_work); mutex_lock(&ftl->mutex); sm_cache_flush(ftl);
diff --git a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c index 530c15d..602e6e1 100644 --- a/drivers/net/arcnet/arcnet.c +++ b/drivers/net/arcnet/arcnet.c
@@ -616,7 +616,7 @@ int arcnet_close(struct net_device *dev) struct arcnet_local *lp = netdev_priv(dev); arcnet_led_event(dev, ARCNET_LED_EVENT_STOP); - del_timer_sync(&lp->timer); + timer_delete_sync(&lp->timer); netif_stop_queue(dev); netif_carrier_off(dev);
diff --git a/drivers/net/arcnet/com20020-pci.c b/drivers/net/arcnet/com20020-pci.c index c5e571e..0472bcd 100644 --- a/drivers/net/arcnet/com20020-pci.c +++ b/drivers/net/arcnet/com20020-pci.c
@@ -251,18 +251,33 @@ static int com20020pci_probe(struct pci_dev *pdev, card->tx_led.default_trigger = devm_kasprintf(&pdev->dev, GFP_KERNEL, "arc%d-%d-tx", dev->dev_id, i); + if (!card->tx_led.default_trigger) { + ret = -ENOMEM; + goto err_free_arcdev; + } card->tx_led.name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "pci:green:tx:%d-%d", dev->dev_id, i); - + if (!card->tx_led.name) { + ret = -ENOMEM; + goto err_free_arcdev; + } card->tx_led.dev = &dev->dev; card->recon_led.brightness_set = led_recon_set; card->recon_led.default_trigger = devm_kasprintf(&pdev->dev, GFP_KERNEL, "arc%d-%d-recon", dev->dev_id, i); + if (!card->recon_led.default_trigger) { + ret = -ENOMEM; + goto err_free_arcdev; + } card->recon_led.name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "pci:red:recon:%d-%d", dev->dev_id, i); + if (!card->recon_led.name) { + ret = -ENOMEM; + goto err_free_arcdev; + } card->recon_led.dev = &dev->dev; ret = devm_led_classdev_register(&pdev->dev, &card->tx_led);
diff --git a/drivers/net/caif/caif_serial.c b/drivers/net/caif/caif_serial.c index 90ea3dc..c398ac4 100644 --- a/drivers/net/caif/caif_serial.c +++ b/drivers/net/caif/caif_serial.c
@@ -330,7 +330,7 @@ static int ldisc_open(struct tty_struct *tty) ser->tty = tty_kref_get(tty); ser->dev = dev; debugfs_init(ser, tty); - tty->receive_room = N_TTY_BUF_SIZE; + tty->receive_room = 4096; tty->disc_data = ser; set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); rtnl_lock();
diff --git a/drivers/net/can/grcan.c b/drivers/net/can/grcan.c index 21a61b8..adf3970 100644 --- a/drivers/net/can/grcan.c +++ b/drivers/net/can/grcan.c
@@ -778,7 +778,7 @@ static irqreturn_t grcan_interrupt(int irq, void *dev_id) */ if (priv->need_txbug_workaround && (sources & (GRCAN_IRQ_TX | GRCAN_IRQ_TXLOSS))) { - del_timer(&priv->hang_timer); + timer_delete(&priv->hang_timer); } /* Frame(s) received or transmitted */ @@ -817,8 +817,8 @@ static void grcan_running_reset(struct timer_list *t) spin_lock_irqsave(&priv->lock, flags); priv->resetting = false; - del_timer(&priv->hang_timer); - del_timer(&priv->rr_timer); + timer_delete(&priv->hang_timer); + timer_delete(&priv->rr_timer); if (!priv->closing) { /* Save and reset - config register preserved by grcan_reset */ @@ -1108,8 +1108,8 @@ static int grcan_close(struct net_device *dev) priv->closing = true; if (priv->need_txbug_workaround) { spin_unlock_irqrestore(&priv->lock, flags); - del_timer_sync(&priv->hang_timer); - del_timer_sync(&priv->rr_timer); + timer_delete_sync(&priv->hang_timer); + timer_delete_sync(&priv->rr_timer); spin_lock_irqsave(&priv->lock, flags); } netif_stop_queue(dev); @@ -1147,7 +1147,7 @@ static void grcan_transmit_catch_up(struct net_device *dev) * so prevent a running reset while catching up */ if (priv->need_txbug_workaround) - del_timer(&priv->hang_timer); + timer_delete(&priv->hang_timer); } spin_unlock_irqrestore(&priv->lock, flags);
diff --git a/drivers/net/can/kvaser_pciefd.c b/drivers/net/can/kvaser_pciefd.c index fa04a7c..cf0d518 100644 --- a/drivers/net/can/kvaser_pciefd.c +++ b/drivers/net/can/kvaser_pciefd.c
@@ -631,7 +631,7 @@ static int kvaser_pciefd_bus_on(struct kvaser_pciefd_can *can) u32 mode; unsigned long irq; - del_timer(&can->bec_poll_timer); + timer_delete(&can->bec_poll_timer); if (!completion_done(&can->flush_comp)) kvaser_pciefd_start_controller_flush(can); @@ -742,7 +742,7 @@ static int kvaser_pciefd_stop(struct net_device *netdev) ret = -ETIMEDOUT; } else { iowrite32(0, can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG); - del_timer(&can->bec_poll_timer); + timer_delete(&can->bec_poll_timer); } can->can.state = CAN_STATE_STOPPED; close_candev(netdev); @@ -1854,7 +1854,7 @@ static void kvaser_pciefd_remove_all_ctrls(struct kvaser_pciefd *pcie) if (can) { iowrite32(0, can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG); unregister_candev(can->can.dev); - del_timer(&can->bec_poll_timer); + timer_delete(&can->bec_poll_timer); kvaser_pciefd_pwm_stop(can); free_candev(can->can.dev); }
diff --git a/drivers/net/can/sja1000/peak_pcmcia.c b/drivers/net/can/sja1000/peak_pcmcia.c index ebd5941..6c7b1c58 100644 --- a/drivers/net/can/sja1000/peak_pcmcia.c +++ b/drivers/net/can/sja1000/peak_pcmcia.c
@@ -167,7 +167,7 @@ static void pcan_start_led_timer(struct pcan_pccard *card) */ static void pcan_stop_led_timer(struct pcan_pccard *card) { - del_timer_sync(&card->led_timer); + timer_delete_sync(&card->led_timer); } /*
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 901929f..29a89ab 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -7350,13 +7350,13 @@ static int mv88e6xxx_probe(struct mdio_device *mdiodev) err = mv88e6xxx_switch_reset(chip); mv88e6xxx_reg_unlock(chip); if (err) - goto out; + goto out_phy; if (np) { chip->irq = of_irq_get(np, 0); if (chip->irq == -EPROBE_DEFER) { err = chip->irq; - goto out; + goto out_phy; } } @@ -7375,7 +7375,7 @@ static int mv88e6xxx_probe(struct mdio_device *mdiodev) mv88e6xxx_reg_unlock(chip); if (err) - goto out; + goto out_phy; if (chip->info->g2_irqs > 0) { err = mv88e6xxx_g2_irq_setup(chip); @@ -7409,6 +7409,8 @@ static int mv88e6xxx_probe(struct mdio_device *mdiodev) mv88e6xxx_g1_irq_free(chip); else mv88e6xxx_irq_poll_free(chip); +out_phy: + mv88e6xxx_phy_destroy(chip); out: if (pdata) dev_put(pdata->netdev); @@ -7431,7 +7433,6 @@ static void mv88e6xxx_remove(struct mdio_device *mdiodev) mv88e6xxx_ptp_free(chip); } - mv88e6xxx_phy_destroy(chip); mv88e6xxx_unregister_switch(chip); mv88e6xxx_g1_vtu_prob_irq_free(chip); @@ -7444,6 +7445,8 @@ static void mv88e6xxx_remove(struct mdio_device *mdiodev) mv88e6xxx_g1_irq_free(chip); else mv88e6xxx_irq_poll_free(chip); + + mv88e6xxx_phy_destroy(chip); } static void mv88e6xxx_shutdown(struct mdio_device *mdiodev)
diff --git a/drivers/net/dsa/mv88e6xxx/phy.c b/drivers/net/dsa/mv88e6xxx/phy.c index 8bb88b3..b6d249e 100644 --- a/drivers/net/dsa/mv88e6xxx/phy.c +++ b/drivers/net/dsa/mv88e6xxx/phy.c
@@ -206,7 +206,7 @@ static int mv88e6xxx_phy_ppu_access_get(struct mv88e6xxx_chip *chip) } chip->ppu_disabled = 1; } else { - del_timer(&chip->ppu_timer); + timer_delete(&chip->ppu_timer); ret = 0; } @@ -229,7 +229,10 @@ static void mv88e6xxx_phy_ppu_state_init(struct mv88e6xxx_chip *chip) static void mv88e6xxx_phy_ppu_state_destroy(struct mv88e6xxx_chip *chip) { - del_timer_sync(&chip->ppu_timer); + mutex_lock(&chip->ppu_mutex); + timer_delete_sync(&chip->ppu_timer); + cancel_work_sync(&chip->ppu_work); + mutex_unlock(&chip->ppu_mutex); } int mv88e6185_phy_ppu_read(struct mv88e6xxx_chip *chip, struct mii_bus *bus,
diff --git a/drivers/net/dsa/sja1105/sja1105_ptp.c b/drivers/net/dsa/sja1105/sja1105_ptp.c index 08b45fd..198e787 100644 --- a/drivers/net/dsa/sja1105/sja1105_ptp.c +++ b/drivers/net/dsa/sja1105/sja1105_ptp.c
@@ -842,7 +842,7 @@ static int sja1105_extts_enable(struct sja1105_private *priv, if (on) sja1105_ptp_extts_setup_timer(&priv->ptp_data); else - del_timer_sync(&priv->ptp_data.extts_timer); + timer_delete_sync(&priv->ptp_data.extts_timer); return 0; } @@ -939,7 +939,7 @@ void sja1105_ptp_clock_unregister(struct dsa_switch *ds) if (IS_ERR_OR_NULL(ptp_data->clock)) return; - del_timer_sync(&ptp_data->extts_timer); + timer_delete_sync(&ptp_data->extts_timer); ptp_cancel_worker_sync(ptp_data->clock); skb_queue_purge(&ptp_data->skb_txtstamp_queue); skb_queue_purge(&ptp_data->skb_rxtstamp_queue);
diff --git a/drivers/net/dummy.c b/drivers/net/dummy.c index a4938c6..d6bdad4 100644 --- a/drivers/net/dummy.c +++ b/drivers/net/dummy.c
@@ -105,6 +105,7 @@ static void dummy_setup(struct net_device *dev) dev->netdev_ops = &dummy_netdev_ops; dev->ethtool_ops = &dummy_ethtool_ops; dev->needs_free_netdev = true; + dev->request_ops_lock = true; /* Fill in device structure with ethernet-generic values. */ dev->flags |= IFF_NOARP;
diff --git a/drivers/net/eql.c b/drivers/net/eql.c index 3c2efda..5889759 100644 --- a/drivers/net/eql.c +++ b/drivers/net/eql.c
@@ -254,7 +254,7 @@ static int eql_close(struct net_device *dev) * at the data structure it scans every so often... */ - del_timer_sync(&eql->timer); + timer_delete_sync(&eql->timer); eql_kill_slave_queue(&eql->queue);
diff --git a/drivers/net/ethernet/3com/3c515.c b/drivers/net/ethernet/3com/3c515.c index 4725a8c..8ba2ed8 100644 --- a/drivers/net/ethernet/3com/3c515.c +++ b/drivers/net/ethernet/3com/3c515.c
@@ -1414,7 +1414,7 @@ static int corkscrew_close(struct net_device *dev) dev->name, rx_nocopy, rx_copy, queued_packet); } - del_timer_sync(&vp->timer); + timer_delete_sync(&vp->timer); /* Turn off statistics ASAP. We update lp->stats below. */ outw(StatsDisable, ioaddr + EL3_CMD);
diff --git a/drivers/net/ethernet/3com/3c574_cs.c b/drivers/net/ethernet/3com/3c574_cs.c index dc3b7c9..b295d52 100644 --- a/drivers/net/ethernet/3com/3c574_cs.c +++ b/drivers/net/ethernet/3com/3c574_cs.c
@@ -1140,7 +1140,7 @@ static int el3_close(struct net_device *dev) link->open--; netif_stop_queue(dev); - del_timer_sync(&lp->media); + timer_delete_sync(&lp->media); return 0; }
diff --git a/drivers/net/ethernet/3com/3c589_cs.c b/drivers/net/ethernet/3com/3c589_cs.c index be58dac..ff331a3 100644 --- a/drivers/net/ethernet/3com/3c589_cs.c +++ b/drivers/net/ethernet/3com/3c589_cs.c
@@ -946,7 +946,7 @@ static int el3_close(struct net_device *dev) link->open--; netif_stop_queue(dev); - del_timer_sync(&lp->media); + timer_delete_sync(&lp->media); return 0; }
diff --git a/drivers/net/ethernet/3com/3c59x.c b/drivers/net/ethernet/3com/3c59x.c index 7902709..1a10f5d 100644 --- a/drivers/net/ethernet/3com/3c59x.c +++ b/drivers/net/ethernet/3com/3c59x.c
@@ -2691,7 +2691,7 @@ vortex_down(struct net_device *dev, int final_down) netdev_reset_queue(dev); netif_stop_queue(dev); - del_timer_sync(&vp->timer); + timer_delete_sync(&vp->timer); /* Turn off statistics ASAP. We update dev->stats below. */ iowrite16(StatsDisable, ioaddr + EL3_CMD);
diff --git a/drivers/net/ethernet/8390/axnet_cs.c b/drivers/net/ethernet/8390/axnet_cs.c index fea489a..e5be504 100644 --- a/drivers/net/ethernet/8390/axnet_cs.c +++ b/drivers/net/ethernet/8390/axnet_cs.c
@@ -504,7 +504,7 @@ static int axnet_close(struct net_device *dev) link->open--; netif_stop_queue(dev); - del_timer_sync(&info->watchdog); + timer_delete_sync(&info->watchdog); return 0; } /* axnet_close */
diff --git a/drivers/net/ethernet/8390/pcnet_cs.c b/drivers/net/ethernet/8390/pcnet_cs.c index 780fb4a..a326f25 100644 --- a/drivers/net/ethernet/8390/pcnet_cs.c +++ b/drivers/net/ethernet/8390/pcnet_cs.c
@@ -947,7 +947,7 @@ static int pcnet_close(struct net_device *dev) link->open--; netif_stop_queue(dev); - del_timer_sync(&info->watchdog); + timer_delete_sync(&info->watchdog); return 0; } /* pcnet_close */
diff --git a/drivers/net/ethernet/agere/et131x.c b/drivers/net/ethernet/agere/et131x.c index b325e0c..b398adac 100644 --- a/drivers/net/ethernet/agere/et131x.c +++ b/drivers/net/ethernet/agere/et131x.c
@@ -3639,7 +3639,7 @@ static int et131x_close(struct net_device *netdev) free_irq(adapter->pdev->irq, netdev); /* Stop the error timer */ - return del_timer_sync(&adapter->error_timer); + return timer_delete_sync(&adapter->error_timer); } /* et131x_set_packet_filter - Configures the Rx Packet filtering */
diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c index c0a6425..d748dc6d 100644 --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c
@@ -2028,7 +2028,7 @@ static int airoha_qdma_set_tx_ets_sched(struct airoha_gdm_port *port, struct tc_ets_qopt_offload_replace_params *p = &opt->replace_params; enum tx_sched_mode mode = TC_SCH_SP; u16 w[AIROHA_NUM_QOS_QUEUES] = {}; - int i, nstrict = 0, nwrr, qidx; + int i, nstrict = 0; if (p->bands > AIROHA_NUM_QOS_QUEUES) return -EINVAL; @@ -2046,17 +2046,17 @@ static int airoha_qdma_set_tx_ets_sched(struct airoha_gdm_port *port, * lowest priorities with respect to SP ones. * e.g: WRR0, WRR1, .., WRRm, SP0, SP1, .., SPn */ - nwrr = p->bands - nstrict; - qidx = nstrict && nwrr ? nstrict : 0; - for (i = 1; i <= p->bands; i++) { - if (p->priomap[i % AIROHA_NUM_QOS_QUEUES] != qidx) + for (i = 0; i < nstrict; i++) { + if (p->priomap[p->bands - i - 1] != i) return -EINVAL; - - qidx = i == nwrr ? 0 : qidx + 1; } - for (i = 0; i < nwrr; i++) + for (i = 0; i < p->bands - nstrict; i++) { + if (p->priomap[i] != nstrict + i) + return -EINVAL; + w[i] = p->weights[nstrict + i]; + } if (!nstrict) mode = TC_SCH_WRR8; @@ -2358,7 +2358,7 @@ static int airoha_tc_get_htb_get_leaf_queue(struct airoha_gdm_port *port, return -EINVAL; } - opt->qid = channel; + opt->qid = AIROHA_NUM_TX_RING + channel; return 0; } @@ -2454,6 +2454,19 @@ static void airoha_metadata_dst_free(struct airoha_gdm_port *port) } } +bool airoha_is_valid_gdm_port(struct airoha_eth *eth, + struct airoha_gdm_port *port) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(eth->ports); i++) { + if (eth->ports[i] == port) + return true; + } + + return false; +} + static int airoha_alloc_gdm_port(struct airoha_eth *eth, struct device_node *np, int index) {
diff --git a/drivers/net/ethernet/airoha/airoha_eth.h b/drivers/net/ethernet/airoha/airoha_eth.h index 60690b6..ec8908f 100644 --- a/drivers/net/ethernet/airoha/airoha_eth.h +++ b/drivers/net/ethernet/airoha/airoha_eth.h
@@ -532,6 +532,9 @@ u32 airoha_rmw(void __iomem *base, u32 offset, u32 mask, u32 val); #define airoha_qdma_clear(qdma, offset, val) \ airoha_rmw((qdma)->regs, (offset), (val), 0) +bool airoha_is_valid_gdm_port(struct airoha_eth *eth, + struct airoha_gdm_port *port); + void airoha_ppe_check_skb(struct airoha_ppe *ppe, u16 hash); int airoha_ppe_setup_tc_block_cb(enum tc_setup_type type, void *type_data, void *cb_priv);
diff --git a/drivers/net/ethernet/airoha/airoha_ppe.c b/drivers/net/ethernet/airoha/airoha_ppe.c index 8b55e87..f10dab9 100644 --- a/drivers/net/ethernet/airoha/airoha_ppe.c +++ b/drivers/net/ethernet/airoha/airoha_ppe.c
@@ -197,7 +197,8 @@ static int airoha_get_dsa_port(struct net_device **dev) #endif } -static int airoha_ppe_foe_entry_prepare(struct airoha_foe_entry *hwe, +static int airoha_ppe_foe_entry_prepare(struct airoha_eth *eth, + struct airoha_foe_entry *hwe, struct net_device *dev, int type, struct airoha_flow_data *data, int l4proto) @@ -225,6 +226,9 @@ static int airoha_ppe_foe_entry_prepare(struct airoha_foe_entry *hwe, struct airoha_gdm_port *port = netdev_priv(dev); u8 pse_port; + if (!airoha_is_valid_gdm_port(eth, port)) + return -EINVAL; + if (dsa_port >= 0) pse_port = port->id == 4 ? FE_PSE_PORT_GDM4 : port->id; else @@ -633,7 +637,7 @@ static int airoha_ppe_flow_offload_replace(struct airoha_gdm_port *port, !is_valid_ether_addr(data.eth.h_dest)) return -EINVAL; - err = airoha_ppe_foe_entry_prepare(&hwe, odev, offload_type, + err = airoha_ppe_foe_entry_prepare(eth, &hwe, odev, offload_type, &data, l4proto); if (err) return err;
diff --git a/drivers/net/ethernet/amazon/ena/ena_netdev.c b/drivers/net/ethernet/amazon/ena/ena_netdev.c index 70fa3ad..897720f 100644 --- a/drivers/net/ethernet/amazon/ena/ena_netdev.c +++ b/drivers/net/ethernet/amazon/ena/ena_netdev.c
@@ -3245,7 +3245,7 @@ static int ena_destroy_device(struct ena_adapter *adapter, bool graceful) netif_carrier_off(netdev); - del_timer_sync(&adapter->timer_service); + timer_delete_sync(&adapter->timer_service); dev_up = test_bit(ENA_FLAG_DEV_UP, &adapter->flags); adapter->dev_up_before_reset = dev_up; @@ -4065,7 +4065,7 @@ static int ena_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ena_free_mgmnt_irq(adapter); ena_disable_msix(adapter); err_worker_destroy: - del_timer(&adapter->timer_service); + timer_delete(&adapter->timer_service); err_device_destroy: ena_com_delete_host_info(ena_dev); ena_com_admin_destroy(ena_dev); @@ -4104,7 +4104,7 @@ static void __ena_shutoff(struct pci_dev *pdev, bool shutdown) /* Make sure timer and reset routine won't be called after * freeing device resources. */ - del_timer_sync(&adapter->timer_service); + timer_delete_sync(&adapter->timer_service); cancel_work_sync(&adapter->reset_task); rtnl_lock(); /* lock released inside the below if-else block */
diff --git a/drivers/net/ethernet/amd/a2065.c b/drivers/net/ethernet/amd/a2065.c index 1ca26a8..b923ad9 100644 --- a/drivers/net/ethernet/amd/a2065.c +++ b/drivers/net/ethernet/amd/a2065.c
@@ -486,7 +486,7 @@ static int lance_close(struct net_device *dev) volatile struct lance_regs *ll = lp->ll; netif_stop_queue(dev); - del_timer_sync(&lp->multicast_timer); + timer_delete_sync(&lp->multicast_timer); /* Stop the card */ ll->rap = LE_CSR0;
diff --git a/drivers/net/ethernet/amd/amd8111e.c b/drivers/net/ethernet/amd/amd8111e.c index f64f96f..86522e8 100644 --- a/drivers/net/ethernet/amd/amd8111e.c +++ b/drivers/net/ethernet/amd/amd8111e.c
@@ -1173,7 +1173,7 @@ static int amd8111e_close(struct net_device *dev) /* Delete ipg timer */ if (lp->options & OPTION_DYN_IPG_ENABLE) - del_timer_sync(&lp->ipg_data.ipg_timer); + timer_delete_sync(&lp->ipg_data.ipg_timer); spin_unlock_irq(&lp->lock); free_irq(dev->irq, dev); @@ -1598,7 +1598,7 @@ static int __maybe_unused amd8111e_suspend(struct device *dev_d) /* stop chip */ spin_lock_irq(&lp->lock); if (lp->options & OPTION_DYN_IPG_ENABLE) - del_timer_sync(&lp->ipg_data.ipg_timer); + timer_delete_sync(&lp->ipg_data.ipg_timer); amd8111e_stop_chip(lp); spin_unlock_irq(&lp->lock);
diff --git a/drivers/net/ethernet/amd/declance.c b/drivers/net/ethernet/amd/declance.c index ec8df05..b072ca5 100644 --- a/drivers/net/ethernet/amd/declance.c +++ b/drivers/net/ethernet/amd/declance.c
@@ -842,7 +842,7 @@ static int lance_close(struct net_device *dev) volatile struct lance_regs *ll = lp->ll; netif_stop_queue(dev); - del_timer_sync(&lp->multicast_timer); + timer_delete_sync(&lp->multicast_timer); /* Stop the card */ writereg(&ll->rap, LE_CSR0);
diff --git a/drivers/net/ethernet/amd/pcnet32.c b/drivers/net/ethernet/amd/pcnet32.c index c6bd803..e5adafe 100644 --- a/drivers/net/ethernet/amd/pcnet32.c +++ b/drivers/net/ethernet/amd/pcnet32.c
@@ -2630,7 +2630,7 @@ static int pcnet32_close(struct net_device *dev) struct pcnet32_private *lp = netdev_priv(dev); unsigned long flags; - del_timer_sync(&lp->watchdog_timer); + timer_delete_sync(&lp->watchdog_timer); netif_stop_queue(dev); napi_disable(&lp->napi);
diff --git a/drivers/net/ethernet/amd/sunlance.c b/drivers/net/ethernet/amd/sunlance.c index 0f98b92..3cd3185 100644 --- a/drivers/net/ethernet/amd/sunlance.c +++ b/drivers/net/ethernet/amd/sunlance.c
@@ -963,7 +963,7 @@ static int lance_close(struct net_device *dev) struct lance_private *lp = netdev_priv(dev); netif_stop_queue(dev); - del_timer_sync(&lp->multicast_timer); + timer_delete_sync(&lp->multicast_timer); STOP_LANCE(lp);
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c index 5475867..d84a310 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
@@ -728,7 +728,7 @@ static void xgbe_stop_timers(struct xgbe_prv_data *pdata) struct xgbe_channel *channel; unsigned int i; - del_timer_sync(&pdata->service_timer); + timer_delete_sync(&pdata->service_timer); for (i = 0; i < pdata->channel_count; i++) { channel = pdata->channel[i]; @@ -736,7 +736,7 @@ static void xgbe_stop_timers(struct xgbe_prv_data *pdata) break; /* Deactivate the Tx timer */ - del_timer_sync(&channel->tx_timer); + timer_delete_sync(&channel->tx_timer); channel->tx_timer_active = 0; } }
diff --git a/drivers/net/ethernet/apple/bmac.c b/drivers/net/ethernet/apple/bmac.c index 785f4b4..b9fdd61 100644 --- a/drivers/net/ethernet/apple/bmac.c +++ b/drivers/net/ethernet/apple/bmac.c
@@ -461,7 +461,7 @@ static int bmac_suspend(struct macio_dev *mdev, pm_message_t state) /* prolly should wait for dma to finish & turn off the chip */ spin_lock_irqsave(&bp->lock, flags); if (bp->timeout_active) { - del_timer(&bp->tx_timeout); + timer_delete(&bp->tx_timeout); bp->timeout_active = 0; } disable_irq(dev->irq); @@ -546,7 +546,7 @@ static inline void bmac_set_timeout(struct net_device *dev) spin_lock_irqsave(&bp->lock, flags); if (bp->timeout_active) - del_timer(&bp->tx_timeout); + timer_delete(&bp->tx_timeout); bp->tx_timeout.expires = jiffies + TX_TIMEOUT; add_timer(&bp->tx_timeout); bp->timeout_active = 1; @@ -755,7 +755,7 @@ static irqreturn_t bmac_txdma_intr(int irq, void *dev_id) XXDEBUG(("bmac_txdma_intr\n")); } - /* del_timer(&bp->tx_timeout); */ + /* timer_delete(&bp->tx_timeout); */ /* bp->timeout_active = 0; */ while (1) {
diff --git a/drivers/net/ethernet/apple/mace.c b/drivers/net/ethernet/apple/mace.c index e635097..1fed112 100644 --- a/drivers/net/ethernet/apple/mace.c +++ b/drivers/net/ethernet/apple/mace.c
@@ -523,7 +523,7 @@ static inline void mace_set_timeout(struct net_device *dev) struct mace_data *mp = netdev_priv(dev); if (mp->timeout_active) - del_timer(&mp->tx_timeout); + timer_delete(&mp->tx_timeout); mp->tx_timeout.expires = jiffies + TX_TIMEOUT; add_timer(&mp->tx_timeout); mp->timeout_active = 1; @@ -676,7 +676,7 @@ static irqreturn_t mace_interrupt(int irq, void *dev_id) i = mp->tx_empty; while (in_8(&mb->pr) & XMTSV) { - del_timer(&mp->tx_timeout); + timer_delete(&mp->tx_timeout); mp->timeout_active = 0; /* * Clear any interrupt indication associated with this status
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c index 71e50fc6..bf3aa46 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
@@ -1389,13 +1389,13 @@ int aq_nic_stop(struct aq_nic_s *self) netif_tx_disable(self->ndev); netif_carrier_off(self->ndev); - del_timer_sync(&self->service_timer); + timer_delete_sync(&self->service_timer); cancel_work_sync(&self->service_task); self->aq_hw_ops->hw_irq_disable(self->aq_hw, AQ_CFG_IRQ_MASK); if (self->aq_nic_cfg.is_polling) - del_timer_sync(&self->polling_timer); + timer_delete_sync(&self->polling_timer); else aq_pci_func_free_irqs(self);
diff --git a/drivers/net/ethernet/atheros/ag71xx.c b/drivers/net/ethernet/atheros/ag71xx.c index 3d4c3d8..67b6548 100644 --- a/drivers/net/ethernet/atheros/ag71xx.c +++ b/drivers/net/ethernet/atheros/ag71xx.c
@@ -1391,7 +1391,7 @@ static void ag71xx_hw_disable(struct ag71xx *ag) ag71xx_dma_reset(ag); napi_disable(&ag->napi); - del_timer_sync(&ag->oom_timer); + timer_delete_sync(&ag->oom_timer); ag71xx_rings_cleanup(ag); }
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c index c571614..82137f9 100644 --- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c +++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
@@ -357,7 +357,7 @@ static void atl1c_common_task(struct work_struct *work) static void atl1c_del_timer(struct atl1c_adapter *adapter) { - del_timer_sync(&adapter->phy_config_timer); + timer_delete_sync(&adapter->phy_config_timer); }
diff --git a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c index 9b778b3..f664a0e 100644 --- a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c +++ b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
@@ -232,7 +232,7 @@ static void atl1e_link_chg_event(struct atl1e_adapter *adapter) static void atl1e_del_timer(struct atl1e_adapter *adapter) { - del_timer_sync(&adapter->phy_config_timer); + timer_delete_sync(&adapter->phy_config_timer); } static void atl1e_cancel_work(struct atl1e_adapter *adapter)
diff --git a/drivers/net/ethernet/atheros/atlx/atl1.c b/drivers/net/ethernet/atheros/atlx/atl1.c index 3afd362..38cd84b 100644 --- a/drivers/net/ethernet/atheros/atlx/atl1.c +++ b/drivers/net/ethernet/atheros/atlx/atl1.c
@@ -2641,7 +2641,7 @@ static void atl1_down(struct atl1_adapter *adapter) napi_disable(&adapter->napi); netif_stop_queue(netdev); - del_timer_sync(&adapter->phy_config_timer); + timer_delete_sync(&adapter->phy_config_timer); adapter->phy_timer_pending = false; atlx_irq_disable(adapter);
diff --git a/drivers/net/ethernet/atheros/atlx/atl2.c b/drivers/net/ethernet/atheros/atlx/atl2.c index fa9a491..88f65f8 100644 --- a/drivers/net/ethernet/atheros/atlx/atl2.c +++ b/drivers/net/ethernet/atheros/atlx/atl2.c
@@ -752,8 +752,8 @@ static void atl2_down(struct atl2_adapter *adapter) atl2_irq_disable(adapter); - del_timer_sync(&adapter->watchdog_timer); - del_timer_sync(&adapter->phy_config_timer); + timer_delete_sync(&adapter->watchdog_timer); + timer_delete_sync(&adapter->phy_config_timer); clear_bit(0, &adapter->cfg_phy); netif_carrier_off(netdev); @@ -1468,8 +1468,8 @@ static void atl2_remove(struct pci_dev *pdev) * explicitly disable watchdog tasks from being rescheduled */ set_bit(__ATL2_DOWN, &adapter->flags); - del_timer_sync(&adapter->watchdog_timer); - del_timer_sync(&adapter->phy_config_timer); + timer_delete_sync(&adapter->watchdog_timer); + timer_delete_sync(&adapter->phy_config_timer); cancel_work_sync(&adapter->reset_task); cancel_work_sync(&adapter->link_chg_task);
diff --git a/drivers/net/ethernet/broadcom/Kconfig b/drivers/net/ethernet/broadcom/Kconfig index eeec8bf..1bd4313 100644 --- a/drivers/net/ethernet/broadcom/Kconfig +++ b/drivers/net/ethernet/broadcom/Kconfig
@@ -143,7 +143,7 @@ depends on PTP_1588_CLOCK_OPTIONAL select FW_LOADER select ZLIB_INFLATE - select LIBCRC32C + select CRC32 select MDIO help This driver supports Broadcom NetXtremeII 10 gigabit Ethernet cards. @@ -207,7 +207,7 @@ depends on PCI depends on PTP_1588_CLOCK_OPTIONAL select FW_LOADER - select LIBCRC32C + select CRC32 select NET_DEVLINK select PAGE_POOL select DIMLIB
diff --git a/drivers/net/ethernet/broadcom/b44.c b/drivers/net/ethernet/broadcom/b44.c index e5809ad..c918843 100644 --- a/drivers/net/ethernet/broadcom/b44.c +++ b/drivers/net/ethernet/broadcom/b44.c
@@ -1628,7 +1628,7 @@ static int b44_close(struct net_device *dev) napi_disable(&bp->napi); - del_timer_sync(&bp->timer); + timer_delete_sync(&bp->timer); spin_lock_irq(&bp->lock); @@ -2473,7 +2473,7 @@ static int b44_suspend(struct ssb_device *sdev, pm_message_t state) if (!netif_running(dev)) return 0; - del_timer_sync(&bp->timer); + timer_delete_sync(&bp->timer); spin_lock_irq(&bp->lock);
diff --git a/drivers/net/ethernet/broadcom/bcm63xx_enet.c b/drivers/net/ethernet/broadcom/bcm63xx_enet.c index 65e3a06..19611bd 100644 --- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c +++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
@@ -1195,7 +1195,7 @@ static int bcm_enet_stop(struct net_device *dev) napi_disable(&priv->napi); if (priv->has_phy) phy_stop(dev->phydev); - del_timer_sync(&priv->rx_timeout); + timer_delete_sync(&priv->rx_timeout); /* mask all interrupts */ enet_writel(priv, 0, ENET_IRMASK_REG); @@ -2346,10 +2346,10 @@ static int bcm_enetsw_stop(struct net_device *dev) priv = netdev_priv(dev); kdev = &priv->pdev->dev; - del_timer_sync(&priv->swphy_poll); + timer_delete_sync(&priv->swphy_poll); netif_stop_queue(dev); napi_disable(&priv->napi); - del_timer_sync(&priv->rx_timeout); + timer_delete_sync(&priv->rx_timeout); /* mask all interrupts */ enet_dmac_writel(priv, 0, ENETDMAC_IRMASK, priv->rx_chan);
diff --git a/drivers/net/ethernet/broadcom/bnx2.c b/drivers/net/ethernet/broadcom/bnx2.c index 6ec773e..ec0c958 100644 --- a/drivers/net/ethernet/broadcom/bnx2.c +++ b/drivers/net/ethernet/broadcom/bnx2.c
@@ -6400,7 +6400,7 @@ bnx2_open(struct net_device *dev) rc = bnx2_request_irq(bp); if (rc) { - del_timer_sync(&bp->timer); + timer_delete_sync(&bp->timer); goto open_err; } bnx2_enable_int(bp); @@ -6752,7 +6752,7 @@ bnx2_close(struct net_device *dev) bnx2_disable_int_sync(bp); bnx2_napi_disable(bp); netif_tx_disable(dev); - del_timer_sync(&bp->timer); + timer_delete_sync(&bp->timer); bnx2_shutdown_chip(bp); bnx2_free_irq(bp); bnx2_free_skbs(bp); @@ -8602,7 +8602,7 @@ bnx2_remove_one(struct pci_dev *pdev) unregister_netdev(dev); - del_timer_sync(&bp->timer); + timer_delete_sync(&bp->timer); cancel_work_sync(&bp->reset_task); pci_iounmap(bp->pdev, bp->regview); @@ -8629,7 +8629,7 @@ bnx2_suspend(struct device *device) cancel_work_sync(&bp->reset_task); bnx2_netif_stop(bp, true); netif_device_detach(dev); - del_timer_sync(&bp->timer); + timer_delete_sync(&bp->timer); bnx2_shutdown_chip(bp); __bnx2_free_irq(bp); bnx2_free_skbs(bp); @@ -8687,7 +8687,7 @@ static pci_ers_result_t bnx2_io_error_detected(struct pci_dev *pdev, if (netif_running(dev)) { bnx2_netif_stop(bp, true); - del_timer_sync(&bp->timer); + timer_delete_sync(&bp->timer); bnx2_reset_nic(bp, BNX2_DRV_MSG_CODE_RESET); }
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c index a8e07e5..e595303 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
@@ -3059,7 +3059,7 @@ int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode, bool keep_link) bp->rx_mode = BNX2X_RX_MODE_NONE; - del_timer_sync(&bp->timer); + timer_delete_sync(&bp->timer); if (IS_PF(bp) && !BP_NOMCP(bp)) { /* Set ALWAYS_ALIVE bit in shmem */
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index 6788296..f522ca8 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
@@ -14140,7 +14140,7 @@ static int bnx2x_eeh_nic_unload(struct bnx2x *bp) bnx2x_tx_disable(bp); netdev_reset_tc(bp->dev); - del_timer_sync(&bp->timer); + timer_delete_sync(&bp->timer); cancel_delayed_work_sync(&bp->sp_task); cancel_delayed_work_sync(&bp->period_task);
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index 934ba94..8725e1e 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -12958,7 +12958,7 @@ static void __bnxt_close_nic(struct bnxt *bp, bool irq_re_init, bnxt_debug_dev_exit(bp); bnxt_disable_napi(bp); - del_timer_sync(&bp->timer); + timer_delete_sync(&bp->timer); bnxt_free_skbs(bp); /* Save ring stats before shutdown */ @@ -15909,7 +15909,7 @@ static int bnxt_queue_start(struct net_device *dev, void *qmem, int idx) goto err_reset; } - napi_enable(&bnapi->napi); + napi_enable_locked(&bnapi->napi); bnxt_db_nq_arm(bp, &cpr->cp_db, cpr->cp_raw_cons); for (i = 0; i < bp->nr_vnics; i++) { @@ -15931,7 +15931,7 @@ static int bnxt_queue_start(struct net_device *dev, void *qmem, int idx) err_reset: netdev_err(bp->dev, "Unexpected HWRM error during queue start rc: %d\n", rc); - napi_enable(&bnapi->napi); + napi_enable_locked(&bnapi->napi); bnxt_db_nq_arm(bp, &cpr->cp_db, cpr->cp_raw_cons); bnxt_reset_task(bp, true); return rc; @@ -15971,7 +15971,7 @@ static int bnxt_queue_stop(struct net_device *dev, void *qmem, int idx) * completion is handled in NAPI to guarantee no more DMA on that ring * after seeing the completion. */ - napi_disable(&bnapi->napi); + napi_disable_locked(&bnapi->napi); if (bp->tph_mode) { bnxt_hwrm_cp_ring_free(bp, rxr->rx_cpr); @@ -16698,6 +16698,7 @@ static void bnxt_shutdown(struct pci_dev *pdev) if (!dev) return; + rtnl_lock(); netdev_lock(dev); bp = netdev_priv(dev); if (!bp) @@ -16717,6 +16718,7 @@ static void bnxt_shutdown(struct pci_dev *pdev) shutdown_exit: netdev_unlock(dev); + rtnl_unlock(); } #ifdef CONFIG_PM_SLEEP
diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index d9d675f..d1f541a 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c
@@ -11252,7 +11252,7 @@ static void tg3_timer_start(struct tg3 *tp) static void tg3_timer_stop(struct tg3 *tp) { - del_timer_sync(&tp->timer); + timer_delete_sync(&tp->timer); } /* Restart hardware after configuration changes, self-test, etc.
diff --git a/drivers/net/ethernet/brocade/bna/bfa_ioc.c b/drivers/net/ethernet/brocade/bna/bfa_ioc.c index 9c80ab0..92c7639 100644 --- a/drivers/net/ethernet/brocade/bna/bfa_ioc.c +++ b/drivers/net/ethernet/brocade/bna/bfa_ioc.c
@@ -314,13 +314,13 @@ bfa_ioc_sm_getattr(struct bfa_ioc *ioc, enum ioc_event event) { switch (event) { case IOC_E_FWRSP_GETATTR: - del_timer(&ioc->ioc_timer); + timer_delete(&ioc->ioc_timer); bfa_fsm_set_state(ioc, bfa_ioc_sm_op); break; case IOC_E_PFFAILED: case IOC_E_HWERROR: - del_timer(&ioc->ioc_timer); + timer_delete(&ioc->ioc_timer); fallthrough; case IOC_E_TIMEOUT: ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE); @@ -330,7 +330,7 @@ bfa_ioc_sm_getattr(struct bfa_ioc *ioc, enum ioc_event event) break; case IOC_E_DISABLE: - del_timer(&ioc->ioc_timer); + timer_delete(&ioc->ioc_timer); bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling); break; @@ -659,13 +659,13 @@ bfa_iocpf_sm_mismatch(struct bfa_iocpf *iocpf, enum iocpf_event event) break; case IOCPF_E_DISABLE: - del_timer(&ioc->iocpf_timer); + timer_delete(&ioc->iocpf_timer); bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset); bfa_ioc_pf_disabled(ioc); break; case IOCPF_E_STOP: - del_timer(&ioc->iocpf_timer); + timer_delete(&ioc->iocpf_timer); bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset); break; @@ -741,7 +741,7 @@ bfa_iocpf_sm_hwinit(struct bfa_iocpf *iocpf, enum iocpf_event event) break; case IOCPF_E_DISABLE: - del_timer(&ioc->iocpf_timer); + timer_delete(&ioc->iocpf_timer); bfa_ioc_sync_leave(ioc); bfa_nw_ioc_hw_sem_release(ioc); bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled); @@ -774,13 +774,13 @@ bfa_iocpf_sm_enabling(struct bfa_iocpf *iocpf, enum iocpf_event event) switch (event) { case IOCPF_E_FWRSP_ENABLE: - del_timer(&ioc->iocpf_timer); + timer_delete(&ioc->iocpf_timer); bfa_nw_ioc_hw_sem_release(ioc); bfa_fsm_set_state(iocpf, bfa_iocpf_sm_ready); break; case IOCPF_E_INITFAIL: - del_timer(&ioc->iocpf_timer); + timer_delete(&ioc->iocpf_timer); fallthrough; case IOCPF_E_TIMEOUT: @@ -791,7 +791,7 @@ bfa_iocpf_sm_enabling(struct bfa_iocpf *iocpf, enum iocpf_event event) break; case IOCPF_E_DISABLE: - del_timer(&ioc->iocpf_timer); + timer_delete(&ioc->iocpf_timer); bfa_nw_ioc_hw_sem_release(ioc); bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling); break; @@ -844,12 +844,12 @@ bfa_iocpf_sm_disabling(struct bfa_iocpf *iocpf, enum iocpf_event event) switch (event) { case IOCPF_E_FWRSP_DISABLE: - del_timer(&ioc->iocpf_timer); + timer_delete(&ioc->iocpf_timer); bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync); break; case IOCPF_E_FAIL: - del_timer(&ioc->iocpf_timer); + timer_delete(&ioc->iocpf_timer); fallthrough; case IOCPF_E_TIMEOUT: @@ -1210,7 +1210,7 @@ bfa_nw_ioc_hw_sem_release(struct bfa_ioc *ioc) static void bfa_ioc_hw_sem_get_cancel(struct bfa_ioc *ioc) { - del_timer(&ioc->sem_timer); + timer_delete(&ioc->sem_timer); } /* Initialize LPU local memory (aka secondary memory / SRAM) */ @@ -1982,7 +1982,7 @@ bfa_ioc_hb_monitor(struct bfa_ioc *ioc) static void bfa_ioc_hb_stop(struct bfa_ioc *ioc) { - del_timer(&ioc->hb_timer); + timer_delete(&ioc->hb_timer); } /* Initiate a full firmware download. */
diff --git a/drivers/net/ethernet/brocade/bna/bnad.c b/drivers/net/ethernet/brocade/bna/bnad.c index 3b91070..a03eff3 100644 --- a/drivers/net/ethernet/brocade/bna/bnad.c +++ b/drivers/net/ethernet/brocade/bna/bnad.c
@@ -1837,7 +1837,7 @@ bnad_stats_timer_stop(struct bnad *bnad) to_del = 1; spin_unlock_irqrestore(&bnad->bna_lock, flags); if (to_del) - del_timer_sync(&bnad->stats_timer); + timer_delete_sync(&bnad->stats_timer); } /* Utilities */ @@ -2160,7 +2160,7 @@ bnad_destroy_rx(struct bnad *bnad, u32 rx_id) } spin_unlock_irqrestore(&bnad->bna_lock, flags); if (to_del) - del_timer_sync(&bnad->dim_timer); + timer_delete_sync(&bnad->dim_timer); } init_completion(&bnad->bnad_completions.rx_comp); @@ -3726,9 +3726,9 @@ bnad_pci_probe(struct pci_dev *pdev, bnad_res_free(bnad, &bnad->mod_res_info[0], BNA_MOD_RES_T_MAX); disable_ioceth: bnad_ioceth_disable(bnad); - del_timer_sync(&bnad->bna.ioceth.ioc.ioc_timer); - del_timer_sync(&bnad->bna.ioceth.ioc.sem_timer); - del_timer_sync(&bnad->bna.ioceth.ioc.hb_timer); + timer_delete_sync(&bnad->bna.ioceth.ioc.ioc_timer); + timer_delete_sync(&bnad->bna.ioceth.ioc.sem_timer); + timer_delete_sync(&bnad->bna.ioceth.ioc.hb_timer); spin_lock_irqsave(&bnad->bna_lock, flags); bna_uninit(bna); spin_unlock_irqrestore(&bnad->bna_lock, flags); @@ -3769,9 +3769,9 @@ bnad_pci_remove(struct pci_dev *pdev) mutex_lock(&bnad->conf_mutex); bnad_ioceth_disable(bnad); - del_timer_sync(&bnad->bna.ioceth.ioc.ioc_timer); - del_timer_sync(&bnad->bna.ioceth.ioc.sem_timer); - del_timer_sync(&bnad->bna.ioceth.ioc.hb_timer); + timer_delete_sync(&bnad->bna.ioceth.ioc.ioc_timer); + timer_delete_sync(&bnad->bna.ioceth.ioc.sem_timer); + timer_delete_sync(&bnad->bna.ioceth.ioc.hb_timer); spin_lock_irqsave(&bnad->bna_lock, flags); bna_uninit(bna); spin_unlock_irqrestore(&bnad->bna_lock, flags);
diff --git a/drivers/net/ethernet/brocade/bna/bnad_ethtool.c b/drivers/net/ethernet/brocade/bna/bnad_ethtool.c index d1ad6c9..216e25f 100644 --- a/drivers/net/ethernet/brocade/bna/bnad_ethtool.c +++ b/drivers/net/ethernet/brocade/bna/bnad_ethtool.c
@@ -373,7 +373,7 @@ static int bnad_set_coalesce(struct net_device *netdev, } spin_unlock_irqrestore(&bnad->bna_lock, flags); if (to_del) - del_timer_sync(&bnad->dim_timer); + timer_delete_sync(&bnad->dim_timer); spin_lock_irqsave(&bnad->bna_lock, flags); bnad_rx_coalescing_timeo_set(bnad); }
diff --git a/drivers/net/ethernet/cavium/Kconfig b/drivers/net/ethernet/cavium/Kconfig index ca742cc..7dae5aa 100644 --- a/drivers/net/ethernet/cavium/Kconfig +++ b/drivers/net/ethernet/cavium/Kconfig
@@ -70,8 +70,8 @@ depends on 64BIT && PCI depends on PCI depends on PTP_1588_CLOCK_OPTIONAL + select CRC32 select FW_LOADER - select LIBCRC32C select LIQUIDIO_CORE select NET_DEVLINK help
diff --git a/drivers/net/ethernet/chelsio/cxgb/sge.c b/drivers/net/ethernet/chelsio/cxgb/sge.c index 861edff..a10923c 100644 --- a/drivers/net/ethernet/chelsio/cxgb/sge.c +++ b/drivers/net/ethernet/chelsio/cxgb/sge.c
@@ -1984,9 +1984,9 @@ void t1_sge_stop(struct sge *sge) readl(sge->adapter->regs + A_SG_CONTROL); /* flush */ if (is_T2(sge->adapter)) - del_timer_sync(&sge->espibug_timer); + timer_delete_sync(&sge->espibug_timer); - del_timer_sync(&sge->tx_reclaim_timer); + timer_delete_sync(&sge->tx_reclaim_timer); if (sge->tx_sched) tx_sched_stop(sge);
diff --git a/drivers/net/ethernet/chelsio/cxgb3/sge.c b/drivers/net/ethernet/chelsio/cxgb3/sge.c index 6268f96..bd5c3b3 100644 --- a/drivers/net/ethernet/chelsio/cxgb3/sge.c +++ b/drivers/net/ethernet/chelsio/cxgb3/sge.c
@@ -3223,9 +3223,9 @@ void t3_stop_sge_timers(struct adapter *adap) struct sge_qset *q = &adap->sge.qs[i]; if (q->tx_reclaim_timer.function) - del_timer_sync(&q->tx_reclaim_timer); + timer_delete_sync(&q->tx_reclaim_timer); if (q->rx_reclaim_timer.function) - del_timer_sync(&q->rx_reclaim_timer); + timer_delete_sync(&q->rx_reclaim_timer); } }
diff --git a/drivers/net/ethernet/chelsio/cxgb4/sge.c b/drivers/net/ethernet/chelsio/cxgb4/sge.c index a7d76a8..f991a28 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/sge.c +++ b/drivers/net/ethernet/chelsio/cxgb4/sge.c
@@ -4996,9 +4996,9 @@ void t4_sge_stop(struct adapter *adap) struct sge *s = &adap->sge; if (s->rx_timer.function) - del_timer_sync(&s->rx_timer); + timer_delete_sync(&s->rx_timer); if (s->tx_timer.function) - del_timer_sync(&s->tx_timer); + timer_delete_sync(&s->tx_timer); if (is_offload(adap)) { struct sge_uld_txq_info *txq_info;
diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/sge.c b/drivers/net/ethernet/chelsio/cxgb4vf/sge.c index 5b1d746..f42af01 100644 --- a/drivers/net/ethernet/chelsio/cxgb4vf/sge.c +++ b/drivers/net/ethernet/chelsio/cxgb4vf/sge.c
@@ -2609,9 +2609,9 @@ void t4vf_sge_stop(struct adapter *adapter) struct sge *s = &adapter->sge; if (s->rx_timer.function) - del_timer_sync(&s->rx_timer); + timer_delete_sync(&s->rx_timer); if (s->tx_timer.function) - del_timer_sync(&s->tx_timer); + timer_delete_sync(&s->tx_timer); } /**
diff --git a/drivers/net/ethernet/cisco/enic/enic_clsf.h b/drivers/net/ethernet/cisco/enic/enic_clsf.h index 8c4ce50..5f52841 100644 --- a/drivers/net/ethernet/cisco/enic/enic_clsf.h +++ b/drivers/net/ethernet/cisco/enic/enic_clsf.h
@@ -26,7 +26,7 @@ static inline void enic_rfs_timer_start(struct enic *enic) static inline void enic_rfs_timer_stop(struct enic *enic) { - del_timer_sync(&enic->rfs_h.rfs_may_expire); + timer_delete_sync(&enic->rfs_h.rfs_may_expire); } #else static inline void enic_rfs_timer_start(struct enic *enic) {}
diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c index 54aa395..c753c35 100644 --- a/drivers/net/ethernet/cisco/enic/enic_main.c +++ b/drivers/net/ethernet/cisco/enic/enic_main.c
@@ -1787,7 +1787,7 @@ static int enic_stop(struct net_device *netdev) enic_synchronize_irqs(enic); - del_timer_sync(&enic->notify_timer); + timer_delete_sync(&enic->notify_timer); enic_rfs_flw_tbl_free(enic); enic_dev_disable(enic);
diff --git a/drivers/net/ethernet/dec/tulip/21142.c b/drivers/net/ethernet/dec/tulip/21142.c index 3698582..76767de 100644 --- a/drivers/net/ethernet/dec/tulip/21142.c +++ b/drivers/net/ethernet/dec/tulip/21142.c
@@ -216,7 +216,7 @@ void t21142_lnk_change(struct net_device *dev, int csr5) (csr12 & 2) == 2) || (tp->nway && (csr5 & (TPLnkFail)))) { /* Link blew? Maybe restart NWay. */ - del_timer_sync(&tp->timer); + timer_delete_sync(&tp->timer); t21142_start_nway(dev); tp->timer.expires = RUN_AT(3*HZ); add_timer(&tp->timer); @@ -226,7 +226,7 @@ void t21142_lnk_change(struct net_device *dev, int csr5) medianame[dev->if_port], (csr12 & 2) ? "failed" : "good"); if ((csr12 & 2) && ! tp->medialock) { - del_timer_sync(&tp->timer); + timer_delete_sync(&tp->timer); t21142_start_nway(dev); tp->timer.expires = RUN_AT(3*HZ); add_timer(&tp->timer);
diff --git a/drivers/net/ethernet/dec/tulip/de2104x.c b/drivers/net/ethernet/dec/tulip/de2104x.c index 0a161a4..f9339d0 100644 --- a/drivers/net/ethernet/dec/tulip/de2104x.c +++ b/drivers/net/ethernet/dec/tulip/de2104x.c
@@ -1428,7 +1428,7 @@ static int de_close (struct net_device *dev) netif_dbg(de, ifdown, dev, "disabling interface\n"); - del_timer_sync(&de->media_timer); + timer_delete_sync(&de->media_timer); spin_lock_irqsave(&de->lock, flags); de_stop_hw(de); @@ -1452,7 +1452,7 @@ static void de_tx_timeout (struct net_device *dev, unsigned int txqueue) dr32(MacStatus), dr32(MacMode), dr32(SIAStatus), de->rx_tail, de->tx_head, de->tx_tail); - del_timer_sync(&de->media_timer); + timer_delete_sync(&de->media_timer); disable_irq(irq); spin_lock_irq(&de->lock); @@ -2126,7 +2126,7 @@ static int __maybe_unused de_suspend(struct device *dev_d) if (netif_running (dev)) { const int irq = pdev->irq; - del_timer_sync(&de->media_timer); + timer_delete_sync(&de->media_timer); disable_irq(irq); spin_lock_irq(&de->lock);
diff --git a/drivers/net/ethernet/dec/tulip/dmfe.c b/drivers/net/ethernet/dec/tulip/dmfe.c index 3188ba7..ae34b95 100644 --- a/drivers/net/ethernet/dec/tulip/dmfe.c +++ b/drivers/net/ethernet/dec/tulip/dmfe.c
@@ -745,7 +745,7 @@ static int dmfe_stop(struct net_device *dev) netif_stop_queue(dev); /* deleted timer */ - del_timer_sync(&db->timer); + timer_delete_sync(&db->timer); /* Reset & stop DM910X board */ dw32(DCR0, DM910X_RESET);
diff --git a/drivers/net/ethernet/dec/tulip/interrupt.c b/drivers/net/ethernet/dec/tulip/interrupt.c index 54560f9..2d926a2 100644 --- a/drivers/net/ethernet/dec/tulip/interrupt.c +++ b/drivers/net/ethernet/dec/tulip/interrupt.c
@@ -699,8 +699,8 @@ irqreturn_t tulip_interrupt(int irq, void *dev_instance) tulip_start_rxtx(tp); } /* - * NB: t21142_lnk_change() does a del_timer_sync(), so be careful if this - * call is ever done under the spinlock + * NB: t21142_lnk_change() does a timer_delete_sync(), so be careful + * if this call is ever done under the spinlock */ if (csr5 & (TPLnkPass | TPLnkFail | 0x08000000)) { if (tp->link_change)
diff --git a/drivers/net/ethernet/dec/tulip/pnic2.c b/drivers/net/ethernet/dec/tulip/pnic2.c index 72a0915..2e3bdc0 100644 --- a/drivers/net/ethernet/dec/tulip/pnic2.c +++ b/drivers/net/ethernet/dec/tulip/pnic2.c
@@ -323,7 +323,7 @@ void pnic2_lnk_change(struct net_device *dev, int csr5) if (tulip_debug > 2) netdev_dbg(dev, "Ugh! Link blew?\n"); - del_timer_sync(&tp->timer); + timer_delete_sync(&tp->timer); pnic2_start_nway(dev); tp->timer.expires = RUN_AT(3*HZ); add_timer(&tp->timer); @@ -348,7 +348,7 @@ void pnic2_lnk_change(struct net_device *dev, int csr5) /* if failed then try doing an nway to get in sync */ if ((csr12 & 2) && ! tp->medialock) { - del_timer_sync(&tp->timer); + timer_delete_sync(&tp->timer); pnic2_start_nway(dev); tp->timer.expires = RUN_AT(3*HZ); add_timer(&tp->timer); @@ -372,7 +372,7 @@ void pnic2_lnk_change(struct net_device *dev, int csr5) /* if failed, try doing an nway to get in sync */ if ((csr12 & 4) && ! tp->medialock) { - del_timer_sync(&tp->timer); + timer_delete_sync(&tp->timer); pnic2_start_nway(dev); tp->timer.expires = RUN_AT(3*HZ); add_timer(&tp->timer);
diff --git a/drivers/net/ethernet/dec/tulip/tulip_core.c b/drivers/net/ethernet/dec/tulip/tulip_core.c index 75eac18..c8c5312 100644 --- a/drivers/net/ethernet/dec/tulip/tulip_core.c +++ b/drivers/net/ethernet/dec/tulip/tulip_core.c
@@ -747,9 +747,9 @@ static void tulip_down (struct net_device *dev) napi_disable(&tp->napi); #endif - del_timer_sync (&tp->timer); + timer_delete_sync(&tp->timer); #ifdef CONFIG_TULIP_NAPI - del_timer_sync (&tp->oom_timer); + timer_delete_sync(&tp->oom_timer); #endif spin_lock_irqsave (&tp->lock, flags);
diff --git a/drivers/net/ethernet/dec/tulip/uli526x.c b/drivers/net/ethernet/dec/tulip/uli526x.c index ff080ab..3f1bd67 100644 --- a/drivers/net/ethernet/dec/tulip/uli526x.c +++ b/drivers/net/ethernet/dec/tulip/uli526x.c
@@ -656,7 +656,7 @@ static int uli526x_stop(struct net_device *dev) netif_stop_queue(dev); /* deleted timer */ - del_timer_sync(&db->timer); + timer_delete_sync(&db->timer); /* Reset & stop ULI526X board */ uw32(DCR0, ULI526X_RESET);
diff --git a/drivers/net/ethernet/dec/tulip/winbond-840.c b/drivers/net/ethernet/dec/tulip/winbond-840.c index 37fba39..5930cde 100644 --- a/drivers/net/ethernet/dec/tulip/winbond-840.c +++ b/drivers/net/ethernet/dec/tulip/winbond-840.c
@@ -1509,7 +1509,7 @@ static int netdev_close(struct net_device *dev) } #endif /* __i386__ debugging only */ - del_timer_sync(&np->timer); + timer_delete_sync(&np->timer); free_rxtx_rings(np); free_ringdesc(np); @@ -1560,7 +1560,7 @@ static int __maybe_unused w840_suspend(struct device *dev_d) rtnl_lock(); if (netif_running (dev)) { - del_timer_sync(&np->timer); + timer_delete_sync(&np->timer); spin_lock_irq(&np->lock); netif_device_detach(dev);
diff --git a/drivers/net/ethernet/dlink/dl2k.c b/drivers/net/ethernet/dlink/dl2k.c index d0ea926..d88fbec 100644 --- a/drivers/net/ethernet/dlink/dl2k.c +++ b/drivers/net/ethernet/dlink/dl2k.c
@@ -1778,7 +1778,7 @@ rio_close (struct net_device *dev) rio_hw_stop(dev); free_irq(pdev->irq, dev); - del_timer_sync (&np->timer); + timer_delete_sync(&np->timer); free_list(dev); @@ -1818,7 +1818,7 @@ static int rio_suspend(struct device *device) return 0; netif_device_detach(dev); - del_timer_sync(&np->timer); + timer_delete_sync(&np->timer); rio_hw_stop(dev); return 0;
diff --git a/drivers/net/ethernet/fealnx.c b/drivers/net/ethernet/fealnx.c index ed18450f..670b682 100644 --- a/drivers/net/ethernet/fealnx.c +++ b/drivers/net/ethernet/fealnx.c
@@ -1900,8 +1900,8 @@ static int netdev_close(struct net_device *dev) /* Stop the chip's Tx and Rx processes. */ stop_nic_rxtx(ioaddr, 0); - del_timer_sync(&np->timer); - del_timer_sync(&np->reset_timer); + timer_delete_sync(&np->timer); + timer_delete_sync(&np->reset_timer); free_irq(np->pci_dev->irq, dev);
diff --git a/drivers/net/ethernet/google/gve/gve_ethtool.c b/drivers/net/ethernet/google/gve/gve_ethtool.c index 31a21cc..eae1a75 100644 --- a/drivers/net/ethernet/google/gve/gve_ethtool.c +++ b/drivers/net/ethernet/google/gve/gve_ethtool.c
@@ -392,7 +392,9 @@ gve_get_ethtool_stats(struct net_device *netdev, */ data[i++] = 0; data[i++] = 0; - data[i++] = tx->dqo_tx.tail - tx->dqo_tx.head; + data[i++] = + (tx->dqo_tx.tail - tx->dqo_tx.head) & + tx->mask; } do { start = @@ -703,7 +705,7 @@ static int gve_set_priv_flags(struct net_device *netdev, u32 flags) memset(priv->stats_report->stats, 0, (tx_stats_num + rx_stats_num) * sizeof(struct stats)); - del_timer_sync(&priv->stats_report_timer); + timer_delete_sync(&priv->stats_report_timer); } return 0; }
diff --git a/drivers/net/ethernet/google/gve/gve_main.c b/drivers/net/ethernet/google/gve/gve_main.c index cb2f997..c3791cf 100644 --- a/drivers/net/ethernet/google/gve/gve_main.c +++ b/drivers/net/ethernet/google/gve/gve_main.c
@@ -302,7 +302,7 @@ static void gve_free_stats_report(struct gve_priv *priv) if (!priv->stats_report) return; - del_timer_sync(&priv->stats_report_timer); + timer_delete_sync(&priv->stats_report_timer); dma_free_coherent(&priv->pdev->dev, priv->stats_report_len, priv->stats_report, priv->stats_report_bus); priv->stats_report = NULL; @@ -1408,7 +1408,7 @@ static int gve_queues_stop(struct gve_priv *priv) goto err; gve_clear_device_rings_ok(priv); } - del_timer_sync(&priv->stats_report_timer); + timer_delete_sync(&priv->stats_report_timer); gve_unreg_xdp_info(priv); @@ -2077,7 +2077,9 @@ static void gve_handle_reset(struct gve_priv *priv) if (gve_get_do_reset(priv)) { rtnl_lock(); + netdev_lock(priv->dev); gve_reset(priv, false); + netdev_unlock(priv->dev); rtnl_unlock(); } } @@ -2714,6 +2716,7 @@ static void gve_shutdown(struct pci_dev *pdev) bool was_up = netif_running(priv->dev); rtnl_lock(); + netdev_lock(netdev); if (was_up && gve_close(priv->dev)) { /* If the dev was up, attempt to close, if close fails, reset */ gve_reset_and_teardown(priv, was_up); @@ -2721,6 +2724,7 @@ static void gve_shutdown(struct pci_dev *pdev) /* If the dev wasn't up or close worked, finish tearing down */ gve_teardown_priv_resources(priv); } + netdev_unlock(netdev); rtnl_unlock(); }
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_enet.c b/drivers/net/ethernet/hisilicon/hns/hns_enet.c index 42bb341..d98f8d3 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_enet.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_enet.c
@@ -1402,7 +1402,7 @@ static void hns_nic_net_down(struct net_device *ndev) if (test_and_set_bit(NIC_STATE_DOWN, &priv->state)) return; - (void)del_timer_sync(&priv->service_timer); + (void) timer_delete_sync(&priv->service_timer); netif_tx_stop_all_queues(ndev); netif_carrier_off(ndev); netif_tx_disable(ndev);
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 92f9b8e..3e28a089 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
@@ -11492,7 +11492,7 @@ static void hclge_state_uninit(struct hclge_dev *hdev) set_bit(HCLGE_STATE_REMOVING, &hdev->state); if (hdev->reset_timer.function) - del_timer_sync(&hdev->reset_timer); + timer_delete_sync(&hdev->reset_timer); if (hdev->service_task.work.func) cancel_delayed_work_sync(&hdev->service_task); }
diff --git a/drivers/net/ethernet/ibm/ibmveth.c b/drivers/net/ethernet/ibm/ibmveth.c index b619a3e..0419219 100644 --- a/drivers/net/ethernet/ibm/ibmveth.c +++ b/drivers/net/ethernet/ibm/ibmveth.c
@@ -1802,18 +1802,22 @@ static ssize_t veth_pool_store(struct kobject *kobj, struct attribute *attr, long value = simple_strtol(buf, NULL, 10); long rc; + rtnl_lock(); + if (attr == &veth_active_attr) { if (value && !pool->active) { if (netif_running(netdev)) { if (ibmveth_alloc_buffer_pool(pool)) { netdev_err(netdev, "unable to alloc pool\n"); - return -ENOMEM; + rc = -ENOMEM; + goto unlock_err; } pool->active = 1; ibmveth_close(netdev); - if ((rc = ibmveth_open(netdev))) - return rc; + rc = ibmveth_open(netdev); + if (rc) + goto unlock_err; } else { pool->active = 1; } @@ -1833,48 +1837,59 @@ static ssize_t veth_pool_store(struct kobject *kobj, struct attribute *attr, if (i == IBMVETH_NUM_BUFF_POOLS) { netdev_err(netdev, "no active pool >= MTU\n"); - return -EPERM; + rc = -EPERM; + goto unlock_err; } if (netif_running(netdev)) { ibmveth_close(netdev); pool->active = 0; - if ((rc = ibmveth_open(netdev))) - return rc; + rc = ibmveth_open(netdev); + if (rc) + goto unlock_err; } pool->active = 0; } } else if (attr == &veth_num_attr) { if (value <= 0 || value > IBMVETH_MAX_POOL_COUNT) { - return -EINVAL; + rc = -EINVAL; + goto unlock_err; } else { if (netif_running(netdev)) { ibmveth_close(netdev); pool->size = value; - if ((rc = ibmveth_open(netdev))) - return rc; + rc = ibmveth_open(netdev); + if (rc) + goto unlock_err; } else { pool->size = value; } } } else if (attr == &veth_size_attr) { if (value <= IBMVETH_BUFF_OH || value > IBMVETH_MAX_BUF_SIZE) { - return -EINVAL; + rc = -EINVAL; + goto unlock_err; } else { if (netif_running(netdev)) { ibmveth_close(netdev); pool->buff_size = value; - if ((rc = ibmveth_open(netdev))) - return rc; + rc = ibmveth_open(netdev); + if (rc) + goto unlock_err; } else { pool->buff_size = value; } } } + rtnl_unlock(); /* kick the interrupt handler to allocate/deallocate pools */ ibmveth_interrupt(netdev->irq, netdev); return count; + +unlock_err: + rtnl_unlock(); + return rc; }
diff --git a/drivers/net/ethernet/intel/e100.c b/drivers/net/ethernet/intel/e100.c index 3a5bbda..c0ead54 100644 --- a/drivers/net/ethernet/intel/e100.c +++ b/drivers/net/ethernet/intel/e100.c
@@ -2293,7 +2293,7 @@ static int e100_up(struct nic *nic) return 0; err_no_irq: - del_timer_sync(&nic->watchdog); + timer_delete_sync(&nic->watchdog); err_clean_cbs: e100_clean_cbs(nic); err_rx_clean_list: @@ -2308,7 +2308,7 @@ static void e100_down(struct nic *nic) netif_stop_queue(nic->netdev); e100_hw_reset(nic); free_irq(nic->pdev->irq, nic->netdev); - del_timer_sync(&nic->watchdog); + timer_delete_sync(&nic->watchdog); netif_carrier_off(nic->netdev); e100_clean_cbs(nic); e100_rx_clean_list(nic);
diff --git a/drivers/net/ethernet/intel/e1000e/defines.h b/drivers/net/ethernet/intel/e1000e/defines.h index 5e2cfa7..8294a7c 100644 --- a/drivers/net/ethernet/intel/e1000e/defines.h +++ b/drivers/net/ethernet/intel/e1000e/defines.h
@@ -803,4 +803,7 @@ /* SerDes Control */ #define E1000_GEN_POLL_TIMEOUT 640 +#define E1000_FEXTNVM12_PHYPD_CTRL_MASK 0x00C00000 +#define E1000_FEXTNVM12_PHYPD_CTRL_P1 0x00800000 + #endif /* _E1000_DEFINES_H_ */
diff --git a/drivers/net/ethernet/intel/e1000e/ich8lan.c b/drivers/net/ethernet/intel/e1000e/ich8lan.c index 2f9655c..3643781 100644 --- a/drivers/net/ethernet/intel/e1000e/ich8lan.c +++ b/drivers/net/ethernet/intel/e1000e/ich8lan.c
@@ -286,6 +286,45 @@ static void e1000_toggle_lanphypc_pch_lpt(struct e1000_hw *hw) } /** + * e1000_reconfigure_k1_exit_timeout - reconfigure K1 exit timeout to + * align to MTP and later platform requirements. + * @hw: pointer to the HW structure + * + * Context: PHY semaphore must be held by caller. + * Return: 0 on success, negative on failure + */ +static s32 e1000_reconfigure_k1_exit_timeout(struct e1000_hw *hw) +{ + u16 phy_timeout; + u32 fextnvm12; + s32 ret_val; + + if (hw->mac.type < e1000_pch_mtp) + return 0; + + /* Change Kumeran K1 power down state from P0s to P1 */ + fextnvm12 = er32(FEXTNVM12); + fextnvm12 &= ~E1000_FEXTNVM12_PHYPD_CTRL_MASK; + fextnvm12 |= E1000_FEXTNVM12_PHYPD_CTRL_P1; + ew32(FEXTNVM12, fextnvm12); + + /* Wait for the interface the settle */ + usleep_range(1000, 1100); + + /* Change K1 exit timeout */ + ret_val = e1e_rphy_locked(hw, I217_PHY_TIMEOUTS_REG, + &phy_timeout); + if (ret_val) + return ret_val; + + phy_timeout &= ~I217_PHY_TIMEOUTS_K1_EXIT_TO_MASK; + phy_timeout |= 0xF00; + + return e1e_wphy_locked(hw, I217_PHY_TIMEOUTS_REG, + phy_timeout); +} + +/** * e1000_init_phy_workarounds_pchlan - PHY initialization workarounds * @hw: pointer to the HW structure * @@ -327,15 +366,22 @@ static s32 e1000_init_phy_workarounds_pchlan(struct e1000_hw *hw) * LANPHYPC Value bit to force the interconnect to PCIe mode. */ switch (hw->mac.type) { + case e1000_pch_mtp: + case e1000_pch_lnp: + case e1000_pch_ptp: + case e1000_pch_nvp: + /* At this point the PHY might be inaccessible so don't + * propagate the failure + */ + if (e1000_reconfigure_k1_exit_timeout(hw)) + e_dbg("Failed to reconfigure K1 exit timeout\n"); + + fallthrough; case e1000_pch_lpt: case e1000_pch_spt: case e1000_pch_cnp: case e1000_pch_tgp: case e1000_pch_adp: - case e1000_pch_mtp: - case e1000_pch_lnp: - case e1000_pch_ptp: - case e1000_pch_nvp: if (e1000_phy_is_accessible_pchlan(hw)) break; @@ -419,8 +465,20 @@ static s32 e1000_init_phy_workarounds_pchlan(struct e1000_hw *hw) * the PHY is in. */ ret_val = hw->phy.ops.check_reset_block(hw); - if (ret_val) + if (ret_val) { e_err("ME blocked access to PHY after reset\n"); + goto out; + } + + if (hw->mac.type >= e1000_pch_mtp) { + ret_val = hw->phy.ops.acquire(hw); + if (ret_val) { + e_err("Failed to reconfigure K1 exit timeout\n"); + goto out; + } + ret_val = e1000_reconfigure_k1_exit_timeout(hw); + hw->phy.ops.release(hw); + } } out: @@ -4888,6 +4946,18 @@ static s32 e1000_init_hw_ich8lan(struct e1000_hw *hw) u16 i; e1000_initialize_hw_bits_ich8lan(hw); + if (hw->mac.type >= e1000_pch_mtp) { + ret_val = hw->phy.ops.acquire(hw); + if (ret_val) + return ret_val; + + ret_val = e1000_reconfigure_k1_exit_timeout(hw); + hw->phy.ops.release(hw); + if (ret_val) { + e_dbg("Error failed to reconfigure K1 exit timeout\n"); + return ret_val; + } + } /* Initialize identification LED */ ret_val = mac->ops.id_led_init(hw);
diff --git a/drivers/net/ethernet/intel/e1000e/ich8lan.h b/drivers/net/ethernet/intel/e1000e/ich8lan.h index 2504b11..5feb589 100644 --- a/drivers/net/ethernet/intel/e1000e/ich8lan.h +++ b/drivers/net/ethernet/intel/e1000e/ich8lan.h
@@ -219,6 +219,10 @@ #define I217_PLL_CLOCK_GATE_REG PHY_REG(772, 28) #define I217_PLL_CLOCK_GATE_MASK 0x07FF +/* PHY Timeouts */ +#define I217_PHY_TIMEOUTS_REG PHY_REG(770, 21) +#define I217_PHY_TIMEOUTS_K1_EXIT_TO_MASK 0x0FC0 + #define SW_FLAG_TIMEOUT 1000 /* SW Semaphore flag timeout in ms */ /* Inband Control */
diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c index 286155ef..8ebcb6a 100644 --- a/drivers/net/ethernet/intel/e1000e/netdev.c +++ b/drivers/net/ethernet/intel/e1000e/netdev.c
@@ -4287,8 +4287,8 @@ void e1000e_down(struct e1000_adapter *adapter, bool reset) napi_synchronize(&adapter->napi); - del_timer_sync(&adapter->watchdog_timer); - del_timer_sync(&adapter->phy_info_timer); + timer_delete_sync(&adapter->watchdog_timer); + timer_delete_sync(&adapter->phy_info_timer); spin_lock(&adapter->stats64_lock); e1000e_update_stats(adapter); @@ -7741,8 +7741,8 @@ static void e1000_remove(struct pci_dev *pdev) * from being rescheduled. */ set_bit(__E1000_DOWN, &adapter->state); - del_timer_sync(&adapter->watchdog_timer); - del_timer_sync(&adapter->phy_info_timer); + timer_delete_sync(&adapter->watchdog_timer); + timer_delete_sync(&adapter->phy_info_timer); cancel_work_sync(&adapter->reset_task); cancel_work_sync(&adapter->watchdog_task);
diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c index 92de609..21267ab 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c
@@ -2245,7 +2245,7 @@ static void fm10k_remove(struct pci_dev *pdev) struct fm10k_intfc *interface = pci_get_drvdata(pdev); struct net_device *netdev = interface->netdev; - del_timer_sync(&interface->service_timer); + timer_delete_sync(&interface->service_timer); fm10k_stop_service_event(interface); fm10k_stop_macvlan_task(interface);
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 65a7026..120d686 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -16382,7 +16382,7 @@ static int i40e_io_suspend(struct i40e_pf *pf) set_bit(__I40E_DOWN, pf->state); /* Ensure service task will not be running */ - del_timer_sync(&pf->service_timer); + timer_delete_sync(&pf->service_timer); cancel_work_sync(&pf->service_task); /* Client close must be called explicitly here because the timer @@ -16581,7 +16581,7 @@ static void i40e_shutdown(struct pci_dev *pdev) set_bit(__I40E_SUSPENDED, pf->state); set_bit(__I40E_DOWN, pf->state); - del_timer_sync(&pf->service_timer); + timer_delete_sync(&pf->service_timer); cancel_work_sync(&pf->service_task); i40e_cloud_filter_exit(pf); i40e_fdir_teardown(pf);
diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c index 049edeb..d390157 100644 --- a/drivers/net/ethernet/intel/ice/ice_main.c +++ b/drivers/net/ethernet/intel/ice/ice_main.c
@@ -1717,7 +1717,7 @@ static int ice_service_task_stop(struct ice_pf *pf) ret = test_and_set_bit(ICE_SERVICE_DIS, pf->state); if (pf->serv_tmr.function) - del_timer_sync(&pf->serv_tmr); + timer_delete_sync(&pf->serv_tmr); if (pf->serv_task.func) cancel_work_sync(&pf->serv_task);
diff --git a/drivers/net/ethernet/intel/ice/ice_virtchnl_fdir.c b/drivers/net/ethernet/intel/ice/ice_virtchnl_fdir.c index 9be4bd7..7752920 100644 --- a/drivers/net/ethernet/intel/ice/ice_virtchnl_fdir.c +++ b/drivers/net/ethernet/intel/ice/ice_virtchnl_fdir.c
@@ -1521,7 +1521,7 @@ ice_vc_fdir_irq_handler(struct ice_vsi *ctrl_vsi, memcpy(&ctx_done->rx_desc, rx_desc, sizeof(*rx_desc)); spin_unlock_irqrestore(&fdir->ctx_lock, flags); - ret = del_timer(&ctx_irq->rx_tmr); + ret = timer_delete(&ctx_irq->rx_tmr); if (!ret) dev_err(dev, "VF %d: Unexpected inactive timer!\n", vf->vf_id); @@ -1916,7 +1916,7 @@ static void ice_vc_fdir_clear_irq_ctx(struct ice_vf *vf) struct ice_vf_fdir_ctx *ctx = &vf->fdir.ctx_irq; unsigned long flags; - del_timer(&ctx->rx_tmr); + timer_delete(&ctx->rx_tmr); spin_lock_irqsave(&vf->fdir.ctx_lock, flags); ctx->flags &= ~ICE_VF_FDIR_CTX_VALID; spin_unlock_irqrestore(&vf->fdir.ctx_lock, flags);
diff --git a/drivers/net/ethernet/intel/idpf/idpf_main.c b/drivers/net/ethernet/intel/idpf/idpf_main.c index b6c515d..bec4a02 100644 --- a/drivers/net/ethernet/intel/idpf/idpf_main.c +++ b/drivers/net/ethernet/intel/idpf/idpf_main.c
@@ -87,7 +87,11 @@ static void idpf_remove(struct pci_dev *pdev) */ static void idpf_shutdown(struct pci_dev *pdev) { - idpf_remove(pdev); + struct idpf_adapter *adapter = pci_get_drvdata(pdev); + + cancel_delayed_work_sync(&adapter->vc_event_task); + idpf_vc_core_deinit(adapter); + idpf_deinit_dflt_mbx(adapter); if (system_state == SYSTEM_POWER_OFF) pci_set_power_state(pdev, PCI_D3hot);
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index d368b75..c646c71 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -2185,8 +2185,8 @@ void igb_down(struct igb_adapter *adapter) } } - del_timer_sync(&adapter->watchdog_timer); - del_timer_sync(&adapter->phy_info_timer); + timer_delete_sync(&adapter->watchdog_timer); + timer_delete_sync(&adapter->phy_info_timer); /* record the stats before reset*/ spin_lock(&adapter->stats64_lock); @@ -3860,8 +3860,8 @@ static void igb_remove(struct pci_dev *pdev) * disable watchdog from being rescheduled. */ set_bit(__IGB_DOWN, &adapter->state); - del_timer_sync(&adapter->watchdog_timer); - del_timer_sync(&adapter->phy_info_timer); + timer_delete_sync(&adapter->watchdog_timer); + timer_delete_sync(&adapter->phy_info_timer); cancel_work_sync(&adapter->reset_task); cancel_work_sync(&adapter->watchdog_task);
diff --git a/drivers/net/ethernet/intel/igbvf/netdev.c b/drivers/net/ethernet/intel/igbvf/netdev.c index 02044aa..beb0124 100644 --- a/drivers/net/ethernet/intel/igbvf/netdev.c +++ b/drivers/net/ethernet/intel/igbvf/netdev.c
@@ -1592,7 +1592,7 @@ void igbvf_down(struct igbvf_adapter *adapter) igbvf_irq_disable(adapter); - del_timer_sync(&adapter->watchdog_timer); + timer_delete_sync(&adapter->watchdog_timer); /* record the stats before reset*/ igbvf_update_stats(adapter); @@ -2912,7 +2912,7 @@ static void igbvf_remove(struct pci_dev *pdev) * disable it from being rescheduled. */ set_bit(__IGBVF_DOWN, &adapter->state); - del_timer_sync(&adapter->watchdog_timer); + timer_delete_sync(&adapter->watchdog_timer); cancel_work_sync(&adapter->reset_task); cancel_work_sync(&adapter->watchdog_task);
diff --git a/drivers/net/ethernet/intel/igc/igc.h b/drivers/net/ethernet/intel/igc/igc.h index cd1d7b6..c35cc5c 100644 --- a/drivers/net/ethernet/intel/igc/igc.h +++ b/drivers/net/ethernet/intel/igc/igc.h
@@ -337,8 +337,6 @@ struct igc_adapter { struct igc_led_classdev *leds; }; -void igc_set_queue_napi(struct igc_adapter *adapter, int q_idx, - struct napi_struct *napi); void igc_up(struct igc_adapter *adapter); void igc_down(struct igc_adapter *adapter); int igc_open(struct net_device *netdev);
diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c index 491d942..f133037 100644 --- a/drivers/net/ethernet/intel/igc/igc_main.c +++ b/drivers/net/ethernet/intel/igc/igc_main.c
@@ -3042,7 +3042,7 @@ static void igc_xdp_xmit_zc(struct igc_ring *ring) * descriptors. Therefore, to be safe, we always ensure we have at least * 4 descriptors available. */ - while (xsk_tx_peek_desc(pool, &xdp_desc) && budget >= 4) { + while (budget >= 4 && xsk_tx_peek_desc(pool, &xdp_desc)) { struct igc_metadata_request meta_req; struct xsk_tx_metadata *meta = NULL; struct igc_tx_buffer *bi; @@ -5022,8 +5022,8 @@ static int igc_sw_init(struct igc_adapter *adapter) return 0; } -void igc_set_queue_napi(struct igc_adapter *adapter, int vector, - struct napi_struct *napi) +static void igc_set_queue_napi(struct igc_adapter *adapter, int vector, + struct napi_struct *napi) { struct igc_q_vector *q_vector = adapter->q_vector[vector]; @@ -5291,8 +5291,8 @@ void igc_down(struct igc_adapter *adapter) } } - del_timer_sync(&adapter->watchdog_timer); - del_timer_sync(&adapter->phy_info_timer); + timer_delete_sync(&adapter->watchdog_timer); + timer_delete_sync(&adapter->phy_info_timer); /* record the stats before reset*/ spin_lock(&adapter->stats64_lock); @@ -7272,8 +7272,8 @@ static void igc_remove(struct pci_dev *pdev) set_bit(__IGC_DOWN, &adapter->state); - del_timer_sync(&adapter->watchdog_timer); - del_timer_sync(&adapter->phy_info_timer); + timer_delete_sync(&adapter->watchdog_timer); + timer_delete_sync(&adapter->phy_info_timer); cancel_work_sync(&adapter->reset_task); cancel_work_sync(&adapter->watchdog_task);
diff --git a/drivers/net/ethernet/intel/igc/igc_xdp.c b/drivers/net/ethernet/intel/igc/igc_xdp.c index c538e6b..9eb47b4 100644 --- a/drivers/net/ethernet/intel/igc/igc_xdp.c +++ b/drivers/net/ethernet/intel/igc/igc_xdp.c
@@ -97,7 +97,6 @@ static int igc_xdp_enable_pool(struct igc_adapter *adapter, napi_disable(napi); } - igc_set_queue_napi(adapter, queue_id, NULL); set_bit(IGC_RING_FLAG_AF_XDP_ZC, &rx_ring->flags); set_bit(IGC_RING_FLAG_AF_XDP_ZC, &tx_ring->flags); @@ -147,7 +146,6 @@ static int igc_xdp_disable_pool(struct igc_adapter *adapter, u16 queue_id) xsk_pool_dma_unmap(pool, IGC_RX_DMA_ATTR); clear_bit(IGC_RING_FLAG_AF_XDP_ZC, &rx_ring->flags); clear_bit(IGC_RING_FLAG_AF_XDP_ZC, &tx_ring->flags); - igc_set_queue_napi(adapter, queue_id, napi); if (needs_reset) { napi_enable(napi);
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_e610.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_e610.c index cb07ecd..0093574 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_e610.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_e610.c
@@ -1453,9 +1453,11 @@ enum ixgbe_media_type ixgbe_get_media_type_e610(struct ixgbe_hw *hw) hw->link.link_info.phy_type_low = 0; } else { highest_bit = fls64(le64_to_cpu(pcaps.phy_type_low)); - if (highest_bit) + if (highest_bit) { hw->link.link_info.phy_type_low = BIT_ULL(highest_bit - 1); + hw->link.link_info.phy_type_high = 0; + } } }
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 481f917..a2718218 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -6538,7 +6538,7 @@ void ixgbe_down(struct ixgbe_adapter *adapter) adapter->flags2 &= ~IXGBE_FLAG2_FDIR_REQUIRES_REINIT; adapter->flags &= ~IXGBE_FLAG_NEED_LINK_UPDATE; - del_timer_sync(&adapter->service_timer); + timer_delete_sync(&adapter->service_timer); if (adapter->num_vfs) { /* Clear EITR Select mapping */
diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c index 6442f11..a217c5c 100644 --- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c +++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
@@ -2514,7 +2514,7 @@ void ixgbevf_down(struct ixgbevf_adapter *adapter) ixgbevf_napi_disable_all(adapter); - del_timer_sync(&adapter->service_timer); + timer_delete_sync(&adapter->service_timer); /* disable transmits in the hardware now that interrupts are off */ for (i = 0; i < adapter->num_tx_queues; i++) {
diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c index 87c7e62..1e2ac1a 100644 --- a/drivers/net/ethernet/korina.c +++ b/drivers/net/ethernet/korina.c
@@ -1239,7 +1239,7 @@ static int korina_close(struct net_device *dev) struct korina_private *lp = netdev_priv(dev); u32 tmp; - del_timer(&lp->media_check_timer); + timer_delete(&lp->media_check_timer); /* Disable interrupts */ disable_irq(lp->rx_irq);
diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c index 67a6ff0..8cc888bf 100644 --- a/drivers/net/ethernet/marvell/mv643xx_eth.c +++ b/drivers/net/ethernet/marvell/mv643xx_eth.c
@@ -2247,7 +2247,7 @@ static int mv643xx_eth_poll(struct napi_struct *napi, int budget) if (unlikely(mp->oom)) { mp->oom = 0; - del_timer(&mp->rx_oom); + timer_delete(&mp->rx_oom); } work_done = 0; @@ -2521,7 +2521,7 @@ static int mv643xx_eth_stop(struct net_device *dev) napi_disable(&mp->napi); - del_timer_sync(&mp->rx_oom); + timer_delete_sync(&mp->rx_oom); netif_carrier_off(dev); if (dev->phydev) @@ -2531,7 +2531,7 @@ static int mv643xx_eth_stop(struct net_device *dev) port_reset(mp); mv643xx_eth_get_stats(dev); mib_counters_update(mp); - del_timer_sync(&mp->mib_counters_timer); + timer_delete_sync(&mp->mib_counters_timer); for (i = 0; i < mp->rxq_count; i++) rxq_deinit(mp->rxq + i);
diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2.h b/drivers/net/ethernet/marvell/mvpp2/mvpp2.h index 44fe9b6..061fcd4 100644 --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2.h +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2.h
@@ -1113,6 +1113,9 @@ struct mvpp2 { /* Spinlocks for CM3 shared memory configuration */ spinlock_t mss_spinlock; + + /* Spinlock for shared PRS parser memory and shadow table */ + spinlock_t prs_spinlock; }; struct mvpp2_pcpu_stats {
diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c index 566c12c..416a926 100644 --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
@@ -7723,8 +7723,9 @@ static int mvpp2_probe(struct platform_device *pdev) if (mvpp2_read(priv, MVPP2_VER_ID_REG) == MVPP2_VER_PP23) priv->hw_version = MVPP23; - /* Init mss lock */ + /* Init locks for shared packet processor resources */ spin_lock_init(&priv->mss_spinlock); + spin_lock_init(&priv->prs_spinlock); /* Initialize network controller */ err = mvpp2_init(pdev, priv);
diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_prs.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_prs.c index 9af22f4..93e978b 100644 --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_prs.c +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_prs.c
@@ -23,6 +23,8 @@ static int mvpp2_prs_hw_write(struct mvpp2 *priv, struct mvpp2_prs_entry *pe) { int i; + lockdep_assert_held(&priv->prs_spinlock); + if (pe->index > MVPP2_PRS_TCAM_SRAM_SIZE - 1) return -EINVAL; @@ -43,11 +45,13 @@ static int mvpp2_prs_hw_write(struct mvpp2 *priv, struct mvpp2_prs_entry *pe) } /* Initialize tcam entry from hw */ -int mvpp2_prs_init_from_hw(struct mvpp2 *priv, struct mvpp2_prs_entry *pe, - int tid) +static int __mvpp2_prs_init_from_hw(struct mvpp2 *priv, + struct mvpp2_prs_entry *pe, int tid) { int i; + lockdep_assert_held(&priv->prs_spinlock); + if (tid > MVPP2_PRS_TCAM_SRAM_SIZE - 1) return -EINVAL; @@ -73,6 +77,18 @@ int mvpp2_prs_init_from_hw(struct mvpp2 *priv, struct mvpp2_prs_entry *pe, return 0; } +int mvpp2_prs_init_from_hw(struct mvpp2 *priv, struct mvpp2_prs_entry *pe, + int tid) +{ + int err; + + spin_lock_bh(&priv->prs_spinlock); + err = __mvpp2_prs_init_from_hw(priv, pe, tid); + spin_unlock_bh(&priv->prs_spinlock); + + return err; +} + /* Invalidate tcam hw entry */ static void mvpp2_prs_hw_inv(struct mvpp2 *priv, int index) { @@ -374,7 +390,7 @@ static int mvpp2_prs_flow_find(struct mvpp2 *priv, int flow) priv->prs_shadow[tid].lu != MVPP2_PRS_LU_FLOWS) continue; - mvpp2_prs_init_from_hw(priv, &pe, tid); + __mvpp2_prs_init_from_hw(priv, &pe, tid); bits = mvpp2_prs_sram_ai_get(&pe); /* Sram store classification lookup ID in AI bits [5:0] */ @@ -441,7 +457,7 @@ static void mvpp2_prs_mac_drop_all_set(struct mvpp2 *priv, int port, bool add) if (priv->prs_shadow[MVPP2_PE_DROP_ALL].valid) { /* Entry exist - update port only */ - mvpp2_prs_init_from_hw(priv, &pe, MVPP2_PE_DROP_ALL); + __mvpp2_prs_init_from_hw(priv, &pe, MVPP2_PE_DROP_ALL); } else { /* Entry doesn't exist - create new */ memset(&pe, 0, sizeof(pe)); @@ -469,14 +485,17 @@ static void mvpp2_prs_mac_drop_all_set(struct mvpp2 *priv, int port, bool add) } /* Set port to unicast or multicast promiscuous mode */ -void mvpp2_prs_mac_promisc_set(struct mvpp2 *priv, int port, - enum mvpp2_prs_l2_cast l2_cast, bool add) +static void __mvpp2_prs_mac_promisc_set(struct mvpp2 *priv, int port, + enum mvpp2_prs_l2_cast l2_cast, + bool add) { struct mvpp2_prs_entry pe; unsigned char cast_match; unsigned int ri; int tid; + lockdep_assert_held(&priv->prs_spinlock); + if (l2_cast == MVPP2_PRS_L2_UNI_CAST) { cast_match = MVPP2_PRS_UCAST_VAL; tid = MVPP2_PE_MAC_UC_PROMISCUOUS; @@ -489,7 +508,7 @@ void mvpp2_prs_mac_promisc_set(struct mvpp2 *priv, int port, /* promiscuous mode - Accept unknown unicast or multicast packets */ if (priv->prs_shadow[tid].valid) { - mvpp2_prs_init_from_hw(priv, &pe, tid); + __mvpp2_prs_init_from_hw(priv, &pe, tid); } else { memset(&pe, 0, sizeof(pe)); mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_MAC); @@ -522,6 +541,14 @@ void mvpp2_prs_mac_promisc_set(struct mvpp2 *priv, int port, mvpp2_prs_hw_write(priv, &pe); } +void mvpp2_prs_mac_promisc_set(struct mvpp2 *priv, int port, + enum mvpp2_prs_l2_cast l2_cast, bool add) +{ + spin_lock_bh(&priv->prs_spinlock); + __mvpp2_prs_mac_promisc_set(priv, port, l2_cast, add); + spin_unlock_bh(&priv->prs_spinlock); +} + /* Set entry for dsa packets */ static void mvpp2_prs_dsa_tag_set(struct mvpp2 *priv, int port, bool add, bool tagged, bool extend) @@ -539,7 +566,7 @@ static void mvpp2_prs_dsa_tag_set(struct mvpp2 *priv, int port, bool add, if (priv->prs_shadow[tid].valid) { /* Entry exist - update port only */ - mvpp2_prs_init_from_hw(priv, &pe, tid); + __mvpp2_prs_init_from_hw(priv, &pe, tid); } else { /* Entry doesn't exist - create new */ memset(&pe, 0, sizeof(pe)); @@ -610,7 +637,7 @@ static void mvpp2_prs_dsa_tag_ethertype_set(struct mvpp2 *priv, int port, if (priv->prs_shadow[tid].valid) { /* Entry exist - update port only */ - mvpp2_prs_init_from_hw(priv, &pe, tid); + __mvpp2_prs_init_from_hw(priv, &pe, tid); } else { /* Entry doesn't exist - create new */ memset(&pe, 0, sizeof(pe)); @@ -673,7 +700,7 @@ static int mvpp2_prs_vlan_find(struct mvpp2 *priv, unsigned short tpid, int ai) priv->prs_shadow[tid].lu != MVPP2_PRS_LU_VLAN) continue; - mvpp2_prs_init_from_hw(priv, &pe, tid); + __mvpp2_prs_init_from_hw(priv, &pe, tid); match = mvpp2_prs_tcam_data_cmp(&pe, 0, tpid); if (!match) continue; @@ -726,7 +753,7 @@ static int mvpp2_prs_vlan_add(struct mvpp2 *priv, unsigned short tpid, int ai, priv->prs_shadow[tid_aux].lu != MVPP2_PRS_LU_VLAN) continue; - mvpp2_prs_init_from_hw(priv, &pe, tid_aux); + __mvpp2_prs_init_from_hw(priv, &pe, tid_aux); ri_bits = mvpp2_prs_sram_ri_get(&pe); if ((ri_bits & MVPP2_PRS_RI_VLAN_MASK) == MVPP2_PRS_RI_VLAN_DOUBLE) @@ -760,7 +787,7 @@ static int mvpp2_prs_vlan_add(struct mvpp2 *priv, unsigned short tpid, int ai, mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_VLAN); } else { - mvpp2_prs_init_from_hw(priv, &pe, tid); + __mvpp2_prs_init_from_hw(priv, &pe, tid); } /* Update ports' mask */ mvpp2_prs_tcam_port_map_set(&pe, port_map); @@ -800,7 +827,7 @@ static int mvpp2_prs_double_vlan_find(struct mvpp2 *priv, unsigned short tpid1, priv->prs_shadow[tid].lu != MVPP2_PRS_LU_VLAN) continue; - mvpp2_prs_init_from_hw(priv, &pe, tid); + __mvpp2_prs_init_from_hw(priv, &pe, tid); match = mvpp2_prs_tcam_data_cmp(&pe, 0, tpid1) && mvpp2_prs_tcam_data_cmp(&pe, 4, tpid2); @@ -849,7 +876,7 @@ static int mvpp2_prs_double_vlan_add(struct mvpp2 *priv, unsigned short tpid1, priv->prs_shadow[tid_aux].lu != MVPP2_PRS_LU_VLAN) continue; - mvpp2_prs_init_from_hw(priv, &pe, tid_aux); + __mvpp2_prs_init_from_hw(priv, &pe, tid_aux); ri_bits = mvpp2_prs_sram_ri_get(&pe); ri_bits &= MVPP2_PRS_RI_VLAN_MASK; if (ri_bits == MVPP2_PRS_RI_VLAN_SINGLE || @@ -880,7 +907,7 @@ static int mvpp2_prs_double_vlan_add(struct mvpp2 *priv, unsigned short tpid1, mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_VLAN); } else { - mvpp2_prs_init_from_hw(priv, &pe, tid); + __mvpp2_prs_init_from_hw(priv, &pe, tid); } /* Update ports' mask */ @@ -1213,8 +1240,8 @@ static void mvpp2_prs_mac_init(struct mvpp2 *priv) /* Create dummy entries for drop all and promiscuous modes */ mvpp2_prs_drop_fc(priv); mvpp2_prs_mac_drop_all_set(priv, 0, false); - mvpp2_prs_mac_promisc_set(priv, 0, MVPP2_PRS_L2_UNI_CAST, false); - mvpp2_prs_mac_promisc_set(priv, 0, MVPP2_PRS_L2_MULTI_CAST, false); + __mvpp2_prs_mac_promisc_set(priv, 0, MVPP2_PRS_L2_UNI_CAST, false); + __mvpp2_prs_mac_promisc_set(priv, 0, MVPP2_PRS_L2_MULTI_CAST, false); } /* Set default entries for various types of dsa packets */ @@ -1533,12 +1560,6 @@ static int mvpp2_prs_vlan_init(struct platform_device *pdev, struct mvpp2 *priv) struct mvpp2_prs_entry pe; int err; - priv->prs_double_vlans = devm_kcalloc(&pdev->dev, sizeof(bool), - MVPP2_PRS_DBL_VLANS_MAX, - GFP_KERNEL); - if (!priv->prs_double_vlans) - return -ENOMEM; - /* Double VLAN: 0x88A8, 0x8100 */ err = mvpp2_prs_double_vlan_add(priv, ETH_P_8021AD, ETH_P_8021Q, MVPP2_PRS_PORT_MASK); @@ -1941,7 +1962,7 @@ static int mvpp2_prs_vid_range_find(struct mvpp2_port *port, u16 vid, u16 mask) port->priv->prs_shadow[tid].lu != MVPP2_PRS_LU_VID) continue; - mvpp2_prs_init_from_hw(port->priv, &pe, tid); + __mvpp2_prs_init_from_hw(port->priv, &pe, tid); mvpp2_prs_tcam_data_byte_get(&pe, 2, &byte[0], &enable[0]); mvpp2_prs_tcam_data_byte_get(&pe, 3, &byte[1], &enable[1]); @@ -1970,6 +1991,8 @@ int mvpp2_prs_vid_entry_add(struct mvpp2_port *port, u16 vid) memset(&pe, 0, sizeof(pe)); + spin_lock_bh(&priv->prs_spinlock); + /* Scan TCAM and see if entry with this <vid,port> already exist */ tid = mvpp2_prs_vid_range_find(port, vid, mask); @@ -1988,8 +2011,10 @@ int mvpp2_prs_vid_entry_add(struct mvpp2_port *port, u16 vid) MVPP2_PRS_VLAN_FILT_MAX_ENTRY); /* There isn't room for a new VID filter */ - if (tid < 0) + if (tid < 0) { + spin_unlock_bh(&priv->prs_spinlock); return tid; + } mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_VID); pe.index = tid; @@ -1997,7 +2022,7 @@ int mvpp2_prs_vid_entry_add(struct mvpp2_port *port, u16 vid) /* Mask all ports */ mvpp2_prs_tcam_port_map_set(&pe, 0); } else { - mvpp2_prs_init_from_hw(priv, &pe, tid); + __mvpp2_prs_init_from_hw(priv, &pe, tid); } /* Enable the current port */ @@ -2019,6 +2044,7 @@ int mvpp2_prs_vid_entry_add(struct mvpp2_port *port, u16 vid) mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_VID); mvpp2_prs_hw_write(priv, &pe); + spin_unlock_bh(&priv->prs_spinlock); return 0; } @@ -2028,15 +2054,16 @@ void mvpp2_prs_vid_entry_remove(struct mvpp2_port *port, u16 vid) struct mvpp2 *priv = port->priv; int tid; - /* Scan TCAM and see if entry with this <vid,port> already exist */ + spin_lock_bh(&priv->prs_spinlock); + + /* Invalidate TCAM entry with this <vid,port>, if it exists */ tid = mvpp2_prs_vid_range_find(port, vid, 0xfff); + if (tid >= 0) { + mvpp2_prs_hw_inv(priv, tid); + priv->prs_shadow[tid].valid = false; + } - /* No such entry */ - if (tid < 0) - return; - - mvpp2_prs_hw_inv(priv, tid); - priv->prs_shadow[tid].valid = false; + spin_unlock_bh(&priv->prs_spinlock); } /* Remove all existing VID filters on this port */ @@ -2045,6 +2072,8 @@ void mvpp2_prs_vid_remove_all(struct mvpp2_port *port) struct mvpp2 *priv = port->priv; int tid; + spin_lock_bh(&priv->prs_spinlock); + for (tid = MVPP2_PRS_VID_PORT_FIRST(port->id); tid <= MVPP2_PRS_VID_PORT_LAST(port->id); tid++) { if (priv->prs_shadow[tid].valid) { @@ -2052,6 +2081,8 @@ void mvpp2_prs_vid_remove_all(struct mvpp2_port *port) priv->prs_shadow[tid].valid = false; } } + + spin_unlock_bh(&priv->prs_spinlock); } /* Remove VID filering entry for this port */ @@ -2060,10 +2091,14 @@ void mvpp2_prs_vid_disable_filtering(struct mvpp2_port *port) unsigned int tid = MVPP2_PRS_VID_PORT_DFLT(port->id); struct mvpp2 *priv = port->priv; + spin_lock_bh(&priv->prs_spinlock); + /* Invalidate the guard entry */ mvpp2_prs_hw_inv(priv, tid); priv->prs_shadow[tid].valid = false; + + spin_unlock_bh(&priv->prs_spinlock); } /* Add guard entry that drops packets when no VID is matched on this port */ @@ -2079,6 +2114,8 @@ void mvpp2_prs_vid_enable_filtering(struct mvpp2_port *port) memset(&pe, 0, sizeof(pe)); + spin_lock_bh(&priv->prs_spinlock); + pe.index = tid; reg_val = mvpp2_read(priv, MVPP2_MH_REG(port->id)); @@ -2111,6 +2148,8 @@ void mvpp2_prs_vid_enable_filtering(struct mvpp2_port *port) /* Update shadow table */ mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_VID); mvpp2_prs_hw_write(priv, &pe); + + spin_unlock_bh(&priv->prs_spinlock); } /* Parser default initialization */ @@ -2118,6 +2157,20 @@ int mvpp2_prs_default_init(struct platform_device *pdev, struct mvpp2 *priv) { int err, index, i; + priv->prs_shadow = devm_kcalloc(&pdev->dev, MVPP2_PRS_TCAM_SRAM_SIZE, + sizeof(*priv->prs_shadow), + GFP_KERNEL); + if (!priv->prs_shadow) + return -ENOMEM; + + priv->prs_double_vlans = devm_kcalloc(&pdev->dev, sizeof(bool), + MVPP2_PRS_DBL_VLANS_MAX, + GFP_KERNEL); + if (!priv->prs_double_vlans) + return -ENOMEM; + + spin_lock_bh(&priv->prs_spinlock); + /* Enable tcam table */ mvpp2_write(priv, MVPP2_PRS_TCAM_CTRL_REG, MVPP2_PRS_TCAM_EN_MASK); @@ -2136,12 +2189,6 @@ int mvpp2_prs_default_init(struct platform_device *pdev, struct mvpp2 *priv) for (index = 0; index < MVPP2_PRS_TCAM_SRAM_SIZE; index++) mvpp2_prs_hw_inv(priv, index); - priv->prs_shadow = devm_kcalloc(&pdev->dev, MVPP2_PRS_TCAM_SRAM_SIZE, - sizeof(*priv->prs_shadow), - GFP_KERNEL); - if (!priv->prs_shadow) - return -ENOMEM; - /* Always start from lookup = 0 */ for (index = 0; index < MVPP2_MAX_PORTS; index++) mvpp2_prs_hw_port_init(priv, index, MVPP2_PRS_LU_MH, @@ -2158,26 +2205,13 @@ int mvpp2_prs_default_init(struct platform_device *pdev, struct mvpp2 *priv) mvpp2_prs_vid_init(priv); err = mvpp2_prs_etype_init(priv); - if (err) - return err; + err = err ? : mvpp2_prs_vlan_init(pdev, priv); + err = err ? : mvpp2_prs_pppoe_init(priv); + err = err ? : mvpp2_prs_ip6_init(priv); + err = err ? : mvpp2_prs_ip4_init(priv); - err = mvpp2_prs_vlan_init(pdev, priv); - if (err) - return err; - - err = mvpp2_prs_pppoe_init(priv); - if (err) - return err; - - err = mvpp2_prs_ip6_init(priv); - if (err) - return err; - - err = mvpp2_prs_ip4_init(priv); - if (err) - return err; - - return 0; + spin_unlock_bh(&priv->prs_spinlock); + return err; } /* Compare MAC DA with tcam entry data */ @@ -2217,7 +2251,7 @@ mvpp2_prs_mac_da_range_find(struct mvpp2 *priv, int pmap, const u8 *da, (priv->prs_shadow[tid].udf != udf_type)) continue; - mvpp2_prs_init_from_hw(priv, &pe, tid); + __mvpp2_prs_init_from_hw(priv, &pe, tid); entry_pmap = mvpp2_prs_tcam_port_map_get(&pe); if (mvpp2_prs_mac_range_equals(&pe, da, mask) && @@ -2229,7 +2263,8 @@ mvpp2_prs_mac_da_range_find(struct mvpp2 *priv, int pmap, const u8 *da, } /* Update parser's mac da entry */ -int mvpp2_prs_mac_da_accept(struct mvpp2_port *port, const u8 *da, bool add) +static int __mvpp2_prs_mac_da_accept(struct mvpp2_port *port, + const u8 *da, bool add) { unsigned char mask[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; struct mvpp2 *priv = port->priv; @@ -2261,7 +2296,7 @@ int mvpp2_prs_mac_da_accept(struct mvpp2_port *port, const u8 *da, bool add) /* Mask all ports */ mvpp2_prs_tcam_port_map_set(&pe, 0); } else { - mvpp2_prs_init_from_hw(priv, &pe, tid); + __mvpp2_prs_init_from_hw(priv, &pe, tid); } mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_MAC); @@ -2317,6 +2352,17 @@ int mvpp2_prs_mac_da_accept(struct mvpp2_port *port, const u8 *da, bool add) return 0; } +int mvpp2_prs_mac_da_accept(struct mvpp2_port *port, const u8 *da, bool add) +{ + int err; + + spin_lock_bh(&port->priv->prs_spinlock); + err = __mvpp2_prs_mac_da_accept(port, da, add); + spin_unlock_bh(&port->priv->prs_spinlock); + + return err; +} + int mvpp2_prs_update_mac_da(struct net_device *dev, const u8 *da) { struct mvpp2_port *port = netdev_priv(dev); @@ -2345,6 +2391,8 @@ void mvpp2_prs_mac_del_all(struct mvpp2_port *port) unsigned long pmap; int index, tid; + spin_lock_bh(&priv->prs_spinlock); + for (tid = MVPP2_PE_MAC_RANGE_START; tid <= MVPP2_PE_MAC_RANGE_END; tid++) { unsigned char da[ETH_ALEN], da_mask[ETH_ALEN]; @@ -2354,7 +2402,7 @@ void mvpp2_prs_mac_del_all(struct mvpp2_port *port) (priv->prs_shadow[tid].udf != MVPP2_PRS_UDF_MAC_DEF)) continue; - mvpp2_prs_init_from_hw(priv, &pe, tid); + __mvpp2_prs_init_from_hw(priv, &pe, tid); pmap = mvpp2_prs_tcam_port_map_get(&pe); @@ -2375,14 +2423,17 @@ void mvpp2_prs_mac_del_all(struct mvpp2_port *port) continue; /* Remove entry from TCAM */ - mvpp2_prs_mac_da_accept(port, da, false); + __mvpp2_prs_mac_da_accept(port, da, false); } + + spin_unlock_bh(&priv->prs_spinlock); } int mvpp2_prs_tag_mode_set(struct mvpp2 *priv, int port, int type) { switch (type) { case MVPP2_TAG_TYPE_EDSA: + spin_lock_bh(&priv->prs_spinlock); /* Add port to EDSA entries */ mvpp2_prs_dsa_tag_set(priv, port, true, MVPP2_PRS_TAGGED, MVPP2_PRS_EDSA); @@ -2393,9 +2444,11 @@ int mvpp2_prs_tag_mode_set(struct mvpp2 *priv, int port, int type) MVPP2_PRS_TAGGED, MVPP2_PRS_DSA); mvpp2_prs_dsa_tag_set(priv, port, false, MVPP2_PRS_UNTAGGED, MVPP2_PRS_DSA); + spin_unlock_bh(&priv->prs_spinlock); break; case MVPP2_TAG_TYPE_DSA: + spin_lock_bh(&priv->prs_spinlock); /* Add port to DSA entries */ mvpp2_prs_dsa_tag_set(priv, port, true, MVPP2_PRS_TAGGED, MVPP2_PRS_DSA); @@ -2406,10 +2459,12 @@ int mvpp2_prs_tag_mode_set(struct mvpp2 *priv, int port, int type) MVPP2_PRS_TAGGED, MVPP2_PRS_EDSA); mvpp2_prs_dsa_tag_set(priv, port, false, MVPP2_PRS_UNTAGGED, MVPP2_PRS_EDSA); + spin_unlock_bh(&priv->prs_spinlock); break; case MVPP2_TAG_TYPE_MH: case MVPP2_TAG_TYPE_NONE: + spin_lock_bh(&priv->prs_spinlock); /* Remove port form EDSA and DSA entries */ mvpp2_prs_dsa_tag_set(priv, port, false, MVPP2_PRS_TAGGED, MVPP2_PRS_DSA); @@ -2419,6 +2474,7 @@ int mvpp2_prs_tag_mode_set(struct mvpp2 *priv, int port, int type) MVPP2_PRS_TAGGED, MVPP2_PRS_EDSA); mvpp2_prs_dsa_tag_set(priv, port, false, MVPP2_PRS_UNTAGGED, MVPP2_PRS_EDSA); + spin_unlock_bh(&priv->prs_spinlock); break; default: @@ -2437,11 +2493,15 @@ int mvpp2_prs_add_flow(struct mvpp2 *priv, int flow, u32 ri, u32 ri_mask) memset(&pe, 0, sizeof(pe)); + spin_lock_bh(&priv->prs_spinlock); + tid = mvpp2_prs_tcam_first_free(priv, MVPP2_PE_LAST_FREE_TID, MVPP2_PE_FIRST_FREE_TID); - if (tid < 0) + if (tid < 0) { + spin_unlock_bh(&priv->prs_spinlock); return tid; + } pe.index = tid; @@ -2461,6 +2521,7 @@ int mvpp2_prs_add_flow(struct mvpp2 *priv, int flow, u32 ri, u32 ri_mask) mvpp2_prs_tcam_port_map_set(&pe, MVPP2_PRS_PORT_MASK); mvpp2_prs_hw_write(priv, &pe); + spin_unlock_bh(&priv->prs_spinlock); return 0; } @@ -2472,6 +2533,8 @@ int mvpp2_prs_def_flow(struct mvpp2_port *port) memset(&pe, 0, sizeof(pe)); + spin_lock_bh(&port->priv->prs_spinlock); + tid = mvpp2_prs_flow_find(port->priv, port->id); /* Such entry not exist */ @@ -2480,8 +2543,10 @@ int mvpp2_prs_def_flow(struct mvpp2_port *port) tid = mvpp2_prs_tcam_first_free(port->priv, MVPP2_PE_LAST_FREE_TID, MVPP2_PE_FIRST_FREE_TID); - if (tid < 0) + if (tid < 0) { + spin_unlock_bh(&port->priv->prs_spinlock); return tid; + } pe.index = tid; @@ -2492,13 +2557,14 @@ int mvpp2_prs_def_flow(struct mvpp2_port *port) /* Update shadow table */ mvpp2_prs_shadow_set(port->priv, pe.index, MVPP2_PRS_LU_FLOWS); } else { - mvpp2_prs_init_from_hw(port->priv, &pe, tid); + __mvpp2_prs_init_from_hw(port->priv, &pe, tid); } mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_FLOWS); mvpp2_prs_tcam_port_map_set(&pe, (1 << port->id)); mvpp2_prs_hw_write(port->priv, &pe); + spin_unlock_bh(&port->priv->prs_spinlock); return 0; } @@ -2509,11 +2575,14 @@ int mvpp2_prs_hits(struct mvpp2 *priv, int index) if (index > MVPP2_PRS_TCAM_SRAM_SIZE) return -EINVAL; + spin_lock_bh(&priv->prs_spinlock); + mvpp2_write(priv, MVPP2_PRS_TCAM_HIT_IDX_REG, index); val = mvpp2_read(priv, MVPP2_PRS_TCAM_HIT_CNT_REG); val &= MVPP2_PRS_TCAM_HIT_CNT_MASK; + spin_unlock_bh(&priv->prs_spinlock); return val; }
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu.c index cd0d7b7..6575c42 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.c
@@ -2634,7 +2634,7 @@ static irqreturn_t rvu_mbox_intr_handler(int irq, void *rvu_irq) rvupf_write64(rvu, RVU_PF_VFPF_MBOX_INTX(1), intr); rvu_queue_work(&rvu->afvf_wq_info, 64, vfs, intr); - vfs -= 64; + vfs = 64; } intr = rvupf_read64(rvu, RVU_PF_VFPF_MBOX_INTX(0));
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_devlink.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_devlink.c index dab4dec..27c3a2da 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_devlink.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_devlink.c
@@ -207,7 +207,7 @@ static void rvu_nix_unregister_interrupts(struct rvu *rvu) rvu->irq_allocated[offs + NIX_AF_INT_VEC_RVU] = false; } - for (i = NIX_AF_INT_VEC_AF_ERR; i < NIX_AF_INT_VEC_CNT; i++) + for (i = NIX_AF_INT_VEC_GEN; i < NIX_AF_INT_VEC_CNT; i++) if (rvu->irq_allocated[offs + i]) { free_irq(pci_irq_vector(rvu->pdev, offs + i), rvu_dl); rvu->irq_allocated[offs + i] = false;
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c index af8cabe..0a6bb34 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c
@@ -1559,12 +1559,11 @@ static bool otx2_xdp_rcv_pkt_handler(struct otx2_nic *pfvf, break; default: bpf_warn_invalid_xdp_action(pfvf->netdev, prog, act); - break; + fallthrough; case XDP_ABORTED: - if (xsk_buff) - xsk_buff_free(xsk_buff); - trace_xdp_exception(pfvf->netdev, prog, act); - break; + if (act == XDP_ABORTED) + trace_xdp_exception(pfvf->netdev, prog, act); + fallthrough; case XDP_DROP: cq->pool_ptrs++; if (xsk_buff) {
diff --git a/drivers/net/ethernet/marvell/pxa168_eth.c b/drivers/net/ethernet/marvell/pxa168_eth.c index 2bf426c..72c1967 100644 --- a/drivers/net/ethernet/marvell/pxa168_eth.c +++ b/drivers/net/ethernet/marvell/pxa168_eth.c
@@ -1175,7 +1175,7 @@ static int pxa168_eth_stop(struct net_device *dev) /* Write to ICR to clear interrupts. */ wrl(pep, INT_W_CLEAR, 0); napi_disable(&pep->napi); - del_timer_sync(&pep->timeout); + timer_delete_sync(&pep->timeout); netif_carrier_off(dev); free_irq(dev->irq, dev); rxq_deinit(dev);
diff --git a/drivers/net/ethernet/marvell/skge.c b/drivers/net/ethernet/marvell/skge.c index a1bada9..b2081d6 100644 --- a/drivers/net/ethernet/marvell/skge.c +++ b/drivers/net/ethernet/marvell/skge.c
@@ -2662,7 +2662,7 @@ static int skge_down(struct net_device *dev) netif_tx_disable(dev); if (is_genesis(hw) && hw->phy_type == SK_PHY_XMAC) - del_timer_sync(&skge->link_timer); + timer_delete_sync(&skge->link_timer); napi_disable(&skge->napi); netif_carrier_off(dev);
diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c index d7121c8..e2a9aae 100644 --- a/drivers/net/ethernet/marvell/sky2.c +++ b/drivers/net/ethernet/marvell/sky2.c
@@ -5052,7 +5052,7 @@ static int sky2_suspend(struct device *dev) if (!hw) return 0; - del_timer_sync(&hw->watchdog_timer); + timer_delete_sync(&hw->watchdog_timer); cancel_work_sync(&hw->restart_work); rtnl_lock();
diff --git a/drivers/net/ethernet/mellanox/mlx4/Kconfig b/drivers/net/ethernet/mellanox/mlx4/Kconfig index 825e05f..0b1cb34 100644 --- a/drivers/net/ethernet/mellanox/mlx4/Kconfig +++ b/drivers/net/ethernet/mellanox/mlx4/Kconfig
@@ -7,6 +7,7 @@ tristate "Mellanox Technologies 1/10/40Gbit Ethernet support" depends on PCI && NETDEVICES && ETHERNET && INET depends on PTP_1588_CLOCK_OPTIONAL + select PAGE_POOL select MLX4_CORE help This driver supports Mellanox Technologies ConnectX Ethernet
diff --git a/drivers/net/ethernet/mellanox/mlx4/catas.c b/drivers/net/ethernet/mellanox/mlx4/catas.c index 0d8a362..33ba0a5 100644 --- a/drivers/net/ethernet/mellanox/mlx4/catas.c +++ b/drivers/net/ethernet/mellanox/mlx4/catas.c
@@ -305,7 +305,7 @@ void mlx4_stop_catas_poll(struct mlx4_dev *dev) { struct mlx4_priv *priv = mlx4_priv(dev); - del_timer_sync(&priv->catas_err.timer); + timer_delete_sync(&priv->catas_err.timer); if (priv->catas_err.map) { iounmap(priv->catas_err.map);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/params.c b/drivers/net/ethernet/mellanox/mlx5/core/en/params.c index aa36670..58ec5e4 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/params.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/params.c
@@ -430,7 +430,7 @@ u8 mlx5e_shampo_get_log_pkt_per_rsrv(struct mlx5_core_dev *mdev, struct mlx5e_params *params) { u32 resrv_size = BIT(mlx5e_shampo_get_log_rsrv_size(mdev, params)) * - PAGE_SIZE; + MLX5E_SHAMPO_WQ_BASE_RESRV_SIZE; return order_base_2(DIV_ROUND_UP(resrv_size, params->sw_mtu)); } @@ -834,7 +834,8 @@ static u32 mlx5e_shampo_get_log_cq_size(struct mlx5_core_dev *mdev, struct mlx5e_params *params, struct mlx5e_xsk_param *xsk) { - int rsrv_size = BIT(mlx5e_shampo_get_log_rsrv_size(mdev, params)) * PAGE_SIZE; + int rsrv_size = BIT(mlx5e_shampo_get_log_rsrv_size(mdev, params)) * + MLX5E_SHAMPO_WQ_BASE_RESRV_SIZE; u16 num_strides = BIT(mlx5e_mpwqe_get_log_num_strides(mdev, params, xsk)); int pkt_per_rsrv = BIT(mlx5e_shampo_get_log_pkt_per_rsrv(mdev, params)); u8 log_stride_sz = mlx5e_mpwqe_get_log_stride_size(mdev, params, xsk); @@ -1043,7 +1044,8 @@ u32 mlx5e_shampo_hd_per_wqe(struct mlx5_core_dev *mdev, struct mlx5e_params *params, struct mlx5e_rq_param *rq_param) { - int resv_size = BIT(mlx5e_shampo_get_log_rsrv_size(mdev, params)) * PAGE_SIZE; + int resv_size = BIT(mlx5e_shampo_get_log_rsrv_size(mdev, params)) * + MLX5E_SHAMPO_WQ_BASE_RESRV_SIZE; u16 num_strides = BIT(mlx5e_mpwqe_get_log_num_strides(mdev, params, NULL)); int pkt_per_resv = BIT(mlx5e_shampo_get_log_pkt_per_rsrv(mdev, params)); u8 log_stride_sz = mlx5e_mpwqe_get_log_stride_size(mdev, params, NULL);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c index 6830a49..5442a02 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c
@@ -246,7 +246,7 @@ static void mlx5_stop_sync_reset_poll(struct mlx5_core_dev *dev) { struct mlx5_fw_reset *fw_reset = dev->priv.fw_reset; - del_timer_sync(&fw_reset->timer); + timer_delete_sync(&fw_reset->timer); } static int mlx5_sync_reset_clear_reset_requested(struct mlx5_core_dev *dev, bool poll_health)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/health.c b/drivers/net/ethernet/mellanox/mlx5/core/health.c index 91613d5..624452d 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/health.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/health.c
@@ -847,7 +847,7 @@ void mlx5_stop_health_poll(struct mlx5_core_dev *dev, bool disable_health) if (disable_health) set_bit(MLX5_DROP_HEALTH_WORK, &health->flags); - del_timer_sync(&health->timer); + timer_delete_sync(&health->timer); } void mlx5_start_health_fw_log_up(struct mlx5_core_dev *dev)
diff --git a/drivers/net/ethernet/micrel/ksz884x.c b/drivers/net/ethernet/micrel/ksz884x.c index dc1d9f7..1302aa8 100644 --- a/drivers/net/ethernet/micrel/ksz884x.c +++ b/drivers/net/ethernet/micrel/ksz884x.c
@@ -3951,7 +3951,7 @@ static void ksz_stop_timer(struct ksz_timer_info *info) { if (info->max) { info->max = 0; - del_timer_sync(&info->timer); + timer_delete_sync(&info->timer); } }
diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c index 1423df8..2bac6be 100644 --- a/drivers/net/ethernet/microsoft/mana/mana_en.c +++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
@@ -661,30 +661,16 @@ int mana_pre_alloc_rxbufs(struct mana_port_context *mpc, int new_mtu, int num_qu mpc->rxbpre_total = 0; for (i = 0; i < num_rxb; i++) { - if (mpc->rxbpre_alloc_size > PAGE_SIZE) { - va = netdev_alloc_frag(mpc->rxbpre_alloc_size); - if (!va) - goto error; + page = dev_alloc_pages(get_order(mpc->rxbpre_alloc_size)); + if (!page) + goto error; - page = virt_to_head_page(va); - /* Check if the frag falls back to single page */ - if (compound_order(page) < - get_order(mpc->rxbpre_alloc_size)) { - put_page(page); - goto error; - } - } else { - page = dev_alloc_page(); - if (!page) - goto error; - - va = page_to_virt(page); - } + va = page_to_virt(page); da = dma_map_single(dev, va + mpc->rxbpre_headroom, mpc->rxbpre_datasize, DMA_FROM_DEVICE); if (dma_mapping_error(dev, da)) { - put_page(virt_to_head_page(va)); + put_page(page); goto error; } @@ -1676,7 +1662,7 @@ static void mana_rx_skb(void *buf_va, bool from_pool, } static void *mana_get_rxfrag(struct mana_rxq *rxq, struct device *dev, - dma_addr_t *da, bool *from_pool, bool is_napi) + dma_addr_t *da, bool *from_pool) { struct page *page; void *va; @@ -1687,21 +1673,6 @@ static void *mana_get_rxfrag(struct mana_rxq *rxq, struct device *dev, if (rxq->xdp_save_va) { va = rxq->xdp_save_va; rxq->xdp_save_va = NULL; - } else if (rxq->alloc_size > PAGE_SIZE) { - if (is_napi) - va = napi_alloc_frag(rxq->alloc_size); - else - va = netdev_alloc_frag(rxq->alloc_size); - - if (!va) - return NULL; - - page = virt_to_head_page(va); - /* Check if the frag falls back to single page */ - if (compound_order(page) < get_order(rxq->alloc_size)) { - put_page(page); - return NULL; - } } else { page = page_pool_dev_alloc_pages(rxq->page_pool); if (!page) @@ -1734,7 +1705,7 @@ static void mana_refill_rx_oob(struct device *dev, struct mana_rxq *rxq, dma_addr_t da; void *va; - va = mana_get_rxfrag(rxq, dev, &da, &from_pool, true); + va = mana_get_rxfrag(rxq, dev, &da, &from_pool); if (!va) return; @@ -2176,7 +2147,7 @@ static int mana_fill_rx_oob(struct mana_recv_buf_oob *rx_oob, u32 mem_key, if (mpc->rxbufs_pre) va = mana_get_rxbuf_pre(rxq, &da); else - va = mana_get_rxfrag(rxq, dev, &da, &from_pool, false); + va = mana_get_rxfrag(rxq, dev, &da, &from_pool); if (!va) return -ENOMEM; @@ -2262,6 +2233,7 @@ static int mana_create_page_pool(struct mana_rxq *rxq, struct gdma_context *gc) pprm.nid = gc->numa_node; pprm.napi = &rxq->rx_cq.napi; pprm.netdev = rxq->ndev; + pprm.order = get_order(rxq->alloc_size); rxq->page_pool = page_pool_create(&pprm);
diff --git a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c index b7d9657..7c501a7 100644 --- a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c +++ b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
@@ -2482,7 +2482,7 @@ static int myri10ge_close(struct net_device *dev) if (mgp->ss[0].tx.req_bytes == NULL) return 0; - del_timer_sync(&mgp->watchdog_timer); + timer_delete_sync(&mgp->watchdog_timer); mgp->running = MYRI10GE_ETH_STOPPING; for (i = 0; i < mgp->num_slices; i++) napi_disable(&mgp->ss[i].napi);
diff --git a/drivers/net/ethernet/natsemi/natsemi.c b/drivers/net/ethernet/natsemi/natsemi.c index ad0c148..0560669 100644 --- a/drivers/net/ethernet/natsemi/natsemi.c +++ b/drivers/net/ethernet/natsemi/natsemi.c
@@ -3179,7 +3179,7 @@ static int netdev_close(struct net_device *dev) * the final WOL settings? */ - del_timer_sync(&np->timer); + timer_delete_sync(&np->timer); disable_irq(irq); spin_lock_irq(&np->lock); natsemi_irq_disable(dev); @@ -3278,7 +3278,7 @@ static int __maybe_unused natsemi_suspend(struct device *dev_d) if (netif_running (dev)) { const int irq = np->pci_dev->irq; - del_timer_sync(&np->timer); + timer_delete_sync(&np->timer); disable_irq(irq); spin_lock_irq(&np->lock);
diff --git a/drivers/net/ethernet/natsemi/ns83820.c b/drivers/net/ethernet/natsemi/ns83820.c index bea969d..bf03477 100644 --- a/drivers/net/ethernet/natsemi/ns83820.c +++ b/drivers/net/ethernet/natsemi/ns83820.c
@@ -1527,7 +1527,7 @@ static int ns83820_stop(struct net_device *ndev) struct ns83820 *dev = PRIV(ndev); /* FIXME: protect against interrupt handler? */ - del_timer_sync(&dev->tx_watchdog); + timer_delete_sync(&dev->tx_watchdog); ns83820_disable_interrupts(dev);
diff --git a/drivers/net/ethernet/neterion/s2io.c b/drivers/net/ethernet/neterion/s2io.c index f8016dc..3e55e8dc 100644 --- a/drivers/net/ethernet/neterion/s2io.c +++ b/drivers/net/ethernet/neterion/s2io.c
@@ -7019,7 +7019,7 @@ static void do_s2io_card_down(struct s2io_nic *sp, int do_io) if (!is_s2io_card_up(sp)) return; - del_timer_sync(&sp->alarm_timer); + timer_delete_sync(&sp->alarm_timer); /* If s2io_set_link task is executing, wait till it completes. */ while (test_and_set_bit(__S2IO_STATE_LINK_TASK, &(sp->state))) msleep(50);
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c index abba165..95514fa 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
@@ -227,7 +227,7 @@ static void nfp_net_reconfig_sync_enter(struct nfp_net *nn) spin_unlock_bh(&nn->reconfig_lock); if (cancelled_timer) { - del_timer_sync(&nn->reconfig_timer); + timer_delete_sync(&nn->reconfig_timer); nfp_net_reconfig_wait(nn, nn->reconfig_timer.expires); }
diff --git a/drivers/net/ethernet/nvidia/forcedeth.c b/drivers/net/ethernet/nvidia/forcedeth.c index 499e5e3..29cb74c 100644 --- a/drivers/net/ethernet/nvidia/forcedeth.c +++ b/drivers/net/ethernet/nvidia/forcedeth.c
@@ -5623,9 +5623,9 @@ static int nv_close(struct net_device *dev) napi_disable(&np->napi); synchronize_irq(np->pci_dev->irq); - del_timer_sync(&np->oom_kick); - del_timer_sync(&np->nic_poll); - del_timer_sync(&np->stats_poll); + timer_delete_sync(&np->oom_kick); + timer_delete_sync(&np->nic_poll); + timer_delete_sync(&np->stats_poll); netif_stop_queue(dev); spin_lock_irq(&np->lock);
diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c index 4ac29cd..1651df8 100644 --- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c +++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
@@ -1916,7 +1916,7 @@ void pch_gbe_down(struct pch_gbe_adapter *adapter) pch_gbe_irq_disable(adapter); pch_gbe_free_irq(adapter); - del_timer_sync(&adapter->watchdog_timer); + timer_delete_sync(&adapter->watchdog_timer); netdev->tx_queue_len = adapter->tx_queue_len; netif_carrier_off(netdev);
diff --git a/drivers/net/ethernet/packetengines/hamachi.c b/drivers/net/ethernet/packetengines/hamachi.c index a36d422..26bc8b3 100644 --- a/drivers/net/ethernet/packetengines/hamachi.c +++ b/drivers/net/ethernet/packetengines/hamachi.c
@@ -1712,7 +1712,7 @@ static int hamachi_close(struct net_device *dev) free_irq(hmp->pci_dev->irq, dev); - del_timer_sync(&hmp->timer); + timer_delete_sync(&hmp->timer); /* Free all the skbuffs in the Rx queue. */ for (i = 0; i < RX_RING_SIZE; i++) {
diff --git a/drivers/net/ethernet/packetengines/yellowfin.c b/drivers/net/ethernet/packetengines/yellowfin.c index c0515dc..21b760e 100644 --- a/drivers/net/ethernet/packetengines/yellowfin.c +++ b/drivers/net/ethernet/packetengines/yellowfin.c
@@ -1222,7 +1222,7 @@ static int yellowfin_close(struct net_device *dev) iowrite32(0x80000000, ioaddr + RxCtrl); iowrite32(0x80000000, ioaddr + TxCtrl); - del_timer(&yp->timer); + timer_delete(&yp->timer); #if defined(__i386__) if (yellowfin_debug > 2) {
diff --git a/drivers/net/ethernet/pasemi/pasemi_mac.c b/drivers/net/ethernet/pasemi/pasemi_mac.c index cb4e12df..8013807 100644 --- a/drivers/net/ethernet/pasemi/pasemi_mac.c +++ b/drivers/net/ethernet/pasemi/pasemi_mac.c
@@ -1288,7 +1288,7 @@ static int pasemi_mac_close(struct net_device *dev) phy_disconnect(dev->phydev); } - del_timer_sync(&mac->tx->clean_timer); + timer_delete_sync(&mac->tx->clean_timer); netif_stop_queue(dev); napi_disable(&mac->napi);
diff --git a/drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c b/drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c index f5dc876..4c377bd 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c +++ b/drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c
@@ -441,7 +441,7 @@ static void ionic_reset_prepare(struct pci_dev *pdev) set_bit(IONIC_LIF_F_FW_RESET, lif->state); - del_timer_sync(&ionic->watchdog_timer); + timer_delete_sync(&ionic->watchdog_timer); cancel_work_sync(&lif->deferred.work); mutex_lock(&lif->queue_lock);
diff --git a/drivers/net/ethernet/qlogic/qla3xxx.c b/drivers/net/ethernet/qlogic/qla3xxx.c index fc78bc9..bf5bf8c 100644 --- a/drivers/net/ethernet/qlogic/qla3xxx.c +++ b/drivers/net/ethernet/qlogic/qla3xxx.c
@@ -3420,7 +3420,7 @@ static int ql_adapter_down(struct ql3_adapter *qdev, int do_reset) pci_disable_msi(qdev->pdev); } - del_timer_sync(&qdev->adapter_timer); + timer_delete_sync(&qdev->adapter_timer); napi_disable(&qdev->napi);
diff --git a/drivers/net/ethernet/realtek/atp.c b/drivers/net/ethernet/realtek/atp.c index 6cbcb31..c73a57e 100644 --- a/drivers/net/ethernet/realtek/atp.c +++ b/drivers/net/ethernet/realtek/atp.c
@@ -832,7 +832,7 @@ net_close(struct net_device *dev) netif_stop_queue(dev); - del_timer_sync(&lp->timer); + timer_delete_sync(&lp->timer); /* Flush the Tx and disable Rx here. */ lp->addr_mode = CMR2h_OFF;
diff --git a/drivers/net/ethernet/rocker/rocker_ofdpa.c b/drivers/net/ethernet/rocker/rocker_ofdpa.c index 8269904..d5db261 100644 --- a/drivers/net/ethernet/rocker/rocker_ofdpa.c +++ b/drivers/net/ethernet/rocker/rocker_ofdpa.c
@@ -2386,7 +2386,7 @@ static void ofdpa_fini(struct rocker *rocker) struct hlist_node *tmp; int bkt; - del_timer_sync(&ofdpa->fdb_cleanup_timer); + timer_delete_sync(&ofdpa->fdb_cleanup_timer); flush_workqueue(rocker->rocker_owq); spin_lock_irqsave(&ofdpa->flow_tbl_lock, flags);
diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c b/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c index 12c8396..36b63bf 100644 --- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c +++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c
@@ -91,7 +91,7 @@ void sxgbe_disable_eee_mode(struct sxgbe_priv_data * const priv) { /* Exit and disable EEE in case of we are in LPI state. */ priv->hw->mac->reset_eee_mode(priv->ioaddr); - del_timer_sync(&priv->eee_ctrl_timer); + timer_delete_sync(&priv->eee_ctrl_timer); priv->tx_path_in_lpi_mode = false; } @@ -1044,7 +1044,7 @@ static void sxgbe_tx_del_timer(struct sxgbe_priv_data *priv) SXGBE_FOR_EACH_QUEUE(SXGBE_TX_QUEUES, queue_num) { struct sxgbe_tx_queue *p = priv->txq[queue_num]; - del_timer_sync(&p->txtimer); + timer_delete_sync(&p->txtimer); } } @@ -1208,7 +1208,7 @@ static int sxgbe_release(struct net_device *dev) struct sxgbe_priv_data *priv = netdev_priv(dev); if (priv->eee_enabled) - del_timer_sync(&priv->eee_ctrl_timer); + timer_delete_sync(&priv->eee_ctrl_timer); /* Stop and disconnect the PHY */ if (dev->phydev) {
diff --git a/drivers/net/ethernet/seeq/ether3.c b/drivers/net/ethernet/seeq/ether3.c index 9319a26..1d65113 100644 --- a/drivers/net/ethernet/seeq/ether3.c +++ b/drivers/net/ethernet/seeq/ether3.c
@@ -181,7 +181,7 @@ static void ether3_ledoff(struct timer_list *t) */ static inline void ether3_ledon(struct net_device *dev) { - del_timer(&priv(dev)->timer); + timer_delete(&priv(dev)->timer); priv(dev)->timer.expires = jiffies + HZ / 50; /* leave on for 1/50th second */ add_timer(&priv(dev)->timer); if (priv(dev)->regs.config2 & CFG2_CTRLO) @@ -454,7 +454,7 @@ static void ether3_timeout(struct net_device *dev, unsigned int txqueue) { unsigned long flags; - del_timer(&priv(dev)->timer); + timer_delete(&priv(dev)->timer); local_irq_save(flags); printk(KERN_ERR "%s: transmit timed out, network cable problem?\n", dev->name); @@ -851,7 +851,7 @@ static void ether3_remove(struct expansion_card *ec) ecard_set_drvdata(ec, NULL); unregister_netdev(dev); - del_timer_sync(&priv(dev)->timer); + timer_delete_sync(&priv(dev)->timer); free_netdev(dev); ecard_release_resources(ec); }
diff --git a/drivers/net/ethernet/sfc/ef100_netdev.c b/drivers/net/ethernet/sfc/ef100_netdev.c index d941f07..3a06e3b 100644 --- a/drivers/net/ethernet/sfc/ef100_netdev.c +++ b/drivers/net/ethernet/sfc/ef100_netdev.c
@@ -450,8 +450,9 @@ int ef100_probe_netdev(struct efx_probe_data *probe_data) net_dev->hw_enc_features |= efx->type->offload_features; net_dev->vlan_features |= NETIF_F_HW_CSUM | NETIF_F_SG | NETIF_F_HIGHDMA | NETIF_F_ALL_TSO; - netif_set_tso_max_segs(net_dev, - ESE_EF100_DP_GZ_TSO_MAX_HDR_NUM_SEGS_DEFAULT); + nic_data = efx->nic_data; + netif_set_tso_max_size(efx->net_dev, nic_data->tso_max_payload_len); + netif_set_tso_max_segs(efx->net_dev, nic_data->tso_max_payload_num_segs); rc = efx_ef100_init_datapath_caps(efx); if (rc < 0) @@ -477,7 +478,6 @@ int ef100_probe_netdev(struct efx_probe_data *probe_data) /* Don't fail init if RSS setup doesn't work. */ efx_mcdi_push_default_indir_table(efx, efx->n_rx_channels); - nic_data = efx->nic_data; rc = ef100_get_mac_address(efx, net_dev->perm_addr, CLIENT_HANDLE_SELF, efx->type->is_vf); if (rc)
diff --git a/drivers/net/ethernet/sfc/ef100_nic.c b/drivers/net/ethernet/sfc/ef100_nic.c index 62e674d..3ad95a4 100644 --- a/drivers/net/ethernet/sfc/ef100_nic.c +++ b/drivers/net/ethernet/sfc/ef100_nic.c
@@ -887,8 +887,7 @@ static int ef100_process_design_param(struct efx_nic *efx, case ESE_EF100_DP_GZ_TSO_MAX_HDR_NUM_SEGS: /* We always put HDR_NUM_SEGS=1 in our TSO descriptors */ if (!reader->value) { - netif_err(efx, probe, efx->net_dev, - "TSO_MAX_HDR_NUM_SEGS < 1\n"); + pci_err(efx->pci_dev, "TSO_MAX_HDR_NUM_SEGS < 1\n"); return -EOPNOTSUPP; } return 0; @@ -901,32 +900,28 @@ static int ef100_process_design_param(struct efx_nic *efx, */ if (!reader->value || reader->value > EFX_MIN_DMAQ_SIZE || EFX_MIN_DMAQ_SIZE % (u32)reader->value) { - netif_err(efx, probe, efx->net_dev, - "%s size granularity is %llu, can't guarantee safety\n", - reader->type == ESE_EF100_DP_GZ_RXQ_SIZE_GRANULARITY ? "RXQ" : "TXQ", - reader->value); + pci_err(efx->pci_dev, + "%s size granularity is %llu, can't guarantee safety\n", + reader->type == ESE_EF100_DP_GZ_RXQ_SIZE_GRANULARITY ? "RXQ" : "TXQ", + reader->value); return -EOPNOTSUPP; } return 0; case ESE_EF100_DP_GZ_TSO_MAX_PAYLOAD_LEN: nic_data->tso_max_payload_len = min_t(u64, reader->value, GSO_LEGACY_MAX_SIZE); - netif_set_tso_max_size(efx->net_dev, - nic_data->tso_max_payload_len); return 0; case ESE_EF100_DP_GZ_TSO_MAX_PAYLOAD_NUM_SEGS: nic_data->tso_max_payload_num_segs = min_t(u64, reader->value, 0xffff); - netif_set_tso_max_segs(efx->net_dev, - nic_data->tso_max_payload_num_segs); return 0; case ESE_EF100_DP_GZ_TSO_MAX_NUM_FRAMES: nic_data->tso_max_frames = min_t(u64, reader->value, 0xffff); return 0; case ESE_EF100_DP_GZ_COMPAT: if (reader->value) { - netif_err(efx, probe, efx->net_dev, - "DP_COMPAT has unknown bits %#llx, driver not compatible with this hw\n", - reader->value); + pci_err(efx->pci_dev, + "DP_COMPAT has unknown bits %#llx, driver not compatible with this hw\n", + reader->value); return -EOPNOTSUPP; } return 0; @@ -946,10 +941,10 @@ static int ef100_process_design_param(struct efx_nic *efx, * So the value of this shouldn't matter. */ if (reader->value != ESE_EF100_DP_GZ_VI_STRIDES_DEFAULT) - netif_dbg(efx, probe, efx->net_dev, - "NIC has other than default VI_STRIDES (mask " - "%#llx), early probing might use wrong one\n", - reader->value); + pci_dbg(efx->pci_dev, + "NIC has other than default VI_STRIDES (mask " + "%#llx), early probing might use wrong one\n", + reader->value); return 0; case ESE_EF100_DP_GZ_RX_MAX_RUNT: /* Driver doesn't look at L2_STATUS:LEN_ERR bit, so we don't @@ -961,9 +956,9 @@ static int ef100_process_design_param(struct efx_nic *efx, /* Host interface says "Drivers should ignore design parameters * that they do not recognise." */ - netif_dbg(efx, probe, efx->net_dev, - "Ignoring unrecognised design parameter %u\n", - reader->type); + pci_dbg(efx->pci_dev, + "Ignoring unrecognised design parameter %u\n", + reader->type); return 0; } } @@ -999,13 +994,13 @@ static int ef100_check_design_params(struct efx_nic *efx) */ if (reader.state != EF100_TLV_TYPE) { if (reader.state == EF100_TLV_TYPE_CONT) - netif_err(efx, probe, efx->net_dev, - "truncated design parameter (incomplete type %u)\n", - reader.type); + pci_err(efx->pci_dev, + "truncated design parameter (incomplete type %u)\n", + reader.type); else - netif_err(efx, probe, efx->net_dev, - "truncated design parameter %u\n", - reader.type); + pci_err(efx->pci_dev, + "truncated design parameter %u\n", + reader.type); rc = -EIO; } out:
diff --git a/drivers/net/ethernet/sfc/falcon/falcon.c b/drivers/net/ethernet/sfc/falcon/falcon.c index 4af5633..b865275b 100644 --- a/drivers/net/ethernet/sfc/falcon/falcon.c +++ b/drivers/net/ethernet/sfc/falcon/falcon.c
@@ -2657,7 +2657,7 @@ void falcon_stop_nic_stats(struct ef4_nic *efx) ++nic_data->stats_disable_count; spin_unlock_bh(&efx->stats_lock); - del_timer_sync(&nic_data->stats_timer); + timer_delete_sync(&nic_data->stats_timer); /* Wait enough time for the most recent transfer to * complete. */
diff --git a/drivers/net/ethernet/sfc/falcon/rx.c b/drivers/net/ethernet/sfc/falcon/rx.c index 6bbdb5d..38ad7ac 100644 --- a/drivers/net/ethernet/sfc/falcon/rx.c +++ b/drivers/net/ethernet/sfc/falcon/rx.c
@@ -791,7 +791,7 @@ void ef4_fini_rx_queue(struct ef4_rx_queue *rx_queue) netif_dbg(rx_queue->efx, drv, rx_queue->efx->net_dev, "shutting down RX queue %d\n", ef4_rx_queue_index(rx_queue)); - del_timer_sync(&rx_queue->slow_fill); + timer_delete_sync(&rx_queue->slow_fill); /* Release RX buffers from the current read ptr to the write ptr */ if (rx_queue->buffer) {
diff --git a/drivers/net/ethernet/sfc/mcdi.c b/drivers/net/ethernet/sfc/mcdi.c index dbd2ee9..dcef058 100644 --- a/drivers/net/ethernet/sfc/mcdi.c +++ b/drivers/net/ethernet/sfc/mcdi.c
@@ -530,7 +530,7 @@ static bool efx_mcdi_complete_async(struct efx_mcdi_iface *mcdi, bool timeout) * of it aborting the next request. */ if (!timeout) - del_timer_sync(&mcdi->async_timer); + timer_delete_sync(&mcdi->async_timer); spin_lock(&mcdi->async_lock); async = list_first_entry(&mcdi->async_list, @@ -1122,7 +1122,7 @@ void efx_mcdi_flush_async(struct efx_nic *efx) /* We must be in poll or fail mode so no more requests can be queued */ BUG_ON(mcdi->mode == MCDI_MODE_EVENTS); - del_timer_sync(&mcdi->async_timer); + timer_delete_sync(&mcdi->async_timer); /* If a request is still running, make sure we give the MC * time to complete it so that the response won't overwrite our
diff --git a/drivers/net/ethernet/sfc/rx_common.c b/drivers/net/ethernet/sfc/rx_common.c index 4cc8320..8eb272b 100644 --- a/drivers/net/ethernet/sfc/rx_common.c +++ b/drivers/net/ethernet/sfc/rx_common.c
@@ -285,7 +285,7 @@ void efx_fini_rx_queue(struct efx_rx_queue *rx_queue) netif_dbg(rx_queue->efx, drv, rx_queue->efx->net_dev, "shutting down RX queue %d\n", efx_rx_queue_index(rx_queue)); - del_timer_sync(&rx_queue->slow_fill); + timer_delete_sync(&rx_queue->slow_fill); if (rx_queue->grant_credits) flush_work(&rx_queue->grant_work);
diff --git a/drivers/net/ethernet/sfc/siena/mcdi.c b/drivers/net/ethernet/sfc/siena/mcdi.c index 3f7899d..99ab5f2 100644 --- a/drivers/net/ethernet/sfc/siena/mcdi.c +++ b/drivers/net/ethernet/sfc/siena/mcdi.c
@@ -534,7 +534,7 @@ static bool efx_mcdi_complete_async(struct efx_mcdi_iface *mcdi, bool timeout) * of it aborting the next request. */ if (!timeout) - del_timer_sync(&mcdi->async_timer); + timer_delete_sync(&mcdi->async_timer); spin_lock(&mcdi->async_lock); async = list_first_entry(&mcdi->async_list, @@ -1145,7 +1145,7 @@ void efx_siena_mcdi_flush_async(struct efx_nic *efx) /* We must be in poll or fail mode so no more requests can be queued */ BUG_ON(mcdi->mode == MCDI_MODE_EVENTS); - del_timer_sync(&mcdi->async_timer); + timer_delete_sync(&mcdi->async_timer); /* If a request is still running, make sure we give the MC * time to complete it so that the response won't overwrite our
diff --git a/drivers/net/ethernet/sfc/siena/rx_common.c b/drivers/net/ethernet/sfc/siena/rx_common.c index 2839d0e..ab493e5 100644 --- a/drivers/net/ethernet/sfc/siena/rx_common.c +++ b/drivers/net/ethernet/sfc/siena/rx_common.c
@@ -284,7 +284,7 @@ void efx_siena_fini_rx_queue(struct efx_rx_queue *rx_queue) netif_dbg(rx_queue->efx, drv, rx_queue->efx->net_dev, "shutting down RX queue %d\n", efx_rx_queue_index(rx_queue)); - del_timer_sync(&rx_queue->slow_fill); + timer_delete_sync(&rx_queue->slow_fill); /* Release RX buffers from the current read ptr to the write ptr */ if (rx_queue->buffer) {
diff --git a/drivers/net/ethernet/sgi/ioc3-eth.c b/drivers/net/ethernet/sgi/ioc3-eth.c index 4535579..7196e1c 100644 --- a/drivers/net/ethernet/sgi/ioc3-eth.c +++ b/drivers/net/ethernet/sgi/ioc3-eth.c
@@ -718,7 +718,7 @@ static void ioc3_init(struct net_device *dev) struct ioc3_private *ip = netdev_priv(dev); struct ioc3_ethregs *regs = ip->regs; - del_timer_sync(&ip->ioc3_timer); /* Kill if running */ + timer_delete_sync(&ip->ioc3_timer); /* Kill if running */ writel(EMCR_RST, ®s->emcr); /* Reset */ readl(®s->emcr); /* Flush WB */ @@ -801,7 +801,7 @@ static int ioc3_close(struct net_device *dev) { struct ioc3_private *ip = netdev_priv(dev); - del_timer_sync(&ip->ioc3_timer); + timer_delete_sync(&ip->ioc3_timer); netif_stop_queue(dev); @@ -950,7 +950,7 @@ static int ioc3eth_probe(struct platform_device *pdev) return 0; out_stop: - del_timer_sync(&ip->ioc3_timer); + timer_delete_sync(&ip->ioc3_timer); if (ip->rxr) dma_free_coherent(ip->dma_dev, RX_RING_SIZE, ip->rxr, ip->rxr_dma); @@ -971,7 +971,7 @@ static void ioc3eth_remove(struct platform_device *pdev) dma_free_coherent(ip->dma_dev, TX_RING_SIZE + SZ_16K - 1, ip->tx_ring, ip->txr_dma); unregister_netdev(dev); - del_timer_sync(&ip->ioc3_timer); + timer_delete_sync(&ip->ioc3_timer); free_netdev(dev); }
diff --git a/drivers/net/ethernet/sis/sis190.c b/drivers/net/ethernet/sis/sis190.c index dda4e48..d10b147 100644 --- a/drivers/net/ethernet/sis/sis190.c +++ b/drivers/net/ethernet/sis/sis190.c
@@ -758,7 +758,7 @@ static irqreturn_t sis190_irq(int irq, void *__dev) if (status & LinkChange) { netif_info(tp, intr, dev, "link change\n"); - del_timer(&tp->timer); + timer_delete(&tp->timer); schedule_work(&tp->phy_task); } @@ -1034,7 +1034,7 @@ static inline void sis190_delete_timer(struct net_device *dev) { struct sis190_private *tp = netdev_priv(dev); - del_timer_sync(&tp->timer); + timer_delete_sync(&tp->timer); } static inline void sis190_request_timer(struct net_device *dev)
diff --git a/drivers/net/ethernet/sis/sis900.c b/drivers/net/ethernet/sis/sis900.c index 85b8503..332cbd7 100644 --- a/drivers/net/ethernet/sis/sis900.c +++ b/drivers/net/ethernet/sis/sis900.c
@@ -1983,7 +1983,7 @@ static int sis900_close(struct net_device *net_dev) /* Stop the chip's Tx and Rx Status Machine */ sw32(cr, RxDIS | TxDIS | sr32(cr)); - del_timer(&sis_priv->timer); + timer_delete(&sis_priv->timer); free_irq(pdev->irq, net_dev);
diff --git a/drivers/net/ethernet/smsc/epic100.c b/drivers/net/ethernet/smsc/epic100.c index 013e90d..ca0ab3a 100644 --- a/drivers/net/ethernet/smsc/epic100.c +++ b/drivers/net/ethernet/smsc/epic100.c
@@ -1292,7 +1292,7 @@ static int epic_close(struct net_device *dev) netdev_dbg(dev, "Shutting down ethercard, status was %2.2x.\n", er32(INTSTAT)); - del_timer_sync(&ep->timer); + timer_delete_sync(&ep->timer); epic_disable_int(dev, ep);
diff --git a/drivers/net/ethernet/smsc/smc91c92_cs.c b/drivers/net/ethernet/smsc/smc91c92_cs.c index 86e3ec2..6fa957f 100644 --- a/drivers/net/ethernet/smsc/smc91c92_cs.c +++ b/drivers/net/ethernet/smsc/smc91c92_cs.c
@@ -1105,7 +1105,7 @@ static int smc_close(struct net_device *dev) outw(CTL_POWERDOWN, ioaddr + CONTROL ); link->open--; - del_timer_sync(&smc->media); + timer_delete_sync(&smc->media); return 0; } /* smc_close */
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 2795326..59d07d0 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -467,7 +467,7 @@ static void stmmac_try_to_start_sw_lpi(struct stmmac_priv *priv) */ static void stmmac_stop_sw_lpi(struct stmmac_priv *priv) { - del_timer_sync(&priv->eee_ctrl_timer); + timer_delete_sync(&priv->eee_ctrl_timer); stmmac_set_lpi_mode(priv, priv->hw, STMMAC_LPI_DISABLE, false, 0); priv->tx_path_in_lpi_mode = false; } @@ -1082,7 +1082,7 @@ static void stmmac_mac_disable_tx_lpi(struct phylink_config *config) netdev_dbg(priv->dev, "disable EEE\n"); priv->eee_sw_timer_en = false; - del_timer_sync(&priv->eee_ctrl_timer); + timer_delete_sync(&priv->eee_ctrl_timer); stmmac_set_lpi_mode(priv, priv->hw, STMMAC_LPI_DISABLE, false, 0); priv->tx_path_in_lpi_mode = false; @@ -7842,7 +7842,7 @@ int stmmac_suspend(struct device *dev) if (priv->eee_sw_timer_en) { priv->tx_path_in_lpi_mode = false; - del_timer_sync(&priv->eee_ctrl_timer); + timer_delete_sync(&priv->eee_ctrl_timer); } /* Stop TX/RX DMA */
diff --git a/drivers/net/ethernet/sun/cassini.c b/drivers/net/ethernet/sun/cassini.c index b8948d5..b777e5a 100644 --- a/drivers/net/ethernet/sun/cassini.c +++ b/drivers/net/ethernet/sun/cassini.c
@@ -3779,7 +3779,7 @@ static void cas_shutdown(struct cas *cp) /* Make us not-running to avoid timers respawning */ cp->hw_running = 0; - del_timer_sync(&cp->link_timer); + timer_delete_sync(&cp->link_timer); /* Stop the reset task */ #if 0
diff --git a/drivers/net/ethernet/sun/ldmvsw.c b/drivers/net/ethernet/sun/ldmvsw.c index a9a6670..6fc37ab 100644 --- a/drivers/net/ethernet/sun/ldmvsw.c +++ b/drivers/net/ethernet/sun/ldmvsw.c
@@ -390,7 +390,7 @@ static int vsw_port_probe(struct vio_dev *vdev, const struct vio_device_id *id) return 0; err_out_del_timer: - del_timer_sync(&port->clean_timer); + timer_delete_sync(&port->clean_timer); list_del_rcu(&port->list); synchronize_rcu(); netif_napi_del(&port->napi); @@ -408,8 +408,8 @@ static void vsw_port_remove(struct vio_dev *vdev) unsigned long flags; if (port) { - del_timer_sync(&port->vio.timer); - del_timer_sync(&port->clean_timer); + timer_delete_sync(&port->vio.timer); + timer_delete_sync(&port->clean_timer); napi_disable(&port->napi); unregister_netdev(port->dev);
diff --git a/drivers/net/ethernet/sun/niu.c b/drivers/net/ethernet/sun/niu.c index 72177fe..73c07f1 100644 --- a/drivers/net/ethernet/sun/niu.c +++ b/drivers/net/ethernet/sun/niu.c
@@ -6165,7 +6165,7 @@ static void niu_full_shutdown(struct niu *np, struct net_device *dev) niu_disable_napi(np); netif_tx_stop_all_queues(dev); - del_timer_sync(&np->timer); + timer_delete_sync(&np->timer); spin_lock_irq(&np->lock); @@ -6511,7 +6511,7 @@ static void niu_reset_task(struct work_struct *work) spin_unlock_irqrestore(&np->lock, flags); - del_timer_sync(&np->timer); + timer_delete_sync(&np->timer); niu_netif_stop(np); @@ -9914,7 +9914,7 @@ static int __maybe_unused niu_suspend(struct device *dev_d) flush_work(&np->reset_task); niu_netif_stop(np); - del_timer_sync(&np->timer); + timer_delete_sync(&np->timer); spin_lock_irqsave(&np->lock, flags); niu_enable_interrupts(np, 0);
diff --git a/drivers/net/ethernet/sun/sunbmac.c b/drivers/net/ethernet/sun/sunbmac.c index bbb3a6c..d2c8210 100644 --- a/drivers/net/ethernet/sun/sunbmac.c +++ b/drivers/net/ethernet/sun/sunbmac.c
@@ -931,7 +931,7 @@ static int bigmac_close(struct net_device *dev) { struct bigmac *bp = netdev_priv(dev); - del_timer(&bp->bigmac_timer); + timer_delete(&bp->bigmac_timer); bp->timer_state = asleep; bp->timer_ticks = 0;
diff --git a/drivers/net/ethernet/sun/sungem.c b/drivers/net/ethernet/sun/sungem.c index 3e5f9b1..06579d7 100644 --- a/drivers/net/ethernet/sun/sungem.c +++ b/drivers/net/ethernet/sun/sungem.c
@@ -2180,7 +2180,7 @@ static void gem_do_stop(struct net_device *dev, int wol) gem_disable_ints(gp); /* Stop the link timer */ - del_timer_sync(&gp->link_timer); + timer_delete_sync(&gp->link_timer); /* We cannot cancel the reset task while holding the * rtnl lock, we'd get an A->B / B->A deadlock stituation @@ -2230,7 +2230,7 @@ static void gem_reset_task(struct work_struct *work) } /* Stop the link timer */ - del_timer_sync(&gp->link_timer); + timer_delete_sync(&gp->link_timer); /* Stop NAPI and tx */ gem_netif_stop(gp); @@ -2610,7 +2610,7 @@ static int gem_set_link_ksettings(struct net_device *dev, /* Apply settings and restart link process. */ if (netif_device_present(gp->dev)) { - del_timer_sync(&gp->link_timer); + timer_delete_sync(&gp->link_timer); gem_begin_auto_negotiation(gp, cmd); } @@ -2626,7 +2626,7 @@ static int gem_nway_reset(struct net_device *dev) /* Restart link process */ if (netif_device_present(gp->dev)) { - del_timer_sync(&gp->link_timer); + timer_delete_sync(&gp->link_timer); gem_begin_auto_negotiation(gp, NULL); }
diff --git a/drivers/net/ethernet/sun/sunhme.c b/drivers/net/ethernet/sun/sunhme.c index 50ace46..9a75866 100644 --- a/drivers/net/ethernet/sun/sunhme.c +++ b/drivers/net/ethernet/sun/sunhme.c
@@ -1265,7 +1265,7 @@ static int happy_meal_init(struct happy_meal *hp) u32 regtmp, rxcfg; /* If auto-negotiation timer is running, kill it. */ - del_timer(&hp->happy_timer); + timer_delete(&hp->happy_timer); HMD("happy_flags[%08x]\n", hp->happy_flags); if (!(hp->happy_flags & HFLAG_INIT)) { @@ -1922,7 +1922,7 @@ static int happy_meal_close(struct net_device *dev) happy_meal_clean_rings(hp); /* If auto-negotiation timer is running, kill it. */ - del_timer(&hp->happy_timer); + timer_delete(&hp->happy_timer); spin_unlock_irq(&hp->happy_lock); @@ -2184,7 +2184,7 @@ static int hme_set_link_ksettings(struct net_device *dev, /* Ok, do it to it. */ spin_lock_irq(&hp->happy_lock); - del_timer(&hp->happy_timer); + timer_delete(&hp->happy_timer); happy_meal_begin_auto_negotiation(hp, hp->tcvregs, cmd); spin_unlock_irq(&hp->happy_lock);
diff --git a/drivers/net/ethernet/sun/sunvnet.c b/drivers/net/ethernet/sun/sunvnet.c index 1e887d95..a2a3e94 100644 --- a/drivers/net/ethernet/sun/sunvnet.c +++ b/drivers/net/ethernet/sun/sunvnet.c
@@ -505,7 +505,7 @@ static void vnet_port_remove(struct vio_dev *vdev) struct vnet_port *port = dev_get_drvdata(&vdev->dev); if (port) { - del_timer_sync(&port->vio.timer); + timer_delete_sync(&port->vio.timer); napi_disable(&port->napi);
diff --git a/drivers/net/ethernet/sun/sunvnet_common.c b/drivers/net/ethernet/sun/sunvnet_common.c index 1cacb2a..ddc6d46 100644 --- a/drivers/net/ethernet/sun/sunvnet_common.c +++ b/drivers/net/ethernet/sun/sunvnet_common.c
@@ -1058,7 +1058,7 @@ void sunvnet_clean_timer_expire_common(struct timer_list *t) (void)mod_timer(&port->clean_timer, jiffies + VNET_CLEAN_TIMEOUT); else - del_timer(&port->clean_timer); + timer_delete(&port->clean_timer); } EXPORT_SYMBOL_GPL(sunvnet_clean_timer_expire_common); @@ -1513,7 +1513,7 @@ sunvnet_start_xmit_common(struct sk_buff *skb, struct net_device *dev, (void)mod_timer(&port->clean_timer, jiffies + VNET_CLEAN_TIMEOUT); else if (port) - del_timer(&port->clean_timer); + timer_delete(&port->clean_timer); rcu_read_unlock(); dev_kfree_skb(skb); vnet_free_skbs(freeskbs); @@ -1707,7 +1707,7 @@ EXPORT_SYMBOL_GPL(sunvnet_port_free_tx_bufs_common); void vnet_port_reset(struct vnet_port *port) { - del_timer(&port->clean_timer); + timer_delete(&port->clean_timer); sunvnet_port_free_tx_bufs_common(port); port->rmtu = 0; port->tso = (port->vsw == 0); /* no tso in vsw, misbehaves in bridge */
diff --git a/drivers/net/ethernet/synopsys/dwc-xlgmac-net.c b/drivers/net/ethernet/synopsys/dwc-xlgmac-net.c index d1793b6..24e4b24 100644 --- a/drivers/net/ethernet/synopsys/dwc-xlgmac-net.c +++ b/drivers/net/ethernet/synopsys/dwc-xlgmac-net.c
@@ -405,7 +405,7 @@ static void xlgmac_stop_timers(struct xlgmac_pdata *pdata) if (!channel->tx_ring) break; - del_timer_sync(&channel->tx_timer); + timer_delete_sync(&channel->tx_timer); } }
diff --git a/drivers/net/ethernet/ti/cpsw_ale.c b/drivers/net/ethernet/ti/cpsw_ale.c index 5cc72a9..7f77694 100644 --- a/drivers/net/ethernet/ti/cpsw_ale.c +++ b/drivers/net/ethernet/ti/cpsw_ale.c
@@ -1287,7 +1287,7 @@ static void cpsw_ale_aging_stop(struct cpsw_ale *ale) return; } - del_timer_sync(&ale->timer); + timer_delete_sync(&ale->timer); } void cpsw_ale_start(struct cpsw_ale *ale)
diff --git a/drivers/net/ethernet/ti/netcp_ethss.c b/drivers/net/ethernet/ti/netcp_ethss.c index 63e686f..fd2b745 100644 --- a/drivers/net/ethernet/ti/netcp_ethss.c +++ b/drivers/net/ethernet/ti/netcp_ethss.c
@@ -3796,7 +3796,7 @@ static int gbe_remove(struct netcp_device *netcp_device, void *inst_priv) { struct gbe_priv *gbe_dev = inst_priv; - del_timer_sync(&gbe_dev->timer); + timer_delete_sync(&gbe_dev->timer); cpts_release(gbe_dev->cpts); cpsw_ale_stop(gbe_dev->ale); netcp_txpipe_close(&gbe_dev->tx_pipe);
diff --git a/drivers/net/ethernet/ti/tlan.c b/drivers/net/ethernet/ti/tlan.c index b3da76e..d9240fb 100644 --- a/drivers/net/ethernet/ti/tlan.c +++ b/drivers/net/ethernet/ti/tlan.c
@@ -332,13 +332,13 @@ static void tlan_stop(struct net_device *dev) { struct tlan_priv *priv = netdev_priv(dev); - del_timer_sync(&priv->media_timer); + timer_delete_sync(&priv->media_timer); tlan_read_and_clear_stats(dev, TLAN_RECORD); outl(TLAN_HC_AD_RST, dev->base_addr + TLAN_HOST_CMD); /* Reset and power down phy */ tlan_reset_adapter(dev); if (priv->timer.function != NULL) { - del_timer_sync(&priv->timer); + timer_delete_sync(&priv->timer); priv->timer.function = NULL; } }
diff --git a/drivers/net/ethernet/tundra/tsi108_eth.c b/drivers/net/ethernet/tundra/tsi108_eth.c index c6957e3..7ec0e3c 100644 --- a/drivers/net/ethernet/tundra/tsi108_eth.c +++ b/drivers/net/ethernet/tundra/tsi108_eth.c
@@ -1379,7 +1379,7 @@ static int tsi108_close(struct net_device *dev) netif_stop_queue(dev); napi_disable(&data->napi); - del_timer_sync(&data->timer); + timer_delete_sync(&data->timer); tsi108_stop_ethernet(dev); tsi108_kill_phy(dev);
diff --git a/drivers/net/fddi/defza.c b/drivers/net/fddi/defza.c index f5c25ac..54b7f24 100644 --- a/drivers/net/fddi/defza.c +++ b/drivers/net/fddi/defza.c
@@ -983,7 +983,7 @@ static irqreturn_t fza_interrupt(int irq, void *dev_id) case FZA_STATE_UNINITIALIZED: netif_carrier_off(dev); - del_timer_sync(&fp->reset_timer); + timer_delete_sync(&fp->reset_timer); fp->ring_cmd_index = 0; fp->ring_uns_index = 0; fp->ring_rmc_tx_index = 0; @@ -1017,7 +1017,7 @@ static irqreturn_t fza_interrupt(int irq, void *dev_id) fp->queue_active = 0; netif_stop_queue(dev); pr_debug("%s: queue stopped\n", fp->name); - del_timer_sync(&fp->reset_timer); + timer_delete_sync(&fp->reset_timer); pr_warn("%s: halted, reason: %x\n", fp->name, FZA_STATUS_GET_HALT(status)); fza_regs_dump(fp); @@ -1227,7 +1227,7 @@ static int fza_close(struct net_device *dev) netif_stop_queue(dev); pr_debug("%s: queue stopped\n", fp->name); - del_timer_sync(&fp->reset_timer); + timer_delete_sync(&fp->reset_timer); spin_lock_irqsave(&fp->lock, flags); fp->state = FZA_STATE_UNINITIALIZED; fp->state_chg_flag = 0; @@ -1493,7 +1493,7 @@ static int fza_probe(struct device *bdev) return 0; err_out_irq: - del_timer_sync(&fp->reset_timer); + timer_delete_sync(&fp->reset_timer); fza_do_shutdown(fp); free_irq(dev->irq, dev); @@ -1520,7 +1520,7 @@ static int fza_remove(struct device *bdev) unregister_netdev(dev); - del_timer_sync(&fp->reset_timer); + timer_delete_sync(&fp->reset_timer); fza_do_shutdown(fp); free_irq(dev->irq, dev);
diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c index 3bf6785..b33d84e 100644 --- a/drivers/net/hamradio/6pack.c +++ b/drivers/net/hamradio/6pack.c
@@ -660,8 +660,8 @@ static void sixpack_close(struct tty_struct *tty) unregister_netdev(sp->dev); - del_timer_sync(&sp->tx_t); - del_timer_sync(&sp->resync_t); + timer_delete_sync(&sp->tx_t); + timer_delete_sync(&sp->resync_t); /* Free all 6pack frame buffers after unreg. */ kfree(sp->xbuff); @@ -937,7 +937,7 @@ sixpack_decode(struct sixpack *sp, const u8 *pre_rbuff, size_t count) inbyte = pre_rbuff[count1]; if (inbyte == SIXP_FOUND_TNC) { tnc_set_sync_state(sp, TNC_IN_SYNC); - del_timer(&sp->resync_t); + timer_delete(&sp->resync_t); } if ((inbyte & SIXP_PRIO_CMD_MASK) != 0) decode_prio_command(sp, inbyte);
diff --git a/drivers/net/hamradio/scc.c b/drivers/net/hamradio/scc.c index c71e522..f88721d 100644 --- a/drivers/net/hamradio/scc.c +++ b/drivers/net/hamradio/scc.c
@@ -794,8 +794,8 @@ static inline void init_brg(struct scc_channel *scc) static void init_channel(struct scc_channel *scc) { - del_timer(&scc->tx_t); - del_timer(&scc->tx_wdog); + timer_delete(&scc->tx_t); + timer_delete(&scc->tx_wdog); disable_irq(scc->irq); @@ -999,7 +999,7 @@ static void __scc_start_tx_timer(struct scc_channel *scc, void (*handler)(struct timer_list *t), unsigned long when) { - del_timer(&scc->tx_t); + timer_delete(&scc->tx_t); if (when == 0) { @@ -1029,7 +1029,7 @@ static void scc_start_defer(struct scc_channel *scc) unsigned long flags; spin_lock_irqsave(&scc->lock, flags); - del_timer(&scc->tx_wdog); + timer_delete(&scc->tx_wdog); if (scc->kiss.maxdefer != 0 && scc->kiss.maxdefer != TIMER_OFF) { @@ -1045,7 +1045,7 @@ static void scc_start_maxkeyup(struct scc_channel *scc) unsigned long flags; spin_lock_irqsave(&scc->lock, flags); - del_timer(&scc->tx_wdog); + timer_delete(&scc->tx_wdog); if (scc->kiss.maxkeyup != 0 && scc->kiss.maxkeyup != TIMER_OFF) { @@ -1194,7 +1194,7 @@ static void t_tail(struct timer_list *t) unsigned long flags; spin_lock_irqsave(&scc->lock, flags); - del_timer(&scc->tx_wdog); + timer_delete(&scc->tx_wdog); scc_key_trx(scc, TX_OFF); spin_unlock_irqrestore(&scc->lock, flags); @@ -1219,7 +1219,7 @@ static void t_busy(struct timer_list *t) { struct scc_channel *scc = from_timer(scc, t, tx_wdog); - del_timer(&scc->tx_t); + timer_delete(&scc->tx_t); netif_stop_queue(scc->dev); /* don't pile on the wabbit! */ scc_discard_buffers(scc); @@ -1248,7 +1248,7 @@ static void t_maxkeyup(struct timer_list *t) netif_stop_queue(scc->dev); scc_discard_buffers(scc); - del_timer(&scc->tx_t); + timer_delete(&scc->tx_t); cl(scc, R1, TxINT_ENAB); /* force an ABORT, but don't */ cl(scc, R15, TxUIE); /* count it. */ @@ -1272,7 +1272,7 @@ static void t_idle(struct timer_list *t) { struct scc_channel *scc = from_timer(scc, t, tx_t); - del_timer(&scc->tx_wdog); + timer_delete(&scc->tx_wdog); scc_key_trx(scc, TX_OFF); if(scc->kiss.mintime) @@ -1407,7 +1407,7 @@ static void scc_stop_calibrate(struct timer_list *t) unsigned long flags; spin_lock_irqsave(&scc->lock, flags); - del_timer(&scc->tx_wdog); + timer_delete(&scc->tx_wdog); scc_key_trx(scc, TX_OFF); wr(scc, R6, 0); wr(scc, R7, FLAG); @@ -1428,7 +1428,7 @@ scc_start_calibrate(struct scc_channel *scc, int duration, unsigned char pattern netif_stop_queue(scc->dev); scc_discard_buffers(scc); - del_timer(&scc->tx_wdog); + timer_delete(&scc->tx_wdog); scc->tx_wdog.function = scc_stop_calibrate; scc->tx_wdog.expires = jiffies + HZ*duration; @@ -1609,8 +1609,8 @@ static int scc_net_close(struct net_device *dev) wr(scc,R3,0); spin_unlock_irqrestore(&scc->lock, flags); - del_timer_sync(&scc->tx_t); - del_timer_sync(&scc->tx_wdog); + timer_delete_sync(&scc->tx_t); + timer_delete_sync(&scc->tx_wdog); scc_discard_buffers(scc);
diff --git a/drivers/net/hamradio/yam.c b/drivers/net/hamradio/yam.c index 2ed2f83..f29997b 100644 --- a/drivers/net/hamradio/yam.c +++ b/drivers/net/hamradio/yam.c
@@ -1158,7 +1158,7 @@ static void __exit yam_cleanup_driver(void) struct yam_mcs *p; int i; - del_timer_sync(&yam_timer); + timer_delete_sync(&yam_timer); for (i = 0; i < NR_PORTS; i++) { struct net_device *dev = yam_devs[i]; if (dev) {
diff --git a/drivers/net/hippi/rrunner.c b/drivers/net/hippi/rrunner.c index aa8f828..6342c319 100644 --- a/drivers/net/hippi/rrunner.c +++ b/drivers/net/hippi/rrunner.c
@@ -1357,7 +1357,7 @@ static int rr_close(struct net_device *dev) rrpriv->fw_running = 0; spin_unlock_irqrestore(&rrpriv->lock, flags); - del_timer_sync(&rrpriv->timer); + timer_delete_sync(&rrpriv->timer); spin_lock_irqsave(&rrpriv->lock, flags); writel(0, ®s->TxPi);
diff --git a/drivers/net/netdevsim/netdev.c b/drivers/net/netdevsim/netdev.c index b67af46..0e0321a 100644 --- a/drivers/net/netdevsim/netdev.c +++ b/drivers/net/netdevsim/netdev.c
@@ -441,8 +441,8 @@ static enum hrtimer_restart nsim_napi_schedule(struct hrtimer *timer) static void nsim_rq_timer_init(struct nsim_rq *rq) { - hrtimer_init(&rq->napi_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); - rq->napi_timer.function = nsim_napi_schedule; + hrtimer_setup(&rq->napi_timer, nsim_napi_schedule, CLOCK_MONOTONIC, + HRTIMER_MODE_REL); } static void nsim_enable_napi(struct netdevsim *ns) @@ -939,6 +939,7 @@ static int nsim_init_netdevsim(struct netdevsim *ns) ns->netdev->netdev_ops = &nsim_netdev_ops; ns->netdev->stat_ops = &nsim_stat_ops; ns->netdev->queue_mgmt_ops = &nsim_queue_mgmt_ops; + netdev_lockdep_set_classes(ns->netdev); err = nsim_udp_tunnels_info_create(ns->nsim_dev, ns->netdev); if (err) @@ -960,6 +961,14 @@ static int nsim_init_netdevsim(struct netdevsim *ns) if (err) goto err_ipsec_teardown; rtnl_unlock(); + + if (IS_ENABLED(CONFIG_DEBUG_NET)) { + ns->nb.notifier_call = netdev_debug_event; + if (register_netdevice_notifier_dev_net(ns->netdev, &ns->nb, + &ns->nn)) + ns->nb.notifier_call = NULL; + } + return 0; err_ipsec_teardown: @@ -1043,6 +1052,10 @@ void nsim_destroy(struct netdevsim *ns) debugfs_remove(ns->qr_dfs); debugfs_remove(ns->pp_dfs); + if (ns->nb.notifier_call) + unregister_netdevice_notifier_dev_net(ns->netdev, &ns->nb, + &ns->nn); + rtnl_lock(); peer = rtnl_dereference(ns->peer); if (peer)
diff --git a/drivers/net/netdevsim/netdevsim.h b/drivers/net/netdevsim/netdevsim.h index 665020d..d04401f 100644 --- a/drivers/net/netdevsim/netdevsim.h +++ b/drivers/net/netdevsim/netdevsim.h
@@ -144,6 +144,9 @@ struct netdevsim { struct nsim_ethtool ethtool; struct netdevsim __rcu *peer; + + struct notifier_block nb; + struct netdev_net_notifier nn; }; struct netdevsim *
diff --git a/drivers/net/ntb_netdev.c b/drivers/net/ntb_netdev.c index ef6df0e..ef42046 100644 --- a/drivers/net/ntb_netdev.c +++ b/drivers/net/ntb_netdev.c
@@ -291,7 +291,7 @@ static int ntb_netdev_close(struct net_device *ndev) while ((skb = ntb_transport_rx_remove(dev->qp, &len))) dev_kfree_skb(skb); - del_timer_sync(&dev->tx_timer); + timer_delete_sync(&dev->tx_timer); return 0; }
diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c index 13e43fe..9b1de54f 100644 --- a/drivers/net/phy/broadcom.c +++ b/drivers/net/phy/broadcom.c
@@ -859,7 +859,7 @@ static int brcm_fet_config_init(struct phy_device *phydev) return reg; /* Unmask events we are interested in and mask interrupts globally. */ - if (phydev->phy_id == PHY_ID_BCM5221) + if (phydev->drv->phy_id == PHY_ID_BCM5221) reg = MII_BRCM_FET_IR_ENABLE | MII_BRCM_FET_IR_MASK; else @@ -888,7 +888,7 @@ static int brcm_fet_config_init(struct phy_device *phydev) return err; } - if (phydev->phy_id != PHY_ID_BCM5221) { + if (phydev->drv->phy_id != PHY_ID_BCM5221) { /* Set the LED mode */ reg = __phy_read(phydev, MII_BRCM_FET_SHDW_AUXMODE4); if (reg < 0) { @@ -1009,7 +1009,7 @@ static int brcm_fet_suspend(struct phy_device *phydev) return err; } - if (phydev->phy_id == PHY_ID_BCM5221) + if (phydev->drv->phy_id == PHY_ID_BCM5221) /* Force Low Power Mode with clock enabled */ reg = BCM5221_SHDW_AM4_EN_CLK_LPM | BCM5221_SHDW_AM4_FORCE_LPM; else
diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c index 69ca765..b68369e 100644 --- a/drivers/net/phy/phylink.c +++ b/drivers/net/phy/phylink.c
@@ -952,7 +952,7 @@ static unsigned int phylink_inband_caps(struct phylink *pl, static void phylink_pcs_poll_stop(struct phylink *pl) { if (pl->cfg_link_an_mode == MLO_AN_INBAND) - del_timer(&pl->link_poll); + timer_delete(&pl->link_poll); } static void phylink_pcs_poll_start(struct phylink *pl) @@ -2448,7 +2448,7 @@ void phylink_stop(struct phylink *pl) sfp_upstream_stop(pl->sfp_bus); if (pl->phydev) phy_stop(pl->phydev); - del_timer_sync(&pl->link_poll); + timer_delete_sync(&pl->link_poll); if (pl->link_irq) { free_irq(pl->link_irq, pl); pl->link_irq = 0;
diff --git a/drivers/net/slip/slip.c b/drivers/net/slip/slip.c index fb362ee..3cfa17c 100644 --- a/drivers/net/slip/slip.c +++ b/drivers/net/slip/slip.c
@@ -899,8 +899,8 @@ static void slip_close(struct tty_struct *tty) /* VSV = very important to remove timers */ #ifdef CONFIG_SLIP_SMART - del_timer_sync(&sl->keepalive_timer); - del_timer_sync(&sl->outfill_timer); + timer_delete_sync(&sl->keepalive_timer); + timer_delete_sync(&sl->outfill_timer); #endif /* Flush network side */ unregister_netdev(sl->dev); @@ -1137,7 +1137,7 @@ static int slip_ioctl(struct tty_struct *tty, unsigned int cmd, jiffies + sl->keepalive * HZ); set_bit(SLF_KEEPTEST, &sl->flags); } else - del_timer(&sl->keepalive_timer); + timer_delete(&sl->keepalive_timer); spin_unlock_bh(&sl->lock); return 0; @@ -1162,7 +1162,7 @@ static int slip_ioctl(struct tty_struct *tty, unsigned int cmd, jiffies + sl->outfill * HZ); set_bit(SLF_OUTWAIT, &sl->flags); } else - del_timer(&sl->outfill_timer); + timer_delete(&sl->outfill_timer); spin_unlock_bh(&sl->lock); return 0; @@ -1217,7 +1217,7 @@ static int sl_siocdevprivate(struct net_device *dev, struct ifreq *rq, jiffies + sl->keepalive * HZ); set_bit(SLF_KEEPTEST, &sl->flags); } else - del_timer(&sl->keepalive_timer); + timer_delete(&sl->keepalive_timer); break; case SIOCGKEEPALIVE: @@ -1235,7 +1235,7 @@ static int sl_siocdevprivate(struct net_device *dev, struct ifreq *rq, jiffies + sl->outfill * HZ); set_bit(SLF_OUTWAIT, &sl->flags); } else - del_timer(&sl->outfill_timer); + timer_delete(&sl->outfill_timer); break; case SIOCGOUTFILL: @@ -1421,7 +1421,7 @@ static void sl_keepalive(struct timer_list *t) /* keepalive still high :(, we must hangup */ if (sl->outfill) /* outfill timer must be deleted too */ - (void)del_timer(&sl->outfill_timer); + (void) timer_delete(&sl->outfill_timer); printk(KERN_DEBUG "%s: no packets received during keepalive timeout, hangup.\n", sl->dev->name); /* this must hangup tty & close slip */ tty_hangup(sl->tty);
diff --git a/drivers/net/tun.c b/drivers/net/tun.c index f75f912..7babd1e 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c
@@ -1295,7 +1295,7 @@ static void tun_flow_init(struct tun_struct *tun) static void tun_flow_uninit(struct tun_struct *tun) { - del_timer_sync(&tun->flow_gc_timer); + timer_delete_sync(&tun->flow_gc_timer); tun_flow_flush(tun); }
diff --git a/drivers/net/usb/catc.c b/drivers/net/usb/catc.c index ff439ef..fc5e441 100644 --- a/drivers/net/usb/catc.c +++ b/drivers/net/usb/catc.c
@@ -738,7 +738,7 @@ static int catc_stop(struct net_device *netdev) netif_stop_queue(netdev); if (!catc->is_f5u011) - del_timer_sync(&catc->timer); + timer_delete_sync(&catc->timer); usb_kill_urb(catc->rx_urb); usb_kill_urb(catc->tx_urb);
diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c index 137adf6..e4f1663 100644 --- a/drivers/net/usb/lan78xx.c +++ b/drivers/net/usb/lan78xx.c
@@ -1661,7 +1661,7 @@ static int lan78xx_link_reset(struct lan78xx_net *dev) if (ret < 0) return ret; - del_timer(&dev->stat_monitor); + timer_delete(&dev->stat_monitor); } else if (link && !dev->link_on) { dev->link_on = true; @@ -3304,7 +3304,7 @@ static int lan78xx_stop(struct net_device *net) mutex_lock(&dev->dev_mutex); if (timer_pending(&dev->stat_monitor)) - del_timer_sync(&dev->stat_monitor); + timer_delete_sync(&dev->stat_monitor); clear_bit(EVENT_DEV_OPEN, &dev->flags); netif_stop_queue(net); @@ -4938,7 +4938,7 @@ static int lan78xx_suspend(struct usb_interface *intf, pm_message_t message) /* reattach */ netif_device_attach(dev->net); - del_timer(&dev->stat_monitor); + timer_delete(&dev->stat_monitor); if (PMSG_IS_AUTO(message)) { ret = lan78xx_set_auto_suspend(dev);
diff --git a/drivers/net/usb/rndis_host.c b/drivers/net/usb/rndis_host.c index 7b3739b..bb0bf14 100644 --- a/drivers/net/usb/rndis_host.c +++ b/drivers/net/usb/rndis_host.c
@@ -630,6 +630,16 @@ static const struct driver_info zte_rndis_info = { .tx_fixup = rndis_tx_fixup, }; +static const struct driver_info wwan_rndis_info = { + .description = "Mobile Broadband RNDIS device", + .flags = FLAG_WWAN | FLAG_POINTTOPOINT | FLAG_FRAMING_RN | FLAG_NO_SETINT, + .bind = rndis_bind, + .unbind = rndis_unbind, + .status = rndis_status, + .rx_fixup = rndis_rx_fixup, + .tx_fixup = rndis_tx_fixup, +}; + /*-------------------------------------------------------------------------*/ static const struct usb_device_id products [] = { @@ -666,9 +676,11 @@ static const struct usb_device_id products [] = { USB_INTERFACE_INFO(USB_CLASS_WIRELESS_CONTROLLER, 1, 3), .driver_info = (unsigned long) &rndis_info, }, { - /* Novatel Verizon USB730L */ + /* Mobile Broadband Modem, seen in Novatel Verizon USB730L and + * Telit FN990A (RNDIS) + */ USB_INTERFACE_INFO(USB_CLASS_MISC, 4, 1), - .driver_info = (unsigned long) &rndis_info, + .driver_info = (unsigned long)&wwan_rndis_info, }, { }, // END };
diff --git a/drivers/net/usb/sierra_net.c b/drivers/net/usb/sierra_net.c index 3d239b8..dec6e82 100644 --- a/drivers/net/usb/sierra_net.c +++ b/drivers/net/usb/sierra_net.c
@@ -522,7 +522,7 @@ static void sierra_net_kevent(struct work_struct *work) " stopping sync timer", hh.msgspecific.byte); /* Got sync resp - stop timer & clear mask */ - del_timer_sync(&priv->sync_timer); + timer_delete_sync(&priv->sync_timer); clear_bit(SIERRA_NET_TIMER_EXPIRY, &priv->kevent_flags); break;
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index 44179f4..c39dfa1 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c
@@ -178,6 +178,17 @@ int usbnet_get_ethernet_addr(struct usbnet *dev, int iMACAddress) } EXPORT_SYMBOL_GPL(usbnet_get_ethernet_addr); +static bool usbnet_needs_usb_name_format(struct usbnet *dev, struct net_device *net) +{ + /* Point to point devices which don't have a real MAC address + * (or report a fake local one) have historically used the usb%d + * naming. Preserve this.. + */ + return (dev->driver_info->flags & FLAG_POINTTOPOINT) != 0 && + (is_zero_ether_addr(net->dev_addr) || + is_local_ether_addr(net->dev_addr)); +} + static void intr_complete (struct urb *urb) { struct usbnet *dev = urb->context; @@ -519,7 +530,8 @@ static int rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags) netif_device_present (dev->net) && test_bit(EVENT_DEV_OPEN, &dev->flags) && !test_bit (EVENT_RX_HALT, &dev->flags) && - !test_bit (EVENT_DEV_ASLEEP, &dev->flags)) { + !test_bit (EVENT_DEV_ASLEEP, &dev->flags) && + !usbnet_going_away(dev)) { switch (retval = usb_submit_urb (urb, GFP_ATOMIC)) { case -EPIPE: usbnet_defer_kevent (dev, EVENT_RX_HALT); @@ -540,8 +552,7 @@ static int rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags) tasklet_schedule (&dev->bh); break; case 0: - if (!usbnet_going_away(dev)) - __usbnet_queue_skb(&dev->rxq, skb, rx_start); + __usbnet_queue_skb(&dev->rxq, skb, rx_start); } } else { netif_dbg(dev, ifdown, dev->net, "rx: stopped\n"); @@ -849,7 +860,7 @@ int usbnet_stop (struct net_device *net) /* deferred work (timer, softirq, task) must also stop */ dev->flags = 0; - del_timer_sync(&dev->delay); + timer_delete_sync(&dev->delay); tasklet_kill(&dev->bh); cancel_work_sync(&dev->kevent); @@ -858,7 +869,7 @@ int usbnet_stop (struct net_device *net) * we have a flag */ tasklet_kill(&dev->bh); - del_timer_sync(&dev->delay); + timer_delete_sync(&dev->delay); cancel_work_sync(&dev->kevent); if (!pm) @@ -1762,13 +1773,11 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod) if (status < 0) goto out1; - // heuristic: "usb%d" for links we know are two-host, - // else "eth%d" when there's reasonable doubt. userspace - // can rename the link if it knows better. + /* heuristic: rename to "eth%d" if we are not sure this link + * is two-host (these links keep "usb%d") + */ if ((dev->driver_info->flags & FLAG_ETHER) != 0 && - ((dev->driver_info->flags & FLAG_POINTTOPOINT) == 0 || - /* somebody touched it*/ - !is_zero_ether_addr(net->dev_addr))) + !usbnet_needs_usb_name_format(dev, net)) strscpy(net->name, "eth%d", sizeof(net->name)); /* WLAN devices should always be named "wlan%d" */ if ((dev->driver_info->flags & FLAG_WLAN) != 0) @@ -1873,7 +1882,7 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod) */ usbnet_mark_going_away(dev); cancel_work_sync(&dev->kevent); - del_timer_sync(&dev->delay); + timer_delete_sync(&dev->delay); free_netdev(net); out: return status;
diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c index 8c49e90..9ccc3f0 100644 --- a/drivers/net/vxlan/vxlan_core.c +++ b/drivers/net/vxlan/vxlan_core.c
@@ -3193,7 +3193,7 @@ static int vxlan_stop(struct net_device *dev) vxlan_multicast_leave(vxlan); - del_timer_sync(&vxlan->age_timer); + timer_delete_sync(&vxlan->age_timer); vxlan_flush(vxlan, &desc); vxlan_sock_release(vxlan);
diff --git a/drivers/net/wan/hdlc_cisco.c b/drivers/net/wan/hdlc_cisco.c index cdebe65..7e65343 100644 --- a/drivers/net/wan/hdlc_cisco.c +++ b/drivers/net/wan/hdlc_cisco.c
@@ -285,7 +285,7 @@ static void cisco_stop(struct net_device *dev) struct cisco_state *st = state(hdlc); unsigned long flags; - del_timer_sync(&st->timer); + timer_delete_sync(&st->timer); spin_lock_irqsave(&st->lock, flags); netif_dormant_on(dev);
diff --git a/drivers/net/wan/hdlc_fr.c b/drivers/net/wan/hdlc_fr.c index 81e72bc..34014f4 100644 --- a/drivers/net/wan/hdlc_fr.c +++ b/drivers/net/wan/hdlc_fr.c
@@ -1025,7 +1025,7 @@ static void fr_stop(struct net_device *dev) printk(KERN_DEBUG "fr_stop\n"); #endif if (state(hdlc)->settings.lmi != LMI_NONE) - del_timer_sync(&state(hdlc)->timer); + timer_delete_sync(&state(hdlc)->timer); fr_set_link_state(0, dev); }
diff --git a/drivers/net/wan/hdlc_ppp.c b/drivers/net/wan/hdlc_ppp.c index 37a3c98..19921b0 100644 --- a/drivers/net/wan/hdlc_ppp.c +++ b/drivers/net/wan/hdlc_ppp.c
@@ -358,7 +358,7 @@ static void ppp_cp_event(struct net_device *dev, u16 pid, u16 event, u8 code, } } if (old_state != CLOSED && proto->state == CLOSED) - del_timer(&proto->timer); + timer_delete(&proto->timer); #if DEBUG_STATE printk(KERN_DEBUG "%s: %s ppp_cp_event(%s) ... %s\n", dev->name,
diff --git a/drivers/net/wan/lapbether.c b/drivers/net/wan/lapbether.c index 56326f3..995a720 100644 --- a/drivers/net/wan/lapbether.c +++ b/drivers/net/wan/lapbether.c
@@ -39,6 +39,7 @@ #include <linux/lapb.h> #include <linux/init.h> +#include <net/netdev_lock.h> #include <net/x25device.h> static const u8 bcast_addr[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; @@ -366,6 +367,7 @@ static const struct net_device_ops lapbeth_netdev_ops = { static void lapbeth_setup(struct net_device *dev) { + netdev_lockdep_set_classes(dev); dev->netdev_ops = &lapbeth_netdev_ops; dev->needs_free_netdev = true; dev->type = ARPHRD_X25;
diff --git a/drivers/net/wireguard/device.c b/drivers/net/wireguard/device.c index c496d35..3ffeeba 100644 --- a/drivers/net/wireguard/device.c +++ b/drivers/net/wireguard/device.c
@@ -81,7 +81,7 @@ static int wg_pm_notification(struct notifier_block *nb, unsigned long action, v list_for_each_entry(wg, &device_list, device_list) { mutex_lock(&wg->device_update_lock); list_for_each_entry(peer, &wg->peer_list, peer_list) { - del_timer(&peer->timer_zero_key_material); + timer_delete(&peer->timer_zero_key_material); wg_noise_handshake_clear(&peer->handshake); wg_noise_keypairs_clear(&peer->keypairs); }
diff --git a/drivers/net/wireguard/timers.c b/drivers/net/wireguard/timers.c index 968bdb4..a9e0890 100644 --- a/drivers/net/wireguard/timers.c +++ b/drivers/net/wireguard/timers.c
@@ -48,7 +48,7 @@ static void wg_expired_retransmit_handshake(struct timer_list *timer) peer->device->dev->name, peer->internal_id, &peer->endpoint.addr, (int)MAX_TIMER_HANDSHAKES + 2); - del_timer(&peer->timer_send_keepalive); + timer_delete(&peer->timer_send_keepalive); /* We drop all packets without a keypair and don't try again, * if we try unsuccessfully for too long to make a handshake. */ @@ -167,7 +167,7 @@ void wg_timers_data_received(struct wg_peer *peer) */ void wg_timers_any_authenticated_packet_sent(struct wg_peer *peer) { - del_timer(&peer->timer_send_keepalive); + timer_delete(&peer->timer_send_keepalive); } /* Should be called after any type of authenticated packet is received, whether @@ -175,7 +175,7 @@ void wg_timers_any_authenticated_packet_sent(struct wg_peer *peer) */ void wg_timers_any_authenticated_packet_received(struct wg_peer *peer) { - del_timer(&peer->timer_new_handshake); + timer_delete(&peer->timer_new_handshake); } /* Should be called after a handshake initiation message is sent. */ @@ -191,7 +191,7 @@ void wg_timers_handshake_initiated(struct wg_peer *peer) */ void wg_timers_handshake_complete(struct wg_peer *peer) { - del_timer(&peer->timer_retransmit_handshake); + timer_delete(&peer->timer_retransmit_handshake); peer->timer_handshake_attempts = 0; peer->sent_lastminute_handshake = false; ktime_get_real_ts64(&peer->walltime_last_handshake);
diff --git a/drivers/net/wireless/ath/ar5523/ar5523.c b/drivers/net/wireless/ath/ar5523/ar5523.c index 156f365..96dc277 100644 --- a/drivers/net/wireless/ath/ar5523/ar5523.c +++ b/drivers/net/wireless/ath/ar5523/ar5523.c
@@ -733,7 +733,7 @@ static void ar5523_data_tx_pkt_put(struct ar5523 *ar) { atomic_dec(&ar->tx_nr_total); if (!atomic_dec_return(&ar->tx_nr_pending)) { - del_timer(&ar->tx_wd_timer); + timer_delete(&ar->tx_wd_timer); wake_up(&ar->tx_flush_waitq); } @@ -1076,7 +1076,7 @@ static void ar5523_stop(struct ieee80211_hw *hw, bool suspend) ar5523_cmd_write(ar, WDCMSG_TARGET_STOP, NULL, 0, 0); - del_timer_sync(&ar->tx_wd_timer); + timer_delete_sync(&ar->tx_wd_timer); cancel_work_sync(&ar->tx_wd_work); cancel_work_sync(&ar->rx_refill_work); ar5523_cancel_rx_bufs(ar);
diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c index 35bfe72..a0c1afe 100644 --- a/drivers/net/wireless/ath/ath10k/debug.c +++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -1751,7 +1751,7 @@ void ath10k_debug_stop(struct ath10k *ar) /* Must not use _sync to avoid deadlock, we do that in * ath10k_debug_destroy(). The check for htt_stats_mask is to avoid - * warning from del_timer(). + * warning from timer_delete(). */ if (ar->debug.htt_stats_mask != 0) cancel_delayed_work(&ar->debug.htt_stats_dwork);
diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c index 7d28ae5..83eab74 100644 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
@@ -287,7 +287,7 @@ void ath10k_htt_rx_free(struct ath10k_htt *htt) if (htt->ar->bus_param.dev_type == ATH10K_DEV_TYPE_HL) return; - del_timer_sync(&htt->rx_ring.refill_retry_timer); + timer_delete_sync(&htt->rx_ring.refill_retry_timer); skb_queue_purge(&htt->rx_msdus_q); skb_queue_purge(&htt->rx_in_ord_compl_q);
diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index c52a16f..fb2c60e 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c
@@ -619,7 +619,7 @@ static void ath10k_pci_sleep_sync(struct ath10k *ar) return; } - del_timer_sync(&ar_pci->ps_timer); + timer_delete_sync(&ar_pci->ps_timer); spin_lock_irqsave(&ar_pci->ps_lock, flags); WARN_ON(ar_pci->ps_wake_refcount > 0); @@ -1817,7 +1817,7 @@ static void ath10k_pci_rx_retry_sync(struct ath10k *ar) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); - del_timer_sync(&ar_pci->rx_post_retry); + timer_delete_sync(&ar_pci->rx_post_retry); } int ath10k_pci_hif_map_service_to_pipe(struct ath10k *ar, u16 service_id,
diff --git a/drivers/net/wireless/ath/ath10k/sdio.c b/drivers/net/wireless/ath/ath10k/sdio.c index 6805357..7ce74b4 100644 --- a/drivers/net/wireless/ath/ath10k/sdio.c +++ b/drivers/net/wireless/ath/ath10k/sdio.c
@@ -1621,7 +1621,7 @@ static void ath10k_sdio_hif_power_down(struct ath10k *ar) ath10k_dbg(ar, ATH10K_DBG_BOOT, "sdio power off\n"); - del_timer_sync(&ar_sdio->sleep_timer); + timer_delete_sync(&ar_sdio->sleep_timer); ath10k_sdio_set_mbox_sleep(ar, true); /* Disable the card */
diff --git a/drivers/net/wireless/ath/ath10k/snoc.c b/drivers/net/wireless/ath/ath10k/snoc.c index d436a87..866bad2 100644 --- a/drivers/net/wireless/ath/ath10k/snoc.c +++ b/drivers/net/wireless/ath/ath10k/snoc.c
@@ -911,7 +911,7 @@ static void ath10k_snoc_buffer_cleanup(struct ath10k *ar) struct ath10k_snoc_pipe *pipe_info; int pipe_num; - del_timer_sync(&ar_snoc->rx_post_retry); + timer_delete_sync(&ar_snoc->rx_post_retry); for (pipe_num = 0; pipe_num < CE_COUNT; pipe_num++) { pipe_info = &ar_snoc->pipe_info[pipe_num]; ath10k_snoc_rx_pipe_cleanup(pipe_info);
diff --git a/drivers/net/wireless/ath/ath11k/ahb.c b/drivers/net/wireless/ath/ath11k/ahb.c index eedba37..2f862f8 100644 --- a/drivers/net/wireless/ath/ath11k/ahb.c +++ b/drivers/net/wireless/ath/ath11k/ahb.c
@@ -397,7 +397,7 @@ static void ath11k_ahb_stop(struct ath11k_base *ab) ath11k_ahb_ce_irqs_disable(ab); ath11k_ahb_sync_ce_irqs(ab); ath11k_ahb_kill_tasklets(ab); - del_timer_sync(&ab->rx_replenish_retry); + timer_delete_sync(&ab->rx_replenish_retry); ath11k_ce_cleanup_pipes(ab); }
diff --git a/drivers/net/wireless/ath/ath11k/dp.c b/drivers/net/wireless/ath/ath11k/dp.c index f124b73..3a544e5 100644 --- a/drivers/net/wireless/ath/ath11k/dp.c +++ b/drivers/net/wireless/ath/ath11k/dp.c
@@ -875,7 +875,7 @@ void ath11k_dp_pdev_free(struct ath11k_base *ab) struct ath11k *ar; int i; - del_timer_sync(&ab->mon_reap_timer); + timer_delete_sync(&ab->mon_reap_timer); for (i = 0; i < ab->num_radios; i++) { ar = ab->pdevs[i].ar; @@ -1170,7 +1170,7 @@ void ath11k_dp_shadow_stop_timer(struct ath11k_base *ab, if (!update_timer->init) return; - del_timer_sync(&update_timer->timer); + timer_delete_sync(&update_timer->timer); } void ath11k_dp_shadow_init_timer(struct ath11k_base *ab,
diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c b/drivers/net/wireless/ath/ath11k/dp_rx.c index f2bdbac..218ab41 100644 --- a/drivers/net/wireless/ath/ath11k/dp_rx.c +++ b/drivers/net/wireless/ath/ath11k/dp_rx.c
@@ -906,7 +906,7 @@ void ath11k_peer_frags_flush(struct ath11k *ar, struct ath11k_peer *peer) rx_tid = &peer->rx_tid[i]; spin_unlock_bh(&ar->ab->base_lock); - del_timer_sync(&rx_tid->frag_timer); + timer_delete_sync(&rx_tid->frag_timer); spin_lock_bh(&ar->ab->base_lock); ath11k_dp_rx_frags_cleanup(rx_tid, true); @@ -927,7 +927,7 @@ void ath11k_peer_rx_tid_cleanup(struct ath11k *ar, struct ath11k_peer *peer) ath11k_dp_rx_frags_cleanup(rx_tid, true); spin_unlock_bh(&ar->ab->base_lock); - del_timer_sync(&rx_tid->frag_timer); + timer_delete_sync(&rx_tid->frag_timer); spin_lock_bh(&ar->ab->base_lock); } } @@ -3710,7 +3710,7 @@ static int ath11k_dp_rx_frag_h_mpdu(struct ath11k *ar, } spin_unlock_bh(&ab->base_lock); - del_timer_sync(&rx_tid->frag_timer); + timer_delete_sync(&rx_tid->frag_timer); spin_lock_bh(&ab->base_lock); peer = ath11k_peer_find_by_id(ab, peer_id); @@ -5781,7 +5781,7 @@ int ath11k_dp_rx_pktlog_stop(struct ath11k_base *ab, bool stop_timer) int ret; if (stop_timer) - del_timer_sync(&ab->mon_reap_timer); + timer_delete_sync(&ab->mon_reap_timer); /* reap all the monitor related rings */ ret = ath11k_dp_purge_mon_ring(ab);
diff --git a/drivers/net/wireless/ath/ath12k/dp.c b/drivers/net/wireless/ath/ath12k/dp.c index b1f27c3..50c36e6 100644 --- a/drivers/net/wireless/ath/ath12k/dp.c +++ b/drivers/net/wireless/ath/ath12k/dp.c
@@ -985,7 +985,7 @@ void ath12k_dp_pdev_free(struct ath12k_base *ab) if (!ab->mon_reap_timer.function) return; - del_timer_sync(&ab->mon_reap_timer); + timer_delete_sync(&ab->mon_reap_timer); for (i = 0; i < ab->num_radios; i++) ath12k_dp_rx_pdev_free(ab, i);
diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.c b/drivers/net/wireless/ath/ath12k/dp_rx.c index ff6a709..75bf421 100644 --- a/drivers/net/wireless/ath/ath12k/dp_rx.c +++ b/drivers/net/wireless/ath/ath12k/dp_rx.c
@@ -895,7 +895,7 @@ void ath12k_dp_rx_peer_tid_cleanup(struct ath12k *ar, struct ath12k_peer *peer) ath12k_dp_rx_frags_cleanup(rx_tid, true); spin_unlock_bh(&ar->ab->base_lock); - del_timer_sync(&rx_tid->frag_timer); + timer_delete_sync(&rx_tid->frag_timer); spin_lock_bh(&ar->ab->base_lock); } } @@ -3451,7 +3451,7 @@ static int ath12k_dp_rx_frag_h_mpdu(struct ath12k *ar, } spin_unlock_bh(&ab->base_lock); - del_timer_sync(&rx_tid->frag_timer); + timer_delete_sync(&rx_tid->frag_timer); spin_lock_bh(&ab->base_lock); peer = ath12k_peer_find_by_id(ab, peer_id);
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index 72ce321..8c2e808 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c
@@ -149,7 +149,7 @@ static bool __ath6kl_cfg80211_sscan_stop(struct ath6kl_vif *vif) if (!test_and_clear_bit(SCHED_SCANNING, &vif->flags)) return false; - del_timer_sync(&vif->sched_scan_timer); + timer_delete_sync(&vif->sched_scan_timer); if (ar->state == ATH6KL_STATE_RECOVERY) return true; @@ -1200,7 +1200,7 @@ static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, if (((vif->auth_mode == WPA_PSK_AUTH) || (vif->auth_mode == WPA2_PSK_AUTH)) && (key_usage & GROUP_USAGE)) - del_timer(&vif->disconnect_timer); + timer_delete(&vif->disconnect_timer); ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: index %d, key_len %d, key_type 0x%x, key_usage 0x%x, seq_len %d\n", @@ -3612,7 +3612,7 @@ void ath6kl_cfg80211_vif_stop(struct ath6kl_vif *vif, bool wmi_ready) discon_issued = test_bit(CONNECTED, &vif->flags) || test_bit(CONNECT_PEND, &vif->flags); ath6kl_disconnect(vif); - del_timer(&vif->disconnect_timer); + timer_delete(&vif->disconnect_timer); if (discon_issued) ath6kl_disconnect_event(vif, DISCONNECT_CMD,
diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c index 15f455a..9b100ee 100644 --- a/drivers/net/wireless/ath/ath6kl/init.c +++ b/drivers/net/wireless/ath/ath6kl/init.c
@@ -1915,7 +1915,7 @@ void ath6kl_stop_txrx(struct ath6kl *ar) clear_bit(WMI_READY, &ar->flag); if (ar->fw_recovery.enable) - del_timer_sync(&ar->fw_recovery.hb_timer); + timer_delete_sync(&ar->fw_recovery.hb_timer); /* * After wmi_shudown all WMI events will be dropped. We
diff --git a/drivers/net/wireless/ath/ath6kl/main.c b/drivers/net/wireless/ath/ath6kl/main.c index 8f9fe23..867089a 100644 --- a/drivers/net/wireless/ath/ath6kl/main.c +++ b/drivers/net/wireless/ath/ath6kl/main.c
@@ -1027,7 +1027,7 @@ void ath6kl_disconnect_event(struct ath6kl_vif *vif, u8 reason, u8 *bssid, aggr_reset_state(vif->aggr_cntxt->aggr_conn); - del_timer(&vif->disconnect_timer); + timer_delete(&vif->disconnect_timer); ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "disconnect reason is %d\n", reason);
diff --git a/drivers/net/wireless/ath/ath6kl/recovery.c b/drivers/net/wireless/ath/ath6kl/recovery.c index c09e40c..fd2dceb 100644 --- a/drivers/net/wireless/ath/ath6kl/recovery.c +++ b/drivers/net/wireless/ath/ath6kl/recovery.c
@@ -25,7 +25,7 @@ static void ath6kl_recovery_work(struct work_struct *work) ar->state = ATH6KL_STATE_RECOVERY; - del_timer_sync(&ar->fw_recovery.hb_timer); + timer_delete_sync(&ar->fw_recovery.hb_timer); ath6kl_init_hw_restart(ar); @@ -119,7 +119,7 @@ void ath6kl_recovery_cleanup(struct ath6kl *ar) set_bit(RECOVERY_CLEANUP, &ar->flag); - del_timer_sync(&ar->fw_recovery.hb_timer); + timer_delete_sync(&ar->fw_recovery.hb_timer); cancel_work_sync(&ar->fw_recovery.recovery_work); }
diff --git a/drivers/net/wireless/ath/ath6kl/txrx.c b/drivers/net/wireless/ath/ath6kl/txrx.c index 80e66ac..3a6f0b6 100644 --- a/drivers/net/wireless/ath/ath6kl/txrx.c +++ b/drivers/net/wireless/ath/ath6kl/txrx.c
@@ -1827,7 +1827,7 @@ void aggr_reset_state(struct aggr_info_conn *aggr_conn) return; if (aggr_conn->timer_scheduled) { - del_timer(&aggr_conn->timer); + timer_delete(&aggr_conn->timer); aggr_conn->timer_scheduled = false; }
diff --git a/drivers/net/wireless/ath/ath9k/channel.c b/drivers/net/wireless/ath/ath9k/channel.c index bae24e3..799be0b 100644 --- a/drivers/net/wireless/ath/ath9k/channel.c +++ b/drivers/net/wireless/ath/ath9k/channel.c
@@ -1556,7 +1556,7 @@ void ath9k_p2p_ps_timer(void *priv) struct ath_node *an; u32 tsf; - del_timer_sync(&sc->sched.timer); + timer_delete_sync(&sc->sched.timer); ath9k_hw_gen_timer_stop(sc->sc_ah, sc->p2p_ps_timer); ath_chanctx_event(sc, NULL, ATH_CHANCTX_EVENT_TSF_TIMER);
diff --git a/drivers/net/wireless/ath/ath9k/gpio.c b/drivers/net/wireless/ath/ath9k/gpio.c index b457e52..5a26f1d 100644 --- a/drivers/net/wireless/ath/ath9k/gpio.c +++ b/drivers/net/wireless/ath/ath9k/gpio.c
@@ -305,7 +305,7 @@ void ath9k_btcoex_timer_resume(struct ath_softc *sc) ath_dbg(ath9k_hw_common(ah), BTCOEX, "Starting btcoex timers\n"); /* make sure duty cycle timer is also stopped when resuming */ - del_timer_sync(&btcoex->no_stomp_timer); + timer_delete_sync(&btcoex->no_stomp_timer); btcoex->bt_priority_cnt = 0; btcoex->bt_priority_time = jiffies; @@ -329,15 +329,15 @@ void ath9k_btcoex_timer_pause(struct ath_softc *sc) ath_dbg(ath9k_hw_common(ah), BTCOEX, "Stopping btcoex timers\n"); - del_timer_sync(&btcoex->period_timer); - del_timer_sync(&btcoex->no_stomp_timer); + timer_delete_sync(&btcoex->period_timer); + timer_delete_sync(&btcoex->no_stomp_timer); } void ath9k_btcoex_stop_gen_timer(struct ath_softc *sc) { struct ath_btcoex *btcoex = &sc->btcoex; - del_timer_sync(&btcoex->no_stomp_timer); + timer_delete_sync(&btcoex->no_stomp_timer); } u16 ath9k_btcoex_aggr_limit(struct ath_softc *sc, u32 max_4ms_framelen)
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 57094bd..1960001 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
@@ -198,7 +198,7 @@ void ath9k_htc_reset(struct ath9k_htc_priv *priv) ath9k_htc_stop_ani(priv); ieee80211_stop_queues(priv->hw); - del_timer_sync(&priv->tx.cleanup_timer); + timer_delete_sync(&priv->tx.cleanup_timer); ath9k_htc_tx_drain(priv); WMI_CMD(WMI_DISABLE_INTR_CMDID); @@ -260,7 +260,7 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv, ath9k_htc_ps_wakeup(priv); ath9k_htc_stop_ani(priv); - del_timer_sync(&priv->tx.cleanup_timer); + timer_delete_sync(&priv->tx.cleanup_timer); ath9k_htc_tx_drain(priv); WMI_CMD(WMI_DISABLE_INTR_CMDID); @@ -997,7 +997,7 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw, bool suspend) tasklet_kill(&priv->rx_tasklet); - del_timer_sync(&priv->tx.cleanup_timer); + timer_delete_sync(&priv->tx.cleanup_timer); ath9k_htc_tx_drain(priv); ath9k_wmi_event_drain(priv);
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 01e0dffb..ee95149 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -1099,7 +1099,7 @@ static void ath9k_deinit_softc(struct ath_softc *sc) if (ATH_TXQ_SETUP(sc, i)) ath_tx_cleanupq(sc, &sc->tx.txq[i]); - del_timer_sync(&sc->sleep_timer); + timer_delete_sync(&sc->sleep_timer); ath9k_hw_deinit(sc->sc_ah); if (sc->dfs_detector != NULL) sc->dfs_detector->exit(sc->dfs_detector);
diff --git a/drivers/net/wireless/ath/ath9k/link.c b/drivers/net/wireless/ath/ath9k/link.c index d078a59..7f89099 100644 --- a/drivers/net/wireless/ath/ath9k/link.c +++ b/drivers/net/wireless/ath/ath9k/link.c
@@ -472,7 +472,7 @@ void ath_stop_ani(struct ath_softc *sc) struct ath_common *common = ath9k_hw_common(sc->sc_ah); ath_dbg(common, ANI, "Stopping ANI\n"); - del_timer_sync(&common->ani.timer); + timer_delete_sync(&common->ani.timer); } void ath_check_ani(struct ath_softc *sc)
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index a70c945..92fc5e3 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -123,7 +123,7 @@ void ath9k_ps_wakeup(struct ath_softc *sc) if (++sc->ps_usecount != 1) goto unlock; - del_timer_sync(&sc->sleep_timer); + timer_delete_sync(&sc->sleep_timer); power_mode = sc->sc_ah->power_mode; ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE); @@ -2418,7 +2418,7 @@ static void ath9k_cancel_pending_offchannel(struct ath_softc *sc) ath_dbg(common, CHAN_CTX, "%s: Aborting RoC\n", __func__); - del_timer_sync(&sc->offchannel.timer); + timer_delete_sync(&sc->offchannel.timer); if (sc->offchannel.state >= ATH_OFFCHANNEL_ROC_START) ath_roc_complete(sc, ATH_ROC_COMPLETE_ABORT); } @@ -2427,7 +2427,7 @@ static void ath9k_cancel_pending_offchannel(struct ath_softc *sc) ath_dbg(common, CHAN_CTX, "%s: Aborting HW scan\n", __func__); - del_timer_sync(&sc->offchannel.timer); + timer_delete_sync(&sc->offchannel.timer); ath_scan_complete(sc, true); } } @@ -2476,7 +2476,7 @@ static void ath9k_cancel_hw_scan(struct ieee80211_hw *hw, ath_dbg(common, CHAN_CTX, "Cancel HW scan on vif: %pM\n", vif->addr); mutex_lock(&sc->mutex); - del_timer_sync(&sc->offchannel.timer); + timer_delete_sync(&sc->offchannel.timer); ath_scan_complete(sc, true); mutex_unlock(&sc->mutex); } @@ -2526,7 +2526,7 @@ static int ath9k_cancel_remain_on_channel(struct ieee80211_hw *hw, mutex_lock(&sc->mutex); ath_dbg(common, CHAN_CTX, "Cancel RoC\n"); - del_timer_sync(&sc->offchannel.timer); + timer_delete_sync(&sc->offchannel.timer); if (sc->offchannel.roc_vif) { if (sc->offchannel.state >= ATH_OFFCHANNEL_ROC_START)
diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index 1ff5352..27d4034 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c
@@ -1029,7 +1029,7 @@ static int ath_pci_suspend(struct device *device) */ ath9k_stop_btcoex(sc); ath9k_hw_disable(sc->sc_ah); - del_timer_sync(&sc->sleep_timer); + timer_delete_sync(&sc->sleep_timer); ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_FULL_SLEEP); return 0;
diff --git a/drivers/net/wireless/ath/wcn36xx/dxe.c b/drivers/net/wireless/ath/wcn36xx/dxe.c index d405a4c..cc2a033 100644 --- a/drivers/net/wireless/ath/wcn36xx/dxe.c +++ b/drivers/net/wireless/ath/wcn36xx/dxe.c
@@ -350,7 +350,7 @@ void wcn36xx_dxe_tx_ack_ind(struct wcn36xx *wcn, u32 status) spin_lock_irqsave(&wcn->dxe_lock, flags); skb = wcn->tx_ack_skb; wcn->tx_ack_skb = NULL; - del_timer(&wcn->tx_ack_timer); + timer_delete(&wcn->tx_ack_timer); spin_unlock_irqrestore(&wcn->dxe_lock, flags); if (!skb) { @@ -1055,7 +1055,7 @@ void wcn36xx_dxe_deinit(struct wcn36xx *wcn) free_irq(wcn->tx_irq, wcn); free_irq(wcn->rx_irq, wcn); - del_timer(&wcn->tx_ack_timer); + timer_delete(&wcn->tx_ack_timer); if (wcn->tx_ack_skb) { ieee80211_tx_status_irqsafe(wcn->hw, wcn->tx_ack_skb);
diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c index a1a0a92..5473c01c 100644 --- a/drivers/net/wireless/ath/wil6210/cfg80211.c +++ b/drivers/net/wireless/ath/wil6210/cfg80211.c
@@ -1017,7 +1017,7 @@ static int wil_cfg80211_scan(struct wiphy *wiphy, out_restore: if (rc) { - del_timer_sync(&vif->scan_timer); + timer_delete_sync(&vif->scan_timer); if (vif->mid == 0) wil->radio_wdev = wil->main_ndev->ieee80211_ptr; vif->scan_request = NULL;
diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c index 94e61db..44c24c6 100644 --- a/drivers/net/wireless/ath/wil6210/main.c +++ b/drivers/net/wireless/ath/wil6210/main.c
@@ -798,7 +798,7 @@ void wil6210_disconnect(struct wil6210_vif *vif, const u8 *bssid, wil_dbg_misc(wil, "disconnecting\n"); - del_timer_sync(&vif->connect_timer); + timer_delete_sync(&vif->connect_timer); _wil6210_disconnect(vif, bssid, reason_code); } @@ -818,7 +818,7 @@ void wil6210_disconnect_complete(struct wil6210_vif *vif, const u8 *bssid, wil_dbg_misc(wil, "got disconnect\n"); - del_timer_sync(&vif->connect_timer); + timer_delete_sync(&vif->connect_timer); _wil6210_disconnect_complete(vif, bssid, reason_code); } @@ -1465,7 +1465,7 @@ void wil_abort_scan(struct wil6210_vif *vif, bool sync) return; wil_dbg_misc(wil, "Abort scan_request 0x%p\n", vif->scan_request); - del_timer_sync(&vif->scan_timer); + timer_delete_sync(&vif->scan_timer); mutex_unlock(&wil->vif_mutex); rc = wmi_abort_scan(vif); if (!rc && sync)
diff --git a/drivers/net/wireless/ath/wil6210/netdev.c b/drivers/net/wireless/ath/wil6210/netdev.c index d5d3646..59884e8e 100644 --- a/drivers/net/wireless/ath/wil6210/netdev.c +++ b/drivers/net/wireless/ath/wil6210/netdev.c
@@ -200,8 +200,8 @@ static void wil_dev_setup(struct net_device *dev) static void wil_vif_deinit(struct wil6210_vif *vif) { - del_timer_sync(&vif->scan_timer); - del_timer_sync(&vif->p2p.discovery_timer); + timer_delete_sync(&vif->scan_timer); + timer_delete_sync(&vif->p2p.discovery_timer); cancel_work_sync(&vif->disconnect_worker); cancel_work_sync(&vif->p2p.discovery_expired_work); cancel_work_sync(&vif->p2p.delayed_listen_work); @@ -533,7 +533,7 @@ void wil_vif_remove(struct wil6210_priv *wil, u8 mid) mutex_unlock(&wil->vif_mutex); flush_work(&wil->wmi_event_worker); - del_timer_sync(&vif->connect_timer); + timer_delete_sync(&vif->connect_timer); cancel_work_sync(&vif->disconnect_worker); wil_probe_client_flush(vif); cancel_work_sync(&vif->probe_client_worker);
diff --git a/drivers/net/wireless/ath/wil6210/p2p.c b/drivers/net/wireless/ath/wil6210/p2p.c index f26bf04..f20caf1 100644 --- a/drivers/net/wireless/ath/wil6210/p2p.c +++ b/drivers/net/wireless/ath/wil6210/p2p.c
@@ -184,7 +184,7 @@ u8 wil_p2p_stop_discovery(struct wil6210_vif *vif) /* discovery not really started, only pending */ p2p->pending_listen_wdev = NULL; } else { - del_timer_sync(&p2p->discovery_timer); + timer_delete_sync(&p2p->discovery_timer); wmi_stop_discovery(vif); } p2p->discovery_started = 0;
diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c index 8ff69dc..74edd00 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.c +++ b/drivers/net/wireless/ath/wil6210/wmi.c
@@ -933,7 +933,7 @@ static void wmi_evt_scan_complete(struct wil6210_vif *vif, int id, wil_dbg_wmi(wil, "SCAN_COMPLETE(0x%08x)\n", status); wil_dbg_misc(wil, "Complete scan_request 0x%p aborted %d\n", vif->scan_request, info.aborted); - del_timer_sync(&vif->scan_timer); + timer_delete_sync(&vif->scan_timer); cfg80211_scan_done(vif->scan_request, &info); if (vif->mid == 0) wil->radio_wdev = wil->main_ndev->ieee80211_ptr; @@ -1023,7 +1023,7 @@ static void wmi_evt_connect(struct wil6210_vif *vif, int id, void *d, int len) mutex_unlock(&wil->mutex); return; } - del_timer_sync(&vif->connect_timer); + timer_delete_sync(&vif->connect_timer); } else if ((wdev->iftype == NL80211_IFTYPE_AP) || (wdev->iftype == NL80211_IFTYPE_P2P_GO)) { if (wil->sta[evt->cid].status != wil_sta_unused) { @@ -1814,7 +1814,7 @@ wmi_evt_reassoc_status(struct wil6210_vif *vif, int id, void *d, int len) wil->sta[cid].stats.ft_roams++; ether_addr_copy(wil->sta[cid].addr, vif->bss->bssid); mutex_unlock(&wil->mutex); - del_timer_sync(&vif->connect_timer); + timer_delete_sync(&vif->connect_timer); cfg80211_ref_bss(wiphy, vif->bss); freq = ieee80211_channel_to_frequency(ch, NL80211_BAND_60GHZ);
diff --git a/drivers/net/wireless/atmel/at76c50x-usb.c b/drivers/net/wireless/atmel/at76c50x-usb.c index 504e05e..4f01189 100644 --- a/drivers/net/wireless/atmel/at76c50x-usb.c +++ b/drivers/net/wireless/atmel/at76c50x-usb.c
@@ -2417,7 +2417,7 @@ static void at76_delete_device(struct at76_priv *priv) kfree(priv->bulk_out_buffer); - del_timer_sync(&ledtrig_tx_timer); + timer_delete_sync(&ledtrig_tx_timer); kfree_skb(priv->rx_skb);
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/btcoex.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/btcoex.c index 1e8495f..e0de34a 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/btcoex.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/btcoex.c
@@ -289,7 +289,7 @@ static void brcmf_btcoex_handler(struct work_struct *work) btci = container_of(work, struct brcmf_btcoex_info, work); if (btci->timer_on) { btci->timer_on = false; - del_timer_sync(&btci->timer); + timer_delete_sync(&btci->timer); } switch (btci->bt_state) { @@ -428,7 +428,7 @@ static void brcmf_btcoex_dhcp_end(struct brcmf_btcoex_info *btci) if (btci->timer_on) { brcmf_dbg(INFO, "disable BT DHCP Timer\n"); btci->timer_on = false; - del_timer_sync(&btci->timer); + timer_delete_sync(&btci->timer); /* schedule worker if transition to IDLE is needed */ if (btci->bt_state != BRCMF_BT_DHCP_IDLE) {
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c index d2caa80..9f1854b 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
@@ -2304,7 +2304,7 @@ brcmf_pcie_fwcon_timer(struct brcmf_pciedev_info *devinfo, bool active) { if (!active) { if (devinfo->console_active) { - del_timer_sync(&devinfo->timer); + timer_delete_sync(&devinfo->timer); devinfo->console_active = false; } return;
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c index b1727f3..93727b9a 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
@@ -4611,7 +4611,7 @@ void brcmf_sdio_wd_timer(struct brcmf_sdio *bus, bool active) { /* Totally stop the timer */ if (!active && bus->wd_active) { - del_timer_sync(&bus->timer); + timer_delete_sync(&bus->timer); bus->wd_active = false; return; }
diff --git a/drivers/net/wireless/intel/ipw2x00/libipw_crypto.c b/drivers/net/wireless/intel/ipw2x00/libipw_crypto.c index 32639e0..dfcc12a 100644 --- a/drivers/net/wireless/intel/ipw2x00/libipw_crypto.c +++ b/drivers/net/wireless/intel/ipw2x00/libipw_crypto.c
@@ -59,7 +59,7 @@ void libipw_crypt_info_free(struct libipw_crypt_info *info) int i; libipw_crypt_quiescing(info); - del_timer_sync(&info->crypt_deinit_timer); + timer_delete_sync(&info->crypt_deinit_timer); libipw_crypt_deinit_entries(info, 1); for (i = 0; i < NUM_WEP_KEYS; i++) {
diff --git a/drivers/net/wireless/intel/iwlegacy/3945-mac.c b/drivers/net/wireless/intel/iwlegacy/3945-mac.c index 4013443..104748f 100644 --- a/drivers/net/wireless/intel/iwlegacy/3945-mac.c +++ b/drivers/net/wireless/intel/iwlegacy/3945-mac.c
@@ -2188,7 +2188,7 @@ __il3945_down(struct il_priv *il) /* Stop TX queues watchdog. We need to have S_EXIT_PENDING bit set * to prevent rearm timer */ - del_timer_sync(&il->watchdog); + timer_delete_sync(&il->watchdog); /* Station information will now be cleared in device */ il_clear_ucode_stations(il);
diff --git a/drivers/net/wireless/intel/iwlegacy/3945-rs.c b/drivers/net/wireless/intel/iwlegacy/3945-rs.c index 0eaad98..df1b8ec 100644 --- a/drivers/net/wireless/intel/iwlegacy/3945-rs.c +++ b/drivers/net/wireless/intel/iwlegacy/3945-rs.c
@@ -413,7 +413,7 @@ il3945_rs_free_sta(void *il_priv, struct ieee80211_sta *sta, void *il_sta) * to use il_priv to print out debugging) since it may not be fully * initialized at this point. */ - del_timer_sync(&rs_sta->rate_scale_flush); + timer_delete_sync(&rs_sta->rate_scale_flush); } /*
diff --git a/drivers/net/wireless/intel/iwlegacy/4965-mac.c b/drivers/net/wireless/intel/iwlegacy/4965-mac.c index 05c4af4..dc8c408 100644 --- a/drivers/net/wireless/intel/iwlegacy/4965-mac.c +++ b/drivers/net/wireless/intel/iwlegacy/4965-mac.c
@@ -5350,7 +5350,7 @@ __il4965_down(struct il_priv *il) /* Stop TX queues watchdog. We need to have S_EXIT_PENDING bit set * to prevent rearm timer */ - del_timer_sync(&il->watchdog); + timer_delete_sync(&il->watchdog); il_clear_ucode_stations(il); @@ -6243,7 +6243,7 @@ il4965_cancel_deferred_work(struct il_priv *il) il_cancel_scan_deferred_work(il); - del_timer_sync(&il->stats_periodic); + timer_delete_sync(&il->stats_periodic); } static void
diff --git a/drivers/net/wireless/intel/iwlegacy/common.c b/drivers/net/wireless/intel/iwlegacy/common.c index af4f425..09fb4b7 100644 --- a/drivers/net/wireless/intel/iwlegacy/common.c +++ b/drivers/net/wireless/intel/iwlegacy/common.c
@@ -4842,7 +4842,7 @@ il_setup_watchdog(struct il_priv *il) mod_timer(&il->watchdog, jiffies + msecs_to_jiffies(IL_WD_TICK(timeout))); else - del_timer(&il->watchdog); + timer_delete(&il->watchdog); } EXPORT_SYMBOL(il_setup_watchdog);
diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/dvm/debugfs.c index b246dbd..2ed4b6e 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/debugfs.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/debugfs.c
@@ -1870,7 +1870,7 @@ static ssize_t iwl_dbgfs_ucode_tracing_write(struct file *file, } } else { priv->event_log.ucode_trace = false; - del_timer_sync(&priv->ucode_trace); + timer_delete_sync(&priv->ucode_trace); } return count;
diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/main.c b/drivers/net/wireless/intel/iwlwifi/dvm/main.c index 30789ba..a27a72c 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/main.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/main.c
@@ -1082,8 +1082,8 @@ void iwl_cancel_deferred_work(struct iwl_priv *priv) cancel_work_sync(&priv->bt_full_concurrency); cancel_work_sync(&priv->bt_runtime_config); - del_timer_sync(&priv->statistics_periodic); - del_timer_sync(&priv->ucode_trace); + timer_delete_sync(&priv->statistics_periodic); + timer_delete_sync(&priv->ucode_trace); } static int iwl_init_drv(struct iwl_priv *priv)
diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/tt.c b/drivers/net/wireless/intel/iwlwifi/dvm/tt.c index e1d7855..98f0949 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/tt.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/tt.c
@@ -257,7 +257,7 @@ static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp, bool force) tt->tt_previous_temp = temp; #endif /* stop ct_kill_waiting_tm timer */ - del_timer_sync(&priv->thermal_throttle.ct_kill_waiting_tm); + timer_delete_sync(&priv->thermal_throttle.ct_kill_waiting_tm); if (tt->state != old_state) { switch (tt->state) { case IWL_TI_0: @@ -378,7 +378,7 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp, bool force) } } /* stop ct_kill_waiting_tm timer */ - del_timer_sync(&priv->thermal_throttle.ct_kill_waiting_tm); + timer_delete_sync(&priv->thermal_throttle.ct_kill_waiting_tm); if (changed) { if (tt->state >= IWL_TI_1) { /* force PI = IWL_POWER_INDEX_5 in the case of TI > 0 */ @@ -506,7 +506,7 @@ static void iwl_bg_ct_exit(struct work_struct *work) return; /* stop ct_kill_exit_tm timer */ - del_timer_sync(&priv->thermal_throttle.ct_kill_exit_tm); + timer_delete_sync(&priv->thermal_throttle.ct_kill_exit_tm); if (tt->state == IWL_TI_CT_KILL) { IWL_ERR(priv, @@ -640,9 +640,9 @@ void iwl_tt_exit(struct iwl_priv *priv) struct iwl_tt_mgmt *tt = &priv->thermal_throttle; /* stop ct_kill_exit_tm timer if activated */ - del_timer_sync(&priv->thermal_throttle.ct_kill_exit_tm); + timer_delete_sync(&priv->thermal_throttle.ct_kill_exit_tm); /* stop ct_kill_waiting_tm timer if activated */ - del_timer_sync(&priv->thermal_throttle.ct_kill_waiting_tm); + timer_delete_sync(&priv->thermal_throttle.ct_kill_waiting_tm); cancel_work_sync(&priv->tt_work); cancel_work_sync(&priv->ct_enter); cancel_work_sync(&priv->ct_exit);
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c index 4a442d0..4a4f8de 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c
@@ -1697,7 +1697,7 @@ static void iwl_pcie_irq_handle_error(struct iwl_trans *trans) for (i = 0; i < trans->trans_cfg->base_params->num_of_queues; i++) { if (!trans_pcie->txqs.txq[i]) continue; - del_timer(&trans_pcie->txqs.txq[i]->stuck_timer); + timer_delete(&trans_pcie->txqs.txq[i]->stuck_timer); } /* The STATUS_FW_ERROR bit is set in this function. This must happen
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c index 401919f..71227fd 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c
@@ -911,7 +911,7 @@ static void iwl_txq_gen2_free(struct iwl_trans *trans, int txq_id) kfree_sensitive(txq->entries[i].cmd); kfree_sensitive(txq->entries[i].free_buf); } - del_timer_sync(&txq->stuck_timer); + timer_delete_sync(&txq->stuck_timer); iwl_txq_gen2_free_memory(trans, txq);
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c index 7c1dd5c..bb90bcf 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c
@@ -469,7 +469,7 @@ static void iwl_pcie_txq_free(struct iwl_trans *trans, int txq_id) kfree(txq->entries); txq->entries = NULL; - del_timer_sync(&txq->stuck_timer); + timer_delete_sync(&txq->stuck_timer); /* 0-fill queue descriptor structure */ memset(txq, 0, sizeof(*txq)); @@ -1054,7 +1054,7 @@ static void iwl_txq_progress(struct iwl_txq *txq) * since we're making progress on this queue */ if (txq->read_ptr == txq->write_ptr) - del_timer(&txq->stuck_timer); + timer_delete(&txq->stuck_timer); else mod_timer(&txq->stuck_timer, jiffies + txq->wd_timeout); } @@ -2529,7 +2529,7 @@ void iwl_pcie_freeze_txq_timer(struct iwl_trans *trans, /* remember how long until the timer fires */ txq->frozen_expiry_remainder = txq->stuck_timer.expires - now; - del_timer(&txq->stuck_timer); + timer_delete(&txq->stuck_timer); goto next_queue; }
diff --git a/drivers/net/wireless/marvell/libertas/cmdresp.c b/drivers/net/wireless/marvell/libertas/cmdresp.c index 8393f39..9742d3d 100644 --- a/drivers/net/wireless/marvell/libertas/cmdresp.c +++ b/drivers/net/wireless/marvell/libertas/cmdresp.c
@@ -119,7 +119,7 @@ int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len) } /* Now we got response from FW, cancel the command timer */ - del_timer(&priv->command_timer); + timer_delete(&priv->command_timer); priv->cmd_timed_out = 0; if (respcmd == CMD_RET(CMD_802_11_PS_MODE)) {
diff --git a/drivers/net/wireless/marvell/libertas/if_usb.c b/drivers/net/wireless/marvell/libertas/if_usb.c index 2240b4db..ea3cc2e 100644 --- a/drivers/net/wireless/marvell/libertas/if_usb.c +++ b/drivers/net/wireless/marvell/libertas/if_usb.c
@@ -897,7 +897,7 @@ static void if_usb_prog_firmware(struct lbs_private *priv, int ret, /* ... and wait for the process to complete */ wait_event_interruptible(cardp->fw_wq, cardp->surprise_removed || cardp->fwdnldover); - del_timer_sync(&cardp->fw_timeout); + timer_delete_sync(&cardp->fw_timeout); usb_kill_urb(cardp->rx_urb); if (!cardp->fwdnldover) {
diff --git a/drivers/net/wireless/marvell/libertas/main.c b/drivers/net/wireless/marvell/libertas/main.c index 017e5c6..26d13e9 100644 --- a/drivers/net/wireless/marvell/libertas/main.c +++ b/drivers/net/wireless/marvell/libertas/main.c
@@ -202,7 +202,7 @@ int lbs_stop_iface(struct lbs_private *priv) spin_unlock_irqrestore(&priv->driver_lock, flags); cancel_work_sync(&priv->mcast_work); - del_timer_sync(&priv->tx_lockup_timer); + timer_delete_sync(&priv->tx_lockup_timer); /* Disable command processing, and wait for all commands to complete */ lbs_deb_main("waiting for commands to complete\n"); @@ -250,7 +250,7 @@ void lbs_host_to_card_done(struct lbs_private *priv) unsigned long flags; spin_lock_irqsave(&priv->driver_lock, flags); - del_timer(&priv->tx_lockup_timer); + timer_delete(&priv->tx_lockup_timer); priv->dnld_sent = DNLD_RES_RECEIVED; @@ -594,8 +594,8 @@ static int lbs_thread(void *data) spin_unlock_irq(&priv->driver_lock); } - del_timer(&priv->command_timer); - del_timer(&priv->tx_lockup_timer); + timer_delete(&priv->command_timer); + timer_delete(&priv->tx_lockup_timer); return 0; } @@ -798,8 +798,8 @@ static void lbs_free_adapter(struct lbs_private *priv) { lbs_free_cmd_buffer(priv); kfifo_free(&priv->event_fifo); - del_timer(&priv->command_timer); - del_timer(&priv->tx_lockup_timer); + timer_delete(&priv->command_timer); + timer_delete(&priv->tx_lockup_timer); } static const struct net_device_ops lbs_netdev_ops = {
diff --git a/drivers/net/wireless/marvell/libertas_tf/cmd.c b/drivers/net/wireless/marvell/libertas_tf/cmd.c index efb9830..7fc1bdb 100644 --- a/drivers/net/wireless/marvell/libertas_tf/cmd.c +++ b/drivers/net/wireless/marvell/libertas_tf/cmd.c
@@ -757,7 +757,7 @@ int lbtf_process_rx_command(struct lbtf_private *priv) } /* Now we got response from FW, cancel the command timer */ - del_timer(&priv->command_timer); + timer_delete(&priv->command_timer); priv->cmd_timed_out = 0; if (priv->nr_retries) priv->nr_retries = 0;
diff --git a/drivers/net/wireless/marvell/libertas_tf/if_usb.c b/drivers/net/wireless/marvell/libertas_tf/if_usb.c index 1750f5e..7c413dc 100644 --- a/drivers/net/wireless/marvell/libertas_tf/if_usb.c +++ b/drivers/net/wireless/marvell/libertas_tf/if_usb.c
@@ -875,7 +875,7 @@ static int if_usb_prog_firmware(struct lbtf_private *priv) wait_event_interruptible(cardp->fw_wq, cardp->priv->surpriseremoved || cardp->fwdnldover); - del_timer_sync(&cardp->fw_timeout); + timer_delete_sync(&cardp->fw_timeout); usb_kill_urb(cardp->rx_urb); if (!cardp->fwdnldover) {
diff --git a/drivers/net/wireless/marvell/libertas_tf/main.c b/drivers/net/wireless/marvell/libertas_tf/main.c index b47a832..a57a11b 100644 --- a/drivers/net/wireless/marvell/libertas_tf/main.c +++ b/drivers/net/wireless/marvell/libertas_tf/main.c
@@ -174,7 +174,7 @@ static void lbtf_free_adapter(struct lbtf_private *priv) { lbtf_deb_enter(LBTF_DEB_MAIN); lbtf_free_cmd_buffer(priv); - del_timer(&priv->command_timer); + timer_delete(&priv->command_timer); lbtf_deb_leave(LBTF_DEB_MAIN); } @@ -642,7 +642,7 @@ int lbtf_remove_card(struct lbtf_private *priv) lbtf_deb_enter(LBTF_DEB_MAIN); priv->surpriseremoved = 1; - del_timer(&priv->command_timer); + timer_delete(&priv->command_timer); lbtf_free_adapter(priv); priv->hw = NULL; ieee80211_unregister_hw(hw);
diff --git a/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c b/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c index cb948ca..8aff1df 100644 --- a/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c +++ b/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c
@@ -206,7 +206,7 @@ mwifiex_del_rx_reorder_entry(struct mwifiex_private *priv, start_win = (tbl->start_win + tbl->win_size) & (MAX_TID_VALUE - 1); mwifiex_11n_dispatch_pkt_until_start_win(priv, tbl, start_win); - del_timer_sync(&tbl->timer_context.timer); + timer_delete_sync(&tbl->timer_context.timer); tbl->timer_context.timer_is_set = false; spin_lock_bh(&priv->rx_reorder_tbl_lock);
diff --git a/drivers/net/wireless/marvell/mwifiex/cmdevt.c b/drivers/net/wireless/marvell/mwifiex/cmdevt.c index b30ed32..5573e2d 100644 --- a/drivers/net/wireless/marvell/mwifiex/cmdevt.c +++ b/drivers/net/wireless/marvell/mwifiex/cmdevt.c
@@ -836,7 +836,7 @@ int mwifiex_process_cmdresp(struct mwifiex_adapter *adapter) return -1; } /* Now we got response from FW, cancel the command timer */ - del_timer_sync(&adapter->cmd_timer); + timer_delete_sync(&adapter->cmd_timer); clear_bit(MWIFIEX_IS_CMD_TIMEDOUT, &adapter->work_flags); if (adapter->curr_cmd->cmd_flag & CMD_F_HOSTCMD) {
diff --git a/drivers/net/wireless/marvell/mwifiex/init.c b/drivers/net/wireless/marvell/mwifiex/init.c index 8b61e45..ce0d42e 100644 --- a/drivers/net/wireless/marvell/mwifiex/init.c +++ b/drivers/net/wireless/marvell/mwifiex/init.c
@@ -390,7 +390,7 @@ static void mwifiex_invalidate_lists(struct mwifiex_adapter *adapter) static void mwifiex_adapter_cleanup(struct mwifiex_adapter *adapter) { - del_timer(&adapter->wakeup_timer); + timer_delete(&adapter->wakeup_timer); cancel_delayed_work_sync(&adapter->devdump_work); mwifiex_cancel_all_pending_cmd(adapter); wake_up_interruptible(&adapter->cmd_wait_q.wait); @@ -613,7 +613,7 @@ mwifiex_shutdown_drv(struct mwifiex_adapter *adapter) if (adapter->curr_cmd) { mwifiex_dbg(adapter, WARN, "curr_cmd is still in processing\n"); - del_timer_sync(&adapter->cmd_timer); + timer_delete_sync(&adapter->cmd_timer); mwifiex_recycle_cmd_node(adapter, adapter->curr_cmd); adapter->curr_cmd = NULL; }
diff --git a/drivers/net/wireless/marvell/mwifiex/main.c b/drivers/net/wireless/marvell/mwifiex/main.c index b07cb30..0e1f539 100644 --- a/drivers/net/wireless/marvell/mwifiex/main.c +++ b/drivers/net/wireless/marvell/mwifiex/main.c
@@ -307,7 +307,7 @@ int mwifiex_main_process(struct mwifiex_adapter *adapter) if (IS_CARD_RX_RCVD(adapter)) { adapter->data_received = false; adapter->pm_wakeup_fw_try = false; - del_timer(&adapter->wakeup_timer); + timer_delete(&adapter->wakeup_timer); if (adapter->ps_state == PS_STATE_SLEEP) adapter->ps_state = PS_STATE_AWAKE; } else {
diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c index e11458f..dd2a42e 100644 --- a/drivers/net/wireless/marvell/mwifiex/pcie.c +++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
@@ -2437,7 +2437,7 @@ static void mwifiex_interrupt_status(struct mwifiex_adapter *adapter, */ adapter->ps_state = PS_STATE_AWAKE; adapter->pm_wakeup_fw_try = false; - del_timer(&adapter->wakeup_timer); + timer_delete(&adapter->wakeup_timer); } spin_lock_irqsave(&adapter->int_lock, flags); @@ -2527,7 +2527,7 @@ static int mwifiex_process_int_status(struct mwifiex_adapter *adapter) adapter->ps_state == PS_STATE_SLEEP) { adapter->ps_state = PS_STATE_AWAKE; adapter->pm_wakeup_fw_try = false; - del_timer(&adapter->wakeup_timer); + timer_delete(&adapter->wakeup_timer); } } }
diff --git a/drivers/net/wireless/marvell/mwifiex/sta_event.c b/drivers/net/wireless/marvell/mwifiex/sta_event.c index 400348a..fecd889 100644 --- a/drivers/net/wireless/marvell/mwifiex/sta_event.c +++ b/drivers/net/wireless/marvell/mwifiex/sta_event.c
@@ -789,7 +789,7 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv) adapter->ps_state = PS_STATE_AWAKE; adapter->pm_wakeup_card_req = false; adapter->pm_wakeup_fw_try = false; - del_timer(&adapter->wakeup_timer); + timer_delete(&adapter->wakeup_timer); break; } if (!mwifiex_send_null_packet @@ -804,7 +804,7 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv) adapter->ps_state = PS_STATE_AWAKE; adapter->pm_wakeup_card_req = false; adapter->pm_wakeup_fw_try = false; - del_timer(&adapter->wakeup_timer); + timer_delete(&adapter->wakeup_timer); break;
diff --git a/drivers/net/wireless/marvell/mwifiex/tdls.c b/drivers/net/wireless/marvell/mwifiex/tdls.c index 0a5f340..18e8c04 100644 --- a/drivers/net/wireless/marvell/mwifiex/tdls.c +++ b/drivers/net/wireless/marvell/mwifiex/tdls.c
@@ -1490,7 +1490,7 @@ void mwifiex_clean_auto_tdls(struct mwifiex_private *priv) priv->adapter->auto_tdls && priv->bss_type == MWIFIEX_BSS_TYPE_STA) { priv->auto_tdls_timer_active = false; - del_timer(&priv->auto_tdls_timer); + timer_delete(&priv->auto_tdls_timer); mwifiex_flush_auto_tdls_list(priv); } }
diff --git a/drivers/net/wireless/marvell/mwifiex/usb.c b/drivers/net/wireless/marvell/mwifiex/usb.c index 3034c44..2f56539 100644 --- a/drivers/net/wireless/marvell/mwifiex/usb.c +++ b/drivers/net/wireless/marvell/mwifiex/usb.c
@@ -877,7 +877,7 @@ static int mwifiex_usb_prepare_tx_aggr_skb(struct mwifiex_adapter *adapter, * write complete, delete the tx_aggr timer */ if (port->tx_aggr.timer_cnxt.is_hold_timer_set) { - del_timer(&port->tx_aggr.timer_cnxt.hold_timer); + timer_delete(&port->tx_aggr.timer_cnxt.hold_timer); port->tx_aggr.timer_cnxt.is_hold_timer_set = false; port->tx_aggr.timer_cnxt.hold_tmo_msecs = 0; } @@ -1354,7 +1354,7 @@ static void mwifiex_usb_cleanup_tx_aggr(struct mwifiex_adapter *adapter) mwifiex_write_data_complete(adapter, skb_tmp, 0, -1); if (port->tx_aggr.timer_cnxt.hold_timer.function) - del_timer_sync(&port->tx_aggr.timer_cnxt.hold_timer); + timer_delete_sync(&port->tx_aggr.timer_cnxt.hold_timer); port->tx_aggr.timer_cnxt.is_hold_timer_set = false; port->tx_aggr.timer_cnxt.hold_tmo_msecs = 0; } @@ -1557,7 +1557,7 @@ static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter) { /* Simulation of HS_AWAKE event */ adapter->pm_wakeup_fw_try = false; - del_timer(&adapter->wakeup_timer); + timer_delete(&adapter->wakeup_timer); adapter->pm_wakeup_card_req = false; adapter->ps_state = PS_STATE_AWAKE;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c index 2e7b05e..c54005d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c
@@ -97,7 +97,7 @@ static void mt7615_stop(struct ieee80211_hw *hw, bool suspend) struct mt7615_phy *phy = mt7615_hw_phy(hw); cancel_delayed_work_sync(&phy->mt76->mac_work); - del_timer_sync(&phy->roc_timer); + timer_delete_sync(&phy->roc_timer); cancel_work_sync(&phy->roc_work); cancel_delayed_work_sync(&dev->pm.ps_work); @@ -1194,7 +1194,7 @@ static int mt7615_cancel_remain_on_channel(struct ieee80211_hw *hw, if (!test_and_clear_bit(MT76_STATE_ROC, &phy->mt76->state)) return 0; - del_timer_sync(&phy->roc_timer); + timer_delete_sync(&phy->roc_timer); cancel_work_sync(&phy->roc_work); mt7615_mutex_acquire(phy->dev);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/pci_mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/pci_mac.c index c2e4e6a..b795d11 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/pci_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/pci_mac.c
@@ -220,12 +220,12 @@ void mt7615_mac_reset_work(struct work_struct *work) set_bit(MT76_MCU_RESET, &dev->mphy.state); wake_up(&dev->mt76.mcu.wait); cancel_delayed_work_sync(&dev->mphy.mac_work); - del_timer_sync(&dev->phy.roc_timer); + timer_delete_sync(&dev->phy.roc_timer); cancel_work_sync(&dev->phy.roc_work); if (phy2) { set_bit(MT76_RESET, &phy2->mt76->state); cancel_delayed_work_sync(&phy2->mt76->mac_work); - del_timer_sync(&phy2->roc_timer); + timer_delete_sync(&phy2->roc_timer); cancel_work_sync(&phy2->roc_work); }
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/usb.c b/drivers/net/wireless/mediatek/mt76/mt7615/usb.c index 4aa9fa1..d96e06b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/usb.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/usb.c
@@ -85,7 +85,7 @@ static void mt7663u_stop(struct ieee80211_hw *hw, bool suspend) struct mt7615_dev *dev = hw->priv; clear_bit(MT76_STATE_RUNNING, &dev->mphy.state); - del_timer_sync(&phy->roc_timer); + timer_delete_sync(&phy->roc_timer); cancel_work_sync(&phy->roc_work); cancel_delayed_work_sync(&phy->scan_work); cancel_delayed_work_sync(&phy->mt76->mac_work);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c index 78b77a5..826c48a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c
@@ -364,7 +364,7 @@ void mt7921_roc_abort_sync(struct mt792x_dev *dev) { struct mt792x_phy *phy = &dev->phy; - del_timer_sync(&phy->roc_timer); + timer_delete_sync(&phy->roc_timer); cancel_work_sync(&phy->roc_work); if (test_and_clear_bit(MT76_STATE_ROC, &phy->mt76->state)) ieee80211_iterate_interfaces(mt76_hw(dev), @@ -395,7 +395,7 @@ static int mt7921_abort_roc(struct mt792x_phy *phy, struct mt792x_vif *vif) { int err = 0; - del_timer_sync(&phy->roc_timer); + timer_delete_sync(&phy->roc_timer); cancel_work_sync(&phy->roc_work); mt792x_mutex_acquire(phy->dev); @@ -1476,7 +1476,7 @@ static void mt7921_abort_channel_switch(struct ieee80211_hw *hw, { struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; - del_timer_sync(&mvif->csa_timer); + timer_delete_sync(&mvif->csa_timer); cancel_work_sync(&mvif->csa_work); }
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/main.c b/drivers/net/wireless/mediatek/mt76/mt7925/main.c index e79364a..66f3277 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7925/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7925/main.c
@@ -453,7 +453,7 @@ void mt7925_roc_abort_sync(struct mt792x_dev *dev) { struct mt792x_phy *phy = &dev->phy; - del_timer_sync(&phy->roc_timer); + timer_delete_sync(&phy->roc_timer); cancel_work_sync(&phy->roc_work); if (test_and_clear_bit(MT76_STATE_ROC, &phy->mt76->state)) ieee80211_iterate_interfaces(mt76_hw(dev), @@ -485,7 +485,7 @@ static int mt7925_abort_roc(struct mt792x_phy *phy, { int err = 0; - del_timer_sync(&phy->roc_timer); + timer_delete_sync(&phy->roc_timer); cancel_work_sync(&phy->roc_work); mt792x_mutex_acquire(phy->dev);
diff --git a/drivers/net/wireless/mediatek/mt76/mt792x_core.c b/drivers/net/wireless/mediatek/mt76/mt792x_core.c index 0f7806f..38dd58f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt792x_core.c +++ b/drivers/net/wireless/mediatek/mt76/mt792x_core.c
@@ -340,7 +340,7 @@ void mt792x_unassign_vif_chanctx(struct ieee80211_hw *hw, mutex_unlock(&dev->mt76.mutex); if (vif->bss_conf.csa_active) { - del_timer_sync(&mvif->csa_timer); + timer_delete_sync(&mvif->csa_timer); cancel_work_sync(&mvif->csa_work); } }
diff --git a/drivers/net/wireless/microchip/wilc1000/hif.c b/drivers/net/wireless/microchip/wilc1000/hif.c index bba5330..cb46a39 100644 --- a/drivers/net/wireless/microchip/wilc1000/hif.c +++ b/drivers/net/wireless/microchip/wilc1000/hif.c
@@ -643,7 +643,7 @@ static inline void host_int_parse_assoc_resp_info(struct wilc_vif *vif, } } - del_timer(&hif_drv->connect_timer); + timer_delete(&hif_drv->connect_timer); conn_info->conn_result(CONN_DISCONN_EVENT_CONN_RESP, mac_status, hif_drv->conn_info.priv); @@ -669,7 +669,7 @@ void wilc_handle_disconnect(struct wilc_vif *vif) struct host_if_drv *hif_drv = vif->hif_drv; if (hif_drv->usr_scan_req.scan_result) { - del_timer(&hif_drv->scan_timer); + timer_delete(&hif_drv->scan_timer); handle_scan_done(vif, SCAN_EVENT_ABORTED); } @@ -713,7 +713,7 @@ static void handle_rcvd_gnrl_async_info(struct work_struct *work) if (hif_drv->hif_state == HOST_IF_CONNECTED) { wilc_handle_disconnect(vif); } else if (hif_drv->usr_scan_req.scan_result) { - del_timer(&hif_drv->scan_timer); + timer_delete(&hif_drv->scan_timer); handle_scan_done(vif, SCAN_EVENT_ABORTED); } } @@ -746,7 +746,7 @@ int wilc_disconnect(struct wilc_vif *vif) conn_info = &hif_drv->conn_info; if (scan_req->scan_result) { - del_timer(&hif_drv->scan_timer); + timer_delete(&hif_drv->scan_timer); scan_req->scan_result(SCAN_EVENT_ABORTED, NULL, scan_req->priv); scan_req->scan_result = NULL; } @@ -754,7 +754,7 @@ int wilc_disconnect(struct wilc_vif *vif) if (conn_info->conn_result) { if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP || hif_drv->hif_state == HOST_IF_EXTERNAL_AUTH) - del_timer(&hif_drv->connect_timer); + timer_delete(&hif_drv->connect_timer); conn_info->conn_result(CONN_DISCONN_EVENT_DISCONN_NOTIF, 0, conn_info->priv); @@ -959,7 +959,7 @@ static void listen_timer_cb(struct timer_list *t) int result; struct host_if_msg *msg; - del_timer(&vif->hif_drv->remain_on_ch_timer); + timer_delete(&vif->hif_drv->remain_on_ch_timer); msg = wilc_alloc_work(vif, wilc_handle_listen_state_expired, false); if (IS_ERR(msg)) @@ -1066,7 +1066,7 @@ static void handle_scan_complete(struct work_struct *work) { struct host_if_msg *msg = container_of(work, struct host_if_msg, work); - del_timer(&msg->vif->hif_drv->scan_timer); + timer_delete(&msg->vif->hif_drv->scan_timer); handle_scan_done(msg->vif, SCAN_EVENT_DONE); @@ -1551,7 +1551,7 @@ int wilc_deinit(struct wilc_vif *vif) timer_shutdown_sync(&hif_drv->scan_timer); timer_shutdown_sync(&hif_drv->connect_timer); - del_timer_sync(&vif->periodic_rssi); + timer_delete_sync(&vif->periodic_rssi); timer_shutdown_sync(&hif_drv->remain_on_ch_timer); if (hif_drv->usr_scan_req.scan_result) { @@ -1718,7 +1718,7 @@ int wilc_listen_state_expired(struct wilc_vif *vif, u64 cookie) return -EFAULT; } - del_timer(&vif->hif_drv->remain_on_ch_timer); + timer_delete(&vif->hif_drv->remain_on_ch_timer); return wilc_handle_roc_expired(vif, cookie); }
diff --git a/drivers/net/wireless/purelifi/plfxlc/usb.c b/drivers/net/wireless/purelifi/plfxlc/usb.c index 56d1139..10d2e21 100644 --- a/drivers/net/wireless/purelifi/plfxlc/usb.c +++ b/drivers/net/wireless/purelifi/plfxlc/usb.c
@@ -714,8 +714,8 @@ static void disconnect(struct usb_interface *intf) mac = plfxlc_hw_mac(hw); usb = &mac->chip.usb; - del_timer_sync(&usb->tx.tx_retry_timer); - del_timer_sync(&usb->sta_queue_cleanup); + timer_delete_sync(&usb->tx.tx_retry_timer); + timer_delete_sync(&usb->sta_queue_cleanup); ieee80211_unregister_hw(hw);
diff --git a/drivers/net/wireless/realtek/rtlwifi/base.c b/drivers/net/wireless/realtek/rtlwifi/base.c index ff61867..6189edc 100644 --- a/drivers/net/wireless/realtek/rtlwifi/base.c +++ b/drivers/net/wireless/realtek/rtlwifi/base.c
@@ -473,7 +473,7 @@ void rtl_deinit_deferred_work(struct ieee80211_hw *hw, bool ips_wq) { struct rtl_priv *rtlpriv = rtl_priv(hw); - del_timer_sync(&rtlpriv->works.watchdog_timer); + timer_delete_sync(&rtlpriv->works.watchdog_timer); cancel_delayed_work_sync(&rtlpriv->works.watchdog_wq); if (ips_wq)
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c index 35875cd..2ad4523 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c
@@ -179,9 +179,9 @@ static void rtl88e_deinit_sw_vars(struct ieee80211_hw *hw) } if (rtlpriv->psc.low_power_enable) - del_timer_sync(&rtlpriv->works.fw_clockoff_timer); + timer_delete_sync(&rtlpriv->works.fw_clockoff_timer); - del_timer_sync(&rtlpriv->works.fast_antenna_training_timer); + timer_delete_sync(&rtlpriv->works.fast_antenna_training_timer); } /* get bt coexist status */
diff --git a/drivers/net/wireless/rsi/rsi_91x_hal.c b/drivers/net/wireless/rsi/rsi_91x_hal.c index 2cebe562..5382765 100644 --- a/drivers/net/wireless/rsi/rsi_91x_hal.c +++ b/drivers/net/wireless/rsi/rsi_91x_hal.c
@@ -493,7 +493,7 @@ static void bl_cmd_timeout(struct timer_list *t) struct rsi_hw *adapter = from_timer(adapter, t, bl_cmd_timer); adapter->blcmd_timer_expired = true; - del_timer(&adapter->bl_cmd_timer); + timer_delete(&adapter->bl_cmd_timer); } static int bl_start_cmd_timer(struct rsi_hw *adapter, u32 timeout) @@ -511,7 +511,7 @@ static int bl_stop_cmd_timer(struct rsi_hw *adapter) { adapter->blcmd_timer_expired = false; if (timer_pending(&adapter->bl_cmd_timer)) - del_timer(&adapter->bl_cmd_timer); + timer_delete(&adapter->bl_cmd_timer); return 0; }
diff --git a/drivers/net/wireless/rsi/rsi_91x_mac80211.c b/drivers/net/wireless/rsi/rsi_91x_mac80211.c index 3425a47..9db0820 100644 --- a/drivers/net/wireless/rsi/rsi_91x_mac80211.c +++ b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
@@ -1754,7 +1754,7 @@ void rsi_roc_timeout(struct timer_list *t) ieee80211_remain_on_channel_expired(common->priv->hw); if (timer_pending(&common->roc_timer)) - del_timer(&common->roc_timer); + timer_delete(&common->roc_timer); rsi_resume_conn_channel(common); mutex_unlock(&common->mutex); @@ -1776,7 +1776,7 @@ static int rsi_mac80211_roc(struct ieee80211_hw *hw, struct ieee80211_vif *vif, if (timer_pending(&common->roc_timer)) { rsi_dbg(INFO_ZONE, "Stop on-going ROC\n"); - del_timer(&common->roc_timer); + timer_delete(&common->roc_timer); } common->roc_timer.expires = msecs_to_jiffies(duration) + jiffies; add_timer(&common->roc_timer); @@ -1820,7 +1820,7 @@ static int rsi_mac80211_cancel_roc(struct ieee80211_hw *hw, return 0; } - del_timer(&common->roc_timer); + timer_delete(&common->roc_timer); rsi_resume_conn_channel(common); mutex_unlock(&common->mutex);
diff --git a/drivers/net/wireless/st/cw1200/main.c b/drivers/net/wireless/st/cw1200/main.c index a54a7b8..5d569ee 100644 --- a/drivers/net/wireless/st/cw1200/main.c +++ b/drivers/net/wireless/st/cw1200/main.c
@@ -458,7 +458,7 @@ static void cw1200_unregister_common(struct ieee80211_hw *dev) ieee80211_unregister_hw(dev); - del_timer_sync(&priv->mcast_timeout); + timer_delete_sync(&priv->mcast_timeout); cw1200_unregister_bh(priv); cw1200_debug_release(priv);
diff --git a/drivers/net/wireless/st/cw1200/pm.c b/drivers/net/wireless/st/cw1200/pm.c index a20ab577..2002e3f 100644 --- a/drivers/net/wireless/st/cw1200/pm.c +++ b/drivers/net/wireless/st/cw1200/pm.c
@@ -105,7 +105,7 @@ int cw1200_pm_init(struct cw1200_pm_state *pm, void cw1200_pm_deinit(struct cw1200_pm_state *pm) { - del_timer_sync(&pm->stay_awake); + timer_delete_sync(&pm->stay_awake); } void cw1200_pm_stay_awake(struct cw1200_pm_state *pm,
diff --git a/drivers/net/wireless/st/cw1200/queue.c b/drivers/net/wireless/st/cw1200/queue.c index 259739e..4fd7618 100644 --- a/drivers/net/wireless/st/cw1200/queue.c +++ b/drivers/net/wireless/st/cw1200/queue.c
@@ -244,7 +244,7 @@ void cw1200_queue_stats_deinit(struct cw1200_queue_stats *stats) void cw1200_queue_deinit(struct cw1200_queue *queue) { cw1200_queue_clear(queue); - del_timer_sync(&queue->gc); + timer_delete_sync(&queue->gc); INIT_LIST_HEAD(&queue->free_pool); kfree(queue->pool); kfree(queue->link_map_cache);
diff --git a/drivers/net/wireless/st/cw1200/sta.c b/drivers/net/wireless/st/cw1200/sta.c index c259da8..444272c 100644 --- a/drivers/net/wireless/st/cw1200/sta.c +++ b/drivers/net/wireless/st/cw1200/sta.c
@@ -113,7 +113,7 @@ void cw1200_stop(struct ieee80211_hw *dev, bool suspend) cancel_work_sync(&priv->unjoin_work); cancel_delayed_work_sync(&priv->link_id_gc_work); flush_workqueue(priv->workqueue); - del_timer_sync(&priv->mcast_timeout); + timer_delete_sync(&priv->mcast_timeout); mutex_lock(&priv->conf_mutex); priv->mode = NL80211_IFTYPE_UNSPECIFIED; priv->listening = false; @@ -2102,7 +2102,7 @@ void cw1200_multicast_stop_work(struct work_struct *work) container_of(work, struct cw1200_common, multicast_stop_work); if (priv->aid0_bit_set) { - del_timer_sync(&priv->mcast_timeout); + timer_delete_sync(&priv->mcast_timeout); wsm_lock_tx(priv); priv->aid0_bit_set = false; cw1200_set_tim_impl(priv, false); @@ -2170,7 +2170,7 @@ void cw1200_suspend_resume(struct cw1200_common *priv, } spin_unlock_bh(&priv->ps_state_lock); if (cancel_tmo) - del_timer_sync(&priv->mcast_timeout); + timer_delete_sync(&priv->mcast_timeout); } else { spin_lock_bh(&priv->ps_state_lock); cw1200_ps_notify(priv, arg->link_id, arg->stop);
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index 8fb58a5..ea9bc47 100644 --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -117,7 +117,7 @@ int wl1271_recalc_rx_streaming(struct wl1271 *wl, struct wl12xx_vif *wlvif) else { ret = wl1271_set_rx_streaming(wl, wlvif, false); /* don't cancel_work_sync since we might deadlock */ - del_timer_sync(&wlvif->rx_streaming_timer); + timer_delete_sync(&wlvif->rx_streaming_timer); } out: return ret; @@ -2841,7 +2841,7 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl, unlock: mutex_unlock(&wl->mutex); - del_timer_sync(&wlvif->rx_streaming_timer); + timer_delete_sync(&wlvif->rx_streaming_timer); cancel_work_sync(&wlvif->rx_streaming_enable_work); cancel_work_sync(&wlvif->rx_streaming_disable_work); cancel_work_sync(&wlvif->rc_update_work);
diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c index 325fcb3..a0a4388 100644 --- a/drivers/net/xen-netback/interface.c +++ b/drivers/net/xen-netback/interface.c
@@ -329,7 +329,7 @@ static void xenvif_down(struct xenvif *vif) if (queue->tx_irq != queue->rx_irq) disable_irq(queue->rx_irq); napi_disable(&queue->napi); - del_timer_sync(&queue->credit_timeout); + timer_delete_sync(&queue->credit_timeout); } }
diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c index 63fe51d..fc52d5c 100644 --- a/drivers/net/xen-netfront.c +++ b/drivers/net/xen-netfront.c
@@ -1819,7 +1819,7 @@ static void xennet_disconnect_backend(struct netfront_info *info) for (i = 0; i < num_queues && info->queues; ++i) { struct netfront_queue *queue = &info->queues[i]; - del_timer_sync(&queue->rx_refill_timer); + timer_delete_sync(&queue->rx_refill_timer); if (queue->tx_irq && (queue->tx_irq == queue->rx_irq)) unbind_from_irqhandler(queue->tx_irq, queue);
diff --git a/drivers/nfc/nfcmrvl/fw_dnld.c b/drivers/nfc/nfcmrvl/fw_dnld.c index 9309441..43ce0c9 100644 --- a/drivers/nfc/nfcmrvl/fw_dnld.c +++ b/drivers/nfc/nfcmrvl/fw_dnld.c
@@ -102,10 +102,10 @@ static void fw_dnld_over(struct nfcmrvl_private *priv, u32 error) atomic_set(&priv->ndev->cmd_cnt, 0); if (timer_pending(&priv->ndev->cmd_timer)) - del_timer_sync(&priv->ndev->cmd_timer); + timer_delete_sync(&priv->ndev->cmd_timer); if (timer_pending(&priv->fw_dnld.timer)) - del_timer_sync(&priv->fw_dnld.timer); + timer_delete_sync(&priv->fw_dnld.timer); nfc_info(priv->dev, "FW loading over (%d)]\n", error); @@ -464,7 +464,7 @@ void nfcmrvl_fw_dnld_recv_frame(struct nfcmrvl_private *priv, { /* Discard command timer */ if (timer_pending(&priv->ndev->cmd_timer)) - del_timer_sync(&priv->ndev->cmd_timer); + timer_delete_sync(&priv->ndev->cmd_timer); /* Allow next command */ atomic_set(&priv->ndev->cmd_cnt, 1);
diff --git a/drivers/nfc/pn533/pn533.c b/drivers/nfc/pn533/pn533.c index e2bc673..34c40d1 100644 --- a/drivers/nfc/pn533/pn533.c +++ b/drivers/nfc/pn533/pn533.c
@@ -1515,7 +1515,7 @@ static int pn533_poll_complete(struct pn533 *dev, void *arg, cur_mod = dev->poll_mod_active[dev->poll_mod_curr]; if (cur_mod->len == 0) { /* Target mode */ - del_timer(&dev->listen_timer); + timer_delete(&dev->listen_timer); rc = pn533_init_target_complete(dev, resp); goto done; } @@ -1749,7 +1749,7 @@ static void pn533_stop_poll(struct nfc_dev *nfc_dev) { struct pn533 *dev = nfc_get_drvdata(nfc_dev); - del_timer(&dev->listen_timer); + timer_delete(&dev->listen_timer); if (!dev->poll_mod_count) { dev_dbg(dev->dev,
diff --git a/drivers/nfc/pn533/uart.c b/drivers/nfc/pn533/uart.c index cfbbe07..580c919 100644 --- a/drivers/nfc/pn533/uart.c +++ b/drivers/nfc/pn533/uart.c
@@ -209,7 +209,7 @@ static size_t pn532_receive_buf(struct serdev_device *serdev, struct pn532_uart_phy *dev = serdev_device_get_drvdata(serdev); size_t i; - del_timer(&dev->cmd_timeout); + timer_delete(&dev->cmd_timeout); for (i = 0; i < count; i++) { skb_put_u8(dev->recv_skb, *data++); if (!pn532_uart_rx_is_frame(dev->recv_skb))
diff --git a/drivers/nfc/st-nci/ndlc.c b/drivers/nfc/st-nci/ndlc.c index d2aa9f76..8feac11 100644 --- a/drivers/nfc/st-nci/ndlc.c +++ b/drivers/nfc/st-nci/ndlc.c
@@ -161,8 +161,8 @@ static void llt_ndlc_rcv_queue(struct llt_ndlc *ndlc) case PCB_SYNC_ACK: skb = skb_dequeue(&ndlc->ack_pending_q); kfree_skb(skb); - del_timer_sync(&ndlc->t1_timer); - del_timer_sync(&ndlc->t2_timer); + timer_delete_sync(&ndlc->t1_timer); + timer_delete_sync(&ndlc->t2_timer); ndlc->t2_active = false; ndlc->t1_active = false; break; @@ -213,8 +213,8 @@ static void llt_ndlc_sm_work(struct work_struct *work) pr_debug("Handle T2(recv DATA) elapsed (T2 now inactive)\n"); ndlc->t2_active = false; ndlc->t1_active = false; - del_timer_sync(&ndlc->t1_timer); - del_timer_sync(&ndlc->t2_timer); + timer_delete_sync(&ndlc->t1_timer); + timer_delete_sync(&ndlc->t2_timer); ndlc_close(ndlc); ndlc->hard_fault = -EREMOTEIO; } @@ -283,8 +283,8 @@ EXPORT_SYMBOL(ndlc_probe); void ndlc_remove(struct llt_ndlc *ndlc) { /* cancel timers */ - del_timer_sync(&ndlc->t1_timer); - del_timer_sync(&ndlc->t2_timer); + timer_delete_sync(&ndlc->t1_timer); + timer_delete_sync(&ndlc->t2_timer); ndlc->t2_active = false; ndlc->t1_active = false; /* cancel work */
diff --git a/drivers/nfc/st-nci/se.c b/drivers/nfc/st-nci/se.c index b2f1ced..8cfe540 100644 --- a/drivers/nfc/st-nci/se.c +++ b/drivers/nfc/st-nci/se.c
@@ -257,7 +257,7 @@ static void st_nci_hci_admin_event_received(struct nci_dev *ndev, case ST_NCI_EVT_HOT_PLUG: if (info->se_info.se_active) { if (!ST_NCI_EVT_HOT_PLUG_IS_INHIBITED(skb)) { - del_timer_sync(&info->se_info.se_active_timer); + timer_delete_sync(&info->se_info.se_active_timer); info->se_info.se_active = false; complete(&info->se_info.req_completion); } else { @@ -282,7 +282,7 @@ static int st_nci_hci_apdu_reader_event_received(struct nci_dev *ndev, switch (event) { case ST_NCI_EVT_TRANSMIT_DATA: - del_timer_sync(&info->se_info.bwi_timer); + timer_delete_sync(&info->se_info.bwi_timer); info->se_info.bwi_active = false; info->se_info.cb(info->se_info.cb_context, skb->data, skb->len, 0); @@ -415,7 +415,7 @@ void st_nci_hci_cmd_received(struct nci_dev *ndev, u8 pipe, u8 cmd, if (ndev->hci_dev->count_pipes == ndev->hci_dev->expected_pipes) { - del_timer_sync(&info->se_info.se_active_timer); + timer_delete_sync(&info->se_info.se_active_timer); info->se_info.se_active = false; ndev->hci_dev->count_pipes = 0; complete(&info->se_info.req_completion); @@ -751,9 +751,9 @@ void st_nci_se_deinit(struct nci_dev *ndev) struct st_nci_info *info = nci_get_drvdata(ndev); if (info->se_info.bwi_active) - del_timer_sync(&info->se_info.bwi_timer); + timer_delete_sync(&info->se_info.bwi_timer); if (info->se_info.se_active) - del_timer_sync(&info->se_info.se_active_timer); + timer_delete_sync(&info->se_info.se_active_timer); info->se_info.se_active = false; info->se_info.bwi_active = false;
diff --git a/drivers/nfc/st21nfca/core.c b/drivers/nfc/st21nfca/core.c index 161caf2..bec6f60 100644 --- a/drivers/nfc/st21nfca/core.c +++ b/drivers/nfc/st21nfca/core.c
@@ -844,7 +844,7 @@ static void st21nfca_hci_cmd_received(struct nfc_hci_dev *hdev, u8 pipe, u8 cmd, info->se_info.count_pipes++; if (info->se_info.count_pipes == info->se_info.expected_pipes) { - del_timer_sync(&info->se_info.se_active_timer); + timer_delete_sync(&info->se_info.se_active_timer); info->se_info.se_active = false; info->se_info.count_pipes = 0; complete(&info->se_info.req_completion); @@ -864,7 +864,7 @@ static int st21nfca_admin_event_received(struct nfc_hci_dev *hdev, u8 event, case ST21NFCA_EVT_HOT_PLUG: if (info->se_info.se_active) { if (!ST21NFCA_EVT_HOT_PLUG_IS_INHIBITED(skb)) { - del_timer_sync(&info->se_info.se_active_timer); + timer_delete_sync(&info->se_info.se_active_timer); info->se_info.se_active = false; complete(&info->se_info.req_completion); } else {
diff --git a/drivers/nfc/st21nfca/se.c b/drivers/nfc/st21nfca/se.c index dae288be..9a50f3c 100644 --- a/drivers/nfc/st21nfca/se.c +++ b/drivers/nfc/st21nfca/se.c
@@ -380,7 +380,7 @@ int st21nfca_apdu_reader_event_received(struct nfc_hci_dev *hdev, switch (event) { case ST21NFCA_EVT_TRANSMIT_DATA: - del_timer_sync(&info->se_info.bwi_timer); + timer_delete_sync(&info->se_info.bwi_timer); cancel_work_sync(&info->se_info.timeout_work); info->se_info.bwi_active = false; r = nfc_hci_send_event(hdev, ST21NFCA_DEVICE_MGNT_GATE, @@ -435,9 +435,9 @@ void st21nfca_se_deinit(struct nfc_hci_dev *hdev) struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev); if (info->se_info.bwi_active) - del_timer_sync(&info->se_info.bwi_timer); + timer_delete_sync(&info->se_info.bwi_timer); if (info->se_info.se_active) - del_timer_sync(&info->se_info.se_active_timer); + timer_delete_sync(&info->se_info.se_active_timer); cancel_work_sync(&info->se_info.timeout_work); info->se_info.bwi_active = false;
diff --git a/drivers/ntb/hw/amd/ntb_hw_amd.c b/drivers/ntb/hw/amd/ntb_hw_amd.c index d687e8c..63ceed8 100644 --- a/drivers/ntb/hw/amd/ntb_hw_amd.c +++ b/drivers/ntb/hw/amd/ntb_hw_amd.c
@@ -1318,6 +1318,7 @@ static const struct pci_device_id amd_ntb_pci_tbl[] = { { PCI_VDEVICE(AMD, 0x148b), (kernel_ulong_t)&dev_data[1] }, { PCI_VDEVICE(AMD, 0x14c0), (kernel_ulong_t)&dev_data[1] }, { PCI_VDEVICE(AMD, 0x14c3), (kernel_ulong_t)&dev_data[1] }, + { PCI_VDEVICE(AMD, 0x155a), (kernel_ulong_t)&dev_data[1] }, { PCI_VDEVICE(HYGON, 0x145b), (kernel_ulong_t)&dev_data[0] }, { 0, } };
diff --git a/drivers/ntb/hw/idt/ntb_hw_idt.c b/drivers/ntb/hw/idt/ntb_hw_idt.c index 544d8a4..f27df8d 100644 --- a/drivers/ntb/hw/idt/ntb_hw_idt.c +++ b/drivers/ntb/hw/idt/ntb_hw_idt.c
@@ -1041,7 +1041,7 @@ static inline char *idt_get_mw_name(enum idt_mw_type mw_type) static struct idt_mw_cfg *idt_scan_mws(struct idt_ntb_dev *ndev, int port, unsigned char *mw_cnt) { - struct idt_mw_cfg mws[IDT_MAX_NR_MWS], *ret_mws; + struct idt_mw_cfg *mws; const struct idt_ntb_bar *bars; enum idt_mw_type mw_type; unsigned char widx, bidx, en_cnt; @@ -1049,6 +1049,11 @@ static struct idt_mw_cfg *idt_scan_mws(struct idt_ntb_dev *ndev, int port, int aprt_size; u32 data; + mws = devm_kcalloc(&ndev->ntb.pdev->dev, IDT_MAX_NR_MWS, + sizeof(*mws), GFP_KERNEL); + if (!mws) + return ERR_PTR(-ENOMEM); + /* Retrieve the array of the BARs registers */ bars = portdata_tbl[port].bars; @@ -1103,16 +1108,7 @@ static struct idt_mw_cfg *idt_scan_mws(struct idt_ntb_dev *ndev, int port, } } - /* Allocate memory for memory window descriptors */ - ret_mws = devm_kcalloc(&ndev->ntb.pdev->dev, *mw_cnt, sizeof(*ret_mws), - GFP_KERNEL); - if (!ret_mws) - return ERR_PTR(-ENOMEM); - - /* Copy the info of detected memory windows */ - memcpy(ret_mws, mws, (*mw_cnt)*sizeof(*ret_mws)); - - return ret_mws; + return mws; } /*
diff --git a/drivers/ntb/hw/intel/ntb_hw_gen3.c b/drivers/ntb/hw/intel/ntb_hw_gen3.c index ffcfc3e..a5aa96a 100644 --- a/drivers/ntb/hw/intel/ntb_hw_gen3.c +++ b/drivers/ntb/hw/intel/ntb_hw_gen3.c
@@ -215,6 +215,9 @@ static int gen3_init_ntb(struct intel_ntb_dev *ndev) } ndev->db_valid_mask = BIT_ULL(ndev->db_count) - 1; + /* Make sure we are not using DB's used for link status */ + if (ndev->hwerr_flags & NTB_HWERR_MSIX_VECTOR32_BAD) + ndev->db_valid_mask &= ~ndev->db_link_mask; ndev->reg->db_iowrite(ndev->db_valid_mask, ndev->self_mmio +
diff --git a/drivers/ntb/hw/mscc/ntb_hw_switchtec.c b/drivers/ntb/hw/mscc/ntb_hw_switchtec.c index ad1786b..f851397 100644 --- a/drivers/ntb/hw/mscc/ntb_hw_switchtec.c +++ b/drivers/ntb/hw/mscc/ntb_hw_switchtec.c
@@ -288,7 +288,7 @@ static int switchtec_ntb_mw_set_trans(struct ntb_dev *ntb, int pidx, int widx, if (size != 0 && xlate_pos < 12) return -EINVAL; - if (!IS_ALIGNED(addr, BIT_ULL(xlate_pos))) { + if (xlate_pos >= 0 && !IS_ALIGNED(addr, BIT_ULL(xlate_pos))) { /* * In certain circumstances we can get a buffer that is * not aligned to its size. (Most of the time
diff --git a/drivers/ntb/ntb_transport.c b/drivers/ntb/ntb_transport.c index a22ea4a..4f775c3 100644 --- a/drivers/ntb/ntb_transport.c +++ b/drivers/ntb/ntb_transport.c
@@ -1353,7 +1353,7 @@ static int ntb_transport_probe(struct ntb_client *self, struct ntb_dev *ndev) qp_count = ilog2(qp_bitmap); if (nt->use_msi) { qp_count -= 1; - nt->msi_db_mask = 1 << qp_count; + nt->msi_db_mask = BIT_ULL(qp_count); ntb_db_clear_mask(ndev, nt->msi_db_mask); }
diff --git a/drivers/ntb/test/ntb_perf.c b/drivers/ntb/test/ntb_perf.c index 72bc1d01..dfd175f 100644 --- a/drivers/ntb/test/ntb_perf.c +++ b/drivers/ntb/test/ntb_perf.c
@@ -839,10 +839,8 @@ static int perf_copy_chunk(struct perf_thread *pthr, dma_set_unmap(tx, unmap); ret = dma_submit_error(dmaengine_submit(tx)); - if (ret) { - dmaengine_unmap_put(unmap); + if (ret) goto err_free_resource; - } dmaengine_unmap_put(unmap);
diff --git a/drivers/nvdimm/claim.c b/drivers/nvdimm/claim.c index 9e84ab4..5161465 100644 --- a/drivers/nvdimm/claim.c +++ b/drivers/nvdimm/claim.c
@@ -56,17 +56,6 @@ bool __nd_attach_ndns(struct device *dev, struct nd_namespace_common *attach, return true; } -bool nd_attach_ndns(struct device *dev, struct nd_namespace_common *attach, - struct nd_namespace_common **_ndns) -{ - bool claimed; - - nvdimm_bus_lock(&attach->dev); - claimed = __nd_attach_ndns(dev, attach, _ndns); - nvdimm_bus_unlock(&attach->dev); - return claimed; -} - static bool is_idle(struct device *dev, struct nd_namespace_common *ndns) { struct nd_region *nd_region = to_nd_region(dev->parent);
diff --git a/drivers/nvdimm/label.c b/drivers/nvdimm/label.c index 082253a..04f4a04 100644 --- a/drivers/nvdimm/label.c +++ b/drivers/nvdimm/label.c
@@ -442,7 +442,8 @@ int nd_label_data_init(struct nvdimm_drvdata *ndd) if (ndd->data) return 0; - if (ndd->nsarea.status || ndd->nsarea.max_xfer == 0) { + if (ndd->nsarea.status || ndd->nsarea.max_xfer == 0 || + ndd->nsarea.config_size == 0) { dev_dbg(ndd->dev, "failed to init config data area: (%u:%u)\n", ndd->nsarea.max_xfer, ndd->nsarea.config_size); return -ENXIO;
diff --git a/drivers/nvdimm/nd-core.h b/drivers/nvdimm/nd-core.h index 86976a9..bfc6bfeb 100644 --- a/drivers/nvdimm/nd-core.h +++ b/drivers/nvdimm/nd-core.h
@@ -127,8 +127,6 @@ resource_size_t nd_region_allocatable_dpa(struct nd_region *nd_region); resource_size_t nd_pmem_available_dpa(struct nd_region *nd_region, struct nd_mapping *nd_mapping); resource_size_t nd_region_available_dpa(struct nd_region *nd_region); -int nd_region_conflict(struct nd_region *nd_region, resource_size_t start, - resource_size_t size); resource_size_t nvdimm_allocated_dpa(struct nvdimm_drvdata *ndd, struct nd_label_id *label_id); int nvdimm_num_label_slots(struct nvdimm_drvdata *ndd); @@ -136,8 +134,6 @@ void get_ndd(struct nvdimm_drvdata *ndd); resource_size_t __nvdimm_namespace_capacity(struct nd_namespace_common *ndns); void nd_detach_ndns(struct device *dev, struct nd_namespace_common **_ndns); void __nd_detach_ndns(struct device *dev, struct nd_namespace_common **_ndns); -bool nd_attach_ndns(struct device *dev, struct nd_namespace_common *attach, - struct nd_namespace_common **_ndns); bool __nd_attach_ndns(struct device *dev, struct nd_namespace_common *attach, struct nd_namespace_common **_ndns); ssize_t nd_namespace_store(struct device *dev,
diff --git a/drivers/nvdimm/region_devs.c b/drivers/nvdimm/region_devs.c index 37417ce..de1ee5e 100644 --- a/drivers/nvdimm/region_devs.c +++ b/drivers/nvdimm/region_devs.c
@@ -1229,45 +1229,4 @@ bool is_nvdimm_sync(struct nd_region *nd_region) } EXPORT_SYMBOL_GPL(is_nvdimm_sync); -struct conflict_context { - struct nd_region *nd_region; - resource_size_t start, size; -}; - -static int region_conflict(struct device *dev, void *data) -{ - struct nd_region *nd_region; - struct conflict_context *ctx = data; - resource_size_t res_end, region_end, region_start; - - if (!is_memory(dev)) - return 0; - - nd_region = to_nd_region(dev); - if (nd_region == ctx->nd_region) - return 0; - - res_end = ctx->start + ctx->size; - region_start = nd_region->ndr_start; - region_end = region_start + nd_region->ndr_size; - if (ctx->start >= region_start && ctx->start < region_end) - return -EBUSY; - if (res_end > region_start && res_end <= region_end) - return -EBUSY; - return 0; -} - -int nd_region_conflict(struct nd_region *nd_region, resource_size_t start, - resource_size_t size) -{ - struct nvdimm_bus *nvdimm_bus = walk_to_nvdimm_bus(&nd_region->dev); - struct conflict_context ctx = { - .nd_region = nd_region, - .start = start, - .size = size, - }; - - return device_for_each_child(&nvdimm_bus->dev, &ctx, region_conflict); -} - MODULE_IMPORT_NS("DEVMEM");
diff --git a/drivers/nvme/host/Kconfig b/drivers/nvme/host/Kconfig index 10e453b..d47dfa8 100644 --- a/drivers/nvme/host/Kconfig +++ b/drivers/nvme/host/Kconfig
@@ -18,10 +18,15 @@ bool "NVMe multipath support" depends on NVME_CORE help - This option enables support for multipath access to NVMe - subsystems. If this option is enabled only a single - /dev/nvmeXnY device will show up for each NVMe namespace, - even if it is accessible through multiple controllers. + This option controls support for multipath access to NVMe + subsystems. If this option is enabled support for NVMe multipath + access is included in the kernel. If this option is disabled support + for NVMe multipath access is excluded from the kernel. When this + option is disabled each controller/namespace receives its + own /dev/nvmeXnY device entry and NVMe multipath access is + not supported. + + If unsure, say Y. config NVME_VERBOSE_ERRORS bool "NVMe verbose error reporting"
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index c2d89fa..cc23035 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c
@@ -3822,7 +3822,7 @@ static int nvme_init_ns_head(struct nvme_ns *ns, struct nvme_ns_info *info) "Found shared namespace %d, but multipathing not supported.\n", info->nsid); dev_warn_once(ctrl->device, - "Support for shared namespaces without CONFIG_NVME_MULTIPATH is deprecated and will be removed in Linux 6.0.\n"); + "Shared namespace support requires core_nvme.multipath=Y.\n"); } }
diff --git a/drivers/nvme/host/ioctl.c b/drivers/nvme/host/ioctl.c index ecf1364..ca86d3b 100644 --- a/drivers/nvme/host/ioctl.c +++ b/drivers/nvme/host/ioctl.c
@@ -114,8 +114,7 @@ static struct request *nvme_alloc_user_request(struct request_queue *q, static int nvme_map_user_request(struct request *req, u64 ubuffer, unsigned bufflen, void __user *meta_buffer, unsigned meta_len, - struct io_uring_cmd *ioucmd, unsigned int flags, - unsigned int iou_issue_flags) + struct iov_iter *iter, unsigned int flags) { struct request_queue *q = req->q; struct nvme_ns *ns = q->queuedata; @@ -129,37 +128,23 @@ static int nvme_map_user_request(struct request *req, u64 ubuffer, if (!nvme_ctrl_sgl_supported(ctrl)) dev_warn_once(ctrl->device, "using unchecked data buffer\n"); if (has_metadata) { - if (!supports_metadata) { - ret = -EINVAL; - goto out; - } + if (!supports_metadata) + return -EINVAL; + if (!nvme_ctrl_meta_sgl_supported(ctrl)) dev_warn_once(ctrl->device, "using unchecked metadata buffer\n"); } - if (ioucmd && (ioucmd->flags & IORING_URING_CMD_FIXED)) { - struct iov_iter iter; - - /* fixedbufs is only for non-vectored io */ - if (WARN_ON_ONCE(flags & NVME_IOCTL_VEC)) { - ret = -EINVAL; - goto out; - } - ret = io_uring_cmd_import_fixed(ubuffer, bufflen, - rq_data_dir(req), &iter, ioucmd, - iou_issue_flags); - if (ret < 0) - goto out; - ret = blk_rq_map_user_iov(q, req, NULL, &iter, GFP_KERNEL); - } else { + if (iter) + ret = blk_rq_map_user_iov(q, req, NULL, iter, GFP_KERNEL); + else ret = blk_rq_map_user_io(req, NULL, nvme_to_user_ptr(ubuffer), bufflen, GFP_KERNEL, flags & NVME_IOCTL_VEC, 0, 0, rq_data_dir(req)); - } if (ret) - goto out; + return ret; bio = req->bio; if (bdev) @@ -176,8 +161,6 @@ static int nvme_map_user_request(struct request *req, u64 ubuffer, out_unmap: if (bio) blk_rq_unmap_user(bio); -out: - blk_mq_free_request(req); return ret; } @@ -200,9 +183,9 @@ static int nvme_submit_user_cmd(struct request_queue *q, req->timeout = timeout; if (ubuffer && bufflen) { ret = nvme_map_user_request(req, ubuffer, bufflen, meta_buffer, - meta_len, NULL, flags, 0); + meta_len, NULL, flags); if (ret) - return ret; + goto out_free_req; } bio = req->bio; @@ -218,7 +201,10 @@ static int nvme_submit_user_cmd(struct request_queue *q, if (effects) nvme_passthru_end(ctrl, ns, effects, cmd, ret); + return ret; +out_free_req: + blk_mq_free_request(req); return ret; } @@ -469,6 +455,8 @@ static int nvme_uring_cmd_io(struct nvme_ctrl *ctrl, struct nvme_ns *ns, struct request_queue *q = ns ? ns->queue : ctrl->admin_q; struct nvme_uring_data d; struct nvme_command c; + struct iov_iter iter; + struct iov_iter *map_iter = NULL; struct request *req; blk_opf_t rq_flags = REQ_ALLOC_CACHE; blk_mq_req_flags_t blk_flags = 0; @@ -504,6 +492,20 @@ static int nvme_uring_cmd_io(struct nvme_ctrl *ctrl, struct nvme_ns *ns, d.metadata_len = READ_ONCE(cmd->metadata_len); d.timeout_ms = READ_ONCE(cmd->timeout_ms); + if (d.data_len && (ioucmd->flags & IORING_URING_CMD_FIXED)) { + /* fixedbufs is only for non-vectored io */ + if (vec) + return -EINVAL; + + ret = io_uring_cmd_import_fixed(d.addr, d.data_len, + nvme_is_write(&c) ? WRITE : READ, &iter, ioucmd, + issue_flags); + if (ret < 0) + return ret; + + map_iter = &iter; + } + if (issue_flags & IO_URING_F_NONBLOCK) { rq_flags |= REQ_NOWAIT; blk_flags = BLK_MQ_REQ_NOWAIT; @@ -517,11 +519,11 @@ static int nvme_uring_cmd_io(struct nvme_ctrl *ctrl, struct nvme_ns *ns, req->timeout = d.timeout_ms ? msecs_to_jiffies(d.timeout_ms) : 0; if (d.data_len) { - ret = nvme_map_user_request(req, d.addr, - d.data_len, nvme_to_user_ptr(d.metadata), - d.metadata_len, ioucmd, vec, issue_flags); + ret = nvme_map_user_request(req, d.addr, d.data_len, + nvme_to_user_ptr(d.metadata), d.metadata_len, + map_iter, vec); if (ret) - return ret; + goto out_free_req; } /* to free bio on completion, as req->bio will be null at that time */ @@ -531,6 +533,10 @@ static int nvme_uring_cmd_io(struct nvme_ctrl *ctrl, struct nvme_ns *ns, req->end_io = nvme_uring_cmd_end_io; blk_execute_rq_nowait(req, false); return -EIOCBQUEUED; + +out_free_req: + blk_mq_free_request(req); + return ret; } static bool is_ctrl_ioctl(unsigned int cmd)
diff --git a/drivers/nvme/host/multipath.c b/drivers/nvme/host/multipath.c index 6b12ca8..89be591 100644 --- a/drivers/nvme/host/multipath.c +++ b/drivers/nvme/host/multipath.c
@@ -860,7 +860,7 @@ static int nvme_read_ana_log(struct nvme_ctrl *ctrl) if (nr_change_groups) mod_timer(&ctrl->anatt_timer, ctrl->anatt * HZ * 2 + jiffies); else - del_timer_sync(&ctrl->anatt_timer); + timer_delete_sync(&ctrl->anatt_timer); out_unlock: mutex_unlock(&ctrl->ana_lock); return error; @@ -900,7 +900,7 @@ void nvme_mpath_stop(struct nvme_ctrl *ctrl) { if (!nvme_ctrl_use_ana(ctrl)) return; - del_timer_sync(&ctrl->anatt_timer); + timer_delete_sync(&ctrl->anatt_timer); cancel_work_sync(&ctrl->ana_work); }
diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c index 2883d17..b178d52 100644 --- a/drivers/nvme/host/pci.c +++ b/drivers/nvme/host/pci.c
@@ -986,6 +986,9 @@ static void nvme_submit_cmds(struct nvme_queue *nvmeq, struct rq_list *rqlist) { struct request *req; + if (rq_list_empty(rqlist)) + return; + spin_lock(&nvmeq->sq_lock); while ((req = rq_list_pop(rqlist))) { struct nvme_iod *iod = blk_mq_rq_to_pdu(req);
diff --git a/drivers/nvme/target/debugfs.c b/drivers/nvme/target/debugfs.c index e4300eb..5dcbd5a 100644 --- a/drivers/nvme/target/debugfs.c +++ b/drivers/nvme/target/debugfs.c
@@ -78,7 +78,7 @@ static int nvmet_ctrl_state_show(struct seq_file *m, void *p) bool sep = false; int i; - for (i = 0; i < 7; i++) { + for (i = 0; i < ARRAY_SIZE(csts_state_names); i++) { int state = BIT(i); if (!(ctrl->csts & state))
diff --git a/drivers/nvme/target/pci-epf.c b/drivers/nvme/target/pci-epf.c index b54b3fd..51c27b3 100644 --- a/drivers/nvme/target/pci-epf.c +++ b/drivers/nvme/target/pci-epf.c
@@ -1264,6 +1264,7 @@ static u16 nvmet_pci_epf_create_cq(struct nvmet_ctrl *tctrl, struct nvmet_pci_epf_ctrl *ctrl = tctrl->drvdata; struct nvmet_pci_epf_queue *cq = &ctrl->cq[cqid]; u16 status; + int ret; if (test_bit(NVMET_PCI_EPF_Q_LIVE, &cq->flags)) return NVME_SC_QID_INVALID | NVME_STATUS_DNR; @@ -1298,6 +1299,24 @@ static u16 nvmet_pci_epf_create_cq(struct nvmet_ctrl *tctrl, if (status != NVME_SC_SUCCESS) goto err; + /* + * Map the CQ PCI address space and since PCI endpoint controllers may + * return a partial mapping, check that the mapping is large enough. + */ + ret = nvmet_pci_epf_mem_map(ctrl->nvme_epf, cq->pci_addr, cq->pci_size, + &cq->pci_map); + if (ret) { + dev_err(ctrl->dev, "Failed to map CQ %u (err=%d)\n", + cq->qid, ret); + goto err_internal; + } + + if (cq->pci_map.pci_size < cq->pci_size) { + dev_err(ctrl->dev, "Invalid partial mapping of queue %u\n", + cq->qid); + goto err_unmap_queue; + } + set_bit(NVMET_PCI_EPF_Q_LIVE, &cq->flags); dev_dbg(ctrl->dev, "CQ[%u]: %u entries of %zu B, IRQ vector %u\n", @@ -1305,6 +1324,10 @@ static u16 nvmet_pci_epf_create_cq(struct nvmet_ctrl *tctrl, return NVME_SC_SUCCESS; +err_unmap_queue: + nvmet_pci_epf_mem_unmap(ctrl->nvme_epf, &cq->pci_map); +err_internal: + status = NVME_SC_INTERNAL | NVME_STATUS_DNR; err: if (test_and_clear_bit(NVMET_PCI_EPF_Q_IRQ_ENABLED, &cq->flags)) nvmet_pci_epf_remove_irq_vector(ctrl, cq->vector); @@ -1322,6 +1345,7 @@ static u16 nvmet_pci_epf_delete_cq(struct nvmet_ctrl *tctrl, u16 cqid) cancel_delayed_work_sync(&cq->work); nvmet_pci_epf_drain_queue(cq); nvmet_pci_epf_remove_irq_vector(ctrl, cq->vector); + nvmet_pci_epf_mem_unmap(ctrl->nvme_epf, &cq->pci_map); return NVME_SC_SUCCESS; } @@ -1553,36 +1577,6 @@ static void nvmet_pci_epf_free_queues(struct nvmet_pci_epf_ctrl *ctrl) ctrl->cq = NULL; } -static int nvmet_pci_epf_map_queue(struct nvmet_pci_epf_ctrl *ctrl, - struct nvmet_pci_epf_queue *queue) -{ - struct nvmet_pci_epf *nvme_epf = ctrl->nvme_epf; - int ret; - - ret = nvmet_pci_epf_mem_map(nvme_epf, queue->pci_addr, - queue->pci_size, &queue->pci_map); - if (ret) { - dev_err(ctrl->dev, "Failed to map queue %u (err=%d)\n", - queue->qid, ret); - return ret; - } - - if (queue->pci_map.pci_size < queue->pci_size) { - dev_err(ctrl->dev, "Invalid partial mapping of queue %u\n", - queue->qid); - nvmet_pci_epf_mem_unmap(nvme_epf, &queue->pci_map); - return -ENOMEM; - } - - return 0; -} - -static inline void nvmet_pci_epf_unmap_queue(struct nvmet_pci_epf_ctrl *ctrl, - struct nvmet_pci_epf_queue *queue) -{ - nvmet_pci_epf_mem_unmap(ctrl->nvme_epf, &queue->pci_map); -} - static void nvmet_pci_epf_exec_iod_work(struct work_struct *work) { struct nvmet_pci_epf_iod *iod = @@ -1746,11 +1740,7 @@ static void nvmet_pci_epf_cq_work(struct work_struct *work) struct nvme_completion *cqe; struct nvmet_pci_epf_iod *iod; unsigned long flags; - int ret, n = 0; - - ret = nvmet_pci_epf_map_queue(ctrl, cq); - if (ret) - goto again; + int ret = 0, n = 0; while (test_bit(NVMET_PCI_EPF_Q_LIVE, &cq->flags) && ctrl->link_up) { @@ -1797,8 +1787,6 @@ static void nvmet_pci_epf_cq_work(struct work_struct *work) n++; } - nvmet_pci_epf_unmap_queue(ctrl, cq); - /* * We do not support precise IRQ coalescing time (100ns units as per * NVMe specifications). So if we have posted completion entries without @@ -1807,7 +1795,6 @@ static void nvmet_pci_epf_cq_work(struct work_struct *work) if (n) nvmet_pci_epf_raise_irq(ctrl, cq, true); -again: if (ret < 0) queue_delayed_work(system_highpri_wq, &cq->work, NVMET_PCI_EPF_CQ_RETRY_INTERVAL);
diff --git a/drivers/parport/ieee1284.c b/drivers/parport/ieee1284.c index 4547ac4..474515d 100644 --- a/drivers/parport/ieee1284.c +++ b/drivers/parport/ieee1284.c
@@ -73,7 +73,7 @@ int parport_wait_event (struct parport *port, signed long timeout) timer_setup(&port->timer, timeout_waiting_on_port, 0); mod_timer(&port->timer, jiffies + timeout); ret = down_interruptible (&port->physport->ieee1284.irq); - if (!del_timer_sync(&port->timer) && !ret) + if (!timer_delete_sync(&port->timer) && !ret) /* Timed out. */ ret = 1;
diff --git a/drivers/pci/hotplug/cpqphp_ctrl.c b/drivers/pci/hotplug/cpqphp_ctrl.c index c01968e..20529d1 100644 --- a/drivers/pci/hotplug/cpqphp_ctrl.c +++ b/drivers/pci/hotplug/cpqphp_ctrl.c
@@ -1794,7 +1794,7 @@ static void interrupt_event_handler(struct controller *ctrl) } else if (ctrl->event_queue[loop].event_type == INT_BUTTON_CANCEL) { dbg("button cancel\n"); - del_timer(&p_slot->task_event); + timer_delete(&p_slot->task_event); mutex_lock(&ctrl->crit_sect);
diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c index bfbec7c..387b855 100644 --- a/drivers/pci/hotplug/shpchp_hpc.c +++ b/drivers/pci/hotplug/shpchp_hpc.c
@@ -564,7 +564,7 @@ void shpchp_release_ctlr(struct controller *ctrl) shpc_writel(ctrl, SERR_INTR_ENABLE, serr_int); if (shpchp_poll_mode) - del_timer(&ctrl->poll_timer); + timer_delete(&ctrl->poll_timer); else { free_irq(ctrl->pci_dev->irq, ctrl); pci_disable_msi(ctrl->pci_dev);
diff --git a/drivers/pcmcia/i82365.c b/drivers/pcmcia/i82365.c index 86a3578..1e464b9 100644 --- a/drivers/pcmcia/i82365.c +++ b/drivers/pcmcia/i82365.c
@@ -1324,7 +1324,7 @@ static void __exit exit_i82365(void) } platform_device_unregister(i82365_device); if (poll_interval != 0) - del_timer_sync(&poll_timer); + timer_delete_sync(&poll_timer); if (grab_irq != 0) free_irq(cs_irq, pcic_interrupt); for (i = 0; i < sockets; i++) {
diff --git a/drivers/pcmcia/soc_common.c b/drivers/pcmcia/soc_common.c index 1deb996..d361124 100644 --- a/drivers/pcmcia/soc_common.c +++ b/drivers/pcmcia/soc_common.c
@@ -766,7 +766,7 @@ EXPORT_SYMBOL(soc_pcmcia_init_one); void soc_pcmcia_remove_one(struct soc_pcmcia_socket *skt) { - del_timer_sync(&skt->poll_timer); + timer_delete_sync(&skt->poll_timer); pcmcia_unregister_socket(&skt->socket); @@ -865,7 +865,7 @@ int soc_pcmcia_add_one(struct soc_pcmcia_socket *skt) return ret; out_err_8: - del_timer_sync(&skt->poll_timer); + timer_delete_sync(&skt->poll_timer); pcmcia_unregister_socket(&skt->socket); out_err_7:
diff --git a/drivers/pcmcia/tcic.c b/drivers/pcmcia/tcic.c index 5ef8886..060aed0 100644 --- a/drivers/pcmcia/tcic.c +++ b/drivers/pcmcia/tcic.c
@@ -509,7 +509,7 @@ static void __exit exit_tcic(void) { int i; - del_timer_sync(&poll_timer); + timer_delete_sync(&poll_timer); if (cs_irq != 0) { tcic_aux_setw(TCIC_AUX_SYSCFG, TCIC_SYSCFG_AUTOBUSY|0x0a00); free_irq(cs_irq, tcic_interrupt);
diff --git a/drivers/platform/mellanox/mlxbf-tmfifo.c b/drivers/platform/mellanox/mlxbf-tmfifo.c index 300cdaa..aae99ad 100644 --- a/drivers/platform/mellanox/mlxbf-tmfifo.c +++ b/drivers/platform/mellanox/mlxbf-tmfifo.c
@@ -1320,7 +1320,7 @@ static void mlxbf_tmfifo_cleanup(struct mlxbf_tmfifo *fifo) int i; fifo->is_ready = false; - del_timer_sync(&fifo->timer); + timer_delete_sync(&fifo->timer); mlxbf_tmfifo_disable_irqs(fifo); cancel_work_sync(&fifo->work); for (i = 0; i < MLXBF_TMFIFO_VDEV_MAX; i++)
diff --git a/drivers/platform/x86/gigabyte-wmi.c b/drivers/platform/x86/gigabyte-wmi.c index f6ba88b..f42c856 100644 --- a/drivers/platform/x86/gigabyte-wmi.c +++ b/drivers/platform/x86/gigabyte-wmi.c
@@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* - * Copyright (C) 2021 Thomas Weißschuh <thomas@weissschuh.net> + * Copyright (C) 2021 Thomas Weißschuh <linux@weissschuh.net> */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt @@ -159,6 +159,6 @@ static struct wmi_driver gigabyte_wmi_driver = { module_wmi_driver(gigabyte_wmi_driver); MODULE_DEVICE_TABLE(wmi, gigabyte_wmi_id_table); -MODULE_AUTHOR("Thomas Weißschuh <thomas@weissschuh.net>"); +MODULE_AUTHOR("Thomas Weißschuh <linux@weissschuh.net>"); MODULE_DESCRIPTION("Gigabyte WMI temperature driver"); MODULE_LICENSE("GPL");
diff --git a/drivers/platform/x86/intel/speed_select_if/isst_if_common.c b/drivers/platform/x86/intel/speed_select_if/isst_if_common.c index dbcd308..31239a9 100644 --- a/drivers/platform/x86/intel/speed_select_if/isst_if_common.c +++ b/drivers/platform/x86/intel/speed_select_if/isst_if_common.c
@@ -84,7 +84,7 @@ static DECLARE_HASHTABLE(isst_hash, 8); static DEFINE_MUTEX(isst_hash_lock); static int isst_store_new_cmd(int cmd, u32 cpu, int mbox_cmd_type, u32 param, - u32 data) + u64 data) { struct isst_cmd *sst_cmd;
diff --git a/drivers/platform/x86/intel_ips.c b/drivers/platform/x86/intel_ips.c index 79a7b68..5d717b1 100644 --- a/drivers/platform/x86/intel_ips.c +++ b/drivers/platform/x86/intel_ips.c
@@ -1108,7 +1108,7 @@ static int ips_monitor(void *data) last_sample_period = 1; } while (!kthread_should_stop()); - del_timer_sync(&ips->timer); + timer_delete_sync(&ips->timer); dev_dbg(ips->dev, "ips-monitor thread stopped\n");
diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index 3197aaa..b52390f 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c
@@ -538,7 +538,7 @@ static void sony_laptop_remove_input(void) if (!atomic_dec_and_test(&sony_laptop_input.users)) return; - del_timer_sync(&sony_laptop_input.release_key_timer); + timer_delete_sync(&sony_laptop_input.release_key_timer); /* * Generate key-up events for remaining keys. Note that we don't
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index 0384cf3..5790095 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -367,6 +367,7 @@ static struct { u32 beep_needs_two_args:1; u32 mixer_no_level_control:1; u32 battery_force_primary:1; + u32 platform_drv_registered:1; u32 hotkey_poll_active:1; u32 has_adaptive_kbd:1; u32 kbd_lang:1; @@ -8793,6 +8794,7 @@ static const struct attribute_group fan_driver_attr_group = { #define TPACPI_FAN_NS 0x0010 /* For EC with non-Standard register addresses */ #define TPACPI_FAN_DECRPM 0x0020 /* For ECFW's with RPM in register as decimal */ #define TPACPI_FAN_TPR 0x0040 /* Fan speed is in Ticks Per Revolution */ +#define TPACPI_FAN_NOACPI 0x0080 /* Don't use ACPI methods even if detected */ static const struct tpacpi_quirk fan_quirk_table[] __initconst = { TPACPI_QEC_IBM('1', 'Y', TPACPI_FAN_Q1), @@ -8823,6 +8825,9 @@ static const struct tpacpi_quirk fan_quirk_table[] __initconst = { TPACPI_Q_LNV3('N', '1', 'O', TPACPI_FAN_NOFAN), /* X1 Tablet (2nd gen) */ TPACPI_Q_LNV3('R', '0', 'Q', TPACPI_FAN_DECRPM),/* L480 */ TPACPI_Q_LNV('8', 'F', TPACPI_FAN_TPR), /* ThinkPad x120e */ + TPACPI_Q_LNV3('R', '0', '0', TPACPI_FAN_NOACPI),/* E560 */ + TPACPI_Q_LNV3('R', '1', '2', TPACPI_FAN_NOACPI),/* T495 */ + TPACPI_Q_LNV3('R', '1', '3', TPACPI_FAN_NOACPI),/* T495s */ }; static int __init fan_init(struct ibm_init_struct *iibm) @@ -8874,6 +8879,13 @@ static int __init fan_init(struct ibm_init_struct *iibm) tp_features.fan_ctrl_status_undef = 1; } + if (quirks & TPACPI_FAN_NOACPI) { + /* E560, T495, T495s */ + pr_info("Ignoring buggy ACPI fan access method\n"); + fang_handle = NULL; + fanw_handle = NULL; + } + if (gfan_handle) { /* 570, 600e/x, 770e, 770x */ fan_status_access_mode = TPACPI_FAN_RD_ACPI_GFAN; @@ -11820,10 +11832,10 @@ static void thinkpad_acpi_module_exit(void) platform_device_unregister(tpacpi_sensors_pdev); } - if (tpacpi_pdev) { + if (tp_features.platform_drv_registered) platform_driver_unregister(&tpacpi_pdriver); + if (tpacpi_pdev) platform_device_unregister(tpacpi_pdev); - } if (proc_dir) remove_proc_entry(TPACPI_PROC_DIR, acpi_root_dir); @@ -11893,9 +11905,8 @@ static int __init tpacpi_pdriver_probe(struct platform_device *pdev) static int __init tpacpi_hwmon_pdriver_probe(struct platform_device *pdev) { - tpacpi_hwmon = devm_hwmon_device_register_with_groups( - &tpacpi_sensors_pdev->dev, TPACPI_NAME, NULL, tpacpi_hwmon_groups); - + tpacpi_hwmon = devm_hwmon_device_register_with_groups(&pdev->dev, TPACPI_NAME, + NULL, tpacpi_hwmon_groups); if (IS_ERR(tpacpi_hwmon)) pr_err("unable to register hwmon device\n"); @@ -11965,16 +11976,24 @@ static int __init thinkpad_acpi_module_init(void) tp_features.quirks = dmi_id->driver_data; /* Device initialization */ - tpacpi_pdev = platform_create_bundle(&tpacpi_pdriver, tpacpi_pdriver_probe, - NULL, 0, NULL, 0); + tpacpi_pdev = platform_device_register_simple(TPACPI_DRVR_NAME, PLATFORM_DEVID_NONE, + NULL, 0); if (IS_ERR(tpacpi_pdev)) { ret = PTR_ERR(tpacpi_pdev); tpacpi_pdev = NULL; - pr_err("unable to register platform device/driver bundle\n"); + pr_err("unable to register platform device\n"); thinkpad_acpi_module_exit(); return ret; } + ret = platform_driver_probe(&tpacpi_pdriver, tpacpi_pdriver_probe); + if (ret) { + pr_err("unable to register main platform driver\n"); + thinkpad_acpi_module_exit(); + return ret; + } + tp_features.platform_drv_registered = 1; + tpacpi_sensors_pdev = platform_create_bundle(&tpacpi_hwmon_pdriver, tpacpi_hwmon_pdriver_probe, NULL, 0, NULL, 0);
diff --git a/drivers/pnp/isapnp/core.c b/drivers/pnp/isapnp/core.c index c43d8ad..d2ff76e 100644 --- a/drivers/pnp/isapnp/core.c +++ b/drivers/pnp/isapnp/core.c
@@ -843,6 +843,7 @@ EXPORT_SYMBOL(isapnp_protocol); EXPORT_SYMBOL(isapnp_present); EXPORT_SYMBOL(isapnp_cfg_begin); EXPORT_SYMBOL(isapnp_cfg_end); +EXPORT_SYMBOL(isapnp_read_byte); EXPORT_SYMBOL(isapnp_write_byte); static int isapnp_get_resources(struct pnp_dev *dev)
diff --git a/drivers/pps/clients/pps-gpio.c b/drivers/pps/clients/pps-gpio.c index 75c1bae3..374ceef 100644 --- a/drivers/pps/clients/pps-gpio.c +++ b/drivers/pps/clients/pps-gpio.c
@@ -229,7 +229,7 @@ static void pps_gpio_remove(struct platform_device *pdev) struct pps_gpio_device_data *data = platform_get_drvdata(pdev); pps_unregister_source(data->pps); - del_timer_sync(&data->echo_timer); + timer_delete_sync(&data->echo_timer); /* reset echo pin in any case */ gpiod_set_value(data->echo_pin, 0); dev_info(&pdev->dev, "removed IRQ %d as PPS source\n", data->irq);
diff --git a/drivers/pps/clients/pps-ktimer.c b/drivers/pps/clients/pps-ktimer.c index 2f46554..121bd29 100644 --- a/drivers/pps/clients/pps-ktimer.c +++ b/drivers/pps/clients/pps-ktimer.c
@@ -58,7 +58,7 @@ static void __exit pps_ktimer_exit(void) { dev_dbg(&pps->dev, "ktimer PPS source unregistered\n"); - del_timer_sync(&ktimer); + timer_delete_sync(&ktimer); pps_unregister_source(pps); }
diff --git a/drivers/pps/generators/pps_gen-dummy.c b/drivers/pps/generators/pps_gen-dummy.c index 55de4ae..547fa7f 100644 --- a/drivers/pps/generators/pps_gen-dummy.c +++ b/drivers/pps/generators/pps_gen-dummy.c
@@ -52,7 +52,7 @@ static int pps_gen_dummy_enable(struct pps_gen_device *pps_gen, bool enable) if (enable) mod_timer(&ktimer, jiffies + get_random_delay()); else - del_timer_sync(&ktimer); + timer_delete_sync(&ktimer); return 0; } @@ -73,7 +73,7 @@ static const struct pps_gen_source_info pps_gen_dummy_info = { static void __exit pps_gen_dummy_exit(void) { - del_timer_sync(&ktimer); + timer_delete_sync(&ktimer); pps_gen_unregister_source(pps_gen); }
diff --git a/drivers/pps/generators/pps_gen_tio.c b/drivers/pps/generators/pps_gen_tio.c index 6c46b46..1d5ffe0 100644 --- a/drivers/pps/generators/pps_gen_tio.c +++ b/drivers/pps/generators/pps_gen_tio.c
@@ -227,8 +227,8 @@ static int pps_gen_tio_probe(struct platform_device *pdev) return PTR_ERR(tio->base); pps_tio_disable(tio); - hrtimer_init(&tio->timer, CLOCK_REALTIME, HRTIMER_MODE_ABS); - tio->timer.function = hrtimer_callback; + hrtimer_setup(&tio->timer, hrtimer_callback, CLOCK_REALTIME, + HRTIMER_MODE_ABS); spin_lock_init(&tio->lock); platform_set_drvdata(pdev, &tio);
diff --git a/drivers/ptp/ptp_ocp.c b/drivers/ptp/ptp_ocp.c index b25635c..7945c6b 100644 --- a/drivers/ptp/ptp_ocp.c +++ b/drivers/ptp/ptp_ocp.c
@@ -4499,7 +4499,7 @@ ptp_ocp_detach(struct ptp_ocp *bp) ptp_ocp_detach_sysfs(bp); ptp_ocp_attr_group_del(bp); if (timer_pending(&bp->watchdog)) - del_timer_sync(&bp->watchdog); + timer_delete_sync(&bp->watchdog); if (bp->ts0) ptp_ocp_unregister_ext(bp->ts0); if (bp->ts1)
diff --git a/drivers/regulator/rk808-regulator.c b/drivers/regulator/rk808-regulator.c index 7d82bd1..1e81424 100644 --- a/drivers/regulator/rk808-regulator.c +++ b/drivers/regulator/rk808-regulator.c
@@ -270,8 +270,8 @@ static const unsigned int rk817_buck1_4_ramp_table[] = { static int rk806_set_mode_dcdc(struct regulator_dev *rdev, unsigned int mode) { - int rid = rdev_get_id(rdev); - int ctr_bit, reg; + unsigned int rid = rdev_get_id(rdev); + unsigned int ctr_bit, reg; reg = RK806_POWER_FPWM_EN0 + rid / 8; ctr_bit = rid % 8;
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 0bbbf77..838bdc1 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig
@@ -1321,13 +1321,6 @@ If you say Y here you will get support for the RTC found on spear -config RTC_DRV_PCF50633 - depends on MFD_PCF50633 - tristate "NXP PCF50633 RTC" - help - If you say yes here you get support for the RTC subsystem of the - NXP PCF50633 used in embedded systems. - config RTC_DRV_AB8500 tristate "ST-Ericsson AB8500 RTC" depends on AB8500_CORE
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 489b4ab..31473b3 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile
@@ -126,7 +126,6 @@ obj-$(CONFIG_RTC_DRV_PCAP) += rtc-pcap.o obj-$(CONFIG_RTC_DRV_PCF2123) += rtc-pcf2123.o obj-$(CONFIG_RTC_DRV_PCF2127) += rtc-pcf2127.o -obj-$(CONFIG_RTC_DRV_PCF50633) += rtc-pcf50633.o obj-$(CONFIG_RTC_DRV_PCF85063) += rtc-pcf85063.o obj-$(CONFIG_RTC_DRV_PCF8523) += rtc-pcf8523.o obj-$(CONFIG_RTC_DRV_PCF85363) += rtc-pcf85363.o
diff --git a/drivers/rtc/dev.c b/drivers/rtc/dev.c index c4a3ab5..0eeae5b 100644 --- a/drivers/rtc/dev.c +++ b/drivers/rtc/dev.c
@@ -90,7 +90,7 @@ static int clear_uie(struct rtc_device *rtc) rtc->stop_uie_polling = 1; if (rtc->uie_timer_active) { spin_unlock_irq(&rtc->irq_lock); - del_timer_sync(&rtc->uie_timer); + timer_delete_sync(&rtc->uie_timer); spin_lock_irq(&rtc->irq_lock); rtc->uie_timer_active = 0; }
diff --git a/drivers/rtc/rtc-ab-eoz9.c b/drivers/rtc/rtc-ab-eoz9.c index d2b6048..de002f7 100644 --- a/drivers/rtc/rtc-ab-eoz9.c +++ b/drivers/rtc/rtc-ab-eoz9.c
@@ -426,29 +426,9 @@ static umode_t abeoz9_is_visible(const void *data, } } -static const u32 abeoz9_chip_config[] = { - HWMON_C_REGISTER_TZ, - 0 -}; - -static const struct hwmon_channel_info abeoz9_chip = { - .type = hwmon_chip, - .config = abeoz9_chip_config, -}; - -static const u32 abeoz9_temp_config[] = { - HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_MIN, - 0 -}; - -static const struct hwmon_channel_info abeoz9_temp = { - .type = hwmon_temp, - .config = abeoz9_temp_config, -}; - static const struct hwmon_channel_info * const abeoz9_info[] = { - &abeoz9_chip, - &abeoz9_temp, + HWMON_CHANNEL_INFO(chip, HWMON_C_REGISTER_TZ), + HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_MIN), NULL };
diff --git a/drivers/rtc/rtc-ab8500.c b/drivers/rtc/rtc-ab8500.c index 2dcda96..ed2b6b8 100644 --- a/drivers/rtc/rtc-ab8500.c +++ b/drivers/rtc/rtc-ab8500.c
@@ -361,7 +361,7 @@ static int ab8500_rtc_probe(struct platform_device *pdev) return -ENODEV; } - device_init_wakeup(&pdev->dev, true); + devm_device_init_wakeup(&pdev->dev); rtc = devm_rtc_allocate_device(&pdev->dev); if (IS_ERR(rtc)) @@ -375,7 +375,7 @@ static int ab8500_rtc_probe(struct platform_device *pdev) if (err < 0) return err; - dev_pm_set_wake_irq(&pdev->dev, irq); + devm_pm_set_wake_irq(&pdev->dev, irq); platform_set_drvdata(pdev, rtc); set_bit(RTC_FEATURE_ALARM_RES_MINUTE, rtc->features); @@ -392,18 +392,11 @@ static int ab8500_rtc_probe(struct platform_device *pdev) return devm_rtc_register_device(rtc); } -static void ab8500_rtc_remove(struct platform_device *pdev) -{ - dev_pm_clear_wake_irq(&pdev->dev); - device_init_wakeup(&pdev->dev, false); -} - static struct platform_driver ab8500_rtc_driver = { .driver = { .name = "ab8500-rtc", }, .probe = ab8500_rtc_probe, - .remove = ab8500_rtc_remove, .id_table = ab85xx_rtc_ids, };
diff --git a/drivers/rtc/rtc-aspeed.c b/drivers/rtc/rtc-aspeed.c index 880b015..0d0053b 100644 --- a/drivers/rtc/rtc-aspeed.c +++ b/drivers/rtc/rtc-aspeed.c
@@ -8,7 +8,6 @@ #include <linux/io.h> struct aspeed_rtc { - struct rtc_device *rtc_dev; void __iomem *base; }; @@ -85,6 +84,7 @@ static const struct rtc_class_ops aspeed_rtc_ops = { static int aspeed_rtc_probe(struct platform_device *pdev) { struct aspeed_rtc *rtc; + struct rtc_device *rtc_dev; rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL); if (!rtc) @@ -94,17 +94,17 @@ static int aspeed_rtc_probe(struct platform_device *pdev) if (IS_ERR(rtc->base)) return PTR_ERR(rtc->base); - rtc->rtc_dev = devm_rtc_allocate_device(&pdev->dev); - if (IS_ERR(rtc->rtc_dev)) - return PTR_ERR(rtc->rtc_dev); + rtc_dev = devm_rtc_allocate_device(&pdev->dev); + if (IS_ERR(rtc_dev)) + return PTR_ERR(rtc_dev); platform_set_drvdata(pdev, rtc); - rtc->rtc_dev->ops = &aspeed_rtc_ops; - rtc->rtc_dev->range_min = RTC_TIMESTAMP_BEGIN_1900; - rtc->rtc_dev->range_max = 38814989399LL; /* 3199-12-31 23:59:59 */ + rtc_dev->ops = &aspeed_rtc_ops; + rtc_dev->range_min = RTC_TIMESTAMP_BEGIN_1900; + rtc_dev->range_max = 38814989399LL; /* 3199-12-31 23:59:59 */ - return devm_rtc_register_device(rtc->rtc_dev); + return devm_rtc_register_device(rtc_dev); } static const struct of_device_id aspeed_rtc_match[] = {
diff --git a/drivers/rtc/rtc-cros-ec.c b/drivers/rtc/rtc-cros-ec.c index 865c2e8..e956505 100644 --- a/drivers/rtc/rtc-cros-ec.c +++ b/drivers/rtc/rtc-cros-ec.c
@@ -35,21 +35,18 @@ struct cros_ec_rtc { static int cros_ec_rtc_get(struct cros_ec_device *cros_ec, u32 command, u32 *response) { + DEFINE_RAW_FLEX(struct cros_ec_command, msg, data, + sizeof(struct ec_response_rtc)); int ret; - struct { - struct cros_ec_command msg; - struct ec_response_rtc data; - } __packed msg; - memset(&msg, 0, sizeof(msg)); - msg.msg.command = command; - msg.msg.insize = sizeof(msg.data); + msg->command = command; + msg->insize = sizeof(struct ec_response_rtc); - ret = cros_ec_cmd_xfer_status(cros_ec, &msg.msg); + ret = cros_ec_cmd_xfer_status(cros_ec, msg); if (ret < 0) return ret; - *response = msg.data.time; + *response = ((struct ec_response_rtc *)msg->data)->time; return 0; } @@ -57,18 +54,15 @@ static int cros_ec_rtc_get(struct cros_ec_device *cros_ec, u32 command, static int cros_ec_rtc_set(struct cros_ec_device *cros_ec, u32 command, u32 param) { + DEFINE_RAW_FLEX(struct cros_ec_command, msg, data, + sizeof(struct ec_response_rtc)); int ret; - struct { - struct cros_ec_command msg; - struct ec_response_rtc data; - } __packed msg; - memset(&msg, 0, sizeof(msg)); - msg.msg.command = command; - msg.msg.outsize = sizeof(msg.data); - msg.data.time = param; + msg->command = command; + msg->outsize = sizeof(struct ec_response_rtc); + ((struct ec_response_rtc *)msg->data)->time = param; - ret = cros_ec_cmd_xfer_status(cros_ec, &msg.msg); + ret = cros_ec_cmd_xfer_status(cros_ec, msg); if (ret < 0) return ret; return 0;
diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c index 872e0b6..5efbe69 100644 --- a/drivers/rtc/rtc-ds1307.c +++ b/drivers/rtc/rtc-ds1307.c
@@ -1807,10 +1807,8 @@ static int ds1307_probe(struct i2c_client *client) * For some variants, be sure alarms can trigger when we're * running on Vbackup (BBSQI/BBSQW) */ - if (want_irq || ds1307_can_wakeup_device) { + if (want_irq || ds1307_can_wakeup_device) regs[0] |= DS1337_BIT_INTCN | chip->bbsqi_bit; - regs[0] &= ~(DS1337_BIT_A2IE | DS1337_BIT_A1IE); - } regmap_write(ds1307->regmap, DS1337_REG_CONTROL, regs[0]);
diff --git a/drivers/rtc/rtc-ds1343.c b/drivers/rtc/rtc-ds1343.c index ed5a6ba..aa95007 100644 --- a/drivers/rtc/rtc-ds1343.c +++ b/drivers/rtc/rtc-ds1343.c
@@ -427,18 +427,13 @@ static int ds1343_probe(struct spi_device *spi) "unable to request irq for rtc ds1343\n"); } else { device_init_wakeup(&spi->dev, true); - dev_pm_set_wake_irq(&spi->dev, spi->irq); + devm_pm_set_wake_irq(&spi->dev, spi->irq); } } return 0; } -static void ds1343_remove(struct spi_device *spi) -{ - dev_pm_clear_wake_irq(&spi->dev); -} - #ifdef CONFIG_PM_SLEEP static int ds1343_suspend(struct device *dev) @@ -471,7 +466,6 @@ static struct spi_driver ds1343_driver = { .pm = &ds1343_pm, }, .probe = ds1343_probe, - .remove = ds1343_remove, .id_table = ds1343_id, };
diff --git a/drivers/rtc/rtc-ds2404.c b/drivers/rtc/rtc-ds2404.c index 3231fd9..217694e 100644 --- a/drivers/rtc/rtc-ds2404.c +++ b/drivers/rtc/rtc-ds2404.c
@@ -31,7 +31,6 @@ struct ds2404 { struct gpio_desc *rst_gpiod; struct gpio_desc *clk_gpiod; struct gpio_desc *dq_gpiod; - struct rtc_device *rtc; }; static int ds2404_gpio_map(struct ds2404 *chip, struct platform_device *pdev) @@ -182,6 +181,7 @@ static const struct rtc_class_ops ds2404_rtc_ops = { static int rtc_probe(struct platform_device *pdev) { struct ds2404 *chip; + struct rtc_device *rtc; int retval = -EBUSY; chip = devm_kzalloc(&pdev->dev, sizeof(struct ds2404), GFP_KERNEL); @@ -190,9 +190,9 @@ static int rtc_probe(struct platform_device *pdev) chip->dev = &pdev->dev; - chip->rtc = devm_rtc_allocate_device(&pdev->dev); - if (IS_ERR(chip->rtc)) - return PTR_ERR(chip->rtc); + rtc = devm_rtc_allocate_device(&pdev->dev); + if (IS_ERR(rtc)) + return PTR_ERR(rtc); retval = ds2404_gpio_map(chip, pdev); if (retval) @@ -200,10 +200,10 @@ static int rtc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, chip); - chip->rtc->ops = &ds2404_rtc_ops; - chip->rtc->range_max = U32_MAX; + rtc->ops = &ds2404_rtc_ops; + rtc->range_max = U32_MAX; - retval = devm_rtc_register_device(chip->rtc); + retval = devm_rtc_register_device(rtc); if (retval) return retval;
diff --git a/drivers/rtc/rtc-ds3232.c b/drivers/rtc/rtc-ds3232.c index 19c09c4..18f3582 100644 --- a/drivers/rtc/rtc-ds3232.c +++ b/drivers/rtc/rtc-ds3232.c
@@ -339,29 +339,9 @@ static int ds3232_hwmon_read(struct device *dev, return err; } -static u32 ds3232_hwmon_chip_config[] = { - HWMON_C_REGISTER_TZ, - 0 -}; - -static const struct hwmon_channel_info ds3232_hwmon_chip = { - .type = hwmon_chip, - .config = ds3232_hwmon_chip_config, -}; - -static u32 ds3232_hwmon_temp_config[] = { - HWMON_T_INPUT, - 0 -}; - -static const struct hwmon_channel_info ds3232_hwmon_temp = { - .type = hwmon_temp, - .config = ds3232_hwmon_temp_config, -}; - static const struct hwmon_channel_info * const ds3232_hwmon_info[] = { - &ds3232_hwmon_chip, - &ds3232_hwmon_temp, + HWMON_CHANNEL_INFO(chip, HWMON_C_REGISTER_TZ), + HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT), NULL };
diff --git a/drivers/rtc/rtc-ep93xx.c b/drivers/rtc/rtc-ep93xx.c index 1fdd20d..dcdcdd0 100644 --- a/drivers/rtc/rtc-ep93xx.c +++ b/drivers/rtc/rtc-ep93xx.c
@@ -28,7 +28,6 @@ struct ep93xx_rtc { void __iomem *mmio_base; - struct rtc_device *rtc; }; static int ep93xx_rtc_get_swcomp(struct device *dev, unsigned short *preload, @@ -123,6 +122,7 @@ static const struct attribute_group ep93xx_rtc_sysfs_files = { static int ep93xx_rtc_probe(struct platform_device *pdev) { struct ep93xx_rtc *ep93xx_rtc; + struct rtc_device *rtc; int err; ep93xx_rtc = devm_kzalloc(&pdev->dev, sizeof(*ep93xx_rtc), GFP_KERNEL); @@ -135,18 +135,18 @@ static int ep93xx_rtc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, ep93xx_rtc); - ep93xx_rtc->rtc = devm_rtc_allocate_device(&pdev->dev); - if (IS_ERR(ep93xx_rtc->rtc)) - return PTR_ERR(ep93xx_rtc->rtc); + rtc = devm_rtc_allocate_device(&pdev->dev); + if (IS_ERR(rtc)) + return PTR_ERR(rtc); - ep93xx_rtc->rtc->ops = &ep93xx_rtc_ops; - ep93xx_rtc->rtc->range_max = U32_MAX; + rtc->ops = &ep93xx_rtc_ops; + rtc->range_max = U32_MAX; - err = rtc_add_group(ep93xx_rtc->rtc, &ep93xx_rtc_sysfs_files); + err = rtc_add_group(rtc, &ep93xx_rtc_sysfs_files); if (err) return err; - return devm_rtc_register_device(ep93xx_rtc->rtc); + return devm_rtc_register_device(rtc); } static const struct of_device_id ep93xx_rtc_of_ids[] = {
diff --git a/drivers/rtc/rtc-fsl-ftm-alarm.c b/drivers/rtc/rtc-fsl-ftm-alarm.c index a72c4ad..c8015f0 100644 --- a/drivers/rtc/rtc-fsl-ftm-alarm.c +++ b/drivers/rtc/rtc-fsl-ftm-alarm.c
@@ -309,7 +309,7 @@ static const struct of_device_id ftm_rtc_match[] = { }; MODULE_DEVICE_TABLE(of, ftm_rtc_match); -static const struct acpi_device_id ftm_imx_acpi_ids[] = { +static const struct acpi_device_id ftm_imx_acpi_ids[] __maybe_unused = { {"NXP0014",}, { } };
diff --git a/drivers/rtc/rtc-ftrtc010.c b/drivers/rtc/rtc-ftrtc010.c index cb4a5d1..02608d3 100644 --- a/drivers/rtc/rtc-ftrtc010.c +++ b/drivers/rtc/rtc-ftrtc010.c
@@ -28,7 +28,6 @@ MODULE_LICENSE("GPL"); MODULE_ALIAS("platform:" DRV_NAME); struct ftrtc010_rtc { - struct rtc_device *rtc_dev; void __iomem *rtc_base; int rtc_irq; struct clk *pclk; @@ -113,6 +112,7 @@ static int ftrtc010_rtc_probe(struct platform_device *pdev) struct ftrtc010_rtc *rtc; struct device *dev = &pdev->dev; struct resource *res; + struct rtc_device *rtc_dev; int ret; rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL); @@ -160,29 +160,28 @@ static int ftrtc010_rtc_probe(struct platform_device *pdev) goto err_disable_extclk; } - rtc->rtc_dev = devm_rtc_allocate_device(dev); - if (IS_ERR(rtc->rtc_dev)) { - ret = PTR_ERR(rtc->rtc_dev); + rtc_dev = devm_rtc_allocate_device(dev); + if (IS_ERR(rtc_dev)) { + ret = PTR_ERR(rtc_dev); goto err_disable_extclk; } - rtc->rtc_dev->ops = &ftrtc010_rtc_ops; + rtc_dev->ops = &ftrtc010_rtc_ops; sec = readl(rtc->rtc_base + FTRTC010_RTC_SECOND); min = readl(rtc->rtc_base + FTRTC010_RTC_MINUTE); hour = readl(rtc->rtc_base + FTRTC010_RTC_HOUR); days = readl(rtc->rtc_base + FTRTC010_RTC_DAYS); - rtc->rtc_dev->range_min = (u64)days * 86400 + hour * 3600 + - min * 60 + sec; - rtc->rtc_dev->range_max = U32_MAX + rtc->rtc_dev->range_min; + rtc_dev->range_min = (u64)days * 86400 + hour * 3600 + min * 60 + sec; + rtc_dev->range_max = U32_MAX + rtc_dev->range_min; ret = devm_request_irq(dev, rtc->rtc_irq, ftrtc010_rtc_interrupt, IRQF_SHARED, pdev->name, dev); if (unlikely(ret)) goto err_disable_extclk; - return devm_rtc_register_device(rtc->rtc_dev); + return devm_rtc_register_device(rtc_dev); err_disable_extclk: clk_disable_unprepare(rtc->extclk);
diff --git a/drivers/rtc/rtc-m48t86.c b/drivers/rtc/rtc-m48t86.c index dd4a62e..10cd054 100644 --- a/drivers/rtc/rtc-m48t86.c +++ b/drivers/rtc/rtc-m48t86.c
@@ -41,7 +41,6 @@ struct m48t86_rtc_info { void __iomem *index_reg; void __iomem *data_reg; - struct rtc_device *rtc; }; static unsigned char m48t86_readb(struct device *dev, unsigned long addr) @@ -219,6 +218,7 @@ static bool m48t86_verify_chip(struct platform_device *pdev) static int m48t86_rtc_probe(struct platform_device *pdev) { struct m48t86_rtc_info *info; + struct rtc_device *rtc; unsigned char reg; int err; struct nvmem_config m48t86_nvmem_cfg = { @@ -250,17 +250,17 @@ static int m48t86_rtc_probe(struct platform_device *pdev) return -ENODEV; } - info->rtc = devm_rtc_allocate_device(&pdev->dev); - if (IS_ERR(info->rtc)) - return PTR_ERR(info->rtc); + rtc = devm_rtc_allocate_device(&pdev->dev); + if (IS_ERR(rtc)) + return PTR_ERR(rtc); - info->rtc->ops = &m48t86_rtc_ops; + rtc->ops = &m48t86_rtc_ops; - err = devm_rtc_register_device(info->rtc); + err = devm_rtc_register_device(rtc); if (err) return err; - devm_rtc_nvmem_register(info->rtc, &m48t86_nvmem_cfg); + devm_rtc_nvmem_register(rtc, &m48t86_nvmem_cfg); /* read battery status */ reg = m48t86_readb(&pdev->dev, M48T86_D);
diff --git a/drivers/rtc/rtc-max31335.c b/drivers/rtc/rtc-max31335.c index 3fbcf5f..a7bb37a 100644 --- a/drivers/rtc/rtc-max31335.c +++ b/drivers/rtc/rtc-max31335.c
@@ -184,31 +184,91 @@ #define MAX31335_RAM_SIZE 32 #define MAX31335_TIME_SIZE 0x07 +/* MAX31331 Register Map */ +#define MAX31331_RTC_CONFIG2 0x04 + #define clk_hw_to_max31335(_hw) container_of(_hw, struct max31335_data, clkout) +/* Supported Maxim RTC */ +enum max_rtc_ids { + ID_MAX31331, + ID_MAX31335, + MAX_RTC_ID_NR +}; + +struct chip_desc { + u8 sec_reg; + u8 alarm1_sec_reg; + + u8 int_en_reg; + u8 int_status_reg; + + u8 ram_reg; + u8 ram_size; + + u8 temp_reg; + + u8 trickle_reg; + + u8 clkout_reg; + + enum max_rtc_ids id; +}; + struct max31335_data { struct regmap *regmap; struct rtc_device *rtc; struct clk_hw clkout; + struct clk *clkin; + const struct chip_desc *chip; + int irq; }; static const int max31335_clkout_freq[] = { 1, 64, 1024, 32768 }; +static const struct chip_desc chip[MAX_RTC_ID_NR] = { + [ID_MAX31331] = { + .id = ID_MAX31331, + .int_en_reg = 0x01, + .int_status_reg = 0x00, + .sec_reg = 0x08, + .alarm1_sec_reg = 0x0F, + .ram_reg = 0x20, + .ram_size = 32, + .trickle_reg = 0x1B, + .clkout_reg = 0x04, + }, + [ID_MAX31335] = { + .id = ID_MAX31335, + .int_en_reg = 0x01, + .int_status_reg = 0x00, + .sec_reg = 0x0A, + .alarm1_sec_reg = 0x11, + .ram_reg = 0x40, + .ram_size = 32, + .temp_reg = 0x35, + .trickle_reg = 0x1D, + .clkout_reg = 0x06, + }, +}; + static const u16 max31335_trickle_resistors[] = {3000, 6000, 11000}; static bool max31335_volatile_reg(struct device *dev, unsigned int reg) { + struct max31335_data *max31335 = dev_get_drvdata(dev); + const struct chip_desc *chip = max31335->chip; + /* time keeping registers */ - if (reg >= MAX31335_SECONDS && - reg < MAX31335_SECONDS + MAX31335_TIME_SIZE) + if (reg >= chip->sec_reg && reg < chip->sec_reg + MAX31335_TIME_SIZE) return true; /* interrupt status register */ - if (reg == MAX31335_STATUS1) + if (reg == chip->int_status_reg) return true; - /* temperature registers */ - if (reg == MAX31335_TEMP_DATA_MSB || reg == MAX31335_TEMP_DATA_LSB) + /* temperature registers if valid */ + if (chip->temp_reg && (reg == chip->temp_reg || reg == chip->temp_reg + 1)) return true; return false; @@ -227,7 +287,7 @@ static int max31335_read_time(struct device *dev, struct rtc_time *tm) u8 date[7]; int ret; - ret = regmap_bulk_read(max31335->regmap, MAX31335_SECONDS, date, + ret = regmap_bulk_read(max31335->regmap, max31335->chip->sec_reg, date, sizeof(date)); if (ret) return ret; @@ -262,7 +322,7 @@ static int max31335_set_time(struct device *dev, struct rtc_time *tm) if (tm->tm_year >= 200) date[5] |= FIELD_PREP(MAX31335_MONTH_CENTURY, 1); - return regmap_bulk_write(max31335->regmap, MAX31335_SECONDS, date, + return regmap_bulk_write(max31335->regmap, max31335->chip->sec_reg, date, sizeof(date)); } @@ -273,7 +333,7 @@ static int max31335_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) struct rtc_time time; u8 regs[6]; - ret = regmap_bulk_read(max31335->regmap, MAX31335_ALM1_SEC, regs, + ret = regmap_bulk_read(max31335->regmap, max31335->chip->alarm1_sec_reg, regs, sizeof(regs)); if (ret) return ret; @@ -292,11 +352,11 @@ static int max31335_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) if (time.tm_year >= 200) alrm->time.tm_year += 100; - ret = regmap_read(max31335->regmap, MAX31335_INT_EN1, &ctrl); + ret = regmap_read(max31335->regmap, max31335->chip->int_en_reg, &ctrl); if (ret) return ret; - ret = regmap_read(max31335->regmap, MAX31335_STATUS1, &status); + ret = regmap_read(max31335->regmap, max31335->chip->int_status_reg, &status); if (ret) return ret; @@ -320,18 +380,18 @@ static int max31335_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) regs[4] = bin2bcd(alrm->time.tm_mon + 1); regs[5] = bin2bcd(alrm->time.tm_year % 100); - ret = regmap_bulk_write(max31335->regmap, MAX31335_ALM1_SEC, + ret = regmap_bulk_write(max31335->regmap, max31335->chip->alarm1_sec_reg, regs, sizeof(regs)); if (ret) return ret; reg = FIELD_PREP(MAX31335_INT_EN1_A1IE, alrm->enabled); - ret = regmap_update_bits(max31335->regmap, MAX31335_INT_EN1, + ret = regmap_update_bits(max31335->regmap, max31335->chip->int_en_reg, MAX31335_INT_EN1_A1IE, reg); if (ret) return ret; - ret = regmap_update_bits(max31335->regmap, MAX31335_STATUS1, + ret = regmap_update_bits(max31335->regmap, max31335->chip->int_status_reg, MAX31335_STATUS1_A1F, 0); return 0; @@ -341,23 +401,33 @@ static int max31335_alarm_irq_enable(struct device *dev, unsigned int enabled) { struct max31335_data *max31335 = dev_get_drvdata(dev); - return regmap_update_bits(max31335->regmap, MAX31335_INT_EN1, + return regmap_update_bits(max31335->regmap, max31335->chip->int_en_reg, MAX31335_INT_EN1_A1IE, enabled); } static irqreturn_t max31335_handle_irq(int irq, void *dev_id) { struct max31335_data *max31335 = dev_id; - bool status; - int ret; + struct mutex *lock = &max31335->rtc->ops_lock; + int ret, status; - ret = regmap_update_bits_check(max31335->regmap, MAX31335_STATUS1, - MAX31335_STATUS1_A1F, 0, &status); + mutex_lock(lock); + + ret = regmap_read(max31335->regmap, max31335->chip->int_status_reg, &status); if (ret) - return IRQ_HANDLED; + goto exit; - if (status) + if (FIELD_GET(MAX31335_STATUS1_A1F, status)) { + ret = regmap_update_bits(max31335->regmap, max31335->chip->int_status_reg, + MAX31335_STATUS1_A1F, 0); + if (ret) + goto exit; + rtc_update_irq(max31335->rtc, 1, RTC_AF | RTC_IRQF); + } + +exit: + mutex_unlock(lock); return IRQ_HANDLED; } @@ -404,7 +474,7 @@ static int max31335_trickle_charger_setup(struct device *dev, i = i + trickle_cfg; - return regmap_write(max31335->regmap, MAX31335_TRICKLE_REG, + return regmap_write(max31335->regmap, max31335->chip->trickle_reg, FIELD_PREP(MAX31335_TRICKLE_REG_TRICKLE, i) | FIELD_PREP(MAX31335_TRICKLE_REG_EN_TRICKLE, chargeable)); @@ -418,7 +488,7 @@ static unsigned long max31335_clkout_recalc_rate(struct clk_hw *hw, unsigned int reg; int ret; - ret = regmap_read(max31335->regmap, MAX31335_RTC_CONFIG2, ®); + ret = regmap_read(max31335->regmap, max31335->chip->clkout_reg, ®); if (ret) return 0; @@ -449,23 +519,23 @@ static int max31335_clkout_set_rate(struct clk_hw *hw, unsigned long rate, ARRAY_SIZE(max31335_clkout_freq)); freq_mask = __roundup_pow_of_two(ARRAY_SIZE(max31335_clkout_freq)) - 1; - return regmap_update_bits(max31335->regmap, MAX31335_RTC_CONFIG2, - freq_mask, index); + return regmap_update_bits(max31335->regmap, max31335->chip->clkout_reg, + freq_mask, index); } static int max31335_clkout_enable(struct clk_hw *hw) { struct max31335_data *max31335 = clk_hw_to_max31335(hw); - return regmap_set_bits(max31335->regmap, MAX31335_RTC_CONFIG2, - MAX31335_RTC_CONFIG2_ENCLKO); + return regmap_set_bits(max31335->regmap, max31335->chip->clkout_reg, + MAX31335_RTC_CONFIG2_ENCLKO); } static void max31335_clkout_disable(struct clk_hw *hw) { struct max31335_data *max31335 = clk_hw_to_max31335(hw); - regmap_clear_bits(max31335->regmap, MAX31335_RTC_CONFIG2, + regmap_clear_bits(max31335->regmap, max31335->chip->clkout_reg, MAX31335_RTC_CONFIG2_ENCLKO); } @@ -475,7 +545,7 @@ static int max31335_clkout_is_enabled(struct clk_hw *hw) unsigned int reg; int ret; - ret = regmap_read(max31335->regmap, MAX31335_RTC_CONFIG2, ®); + ret = regmap_read(max31335->regmap, max31335->chip->clkout_reg, ®); if (ret) return ret; @@ -500,7 +570,7 @@ static int max31335_nvmem_reg_read(void *priv, unsigned int offset, void *val, size_t bytes) { struct max31335_data *max31335 = priv; - unsigned int reg = MAX31335_TS0_SEC_1_128 + offset; + unsigned int reg = max31335->chip->ram_reg + offset; return regmap_bulk_read(max31335->regmap, reg, val, bytes); } @@ -509,7 +579,7 @@ static int max31335_nvmem_reg_write(void *priv, unsigned int offset, void *val, size_t bytes) { struct max31335_data *max31335 = priv; - unsigned int reg = MAX31335_TS0_SEC_1_128 + offset; + unsigned int reg = max31335->chip->ram_reg + offset; return regmap_bulk_write(max31335->regmap, reg, val, bytes); } @@ -533,7 +603,7 @@ static int max31335_read_temp(struct device *dev, enum hwmon_sensor_types type, if (type != hwmon_temp || attr != hwmon_temp_input) return -EOPNOTSUPP; - ret = regmap_bulk_read(max31335->regmap, MAX31335_TEMP_DATA_MSB, + ret = regmap_bulk_read(max31335->regmap, max31335->chip->temp_reg, reg, 2); if (ret) return ret; @@ -577,8 +647,8 @@ static int max31335_clkout_register(struct device *dev) int ret; if (!device_property_present(dev, "#clock-cells")) - return regmap_clear_bits(max31335->regmap, MAX31335_RTC_CONFIG2, - MAX31335_RTC_CONFIG2_ENCLKO); + return regmap_clear_bits(max31335->regmap, max31335->chip->clkout_reg, + MAX31335_RTC_CONFIG2_ENCLKO); max31335->clkout.init = &max31335_clk_init; @@ -605,6 +675,7 @@ static int max31335_probe(struct i2c_client *client) #if IS_REACHABLE(HWMON) struct device *hwmon; #endif + const struct chip_desc *match; int ret; max31335 = devm_kzalloc(&client->dev, sizeof(*max31335), GFP_KERNEL); @@ -616,7 +687,10 @@ static int max31335_probe(struct i2c_client *client) return PTR_ERR(max31335->regmap); i2c_set_clientdata(client, max31335); - + match = i2c_get_match_data(client); + if (!match) + return -ENODEV; + max31335->chip = match; max31335->rtc = devm_rtc_allocate_device(&client->dev); if (IS_ERR(max31335->rtc)) return PTR_ERR(max31335->rtc); @@ -639,6 +713,8 @@ static int max31335_probe(struct i2c_client *client) dev_warn(&client->dev, "unable to request IRQ, alarm max31335 disabled\n"); client->irq = 0; + } else { + max31335->irq = client->irq; } } @@ -652,13 +728,13 @@ static int max31335_probe(struct i2c_client *client) "cannot register rtc nvmem\n"); #if IS_REACHABLE(HWMON) - hwmon = devm_hwmon_device_register_with_info(&client->dev, client->name, - max31335, - &max31335_chip_info, - NULL); - if (IS_ERR(hwmon)) - return dev_err_probe(&client->dev, PTR_ERR(hwmon), - "cannot register hwmon device\n"); + if (max31335->chip->temp_reg) { + hwmon = devm_hwmon_device_register_with_info(&client->dev, client->name, max31335, + &max31335_chip_info, NULL); + if (IS_ERR(hwmon)) + return dev_err_probe(&client->dev, PTR_ERR(hwmon), + "cannot register hwmon device\n"); + } #endif ret = max31335_trickle_charger_setup(&client->dev, max31335); @@ -669,14 +745,16 @@ static int max31335_probe(struct i2c_client *client) } static const struct i2c_device_id max31335_id[] = { - { "max31335" }, + { "max31331", (kernel_ulong_t)&chip[ID_MAX31331] }, + { "max31335", (kernel_ulong_t)&chip[ID_MAX31335] }, { } }; MODULE_DEVICE_TABLE(i2c, max31335_id); static const struct of_device_id max31335_of_match[] = { - { .compatible = "adi,max31335" }, + { .compatible = "adi,max31331", .data = &chip[ID_MAX31331] }, + { .compatible = "adi,max31335", .data = &chip[ID_MAX31335] }, { } }; @@ -693,5 +771,6 @@ static struct i2c_driver max31335_driver = { module_i2c_driver(max31335_driver); MODULE_AUTHOR("Antoniu Miclaus <antoniu.miclaus@analog.com>"); +MODULE_AUTHOR("Saket Kumar Purwar <Saket.Kumarpurwar@analog.com>"); MODULE_DESCRIPTION("MAX31335 RTC driver"); MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-max77686.c b/drivers/rtc/rtc-max77686.c index 7bb044d..69ea3ce 100644 --- a/drivers/rtc/rtc-max77686.c +++ b/drivers/rtc/rtc-max77686.c
@@ -85,7 +85,6 @@ struct max77686_rtc_driver_data { struct max77686_rtc_info { struct device *dev; - struct i2c_client *rtc; struct rtc_device *rtc_dev; struct mutex lock; @@ -691,6 +690,7 @@ static int max77686_init_rtc_regmap(struct max77686_rtc_info *info) { struct device *parent = info->dev->parent; struct i2c_client *parent_i2c = to_i2c_client(parent); + struct i2c_client *client; int ret; if (info->drv_data->rtc_irq_from_platform) { @@ -704,40 +704,35 @@ static int max77686_init_rtc_regmap(struct max77686_rtc_info *info) } info->regmap = dev_get_regmap(parent, NULL); - if (!info->regmap) { - dev_err(info->dev, "Failed to get rtc regmap\n"); - return -ENODEV; - } + if (!info->regmap) + return dev_err_probe(info->dev, -ENODEV, + "Failed to get rtc regmap\n"); if (info->drv_data->rtc_i2c_addr == MAX77686_INVALID_I2C_ADDR) { info->rtc_regmap = info->regmap; goto add_rtc_irq; } - info->rtc = devm_i2c_new_dummy_device(info->dev, parent_i2c->adapter, - info->drv_data->rtc_i2c_addr); - if (IS_ERR(info->rtc)) { - dev_err(info->dev, "Failed to allocate I2C device for RTC\n"); - return PTR_ERR(info->rtc); - } + client = devm_i2c_new_dummy_device(info->dev, parent_i2c->adapter, + info->drv_data->rtc_i2c_addr); + if (IS_ERR(client)) + return dev_err_probe(info->dev, PTR_ERR(client), + "Failed to allocate I2C device for RTC\n"); - info->rtc_regmap = devm_regmap_init_i2c(info->rtc, + info->rtc_regmap = devm_regmap_init_i2c(client, info->drv_data->regmap_config); - if (IS_ERR(info->rtc_regmap)) { - ret = PTR_ERR(info->rtc_regmap); - dev_err(info->dev, "Failed to allocate RTC regmap: %d\n", ret); - return ret; - } + if (IS_ERR(info->rtc_regmap)) + return dev_err_probe(info->dev, PTR_ERR(info->rtc_regmap), + "Failed to allocate RTC regmap\n"); add_rtc_irq: ret = regmap_add_irq_chip(info->rtc_regmap, info->rtc_irq, IRQF_ONESHOT | IRQF_SHARED, 0, info->drv_data->rtc_irq_chip, &info->rtc_irq_data); - if (ret < 0) { - dev_err(info->dev, "Failed to add RTC irq chip: %d\n", ret); - return ret; - } + if (ret < 0) + return dev_err_probe(info->dev, ret, + "Failed to add RTC irq chip\n"); return 0; }
diff --git a/drivers/rtc/rtc-meson-vrtc.c b/drivers/rtc/rtc-meson-vrtc.c index 5849729..7d38258 100644 --- a/drivers/rtc/rtc-meson-vrtc.c +++ b/drivers/rtc/rtc-meson-vrtc.c
@@ -13,7 +13,6 @@ struct meson_vrtc_data { void __iomem *io_alarm; - struct rtc_device *rtc; unsigned long alarm_time; bool enabled; }; @@ -65,6 +64,7 @@ static const struct rtc_class_ops meson_vrtc_ops = { static int meson_vrtc_probe(struct platform_device *pdev) { struct meson_vrtc_data *vrtc; + struct rtc_device *rtc; vrtc = devm_kzalloc(&pdev->dev, sizeof(*vrtc), GFP_KERNEL); if (!vrtc) @@ -78,12 +78,12 @@ static int meson_vrtc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, vrtc); - vrtc->rtc = devm_rtc_allocate_device(&pdev->dev); - if (IS_ERR(vrtc->rtc)) - return PTR_ERR(vrtc->rtc); + rtc = devm_rtc_allocate_device(&pdev->dev); + if (IS_ERR(rtc)) + return PTR_ERR(rtc); - vrtc->rtc->ops = &meson_vrtc_ops; - return devm_rtc_register_device(vrtc->rtc); + rtc->ops = &meson_vrtc_ops; + return devm_rtc_register_device(rtc); } static int __maybe_unused meson_vrtc_suspend(struct device *dev)
diff --git a/drivers/rtc/rtc-meson.c b/drivers/rtc/rtc-meson.c index db1d626..47e9ebf 100644 --- a/drivers/rtc/rtc-meson.c +++ b/drivers/rtc/rtc-meson.c
@@ -59,7 +59,6 @@ #define MESON_STATIC_DEFAULT (MESON_STATIC_BIAS_CUR | MESON_STATIC_VOLTAGE) struct meson_rtc { - struct rtc_device *rtc; /* rtc device we created */ struct device *dev; /* device we bound from */ struct reset_control *reset; /* reset source */ struct regulator *vdd; /* voltage input */ @@ -292,6 +291,7 @@ static int meson_rtc_probe(struct platform_device *pdev) }; struct device *dev = &pdev->dev; struct meson_rtc *rtc; + struct rtc_device *rtc_dev; void __iomem *base; int ret; u32 tm; @@ -300,16 +300,16 @@ static int meson_rtc_probe(struct platform_device *pdev) if (!rtc) return -ENOMEM; - rtc->rtc = devm_rtc_allocate_device(dev); - if (IS_ERR(rtc->rtc)) - return PTR_ERR(rtc->rtc); + rtc_dev = devm_rtc_allocate_device(dev); + if (IS_ERR(rtc_dev)) + return PTR_ERR(rtc_dev); platform_set_drvdata(pdev, rtc); rtc->dev = dev; - rtc->rtc->ops = &meson_rtc_ops; - rtc->rtc->range_max = U32_MAX; + rtc_dev->ops = &meson_rtc_ops; + rtc_dev->range_max = U32_MAX; base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(base)) @@ -365,11 +365,11 @@ static int meson_rtc_probe(struct platform_device *pdev) } meson_rtc_nvmem_config.priv = rtc; - ret = devm_rtc_nvmem_register(rtc->rtc, &meson_rtc_nvmem_config); + ret = devm_rtc_nvmem_register(rtc_dev, &meson_rtc_nvmem_config); if (ret) goto out_disable_vdd; - ret = devm_rtc_register_device(rtc->rtc); + ret = devm_rtc_register_device(rtc_dev); if (ret) goto out_disable_vdd;
diff --git a/drivers/rtc/rtc-mpfs.c b/drivers/rtc/rtc-mpfs.c index 3892b0f..6aa3eae 100644 --- a/drivers/rtc/rtc-mpfs.c +++ b/drivers/rtc/rtc-mpfs.c
@@ -266,19 +266,14 @@ static int mpfs_rtc_probe(struct platform_device *pdev) writel(prescaler, rtcdev->base + PRESCALER_REG); dev_info(&pdev->dev, "prescaler set to: %lu\n", prescaler); - device_init_wakeup(&pdev->dev, true); - ret = dev_pm_set_wake_irq(&pdev->dev, wakeup_irq); + devm_device_init_wakeup(&pdev->dev); + ret = devm_pm_set_wake_irq(&pdev->dev, wakeup_irq); if (ret) dev_err(&pdev->dev, "failed to enable irq wake\n"); return devm_rtc_register_device(rtcdev->rtc); } -static void mpfs_rtc_remove(struct platform_device *pdev) -{ - dev_pm_clear_wake_irq(&pdev->dev); -} - static const struct of_device_id mpfs_rtc_of_match[] = { { .compatible = "microchip,mpfs-rtc" }, { } @@ -288,7 +283,6 @@ MODULE_DEVICE_TABLE(of, mpfs_rtc_of_match); static struct platform_driver mpfs_rtc_driver = { .probe = mpfs_rtc_probe, - .remove = mpfs_rtc_remove, .driver = { .name = "mpfs_rtc", .of_match_table = mpfs_rtc_of_match,
diff --git a/drivers/rtc/rtc-nxp-bbnsm.c b/drivers/rtc/rtc-nxp-bbnsm.c index fa3b032..d4fc9dc5 100644 --- a/drivers/rtc/rtc-nxp-bbnsm.c +++ b/drivers/rtc/rtc-nxp-bbnsm.c
@@ -189,36 +189,26 @@ static int bbnsm_rtc_probe(struct platform_device *pdev) /* clear all the pending events */ regmap_write(bbnsm->regmap, BBNSM_EVENTS, 0x7A); - device_init_wakeup(&pdev->dev, true); - dev_pm_set_wake_irq(&pdev->dev, bbnsm->irq); + ret = devm_device_init_wakeup(&pdev->dev); + if (ret) + dev_err(&pdev->dev, "failed to init wakeup, %d\n", ret); + + ret = devm_pm_set_wake_irq(&pdev->dev, bbnsm->irq); + if (ret) + dev_err(&pdev->dev, "failed to set wake irq, %d\n", ret); ret = devm_request_irq(&pdev->dev, bbnsm->irq, bbnsm_rtc_irq_handler, IRQF_SHARED, "rtc alarm", &pdev->dev); if (ret) { dev_err(&pdev->dev, "failed to request irq %d: %d\n", bbnsm->irq, ret); - goto err; + return ret; } bbnsm->rtc->ops = &bbnsm_rtc_ops; bbnsm->rtc->range_max = U32_MAX; - ret = devm_rtc_register_device(bbnsm->rtc); - if (ret) - goto err; - - return 0; - -err: - dev_pm_clear_wake_irq(&pdev->dev); - device_init_wakeup(&pdev->dev, false); - return ret; -} - -static void bbnsm_rtc_remove(struct platform_device *pdev) -{ - dev_pm_clear_wake_irq(&pdev->dev); - device_init_wakeup(&pdev->dev, false); + return devm_rtc_register_device(bbnsm->rtc); } static const struct of_device_id bbnsm_dt_ids[] = { @@ -233,7 +223,6 @@ static struct platform_driver bbnsm_rtc_driver = { .of_match_table = bbnsm_dt_ids, }, .probe = bbnsm_rtc_probe, - .remove = bbnsm_rtc_remove, }; module_platform_driver(bbnsm_rtc_driver);
diff --git a/drivers/rtc/rtc-pcf50633.c b/drivers/rtc/rtc-pcf50633.c deleted file mode 100644 index c019c4d..0000000 --- a/drivers/rtc/rtc-pcf50633.c +++ /dev/null
@@ -1,284 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* NXP PCF50633 RTC Driver - * - * (C) 2006-2008 by Openmoko, Inc. - * Author: Balaji Rao <balajirrao@openmoko.org> - * All rights reserved. - * - * Broken down from monstrous PCF50633 driver mainly by - * Harald Welte, Andy Green and Werner Almesberger - */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/init.h> -#include <linux/device.h> -#include <linux/slab.h> -#include <linux/platform_device.h> -#include <linux/rtc.h> -#include <linux/bcd.h> -#include <linux/err.h> - -#include <linux/mfd/pcf50633/core.h> - -#define PCF50633_REG_RTCSC 0x59 /* Second */ -#define PCF50633_REG_RTCMN 0x5a /* Minute */ -#define PCF50633_REG_RTCHR 0x5b /* Hour */ -#define PCF50633_REG_RTCWD 0x5c /* Weekday */ -#define PCF50633_REG_RTCDT 0x5d /* Day */ -#define PCF50633_REG_RTCMT 0x5e /* Month */ -#define PCF50633_REG_RTCYR 0x5f /* Year */ -#define PCF50633_REG_RTCSCA 0x60 /* Alarm Second */ -#define PCF50633_REG_RTCMNA 0x61 /* Alarm Minute */ -#define PCF50633_REG_RTCHRA 0x62 /* Alarm Hour */ -#define PCF50633_REG_RTCWDA 0x63 /* Alarm Weekday */ -#define PCF50633_REG_RTCDTA 0x64 /* Alarm Day */ -#define PCF50633_REG_RTCMTA 0x65 /* Alarm Month */ -#define PCF50633_REG_RTCYRA 0x66 /* Alarm Year */ - -enum pcf50633_time_indexes { - PCF50633_TI_SEC, - PCF50633_TI_MIN, - PCF50633_TI_HOUR, - PCF50633_TI_WKDAY, - PCF50633_TI_DAY, - PCF50633_TI_MONTH, - PCF50633_TI_YEAR, - PCF50633_TI_EXTENT /* always last */ -}; - -struct pcf50633_time { - u_int8_t time[PCF50633_TI_EXTENT]; -}; - -struct pcf50633_rtc { - int alarm_enabled; - int alarm_pending; - - struct pcf50633 *pcf; - struct rtc_device *rtc_dev; -}; - -static void pcf2rtc_time(struct rtc_time *rtc, struct pcf50633_time *pcf) -{ - rtc->tm_sec = bcd2bin(pcf->time[PCF50633_TI_SEC]); - rtc->tm_min = bcd2bin(pcf->time[PCF50633_TI_MIN]); - rtc->tm_hour = bcd2bin(pcf->time[PCF50633_TI_HOUR]); - rtc->tm_wday = bcd2bin(pcf->time[PCF50633_TI_WKDAY]); - rtc->tm_mday = bcd2bin(pcf->time[PCF50633_TI_DAY]); - rtc->tm_mon = bcd2bin(pcf->time[PCF50633_TI_MONTH]) - 1; - rtc->tm_year = bcd2bin(pcf->time[PCF50633_TI_YEAR]) + 100; -} - -static void rtc2pcf_time(struct pcf50633_time *pcf, struct rtc_time *rtc) -{ - pcf->time[PCF50633_TI_SEC] = bin2bcd(rtc->tm_sec); - pcf->time[PCF50633_TI_MIN] = bin2bcd(rtc->tm_min); - pcf->time[PCF50633_TI_HOUR] = bin2bcd(rtc->tm_hour); - pcf->time[PCF50633_TI_WKDAY] = bin2bcd(rtc->tm_wday); - pcf->time[PCF50633_TI_DAY] = bin2bcd(rtc->tm_mday); - pcf->time[PCF50633_TI_MONTH] = bin2bcd(rtc->tm_mon + 1); - pcf->time[PCF50633_TI_YEAR] = bin2bcd(rtc->tm_year % 100); -} - -static int -pcf50633_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) -{ - struct pcf50633_rtc *rtc = dev_get_drvdata(dev); - int err; - - if (enabled) - err = pcf50633_irq_unmask(rtc->pcf, PCF50633_IRQ_ALARM); - else - err = pcf50633_irq_mask(rtc->pcf, PCF50633_IRQ_ALARM); - - if (err < 0) - return err; - - rtc->alarm_enabled = enabled; - - return 0; -} - -static int pcf50633_rtc_read_time(struct device *dev, struct rtc_time *tm) -{ - struct pcf50633_rtc *rtc; - struct pcf50633_time pcf_tm; - int ret; - - rtc = dev_get_drvdata(dev); - - ret = pcf50633_read_block(rtc->pcf, PCF50633_REG_RTCSC, - PCF50633_TI_EXTENT, - &pcf_tm.time[0]); - if (ret != PCF50633_TI_EXTENT) { - dev_err(dev, "Failed to read time\n"); - return -EIO; - } - - dev_dbg(dev, "PCF_TIME: %02x.%02x.%02x %02x:%02x:%02x\n", - pcf_tm.time[PCF50633_TI_DAY], - pcf_tm.time[PCF50633_TI_MONTH], - pcf_tm.time[PCF50633_TI_YEAR], - pcf_tm.time[PCF50633_TI_HOUR], - pcf_tm.time[PCF50633_TI_MIN], - pcf_tm.time[PCF50633_TI_SEC]); - - pcf2rtc_time(tm, &pcf_tm); - - dev_dbg(dev, "RTC_TIME: %ptRr\n", tm); - - return 0; -} - -static int pcf50633_rtc_set_time(struct device *dev, struct rtc_time *tm) -{ - struct pcf50633_rtc *rtc; - struct pcf50633_time pcf_tm; - int alarm_masked, ret = 0; - - rtc = dev_get_drvdata(dev); - - dev_dbg(dev, "RTC_TIME: %ptRr\n", tm); - - rtc2pcf_time(&pcf_tm, tm); - - dev_dbg(dev, "PCF_TIME: %02x.%02x.%02x %02x:%02x:%02x\n", - pcf_tm.time[PCF50633_TI_DAY], - pcf_tm.time[PCF50633_TI_MONTH], - pcf_tm.time[PCF50633_TI_YEAR], - pcf_tm.time[PCF50633_TI_HOUR], - pcf_tm.time[PCF50633_TI_MIN], - pcf_tm.time[PCF50633_TI_SEC]); - - - alarm_masked = pcf50633_irq_mask_get(rtc->pcf, PCF50633_IRQ_ALARM); - - if (!alarm_masked) - pcf50633_irq_mask(rtc->pcf, PCF50633_IRQ_ALARM); - - /* Returns 0 on success */ - ret = pcf50633_write_block(rtc->pcf, PCF50633_REG_RTCSC, - PCF50633_TI_EXTENT, - &pcf_tm.time[0]); - - if (!alarm_masked) - pcf50633_irq_unmask(rtc->pcf, PCF50633_IRQ_ALARM); - - return ret; -} - -static int pcf50633_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) -{ - struct pcf50633_rtc *rtc; - struct pcf50633_time pcf_tm; - int ret = 0; - - rtc = dev_get_drvdata(dev); - - alrm->enabled = rtc->alarm_enabled; - alrm->pending = rtc->alarm_pending; - - ret = pcf50633_read_block(rtc->pcf, PCF50633_REG_RTCSCA, - PCF50633_TI_EXTENT, &pcf_tm.time[0]); - if (ret != PCF50633_TI_EXTENT) { - dev_err(dev, "Failed to read time\n"); - return -EIO; - } - - pcf2rtc_time(&alrm->time, &pcf_tm); - - return rtc_valid_tm(&alrm->time); -} - -static int pcf50633_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) -{ - struct pcf50633_rtc *rtc; - struct pcf50633_time pcf_tm; - int alarm_masked, ret = 0; - - rtc = dev_get_drvdata(dev); - - rtc2pcf_time(&pcf_tm, &alrm->time); - - /* do like mktime does and ignore tm_wday */ - pcf_tm.time[PCF50633_TI_WKDAY] = 7; - - alarm_masked = pcf50633_irq_mask_get(rtc->pcf, PCF50633_IRQ_ALARM); - - /* disable alarm interrupt */ - if (!alarm_masked) - pcf50633_irq_mask(rtc->pcf, PCF50633_IRQ_ALARM); - - /* Returns 0 on success */ - ret = pcf50633_write_block(rtc->pcf, PCF50633_REG_RTCSCA, - PCF50633_TI_EXTENT, &pcf_tm.time[0]); - if (!alrm->enabled) - rtc->alarm_pending = 0; - - if (!alarm_masked || alrm->enabled) - pcf50633_irq_unmask(rtc->pcf, PCF50633_IRQ_ALARM); - rtc->alarm_enabled = alrm->enabled; - - return ret; -} - -static const struct rtc_class_ops pcf50633_rtc_ops = { - .read_time = pcf50633_rtc_read_time, - .set_time = pcf50633_rtc_set_time, - .read_alarm = pcf50633_rtc_read_alarm, - .set_alarm = pcf50633_rtc_set_alarm, - .alarm_irq_enable = pcf50633_rtc_alarm_irq_enable, -}; - -static void pcf50633_rtc_irq(int irq, void *data) -{ - struct pcf50633_rtc *rtc = data; - - rtc_update_irq(rtc->rtc_dev, 1, RTC_AF | RTC_IRQF); - rtc->alarm_pending = 1; -} - -static int pcf50633_rtc_probe(struct platform_device *pdev) -{ - struct pcf50633_rtc *rtc; - - rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL); - if (!rtc) - return -ENOMEM; - - rtc->pcf = dev_to_pcf50633(pdev->dev.parent); - platform_set_drvdata(pdev, rtc); - rtc->rtc_dev = devm_rtc_device_register(&pdev->dev, "pcf50633-rtc", - &pcf50633_rtc_ops, THIS_MODULE); - - if (IS_ERR(rtc->rtc_dev)) - return PTR_ERR(rtc->rtc_dev); - - pcf50633_register_irq(rtc->pcf, PCF50633_IRQ_ALARM, - pcf50633_rtc_irq, rtc); - return 0; -} - -static void pcf50633_rtc_remove(struct platform_device *pdev) -{ - struct pcf50633_rtc *rtc; - - rtc = platform_get_drvdata(pdev); - pcf50633_free_irq(rtc->pcf, PCF50633_IRQ_ALARM); -} - -static struct platform_driver pcf50633_rtc_driver = { - .driver = { - .name = "pcf50633-rtc", - }, - .probe = pcf50633_rtc_probe, - .remove = pcf50633_rtc_remove, -}; - -module_platform_driver(pcf50633_rtc_driver); - -MODULE_DESCRIPTION("PCF50633 RTC driver"); -MODULE_AUTHOR("Balaji Rao <balajirrao@openmoko.org>"); -MODULE_LICENSE("GPL"); -
diff --git a/drivers/rtc/rtc-pcf85063.c b/drivers/rtc/rtc-pcf85063.c index 905986c..4fa5c4e 100644 --- a/drivers/rtc/rtc-pcf85063.c +++ b/drivers/rtc/rtc-pcf85063.c
@@ -35,6 +35,7 @@ #define PCF85063_REG_CTRL1_CAP_SEL BIT(0) #define PCF85063_REG_CTRL1_STOP BIT(5) #define PCF85063_REG_CTRL1_EXT_TEST BIT(7) +#define PCF85063_REG_CTRL1_SWR 0x58 #define PCF85063_REG_CTRL2 0x01 #define PCF85063_CTRL2_AF BIT(6) @@ -589,16 +590,30 @@ static int pcf85063_probe(struct i2c_client *client) i2c_set_clientdata(client, pcf85063); - err = regmap_read(pcf85063->regmap, PCF85063_REG_CTRL1, &tmp); - if (err) { - dev_err(&client->dev, "RTC chip is not present\n"); - return err; - } + err = regmap_read(pcf85063->regmap, PCF85063_REG_SC, &tmp); + if (err) + return dev_err_probe(&client->dev, err, "RTC chip is not present\n"); pcf85063->rtc = devm_rtc_allocate_device(&client->dev); if (IS_ERR(pcf85063->rtc)) return PTR_ERR(pcf85063->rtc); + /* + * If a Power loss is detected, SW reset the device. + * From PCF85063A datasheet: + * There is a low probability that some devices will have corruption + * of the registers after the automatic power-on reset... + */ + if (tmp & PCF85063_REG_SC_OS) { + dev_warn(&client->dev, + "POR issue detected, sending a SW reset\n"); + err = regmap_write(pcf85063->regmap, PCF85063_REG_CTRL1, + PCF85063_REG_CTRL1_SWR); + if (err < 0) + dev_warn(&client->dev, + "SW reset failed, trying to continue\n"); + } + err = pcf85063_load_capacitance(pcf85063, client->dev.of_node, config->force_cap_7000 ? 7000 : 0); if (err < 0)
diff --git a/drivers/rtc/rtc-pl030.c b/drivers/rtc/rtc-pl030.c index 39038c0..5caaa71 100644 --- a/drivers/rtc/rtc-pl030.c +++ b/drivers/rtc/rtc-pl030.c
@@ -21,7 +21,6 @@ #define RTC_CR_MIE (1 << 0) struct pl030_rtc { - struct rtc_device *rtc; void __iomem *base; }; @@ -86,6 +85,7 @@ static int pl030_probe(struct amba_device *dev, const struct amba_id *id) { struct pl030_rtc *rtc; int ret; + struct rtc_device *rtc_dev; ret = amba_request_regions(dev, NULL); if (ret) @@ -97,14 +97,14 @@ static int pl030_probe(struct amba_device *dev, const struct amba_id *id) goto err_rtc; } - rtc->rtc = devm_rtc_allocate_device(&dev->dev); - if (IS_ERR(rtc->rtc)) { - ret = PTR_ERR(rtc->rtc); + rtc_dev = devm_rtc_allocate_device(&dev->dev); + if (IS_ERR(rtc_dev)) { + ret = PTR_ERR(rtc_dev); goto err_rtc; } - rtc->rtc->ops = &pl030_ops; - rtc->rtc->range_max = U32_MAX; + rtc_dev->ops = &pl030_ops; + rtc_dev->range_max = U32_MAX; rtc->base = ioremap(dev->res.start, resource_size(&dev->res)); if (!rtc->base) { ret = -ENOMEM; @@ -121,7 +121,7 @@ static int pl030_probe(struct amba_device *dev, const struct amba_id *id) if (ret) goto err_irq; - ret = devm_rtc_register_device(rtc->rtc); + ret = devm_rtc_register_device(rtc_dev); if (ret) goto err_reg; @@ -148,7 +148,7 @@ static void pl030_remove(struct amba_device *dev) amba_release_regions(dev); } -static struct amba_id pl030_ids[] = { +static const struct amba_id pl030_ids[] = { { .id = 0x00041030, .mask = 0x000fffff,
diff --git a/drivers/rtc/rtc-pl031.c b/drivers/rtc/rtc-pl031.c index bad6a5d..eab39df 100644 --- a/drivers/rtc/rtc-pl031.c +++ b/drivers/rtc/rtc-pl031.c
@@ -74,6 +74,8 @@ * @st_weekday: if this is an ST Microelectronics silicon version that need * the weekday fix * @irqflags: special IRQ flags per variant + * @range_min: minimum date/time supported by the RTC + * @range_max: maximum date/time supported by the RTC */ struct pl031_vendor_data { struct rtc_class_ops ops; @@ -284,8 +286,6 @@ static void pl031_remove(struct amba_device *adev) { struct pl031_local *ldata = dev_get_drvdata(&adev->dev); - dev_pm_clear_wake_irq(&adev->dev); - device_init_wakeup(&adev->dev, false); if (adev->irq[0]) free_irq(adev->irq[0], ldata); amba_release_regions(adev); @@ -350,7 +350,7 @@ static int pl031_probe(struct amba_device *adev, const struct amba_id *id) } } - device_init_wakeup(&adev->dev, true); + devm_device_init_wakeup(&adev->dev); ldata->rtc = devm_rtc_allocate_device(&adev->dev); if (IS_ERR(ldata->rtc)) { ret = PTR_ERR(ldata->rtc); @@ -373,7 +373,7 @@ static int pl031_probe(struct amba_device *adev, const struct amba_id *id) vendor->irqflags, "rtc-pl031", ldata); if (ret) goto out; - dev_pm_set_wake_irq(&adev->dev, adev->irq[0]); + devm_pm_set_wake_irq(&adev->dev, adev->irq[0]); } return 0;
diff --git a/drivers/rtc/rtc-pm8xxx.c b/drivers/rtc/rtc-pm8xxx.c index b2518ae..3c1dddc 100644 --- a/drivers/rtc/rtc-pm8xxx.c +++ b/drivers/rtc/rtc-pm8xxx.c
@@ -5,6 +5,7 @@ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. * Copyright (c) 2023, Linaro Limited */ +#include <linux/efi.h> #include <linux/of.h> #include <linux/module.h> #include <linux/nvmem-consumer.h> @@ -16,9 +17,10 @@ #include <linux/regmap.h> #include <linux/slab.h> #include <linux/spinlock.h> - #include <linux/unaligned.h> +#include <asm/byteorder.h> + /* RTC_CTRL register bit fields */ #define PM8xxx_RTC_ENABLE BIT(7) #define PM8xxx_RTC_ALARM_CLEAR BIT(0) @@ -46,28 +48,125 @@ struct pm8xxx_rtc_regs { unsigned int alarm_en; }; +struct qcom_uefi_rtc_info { + __le32 offset_gps; + u8 reserved[8]; +} __packed; + /** * struct pm8xxx_rtc - RTC driver internal structure * @rtc: RTC device * @regmap: regmap used to access registers * @allow_set_time: whether the time can be set + * @use_uefi: use UEFI variable as fallback for offset * @alarm_irq: alarm irq number * @regs: register description * @dev: device structure + * @rtc_info: qcom uefi rtc-info structure * @nvmem_cell: nvmem cell for offset * @offset: offset from epoch in seconds + * @offset_dirty: offset needs to be stored on shutdown */ struct pm8xxx_rtc { struct rtc_device *rtc; struct regmap *regmap; bool allow_set_time; + bool use_uefi; int alarm_irq; const struct pm8xxx_rtc_regs *regs; struct device *dev; + struct qcom_uefi_rtc_info rtc_info; struct nvmem_cell *nvmem_cell; u32 offset; + bool offset_dirty; }; +#ifdef CONFIG_EFI + +MODULE_IMPORT_NS("EFIVAR"); + +#define QCOM_UEFI_NAME L"RTCInfo" +#define QCOM_UEFI_GUID EFI_GUID(0x882f8c2b, 0x9646, 0x435f, \ + 0x8d, 0xe5, 0xf2, 0x08, 0xff, 0x80, 0xc1, 0xbd) +#define QCOM_UEFI_ATTRS (EFI_VARIABLE_NON_VOLATILE | \ + EFI_VARIABLE_BOOTSERVICE_ACCESS | \ + EFI_VARIABLE_RUNTIME_ACCESS) + +static int pm8xxx_rtc_read_uefi_offset(struct pm8xxx_rtc *rtc_dd) +{ + struct qcom_uefi_rtc_info *rtc_info = &rtc_dd->rtc_info; + unsigned long size = sizeof(*rtc_info); + struct device *dev = rtc_dd->dev; + efi_status_t status; + u32 offset_gps; + int rc; + + rc = efivar_lock(); + if (rc) + return rc; + + status = efivar_get_variable(QCOM_UEFI_NAME, &QCOM_UEFI_GUID, NULL, + &size, rtc_info); + efivar_unlock(); + + if (status != EFI_SUCCESS) { + dev_dbg(dev, "failed to read UEFI offset: %lu\n", status); + return efi_status_to_err(status); + } + + if (size != sizeof(*rtc_info)) { + dev_dbg(dev, "unexpected UEFI structure size %lu\n", size); + return -EINVAL; + } + + dev_dbg(dev, "uefi_rtc_info = %*ph\n", (int)size, rtc_info); + + /* Convert from GPS to Unix time offset */ + offset_gps = le32_to_cpu(rtc_info->offset_gps); + rtc_dd->offset = offset_gps + (u32)RTC_TIMESTAMP_EPOCH_GPS; + + return 0; +} + +static int pm8xxx_rtc_write_uefi_offset(struct pm8xxx_rtc *rtc_dd, u32 offset) +{ + struct qcom_uefi_rtc_info *rtc_info = &rtc_dd->rtc_info; + unsigned long size = sizeof(*rtc_info); + struct device *dev = rtc_dd->dev; + efi_status_t status; + u32 offset_gps; + + /* Convert from Unix to GPS time offset */ + offset_gps = offset - (u32)RTC_TIMESTAMP_EPOCH_GPS; + + rtc_info->offset_gps = cpu_to_le32(offset_gps); + + dev_dbg(dev, "efi_rtc_info = %*ph\n", (int)size, rtc_info); + + status = efivar_set_variable(QCOM_UEFI_NAME, &QCOM_UEFI_GUID, + QCOM_UEFI_ATTRS, size, rtc_info); + if (status != EFI_SUCCESS) { + dev_dbg(dev, "failed to write UEFI offset: %lx\n", status); + return efi_status_to_err(status); + } + + return 0; +} + +#else /* CONFIG_EFI */ + +static int pm8xxx_rtc_read_uefi_offset(struct pm8xxx_rtc *rtc_dd) +{ + return -ENODEV; +} + +static int pm8xxx_rtc_write_uefi_offset(struct pm8xxx_rtc *rtc_dd, u32 offset) +{ + return -ENODEV; +} + +#endif /* CONFIG_EFI */ + static int pm8xxx_rtc_read_nvmem_offset(struct pm8xxx_rtc *rtc_dd) { size_t len; @@ -110,14 +209,6 @@ static int pm8xxx_rtc_write_nvmem_offset(struct pm8xxx_rtc *rtc_dd, u32 offset) return 0; } -static int pm8xxx_rtc_read_offset(struct pm8xxx_rtc *rtc_dd) -{ - if (!rtc_dd->nvmem_cell) - return 0; - - return pm8xxx_rtc_read_nvmem_offset(rtc_dd); -} - static int pm8xxx_rtc_read_raw(struct pm8xxx_rtc *rtc_dd, u32 *secs) { const struct pm8xxx_rtc_regs *regs = rtc_dd->regs; @@ -155,7 +246,7 @@ static int pm8xxx_rtc_update_offset(struct pm8xxx_rtc *rtc_dd, u32 secs) u32 offset; int rc; - if (!rtc_dd->nvmem_cell) + if (!rtc_dd->nvmem_cell && !rtc_dd->use_uefi) return -ENODEV; rc = pm8xxx_rtc_read_raw(rtc_dd, &raw_secs); @@ -167,10 +258,25 @@ static int pm8xxx_rtc_update_offset(struct pm8xxx_rtc *rtc_dd, u32 secs) if (offset == rtc_dd->offset) return 0; - rc = pm8xxx_rtc_write_nvmem_offset(rtc_dd, offset); + /* + * Reduce flash wear by deferring updates due to clock drift until + * shutdown. + */ + if (abs_diff(offset, rtc_dd->offset) < 30) { + rtc_dd->offset_dirty = true; + goto out; + } + + if (rtc_dd->nvmem_cell) + rc = pm8xxx_rtc_write_nvmem_offset(rtc_dd, offset); + else + rc = pm8xxx_rtc_write_uefi_offset(rtc_dd, offset); + if (rc) return rc; + rtc_dd->offset_dirty = false; +out: rtc_dd->offset = offset; return 0; @@ -455,6 +561,30 @@ static const struct of_device_id pm8xxx_id_table[] = { }; MODULE_DEVICE_TABLE(of, pm8xxx_id_table); +static int pm8xxx_rtc_probe_offset(struct pm8xxx_rtc *rtc_dd) +{ + int rc; + + rtc_dd->nvmem_cell = devm_nvmem_cell_get(rtc_dd->dev, "offset"); + if (IS_ERR(rtc_dd->nvmem_cell)) { + rc = PTR_ERR(rtc_dd->nvmem_cell); + if (rc != -ENOENT) + return rc; + rtc_dd->nvmem_cell = NULL; + } else { + return pm8xxx_rtc_read_nvmem_offset(rtc_dd); + } + + /* Use UEFI storage as fallback if available */ + if (efivar_is_available()) { + rc = pm8xxx_rtc_read_uefi_offset(rtc_dd); + if (rc == 0) + rtc_dd->use_uefi = true; + } + + return 0; +} + static int pm8xxx_rtc_probe(struct platform_device *pdev) { const struct of_device_id *match; @@ -469,30 +599,23 @@ static int pm8xxx_rtc_probe(struct platform_device *pdev) if (rtc_dd == NULL) return -ENOMEM; + rtc_dd->regs = match->data; + rtc_dd->dev = &pdev->dev; + rtc_dd->regmap = dev_get_regmap(pdev->dev.parent, NULL); if (!rtc_dd->regmap) return -ENXIO; - rtc_dd->alarm_irq = platform_get_irq(pdev, 0); - if (rtc_dd->alarm_irq < 0) - return -ENXIO; + if (!of_property_read_bool(pdev->dev.of_node, "qcom,no-alarm")) { + rtc_dd->alarm_irq = platform_get_irq(pdev, 0); + if (rtc_dd->alarm_irq < 0) + return -ENXIO; + } rtc_dd->allow_set_time = of_property_read_bool(pdev->dev.of_node, "allow-set-time"); - - rtc_dd->nvmem_cell = devm_nvmem_cell_get(&pdev->dev, "offset"); - if (IS_ERR(rtc_dd->nvmem_cell)) { - rc = PTR_ERR(rtc_dd->nvmem_cell); - if (rc != -ENOENT) - return rc; - rtc_dd->nvmem_cell = NULL; - } - - rtc_dd->regs = match->data; - rtc_dd->dev = &pdev->dev; - if (!rtc_dd->allow_set_time) { - rc = pm8xxx_rtc_read_offset(rtc_dd); + rc = pm8xxx_rtc_probe_offset(rtc_dd); if (rc) return rc; } @@ -503,8 +626,6 @@ static int pm8xxx_rtc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, rtc_dd); - device_init_wakeup(&pdev->dev, true); - rtc_dd->rtc = devm_rtc_allocate_device(&pdev->dev); if (IS_ERR(rtc_dd->rtc)) return PTR_ERR(rtc_dd->rtc); @@ -512,32 +633,41 @@ static int pm8xxx_rtc_probe(struct platform_device *pdev) rtc_dd->rtc->ops = &pm8xxx_rtc_ops; rtc_dd->rtc->range_max = U32_MAX; - rc = devm_request_any_context_irq(&pdev->dev, rtc_dd->alarm_irq, - pm8xxx_alarm_trigger, - IRQF_TRIGGER_RISING, - "pm8xxx_rtc_alarm", rtc_dd); - if (rc < 0) - return rc; + if (rtc_dd->alarm_irq) { + rc = devm_request_any_context_irq(&pdev->dev, rtc_dd->alarm_irq, + pm8xxx_alarm_trigger, + IRQF_TRIGGER_RISING, + "pm8xxx_rtc_alarm", rtc_dd); + if (rc < 0) + return rc; - rc = devm_rtc_register_device(rtc_dd->rtc); - if (rc) - return rc; + rc = devm_pm_set_wake_irq(&pdev->dev, rtc_dd->alarm_irq); + if (rc) + return rc; - rc = dev_pm_set_wake_irq(&pdev->dev, rtc_dd->alarm_irq); - if (rc) - return rc; + devm_device_init_wakeup(&pdev->dev); + } else { + clear_bit(RTC_FEATURE_ALARM, rtc_dd->rtc->features); + } - return 0; + return devm_rtc_register_device(rtc_dd->rtc); } -static void pm8xxx_remove(struct platform_device *pdev) +static void pm8xxx_shutdown(struct platform_device *pdev) { - dev_pm_clear_wake_irq(&pdev->dev); + struct pm8xxx_rtc *rtc_dd = platform_get_drvdata(pdev); + + if (rtc_dd->offset_dirty) { + if (rtc_dd->nvmem_cell) + pm8xxx_rtc_write_nvmem_offset(rtc_dd, rtc_dd->offset); + else + pm8xxx_rtc_write_uefi_offset(rtc_dd, rtc_dd->offset); + } } static struct platform_driver pm8xxx_rtc_driver = { .probe = pm8xxx_rtc_probe, - .remove = pm8xxx_remove, + .shutdown = pm8xxx_shutdown, .driver = { .name = "rtc-pm8xxx", .of_match_table = pm8xxx_id_table,
diff --git a/drivers/rtc/rtc-renesas-rtca3.c b/drivers/rtc/rtc-renesas-rtca3.c index a056291..ab816bd 100644 --- a/drivers/rtc/rtc-renesas-rtca3.c +++ b/drivers/rtc/rtc-renesas-rtca3.c
@@ -586,17 +586,14 @@ static int rtca3_initial_setup(struct clk *clk, struct rtca3_priv *priv) */ usleep_range(sleep_us, sleep_us + 10); - /* Disable all interrupts. */ - mask = RTCA3_RCR1_AIE | RTCA3_RCR1_CIE | RTCA3_RCR1_PIE; - ret = rtca3_alarm_irq_set_helper(priv, mask, 0); - if (ret) - return ret; - mask = RTCA3_RCR2_START | RTCA3_RCR2_HR24; val = readb(priv->base + RTCA3_RCR2); - /* Nothing to do if already started in 24 hours and calendar count mode. */ - if ((val & mask) == mask) - return 0; + /* Only disable the interrupts if already started in 24 hours and calendar count mode. */ + if ((val & mask) == mask) { + /* Disable all interrupts. */ + mask = RTCA3_RCR1_AIE | RTCA3_RCR1_CIE | RTCA3_RCR1_PIE; + return rtca3_alarm_irq_set_helper(priv, mask, 0); + } /* Reconfigure the RTC in 24 hours and calendar count mode. */ mask = RTCA3_RCR2_START | RTCA3_RCR2_CNTMD;
diff --git a/drivers/rtc/rtc-rv3032.c b/drivers/rtc/rtc-rv3032.c index 35b2e36..2c6a891 100644 --- a/drivers/rtc/rtc-rv3032.c +++ b/drivers/rtc/rtc-rv3032.c
@@ -69,8 +69,7 @@ #define RV3032_CLKOUT2_FD_MSK GENMASK(6, 5) #define RV3032_CLKOUT2_OS BIT(7) -#define RV3032_CTRL1_EERD BIT(3) -#define RV3032_CTRL1_WADA BIT(5) +#define RV3032_CTRL1_EERD BIT(2) #define RV3032_CTRL2_STOP BIT(0) #define RV3032_CTRL2_EIE BIT(2) @@ -947,11 +946,6 @@ static int rv3032_probe(struct i2c_client *client) if (!client->irq) clear_bit(RTC_FEATURE_ALARM, rv3032->rtc->features); - ret = regmap_update_bits(rv3032->regmap, RV3032_CTRL1, - RV3032_CTRL1_WADA, RV3032_CTRL1_WADA); - if (ret) - return ret; - rv3032_trickle_charger_setup(&client->dev, rv3032); set_bit(RTC_FEATURE_BACKUP_SWITCH_MODE, rv3032->rtc->features);
diff --git a/drivers/rtc/rtc-rx8581.c b/drivers/rtc/rtc-rx8581.c index b18c128..20c2dff 100644 --- a/drivers/rtc/rtc-rx8581.c +++ b/drivers/rtc/rtc-rx8581.c
@@ -52,11 +52,6 @@ #define RX8571_USER_RAM 0x10 #define RX8571_NVRAM_SIZE 0x10 -struct rx8581 { - struct regmap *regmap; - struct rtc_device *rtc; -}; - struct rx85x1_config { struct regmap_config regmap; unsigned int num_nvram; @@ -72,14 +67,14 @@ static int rx8581_rtc_read_time(struct device *dev, struct rtc_time *tm) unsigned char date[7]; unsigned int data; int err; - struct rx8581 *rx8581 = i2c_get_clientdata(client); + struct regmap *regmap = i2c_get_clientdata(client); /* First we ensure that the "update flag" is not set, we read the * time and date then re-read the "update flag". If the update flag * has been set, we know that the time has changed during the read so * we repeat the whole process again. */ - err = regmap_read(rx8581->regmap, RX8581_REG_FLAG, &data); + err = regmap_read(regmap, RX8581_REG_FLAG, &data); if (err < 0) return err; @@ -92,20 +87,20 @@ static int rx8581_rtc_read_time(struct device *dev, struct rtc_time *tm) do { /* If update flag set, clear it */ if (data & RX8581_FLAG_UF) { - err = regmap_write(rx8581->regmap, RX8581_REG_FLAG, - data & ~RX8581_FLAG_UF); + err = regmap_write(regmap, RX8581_REG_FLAG, + data & ~RX8581_FLAG_UF); if (err < 0) return err; } /* Now read time and date */ - err = regmap_bulk_read(rx8581->regmap, RX8581_REG_SC, date, + err = regmap_bulk_read(regmap, RX8581_REG_SC, date, sizeof(date)); if (err < 0) return err; /* Check flag register */ - err = regmap_read(rx8581->regmap, RX8581_REG_FLAG, &data); + err = regmap_read(regmap, RX8581_REG_FLAG, &data); if (err < 0) return err; } while (data & RX8581_FLAG_UF); @@ -137,7 +132,7 @@ static int rx8581_rtc_set_time(struct device *dev, struct rtc_time *tm) struct i2c_client *client = to_i2c_client(dev); int err; unsigned char buf[7]; - struct rx8581 *rx8581 = i2c_get_clientdata(client); + struct regmap *regmap = i2c_get_clientdata(client); dev_dbg(dev, "%s: secs=%d, mins=%d, hours=%d, " "mday=%d, mon=%d, year=%d, wday=%d\n", @@ -160,25 +155,23 @@ static int rx8581_rtc_set_time(struct device *dev, struct rtc_time *tm) buf[RX8581_REG_DW] = (0x1 << tm->tm_wday); /* Stop the clock */ - err = regmap_update_bits(rx8581->regmap, RX8581_REG_CTRL, + err = regmap_update_bits(regmap, RX8581_REG_CTRL, RX8581_CTRL_STOP, RX8581_CTRL_STOP); if (err < 0) return err; /* write register's data */ - err = regmap_bulk_write(rx8581->regmap, RX8581_REG_SC, - buf, sizeof(buf)); + err = regmap_bulk_write(regmap, RX8581_REG_SC, buf, sizeof(buf)); if (err < 0) return err; /* get VLF and clear it */ - err = regmap_update_bits(rx8581->regmap, RX8581_REG_FLAG, - RX8581_FLAG_VLF, 0); + err = regmap_update_bits(regmap, RX8581_REG_FLAG, RX8581_FLAG_VLF, 0); if (err < 0) return err; /* Restart the clock */ - return regmap_update_bits(rx8581->regmap, RX8581_REG_CTRL, + return regmap_update_bits(regmap, RX8581_REG_CTRL, RX8581_CTRL_STOP, 0); } @@ -190,29 +183,27 @@ static const struct rtc_class_ops rx8581_rtc_ops = { static int rx8571_nvram_read(void *priv, unsigned int offset, void *val, size_t bytes) { - struct rx8581 *rx8581 = priv; + struct regmap *regmap = priv; - return regmap_bulk_read(rx8581->regmap, RX8571_USER_RAM + offset, - val, bytes); + return regmap_bulk_read(regmap, RX8571_USER_RAM + offset, val, bytes); } static int rx8571_nvram_write(void *priv, unsigned int offset, void *val, size_t bytes) { - struct rx8581 *rx8581 = priv; + struct regmap *regmap = priv; - return regmap_bulk_write(rx8581->regmap, RX8571_USER_RAM + offset, - val, bytes); + return regmap_bulk_write(regmap, RX8571_USER_RAM + offset, val, bytes); } static int rx85x1_nvram_read(void *priv, unsigned int offset, void *val, size_t bytes) { - struct rx8581 *rx8581 = priv; + struct regmap *regmap = priv; unsigned int tmp_val; int ret; - ret = regmap_read(rx8581->regmap, RX8581_REG_RAM, &tmp_val); + ret = regmap_read(regmap, RX8581_REG_RAM, &tmp_val); (*(unsigned char *)val) = (unsigned char) tmp_val; return ret; @@ -221,12 +212,11 @@ static int rx85x1_nvram_read(void *priv, unsigned int offset, void *val, static int rx85x1_nvram_write(void *priv, unsigned int offset, void *val, size_t bytes) { - struct rx8581 *rx8581 = priv; + struct regmap *regmap = priv; unsigned char tmp_val; tmp_val = *((unsigned char *)val); - return regmap_write(rx8581->regmap, RX8581_REG_RAM, - (unsigned int)tmp_val); + return regmap_write(regmap, RX8581_REG_RAM, (unsigned int)tmp_val); } static const struct rx85x1_config rx8581_config = { @@ -249,9 +239,10 @@ static const struct rx85x1_config rx8571_config = { static int rx8581_probe(struct i2c_client *client) { - struct rx8581 *rx8581; + struct regmap *regmap; const struct rx85x1_config *config = &rx8581_config; const void *data = of_device_get_match_data(&client->dev); + struct rtc_device *rtc; static struct nvmem_config nvmem_cfg[] = { { .name = "rx85x1-", @@ -276,31 +267,27 @@ static int rx8581_probe(struct i2c_client *client) if (data) config = data; - rx8581 = devm_kzalloc(&client->dev, sizeof(struct rx8581), GFP_KERNEL); - if (!rx8581) - return -ENOMEM; + regmap = devm_regmap_init_i2c(client, &config->regmap); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); - i2c_set_clientdata(client, rx8581); + i2c_set_clientdata(client, regmap); - rx8581->regmap = devm_regmap_init_i2c(client, &config->regmap); - if (IS_ERR(rx8581->regmap)) - return PTR_ERR(rx8581->regmap); + rtc = devm_rtc_allocate_device(&client->dev); + if (IS_ERR(rtc)) + return PTR_ERR(rtc); - rx8581->rtc = devm_rtc_allocate_device(&client->dev); - if (IS_ERR(rx8581->rtc)) - return PTR_ERR(rx8581->rtc); + rtc->ops = &rx8581_rtc_ops; + rtc->range_min = RTC_TIMESTAMP_BEGIN_2000; + rtc->range_max = RTC_TIMESTAMP_END_2099; + rtc->start_secs = 0; + rtc->set_start_time = true; - rx8581->rtc->ops = &rx8581_rtc_ops; - rx8581->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000; - rx8581->rtc->range_max = RTC_TIMESTAMP_END_2099; - rx8581->rtc->start_secs = 0; - rx8581->rtc->set_start_time = true; - - ret = devm_rtc_register_device(rx8581->rtc); + ret = devm_rtc_register_device(rtc); for (i = 0; i < config->num_nvram; i++) { - nvmem_cfg[i].priv = rx8581; - devm_rtc_nvmem_register(rx8581->rtc, &nvmem_cfg[i]); + nvmem_cfg[i].priv = regmap; + devm_rtc_nvmem_register(rtc, &nvmem_cfg[i]); } return ret;
diff --git a/drivers/rtc/rtc-rzn1.c b/drivers/rtc/rtc-rzn1.c index cb22080..eeb9612 100644 --- a/drivers/rtc/rtc-rzn1.c +++ b/drivers/rtc/rtc-rzn1.c
@@ -19,6 +19,7 @@ #include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/rtc.h> +#include <linux/spinlock.h> #define RZN1_RTC_CTL0 0x00 #define RZN1_RTC_CTL0_SLSB_SUBU 0 @@ -27,6 +28,7 @@ #define RZN1_RTC_CTL0_CE BIT(7) #define RZN1_RTC_CTL1 0x04 +#define RZN1_RTC_CTL1_1SE BIT(3) #define RZN1_RTC_CTL1_ALME BIT(4) #define RZN1_RTC_CTL2 0x08 @@ -58,6 +60,13 @@ struct rzn1_rtc { struct rtc_device *rtcdev; void __iomem *base; + /* + * Protects access to RZN1_RTC_CTL1 reg. rtc_lock with threaded_irqs + * would introduce race conditions when switching interrupts because + * of potential sleeps + */ + spinlock_t ctl1_access_lock; + struct rtc_time tm_alarm; }; static void rzn1_rtc_get_time_snapshot(struct rzn1_rtc *rtc, struct rtc_time *tm) @@ -135,8 +144,38 @@ static int rzn1_rtc_set_time(struct device *dev, struct rtc_time *tm) static irqreturn_t rzn1_rtc_alarm_irq(int irq, void *dev_id) { struct rzn1_rtc *rtc = dev_id; + u32 ctl1, set_irq_bits = 0; - rtc_update_irq(rtc->rtcdev, 1, RTC_AF | RTC_IRQF); + if (rtc->tm_alarm.tm_sec == 0) + rtc_update_irq(rtc->rtcdev, 1, RTC_AF | RTC_IRQF); + else + /* Switch to 1s interrupts */ + set_irq_bits = RZN1_RTC_CTL1_1SE; + + guard(spinlock)(&rtc->ctl1_access_lock); + + ctl1 = readl(rtc->base + RZN1_RTC_CTL1); + ctl1 &= ~RZN1_RTC_CTL1_ALME; + ctl1 |= set_irq_bits; + writel(ctl1, rtc->base + RZN1_RTC_CTL1); + + return IRQ_HANDLED; +} + +static irqreturn_t rzn1_rtc_1s_irq(int irq, void *dev_id) +{ + struct rzn1_rtc *rtc = dev_id; + u32 ctl1; + + if (readl(rtc->base + RZN1_RTC_SECC) == bin2bcd(rtc->tm_alarm.tm_sec)) { + guard(spinlock)(&rtc->ctl1_access_lock); + + ctl1 = readl(rtc->base + RZN1_RTC_CTL1); + ctl1 &= ~RZN1_RTC_CTL1_1SE; + writel(ctl1, rtc->base + RZN1_RTC_CTL1); + + rtc_update_irq(rtc->rtcdev, 1, RTC_AF | RTC_IRQF); + } return IRQ_HANDLED; } @@ -144,14 +183,38 @@ static irqreturn_t rzn1_rtc_alarm_irq(int irq, void *dev_id) static int rzn1_rtc_alarm_irq_enable(struct device *dev, unsigned int enable) { struct rzn1_rtc *rtc = dev_get_drvdata(dev); - u32 ctl1 = readl(rtc->base + RZN1_RTC_CTL1); + struct rtc_time *tm = &rtc->tm_alarm, tm_now; + u32 ctl1; + int ret; - if (enable) - ctl1 |= RZN1_RTC_CTL1_ALME; - else - ctl1 &= ~RZN1_RTC_CTL1_ALME; + guard(spinlock_irqsave)(&rtc->ctl1_access_lock); - writel(ctl1, rtc->base + RZN1_RTC_CTL1); + ctl1 = readl(rtc->base + RZN1_RTC_CTL1); + + if (enable) { + /* + * Use alarm interrupt if alarm time is at least a minute away + * or less than a minute but in the next minute. Otherwise use + * 1 second interrupt to wait for the proper second + */ + do { + ctl1 &= ~(RZN1_RTC_CTL1_ALME | RZN1_RTC_CTL1_1SE); + + ret = rzn1_rtc_read_time(dev, &tm_now); + if (ret) + return ret; + + if (rtc_tm_sub(tm, &tm_now) > 59 || tm->tm_min != tm_now.tm_min) + ctl1 |= RZN1_RTC_CTL1_ALME; + else + ctl1 |= RZN1_RTC_CTL1_1SE; + + writel(ctl1, rtc->base + RZN1_RTC_CTL1); + } while (readl(rtc->base + RZN1_RTC_SECC) != bin2bcd(tm_now.tm_sec)); + } else { + ctl1 &= ~(RZN1_RTC_CTL1_ALME | RZN1_RTC_CTL1_1SE); + writel(ctl1, rtc->base + RZN1_RTC_CTL1); + } return 0; } @@ -185,7 +248,7 @@ static int rzn1_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) } ctl1 = readl(rtc->base + RZN1_RTC_CTL1); - alrm->enabled = !!(ctl1 & RZN1_RTC_CTL1_ALME); + alrm->enabled = !!(ctl1 & (RZN1_RTC_CTL1_ALME | RZN1_RTC_CTL1_1SE)); return 0; } @@ -216,6 +279,8 @@ static int rzn1_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) writel(bin2bcd(tm->tm_hour), rtc->base + RZN1_RTC_ALH); writel(BIT(wday), rtc->base + RZN1_RTC_ALW); + rtc->tm_alarm = alrm->time; + rzn1_rtc_alarm_irq_enable(dev, alrm->enabled); return 0; @@ -304,7 +369,7 @@ static const struct rtc_class_ops rzn1_rtc_ops = { static int rzn1_rtc_probe(struct platform_device *pdev) { struct rzn1_rtc *rtc; - int alarm_irq; + int irq; int ret; rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL); @@ -317,9 +382,9 @@ static int rzn1_rtc_probe(struct platform_device *pdev) if (IS_ERR(rtc->base)) return dev_err_probe(&pdev->dev, PTR_ERR(rtc->base), "Missing reg\n"); - alarm_irq = platform_get_irq(pdev, 0); - if (alarm_irq < 0) - return alarm_irq; + irq = platform_get_irq_byname(pdev, "alarm"); + if (irq < 0) + return irq; rtc->rtcdev = devm_rtc_allocate_device(&pdev->dev); if (IS_ERR(rtc->rtcdev)) @@ -329,8 +394,6 @@ static int rzn1_rtc_probe(struct platform_device *pdev) rtc->rtcdev->range_max = RTC_TIMESTAMP_END_2099; rtc->rtcdev->alarm_offset_max = 7 * 86400; rtc->rtcdev->ops = &rzn1_rtc_ops; - set_bit(RTC_FEATURE_ALARM_RES_MINUTE, rtc->rtcdev->features); - clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, rtc->rtcdev->features); ret = devm_pm_runtime_enable(&pdev->dev); if (ret < 0) @@ -349,13 +412,24 @@ static int rzn1_rtc_probe(struct platform_device *pdev) /* Disable all interrupts */ writel(0, rtc->base + RZN1_RTC_CTL1); - ret = devm_request_irq(&pdev->dev, alarm_irq, rzn1_rtc_alarm_irq, 0, - dev_name(&pdev->dev), rtc); + spin_lock_init(&rtc->ctl1_access_lock); + + ret = devm_request_irq(&pdev->dev, irq, rzn1_rtc_alarm_irq, 0, "RZN1 RTC Alarm", rtc); if (ret) { - dev_err(&pdev->dev, "RTC timer interrupt not available\n"); + dev_err(&pdev->dev, "RTC alarm interrupt not available\n"); goto dis_runtime_pm; } + irq = platform_get_irq_byname_optional(pdev, "pps"); + if (irq >= 0) + ret = devm_request_irq(&pdev->dev, irq, rzn1_rtc_1s_irq, 0, "RZN1 RTC 1s", rtc); + + if (irq < 0 || ret) { + set_bit(RTC_FEATURE_ALARM_RES_MINUTE, rtc->rtcdev->features); + clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, rtc->rtcdev->features); + dev_warn(&pdev->dev, "RTC pps interrupt not available. Alarm has only minute accuracy\n"); + } + ret = devm_rtc_register_device(rtc->rtcdev); if (ret) goto dis_runtime_pm;
diff --git a/drivers/rtc/rtc-s35390a.c b/drivers/rtc/rtc-s35390a.c index e3dc188..3408d2a 100644 --- a/drivers/rtc/rtc-s35390a.c +++ b/drivers/rtc/rtc-s35390a.c
@@ -63,7 +63,6 @@ MODULE_DEVICE_TABLE(of, s35390a_of_match); struct s35390a { struct i2c_client *client[8]; - struct rtc_device *rtc; int twentyfourhour; }; @@ -422,6 +421,7 @@ static int s35390a_probe(struct i2c_client *client) int err, err_read; unsigned int i; struct s35390a *s35390a; + struct rtc_device *rtc; char buf, status1; struct device *dev = &client->dev; @@ -447,9 +447,9 @@ static int s35390a_probe(struct i2c_client *client) } } - s35390a->rtc = devm_rtc_allocate_device(dev); - if (IS_ERR(s35390a->rtc)) - return PTR_ERR(s35390a->rtc); + rtc = devm_rtc_allocate_device(dev); + if (IS_ERR(rtc)) + return PTR_ERR(rtc); err_read = s35390a_read_status(s35390a, &status1); if (err_read < 0) { @@ -480,17 +480,17 @@ static int s35390a_probe(struct i2c_client *client) device_set_wakeup_capable(dev, 1); - s35390a->rtc->ops = &s35390a_rtc_ops; - s35390a->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000; - s35390a->rtc->range_max = RTC_TIMESTAMP_END_2099; + rtc->ops = &s35390a_rtc_ops; + rtc->range_min = RTC_TIMESTAMP_BEGIN_2000; + rtc->range_max = RTC_TIMESTAMP_END_2099; - set_bit(RTC_FEATURE_ALARM_RES_MINUTE, s35390a->rtc->features); - clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, s35390a->rtc->features ); + set_bit(RTC_FEATURE_ALARM_RES_MINUTE, rtc->features); + clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, rtc->features); if (status1 & S35390A_FLAG_INT2) - rtc_update_irq(s35390a->rtc, 1, RTC_AF); + rtc_update_irq(rtc, 1, RTC_AF); - return devm_rtc_register_device(s35390a->rtc); + return devm_rtc_register_device(rtc); } static struct i2c_driver s35390a_driver = {
diff --git a/drivers/rtc/rtc-s5m.c b/drivers/rtc/rtc-s5m.c index 36acca5..db5c9b6 100644 --- a/drivers/rtc/rtc-s5m.c +++ b/drivers/rtc/rtc-s5m.c
@@ -146,7 +146,6 @@ static const struct s5m_rtc_reg_config s2mps15_rtc_regs = { struct s5m_rtc_info { struct device *dev; - struct i2c_client *i2c; struct sec_pmic_dev *s5m87xx; struct regmap *regmap; struct rtc_device *rtc_dev; @@ -627,11 +626,10 @@ static int s5m8767_rtc_init_reg(struct s5m_rtc_info *info) } info->rtc_24hr_mode = 1; - if (ret < 0) { - dev_err(info->dev, "%s: fail to write controlm reg(%d)\n", - __func__, ret); - return ret; - } + if (ret < 0) + return dev_err_probe(info->dev, ret, + "%s: fail to write controlm reg\n", + __func__); return ret; } @@ -640,6 +638,7 @@ static int s5m_rtc_probe(struct platform_device *pdev) { struct sec_pmic_dev *s5m87xx = dev_get_drvdata(pdev->dev.parent); struct s5m_rtc_info *info; + struct i2c_client *i2c; const struct regmap_config *regmap_cfg; int ret, alarm_irq; @@ -669,26 +668,21 @@ static int s5m_rtc_probe(struct platform_device *pdev) alarm_irq = S5M8767_IRQ_RTCA1; break; default: - dev_err(&pdev->dev, - "Device type %lu is not supported by RTC driver\n", - platform_get_device_id(pdev)->driver_data); - return -ENODEV; + return dev_err_probe(&pdev->dev, -ENODEV, + "Device type %lu is not supported by RTC driver\n", + platform_get_device_id(pdev)->driver_data); } - info->i2c = devm_i2c_new_dummy_device(&pdev->dev, s5m87xx->i2c->adapter, - RTC_I2C_ADDR); - if (IS_ERR(info->i2c)) { - dev_err(&pdev->dev, "Failed to allocate I2C for RTC\n"); - return PTR_ERR(info->i2c); - } + i2c = devm_i2c_new_dummy_device(&pdev->dev, s5m87xx->i2c->adapter, + RTC_I2C_ADDR); + if (IS_ERR(i2c)) + return dev_err_probe(&pdev->dev, PTR_ERR(i2c), + "Failed to allocate I2C for RTC\n"); - info->regmap = devm_regmap_init_i2c(info->i2c, regmap_cfg); - if (IS_ERR(info->regmap)) { - ret = PTR_ERR(info->regmap); - dev_err(&pdev->dev, "Failed to allocate RTC register map: %d\n", - ret); - return ret; - } + info->regmap = devm_regmap_init_i2c(i2c, regmap_cfg); + if (IS_ERR(info->regmap)) + return dev_err_probe(&pdev->dev, PTR_ERR(info->regmap), + "Failed to allocate RTC register map\n"); info->dev = &pdev->dev; info->s5m87xx = s5m87xx; @@ -696,11 +690,10 @@ static int s5m_rtc_probe(struct platform_device *pdev) if (s5m87xx->irq_data) { info->irq = regmap_irq_get_virq(s5m87xx->irq_data, alarm_irq); - if (info->irq <= 0) { - dev_err(&pdev->dev, "Failed to get virtual IRQ %d\n", - alarm_irq); - return -EINVAL; - } + if (info->irq <= 0) + return dev_err_probe(&pdev->dev, -EINVAL, + "Failed to get virtual IRQ %d\n", + alarm_irq); } platform_set_drvdata(pdev, info); @@ -724,11 +717,10 @@ static int s5m_rtc_probe(struct platform_device *pdev) ret = devm_request_threaded_irq(&pdev->dev, info->irq, NULL, s5m_rtc_alarm_irq, 0, "rtc-alarm0", info); - if (ret < 0) { - dev_err(&pdev->dev, "Failed to request alarm IRQ: %d: %d\n", - info->irq, ret); - return ret; - } + if (ret < 0) + return dev_err_probe(&pdev->dev, ret, + "Failed to request alarm IRQ %d\n", + info->irq); device_init_wakeup(&pdev->dev, true); }
diff --git a/drivers/rtc/rtc-sd2405al.c b/drivers/rtc/rtc-sd2405al.c index d2568c3..00c3033 100644 --- a/drivers/rtc/rtc-sd2405al.c +++ b/drivers/rtc/rtc-sd2405al.c
@@ -42,7 +42,6 @@ struct sd2405al { struct device *dev; - struct rtc_device *rtc; struct regmap *regmap; }; @@ -167,6 +166,7 @@ static const struct regmap_config sd2405al_regmap_conf = { static int sd2405al_probe(struct i2c_client *client) { struct sd2405al *sd2405al; + struct rtc_device *rtc; int ret; if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) @@ -182,17 +182,17 @@ static int sd2405al_probe(struct i2c_client *client) if (IS_ERR(sd2405al->regmap)) return PTR_ERR(sd2405al->regmap); - sd2405al->rtc = devm_rtc_allocate_device(&client->dev); - if (IS_ERR(sd2405al->rtc)) - return PTR_ERR(sd2405al->rtc); + rtc = devm_rtc_allocate_device(&client->dev); + if (IS_ERR(rtc)) + return PTR_ERR(rtc); - sd2405al->rtc->ops = &sd2405al_rtc_ops; - sd2405al->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000; - sd2405al->rtc->range_max = RTC_TIMESTAMP_END_2099; + rtc->ops = &sd2405al_rtc_ops; + rtc->range_min = RTC_TIMESTAMP_BEGIN_2000; + rtc->range_max = RTC_TIMESTAMP_END_2099; dev_set_drvdata(&client->dev, sd2405al); - ret = devm_rtc_register_device(sd2405al->rtc); + ret = devm_rtc_register_device(rtc); if (ret < 0) return ret;
diff --git a/drivers/rtc/rtc-sd3078.c b/drivers/rtc/rtc-sd3078.c index fe27b54..10cc1dc 100644 --- a/drivers/rtc/rtc-sd3078.c +++ b/drivers/rtc/rtc-sd3078.c
@@ -36,11 +36,6 @@ */ #define WRITE_PROTECT_EN 0 -struct sd3078 { - struct rtc_device *rtc; - struct regmap *regmap; -}; - /* * In order to prevent arbitrary modification of the time register, * when modification of the register, @@ -49,14 +44,11 @@ struct sd3078 { * 2. set WRITE2 bit * 3. set WRITE3 bit */ -static void sd3078_enable_reg_write(struct sd3078 *sd3078) +static void sd3078_enable_reg_write(struct regmap *regmap) { - regmap_update_bits(sd3078->regmap, SD3078_REG_CTRL2, - KEY_WRITE1, KEY_WRITE1); - regmap_update_bits(sd3078->regmap, SD3078_REG_CTRL1, - KEY_WRITE2, KEY_WRITE2); - regmap_update_bits(sd3078->regmap, SD3078_REG_CTRL1, - KEY_WRITE3, KEY_WRITE3); + regmap_update_bits(regmap, SD3078_REG_CTRL2, KEY_WRITE1, KEY_WRITE1); + regmap_update_bits(regmap, SD3078_REG_CTRL1, KEY_WRITE2, KEY_WRITE2); + regmap_update_bits(regmap, SD3078_REG_CTRL1, KEY_WRITE3, KEY_WRITE3); } #if WRITE_PROTECT_EN @@ -69,14 +61,11 @@ static void sd3078_enable_reg_write(struct sd3078 *sd3078) * 2. clear WRITE3 bit * 3. clear WRITE1 bit */ -static void sd3078_disable_reg_write(struct sd3078 *sd3078) +static void sd3078_disable_reg_write(struct regmap *regmap) { - regmap_update_bits(sd3078->regmap, SD3078_REG_CTRL1, - KEY_WRITE2, 0); - regmap_update_bits(sd3078->regmap, SD3078_REG_CTRL1, - KEY_WRITE3, 0); - regmap_update_bits(sd3078->regmap, SD3078_REG_CTRL2, - KEY_WRITE1, 0); + regmap_update_bits(regmap, SD3078_REG_CTRL1, KEY_WRITE2, 0); + regmap_update_bits(regmap, SD3078_REG_CTRL1, KEY_WRITE3, 0); + regmap_update_bits(regmap, SD3078_REG_CTRL2, KEY_WRITE1, 0); } #endif @@ -85,11 +74,10 @@ static int sd3078_rtc_read_time(struct device *dev, struct rtc_time *tm) unsigned char hour; unsigned char rtc_data[NUM_TIME_REGS] = {0}; struct i2c_client *client = to_i2c_client(dev); - struct sd3078 *sd3078 = i2c_get_clientdata(client); + struct regmap *regmap = i2c_get_clientdata(client); int ret; - ret = regmap_bulk_read(sd3078->regmap, SD3078_REG_SC, rtc_data, - NUM_TIME_REGS); + ret = regmap_bulk_read(regmap, SD3078_REG_SC, rtc_data, NUM_TIME_REGS); if (ret < 0) { dev_err(dev, "reading from RTC failed with err:%d\n", ret); return ret; @@ -123,7 +111,7 @@ static int sd3078_rtc_set_time(struct device *dev, struct rtc_time *tm) { unsigned char rtc_data[NUM_TIME_REGS]; struct i2c_client *client = to_i2c_client(dev); - struct sd3078 *sd3078 = i2c_get_clientdata(client); + struct regmap *regmap = i2c_get_clientdata(client); int ret; rtc_data[SD3078_REG_SC] = bin2bcd(tm->tm_sec); @@ -135,10 +123,10 @@ static int sd3078_rtc_set_time(struct device *dev, struct rtc_time *tm) rtc_data[SD3078_REG_YR] = bin2bcd(tm->tm_year - 100); #if WRITE_PROTECT_EN - sd3078_enable_reg_write(sd3078); + sd3078_enable_reg_write(regmap); #endif - ret = regmap_bulk_write(sd3078->regmap, SD3078_REG_SC, rtc_data, + ret = regmap_bulk_write(regmap, SD3078_REG_SC, rtc_data, NUM_TIME_REGS); if (ret < 0) { dev_err(dev, "writing to RTC failed with err:%d\n", ret); @@ -146,7 +134,7 @@ static int sd3078_rtc_set_time(struct device *dev, struct rtc_time *tm) } #if WRITE_PROTECT_EN - sd3078_disable_reg_write(sd3078); + sd3078_disable_reg_write(regmap); #endif return 0; @@ -166,36 +154,33 @@ static const struct regmap_config regmap_config = { static int sd3078_probe(struct i2c_client *client) { int ret; - struct sd3078 *sd3078; + struct regmap *regmap; + struct rtc_device *rtc; if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) return -ENODEV; - sd3078 = devm_kzalloc(&client->dev, sizeof(*sd3078), GFP_KERNEL); - if (!sd3078) - return -ENOMEM; - - sd3078->regmap = devm_regmap_init_i2c(client, ®map_config); - if (IS_ERR(sd3078->regmap)) { + regmap = devm_regmap_init_i2c(client, ®map_config); + if (IS_ERR(regmap)) { dev_err(&client->dev, "regmap allocation failed\n"); - return PTR_ERR(sd3078->regmap); + return PTR_ERR(regmap); } - i2c_set_clientdata(client, sd3078); + i2c_set_clientdata(client, regmap); - sd3078->rtc = devm_rtc_allocate_device(&client->dev); - if (IS_ERR(sd3078->rtc)) - return PTR_ERR(sd3078->rtc); + rtc = devm_rtc_allocate_device(&client->dev); + if (IS_ERR(rtc)) + return PTR_ERR(rtc); - sd3078->rtc->ops = &sd3078_rtc_ops; - sd3078->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000; - sd3078->rtc->range_max = RTC_TIMESTAMP_END_2099; + rtc->ops = &sd3078_rtc_ops; + rtc->range_min = RTC_TIMESTAMP_BEGIN_2000; + rtc->range_max = RTC_TIMESTAMP_END_2099; - ret = devm_rtc_register_device(sd3078->rtc); + ret = devm_rtc_register_device(rtc); if (ret) return ret; - sd3078_enable_reg_write(sd3078); + sd3078_enable_reg_write(regmap); return 0; }
diff --git a/drivers/rtc/rtc-stm32.c b/drivers/rtc/rtc-stm32.c index a0564d4..1b715db 100644 --- a/drivers/rtc/rtc-stm32.c +++ b/drivers/rtc/rtc-stm32.c
@@ -1143,11 +1143,11 @@ static int stm32_rtc_probe(struct platform_device *pdev) goto err; } - ret = device_init_wakeup(&pdev->dev, true); + ret = devm_device_init_wakeup(&pdev->dev); if (ret) goto err; - ret = dev_pm_set_wake_irq(&pdev->dev, rtc->irq_alarm); + ret = devm_pm_set_wake_irq(&pdev->dev, rtc->irq_alarm); if (ret) goto err; @@ -1208,9 +1208,6 @@ static int stm32_rtc_probe(struct platform_device *pdev) if (rtc->data->need_dbp) regmap_update_bits(rtc->dbp, rtc->dbp_reg, rtc->dbp_mask, 0); - dev_pm_clear_wake_irq(&pdev->dev); - device_init_wakeup(&pdev->dev, false); - return ret; } @@ -1237,9 +1234,6 @@ static void stm32_rtc_remove(struct platform_device *pdev) /* Enable backup domain write protection if needed */ if (rtc->data->need_dbp) regmap_update_bits(rtc->dbp, rtc->dbp_reg, rtc->dbp_mask, 0); - - dev_pm_clear_wake_irq(&pdev->dev); - device_init_wakeup(&pdev->dev, false); } static int stm32_rtc_suspend(struct device *dev)
diff --git a/drivers/rtc/rtc-test.c b/drivers/rtc/rtc-test.c index a68b8c8..a9f5b94 100644 --- a/drivers/rtc/rtc-test.c +++ b/drivers/rtc/rtc-test.c
@@ -44,7 +44,7 @@ static int test_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) timeout = rtc_tm_to_time64(&alrm->time) - ktime_get_real_seconds(); timeout -= rtd->offset; - del_timer(&rtd->alarm); + timer_delete(&rtd->alarm); expires = jiffies + timeout * HZ; if (expires > U32_MAX) @@ -86,7 +86,7 @@ static int test_rtc_alarm_irq_enable(struct device *dev, unsigned int enable) if (enable) add_timer(&rtd->alarm); else - del_timer(&rtd->alarm); + timer_delete(&rtd->alarm); return 0; }
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index 31bfb49..cf36d3b 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c
@@ -1507,7 +1507,7 @@ static void dasd_device_timeout(struct timer_list *t) void dasd_device_set_timer(struct dasd_device *device, int expires) { if (expires == 0) - del_timer(&device->timer); + timer_delete(&device->timer); else mod_timer(&device->timer, jiffies + expires); } @@ -1518,7 +1518,7 @@ EXPORT_SYMBOL(dasd_device_set_timer); */ void dasd_device_clear_timer(struct dasd_device *device) { - del_timer(&device->timer); + timer_delete(&device->timer); } EXPORT_SYMBOL(dasd_device_clear_timer); @@ -2692,7 +2692,7 @@ static void dasd_block_timeout(struct timer_list *t) void dasd_block_set_timer(struct dasd_block *block, int expires) { if (expires == 0) - del_timer(&block->timer); + timer_delete(&block->timer); else mod_timer(&block->timer, jiffies + expires); } @@ -2703,7 +2703,7 @@ EXPORT_SYMBOL(dasd_block_set_timer); */ void dasd_block_clear_timer(struct dasd_block *block) { - del_timer(&block->timer); + timer_delete(&block->timer); } EXPORT_SYMBOL(dasd_block_clear_timer);
diff --git a/drivers/s390/char/con3270.c b/drivers/s390/char/con3270.c index 1a31908..34f3820 100644 --- a/drivers/s390/char/con3270.c +++ b/drivers/s390/char/con3270.c
@@ -793,7 +793,7 @@ static void tty3270_deactivate(struct raw3270_view *view) { struct tty3270 *tp = container_of(view, struct tty3270, view); - del_timer(&tp->timer); + timer_delete(&tp->timer); } static void tty3270_irq(struct tty3270 *tp, struct raw3270_request *rq, struct irb *irb) @@ -1060,7 +1060,7 @@ static void tty3270_free(struct raw3270_view *view) { struct tty3270 *tp = container_of(view, struct tty3270, view); - del_timer_sync(&tp->timer); + timer_delete_sync(&tp->timer); tty3270_free_screen(tp->screen, tp->allocated_lines); free_page((unsigned long)tp->converted_line); kfree(tp->input);
diff --git a/drivers/s390/char/sclp.c b/drivers/s390/char/sclp.c index 45bd001..840be75 100644 --- a/drivers/s390/char/sclp.c +++ b/drivers/s390/char/sclp.c
@@ -261,7 +261,7 @@ __sclp_queue_read_req(void) static inline void __sclp_set_request_timer(unsigned long time, void (*cb)(struct timer_list *)) { - del_timer(&sclp_request_timer); + timer_delete(&sclp_request_timer); sclp_request_timer.function = cb; sclp_request_timer.expires = jiffies + time; add_timer(&sclp_request_timer); @@ -407,7 +407,7 @@ __sclp_start_request(struct sclp_req *req) if (sclp_running_state != sclp_running_state_idle) return 0; - del_timer(&sclp_request_timer); + timer_delete(&sclp_request_timer); rc = sclp_service_call_trace(req->command, req->sccb); req->start_count++; @@ -442,7 +442,7 @@ sclp_process_queue(void) spin_unlock_irqrestore(&sclp_lock, flags); return; } - del_timer(&sclp_request_timer); + timer_delete(&sclp_request_timer); while (!list_empty(&sclp_req_queue)) { req = list_entry(sclp_req_queue.next, struct sclp_req, list); rc = __sclp_start_request(req); @@ -662,7 +662,7 @@ static void sclp_interrupt_handler(struct ext_code ext_code, !ok_response(finished_sccb, active_cmd)); if (finished_sccb) { - del_timer(&sclp_request_timer); + timer_delete(&sclp_request_timer); sclp_running_state = sclp_running_state_reset_pending; req = __sclp_find_req(finished_sccb); if (req) { @@ -739,7 +739,7 @@ sclp_sync_wait(void) /* Loop until driver state indicates finished request */ while (sclp_running_state != sclp_running_state_idle) { /* Check for expired request timer */ - if (get_tod_clock_fast() > timeout && del_timer(&sclp_request_timer)) + if (get_tod_clock_fast() > timeout && timer_delete(&sclp_request_timer)) sclp_request_timer.function(&sclp_request_timer); cpu_relax(); } @@ -1165,7 +1165,7 @@ sclp_check_interface(void) * with IRQs enabled. */ irq_subclass_unregister(IRQ_SUBCLASS_SERVICE_SIGNAL); spin_lock_irqsave(&sclp_lock, flags); - del_timer(&sclp_request_timer); + timer_delete(&sclp_request_timer); rc = -EBUSY; if (sclp_init_req.status == SCLP_REQ_DONE) { if (sccb->header.response_code == 0x20) {
diff --git a/drivers/s390/char/sclp_con.c b/drivers/s390/char/sclp_con.c index 6a030ba..d8544c4 100644 --- a/drivers/s390/char/sclp_con.c +++ b/drivers/s390/char/sclp_con.c
@@ -109,7 +109,7 @@ static void sclp_console_sync_queue(void) unsigned long flags; spin_lock_irqsave(&sclp_con_lock, flags); - del_timer(&sclp_con_timer); + timer_delete(&sclp_con_timer); while (sclp_con_queue_running) { spin_unlock_irqrestore(&sclp_con_lock, flags); sclp_sync_wait();
diff --git a/drivers/s390/char/sclp_vt220.c b/drivers/s390/char/sclp_vt220.c index 33b9c96..62979ad 100644 --- a/drivers/s390/char/sclp_vt220.c +++ b/drivers/s390/char/sclp_vt220.c
@@ -231,7 +231,7 @@ sclp_vt220_emit_current(void) list_add_tail(&sclp_vt220_current_request->list, &sclp_vt220_outqueue); sclp_vt220_current_request = NULL; - del_timer(&sclp_vt220_timer); + timer_delete(&sclp_vt220_timer); } sclp_vt220_flush_later = 0; } @@ -798,7 +798,7 @@ sclp_vt220_notify(struct notifier_block *self, sclp_vt220_emit_current(); spin_lock_irqsave(&sclp_vt220_lock, flags); - del_timer(&sclp_vt220_timer); + timer_delete(&sclp_vt220_timer); while (sclp_vt220_queue_running) { spin_unlock_irqrestore(&sclp_vt220_lock, flags); sclp_sync_wait();
diff --git a/drivers/s390/char/tape_core.c b/drivers/s390/char/tape_core.c index ce8a440..48e8417 100644 --- a/drivers/s390/char/tape_core.c +++ b/drivers/s390/char/tape_core.c
@@ -1108,7 +1108,7 @@ __tape_do_irq (struct ccw_device *cdev, unsigned long intparm, struct irb *irb) struct tape_request, list); if (req->status == TAPE_REQUEST_LONG_BUSY) { DBF_EVENT(3, "(%08x): del timer\n", device->cdev_id); - if (del_timer(&device->lb_timeout)) { + if (timer_delete(&device->lb_timeout)) { tape_put_device(device); __tape_start_next_request(device); }
diff --git a/drivers/s390/char/tape_std.c b/drivers/s390/char/tape_std.c index f7e75d9..b760386 100644 --- a/drivers/s390/char/tape_std.c +++ b/drivers/s390/char/tape_std.c
@@ -73,7 +73,7 @@ tape_std_assign(struct tape_device *device) rc = tape_do_io_interruptible(device, request); - del_timer_sync(&request->timer); + timer_delete_sync(&request->timer); if (rc != 0) { DBF_EVENT(3, "%08x: assign failed - device might be busy\n",
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c index 42791fa..e1b1fbd 100644 --- a/drivers/s390/cio/device_fsm.c +++ b/drivers/s390/cio/device_fsm.c
@@ -115,7 +115,7 @@ void ccw_device_set_timeout(struct ccw_device *cdev, int expires) { if (expires == 0) - del_timer(&cdev->private->timer); + timer_delete(&cdev->private->timer); else mod_timer(&cdev->private->timer, jiffies + expires); }
diff --git a/drivers/s390/cio/eadm_sch.c b/drivers/s390/cio/eadm_sch.c index 165de15..ac38235 100644 --- a/drivers/s390/cio/eadm_sch.c +++ b/drivers/s390/cio/eadm_sch.c
@@ -114,7 +114,7 @@ static void eadm_subchannel_set_timeout(struct subchannel *sch, int expires) struct eadm_private *private = get_eadm_private(sch); if (expires == 0) - del_timer(&private->timer); + timer_delete(&private->timer); else mod_timer(&private->timer, jiffies + expires); }
diff --git a/drivers/s390/crypto/ap_queue.c b/drivers/s390/crypto/ap_queue.c index 9a0e6e4..4088fda 100644 --- a/drivers/s390/crypto/ap_queue.c +++ b/drivers/s390/crypto/ap_queue.c
@@ -1289,7 +1289,7 @@ void ap_queue_prepare_remove(struct ap_queue *aq) /* move queue device state to SHUTDOWN in progress */ aq->dev_state = AP_DEV_STATE_SHUTDOWN; spin_unlock_bh(&aq->lock); - del_timer_sync(&aq->timeout); + timer_delete_sync(&aq->timeout); } void ap_queue_remove(struct ap_queue *aq)
diff --git a/drivers/s390/crypto/vfio_ap_ops.c b/drivers/s390/crypto/vfio_ap_ops.c index bc8669b..7665575 100644 --- a/drivers/s390/crypto/vfio_ap_ops.c +++ b/drivers/s390/crypto/vfio_ap_ops.c
@@ -873,48 +873,66 @@ static void vfio_ap_mdev_remove(struct mdev_device *mdev) vfio_put_device(&matrix_mdev->vdev); } -#define MDEV_SHARING_ERR "Userspace may not re-assign queue %02lx.%04lx " \ - "already assigned to %s" +#define MDEV_SHARING_ERR "Userspace may not assign queue %02lx.%04lx to mdev: already assigned to %s" -static void vfio_ap_mdev_log_sharing_err(struct ap_matrix_mdev *matrix_mdev, - unsigned long *apm, - unsigned long *aqm) +#define MDEV_IN_USE_ERR "Can not reserve queue %02lx.%04lx for host driver: in use by mdev" + +static void vfio_ap_mdev_log_sharing_err(struct ap_matrix_mdev *assignee, + struct ap_matrix_mdev *assigned_to, + unsigned long *apm, unsigned long *aqm) { unsigned long apid, apqi; - const struct device *dev = mdev_dev(matrix_mdev->mdev); - const char *mdev_name = dev_name(dev); - for_each_set_bit_inv(apid, apm, AP_DEVICES) + for_each_set_bit_inv(apid, apm, AP_DEVICES) { + for_each_set_bit_inv(apqi, aqm, AP_DOMAINS) { + dev_warn(mdev_dev(assignee->mdev), MDEV_SHARING_ERR, + apid, apqi, dev_name(mdev_dev(assigned_to->mdev))); + } + } +} + +static void vfio_ap_mdev_log_in_use_err(struct ap_matrix_mdev *assignee, + unsigned long *apm, unsigned long *aqm) +{ + unsigned long apid, apqi; + + for_each_set_bit_inv(apid, apm, AP_DEVICES) { for_each_set_bit_inv(apqi, aqm, AP_DOMAINS) - dev_warn(dev, MDEV_SHARING_ERR, apid, apqi, mdev_name); + dev_warn(mdev_dev(assignee->mdev), MDEV_IN_USE_ERR, apid, apqi); + } } /** * vfio_ap_mdev_verify_no_sharing - verify APQNs are not shared by matrix mdevs * + * @assignee: the matrix mdev to which @mdev_apm and @mdev_aqm are being + * assigned; or, NULL if this function was called by the AP bus + * driver in_use callback to verify none of the APQNs being reserved + * for the host device driver are in use by a vfio_ap mediated device * @mdev_apm: mask indicating the APIDs of the APQNs to be verified * @mdev_aqm: mask indicating the APQIs of the APQNs to be verified * - * Verifies that each APQN derived from the Cartesian product of a bitmap of - * AP adapter IDs and AP queue indexes is not configured for any matrix - * mediated device. AP queue sharing is not allowed. + * Verifies that each APQN derived from the Cartesian product of APIDs + * represented by the bits set in @mdev_apm and the APQIs of the bits set in + * @mdev_aqm is not assigned to a mediated device other than the mdev to which + * the APQN is being assigned (@assignee). AP queue sharing is not allowed. * * Return: 0 if the APQNs are not shared; otherwise return -EADDRINUSE. */ -static int vfio_ap_mdev_verify_no_sharing(unsigned long *mdev_apm, +static int vfio_ap_mdev_verify_no_sharing(struct ap_matrix_mdev *assignee, + unsigned long *mdev_apm, unsigned long *mdev_aqm) { - struct ap_matrix_mdev *matrix_mdev; + struct ap_matrix_mdev *assigned_to; DECLARE_BITMAP(apm, AP_DEVICES); DECLARE_BITMAP(aqm, AP_DOMAINS); - list_for_each_entry(matrix_mdev, &matrix_dev->mdev_list, node) { + list_for_each_entry(assigned_to, &matrix_dev->mdev_list, node) { /* - * If the input apm and aqm are fields of the matrix_mdev - * object, then move on to the next matrix_mdev. + * If the mdev to which the mdev_apm and mdev_aqm is being + * assigned is the same as the mdev being verified */ - if (mdev_apm == matrix_mdev->matrix.apm && - mdev_aqm == matrix_mdev->matrix.aqm) + if (assignee == assigned_to) continue; memset(apm, 0, sizeof(apm)); @@ -924,15 +942,16 @@ static int vfio_ap_mdev_verify_no_sharing(unsigned long *mdev_apm, * We work on full longs, as we can only exclude the leftover * bits in non-inverse order. The leftover is all zeros. */ - if (!bitmap_and(apm, mdev_apm, matrix_mdev->matrix.apm, - AP_DEVICES)) + if (!bitmap_and(apm, mdev_apm, assigned_to->matrix.apm, AP_DEVICES)) continue; - if (!bitmap_and(aqm, mdev_aqm, matrix_mdev->matrix.aqm, - AP_DOMAINS)) + if (!bitmap_and(aqm, mdev_aqm, assigned_to->matrix.aqm, AP_DOMAINS)) continue; - vfio_ap_mdev_log_sharing_err(matrix_mdev, apm, aqm); + if (assignee) + vfio_ap_mdev_log_sharing_err(assignee, assigned_to, apm, aqm); + else + vfio_ap_mdev_log_in_use_err(assigned_to, apm, aqm); return -EADDRINUSE; } @@ -961,7 +980,8 @@ static int vfio_ap_mdev_validate_masks(struct ap_matrix_mdev *matrix_mdev) matrix_mdev->matrix.aqm)) return -EADDRNOTAVAIL; - return vfio_ap_mdev_verify_no_sharing(matrix_mdev->matrix.apm, + return vfio_ap_mdev_verify_no_sharing(matrix_mdev, + matrix_mdev->matrix.apm, matrix_mdev->matrix.aqm); } @@ -2516,7 +2536,7 @@ int vfio_ap_mdev_resource_in_use(unsigned long *apm, unsigned long *aqm) mutex_lock(&matrix_dev->guests_lock); mutex_lock(&matrix_dev->mdevs_lock); - ret = vfio_ap_mdev_verify_no_sharing(apm, aqm); + ret = vfio_ap_mdev_verify_no_sharing(NULL, apm, aqm); mutex_unlock(&matrix_dev->mdevs_lock); mutex_unlock(&matrix_dev->guests_lock);
diff --git a/drivers/s390/net/fsm.c b/drivers/s390/net/fsm.c index 8672d225..5fcdce1 100644 --- a/drivers/s390/net/fsm.c +++ b/drivers/s390/net/fsm.c
@@ -158,7 +158,7 @@ fsm_deltimer(fsm_timer *this) printk(KERN_DEBUG "fsm(%s): Delete timer %p\n", this->fi->name, this); #endif - del_timer(&this->tl); + timer_delete(&this->tl); } int @@ -188,7 +188,7 @@ fsm_modtimer(fsm_timer *this, int millisec, int event, void *arg) this->fi->name, this, millisec); #endif - del_timer(&this->tl); + timer_delete(&this->tl); timer_setup(&this->tl, fsm_expire_timer, 0); this->expire_event = event; this->event_arg = arg;
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 20328d6..f5cfaeb 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c
@@ -7088,7 +7088,7 @@ int qeth_stop(struct net_device *dev) netif_tx_disable(dev); qeth_for_each_output_queue(card, queue, i) { - del_timer_sync(&queue->timer); + timer_delete_sync(&queue->timer); /* Queues may get re-allocated, so remove the NAPIs. */ netif_napi_del(&queue->napi); }
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index 99d6b3f..d5f5f56 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c
@@ -458,7 +458,7 @@ static void zfcp_fsf_req_complete(struct zfcp_fsf_req *req) return; } - del_timer_sync(&req->timer); + timer_delete_sync(&req->timer); zfcp_fsf_protstatus_eval(req); zfcp_fsf_fsfstatus_eval(req); req->handler(req); @@ -891,7 +891,7 @@ static int zfcp_fsf_req_send(struct zfcp_fsf_req *req) req->qdio_req.qdio_outb_usage = atomic_read(&qdio->req_q_free); req->issued = get_tod_clock(); if (zfcp_qdio_send(qdio, &req->qdio_req)) { - del_timer_sync(&req->timer); + timer_delete_sync(&req->timer); /* lookup request again, list might have changed */ if (zfcp_reqlist_find_rm(adapter->req_list, req_id) == NULL)
diff --git a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c index 8cbc5e1..0957e3f 100644 --- a/drivers/s390/scsi/zfcp_qdio.c +++ b/drivers/s390/scsi/zfcp_qdio.c
@@ -408,7 +408,7 @@ void zfcp_qdio_close(struct zfcp_qdio *qdio) tasklet_disable(&qdio->irq_tasklet); tasklet_disable(&qdio->request_tasklet); - del_timer_sync(&qdio->request_timer); + timer_delete_sync(&qdio->request_timer); qdio_stop_irq(adapter->ccw_device); qdio_shutdown(adapter->ccw_device, QDIO_FLAG_CLEANUP_USING_CLEAR);
diff --git a/drivers/scsi/aic7xxx/aic79xx_core.c b/drivers/scsi/aic7xxx/aic79xx_core.c index 3e3100d..f9372a8 100644 --- a/drivers/scsi/aic7xxx/aic79xx_core.c +++ b/drivers/scsi/aic7xxx/aic79xx_core.c
@@ -6181,7 +6181,7 @@ ahd_shutdown(void *arg) /* * Stop periodic timer callbacks. */ - del_timer_sync(&ahd->stat_timer); + timer_delete_sync(&ahd->stat_timer); /* This will reset most registers to 0, but not all */ ahd_reset(ahd, /*reinit*/FALSE); @@ -6975,7 +6975,7 @@ static const char *termstat_strings[] = { static void ahd_timer_reset(struct timer_list *timer, int usec) { - del_timer(timer); + timer_delete(timer); timer->expires = jiffies + (usec * HZ)/1000000; add_timer(timer); }
diff --git a/drivers/scsi/aic94xx/aic94xx_hwi.c b/drivers/scsi/aic94xx/aic94xx_hwi.c index 9dda296..e743933 100644 --- a/drivers/scsi/aic94xx/aic94xx_hwi.c +++ b/drivers/scsi/aic94xx/aic94xx_hwi.c
@@ -731,7 +731,7 @@ static void asd_dl_tasklet_handler(unsigned long data) goto next_1; } else if (ascb->scb->header.opcode == EMPTY_SCB) { goto out; - } else if (!ascb->uldd_timer && !del_timer(&ascb->timer)) { + } else if (!ascb->uldd_timer && !timer_delete(&ascb->timer)) { goto next_1; } spin_lock_irqsave(&seq->pend_q_lock, flags);
diff --git a/drivers/scsi/aic94xx/aic94xx_init.c b/drivers/scsi/aic94xx/aic94xx_init.c index 538a586..adf3d91 100644 --- a/drivers/scsi/aic94xx/aic94xx_init.c +++ b/drivers/scsi/aic94xx/aic94xx_init.c
@@ -851,7 +851,7 @@ static void asd_free_queues(struct asd_ha_struct *asd_ha) * times out. Apparently we don't wait for the CONTROL PHY * to complete, so it doesn't matter if we kill the timer. */ - del_timer_sync(&ascb->timer); + timer_delete_sync(&ascb->timer); WARN_ON(ascb->scb->header.opcode != CONTROL_PHY); list_del_init(pos);
diff --git a/drivers/scsi/aic94xx/aic94xx_tmf.c b/drivers/scsi/aic94xx/aic94xx_tmf.c index 27d32b8..d45dbf9 100644 --- a/drivers/scsi/aic94xx/aic94xx_tmf.c +++ b/drivers/scsi/aic94xx/aic94xx_tmf.c
@@ -31,7 +31,7 @@ static int asd_enqueue_internal(struct asd_ascb *ascb, res = asd_post_ascb_list(ascb->ha, ascb, 1); if (unlikely(res)) - del_timer(&ascb->timer); + timer_delete(&ascb->timer); return res; } @@ -58,7 +58,7 @@ static void asd_clear_nexus_tasklet_complete(struct asd_ascb *ascb, { struct tasklet_completion_status *tcs = ascb->uldd_task; ASD_DPRINTK("%s: here\n", __func__); - if (!del_timer(&ascb->timer)) { + if (!timer_delete(&ascb->timer)) { ASD_DPRINTK("%s: couldn't delete timer\n", __func__); return; } @@ -303,7 +303,7 @@ static void asd_tmf_tasklet_complete(struct asd_ascb *ascb, { struct tasklet_completion_status *tcs; - if (!del_timer(&ascb->timer)) + if (!timer_delete(&ascb->timer)) return; tcs = ascb->uldd_task;
diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c index 221a520..b450b1f 100644 --- a/drivers/scsi/arcmsr/arcmsr_hba.c +++ b/drivers/scsi/arcmsr/arcmsr_hba.c
@@ -1161,8 +1161,8 @@ static int arcmsr_probe(struct pci_dev *pdev, const struct pci_device_id *id) return 0; out_free_sysfs: if (set_date_time) - del_timer_sync(&acb->refresh_timer); - del_timer_sync(&acb->eternal_timer); + timer_delete_sync(&acb->refresh_timer); + timer_delete_sync(&acb->eternal_timer); flush_work(&acb->arcmsr_do_message_isr_bh); arcmsr_stop_adapter_bgrb(acb); arcmsr_flush_adapter_cache(acb); @@ -1204,9 +1204,9 @@ static int __maybe_unused arcmsr_suspend(struct device *dev) arcmsr_disable_outbound_ints(acb); arcmsr_free_irq(pdev, acb); - del_timer_sync(&acb->eternal_timer); + timer_delete_sync(&acb->eternal_timer); if (set_date_time) - del_timer_sync(&acb->refresh_timer); + timer_delete_sync(&acb->refresh_timer); flush_work(&acb->arcmsr_do_message_isr_bh); arcmsr_stop_adapter_bgrb(acb); arcmsr_flush_adapter_cache(acb); @@ -1685,9 +1685,9 @@ static void arcmsr_free_pcidev(struct AdapterControlBlock *acb) arcmsr_free_sysfs_attr(acb); scsi_remove_host(host); flush_work(&acb->arcmsr_do_message_isr_bh); - del_timer_sync(&acb->eternal_timer); + timer_delete_sync(&acb->eternal_timer); if (set_date_time) - del_timer_sync(&acb->refresh_timer); + timer_delete_sync(&acb->refresh_timer); pdev = acb->pdev; arcmsr_free_irq(pdev, acb); arcmsr_free_ccb_pool(acb); @@ -1718,9 +1718,9 @@ static void arcmsr_remove(struct pci_dev *pdev) arcmsr_free_sysfs_attr(acb); scsi_remove_host(host); flush_work(&acb->arcmsr_do_message_isr_bh); - del_timer_sync(&acb->eternal_timer); + timer_delete_sync(&acb->eternal_timer); if (set_date_time) - del_timer_sync(&acb->refresh_timer); + timer_delete_sync(&acb->refresh_timer); arcmsr_disable_outbound_ints(acb); arcmsr_stop_adapter_bgrb(acb); arcmsr_flush_adapter_cache(acb); @@ -1765,9 +1765,9 @@ static void arcmsr_shutdown(struct pci_dev *pdev) (struct AdapterControlBlock *)host->hostdata; if (acb->acb_flags & ACB_F_ADAPTER_REMOVED) return; - del_timer_sync(&acb->eternal_timer); + timer_delete_sync(&acb->eternal_timer); if (set_date_time) - del_timer_sync(&acb->refresh_timer); + timer_delete_sync(&acb->refresh_timer); arcmsr_disable_outbound_ints(acb); arcmsr_free_irq(pdev, acb); flush_work(&acb->arcmsr_do_message_isr_bh);
diff --git a/drivers/scsi/arm/fas216.c b/drivers/scsi/arm/fas216.c index 4ce0b2d..e0b55d8 100644 --- a/drivers/scsi/arm/fas216.c +++ b/drivers/scsi/arm/fas216.c
@@ -2331,7 +2331,7 @@ static void fas216_eh_timer(struct timer_list *t) fas216_log(info, LOG_ERROR, "error handling timed out\n"); - del_timer(&info->eh_timer); + timer_delete(&info->eh_timer); if (info->rst_bus_status == 0) info->rst_bus_status = -1; @@ -2532,7 +2532,7 @@ int fas216_eh_device_reset(struct scsi_cmnd *SCpnt) */ wait_event(info->eh_wait, info->rst_dev_status); - del_timer_sync(&info->eh_timer); + timer_delete_sync(&info->eh_timer); spin_lock_irqsave(&info->host_lock, flags); info->rstSCpnt = NULL; @@ -2622,7 +2622,7 @@ int fas216_eh_bus_reset(struct scsi_cmnd *SCpnt) * Wait one second for the interrupt. */ wait_event(info->eh_wait, info->rst_bus_status); - del_timer_sync(&info->eh_timer); + timer_delete_sync(&info->eh_timer); fas216_log(info, LOG_ERROR, "bus reset complete: %s\n", info->rst_bus_status == 1 ? "success" : "failed");
diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index a8b399e..7d1b767 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c
@@ -5448,7 +5448,7 @@ static pci_ers_result_t beiscsi_eeh_err_detected(struct pci_dev *pdev, "BM_%d : EEH error detected\n"); /* first stop UE detection when PCI error detected */ - del_timer_sync(&phba->hw_check); + timer_delete_sync(&phba->hw_check); cancel_delayed_work_sync(&phba->recover_port); /* sessions are no longer valid, so first fail the sessions */ @@ -5746,7 +5746,7 @@ static void beiscsi_remove(struct pci_dev *pcidev) } /* first stop UE detection before unloading */ - del_timer_sync(&phba->hw_check); + timer_delete_sync(&phba->hw_check); cancel_delayed_work_sync(&phba->recover_port); cancel_work_sync(&phba->sess_work);
diff --git a/drivers/scsi/bfa/bfad.c b/drivers/scsi/bfa/bfad.c index f015c53..598f2fc 100644 --- a/drivers/scsi/bfa/bfad.c +++ b/drivers/scsi/bfa/bfad.c
@@ -327,7 +327,7 @@ bfad_sm_failed(struct bfad_s *bfad, enum bfad_sm_event event) case BFAD_E_EXIT_COMP: bfa_sm_set_state(bfad, bfad_sm_uninit); bfad_remove_intr(bfad); - del_timer_sync(&bfad->hal_tmo); + timer_delete_sync(&bfad->hal_tmo); break; default: @@ -376,7 +376,7 @@ bfad_sm_stopping(struct bfad_s *bfad, enum bfad_sm_event event) case BFAD_E_EXIT_COMP: bfa_sm_set_state(bfad, bfad_sm_uninit); bfad_remove_intr(bfad); - del_timer_sync(&bfad->hal_tmo); + timer_delete_sync(&bfad->hal_tmo); bfad_im_probe_undo(bfad); bfad->bfad_flags &= ~BFAD_FC4_PROBE_DONE; bfad_uncfg_pport(bfad); @@ -1421,7 +1421,7 @@ bfad_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state) /* Suspend/fail all bfa operations */ bfa_ioc_suspend(&bfad->bfa.ioc); spin_unlock_irqrestore(&bfad->bfad_lock, flags); - del_timer_sync(&bfad->hal_tmo); + timer_delete_sync(&bfad->hal_tmo); ret = PCI_ERS_RESULT_CAN_RECOVER; break; case pci_channel_io_frozen: /* fatal error */ @@ -1435,7 +1435,7 @@ bfad_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state) wait_for_completion(&bfad->comp); bfad_remove_intr(bfad); - del_timer_sync(&bfad->hal_tmo); + timer_delete_sync(&bfad->hal_tmo); pci_disable_device(pdev); ret = PCI_ERS_RESULT_NEED_RESET; break; @@ -1566,7 +1566,7 @@ bfad_pci_mmio_enabled(struct pci_dev *pdev) wait_for_completion(&bfad->comp); bfad_remove_intr(bfad); - del_timer_sync(&bfad->hal_tmo); + timer_delete_sync(&bfad->hal_tmo); pci_disable_device(pdev); return PCI_ERS_RESULT_NEED_RESET;
diff --git a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c index 5ac20c9..de6574c 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c +++ b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c
@@ -1599,7 +1599,7 @@ static void bnx2fc_interface_cleanup(struct bnx2fc_interface *interface) struct bnx2fc_hba *hba = interface->hba; /* Stop the transmit retry timer */ - del_timer_sync(&port->timer); + timer_delete_sync(&port->timer); /* Free existing transmit skbs */ fcoe_clean_pending_queue(lport); @@ -1938,7 +1938,7 @@ static void bnx2fc_fw_destroy(struct bnx2fc_hba *hba) if (signal_pending(current)) flush_signals(current); - del_timer_sync(&hba->destroy_timer); + timer_delete_sync(&hba->destroy_timer); } bnx2fc_unbind_adapter_devices(hba); }
diff --git a/drivers/scsi/bnx2fc/bnx2fc_tgt.c b/drivers/scsi/bnx2fc/bnx2fc_tgt.c index eb32091..b8227cf 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_tgt.c +++ b/drivers/scsi/bnx2fc/bnx2fc_tgt.c
@@ -74,7 +74,7 @@ static void bnx2fc_ofld_wait(struct bnx2fc_rport *tgt) &tgt->flags))); if (signal_pending(current)) flush_signals(current); - del_timer_sync(&tgt->ofld_timer); + timer_delete_sync(&tgt->ofld_timer); } static void bnx2fc_offload_session(struct fcoe_port *port, @@ -283,7 +283,7 @@ static void bnx2fc_upld_wait(struct bnx2fc_rport *tgt) &tgt->flags))); if (signal_pending(current)) flush_signals(current); - del_timer_sync(&tgt->upld_timer); + timer_delete_sync(&tgt->upld_timer); } static void bnx2fc_upload_session(struct fcoe_port *port,
diff --git a/drivers/scsi/bnx2i/bnx2i_iscsi.c b/drivers/scsi/bnx2i/bnx2i_iscsi.c index 9971f32..6c80e5b 100644 --- a/drivers/scsi/bnx2i/bnx2i_iscsi.c +++ b/drivers/scsi/bnx2i/bnx2i_iscsi.c
@@ -1626,7 +1626,7 @@ static int bnx2i_conn_start(struct iscsi_cls_conn *cls_conn) if (signal_pending(current)) flush_signals(current); - del_timer_sync(&bnx2i_conn->ep->ofld_timer); + timer_delete_sync(&bnx2i_conn->ep->ofld_timer); iscsi_conn_start(cls_conn); return 0; @@ -1749,7 +1749,7 @@ static int bnx2i_tear_down_conn(struct bnx2i_hba *hba, if (signal_pending(current)) flush_signals(current); - del_timer_sync(&ep->ofld_timer); + timer_delete_sync(&ep->ofld_timer); bnx2i_ep_destroy_list_del(hba, ep); @@ -1861,7 +1861,7 @@ static struct iscsi_endpoint *bnx2i_ep_connect(struct Scsi_Host *shost, if (signal_pending(current)) flush_signals(current); - del_timer_sync(&bnx2i_ep->ofld_timer); + timer_delete_sync(&bnx2i_ep->ofld_timer); bnx2i_ep_ofld_list_del(hba, bnx2i_ep); @@ -2100,7 +2100,7 @@ int bnx2i_hw_ep_disconnect(struct bnx2i_endpoint *bnx2i_ep) if (signal_pending(current)) flush_signals(current); - del_timer_sync(&bnx2i_ep->ofld_timer); + timer_delete_sync(&bnx2i_ep->ofld_timer); destroy_conn: bnx2i_ep_active_list_del(hba, bnx2i_ep);
diff --git a/drivers/scsi/csiostor/csio_hw.c b/drivers/scsi/csiostor/csio_hw.c index e43c541..beded09 100644 --- a/drivers/scsi/csiostor/csio_hw.c +++ b/drivers/scsi/csiostor/csio_hw.c
@@ -3701,7 +3701,7 @@ csio_mberr_worker(void *data) struct csio_mb *mbp_next; int rv; - del_timer_sync(&mbm->timer); + timer_delete_sync(&mbm->timer); spin_lock_irq(&hw->lock); if (list_empty(&mbm->cbfn_q)) { @@ -4210,7 +4210,7 @@ csio_mgmtm_init(struct csio_mgmtm *mgmtm, struct csio_hw *hw) static void csio_mgmtm_exit(struct csio_mgmtm *mgmtm) { - del_timer_sync(&mgmtm->mgmt_timer); + timer_delete_sync(&mgmtm->mgmt_timer); }
diff --git a/drivers/scsi/csiostor/csio_mb.c b/drivers/scsi/csiostor/csio_mb.c index 94810b1..c7b4c46 100644 --- a/drivers/scsi/csiostor/csio_mb.c +++ b/drivers/scsi/csiostor/csio_mb.c
@@ -1619,7 +1619,7 @@ csio_mb_cancel_all(struct csio_hw *hw, struct list_head *cbfn_q) mbp = mbm->mcurrent; /* Stop mailbox completion timer */ - del_timer_sync(&mbm->timer); + timer_delete_sync(&mbm->timer); /* Add completion to tail of cbfn queue */ list_add_tail(&mbp->list, cbfn_q); @@ -1682,7 +1682,7 @@ csio_mbm_init(struct csio_mbm *mbm, struct csio_hw *hw, void csio_mbm_exit(struct csio_mbm *mbm) { - del_timer_sync(&mbm->timer); + timer_delete_sync(&mbm->timer); CSIO_DB_ASSERT(mbm->mcurrent == NULL); CSIO_DB_ASSERT(list_empty(&mbm->req_q));
diff --git a/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c b/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c index ec65302..461d38e 100644 --- a/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c +++ b/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c
@@ -495,7 +495,7 @@ static int do_act_establish(struct t3cdev *tdev, struct sk_buff *skb, void *ctx) spin_lock_bh(&csk->lock); if (csk->retry_timer.function) { - del_timer(&csk->retry_timer); + timer_delete(&csk->retry_timer); csk->retry_timer.function = NULL; }
diff --git a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c index c07d2e3b..aaba294 100644 --- a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c +++ b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c
@@ -930,7 +930,7 @@ static void do_act_establish(struct cxgbi_device *cdev, struct sk_buff *skb) csk, csk->state, csk->flags, csk->tid); if (csk->retry_timer.function) { - del_timer(&csk->retry_timer); + timer_delete(&csk->retry_timer); csk->retry_timer.function = NULL; }
diff --git a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c index e71de24..8dc6be9 100644 --- a/drivers/scsi/dc395x.c +++ b/drivers/scsi/dc395x.c
@@ -765,7 +765,7 @@ static void waiting_process_next(struct AdapterCtlBlk *acb) return; if (timer_pending(&acb->waiting_timer)) - del_timer(&acb->waiting_timer); + timer_delete(&acb->waiting_timer); if (list_empty(dcb_list_head)) return; @@ -1153,7 +1153,7 @@ static int __dc395x_eh_bus_reset(struct scsi_cmnd *cmd) cmd, cmd->device->id, (u8)cmd->device->lun, cmd); if (timer_pending(&acb->waiting_timer)) - del_timer(&acb->waiting_timer); + timer_delete(&acb->waiting_timer); /* * disable interrupt @@ -1561,7 +1561,7 @@ static void dc395x_handle_interrupt(struct AdapterCtlBlk *acb, /*dprintkl(KERN_DEBUG, "handle_interrupt: intstatus = 0x%02x ", scsi_intstatus); */ if (timer_pending(&acb->selto_timer)) - del_timer(&acb->selto_timer); + timer_delete(&acb->selto_timer); if (scsi_intstatus & (INT_SELTIMEOUT | INT_DISCONNECT)) { disconnect(acb); /* bus free interrupt */ @@ -3454,7 +3454,7 @@ static void scsi_reset_detect(struct AdapterCtlBlk *acb) dprintkl(KERN_INFO, "scsi_reset_detect: acb=%p\n", acb); /* delay half a second */ if (timer_pending(&acb->waiting_timer)) - del_timer(&acb->waiting_timer); + timer_delete(&acb->waiting_timer); DC395x_write8(acb, TRM_S1040_SCSI_CONTROL, DO_RSTMODULE); DC395x_write8(acb, TRM_S1040_DMA_CONTROL, DMARESETMODULE); @@ -4415,9 +4415,9 @@ static void adapter_uninit(struct AdapterCtlBlk *acb) /* remove timers */ if (timer_pending(&acb->waiting_timer)) - del_timer(&acb->waiting_timer); + timer_delete(&acb->waiting_timer); if (timer_pending(&acb->selto_timer)) - del_timer(&acb->selto_timer); + timer_delete(&acb->selto_timer); adapter_uninit_chip(acb); adapter_remove_and_free_all_devices(acb);
diff --git a/drivers/scsi/elx/efct/efct_driver.c b/drivers/scsi/elx/efct/efct_driver.c index 59f2775..1bd42f7 100644 --- a/drivers/scsi/elx/efct/efct_driver.c +++ b/drivers/scsi/elx/efct/efct_driver.c
@@ -310,7 +310,7 @@ efct_fw_reset(struct efct *efct) * during attach. */ if (timer_pending(&efct->xport->stats_timer)) - del_timer(&efct->xport->stats_timer); + timer_delete(&efct->xport->stats_timer); if (efct_hw_reset(&efct->hw, EFCT_HW_RESET_FIRMWARE)) { efc_log_info(efct, "failed to reset firmware\n");
diff --git a/drivers/scsi/elx/efct/efct_xport.c b/drivers/scsi/elx/efct/efct_xport.c index cf4dced..2aca60f 100644 --- a/drivers/scsi/elx/efct/efct_xport.c +++ b/drivers/scsi/elx/efct/efct_xport.c
@@ -508,7 +508,7 @@ efct_xport_detach(struct efct_xport *xport) /*Shutdown FC Statistics timer*/ if (timer_pending(&xport->stats_timer)) - del_timer(&xport->stats_timer); + timer_delete(&xport->stats_timer); efct_hw_teardown(&efct->hw);
diff --git a/drivers/scsi/elx/libefc/efc_fabric.c b/drivers/scsi/elx/libefc/efc_fabric.c index 9661eea..cf7e738 100644 --- a/drivers/scsi/elx/libefc/efc_fabric.c +++ b/drivers/scsi/elx/libefc/efc_fabric.c
@@ -888,7 +888,7 @@ gidpt_delay_timer_cb(struct timer_list *t) { struct efc_node *node = from_timer(node, t, gidpt_delay_timer); - del_timer(&node->gidpt_delay_timer); + timer_delete(&node->gidpt_delay_timer); efc_node_post_event(node, EFC_EVT_GIDPT_DELAY_EXPIRED, NULL); }
diff --git a/drivers/scsi/elx/libefc/efc_node.c b/drivers/scsi/elx/libefc/efc_node.c index a1b4ce6..f17e052 100644 --- a/drivers/scsi/elx/libefc/efc_node.c +++ b/drivers/scsi/elx/libefc/efc_node.c
@@ -149,7 +149,7 @@ efc_node_free(struct efc_node *node) /* if the gidpt_delay_timer is still running, then delete it */ if (timer_pending(&node->gidpt_delay_timer)) - del_timer(&node->gidpt_delay_timer); + timer_delete(&node->gidpt_delay_timer); xa_erase(&nport->lookup, node->rnode.fc_id);
diff --git a/drivers/scsi/esas2r/esas2r_init.c b/drivers/scsi/esas2r/esas2r_init.c index 0cea5f3..04a07fe 100644 --- a/drivers/scsi/esas2r/esas2r_init.c +++ b/drivers/scsi/esas2r/esas2r_init.c
@@ -439,7 +439,7 @@ static void esas2r_adapter_power_down(struct esas2r_adapter *a, if ((test_bit(AF2_INIT_DONE, &a->flags2)) && (!test_bit(AF_DEGRADED_MODE, &a->flags))) { if (!power_management) { - del_timer_sync(&a->timer); + timer_delete_sync(&a->timer); tasklet_kill(&a->tasklet); } esas2r_power_down(a);
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index 038e3857..b911fdb 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c
@@ -1013,7 +1013,7 @@ static void fcoe_if_destroy(struct fc_lport *lport) fc_lport_destroy(lport); /* Stop the transmit retry timer */ - del_timer_sync(&port->timer); + timer_delete_sync(&port->timer); /* Free existing transmit skbs */ fcoe_clean_pending_queue(lport);
diff --git a/drivers/scsi/fcoe/fcoe_ctlr.c b/drivers/scsi/fcoe/fcoe_ctlr.c index 5c8d1ba..56d2705 100644 --- a/drivers/scsi/fcoe/fcoe_ctlr.c +++ b/drivers/scsi/fcoe/fcoe_ctlr.c
@@ -302,7 +302,7 @@ void fcoe_ctlr_destroy(struct fcoe_ctlr *fip) fcoe_ctlr_set_state(fip, FIP_ST_DISABLED); fcoe_ctlr_reset_fcfs(fip); mutex_unlock(&fip->ctlr_mutex); - del_timer_sync(&fip->timer); + timer_delete_sync(&fip->timer); cancel_work_sync(&fip->timer_work); } EXPORT_SYMBOL(fcoe_ctlr_destroy); @@ -478,7 +478,7 @@ EXPORT_SYMBOL(fcoe_ctlr_link_up); static void fcoe_ctlr_reset(struct fcoe_ctlr *fip) { fcoe_ctlr_reset_fcfs(fip); - del_timer(&fip->timer); + timer_delete(&fip->timer); fip->ctlr_ka_time = 0; fip->port_ka_time = 0; fip->sol_time = 0;
diff --git a/drivers/scsi/fnic/fdls_disc.c b/drivers/scsi/fnic/fdls_disc.c index 4c6bbf4..c2b6f4e 100644 --- a/drivers/scsi/fnic/fdls_disc.c +++ b/drivers/scsi/fnic/fdls_disc.c
@@ -394,7 +394,7 @@ void fnic_del_fabric_timer_sync(struct fnic *fnic) { fnic->iport.fabric.del_timer_inprogress = 1; spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags); - del_timer_sync(&fnic->iport.fabric.retry_timer); + timer_delete_sync(&fnic->iport.fabric.retry_timer); spin_lock_irqsave(&fnic->fnic_lock, fnic->lock_flags); fnic->iport.fabric.del_timer_inprogress = 0; } @@ -404,7 +404,7 @@ void fnic_del_tport_timer_sync(struct fnic *fnic, { tport->del_timer_inprogress = 1; spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags); - del_timer_sync(&tport->retry_timer); + timer_delete_sync(&tport->retry_timer); spin_lock_irqsave(&fnic->fnic_lock, fnic->lock_flags); tport->del_timer_inprogress = 0; } @@ -3617,7 +3617,7 @@ static void fdls_process_fdmi_plogi_rsp(struct fnic_iport_s *iport, fdls_free_oxid(iport, oxid, &iport->active_oxid_fdmi_plogi); if (ntoh24(fchdr->fh_s_id) == FC_FID_MGMT_SERV) { - del_timer_sync(&iport->fabric.fdmi_timer); + timer_delete_sync(&iport->fabric.fdmi_timer); iport->fabric.fdmi_pending = 0; switch (plogi_rsp->els.fl_cmd) { case ELS_LS_ACC: @@ -3686,7 +3686,7 @@ static void fdls_process_fdmi_reg_ack(struct fnic_iport_s *iport, iport->fcid); if (!iport->fabric.fdmi_pending) { - del_timer_sync(&iport->fabric.fdmi_timer); + timer_delete_sync(&iport->fabric.fdmi_timer); FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num, "iport fcid: 0x%x: Canceling FDMI timer\n", iport->fcid); @@ -3728,7 +3728,7 @@ static void fdls_process_fdmi_abts_rsp(struct fnic_iport_s *iport, break; } - del_timer_sync(&iport->fabric.fdmi_timer); + timer_delete_sync(&iport->fabric.fdmi_timer); iport->fabric.fdmi_pending &= ~FDLS_FDMI_ABORT_PENDING; fdls_send_fdmi_plogi(iport); @@ -4971,7 +4971,7 @@ void fnic_fdls_link_down(struct fnic_iport_s *iport) } if ((fnic_fdmi_support == 1) && (iport->fabric.fdmi_pending > 0)) { - del_timer_sync(&iport->fabric.fdmi_timer); + timer_delete_sync(&iport->fabric.fdmi_timer); iport->fabric.fdmi_pending = 0; }
diff --git a/drivers/scsi/fnic/fip.c b/drivers/scsi/fnic/fip.c index 7bb8594..6e7c0b0 100644 --- a/drivers/scsi/fnic/fip.c +++ b/drivers/scsi/fnic/fip.c
@@ -319,7 +319,7 @@ void fnic_fcoe_fip_discovery_resp(struct fnic *fnic, struct fip_header *fiph) round_jiffies(fcs_ka_tov)); } else { if (timer_pending(&fnic->fcs_ka_timer)) - del_timer_sync(&fnic->fcs_ka_timer); + timer_delete_sync(&fnic->fcs_ka_timer); } if (fka_has_changed) { @@ -497,7 +497,7 @@ void fnic_fcoe_process_flogi_resp(struct fnic *fnic, struct fip_header *fiph) oxid = FNIC_STD_GET_OX_ID(fchdr); fdls_free_oxid(iport, oxid, &iport->active_oxid_fabric_req); - del_timer_sync(&fnic->retry_fip_timer); + timer_delete_sync(&fnic->retry_fip_timer); if ((be16_to_cpu(flogi_rsp->fip.fip_dl_len) == FIP_FLOGI_LEN) && (flogi_rsp->rsp_desc.flogi.els.fl_cmd == ELS_LS_ACC)) { @@ -580,10 +580,10 @@ void fnic_common_fip_cleanup(struct fnic *fnic) iport->fip.state = FDLS_FIP_INIT; - del_timer_sync(&fnic->retry_fip_timer); - del_timer_sync(&fnic->fcs_ka_timer); - del_timer_sync(&fnic->enode_ka_timer); - del_timer_sync(&fnic->vn_ka_timer); + timer_delete_sync(&fnic->retry_fip_timer); + timer_delete_sync(&fnic->fcs_ka_timer); + timer_delete_sync(&fnic->enode_ka_timer); + timer_delete_sync(&fnic->vn_ka_timer); if (!is_zero_ether_addr(iport->fpma)) vnic_dev_del_addr(fnic->vdev, iport->fpma);
diff --git a/drivers/scsi/fnic/fnic_main.c b/drivers/scsi/fnic/fnic_main.c index 3dd0637..9a357ff4 100644 --- a/drivers/scsi/fnic/fnic_main.c +++ b/drivers/scsi/fnic/fnic_main.c
@@ -1149,20 +1149,20 @@ static void fnic_remove(struct pci_dev *pdev) fnic_scsi_unload(fnic); if (vnic_dev_get_intr_mode(fnic->vdev) == VNIC_DEV_INTR_MODE_MSI) - del_timer_sync(&fnic->notify_timer); + timer_delete_sync(&fnic->notify_timer); if (fnic->config.flags & VFCF_FIP_CAPABLE) { - del_timer_sync(&fnic->retry_fip_timer); - del_timer_sync(&fnic->fcs_ka_timer); - del_timer_sync(&fnic->enode_ka_timer); - del_timer_sync(&fnic->vn_ka_timer); + timer_delete_sync(&fnic->retry_fip_timer); + timer_delete_sync(&fnic->fcs_ka_timer); + timer_delete_sync(&fnic->enode_ka_timer); + timer_delete_sync(&fnic->vn_ka_timer); fnic_free_txq(&fnic->fip_frame_queue); fnic_fcoe_reset_vlans(fnic); } if ((fnic_fdmi_support == 1) && (fnic->iport.fabric.fdmi_pending > 0)) - del_timer_sync(&fnic->iport.fabric.fdmi_timer); + timer_delete_sync(&fnic->iport.fabric.fdmi_timer); fnic_stats_debugfs_remove(fnic);
diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index 3596414..5cb1d3d 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -1548,7 +1548,7 @@ void hisi_sas_controller_reset_prepare(struct hisi_hba *hisi_hba) * which is also only used for v1/v2 hw to skip it for v3 hw */ if (hisi_hba->hw->sht) - del_timer_sync(&hisi_hba->timer); + timer_delete_sync(&hisi_hba->timer); set_bit(HISI_SAS_REJECT_CMD_BIT, &hisi_hba->flags); } @@ -2363,7 +2363,7 @@ void hisi_sas_free(struct hisi_hba *hisi_hba) for (i = 0; i < hisi_hba->n_phy; i++) { struct hisi_sas_phy *phy = &hisi_hba->phy[i]; - del_timer_sync(&phy->timer); + timer_delete_sync(&phy->timer); } if (hisi_hba->wq) @@ -2625,7 +2625,7 @@ void hisi_sas_remove(struct platform_device *pdev) struct hisi_hba *hisi_hba = sha->lldd_ha; struct Scsi_Host *shost = sha->shost; - del_timer_sync(&hisi_hba->timer); + timer_delete_sync(&hisi_hba->timer); sas_unregister_ha(sha); sas_remove_host(shost);
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c index 04ee027..a1fc400 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -2372,18 +2372,18 @@ static void slot_complete_v2_hw(struct hisi_hba *hisi_hba, case STAT_IO_COMPLETE: /* internal abort command complete */ ts->stat = TMF_RESP_FUNC_SUCC; - del_timer_sync(&slot->internal_abort_timer); + timer_delete_sync(&slot->internal_abort_timer); goto out; case STAT_IO_NO_DEVICE: ts->stat = TMF_RESP_FUNC_COMPLETE; - del_timer_sync(&slot->internal_abort_timer); + timer_delete_sync(&slot->internal_abort_timer); goto out; case STAT_IO_NOT_VALID: /* abort single io, controller don't find * the io need to abort */ ts->stat = TMF_RESP_FUNC_FAILED; - del_timer_sync(&slot->internal_abort_timer); + timer_delete_sync(&slot->internal_abort_timer); goto out; default: break; @@ -2654,7 +2654,7 @@ static int phy_up_v2_hw(int phy_no, struct hisi_hba *hisi_hba) if (is_sata_phy_v2_hw(hisi_hba, phy_no)) goto end; - del_timer(&phy->timer); + timer_delete(&phy->timer); if (phy_no == 8) { u32 port_state = hisi_sas_read32(hisi_hba, PORT_STATE); @@ -2730,7 +2730,7 @@ static int phy_down_v2_hw(int phy_no, struct hisi_hba *hisi_hba) struct hisi_sas_port *port = phy->port; struct device *dev = hisi_hba->dev; - del_timer(&phy->timer); + timer_delete(&phy->timer); hisi_sas_phy_write32(hisi_hba, phy_no, PHYCTRL_NOT_RDY_MSK, 1); phy_state = hisi_sas_read32(hisi_hba, PHY_STATE); @@ -2744,7 +2744,7 @@ static int phy_down_v2_hw(int phy_no, struct hisi_hba *hisi_hba) if (port && !get_wideport_bitmap_v2_hw(hisi_hba, port->id)) if (!check_any_wideports_v2_hw(hisi_hba) && timer_pending(&hisi_hba->timer)) - del_timer(&hisi_hba->timer); + timer_delete(&hisi_hba->timer); txid_auto = hisi_sas_phy_read32(hisi_hba, phy_no, TXID_AUTO); hisi_sas_phy_write32(hisi_hba, phy_no, TXID_AUTO, @@ -3204,7 +3204,7 @@ static irqreturn_t sata_int_v2_hw(int irq_no, void *p) u8 attached_sas_addr[SAS_ADDR_SIZE] = {0}; int phy_no, offset; - del_timer(&phy->timer); + timer_delete(&phy->timer); phy_no = sas_phy->id; initial_fis = &hisi_hba->initial_fis[phy_no];
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c index 095bbf8..2684d64 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
@@ -1609,7 +1609,7 @@ static irqreturn_t phy_up_v3_hw(int phy_no, struct hisi_hba *hisi_hba) phy->port_id = port_id; spin_lock(&phy->lock); /* Delete timer and set phy_attached atomically */ - del_timer(&phy->timer); + timer_delete(&phy->timer); phy->phy_attached = 1; spin_unlock(&phy->lock); @@ -1643,7 +1643,7 @@ static irqreturn_t phy_down_v3_hw(int phy_no, struct hisi_hba *hisi_hba) atomic_inc(&phy->down_cnt); - del_timer(&phy->timer); + timer_delete(&phy->timer); hisi_sas_phy_write32(hisi_hba, phy_no, PHYCTRL_NOT_RDY_MSK, 1); phy_state = hisi_sas_read32(hisi_hba, PHY_STATE);
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c index 773ec2f..4c493b0 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.c +++ b/drivers/scsi/ibmvscsi/ibmvfc.c
@@ -1110,7 +1110,7 @@ static void ibmvfc_fail_request(struct ibmvfc_event *evt, int error_code) } else evt->xfer_iu->mad_common.status = cpu_to_be16(IBMVFC_MAD_DRIVER_FAILED); - del_timer(&evt->timer); + timer_delete(&evt->timer); } /** @@ -1754,7 +1754,7 @@ static int ibmvfc_send_event(struct ibmvfc_event *evt, atomic_set(&evt->active, 0); list_del(&evt->queue_list); spin_unlock_irqrestore(&evt->queue->l_lock, flags); - del_timer(&evt->timer); + timer_delete(&evt->timer); /* If send_crq returns H_CLOSED, return SCSI_MLQUEUE_HOST_BUSY. * Firmware will send a CRQ with a transport event (0xFF) to @@ -3832,7 +3832,7 @@ static void ibmvfc_tasklet(void *data) spin_unlock_irqrestore(vhost->host->host_lock, flags); list_for_each_entry_safe(evt, temp, &evt_doneq, queue_list) { - del_timer(&evt->timer); + timer_delete(&evt->timer); list_del(&evt->queue_list); ibmvfc_trc_end(evt); evt->done(evt); @@ -3938,7 +3938,7 @@ static void ibmvfc_drain_sub_crq(struct ibmvfc_queue *scrq) spin_unlock_irqrestore(scrq->q_lock, flags); list_for_each_entry_safe(evt, temp, &evt_doneq, queue_list) { - del_timer(&evt->timer); + timer_delete(&evt->timer); list_del(&evt->queue_list); ibmvfc_trc_end(evt); evt->done(evt); @@ -4542,7 +4542,7 @@ static void ibmvfc_tgt_adisc_done(struct ibmvfc_event *evt) vhost->discovery_threads--; ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_NONE); - del_timer(&tgt->timer); + timer_delete(&tgt->timer); switch (status) { case IBMVFC_MAD_SUCCESS: @@ -4741,7 +4741,7 @@ static void ibmvfc_tgt_adisc(struct ibmvfc_target *tgt) ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_INIT_WAIT); if (ibmvfc_send_event(evt, vhost, IBMVFC_ADISC_PLUS_CANCEL_TIMEOUT)) { vhost->discovery_threads--; - del_timer(&tgt->timer); + timer_delete(&tgt->timer); ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_NONE); kref_put(&tgt->kref, ibmvfc_release_tgt); } else @@ -5519,7 +5519,7 @@ static void ibmvfc_tgt_add_rport(struct ibmvfc_target *tgt) ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DELETED_RPORT); spin_unlock_irqrestore(vhost->host->host_lock, flags); fc_remote_port_delete(rport); - del_timer_sync(&tgt->timer); + timer_delete_sync(&tgt->timer); kref_put(&tgt->kref, ibmvfc_release_tgt); return; } else if (rport && tgt->action == IBMVFC_TGT_ACTION_DEL_AND_LOGOUT_RPORT) { @@ -5672,7 +5672,7 @@ static void ibmvfc_do_work(struct ibmvfc_host *vhost) spin_unlock_irqrestore(vhost->host->host_lock, flags); if (rport) fc_remote_port_delete(rport); - del_timer_sync(&tgt->timer); + timer_delete_sync(&tgt->timer); kref_put(&tgt->kref, ibmvfc_release_tgt); return; } else if (tgt->action == IBMVFC_TGT_ACTION_DEL_AND_LOGOUT_RPORT) {
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c index 16a1aac..d65a4586 100644 --- a/drivers/scsi/ibmvscsi/ibmvscsi.c +++ b/drivers/scsi/ibmvscsi/ibmvscsi.c
@@ -789,7 +789,7 @@ static void purge_requests(struct ibmvscsi_host_data *hostdata, int error_code) while (!list_empty(&hostdata->sent)) { evt = list_first_entry(&hostdata->sent, struct srp_event_struct, list); list_del(&evt->list); - del_timer(&evt->timer); + timer_delete(&evt->timer); spin_unlock_irqrestore(hostdata->host->host_lock, flags); if (evt->cmnd) { @@ -944,7 +944,7 @@ static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct, be64_to_cpu(crq_as_u64[1])); if (rc != 0) { list_del(&evt_struct->list); - del_timer(&evt_struct->timer); + timer_delete(&evt_struct->timer); /* If send_crq returns H_CLOSED, return SCSI_MLQUEUE_HOST_BUSY. * Firmware will send a CRQ with a transport event (0xFF) to @@ -1840,7 +1840,7 @@ static void ibmvscsi_handle_crq(struct viosrp_crq *crq, atomic_add(be32_to_cpu(evt_struct->xfer_iu->srp.rsp.req_lim_delta), &hostdata->request_limit); - del_timer(&evt_struct->timer); + timer_delete(&evt_struct->timer); if ((crq->status != VIOSRP_OK && crq->status != VIOSRP_OK2) && evt_struct->cmnd) evt_struct->cmnd->result = DID_ERROR << 16;
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 3bfafd4..d89135f 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c
@@ -873,7 +873,7 @@ static void ipr_fail_all_ops(struct ipr_ioa_cfg *ioa_cfg) ipr_trc_hook(ipr_cmd, IPR_TRACE_FINISH, IPR_IOASC_IOA_WAS_RESET); - del_timer(&ipr_cmd->timer); + timer_delete(&ipr_cmd->timer); ipr_cmd->done(ipr_cmd); } spin_unlock(&hrrq->_lock); @@ -5347,7 +5347,7 @@ static irqreturn_t ipr_handle_other_interrupt(struct ipr_ioa_cfg *ioa_cfg, writel(IPR_PCII_IPL_STAGE_CHANGE, ioa_cfg->regs.clr_interrupt_reg); int_reg = readl(ioa_cfg->regs.sense_interrupt_reg) & ~int_mask_reg; list_del(&ioa_cfg->reset_cmd->queue); - del_timer(&ioa_cfg->reset_cmd->timer); + timer_delete(&ioa_cfg->reset_cmd->timer); ipr_reset_ioa_job(ioa_cfg->reset_cmd); return IRQ_HANDLED; } @@ -5362,7 +5362,7 @@ static irqreturn_t ipr_handle_other_interrupt(struct ipr_ioa_cfg *ioa_cfg, int_reg = readl(ioa_cfg->regs.sense_interrupt_reg); list_del(&ioa_cfg->reset_cmd->queue); - del_timer(&ioa_cfg->reset_cmd->timer); + timer_delete(&ioa_cfg->reset_cmd->timer); ipr_reset_ioa_job(ioa_cfg->reset_cmd); } else if ((int_reg & IPR_PCII_HRRQ_UPDATED) == int_reg) { if (ioa_cfg->clear_isr) { @@ -5481,7 +5481,7 @@ static int ipr_iopoll(struct irq_poll *iop, int budget) list_for_each_entry_safe(ipr_cmd, temp, &doneq, queue) { list_del(&ipr_cmd->queue); - del_timer(&ipr_cmd->timer); + timer_delete(&ipr_cmd->timer); ipr_cmd->fast_done(ipr_cmd); } @@ -5550,7 +5550,7 @@ static irqreturn_t ipr_isr(int irq, void *devp) spin_unlock_irqrestore(hrrq->lock, hrrq_flags); list_for_each_entry_safe(ipr_cmd, temp, &doneq, queue) { list_del(&ipr_cmd->queue); - del_timer(&ipr_cmd->timer); + timer_delete(&ipr_cmd->timer); ipr_cmd->fast_done(ipr_cmd); } return rc; @@ -5600,7 +5600,7 @@ static irqreturn_t ipr_isr_mhrrq(int irq, void *devp) list_for_each_entry_safe(ipr_cmd, temp, &doneq, queue) { list_del(&ipr_cmd->queue); - del_timer(&ipr_cmd->timer); + timer_delete(&ipr_cmd->timer); ipr_cmd->fast_done(ipr_cmd); } return rc;
diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index 35589b6..c108b5b 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c
@@ -1271,22 +1271,22 @@ void isci_host_deinit(struct isci_host *ihost) /* Cancel any/all outstanding port timers */ for (i = 0; i < ihost->logical_port_entries; i++) { struct isci_port *iport = &ihost->ports[i]; - del_timer_sync(&iport->timer.timer); + timer_delete_sync(&iport->timer.timer); } /* Cancel any/all outstanding phy timers */ for (i = 0; i < SCI_MAX_PHYS; i++) { struct isci_phy *iphy = &ihost->phys[i]; - del_timer_sync(&iphy->sata_timer.timer); + timer_delete_sync(&iphy->sata_timer.timer); } - del_timer_sync(&ihost->port_agent.timer.timer); + timer_delete_sync(&ihost->port_agent.timer.timer); - del_timer_sync(&ihost->power_control.timer.timer); + timer_delete_sync(&ihost->power_control.timer.timer); - del_timer_sync(&ihost->timer.timer); + timer_delete_sync(&ihost->timer.timer); - del_timer_sync(&ihost->phy_timer.timer); + timer_delete_sync(&ihost->phy_timer.timer); } static void __iomem *scu_base(struct isci_host *isci_host)
diff --git a/drivers/scsi/isci/isci.h b/drivers/scsi/isci/isci.h index f6a8fe2..d827e49 100644 --- a/drivers/scsi/isci/isci.h +++ b/drivers/scsi/isci/isci.h
@@ -481,9 +481,9 @@ irqreturn_t isci_error_isr(int vec, void *data); /* * Each timer is associated with a cancellation flag that is set when - * del_timer() is called and checked in the timer callback function. This - * is needed since del_timer_sync() cannot be called with sci_lock held. - * For deinit however, del_timer_sync() is used without holding the lock. + * timer_delete() is called and checked in the timer callback function. This + * is needed since timer_delete_sync() cannot be called with sci_lock held. + * For deinit however, timer_delete_sync() is used without holding the lock. */ struct sci_timer { struct timer_list timer; @@ -506,7 +506,7 @@ static inline void sci_mod_timer(struct sci_timer *tmr, unsigned long msec) static inline void sci_del_timer(struct sci_timer *tmr) { tmr->cancel = true; - del_timer(&tmr->timer); + timer_delete(&tmr->timer); } struct sci_base_state_machine {
diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index fd1ef06..e705c30 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c
@@ -1329,7 +1329,7 @@ static int fc_lun_reset(struct fc_lport *lport, struct fc_fcp_pkt *fsp, fsp->state |= FC_SRB_COMPL; spin_unlock_bh(&fsp->scsi_pkt_lock); - del_timer_sync(&fsp->timer); + timer_delete_sync(&fsp->timer); spin_lock_bh(&fsp->scsi_pkt_lock); if (fsp->seq_ptr) { @@ -1961,7 +1961,7 @@ static void fc_io_compl(struct fc_fcp_pkt *fsp) fsp->state |= FC_SRB_COMPL; if (!(fsp->state & FC_SRB_FCP_PROCESSING_TMO)) { spin_unlock_bh(&fsp->scsi_pkt_lock); - del_timer_sync(&fsp->timer); + timer_delete_sync(&fsp->timer); spin_lock_bh(&fsp->scsi_pkt_lock); }
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 2b1bf99..1ddaf72 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c
@@ -1945,7 +1945,7 @@ static int iscsi_exec_task_mgmt_fn(struct iscsi_conn *conn, session->tmf_state != TMF_QUEUED); if (signal_pending(current)) flush_signals(current); - del_timer_sync(&session->tmf_timer); + timer_delete_sync(&session->tmf_timer); mutex_lock(&session->eh_mutex); spin_lock_bh(&session->frwd_lock); @@ -3247,7 +3247,7 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn) iscsi_remove_conn(cls_conn); - del_timer_sync(&conn->transport_timer); + timer_delete_sync(&conn->transport_timer); mutex_lock(&session->eh_mutex); spin_lock_bh(&session->frwd_lock); @@ -3411,7 +3411,7 @@ void iscsi_conn_stop(struct iscsi_cls_conn *cls_conn, int flag) conn->stop_stage = flag; spin_unlock_bh(&session->frwd_lock); - del_timer_sync(&conn->transport_timer); + timer_delete_sync(&conn->transport_timer); iscsi_suspend_tx(conn); spin_lock_bh(&session->frwd_lock);
diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c index 2b8004e..869b5d4 100644 --- a/drivers/scsi/libsas/sas_expander.c +++ b/drivers/scsi/libsas/sas_expander.c
@@ -89,7 +89,7 @@ static int smp_execute_task_sg(struct domain_device *dev, res = i->dft->lldd_execute_task(task, GFP_KERNEL); if (res) { - del_timer_sync(&task->slow_task->timer); + timer_delete_sync(&task->slow_task->timer); pr_notice("executing SMP task failed:%d\n", res); break; }
diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c index 55ce789..feb2461 100644 --- a/drivers/scsi/libsas/sas_scsi_host.c +++ b/drivers/scsi/libsas/sas_scsi_host.c
@@ -859,7 +859,7 @@ EXPORT_SYMBOL_GPL(sas_bios_param); void sas_task_internal_done(struct sas_task *task) { - del_timer(&task->slow_task->timer); + timer_delete(&task->slow_task->timer); complete(&task->slow_task->completion); } @@ -911,7 +911,7 @@ static int sas_execute_internal_abort(struct domain_device *device, res = i->dft->lldd_execute_task(task, GFP_KERNEL); if (res) { - del_timer_sync(&task->slow_task->timer); + timer_delete_sync(&task->slow_task->timer); pr_err("Executing internal abort failed %016llx (%d)\n", SAS_ADDR(device->sas_addr), res); break; @@ -1010,7 +1010,7 @@ int sas_execute_tmf(struct domain_device *device, void *parameter, res = i->dft->lldd_execute_task(task, GFP_KERNEL); if (res) { - del_timer_sync(&task->slow_task->timer); + timer_delete_sync(&task->slow_task->timer); pr_err("executing TMF task failed %016llx (%d)\n", SAS_ADDR(device->sas_addr), res); break; @@ -1180,7 +1180,7 @@ void sas_task_abort(struct sas_task *task) if (!slow) return; - if (!del_timer(&slow->timer)) + if (!timer_delete(&slow->timer)) return; slow->timer.function(&slow->timer); return;
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index 0d0213b..397216f 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -2578,7 +2578,7 @@ lpfc_poll_store(struct device *dev, struct device_attribute *attr, (old_val & DISABLE_FCP_RING_INT)) { spin_unlock_irq(&phba->hbalock); - del_timer(&phba->fcp_poll_timer); + timer_delete(&phba->fcp_poll_timer); spin_lock_irq(&phba->hbalock); if (lpfc_readl(phba->HCregaddr, &creg_val)) { spin_unlock_irq(&phba->hbalock);
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index e08b48b..375a879 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -4333,7 +4333,7 @@ lpfc_cancel_retry_delay_tmo(struct lpfc_vport *vport, struct lpfc_nodelist *nlp) if (!test_and_clear_bit(NLP_DELAY_TMO, &nlp->nlp_flag)) return; - del_timer_sync(&nlp->nlp_delayfunc); + timer_delete_sync(&nlp->nlp_delayfunc); nlp->nlp_last_elscmd = 0; if (!list_empty(&nlp->els_retry_evt.evt_listp)) { list_del_init(&nlp->els_retry_evt.evt_listp); @@ -4431,7 +4431,7 @@ lpfc_els_retry_delay_handler(struct lpfc_nodelist *ndlp) * firing and before processing the timer, cancel the * nlp_delayfunc. */ - del_timer_sync(&ndlp->nlp_delayfunc); + timer_delete_sync(&ndlp->nlp_delayfunc); retry = ndlp->nlp_retry; ndlp->nlp_retry = 0;
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 8ca590e..179be6c 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
@@ -1228,7 +1228,7 @@ lpfc_linkdown_port(struct lpfc_vport *vport) /* Stop delayed Nport discovery */ clear_bit(FC_DISC_DELAYED, &vport->fc_flag); - del_timer_sync(&vport->delayed_disc_tmo); + timer_delete_sync(&vport->delayed_disc_tmo); if (phba->sli_rev == LPFC_SLI_REV4 && vport->port_type == LPFC_PHYSICAL_PORT && @@ -1418,7 +1418,7 @@ lpfc_linkup(struct lpfc_hba *phba) /* Unblock fabric iocbs if they are blocked */ clear_bit(FABRIC_COMANDS_BLOCKED, &phba->bit_flags); - del_timer_sync(&phba->fabric_block_timer); + timer_delete_sync(&phba->fabric_block_timer); vports = lpfc_create_vport_work_array(phba); if (vports != NULL) @@ -5010,7 +5010,7 @@ lpfc_can_disctmo(struct lpfc_vport *vport) if (test_bit(FC_DISC_TMO, &vport->fc_flag) || timer_pending(&vport->fc_disctmo)) { clear_bit(FC_DISC_TMO, &vport->fc_flag); - del_timer_sync(&vport->fc_disctmo); + timer_delete_sync(&vport->fc_disctmo); spin_lock_irqsave(&vport->work_port_lock, iflags); vport->work_port_events &= ~WORKER_DISC_TMO; spin_unlock_irqrestore(&vport->work_port_lock, iflags); @@ -5501,7 +5501,7 @@ lpfc_cleanup_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) clear_bit(NLP_DELAY_TMO, &ndlp->nlp_flag); ndlp->nlp_last_elscmd = 0; - del_timer_sync(&ndlp->nlp_delayfunc); + timer_delete_sync(&ndlp->nlp_delayfunc); list_del_init(&ndlp->els_retry_evt.evt_listp); list_del_init(&ndlp->dev_loss_evt.evt_listp);
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 7238608..9002165 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -3120,8 +3120,8 @@ lpfc_cleanup(struct lpfc_vport *vport) void lpfc_stop_vport_timers(struct lpfc_vport *vport) { - del_timer_sync(&vport->els_tmofunc); - del_timer_sync(&vport->delayed_disc_tmo); + timer_delete_sync(&vport->els_tmofunc); + timer_delete_sync(&vport->delayed_disc_tmo); lpfc_can_disctmo(vport); return; } @@ -3140,7 +3140,7 @@ __lpfc_sli4_stop_fcf_redisc_wait_timer(struct lpfc_hba *phba) phba->fcf.fcf_flag &= ~FCF_REDISC_PEND; /* Now, try to stop the timer */ - del_timer(&phba->fcf.redisc_wait); + timer_delete(&phba->fcf.redisc_wait); } /** @@ -3302,12 +3302,12 @@ lpfc_stop_hba_timers(struct lpfc_hba *phba) lpfc_stop_vport_timers(phba->pport); cancel_delayed_work_sync(&phba->eq_delay_work); cancel_delayed_work_sync(&phba->idle_stat_delay_work); - del_timer_sync(&phba->sli.mbox_tmo); - del_timer_sync(&phba->fabric_block_timer); - del_timer_sync(&phba->eratt_poll); - del_timer_sync(&phba->hb_tmofunc); + timer_delete_sync(&phba->sli.mbox_tmo); + timer_delete_sync(&phba->fabric_block_timer); + timer_delete_sync(&phba->eratt_poll); + timer_delete_sync(&phba->hb_tmofunc); if (phba->sli_rev == LPFC_SLI_REV4) { - del_timer_sync(&phba->rrq_tmr); + timer_delete_sync(&phba->rrq_tmr); clear_bit(HBA_RRQ_ACTIVE, &phba->hba_flag); } clear_bit(HBA_HBEAT_INP, &phba->hba_flag); @@ -3316,7 +3316,7 @@ lpfc_stop_hba_timers(struct lpfc_hba *phba) switch (phba->pci_dev_grp) { case LPFC_PCI_DEV_LP: /* Stop any LightPulse device specific driver timers */ - del_timer_sync(&phba->fcp_poll_timer); + timer_delete_sync(&phba->fcp_poll_timer); break; case LPFC_PCI_DEV_OC: /* Stop any OneConnect device specific driver timers */ @@ -12761,7 +12761,7 @@ static void __lpfc_cpuhp_remove(struct lpfc_hba *phba) * timer. Wait for the poll timer to retire. */ synchronize_rcu(); - del_timer_sync(&phba->cpuhp_poll_timer); + timer_delete_sync(&phba->cpuhp_poll_timer); } static void lpfc_cpuhp_remove(struct lpfc_hba *phba)
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index f0158fc..9edf80b 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c
@@ -5488,7 +5488,7 @@ void lpfc_vmid_vport_cleanup(struct lpfc_vport *vport) struct lpfc_vmid *cur; if (vport->port_type == LPFC_PHYSICAL_PORT) - del_timer_sync(&vport->phba->inactive_vmid_poll); + timer_delete_sync(&vport->phba->inactive_vmid_poll); kfree(vport->qfpa_res); kfree(vport->vmid_priority.vmid_range);
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 4e0d48f..6574f9e 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -5041,7 +5041,7 @@ lpfc_sli_brdkill(struct lpfc_hba *phba) return 1; } - del_timer_sync(&psli->mbox_tmo); + timer_delete_sync(&psli->mbox_tmo); if (ha_copy & HA_ERATT) { writel(HA_ERATT, phba->HAregaddr); phba->pport->stopped = 1; @@ -12076,7 +12076,7 @@ lpfc_sli_hba_down(struct lpfc_hba *phba) local_bh_enable(); /* Return any active mbox cmds */ - del_timer_sync(&psli->mbox_tmo); + timer_delete_sync(&psli->mbox_tmo); spin_lock_irqsave(&phba->pport->work_port_lock, flags); phba->pport->work_port_events &= ~WORKER_MBOX_TMO; @@ -13802,7 +13802,7 @@ lpfc_sli_sp_intr_handler(int irq, void *dev_id) phba->sli.mbox_active = NULL; spin_unlock_irqrestore(&phba->hbalock, iflag); phba->last_completion_time = jiffies; - del_timer(&phba->sli.mbox_tmo); + timer_delete(&phba->sli.mbox_tmo); if (pmb->mbox_cmpl) { lpfc_sli_pcimem_bcopy(mbox, pmbox, MAILBOX_CMD_SIZE); @@ -14302,7 +14302,7 @@ lpfc_sli4_sp_handle_mbox_event(struct lpfc_hba *phba, struct lpfc_mcqe *mcqe) /* Reset heartbeat timer */ phba->last_completion_time = jiffies; - del_timer(&phba->sli.mbox_tmo); + timer_delete(&phba->sli.mbox_tmo); /* Move mbox data to caller's mailbox region, do endian swapping */ if (pmb->mbox_cmpl && mbox) @@ -15689,7 +15689,7 @@ static inline void lpfc_sli4_remove_from_poll_list(struct lpfc_queue *eq) synchronize_rcu(); if (list_empty(&phba->poll_list)) - del_timer_sync(&phba->cpuhp_poll_timer); + timer_delete_sync(&phba->cpuhp_poll_timer); } void lpfc_sli4_cleanup_poll_list(struct lpfc_hba *phba)
diff --git a/drivers/scsi/megaraid/megaraid_mbox.c b/drivers/scsi/megaraid/megaraid_mbox.c index 3ba837b..d533a8a 100644 --- a/drivers/scsi/megaraid/megaraid_mbox.c +++ b/drivers/scsi/megaraid/megaraid_mbox.c
@@ -3951,7 +3951,7 @@ megaraid_sysfs_get_ldmap(adapter_t *adapter) } - del_timer_sync(&timeout.timer); + timer_delete_sync(&timeout.timer); destroy_timer_on_stack(&timeout.timer); mutex_unlock(&raid_dev->sysfs_mtx);
diff --git a/drivers/scsi/megaraid/megaraid_mm.c b/drivers/scsi/megaraid/megaraid_mm.c index c509440..1f2cd15 100644 --- a/drivers/scsi/megaraid/megaraid_mm.c +++ b/drivers/scsi/megaraid/megaraid_mm.c
@@ -703,7 +703,7 @@ lld_ioctl(mraid_mmadp_t *adp, uioc_t *kioc) */ wait_event(wait_q, (kioc->status != -ENODATA)); if (timeout.timer.function) { - del_timer_sync(&timeout.timer); + timer_delete_sync(&timeout.timer); destroy_timer_on_stack(&timeout.timer); }
diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index 28c7586..c20447b 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c
@@ -6521,7 +6521,7 @@ static int megasas_init_fw(struct megasas_instance *instance) fail_start_watchdog: if (instance->requestorId && !instance->skip_heartbeat_timer_del) - del_timer_sync(&instance->sriov_heartbeat_timer); + timer_delete_sync(&instance->sriov_heartbeat_timer); fail_get_ld_pd_list: instance->instancet->disable_intr(instance); megasas_destroy_irqs(instance); @@ -7603,7 +7603,7 @@ static int megasas_probe_one(struct pci_dev *pdev, megasas_mgmt_info.instance[megasas_mgmt_info.max_index] = NULL; if (instance->requestorId && !instance->skip_heartbeat_timer_del) - del_timer_sync(&instance->sriov_heartbeat_timer); + timer_delete_sync(&instance->sriov_heartbeat_timer); instance->instancet->disable_intr(instance); megasas_destroy_irqs(instance); @@ -7743,7 +7743,7 @@ megasas_suspend(struct device *dev) /* Shutdown SR-IOV heartbeat timer */ if (instance->requestorId && !instance->skip_heartbeat_timer_del) - del_timer_sync(&instance->sriov_heartbeat_timer); + timer_delete_sync(&instance->sriov_heartbeat_timer); /* Stop the FW fault detection watchdog */ if (instance->adapter_type != MFI_SERIES) @@ -7907,7 +7907,7 @@ megasas_resume(struct device *dev) fail_start_watchdog: if (instance->requestorId && !instance->skip_heartbeat_timer_del) - del_timer_sync(&instance->sriov_heartbeat_timer); + timer_delete_sync(&instance->sriov_heartbeat_timer); fail_init_mfi: megasas_free_ctrl_dma_buffers(instance); megasas_free_ctrl_mem(instance); @@ -7971,7 +7971,7 @@ static void megasas_detach_one(struct pci_dev *pdev) /* Shutdown SR-IOV heartbeat timer */ if (instance->requestorId && !instance->skip_heartbeat_timer_del) - del_timer_sync(&instance->sriov_heartbeat_timer); + timer_delete_sync(&instance->sriov_heartbeat_timer); /* Stop the FW fault detection watchdog */ if (instance->adapter_type != MFI_SERIES)
diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c index 1eec23d..721860c 100644 --- a/drivers/scsi/megaraid/megaraid_sas_fusion.c +++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c
@@ -4969,7 +4969,7 @@ int megasas_reset_fusion(struct Scsi_Host *shost, int reason) } if (instance->requestorId && !instance->skip_heartbeat_timer_del) - del_timer_sync(&instance->sriov_heartbeat_timer); + timer_delete_sync(&instance->sriov_heartbeat_timer); set_bit(MEGASAS_FUSION_IN_RESET, &instance->reset_flags); set_bit(MEGASAS_FUSION_OCR_NOT_POSSIBLE, &instance->reset_flags); atomic_set(&instance->adprecovery, MEGASAS_ADPRESET_SM_POLLING);
diff --git a/drivers/scsi/mvsas/mv_sas.c b/drivers/scsi/mvsas/mv_sas.c index c4592de..52ac102 100644 --- a/drivers/scsi/mvsas/mv_sas.c +++ b/drivers/scsi/mvsas/mv_sas.c
@@ -976,7 +976,7 @@ static u32 mvs_is_sig_fis_received(u32 irq_status) static void mvs_sig_remove_timer(struct mvs_phy *phy) { if (phy->timer.function) - del_timer(&phy->timer); + timer_delete(&phy->timer); phy->timer.function = NULL; }
diff --git a/drivers/scsi/pmcraid.c b/drivers/scsi/pmcraid.c index 3ba5391..e0aeb20 100644 --- a/drivers/scsi/pmcraid.c +++ b/drivers/scsi/pmcraid.c
@@ -495,7 +495,7 @@ static void pmcraid_clr_trans_op( } if (pinstance->reset_cmd != NULL) { - del_timer(&pinstance->reset_cmd->timer); + timer_delete(&pinstance->reset_cmd->timer); spin_lock_irqsave( pinstance->host->host_lock, lock_flags); pinstance->reset_cmd->cmd_done(pinstance->reset_cmd); @@ -1999,7 +1999,7 @@ static void pmcraid_fail_outstanding_cmds(struct pmcraid_instance *pinstance) cpu_to_le32(PMCRAID_DRIVER_ILID); /* In case the command timer is still running */ - del_timer(&cmd->timer); + timer_delete(&cmd->timer); /* If this is an IO command, complete it by invoking scsi_done * function. If this is one of the internal commands other @@ -3982,7 +3982,7 @@ static void pmcraid_tasklet_function(unsigned long instance) list_del(&cmd->free_list); spin_unlock_irqrestore(&pinstance->pending_pool_lock, pending_lock_flags); - del_timer(&cmd->timer); + timer_delete(&cmd->timer); atomic_dec(&pinstance->outstanding_cmds); if (cmd->cmd_done == pmcraid_ioa_reset) {
diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c index 47d74f8..078a9c8 100644 --- a/drivers/scsi/qla1280.c +++ b/drivers/scsi/qla1280.c
@@ -2454,7 +2454,7 @@ qla1280_mailbox_command(struct scsi_qla_host *ha, uint8_t mr, uint16_t *mb) qla1280_debounce_register(®->istatus); wait_for_completion(&wait); - del_timer_sync(&ha->mailbox_timer); + timer_delete_sync(&ha->mailbox_timer); spin_lock_irq(ha->host->host_lock);
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 79cdfec..0c2dd78 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -67,7 +67,7 @@ void qla2x00_sp_free(srb_t *sp) { struct srb_iocb *iocb = &sp->u.iocb_cmd; - del_timer(&iocb->timer); + timer_delete(&iocb->timer); qla2x00_rel_sp(sp); }
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index 0b41e8a..3224044 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c
@@ -2572,7 +2572,7 @@ qla24xx_tm_iocb(srb_t *sp, struct tsk_mgmt_entry *tsk) static void qla2x00_async_done(struct srb *sp, int res) { - if (del_timer(&sp->u.iocb_cmd.timer)) { + if (timer_delete(&sp->u.iocb_cmd.timer)) { /* * Successfully cancelled the timeout handler * ref: TMR @@ -2645,7 +2645,7 @@ static void qla2x00_els_dcmd_sp_free(srb_t *sp) elsio->u.els_logo.els_logo_pyld, elsio->u.els_logo.els_logo_pyld_dma); - del_timer(&elsio->timer); + timer_delete(&elsio->timer); qla2x00_rel_sp(sp); }
diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c index 79879c4..8b71ac0 100644 --- a/drivers/scsi/qla2xxx/qla_mid.c +++ b/drivers/scsi/qla2xxx/qla_mid.c
@@ -20,7 +20,7 @@ void qla2x00_vp_stop_timer(scsi_qla_host_t *vha) { if (vha->vp_idx && vha->timer_active) { - del_timer_sync(&vha->timer); + timer_delete_sync(&vha->timer); vha->timer_active = 0; } }
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 6b9b821..b44d134 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -401,7 +401,7 @@ qla2x00_restart_timer(scsi_qla_host_t *vha, unsigned long interval) static __inline__ void qla2x00_stop_timer(scsi_qla_host_t *vha) { - del_timer_sync(&vha->timer); + timer_delete_sync(&vha->timer); vha->timer_active = 0; }
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index 6b0e6b4..d540d66 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c
@@ -4021,7 +4021,7 @@ static void qla4xxx_start_timer(struct scsi_qla_host *ha, static void qla4xxx_stop_timer(struct scsi_qla_host *ha) { - del_timer_sync(&ha->timer); + timer_delete_sync(&ha->timer); ha->timer_active = 0; }
diff --git a/drivers/scsi/smartpqi/smartpqi_init.c b/drivers/scsi/smartpqi/smartpqi_init.c index 0da7be40..88135fd 100644 --- a/drivers/scsi/smartpqi/smartpqi_init.c +++ b/drivers/scsi/smartpqi/smartpqi_init.c
@@ -3853,7 +3853,7 @@ static void pqi_start_heartbeat_timer(struct pqi_ctrl_info *ctrl_info) static inline void pqi_stop_heartbeat_timer(struct pqi_ctrl_info *ctrl_info) { - del_timer_sync(&ctrl_info->heartbeat_timer); + timer_delete_sync(&ctrl_info->heartbeat_timer); } static void pqi_ofa_capture_event_payload(struct pqi_ctrl_info *ctrl_info,
diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c index 212d89d..1a6eb72 100644 --- a/drivers/scsi/sym53c8xx_2/sym_glue.c +++ b/drivers/scsi/sym53c8xx_2/sym_glue.c
@@ -1657,7 +1657,7 @@ static int sym_detach(struct Scsi_Host *shost, struct pci_dev *pdev) struct sym_hcb *np = sym_get_hcb(shost); printk("%s: detaching ...\n", sym_name(np)); - del_timer_sync(&np->s.timer); + timer_delete_sync(&np->s.timer); /* * Reset NCR chip.
diff --git a/drivers/soc/fsl/qe/qe_ic.c b/drivers/soc/fsl/qe/qe_ic.c index bbae3d3..77bf0e8 100644 --- a/drivers/soc/fsl/qe/qe_ic.c +++ b/drivers/soc/fsl/qe/qe_ic.c
@@ -344,7 +344,7 @@ static unsigned int qe_ic_get_low_irq(struct qe_ic *qe_ic) if (irq == 0) return 0; - return irq_linear_revmap(qe_ic->irqhost, irq); + return irq_find_mapping(qe_ic->irqhost, irq); } /* Return an interrupt vector or 0 if no interrupt is pending. */ @@ -360,7 +360,7 @@ static unsigned int qe_ic_get_high_irq(struct qe_ic *qe_ic) if (irq == 0) return 0; - return irq_linear_revmap(qe_ic->irqhost, irq); + return irq_find_mapping(qe_ic->irqhost, irq); } static void qe_ic_cascade_low(struct irq_desc *desc)
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index f40c282..ed38f6d 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig
@@ -937,9 +937,9 @@ QSPI(Quad SPI) driver for Qualcomm QSPI controller. config SPI_QPIC_SNAND - bool "QPIC SNAND controller" + tristate "QPIC SNAND controller" depends on ARCH_QCOM || COMPILE_TEST - select MTD + depends on MTD help QPIC_SNAND (QPIC SPI NAND) driver for Qualcomm QPIC controller. QPIC controller supports both parallel nand and serial nand.
diff --git a/drivers/spi/spi-amd.c b/drivers/spi/spi-amd.c index c859974..17fc0b1 100644 --- a/drivers/spi/spi-amd.c +++ b/drivers/spi/spi-amd.c
@@ -302,7 +302,7 @@ static void amd_set_spi_freq(struct amd_spi *amd_spi, u32 speed_hz) { unsigned int i, spd7_val, alt_spd; - for (i = 0; i < ARRAY_SIZE(amd_spi_freq); i++) + for (i = 0; i < ARRAY_SIZE(amd_spi_freq)-1; i++) if (speed_hz >= amd_spi_freq[i].speed_hz) break;
diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c index 0d1aa65..77de5a0 100644 --- a/drivers/spi/spi-bcm2835.c +++ b/drivers/spi/spi-bcm2835.c
@@ -1162,7 +1162,8 @@ static void bcm2835_spi_cleanup(struct spi_device *spi) sizeof(u32), DMA_TO_DEVICE); - gpiod_put(bs->cs_gpio); + if (!IS_ERR(bs->cs_gpio)) + gpiod_put(bs->cs_gpio); spi_set_csgpiod(spi, 0, NULL); kfree(target); @@ -1225,7 +1226,12 @@ static int bcm2835_spi_setup(struct spi_device *spi) struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr); struct bcm2835_spidev *target = spi_get_ctldata(spi); struct gpiod_lookup_table *lookup __free(kfree) = NULL; - int ret; + const char *pinctrl_compats[] = { + "brcm,bcm2835-gpio", + "brcm,bcm2711-gpio", + "brcm,bcm7211-gpio", + }; + int ret, i; u32 cs; if (!target) { @@ -1290,6 +1296,14 @@ static int bcm2835_spi_setup(struct spi_device *spi) goto err_cleanup; } + for (i = 0; i < ARRAY_SIZE(pinctrl_compats); i++) { + if (of_find_compatible_node(NULL, NULL, pinctrl_compats[i])) + break; + } + + if (i == ARRAY_SIZE(pinctrl_compats)) + return 0; + /* * TODO: The code below is a slightly better alternative to the utter * abuse of the GPIO API that I found here before. It creates a
diff --git a/drivers/spi/spi-cadence-quadspi.c b/drivers/spi/spi-cadence-quadspi.c index 559fbdf..c904627 100644 --- a/drivers/spi/spi-cadence-quadspi.c +++ b/drivers/spi/spi-cadence-quadspi.c
@@ -2073,7 +2073,7 @@ static const struct cqspi_driver_platdata k2g_qspi = { static const struct cqspi_driver_platdata am654_ospi = { .hwcaps_mask = CQSPI_SUPPORTS_OCTAL | CQSPI_SUPPORTS_QUAD, - .quirks = CQSPI_DISABLE_DAC_MODE | CQSPI_NEEDS_WR_DELAY, + .quirks = CQSPI_NEEDS_WR_DELAY, }; static const struct cqspi_driver_platdata intel_lgm_qspi = {
diff --git a/drivers/spi/spi-cadence-xspi.c b/drivers/spi/spi-cadence-xspi.c index aed98ab..6dcba0e 100644 --- a/drivers/spi/spi-cadence-xspi.c +++ b/drivers/spi/spi-cadence-xspi.c
@@ -432,7 +432,7 @@ static bool cdns_mrvl_xspi_setup_clock(struct cdns_xspi_dev *cdns_xspi, u32 clk_reg; bool update_clk = false; - while (i < ARRAY_SIZE(cdns_mrvl_xspi_clk_div_list)) { + while (i < (ARRAY_SIZE(cdns_mrvl_xspi_clk_div_list) - 1)) { clk_val = MRVL_XSPI_CLOCK_DIVIDED( cdns_mrvl_xspi_clk_div_list[i]); if (clk_val <= requested_clk)
diff --git a/drivers/spi/spi-fsl-qspi.c b/drivers/spi/spi-fsl-qspi.c index 355e6a3..5c59fdd 100644 --- a/drivers/spi/spi-fsl-qspi.c +++ b/drivers/spi/spi-fsl-qspi.c
@@ -844,6 +844,19 @@ static const struct spi_controller_mem_caps fsl_qspi_mem_caps = { .per_op_freq = true, }; +static void fsl_qspi_cleanup(void *data) +{ + struct fsl_qspi *q = data; + + /* disable the hardware */ + qspi_writel(q, QUADSPI_MCR_MDIS_MASK, q->iobase + QUADSPI_MCR); + qspi_writel(q, 0x0, q->iobase + QUADSPI_RSER); + + fsl_qspi_clk_disable_unprep(q); + + mutex_destroy(&q->lock); +} + static int fsl_qspi_probe(struct platform_device *pdev) { struct spi_controller *ctlr; @@ -934,6 +947,10 @@ static int fsl_qspi_probe(struct platform_device *pdev) ctlr->dev.of_node = np; + ret = devm_add_action_or_reset(dev, fsl_qspi_cleanup, q); + if (ret) + goto err_destroy_mutex; + ret = devm_spi_register_controller(dev, ctlr); if (ret) goto err_destroy_mutex; @@ -953,19 +970,6 @@ static int fsl_qspi_probe(struct platform_device *pdev) return ret; } -static void fsl_qspi_remove(struct platform_device *pdev) -{ - struct fsl_qspi *q = platform_get_drvdata(pdev); - - /* disable the hardware */ - qspi_writel(q, QUADSPI_MCR_MDIS_MASK, q->iobase + QUADSPI_MCR); - qspi_writel(q, 0x0, q->iobase + QUADSPI_RSER); - - fsl_qspi_clk_disable_unprep(q); - - mutex_destroy(&q->lock); -} - static int fsl_qspi_suspend(struct device *dev) { return 0; @@ -1003,7 +1007,6 @@ static struct platform_driver fsl_qspi_driver = { .pm = &fsl_qspi_pm_ops, }, .probe = fsl_qspi_probe, - .remove = fsl_qspi_remove, }; module_platform_driver(fsl_qspi_driver);
diff --git a/drivers/spi/spi-qpic-snand.c b/drivers/spi/spi-qpic-snand.c index fbba774..17eb67e 100644 --- a/drivers/spi/spi-qpic-snand.c +++ b/drivers/spi/spi-qpic-snand.c
@@ -1614,7 +1614,7 @@ static const struct of_device_id qcom_snandc_of_match[] = { .data = &ipq9574_snandc_props, }, {} -} +}; MODULE_DEVICE_TABLE(of, qcom_snandc_of_match); static struct platform_driver qcom_spi_driver = {
diff --git a/drivers/spi/spi-rockchip.c b/drivers/spi/spi-rockchip.c index 1bc012f..1a6381d 100644 --- a/drivers/spi/spi-rockchip.c +++ b/drivers/spi/spi-rockchip.c
@@ -547,7 +547,7 @@ static int rockchip_spi_config(struct rockchip_spi *rs, cr0 |= (spi->mode & 0x3U) << CR0_SCPH_OFFSET; if (spi->mode & SPI_LSB_FIRST) cr0 |= CR0_FBM_LSB << CR0_FBM_OFFSET; - if (spi->mode & SPI_CS_HIGH) + if ((spi->mode & SPI_CS_HIGH) && !(spi_get_csgpiod(spi, 0))) cr0 |= BIT(spi_get_chipselect(spi, 0)) << CR0_SOI_OFFSET; if (xfer->rx_buf && xfer->tx_buf)
diff --git a/drivers/staging/gpib/Kconfig b/drivers/staging/gpib/Kconfig index 81510db..aa01538 100644 --- a/drivers/staging/gpib/Kconfig +++ b/drivers/staging/gpib/Kconfig
@@ -50,7 +50,6 @@ tristate "CEC PCI board" depends on PCI depends on HAS_IOPORT - depends on !X86_PAE select GPIB_COMMON select GPIB_NEC7210 help @@ -64,7 +63,6 @@ tristate "NI PCI/ISA compatible boards" depends on ISA_BUS || PCI || PCMCIA depends on HAS_IOPORT - depends on !X86_PAE depends on PCMCIA || !PCMCIA depends on HAS_IOPORT_MAP select GPIB_COMMON @@ -90,7 +88,6 @@ tristate "Measurement Computing compatible boards" depends on HAS_IOPORT depends on ISA_BUS || PCI || PCMCIA - depends on !X86_PAE depends on PCMCIA || !PCMCIA select GPIB_COMMON select GPIB_NEC7210 @@ -169,7 +166,6 @@ tristate "HP82341x" select GPIB_COMMON select GPIB_TMS9914 - depends on BROKEN depends on ISA_BUS || EISA help GPIB driver for HP82341 A/B/C/D boards @@ -182,7 +178,6 @@ depends on PCI || ISA_BUS || PCMCIA depends on PCMCIA || !PCMCIA depends on HAS_IOPORT - depends on !X86_PAE select GPIB_COMMON select GPIB_NEC7210 help
diff --git a/drivers/staging/gpib/agilent_82350b/agilent_82350b.c b/drivers/staging/gpib/agilent_82350b/agilent_82350b.c index 3f4f95b..445b938 100644 --- a/drivers/staging/gpib/agilent_82350b/agilent_82350b.c +++ b/drivers/staging/gpib/agilent_82350b/agilent_82350b.c
@@ -4,6 +4,10 @@ * copyright : (C) 2002, 2004 by Frank Mori Hess * ***************************************************************************/ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#define dev_fmt pr_fmt +#define DRV_NAME KBUILD_MODNAME + #include "agilent_82350b.h" #include <linux/delay.h> #include <linux/ioport.h> @@ -20,8 +24,14 @@ MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("GPIB driver for Agilent 82350b"); -int agilent_82350b_accel_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *end, - size_t *bytes_read) +static int read_transfer_counter(struct agilent_82350b_priv *a_priv); +static unsigned short read_and_clear_event_status(struct gpib_board *board); +static void set_transfer_counter(struct agilent_82350b_priv *a_priv, int count); +static int agilent_82350b_write(struct gpib_board *board, uint8_t *buffer, + size_t length, int send_eoi, size_t *bytes_written); + +static int agilent_82350b_accel_read(struct gpib_board *board, uint8_t *buffer, + size_t length, int *end, size_t *bytes_read) { struct agilent_82350b_priv *a_priv = board->private_data; @@ -48,9 +58,6 @@ int agilent_82350b_accel_read(gpib_board_t *board, uint8_t *buffer, size_t lengt retval = tms9914_read(board, tms_priv, buffer, 1, end, &num_bytes); *bytes_read += num_bytes; - if (retval < 0) - dev_err(board->gpib_dev, "%s: tms9914_read failed retval=%i\n", - driver_name, retval); if (retval < 0 || *end) return retval; ++buffer; @@ -66,10 +73,7 @@ int agilent_82350b_accel_read(gpib_board_t *board, uint8_t *buffer, size_t lengt int j; int count; - if (num_fifo_bytes - i < agilent_82350b_fifo_size) - block_size = num_fifo_bytes - i; - else - block_size = agilent_82350b_fifo_size; + block_size = min(num_fifo_bytes - i, agilent_82350b_fifo_size); set_transfer_counter(a_priv, block_size); writeb(ENABLE_TI_TO_SRAM | DIRECTION_GPIB_TO_HOST, a_priv->gpib_base + SRAM_ACCESS_CONTROL_REG); @@ -86,7 +90,6 @@ int agilent_82350b_accel_read(gpib_board_t *board, uint8_t *buffer, size_t lengt test_bit(DEV_CLEAR_BN, &tms_priv->state) || test_bit(TIMO_NUM, &board->status)); if (retval) { - dev_dbg(board->gpib_dev, "%s: read wait interrupted\n", driver_name); retval = -ERESTARTSYS; break; } @@ -100,13 +103,10 @@ int agilent_82350b_accel_read(gpib_board_t *board, uint8_t *buffer, size_t lengt *end = 1; } if (test_bit(TIMO_NUM, &board->status)) { - dev_err(board->gpib_dev, "%s: read timed out\n", driver_name); retval = -ETIMEDOUT; break; } if (test_bit(DEV_CLEAR_BN, &tms_priv->state)) { - dev_err(board->gpib_dev, "%s: device clear interrupted read\n", - driver_name); retval = -EINTR; break; } @@ -130,30 +130,24 @@ int agilent_82350b_accel_read(gpib_board_t *board, uint8_t *buffer, size_t lengt return 0; } -static int translate_wait_return_value(gpib_board_t *board, int retval) +static int translate_wait_return_value(struct gpib_board *board, int retval) { struct agilent_82350b_priv *a_priv = board->private_data; struct tms9914_priv *tms_priv = &a_priv->tms9914_priv; - if (retval) { - dev_err(board->gpib_dev, "%s: write wait interrupted\n", driver_name); + if (retval) return -ERESTARTSYS; - } - if (test_bit(TIMO_NUM, &board->status)) { - dev_err(board->gpib_dev, "%s: write timed out\n", driver_name); + if (test_bit(TIMO_NUM, &board->status)) return -ETIMEDOUT; - } - if (test_bit(DEV_CLEAR_BN, &tms_priv->state)) { - dev_err(board->gpib_dev, "%s: device clear interrupted write\n", driver_name); + if (test_bit(DEV_CLEAR_BN, &tms_priv->state)) return -EINTR; - } return 0; } -int agilent_82350b_accel_write(gpib_board_t *board, uint8_t *buffer, size_t length, int send_eoi, - size_t *bytes_written) - +static int agilent_82350b_accel_write(struct gpib_board *board, uint8_t *buffer, + size_t length, int send_eoi, + size_t *bytes_written) { struct agilent_82350b_priv *a_priv = board->private_data; struct tms9914_priv *tms_priv = &a_priv->tms9914_priv; @@ -174,10 +168,8 @@ int agilent_82350b_accel_write(gpib_board_t *board, uint8_t *buffer, size_t leng event_status = read_and_clear_event_status(board); - //pr_info("ag_ac_wr: event status 0x%x tms state 0x%lx\n", event_status, tms_priv->state); - #ifdef EXPERIMENTAL - pr_info("ag_ac_wr: wait for previous BO to complete if any\n"); + // wait for previous BO to complete if any retval = wait_event_interruptible(board->wait, test_bit(DEV_CLEAR_BN, &tms_priv->state) || test_bit(WRITE_READY_BN, &tms_priv->state) || @@ -188,22 +180,16 @@ int agilent_82350b_accel_write(gpib_board_t *board, uint8_t *buffer, size_t leng return retval; #endif - //pr_info("ag_ac_wr: sending first byte\n"); retval = agilent_82350b_write(board, buffer, 1, 0, &num_bytes); *bytes_written += num_bytes; if (retval < 0) return retval; - //pr_info("ag_ac_wr: %ld bytes eoi %d tms state 0x%lx\n",length, send_eoi, tms_priv->state); - write_byte(tms_priv, tms_priv->imr0_bits & ~HR_BOIE, IMR0); for (i = 1; i < fifotransferlength;) { clear_bit(WRITE_READY_BN, &tms_priv->state); - if (fifotransferlength - i < agilent_82350b_fifo_size) - block_size = fifotransferlength - i; - else - block_size = agilent_82350b_fifo_size; + block_size = min(fifotransferlength - i, agilent_82350b_fifo_size); set_transfer_counter(a_priv, block_size); for (j = 0; j < block_size; ++j, ++i) { // load data into board's sram @@ -211,13 +197,8 @@ int agilent_82350b_accel_write(gpib_board_t *board, uint8_t *buffer, size_t leng } writeb(ENABLE_TI_TO_SRAM, a_priv->gpib_base + SRAM_ACCESS_CONTROL_REG); - //pr_info("ag_ac_wr: send block: %d bytes tms 0x%lx\n", block_size, - // tms_priv->state); - - if (agilent_82350b_fifo_is_halted(a_priv)) { + if (agilent_82350b_fifo_is_halted(a_priv)) writeb(RESTART_STREAM_BIT, a_priv->gpib_base + STREAM_STATUS_REG); - // pr_info("ag_ac_wr: needed restart\n"); - } retval = wait_event_interruptible(board->wait, ((event_status = @@ -227,7 +208,6 @@ int agilent_82350b_accel_write(gpib_board_t *board, uint8_t *buffer, size_t leng test_bit(TIMO_NUM, &board->status)); writeb(0, a_priv->gpib_base + SRAM_ACCESS_CONTROL_REG); num_bytes = block_size - read_transfer_counter(a_priv); - //pr_info("ag_ac_wr: sent %ld bytes tms 0x%lx\n", num_bytes, tms_priv->state); *bytes_written += num_bytes; retval = translate_wait_return_value(board, retval); @@ -239,9 +219,6 @@ int agilent_82350b_accel_write(gpib_board_t *board, uint8_t *buffer, size_t leng return retval; if (send_eoi) { - //pr_info("ag_ac_wr: sending last byte with eoi byte no: %d\n", - // fifotransferlength+1); - retval = agilent_82350b_write(board, buffer + fifotransferlength, 1, send_eoi, &num_bytes); *bytes_written += num_bytes; @@ -251,8 +228,7 @@ int agilent_82350b_accel_write(gpib_board_t *board, uint8_t *buffer, size_t leng return 0; } -unsigned short read_and_clear_event_status(gpib_board_t *board) - +static unsigned short read_and_clear_event_status(struct gpib_board *board) { struct agilent_82350b_priv *a_priv = board->private_data; unsigned long flags; @@ -265,12 +241,12 @@ unsigned short read_and_clear_event_status(gpib_board_t *board) return status; } -irqreturn_t agilent_82350b_interrupt(int irq, void *arg) +static irqreturn_t agilent_82350b_interrupt(int irq, void *arg) { int tms9914_status1 = 0, tms9914_status2 = 0; int event_status; - gpib_board_t *board = arg; + struct gpib_board *board = arg; struct agilent_82350b_priv *a_priv = board->private_data; unsigned long flags; irqreturn_t retval = IRQ_NONE; @@ -286,7 +262,6 @@ irqreturn_t agilent_82350b_interrupt(int irq, void *arg) tms9914_interrupt_have_status(board, &a_priv->tms9914_priv, tms9914_status1, tms9914_status2); } -//pr_info("event_status=0x%x s1 %x s2 %x\n", event_status,tms9914_status1,tms9914_status2); //write-clear status bits if (event_status & (BUFFER_END_STATUS_BIT | TERM_COUNT_STATUS_BIT)) { writeb(event_status & (BUFFER_END_STATUS_BIT | TERM_COUNT_STATUS_BIT), @@ -298,12 +273,9 @@ irqreturn_t agilent_82350b_interrupt(int irq, void *arg) return retval; } -void agilent_82350b_detach(gpib_board_t *board); +static void agilent_82350b_detach(struct gpib_board *board); -const char *driver_name = "agilent_82350b"; - -int read_transfer_counter(struct agilent_82350b_priv *a_priv) - +static int read_transfer_counter(struct agilent_82350b_priv *a_priv) { int lo, mid, value; @@ -314,8 +286,7 @@ int read_transfer_counter(struct agilent_82350b_priv *a_priv) return value; } -void set_transfer_counter(struct agilent_82350b_priv *a_priv, int count) - +static void set_transfer_counter(struct agilent_82350b_priv *a_priv, int count) { int complement = -count; @@ -326,17 +297,16 @@ void set_transfer_counter(struct agilent_82350b_priv *a_priv, int count) } // wrappers for interface functions -int agilent_82350b_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *end, - size_t *bytes_read) - +static int agilent_82350b_read(struct gpib_board *board, uint8_t *buffer, + size_t length, int *end, size_t *bytes_read) { struct agilent_82350b_priv *priv = board->private_data; return tms9914_read(board, &priv->tms9914_priv, buffer, length, end, bytes_read); } -int agilent_82350b_write(gpib_board_t *board, uint8_t *buffer, size_t length, int send_eoi, - size_t *bytes_written) +static int agilent_82350b_write(struct gpib_board *board, uint8_t *buffer, + size_t length, int send_eoi, size_t *bytes_written) { struct agilent_82350b_priv *priv = board->private_data; @@ -344,8 +314,8 @@ int agilent_82350b_write(gpib_board_t *board, uint8_t *buffer, size_t length, in return tms9914_write(board, &priv->tms9914_priv, buffer, length, send_eoi, bytes_written); } -int agilent_82350b_command(gpib_board_t *board, uint8_t *buffer, size_t length, - size_t *bytes_written) +static int agilent_82350b_command(struct gpib_board *board, uint8_t *buffer, + size_t length, size_t *bytes_written) { struct agilent_82350b_priv *priv = board->private_data; @@ -353,7 +323,7 @@ int agilent_82350b_command(gpib_board_t *board, uint8_t *buffer, size_t length, return tms9914_command(board, &priv->tms9914_priv, buffer, length, bytes_written); } -int agilent_82350b_take_control(gpib_board_t *board, int synchronous) +static int agilent_82350b_take_control(struct gpib_board *board, int synchronous) { struct agilent_82350b_priv *priv = board->private_data; @@ -361,7 +331,7 @@ int agilent_82350b_take_control(gpib_board_t *board, int synchronous) return tms9914_take_control_workaround(board, &priv->tms9914_priv, synchronous); } -int agilent_82350b_go_to_standby(gpib_board_t *board) +static int agilent_82350b_go_to_standby(struct gpib_board *board) { struct agilent_82350b_priv *priv = board->private_data; @@ -369,7 +339,8 @@ int agilent_82350b_go_to_standby(gpib_board_t *board) return tms9914_go_to_standby(board, &priv->tms9914_priv); } -void agilent_82350b_request_system_control(gpib_board_t *board, int request_control) +static void agilent_82350b_request_system_control(struct gpib_board *board, + int request_control) { struct agilent_82350b_priv *a_priv = board->private_data; @@ -387,7 +358,7 @@ void agilent_82350b_request_system_control(gpib_board_t *board, int request_cont tms9914_request_system_control(board, &a_priv->tms9914_priv, request_control); } -void agilent_82350b_interface_clear(gpib_board_t *board, int assert) +static void agilent_82350b_interface_clear(struct gpib_board *board, int assert) { struct agilent_82350b_priv *priv = board->private_data; @@ -395,104 +366,96 @@ void agilent_82350b_interface_clear(gpib_board_t *board, int assert) tms9914_interface_clear(board, &priv->tms9914_priv, assert); } -void agilent_82350b_remote_enable(gpib_board_t *board, int enable) - +static void agilent_82350b_remote_enable(struct gpib_board *board, int enable) { struct agilent_82350b_priv *priv = board->private_data; tms9914_remote_enable(board, &priv->tms9914_priv, enable); } -int agilent_82350b_enable_eos(gpib_board_t *board, uint8_t eos_byte, int compare_8_bits) - +static int agilent_82350b_enable_eos(struct gpib_board *board, uint8_t eos_byte, + int compare_8_bits) { struct agilent_82350b_priv *priv = board->private_data; return tms9914_enable_eos(board, &priv->tms9914_priv, eos_byte, compare_8_bits); } -void agilent_82350b_disable_eos(gpib_board_t *board) - +static void agilent_82350b_disable_eos(struct gpib_board *board) { struct agilent_82350b_priv *priv = board->private_data; tms9914_disable_eos(board, &priv->tms9914_priv); } -unsigned int agilent_82350b_update_status(gpib_board_t *board, unsigned int clear_mask) - +static unsigned int agilent_82350b_update_status(struct gpib_board *board, + unsigned int clear_mask) { struct agilent_82350b_priv *priv = board->private_data; return tms9914_update_status(board, &priv->tms9914_priv, clear_mask); } -int agilent_82350b_primary_address(gpib_board_t *board, unsigned int address) - +static int agilent_82350b_primary_address(struct gpib_board *board, + unsigned int address) { struct agilent_82350b_priv *priv = board->private_data; return tms9914_primary_address(board, &priv->tms9914_priv, address); } -int agilent_82350b_secondary_address(gpib_board_t *board, unsigned int address, int enable) - +static int agilent_82350b_secondary_address(struct gpib_board *board, + unsigned int address, int enable) { struct agilent_82350b_priv *priv = board->private_data; return tms9914_secondary_address(board, &priv->tms9914_priv, address, enable); } -int agilent_82350b_parallel_poll(gpib_board_t *board, uint8_t *result) - +static int agilent_82350b_parallel_poll(struct gpib_board *board, uint8_t *result) { struct agilent_82350b_priv *priv = board->private_data; return tms9914_parallel_poll(board, &priv->tms9914_priv, result); } -void agilent_82350b_parallel_poll_configure(gpib_board_t *board, uint8_t config) - +static void agilent_82350b_parallel_poll_configure(struct gpib_board *board, + uint8_t config) { struct agilent_82350b_priv *priv = board->private_data; tms9914_parallel_poll_configure(board, &priv->tms9914_priv, config); } -void agilent_82350b_parallel_poll_response(gpib_board_t *board, int ist) - +static void agilent_82350b_parallel_poll_response(struct gpib_board *board, int ist) { struct agilent_82350b_priv *priv = board->private_data; tms9914_parallel_poll_response(board, &priv->tms9914_priv, ist); } -void agilent_82350b_serial_poll_response(gpib_board_t *board, uint8_t status) - +static void agilent_82350b_serial_poll_response(struct gpib_board *board, uint8_t status) { struct agilent_82350b_priv *priv = board->private_data; tms9914_serial_poll_response(board, &priv->tms9914_priv, status); } -uint8_t agilent_82350b_serial_poll_status(gpib_board_t *board) - +static uint8_t agilent_82350b_serial_poll_status(struct gpib_board *board) { struct agilent_82350b_priv *priv = board->private_data; return tms9914_serial_poll_status(board, &priv->tms9914_priv); } -int agilent_82350b_line_status(const gpib_board_t *board) - +static int agilent_82350b_line_status(const struct gpib_board *board) { struct agilent_82350b_priv *priv = board->private_data; return tms9914_line_status(board, &priv->tms9914_priv); } -unsigned int agilent_82350b_t1_delay(gpib_board_t *board, unsigned int nanosec) - +static int agilent_82350b_t1_delay(struct gpib_board *board, unsigned int nanosec) { struct agilent_82350b_priv *a_priv = board->private_data; static const int nanosec_per_clock = 30; @@ -507,16 +470,14 @@ unsigned int agilent_82350b_t1_delay(gpib_board_t *board, unsigned int nanosec) return value * nanosec_per_clock; } -void agilent_82350b_return_to_local(gpib_board_t *board) - +static void agilent_82350b_return_to_local(struct gpib_board *board) { struct agilent_82350b_priv *priv = board->private_data; tms9914_return_to_local(board, &priv->tms9914_priv); } -int agilent_82350b_allocate_private(gpib_board_t *board) - +static int agilent_82350b_allocate_private(struct gpib_board *board) { board->private_data = kzalloc(sizeof(struct agilent_82350b_priv), GFP_KERNEL); if (!board->private_data) @@ -524,15 +485,14 @@ int agilent_82350b_allocate_private(gpib_board_t *board) return 0; } -void agilent_82350b_free_private(gpib_board_t *board) - +static void agilent_82350b_free_private(struct gpib_board *board) { kfree(board->private_data); board->private_data = NULL; } -static int init_82350a_hardware(gpib_board_t *board, const gpib_board_config_t *config) - +static int init_82350a_hardware(struct gpib_board *board, + const gpib_board_config_t *config) { struct agilent_82350b_priv *a_priv = board->private_data; static const unsigned int firmware_length = 5302; @@ -557,11 +517,10 @@ static int init_82350a_hardware(gpib_board_t *board, const gpib_board_config_t * return 0; // need to programme borg if (!config->init_data || config->init_data_length != firmware_length) { - dev_err(board->gpib_dev, "%s: the 82350A board requires firmware after powering on.\n", - driver_name); + dev_err(board->gpib_dev, "the 82350A board requires firmware after powering on.\n"); return -EIO; } - dev_info(board->gpib_dev, "%s: Loading firmware...\n", driver_name); + dev_dbg(board->gpib_dev, "Loading firmware...\n"); // tickle the borg writel(plx_cntrl_static_bits | PLX9050_USER3_DATA_BIT, @@ -580,7 +539,7 @@ static int init_82350a_hardware(gpib_board_t *board, const gpib_board_config_t * usleep_range(10, 20); } if (j == timeout) { - dev_err(board->gpib_dev, "%s: timed out loading firmware.\n", driver_name); + dev_err(board->gpib_dev, "timed out loading firmware.\n"); return -ETIMEDOUT; } writeb(firmware_data[i], a_priv->gpib_base + CONFIG_DATA_REG); @@ -591,15 +550,14 @@ static int init_82350a_hardware(gpib_board_t *board, const gpib_board_config_t * usleep_range(10, 20); } if (j == timeout) { - dev_err(board->gpib_dev, "%s: timed out waiting for firmware load to complete.\n", - driver_name); + dev_err(board->gpib_dev, "timed out waiting for firmware load to complete.\n"); return -ETIMEDOUT; } - dev_info(board->gpib_dev, "%s: ...done.\n", driver_name); + dev_dbg(board->gpib_dev, " ...done.\n"); return 0; } -static int test_sram(gpib_board_t *board) +static int test_sram(struct gpib_board *board) { struct agilent_82350b_priv *a_priv = board->private_data; @@ -617,19 +575,19 @@ static int test_sram(gpib_board_t *board) unsigned int read_value = readb(a_priv->sram_base + i); if ((i & byte_mask) != read_value) { - dev_err(board->gpib_dev, "%s: SRAM test failed at %d wanted %d got %d\n", - driver_name, i, (i & byte_mask), read_value); + dev_err(board->gpib_dev, "SRAM test failed at %d wanted %d got %d\n", + i, (i & byte_mask), read_value); return -EIO; } if (need_resched()) schedule(); } - dev_info(board->gpib_dev, "%s: SRAM test passed 0x%x bytes checked\n", - driver_name, sram_length); + dev_dbg(board->gpib_dev, "SRAM test passed 0x%x bytes checked\n", sram_length); return 0; } -static int agilent_82350b_generic_attach(gpib_board_t *board, const gpib_board_config_t *config, +static int agilent_82350b_generic_attach(struct gpib_board *board, + const gpib_board_config_t *config, int use_fifos) { @@ -653,14 +611,14 @@ static int agilent_82350b_generic_attach(gpib_board_t *board, const gpib_board_c PCI_DEVICE_ID_82350B, NULL); if (a_priv->pci_device) { a_priv->model = MODEL_82350B; - dev_info(board->gpib_dev, "%s: Agilent 82350B board found\n", driver_name); + dev_dbg(board->gpib_dev, "Agilent 82350B board found\n"); } else { a_priv->pci_device = gpib_pci_get_device(config, PCI_VENDOR_ID_AGILENT, PCI_DEVICE_ID_82351A, NULL); if (a_priv->pci_device) { a_priv->model = MODEL_82351A; - dev_info(board->gpib_dev, "%s: Agilent 82351B board found\n", driver_name); + dev_dbg(board->gpib_dev, "Agilent 82351B board found\n"); } else { a_priv->pci_device = gpib_pci_get_subsys(config, PCI_VENDOR_ID_PLX, @@ -670,46 +628,40 @@ static int agilent_82350b_generic_attach(gpib_board_t *board, const gpib_board_c a_priv->pci_device); if (a_priv->pci_device) { a_priv->model = MODEL_82350A; - dev_info(board->gpib_dev, "%s: HP/Agilent 82350A board found\n", - driver_name); + dev_dbg(board->gpib_dev, "HP/Agilent 82350A board found\n"); } else { - dev_err(board->gpib_dev, "%s: no 82350/82351 board found\n", - driver_name); + dev_err(board->gpib_dev, "no 82350/82351 board found\n"); return -ENODEV; } } } if (pci_enable_device(a_priv->pci_device)) { - dev_err(board->gpib_dev, "%s: error enabling pci device\n", driver_name); + dev_err(board->gpib_dev, "error enabling pci device\n"); return -EIO; } - if (pci_request_regions(a_priv->pci_device, driver_name)) - return -EIO; + if (pci_request_regions(a_priv->pci_device, DRV_NAME)) + return -ENOMEM; switch (a_priv->model) { case MODEL_82350A: a_priv->plx_base = ioremap(pci_resource_start(a_priv->pci_device, PLX_MEM_REGION), pci_resource_len(a_priv->pci_device, PLX_MEM_REGION)); - dev_dbg(board->gpib_dev, "%s: plx base address remapped to 0x%p\n", - driver_name, a_priv->plx_base); + dev_dbg(board->gpib_dev, "plx base address remapped to 0x%p\n", a_priv->plx_base); a_priv->gpib_base = ioremap(pci_resource_start(a_priv->pci_device, GPIB_82350A_REGION), pci_resource_len(a_priv->pci_device, GPIB_82350A_REGION)); - dev_dbg(board->gpib_dev, "%s: gpib base address remapped to 0x%p\n", - driver_name, a_priv->gpib_base); + dev_dbg(board->gpib_dev, "chip base address remapped to 0x%p\n", a_priv->gpib_base); tms_priv->mmiobase = a_priv->gpib_base + TMS9914_BASE_REG; a_priv->sram_base = ioremap(pci_resource_start(a_priv->pci_device, SRAM_82350A_REGION), pci_resource_len(a_priv->pci_device, SRAM_82350A_REGION)); - dev_dbg(board->gpib_dev, "%s: sram base address remapped to 0x%p\n", - driver_name, a_priv->sram_base); + dev_dbg(board->gpib_dev, "sram base address remapped to 0x%p\n", a_priv->sram_base); a_priv->borg_base = ioremap(pci_resource_start(a_priv->pci_device, BORG_82350A_REGION), pci_resource_len(a_priv->pci_device, BORG_82350A_REGION)); - dev_dbg(board->gpib_dev, "%s: borg base address remapped to 0x%p\n", - driver_name, a_priv->borg_base); + dev_dbg(board->gpib_dev, "borg base address remapped to 0x%p\n", a_priv->borg_base); retval = init_82350a_hardware(board, config); if (retval < 0) @@ -719,21 +671,18 @@ static int agilent_82350b_generic_attach(gpib_board_t *board, const gpib_board_c case MODEL_82351A: a_priv->gpib_base = ioremap(pci_resource_start(a_priv->pci_device, GPIB_REGION), pci_resource_len(a_priv->pci_device, GPIB_REGION)); - dev_dbg(board->gpib_dev, "%s: gpib base address remapped to 0x%p\n", - driver_name, a_priv->gpib_base); + dev_dbg(board->gpib_dev, "chip base address remapped to 0x%p\n", a_priv->gpib_base); tms_priv->mmiobase = a_priv->gpib_base + TMS9914_BASE_REG; a_priv->sram_base = ioremap(pci_resource_start(a_priv->pci_device, SRAM_REGION), pci_resource_len(a_priv->pci_device, SRAM_REGION)); - dev_dbg(board->gpib_dev, "%s: sram base address remapped to 0x%p\n", - driver_name, a_priv->sram_base); + dev_dbg(board->gpib_dev, "sram base address remapped to 0x%p\n", a_priv->sram_base); a_priv->misc_base = ioremap(pci_resource_start(a_priv->pci_device, MISC_REGION), pci_resource_len(a_priv->pci_device, MISC_REGION)); - dev_dbg(board->gpib_dev, "%s: misc base address remapped to 0x%p\n", - driver_name, a_priv->misc_base); + dev_dbg(board->gpib_dev, "misc base address remapped to 0x%p\n", a_priv->misc_base); break; default: - pr_err("%s: invalid board\n", driver_name); - return -1; + dev_err(board->gpib_dev, "invalid board\n"); + return -ENODEV; } retval = test_sram(board); @@ -741,12 +690,12 @@ static int agilent_82350b_generic_attach(gpib_board_t *board, const gpib_board_c return retval; if (request_irq(a_priv->pci_device->irq, agilent_82350b_interrupt, - IRQF_SHARED, driver_name, board)) { - pr_err("%s: can't request IRQ %d\n", driver_name, a_priv->pci_device->irq); + IRQF_SHARED, DRV_NAME, board)) { + dev_err(board->gpib_dev, "failed to obtain irq %d\n", a_priv->pci_device->irq); return -EIO; } a_priv->irq = a_priv->pci_device->irq; - dev_dbg(board->gpib_dev, "%s: IRQ %d\n", driver_name, a_priv->irq); + dev_dbg(board->gpib_dev, " IRQ %d\n", a_priv->irq); writeb(0, a_priv->gpib_base + SRAM_ACCESS_CONTROL_REG); a_priv->card_mode_bits = ENABLE_PCI_IRQ_BIT; @@ -780,20 +729,19 @@ static int agilent_82350b_generic_attach(gpib_board_t *board, const gpib_board_c return 0; } -int agilent_82350b_unaccel_attach(gpib_board_t *board, const gpib_board_config_t *config) - +static int agilent_82350b_unaccel_attach(struct gpib_board *board, + const gpib_board_config_t *config) { return agilent_82350b_generic_attach(board, config, 0); } -int agilent_82350b_accel_attach(gpib_board_t *board, const gpib_board_config_t *config) - +static int agilent_82350b_accel_attach(struct gpib_board *board, + const gpib_board_config_t *config) { return agilent_82350b_generic_attach(board, config, 1); } -void agilent_82350b_detach(gpib_board_t *board) - +static void agilent_82350b_detach(struct gpib_board *board) { struct agilent_82350b_priv *a_priv = board->private_data; struct tms9914_priv *tms_priv; @@ -848,6 +796,7 @@ static gpib_interface_t agilent_82350b_unaccel_interface = { .primary_address = agilent_82350b_primary_address, .secondary_address = agilent_82350b_secondary_address, .serial_poll_response = agilent_82350b_serial_poll_response, + .serial_poll_status = agilent_82350b_serial_poll_status, .t1_delay = agilent_82350b_t1_delay, .return_to_local = agilent_82350b_return_to_local, }; @@ -875,6 +824,7 @@ static gpib_interface_t agilent_82350b_interface = { .primary_address = agilent_82350b_primary_address, .secondary_address = agilent_82350b_secondary_address, .serial_poll_response = agilent_82350b_serial_poll_response, + .serial_poll_status = agilent_82350b_serial_poll_status, .t1_delay = agilent_82350b_t1_delay, .return_to_local = agilent_82350b_return_to_local, }; @@ -895,31 +845,30 @@ static const struct pci_device_id agilent_82350b_pci_table[] = { MODULE_DEVICE_TABLE(pci, agilent_82350b_pci_table); static struct pci_driver agilent_82350b_pci_driver = { - .name = "agilent_82350b", + .name = DRV_NAME, .id_table = agilent_82350b_pci_table, .probe = &agilent_82350b_pci_probe }; static int __init agilent_82350b_init_module(void) - { int result; result = pci_register_driver(&agilent_82350b_pci_driver); if (result) { - pr_err("agilent_82350b: pci_register_driver failed: error = %d\n", result); + pr_err("pci_register_driver failed: error = %d\n", result); return result; } result = gpib_register_driver(&agilent_82350b_unaccel_interface, THIS_MODULE); if (result) { - pr_err("agilent_82350b: gpib_register_driver failed: error = %d\n", result); + pr_err("gpib_register_driver failed: error = %d\n", result); goto err_unaccel; } result = gpib_register_driver(&agilent_82350b_interface, THIS_MODULE); if (result) { - pr_err("agilent_82350b: gpib_register_driver failed: error = %d\n", result); + pr_err("gpib_register_driver failed: error = %d\n", result); goto err_interface; } @@ -934,7 +883,6 @@ static int __init agilent_82350b_init_module(void) } static void __exit agilent_82350b_exit_module(void) - { gpib_unregister_driver(&agilent_82350b_interface); gpib_unregister_driver(&agilent_82350b_unaccel_interface);
diff --git a/drivers/staging/gpib/agilent_82350b/agilent_82350b.h b/drivers/staging/gpib/agilent_82350b/agilent_82350b.h index 32b3221..1573230 100644 --- a/drivers/staging/gpib/agilent_82350b/agilent_82350b.h +++ b/drivers/staging/gpib/agilent_82350b/agilent_82350b.h
@@ -57,56 +57,6 @@ struct agilent_82350b_priv { bool using_fifos; }; -// driver name -extern const char *driver_name; - -// init functions - -int agilent_82350b_unaccel_attach(gpib_board_t *board, const gpib_board_config_t *config); -int agilent_82350b_accel_attach(gpib_board_t *board, const gpib_board_config_t *config); - -// interface functions -int agilent_82350b_accel_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *end, - size_t *bytes_read); -int agilent_82350b_accel_write(gpib_board_t *board, uint8_t *buffer, size_t length, int send_eoi, - size_t *bytes_written); -int agilent_82350b_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *end, - size_t *bytes_read); -int agilent_82350b_write(gpib_board_t *board, uint8_t *buffer, size_t length, int send_eoi, - size_t *bytes_written); -int agilent_82350b_command(gpib_board_t *board, uint8_t *buffer, size_t length, - size_t *bytes_written); -int agilent_82350b_take_control(gpib_board_t *board, int synchronous); -int agilent_82350b_go_to_standby(gpib_board_t *board); -void agilent_82350b_request_system_control(gpib_board_t *board, int request_control); -void agilent_82350b_interface_clear(gpib_board_t *board, int assert); -void agilent_82350b_remote_enable(gpib_board_t *board, int enable); -int agilent_82350b_enable_eos(gpib_board_t *board, uint8_t eos_byte, int - compare_8_bits); -void agilent_82350b_disable_eos(gpib_board_t *board); -unsigned int agilent_82350b_update_status(gpib_board_t *board, unsigned int clear_mask); -int agilent_82350b_primary_address(gpib_board_t *board, unsigned int address); -int agilent_82350b_secondary_address(gpib_board_t *board, unsigned int address, int - enable); -int agilent_82350b_parallel_poll(gpib_board_t *board, uint8_t *result); -void agilent_82350b_parallel_poll_configure(gpib_board_t *board, uint8_t config); -void agilent_82350b_parallel_poll_response(gpib_board_t *board, int ist); -void agilent_82350b_serial_poll_response(gpib_board_t *board, uint8_t status); -void agilent_82350b_return_to_local(gpib_board_t *board); -uint8_t agilent_82350b_serial_poll_status(gpib_board_t *board); -int agilent_82350b_line_status(const gpib_board_t *board); -unsigned int agilent_82350b_t1_delay(gpib_board_t *board, unsigned int nanosec); - -// interrupt service routines -irqreturn_t agilent_82350b_interrupt(int irq, void *arg); - -// utility functions -int agilent_82350b_allocate_private(gpib_board_t *board); -void agilent_82350b_free_private(gpib_board_t *board); -unsigned short read_and_clear_event_status(gpib_board_t *board); -int read_transfer_counter(struct agilent_82350b_priv *a_priv); -void set_transfer_counter(struct agilent_82350b_priv *a_priv, int count); - //registers enum agilent_82350b_gpib_registers
diff --git a/drivers/staging/gpib/agilent_82357a/agilent_82357a.c b/drivers/staging/gpib/agilent_82357a/agilent_82357a.c index 69f0e49..da22996 100644 --- a/drivers/staging/gpib/agilent_82357a/agilent_82357a.c +++ b/drivers/staging/gpib/agilent_82357a/agilent_82357a.c
@@ -7,6 +7,10 @@ #define _GNU_SOURCE +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#define dev_fmt pr_fmt +#define DRV_NAME KBUILD_MODNAME + #include <linux/kernel.h> #include <linux/module.h> #include <linux/slab.h> @@ -21,9 +25,10 @@ MODULE_DESCRIPTION("GPIB driver for Agilent 82357A/B usb adapters"); static struct usb_interface *agilent_82357a_driver_interfaces[MAX_NUM_82357A_INTERFACES]; static DEFINE_MUTEX(agilent_82357a_hotplug_lock); // protect board insertion and removal -static unsigned int agilent_82357a_update_status(gpib_board_t *board, unsigned int clear_mask); +static unsigned int agilent_82357a_update_status(struct gpib_board *board, + unsigned int clear_mask); -static int agilent_82357a_take_control_internal(gpib_board_t *board, int synchronous); +static int agilent_82357a_take_control_internal(struct gpib_board *board, int synchronous); static void agilent_82357a_bulk_complete(struct urb *urb) { @@ -79,14 +84,12 @@ static int agilent_82357a_send_bulk_msg(struct agilent_82357a_priv *a_priv, void retval = usb_submit_urb(a_priv->bulk_urb, GFP_KERNEL); if (retval) { - dev_err(&usb_dev->dev, "%s: failed to submit bulk out urb, retval=%i\n", - __func__, retval); + dev_err(&usb_dev->dev, "failed to submit bulk out urb, retval=%i\n", retval); mutex_unlock(&a_priv->bulk_alloc_lock); goto cleanup; } mutex_unlock(&a_priv->bulk_alloc_lock); if (down_interruptible(&context->complete)) { - dev_err(&usb_dev->dev, "%s: interrupted\n", __func__); retval = -ERESTARTSYS; goto cleanup; } @@ -99,7 +102,7 @@ static int agilent_82357a_send_bulk_msg(struct agilent_82357a_priv *a_priv, void cleanup: if (timeout_msecs) { if (timer_pending(&a_priv->bulk_timer)) - del_timer_sync(&a_priv->bulk_timer); + timer_delete_sync(&a_priv->bulk_timer); } mutex_lock(&a_priv->bulk_alloc_lock); if (a_priv->bulk_urb) { @@ -149,14 +152,12 @@ static int agilent_82357a_receive_bulk_msg(struct agilent_82357a_priv *a_priv, v retval = usb_submit_urb(a_priv->bulk_urb, GFP_KERNEL); if (retval) { - dev_err(&usb_dev->dev, "%s: failed to submit bulk out urb, retval=%i\n", - __func__, retval); + dev_err(&usb_dev->dev, "failed to submit bulk in urb, retval=%i\n", retval); mutex_unlock(&a_priv->bulk_alloc_lock); goto cleanup; } mutex_unlock(&a_priv->bulk_alloc_lock); if (down_interruptible(&context->complete)) { - dev_err(&usb_dev->dev, "%s: interrupted\n", __func__); retval = -ERESTARTSYS; goto cleanup; } @@ -168,7 +169,7 @@ static int agilent_82357a_receive_bulk_msg(struct agilent_82357a_priv *a_priv, v *actual_data_length = a_priv->bulk_urb->actual_length; cleanup: if (timeout_msecs) - del_timer_sync(&a_priv->bulk_timer); + timer_delete_sync(&a_priv->bulk_timer); mutex_lock(&a_priv->bulk_alloc_lock); if (a_priv->bulk_urb) { @@ -205,7 +206,6 @@ static int agilent_82357a_receive_control_msg(struct agilent_82357a_priv *a_priv static void agilent_82357a_dump_raw_block(const u8 *raw_data, int length) { - pr_info("hex block dump\n"); print_hex_dump(KERN_INFO, "", DUMP_PREFIX_NONE, 8, 1, raw_data, length, true); } @@ -225,7 +225,7 @@ static int agilent_82357a_write_registers(struct agilent_82357a_priv *a_priv, static const int max_writes = 31; if (num_writes > max_writes) { - dev_err(&usb_dev->dev, "%s: bug! num_writes=%i too large\n", __func__, num_writes); + dev_err(&usb_dev->dev, "bug! num_writes=%i too large\n", num_writes); return -EIO; } out_data_length = num_writes * bytes_per_write + header_length; @@ -239,8 +239,7 @@ static int agilent_82357a_write_registers(struct agilent_82357a_priv *a_priv, out_data[i++] = writes[j].address; out_data[i++] = writes[j].value; } - if (i > out_data_length) - dev_err(&usb_dev->dev, "%s: bug! buffer overrun\n", __func__); + retval = mutex_lock_interruptible(&a_priv->bulk_transfer_lock); if (retval) { kfree(out_data); @@ -249,8 +248,8 @@ static int agilent_82357a_write_registers(struct agilent_82357a_priv *a_priv, retval = agilent_82357a_send_bulk_msg(a_priv, out_data, i, &bytes_written, 1000); kfree(out_data); if (retval) { - dev_err(&usb_dev->dev, "%s: agilent_82357a_send_bulk_msg returned %i, bytes_written=%i, i=%i\n", - __func__, retval, bytes_written, i); + dev_err(&usb_dev->dev, "send_bulk_msg returned %i, bytes_written=%i, i=%i\n", + retval, bytes_written, i); mutex_unlock(&a_priv->bulk_transfer_lock); return retval; } @@ -265,20 +264,19 @@ static int agilent_82357a_write_registers(struct agilent_82357a_priv *a_priv, mutex_unlock(&a_priv->bulk_transfer_lock); if (retval) { - dev_err(&usb_dev->dev, "%s: agilent_82357a_receive_bulk_msg returned %i, bytes_read=%i\n", - __func__, retval, bytes_read); + dev_err(&usb_dev->dev, "receive_bulk_msg returned %i, bytes_read=%i\n", + retval, bytes_read); agilent_82357a_dump_raw_block(in_data, bytes_read); kfree(in_data); return -EIO; } if (in_data[0] != (0xff & ~DATA_PIPE_CMD_WR_REGS)) { - dev_err(&usb_dev->dev, "%s: error, bulk command=0x%x != ~DATA_PIPE_CMD_WR_REGS\n", - __func__, in_data[0]); + dev_err(&usb_dev->dev, "bulk command=0x%x != ~DATA_PIPE_CMD_WR_REGS\n", in_data[0]); return -EIO; } if (in_data[1]) { - dev_err(&usb_dev->dev, "%s: nonzero error code 0x%x in DATA_PIPE_CMD_WR_REGS response\n", - __func__, in_data[1]); + dev_err(&usb_dev->dev, "nonzero error code 0x%x in DATA_PIPE_CMD_WR_REGS response\n", + in_data[1]); return -EIO; } kfree(in_data); @@ -299,9 +297,10 @@ static int agilent_82357a_read_registers(struct agilent_82357a_priv *a_priv, static const int header_length = 2; static const int max_reads = 62; - if (num_reads > max_reads) - dev_err(&usb_dev->dev, "%s: bug! num_reads=%i too large\n", __func__, num_reads); - + if (num_reads > max_reads) { + dev_err(&usb_dev->dev, "bug! num_reads=%i too large\n", num_reads); + return -EIO; + } out_data_length = num_reads + header_length; out_data = kmalloc(out_data_length, GFP_KERNEL); if (!out_data) @@ -311,8 +310,7 @@ static int agilent_82357a_read_registers(struct agilent_82357a_priv *a_priv, out_data[i++] = num_reads; for (j = 0; j < num_reads; j++) out_data[i++] = reads[j].address; - if (i > out_data_length) - dev_err(&usb_dev->dev, "%s: bug! buffer overrun\n", __func__); + if (blocking) { retval = mutex_lock_interruptible(&a_priv->bulk_transfer_lock); if (retval) { @@ -329,8 +327,8 @@ static int agilent_82357a_read_registers(struct agilent_82357a_priv *a_priv, retval = agilent_82357a_send_bulk_msg(a_priv, out_data, i, &bytes_written, 1000); kfree(out_data); if (retval) { - dev_err(&usb_dev->dev, "%s: agilent_82357a_send_bulk_msg returned %i, bytes_written=%i, i=%i\n", - __func__, retval, bytes_written, i); + dev_err(&usb_dev->dev, "send_bulk_msg returned %i, bytes_written=%i, i=%i\n", + retval, bytes_written, i); mutex_unlock(&a_priv->bulk_transfer_lock); return retval; } @@ -345,21 +343,20 @@ static int agilent_82357a_read_registers(struct agilent_82357a_priv *a_priv, mutex_unlock(&a_priv->bulk_transfer_lock); if (retval) { - dev_err(&usb_dev->dev, "%s: agilent_82357a_receive_bulk_msg returned %i, bytes_read=%i\n", - __func__, retval, bytes_read); + dev_err(&usb_dev->dev, "receive_bulk_msg returned %i, bytes_read=%i\n", + retval, bytes_read); agilent_82357a_dump_raw_block(in_data, bytes_read); kfree(in_data); return -EIO; } i = 0; if (in_data[i++] != (0xff & ~DATA_PIPE_CMD_RD_REGS)) { - dev_err(&usb_dev->dev, "%s: error, bulk command=0x%x != ~DATA_PIPE_CMD_RD_REGS\n", - __func__, in_data[0]); + dev_err(&usb_dev->dev, "bulk command=0x%x != ~DATA_PIPE_CMD_RD_REGS\n", in_data[0]); return -EIO; } if (in_data[i++]) { - dev_err(&usb_dev->dev, "%s: nonzero error code 0x%x in DATA_PIPE_CMD_RD_REGS response\n", - __func__, in_data[1]); + dev_err(&usb_dev->dev, "nonzero error code 0x%x in DATA_PIPE_CMD_RD_REGS response\n", + in_data[1]); return -EIO; } for (j = 0; j < num_reads; j++) @@ -390,14 +387,13 @@ static int agilent_82357a_abort(struct agilent_82357a_priv *a_priv, int flush) wIndex, status_data, status_data_len, 100); if (receive_control_retval < 0) { - dev_err(&usb_dev->dev, "%s: agilent_82357a_receive_control_msg() returned %i\n", - __func__, receive_control_retval); + dev_err(&usb_dev->dev, "82357a_receive_control_msg() returned %i\n", + receive_control_retval); retval = -EIO; goto cleanup; } if (status_data[0] != (~XFER_ABORT & 0xff)) { - dev_err(&usb_dev->dev, "%s: error, major code=0x%x != ~XFER_ABORT\n", - __func__, status_data[0]); + dev_err(&usb_dev->dev, "major code=0x%x != ~XFER_ABORT\n", status_data[0]); retval = -EIO; goto cleanup; } @@ -413,8 +409,7 @@ static int agilent_82357a_abort(struct agilent_82357a_priv *a_priv, int flush) fallthrough; case UGP_ERR_FLUSHING_ALREADY: default: - dev_err(&usb_dev->dev, "%s: abort returned error code=0x%x\n", - __func__, status_data[1]); + dev_err(&usb_dev->dev, "abort returned error code=0x%x\n", status_data[1]); retval = -EIO; break; } @@ -425,15 +420,15 @@ static int agilent_82357a_abort(struct agilent_82357a_priv *a_priv, int flush) } // interface functions -int agilent_82357a_command(gpib_board_t *board, uint8_t *buffer, size_t length, +int agilent_82357a_command(struct gpib_board *board, uint8_t *buffer, size_t length, size_t *bytes_written); -static int agilent_82357a_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *end, +static int agilent_82357a_read(struct gpib_board *board, uint8_t *buffer, size_t length, int *end, size_t *nbytes) { int retval; struct agilent_82357a_priv *a_priv = board->private_data; - struct usb_device *usb_dev = interface_to_usbdev(a_priv->bus_interface); + struct usb_device *usb_dev; u8 *out_data, *in_data; int out_data_length, in_data_length; int bytes_written, bytes_read; @@ -444,6 +439,10 @@ static int agilent_82357a_read(gpib_board_t *board, uint8_t *buffer, size_t leng *nbytes = 0; *end = 0; + + if (!a_priv->bus_interface) + return -ENODEV; + usb_dev = interface_to_usbdev(a_priv->bus_interface); out_data_length = 0x9; out_data = kmalloc(out_data_length, GFP_KERNEL); if (!out_data) @@ -469,8 +468,8 @@ static int agilent_82357a_read(gpib_board_t *board, uint8_t *buffer, size_t leng retval = agilent_82357a_send_bulk_msg(a_priv, out_data, i, &bytes_written, msec_timeout); kfree(out_data); if (retval || bytes_written != i) { - dev_err(&usb_dev->dev, "%s: agilent_82357a_send_bulk_msg returned %i, bytes_written=%i, i=%i\n", - __func__, retval, bytes_written, i); + dev_err(&usb_dev->dev, "send_bulk_msg returned %i, bytes_written=%i, i=%i\n", + retval, bytes_written, i); mutex_unlock(&a_priv->bulk_transfer_lock); if (retval < 0) return retval; @@ -501,19 +500,19 @@ static int agilent_82357a_read(gpib_board_t *board, uint8_t *buffer, size_t leng &extra_bytes_read, 100); bytes_read += extra_bytes_read; if (extra_bytes_retval) { - dev_err(&usb_dev->dev, "%s: extra_bytes_retval=%i, bytes_read=%i\n", - __func__, extra_bytes_retval, bytes_read); + dev_err(&usb_dev->dev, "extra_bytes_retval=%i, bytes_read=%i\n", + extra_bytes_retval, bytes_read); agilent_82357a_abort(a_priv, 0); } } else if (retval) { - dev_err(&usb_dev->dev, "%s: agilent_82357a_receive_bulk_msg returned %i, bytes_read=%i\n", - __func__, retval, bytes_read); + dev_err(&usb_dev->dev, "receive_bulk_msg returned %i, bytes_read=%i\n", + retval, bytes_read); agilent_82357a_abort(a_priv, 0); } mutex_unlock(&a_priv->bulk_transfer_lock); if (bytes_read > length + 1) { bytes_read = length + 1; - pr_warn("%s: bytes_read > length? truncating", __func__); + dev_warn(&usb_dev->dev, "bytes_read > length? truncating"); } if (bytes_read >= 1) { @@ -535,12 +534,14 @@ static int agilent_82357a_read(gpib_board_t *board, uint8_t *buffer, size_t leng return retval; } -static ssize_t agilent_82357a_generic_write(gpib_board_t *board, uint8_t *buffer, size_t length, - int send_commands, int send_eoi, size_t *bytes_written) +static ssize_t agilent_82357a_generic_write(struct gpib_board *board, + uint8_t *buffer, size_t length, + int send_commands, int send_eoi, + size_t *bytes_written) { int retval; struct agilent_82357a_priv *a_priv = board->private_data; - struct usb_device *usb_dev = interface_to_usbdev(a_priv->bus_interface); + struct usb_device *usb_dev; u8 *out_data = NULL; u8 *status_data = NULL; int out_data_length; @@ -551,6 +552,10 @@ static ssize_t agilent_82357a_generic_write(gpib_board_t *board, uint8_t *buffer struct agilent_82357a_register_pairlet read_reg; *bytes_written = 0; + if (!a_priv->bus_interface) + return -ENODEV; + + usb_dev = interface_to_usbdev(a_priv->bus_interface); out_data_length = length + 0x8; out_data = kmalloc(out_data_length, GFP_KERNEL); if (!out_data) @@ -584,8 +589,8 @@ static ssize_t agilent_82357a_generic_write(gpib_board_t *board, uint8_t *buffer kfree(out_data); if (retval || raw_bytes_written != i) { agilent_82357a_abort(a_priv, 0); - dev_err(&usb_dev->dev, "%s: agilent_82357a_send_bulk_msg returned %i, raw_bytes_written=%i, i=%i\n", - __func__, retval, raw_bytes_written, i); + dev_err(&usb_dev->dev, "send_bulk_msg returned %i, raw_bytes_written=%i, i=%i\n", + retval, raw_bytes_written, i); mutex_unlock(&a_priv->bulk_transfer_lock); if (retval < 0) return retval; @@ -597,7 +602,7 @@ static ssize_t agilent_82357a_generic_write(gpib_board_t *board, uint8_t *buffer &a_priv->interrupt_flags) || test_bit(TIMO_NUM, &board->status)); if (retval) { - dev_err(&usb_dev->dev, "%s: wait write complete interrupted\n", __func__); + dev_dbg(&usb_dev->dev, "wait write complete interrupted\n"); agilent_82357a_abort(a_priv, 0); mutex_unlock(&a_priv->bulk_transfer_lock); return -ERESTARTSYS; @@ -614,8 +619,7 @@ static ssize_t agilent_82357a_generic_write(gpib_board_t *board, uint8_t *buffer read_reg.address = BSR; retval = agilent_82357a_read_registers(a_priv, &read_reg, 1, 1); if (retval) { - dev_err(&usb_dev->dev, "%s: agilent_82357a_read_registers() returned error\n", - __func__); + dev_err(&usb_dev->dev, "read_registers() returned error\n"); return -ETIMEDOUT; } @@ -632,8 +636,7 @@ static ssize_t agilent_82357a_generic_write(gpib_board_t *board, uint8_t *buffer read_reg.address = ADSR; retval = agilent_82357a_read_registers(a_priv, &read_reg, 1, 1); if (retval) { - dev_err(&usb_dev->dev, "%s: agilent_82357a_read_registers() returned error\n", - __func__); + dev_err(&usb_dev->dev, "read_registers() returned error\n"); return -ETIMEDOUT; } adsr = read_reg.value; @@ -659,8 +662,7 @@ static ssize_t agilent_82357a_generic_write(gpib_board_t *board, uint8_t *buffer 100); mutex_unlock(&a_priv->bulk_transfer_lock); if (retval < 0) { - dev_err(&usb_dev->dev, "%s: agilent_82357a_receive_control_msg() returned %i\n", - __func__, retval); + dev_err(&usb_dev->dev, "receive_control_msg() returned %i\n", retval); kfree(status_data); return -EIO; } @@ -673,19 +675,19 @@ static ssize_t agilent_82357a_generic_write(gpib_board_t *board, uint8_t *buffer return 0; } -static int agilent_82357a_write(gpib_board_t *board, uint8_t *buffer, size_t length, - int send_eoi, size_t *bytes_written) +static int agilent_82357a_write(struct gpib_board *board, uint8_t *buffer, + size_t length, int send_eoi, size_t *bytes_written) { return agilent_82357a_generic_write(board, buffer, length, 0, send_eoi, bytes_written); } -int agilent_82357a_command(gpib_board_t *board, uint8_t *buffer, size_t length, +int agilent_82357a_command(struct gpib_board *board, uint8_t *buffer, size_t length, size_t *bytes_written) { return agilent_82357a_generic_write(board, buffer, length, 1, 0, bytes_written); } -int agilent_82357a_take_control_internal(gpib_board_t *board, int synchronous) +int agilent_82357a_take_control_internal(struct gpib_board *board, int synchronous) { struct agilent_82357a_priv *a_priv = board->private_data; struct usb_device *usb_dev = interface_to_usbdev(a_priv->bus_interface); @@ -699,17 +701,20 @@ int agilent_82357a_take_control_internal(gpib_board_t *board, int synchronous) write.value = AUX_TCA; retval = agilent_82357a_write_registers(a_priv, &write, 1); if (retval) - dev_err(&usb_dev->dev, "%s: agilent_82357a_write_registers() returned error\n", - __func__); + dev_err(&usb_dev->dev, "write_registers() returned error\n"); return retval; } -static int agilent_82357a_take_control(gpib_board_t *board, int synchronous) +static int agilent_82357a_take_control(struct gpib_board *board, int synchronous) { + struct agilent_82357a_priv *a_priv = board->private_data; const int timeout = 10; int i; + if (!a_priv->bus_interface) + return -ENODEV; + /* It looks like the 9914 does not handle tcs properly. * See comment above tms9914_take_control_workaround() in * drivers/gpib/tms9914/tms9914_aux.c @@ -730,31 +735,39 @@ static int agilent_82357a_take_control(gpib_board_t *board, int synchronous) return 0; } -static int agilent_82357a_go_to_standby(gpib_board_t *board) +static int agilent_82357a_go_to_standby(struct gpib_board *board) { struct agilent_82357a_priv *a_priv = board->private_data; - struct usb_device *usb_dev = interface_to_usbdev(a_priv->bus_interface); + struct usb_device *usb_dev; struct agilent_82357a_register_pairlet write; int retval; + if (!a_priv->bus_interface) + return -ENODEV; + + usb_dev = interface_to_usbdev(a_priv->bus_interface); write.address = AUXCR; write.value = AUX_GTS; retval = agilent_82357a_write_registers(a_priv, &write, 1); if (retval) - dev_err(&usb_dev->dev, "%s: agilent_82357a_write_registers() returned error\n", - __func__); + dev_err(&usb_dev->dev, "write_registers() returned error\n"); return 0; } //FIXME should change prototype to return int -static void agilent_82357a_request_system_control(gpib_board_t *board, int request_control) +static void agilent_82357a_request_system_control(struct gpib_board *board, + int request_control) { struct agilent_82357a_priv *a_priv = board->private_data; - struct usb_device *usb_dev = interface_to_usbdev(a_priv->bus_interface); + struct usb_device *usb_dev; struct agilent_82357a_register_pairlet writes[2]; int retval; int i = 0; + if (!a_priv->bus_interface) + return; // -ENODEV; + + usb_dev = interface_to_usbdev(a_priv->bus_interface); /* 82357B needs bit to be set in 9914 AUXCR register */ writes[i].address = AUXCR; if (request_control) { @@ -771,18 +784,21 @@ static void agilent_82357a_request_system_control(gpib_board_t *board, int reque ++i; retval = agilent_82357a_write_registers(a_priv, writes, i); if (retval) - dev_err(&usb_dev->dev, "%s: agilent_82357a_write_registers() returned error\n", - __func__); + dev_err(&usb_dev->dev, "write_registers() returned error\n"); return;// retval; } -static void agilent_82357a_interface_clear(gpib_board_t *board, int assert) +static void agilent_82357a_interface_clear(struct gpib_board *board, int assert) { struct agilent_82357a_priv *a_priv = board->private_data; - struct usb_device *usb_dev = interface_to_usbdev(a_priv->bus_interface); + struct usb_device *usb_dev; struct agilent_82357a_register_pairlet write; int retval; + if (!a_priv->bus_interface) + return; // -ENODEV; + + usb_dev = interface_to_usbdev(a_priv->bus_interface); write.address = AUXCR; write.value = AUX_SIC; if (assert) { @@ -791,56 +807,64 @@ static void agilent_82357a_interface_clear(gpib_board_t *board, int assert) } retval = agilent_82357a_write_registers(a_priv, &write, 1); if (retval) - dev_err(&usb_dev->dev, "%s: agilent_82357a_write_registers() returned error\n", - __func__); + dev_err(&usb_dev->dev, "write_registers() returned error\n"); } -static void agilent_82357a_remote_enable(gpib_board_t *board, int enable) +static void agilent_82357a_remote_enable(struct gpib_board *board, int enable) { struct agilent_82357a_priv *a_priv = board->private_data; - struct usb_device *usb_dev = interface_to_usbdev(a_priv->bus_interface); + struct usb_device *usb_dev; struct agilent_82357a_register_pairlet write; int retval; + if (!a_priv->bus_interface) + return; //-ENODEV; + + usb_dev = interface_to_usbdev(a_priv->bus_interface); write.address = AUXCR; write.value = AUX_SRE; if (enable) write.value |= AUX_CS; retval = agilent_82357a_write_registers(a_priv, &write, 1); if (retval) - dev_err(&usb_dev->dev, "%s: agilent_82357a_write_registers() returned error\n", - __func__); + dev_err(&usb_dev->dev, "write_registers() returned error\n"); a_priv->ren_state = enable; return;// 0; } -static int agilent_82357a_enable_eos(gpib_board_t *board, uint8_t eos_byte, int compare_8_bits) +static int agilent_82357a_enable_eos(struct gpib_board *board, uint8_t eos_byte, + int compare_8_bits) { struct agilent_82357a_priv *a_priv = board->private_data; - if (compare_8_bits == 0) { - pr_warn("%s: hardware only supports 8-bit EOS compare", __func__); + if (!a_priv->bus_interface) + return -ENODEV; + if (compare_8_bits == 0) return -EOPNOTSUPP; - } + a_priv->eos_char = eos_byte; a_priv->eos_mode = REOS | BIN; return 0; } -static void agilent_82357a_disable_eos(gpib_board_t *board) +static void agilent_82357a_disable_eos(struct gpib_board *board) { struct agilent_82357a_priv *a_priv = board->private_data; a_priv->eos_mode &= ~REOS; } -static unsigned int agilent_82357a_update_status(gpib_board_t *board, unsigned int clear_mask) +static unsigned int agilent_82357a_update_status(struct gpib_board *board, + unsigned int clear_mask) { struct agilent_82357a_priv *a_priv = board->private_data; - struct usb_device *usb_dev = interface_to_usbdev(a_priv->bus_interface); + struct usb_device *usb_dev; struct agilent_82357a_register_pairlet address_status, bus_status; int retval; + if (!a_priv->bus_interface) + return -ENODEV; + usb_dev = interface_to_usbdev(a_priv->bus_interface); board->status &= ~clear_mask; if (a_priv->is_cic) set_bit(CIC_NUM, &board->status); @@ -850,8 +874,7 @@ static unsigned int agilent_82357a_update_status(gpib_board_t *board, unsigned i retval = agilent_82357a_read_registers(a_priv, &address_status, 1, 0); if (retval) { if (retval != -EAGAIN) - dev_err(&usb_dev->dev, "%s: agilent_82357a_read_registers() returned error\n", - __func__); + dev_err(&usb_dev->dev, "read_registers() returned error\n"); return board->status; } // check for remote/local @@ -883,8 +906,7 @@ static unsigned int agilent_82357a_update_status(gpib_board_t *board, unsigned i retval = agilent_82357a_read_registers(a_priv, &bus_status, 1, 0); if (retval) { if (retval != -EAGAIN) - dev_err(&usb_dev->dev, "%s: agilent_82357a_read_registers() returned error\n", - __func__); + dev_err(&usb_dev->dev, "read_registers() returned error\n"); return board->status; } if (bus_status.value & BSR_SRQ_BIT) @@ -895,40 +917,46 @@ static unsigned int agilent_82357a_update_status(gpib_board_t *board, unsigned i return board->status; } -static int agilent_82357a_primary_address(gpib_board_t *board, unsigned int address) +static int agilent_82357a_primary_address(struct gpib_board *board, unsigned int address) { struct agilent_82357a_priv *a_priv = board->private_data; struct usb_device *usb_dev = interface_to_usbdev(a_priv->bus_interface); struct agilent_82357a_register_pairlet write; int retval; + if (!a_priv->bus_interface) + return -ENODEV; + usb_dev = interface_to_usbdev(a_priv->bus_interface); // put primary address in address0 write.address = ADR; write.value = address & ADDRESS_MASK; retval = agilent_82357a_write_registers(a_priv, &write, 1); if (retval) { - dev_err(&usb_dev->dev, "%s: agilent_82357a_write_registers() returned error\n", - __func__); + dev_err(&usb_dev->dev, "write_registers() returned error\n"); return retval; } return retval; } -static int agilent_82357a_secondary_address(gpib_board_t *board, unsigned int address, int enable) +static int agilent_82357a_secondary_address(struct gpib_board *board, + unsigned int address, int enable) { if (enable) - pr_warn("%s: warning: assigning a secondary address not supported\n", __func__); - return -EOPNOTSUPP; + return -EOPNOTSUPP; + return 0; } -static int agilent_82357a_parallel_poll(gpib_board_t *board, uint8_t *result) +static int agilent_82357a_parallel_poll(struct gpib_board *board, uint8_t *result) { struct agilent_82357a_priv *a_priv = board->private_data; - struct usb_device *usb_dev = interface_to_usbdev(a_priv->bus_interface); + struct usb_device *usb_dev; struct agilent_82357a_register_pairlet writes[2]; struct agilent_82357a_register_pairlet read; int retval; + if (!a_priv->bus_interface) + return -ENODEV; + usb_dev = interface_to_usbdev(a_priv->bus_interface); // execute parallel poll writes[0].address = AUXCR; writes[0].value = AUX_CS | AUX_RPP; @@ -936,16 +964,14 @@ static int agilent_82357a_parallel_poll(gpib_board_t *board, uint8_t *result) writes[1].value = a_priv->hw_control_bits & ~NOT_PARALLEL_POLL; retval = agilent_82357a_write_registers(a_priv, writes, 2); if (retval) { - dev_err(&usb_dev->dev, "%s: agilent_82357a_write_registers() returned error\n", - __func__); + dev_err(&usb_dev->dev, "write_registers() returned error\n"); return retval; } udelay(2); //silly, since usb write will take way longer read.address = CPTR; retval = agilent_82357a_read_registers(a_priv, &read, 1, 1); if (retval) { - dev_err(&usb_dev->dev, "%s: agilent_82357a_read_registers() returned error\n", - __func__); + dev_err(&usb_dev->dev, "read_registers() returned error\n"); return retval; } *result = read.value; @@ -956,75 +982,76 @@ static int agilent_82357a_parallel_poll(gpib_board_t *board, uint8_t *result) writes[1].value = AUX_RPP; retval = agilent_82357a_write_registers(a_priv, writes, 2); if (retval) { - dev_err(&usb_dev->dev, "%s: agilent_82357a_write_registers() returned error\n", - __func__); + dev_err(&usb_dev->dev, "write_registers() returned error\n"); return retval; } return 0; } -static void agilent_82357a_parallel_poll_configure(gpib_board_t *board, uint8_t config) +static void agilent_82357a_parallel_poll_configure(struct gpib_board *board, uint8_t config) { //board can only be system controller return;// 0; } -static void agilent_82357a_parallel_poll_response(gpib_board_t *board, int ist) +static void agilent_82357a_parallel_poll_response(struct gpib_board *board, int ist) { //board can only be system controller return;// 0; } -static void agilent_82357a_serial_poll_response(gpib_board_t *board, uint8_t status) +static void agilent_82357a_serial_poll_response(struct gpib_board *board, uint8_t status) { //board can only be system controller return;// 0; } -static uint8_t agilent_82357a_serial_poll_status(gpib_board_t *board) +static uint8_t agilent_82357a_serial_poll_status(struct gpib_board *board) { //board can only be system controller return 0; } -static void agilent_82357a_return_to_local(gpib_board_t *board) +static void agilent_82357a_return_to_local(struct gpib_board *board) { //board can only be system controller return;// 0; } -static int agilent_82357a_line_status(const gpib_board_t *board) +static int agilent_82357a_line_status(const struct gpib_board *board) { struct agilent_82357a_priv *a_priv = board->private_data; - struct usb_device *usb_dev = interface_to_usbdev(a_priv->bus_interface); + struct usb_device *usb_dev; struct agilent_82357a_register_pairlet bus_status; int retval; - int status = ValidALL; + int status = VALID_ALL; + if (!a_priv->bus_interface) + return -ENODEV; + usb_dev = interface_to_usbdev(a_priv->bus_interface); bus_status.address = BSR; retval = agilent_82357a_read_registers(a_priv, &bus_status, 1, 0); if (retval) { if (retval != -EAGAIN) - dev_err(&usb_dev->dev, "%s: agilent_82357a_read_registers() returned error\n", - __func__); + dev_err(&usb_dev->dev, "read_registers() returned error\n"); return retval; } if (bus_status.value & BSR_REN_BIT) - status |= BusREN; + status |= BUS_REN; if (bus_status.value & BSR_IFC_BIT) - status |= BusIFC; + status |= BUS_IFC; if (bus_status.value & BSR_SRQ_BIT) - status |= BusSRQ; + status |= BUS_SRQ; if (bus_status.value & BSR_EOI_BIT) - status |= BusEOI; + status |= BUS_EOI; if (bus_status.value & BSR_NRFD_BIT) - status |= BusNRFD; + status |= BUS_NRFD; if (bus_status.value & BSR_NDAC_BIT) - status |= BusNDAC; + status |= BUS_NDAC; if (bus_status.value & BSR_DAV_BIT) - status |= BusDAV; + status |= BUS_DAV; if (bus_status.value & BSR_ATN_BIT) - status |= BusATN; + status |= BUS_ATN; return status; } @@ -1044,25 +1071,27 @@ static unsigned short nanosec_to_fast_talker_bits(unsigned int *nanosec) return bits; } -static unsigned int agilent_82357a_t1_delay(gpib_board_t *board, unsigned int nanosec) +static int agilent_82357a_t1_delay(struct gpib_board *board, unsigned int nanosec) { struct agilent_82357a_priv *a_priv = board->private_data; - struct usb_device *usb_dev = interface_to_usbdev(a_priv->bus_interface); + struct usb_device *usb_dev; struct agilent_82357a_register_pairlet write; int retval; + if (!a_priv->bus_interface) + return -ENODEV; + usb_dev = interface_to_usbdev(a_priv->bus_interface); write.address = FAST_TALKER_T1; write.value = nanosec_to_fast_talker_bits(&nanosec); retval = agilent_82357a_write_registers(a_priv, &write, 1); if (retval) - dev_err(&usb_dev->dev, "%s: agilent_82357a_write_registers() returned error\n", - __func__); + dev_err(&usb_dev->dev, "write_registers() returned error\n"); return nanosec; } static void agilent_82357a_interrupt_complete(struct urb *urb) { - gpib_board_t *board = urb->context; + struct gpib_board *board = urb->context; struct agilent_82357a_priv *a_priv = board->private_data; struct usb_device *usb_dev = interface_to_usbdev(a_priv->bus_interface); int retval; @@ -1081,7 +1110,7 @@ static void agilent_82357a_interrupt_complete(struct urb *urb) default: /* other error, resubmit */ retval = usb_submit_urb(a_priv->interrupt_urb, GFP_ATOMIC); if (retval) - dev_err(&usb_dev->dev, "%s: failed to resubmit interrupt urb\n", __func__); + dev_err(&usb_dev->dev, "failed to resubmit interrupt urb\n"); return; } @@ -1097,10 +1126,10 @@ static void agilent_82357a_interrupt_complete(struct urb *urb) retval = usb_submit_urb(a_priv->interrupt_urb, GFP_ATOMIC); if (retval) - dev_err(&usb_dev->dev, "%s: failed to resubmit interrupt urb\n", __func__); + dev_err(&usb_dev->dev, "failed to resubmit interrupt urb\n"); } -static int agilent_82357a_setup_urbs(gpib_board_t *board) +static int agilent_82357a_setup_urbs(struct gpib_board *board) { struct agilent_82357a_priv *a_priv = board->private_data; struct usb_device *usb_dev; @@ -1133,8 +1162,7 @@ static int agilent_82357a_setup_urbs(gpib_board_t *board) if (retval) { usb_free_urb(a_priv->interrupt_urb); a_priv->interrupt_urb = NULL; - dev_err(&usb_dev->dev, "%s: failed to submit first interrupt urb, retval=%i\n", - __func__, retval); + dev_err(&usb_dev->dev, "failed to submit first interrupt urb, retval=%i\n", retval); goto setup_exit; } mutex_unlock(&a_priv->interrupt_alloc_lock); @@ -1165,7 +1193,7 @@ static void agilent_82357a_release_urbs(struct agilent_82357a_priv *a_priv) } } -static int agilent_82357a_allocate_private(gpib_board_t *board) +static int agilent_82357a_allocate_private(struct gpib_board *board) { struct agilent_82357a_priv *a_priv; @@ -1180,112 +1208,82 @@ static int agilent_82357a_allocate_private(gpib_board_t *board) return 0; } -static void agilent_82357a_free_private(gpib_board_t *board) +static void agilent_82357a_free_private(struct gpib_board *board) { kfree(board->private_data); board->private_data = NULL; - } -static int agilent_82357a_init(gpib_board_t *board) +#define INIT_NUM_REG_WRITES 18 +static int agilent_82357a_init(struct gpib_board *board) { struct agilent_82357a_priv *a_priv = board->private_data; struct usb_device *usb_dev = interface_to_usbdev(a_priv->bus_interface); struct agilent_82357a_register_pairlet hw_control; - struct agilent_82357a_register_pairlet writes[0x20]; + struct agilent_82357a_register_pairlet writes[INIT_NUM_REG_WRITES]; int retval; - int i; unsigned int nanosec; - i = 0; - writes[i].address = LED_CONTROL; - writes[i].value = FAIL_LED_ON; - ++i; - writes[i].address = RESET_TO_POWERUP; - writes[i].value = RESET_SPACEBALL; - ++i; - retval = agilent_82357a_write_registers(a_priv, writes, i); + writes[0].address = LED_CONTROL; + writes[0].value = FAIL_LED_ON; + writes[1].address = RESET_TO_POWERUP; + writes[1].value = RESET_SPACEBALL; + retval = agilent_82357a_write_registers(a_priv, writes, 2); if (retval) { - dev_err(&usb_dev->dev, "%s: agilent_82357a_write_registers() returned error\n", - __func__); + dev_err(&usb_dev->dev, "write_registers() returned error\n"); return -EIO; } set_current_state(TASK_INTERRUPTIBLE); if (schedule_timeout(usec_to_jiffies(2000))) return -ERESTARTSYS; - i = 0; - writes[i].address = AUXCR; - writes[i].value = AUX_NBAF; - ++i; - writes[i].address = AUXCR; - writes[i].value = AUX_HLDE; - ++i; - writes[i].address = AUXCR; - writes[i].value = AUX_TON; - ++i; - writes[i].address = AUXCR; - writes[i].value = AUX_LON; - ++i; - writes[i].address = AUXCR; - writes[i].value = AUX_RSV2; - ++i; - writes[i].address = AUXCR; - writes[i].value = AUX_INVAL; - ++i; - writes[i].address = AUXCR; - writes[i].value = AUX_RPP; - ++i; - writes[i].address = AUXCR; - writes[i].value = AUX_STDL; - ++i; - writes[i].address = AUXCR; - writes[i].value = AUX_VSTDL; - ++i; - writes[i].address = FAST_TALKER_T1; + writes[0].address = AUXCR; + writes[0].value = AUX_NBAF; + writes[1].address = AUXCR; + writes[1].value = AUX_HLDE; + writes[2].address = AUXCR; + writes[2].value = AUX_TON; + writes[3].address = AUXCR; + writes[3].value = AUX_LON; + writes[4].address = AUXCR; + writes[4].value = AUX_RSV2; + writes[5].address = AUXCR; + writes[5].value = AUX_INVAL; + writes[6].address = AUXCR; + writes[6].value = AUX_RPP; + writes[7].address = AUXCR; + writes[7].value = AUX_STDL; + writes[8].address = AUXCR; + writes[8].value = AUX_VSTDL; + writes[9].address = FAST_TALKER_T1; nanosec = board->t1_nano_sec; - writes[i].value = nanosec_to_fast_talker_bits(&nanosec); + writes[9].value = nanosec_to_fast_talker_bits(&nanosec); board->t1_nano_sec = nanosec; - ++i; - writes[i].address = ADR; - writes[i].value = board->pad & ADDRESS_MASK; - ++i; - writes[i].address = PPR; - writes[i].value = 0; - ++i; - writes[i].address = SPMR; - writes[i].value = 0; - ++i; - writes[i].address = PROTOCOL_CONTROL; - writes[i].value = WRITE_COMPLETE_INTERRUPT_EN; - ++i; - writes[i].address = IMR0; - writes[i].value = HR_BOIE | HR_BIIE; - ++i; - writes[i].address = IMR1; - writes[i].value = HR_SRQIE; - ++i; + writes[10].address = ADR; + writes[10].value = board->pad & ADDRESS_MASK; + writes[11].address = PPR; + writes[11].value = 0; + writes[12].address = SPMR; + writes[12].value = 0; + writes[13].address = PROTOCOL_CONTROL; + writes[13].value = WRITE_COMPLETE_INTERRUPT_EN; + writes[14].address = IMR0; + writes[14].value = HR_BOIE | HR_BIIE; + writes[15].address = IMR1; + writes[15].value = HR_SRQIE; // turn off reset state - writes[i].address = AUXCR; - writes[i].value = AUX_CHIP_RESET; - ++i; - writes[i].address = LED_CONTROL; - writes[i].value = FIRMWARE_LED_CONTROL; - ++i; - if (i > ARRAY_SIZE(writes)) { - dev_err(&usb_dev->dev, "%s: bug! writes[] overflow\n", __func__); - return -EFAULT; - } - retval = agilent_82357a_write_registers(a_priv, writes, i); + writes[16].address = AUXCR; + writes[16].value = AUX_CHIP_RESET; + writes[17].address = LED_CONTROL; + writes[17].value = FIRMWARE_LED_CONTROL; + retval = agilent_82357a_write_registers(a_priv, writes, INIT_NUM_REG_WRITES); if (retval) { - dev_err(&usb_dev->dev, "%s: agilent_82357a_write_registers() returned error\n", - __func__); + dev_err(&usb_dev->dev, "write_registers() returned error\n"); return -EIO; } hw_control.address = HW_CONTROL; retval = agilent_82357a_read_registers(a_priv, &hw_control, 1, 1); if (retval) { - dev_err(&usb_dev->dev, "%s: agilent_82357a_read_registers() returned error\n", - __func__); + dev_err(&usb_dev->dev, "read_registers() returned error\n"); return -EIO; } a_priv->hw_control_bits = (hw_control.value & ~0x7) | NOT_TI_RESET | NOT_PARALLEL_POLL; @@ -1307,7 +1305,7 @@ static inline int agilent_82357a_device_match(struct usb_interface *interface, return 1; } -static int agilent_82357a_attach(gpib_board_t *board, const gpib_board_config_t *config) +static int agilent_82357a_attach(struct gpib_board *board, const gpib_board_config_t *config) { int retval; int i; @@ -1336,7 +1334,7 @@ static int agilent_82357a_attach(gpib_board_t *board, const gpib_board_config_t } if (i == MAX_NUM_82357A_INTERFACES) { dev_err(board->gpib_dev, - "No Agilent 82357 gpib adapters found, have you loaded its firmware?\n"); + "No supported adapters found, have you loaded its firmware?\n"); retval = -ENODEV; goto attach_fail; } @@ -1372,8 +1370,7 @@ static int agilent_82357a_attach(gpib_board_t *board, const gpib_board_config_t goto attach_fail; } - dev_info(&usb_dev->dev, - "bus %d dev num %d attached to gpib minor %d, agilent usb interface %i\n", + dev_info(&usb_dev->dev, "bus %d dev num %d attached to gpib%d, interface %i\n", usb_dev->bus->busnum, usb_dev->devnum, board->minor, i); mutex_unlock(&agilent_82357a_hotplug_lock); return retval; @@ -1384,49 +1381,36 @@ static int agilent_82357a_attach(gpib_board_t *board, const gpib_board_config_t return retval; } -static int agilent_82357a_go_idle(gpib_board_t *board) +static int agilent_82357a_go_idle(struct gpib_board *board) { struct agilent_82357a_priv *a_priv = board->private_data; struct usb_device *usb_dev = interface_to_usbdev(a_priv->bus_interface); struct agilent_82357a_register_pairlet writes[0x20]; int retval; - int i; - i = 0; // turn on tms9914 reset state - writes[i].address = AUXCR; - writes[i].value = AUX_CS | AUX_CHIP_RESET; - ++i; + writes[0].address = AUXCR; + writes[0].value = AUX_CS | AUX_CHIP_RESET; a_priv->hw_control_bits &= ~NOT_TI_RESET; - writes[i].address = HW_CONTROL; - writes[i].value = a_priv->hw_control_bits; - ++i; - writes[i].address = PROTOCOL_CONTROL; - writes[i].value = 0; - ++i; - writes[i].address = IMR0; - writes[i].value = 0; - ++i; - writes[i].address = IMR1; - writes[i].value = 0; - ++i; - writes[i].address = LED_CONTROL; - writes[i].value = 0; - ++i; - if (i > ARRAY_SIZE(writes)) { - dev_err(&usb_dev->dev, "%s: bug! writes[] overflow\n", __func__); - return -EFAULT; - } - retval = agilent_82357a_write_registers(a_priv, writes, i); + writes[1].address = HW_CONTROL; + writes[1].value = a_priv->hw_control_bits; + writes[2].address = PROTOCOL_CONTROL; + writes[2].value = 0; + writes[3].address = IMR0; + writes[3].value = 0; + writes[4].address = IMR1; + writes[4].value = 0; + writes[5].address = LED_CONTROL; + writes[5].value = 0; + retval = agilent_82357a_write_registers(a_priv, writes, 6); if (retval) { - dev_err(&usb_dev->dev, "%s: agilent_82357a_write_registers() returned error\n", - __func__); + dev_err(&usb_dev->dev, "write_registers() returned error\n"); return -EIO; } return 0; } -static void agilent_82357a_detach(gpib_board_t *board) +static void agilent_82357a_detach(struct gpib_board *board) { struct agilent_82357a_priv *a_priv; @@ -1445,7 +1429,6 @@ static void agilent_82357a_detach(gpib_board_t *board) agilent_82357a_release_urbs(a_priv); agilent_82357a_free_private(board); } - dev_info(board->gpib_dev, "%s: detached\n", __func__); mutex_unlock(&agilent_82357a_hotplug_lock); } @@ -1510,8 +1493,7 @@ static int agilent_82357a_driver_probe(struct usb_interface *interface, if (i == MAX_NUM_82357A_INTERFACES) { usb_put_dev(usb_dev); mutex_unlock(&agilent_82357a_hotplug_lock); - dev_err(&usb_dev->dev, "%s: out of space in agilent_82357a_driver_interfaces[]\n", - __func__); + dev_err(&usb_dev->dev, "out of space in agilent_82357a_driver_interfaces[]\n"); return -1; } path = kmalloc(path_length, GFP_KERNEL); @@ -1536,7 +1518,7 @@ static void agilent_82357a_driver_disconnect(struct usb_interface *interface) for (i = 0; i < MAX_NUM_82357A_INTERFACES; ++i) { if (agilent_82357a_driver_interfaces[i] == interface) { - gpib_board_t *board = usb_get_intfdata(interface); + struct gpib_board *board = usb_get_intfdata(interface); if (board) { struct agilent_82357a_priv *a_priv = board->private_data; @@ -1552,13 +1534,12 @@ static void agilent_82357a_driver_disconnect(struct usb_interface *interface) mutex_unlock(&a_priv->control_alloc_lock); } } - dev_dbg(&usb_dev->dev, "nulled agilent_82357a_driver_interfaces[%i]\n", i); agilent_82357a_driver_interfaces[i] = NULL; break; } } if (i == MAX_NUM_82357A_INTERFACES) - dev_err(&usb_dev->dev, "unable to find interface in agilent_82357a_driver_interfaces[]? bug?\n"); + dev_err(&usb_dev->dev, "unable to find interface - bug?\n"); usb_put_dev(usb_dev); mutex_unlock(&agilent_82357a_hotplug_lock); @@ -1573,7 +1554,7 @@ static int agilent_82357a_driver_suspend(struct usb_interface *interface, pm_mes for (i = 0; i < MAX_NUM_82357A_INTERFACES; ++i) { if (agilent_82357a_driver_interfaces[i] == interface) { - gpib_board_t *board = usb_get_intfdata(interface); + struct gpib_board *board = usb_get_intfdata(interface); if (board) { struct agilent_82357a_priv *a_priv = board->private_data; @@ -1583,18 +1564,18 @@ static int agilent_82357a_driver_suspend(struct usb_interface *interface, pm_mes agilent_82357a_abort(a_priv, 0); retval = agilent_82357a_go_idle(board); if (retval) { - dev_err(&usb_dev->dev, "%s: failed to go idle, retval=%i\n", - __func__, retval); + dev_err(&usb_dev->dev, "failed to go idle, retval=%i\n", + retval); mutex_unlock(&agilent_82357a_hotplug_lock); return retval; } mutex_lock(&a_priv->interrupt_alloc_lock); agilent_82357a_cleanup_urbs(a_priv); mutex_unlock(&a_priv->interrupt_alloc_lock); - dev_info(&usb_dev->dev, - "bus %d dev num %d gpib minor %d, agilent usb interface %i suspended\n", - usb_dev->bus->busnum, usb_dev->devnum, - board->minor, i); + dev_dbg(&usb_dev->dev, + "bus %d dev num %d gpib %d, interface %i suspended\n", + usb_dev->bus->busnum, usb_dev->devnum, + board->minor, i); } } break; @@ -1609,7 +1590,7 @@ static int agilent_82357a_driver_suspend(struct usb_interface *interface, pm_mes static int agilent_82357a_driver_resume(struct usb_interface *interface) { struct usb_device *usb_dev = interface_to_usbdev(interface); - gpib_board_t *board; + struct gpib_board *board; int i, retval; mutex_lock(&agilent_82357a_hotplug_lock); @@ -1631,8 +1612,8 @@ static int agilent_82357a_driver_resume(struct usb_interface *interface) mutex_lock(&a_priv->interrupt_alloc_lock); retval = usb_submit_urb(a_priv->interrupt_urb, GFP_KERNEL); if (retval) { - dev_err(&usb_dev->dev, "%s: failed to resubmit interrupt urb, retval=%i\n", - __func__, retval); + dev_err(&usb_dev->dev, "failed to resubmit interrupt urb in resume, retval=%i\n", + retval); mutex_unlock(&a_priv->interrupt_alloc_lock); mutex_unlock(&agilent_82357a_hotplug_lock); return retval; @@ -1655,9 +1636,9 @@ static int agilent_82357a_driver_resume(struct usb_interface *interface) // assert/unassert REN agilent_82357a_remote_enable(board, a_priv->ren_state); - dev_info(&usb_dev->dev, - "bus %d dev num %d gpib minor %d, agilent usb interface %i resumed\n", - usb_dev->bus->busnum, usb_dev->devnum, board->minor, i); + dev_dbg(&usb_dev->dev, + "bus %d dev num %d gpib%d, interface %i resumed\n", + usb_dev->bus->busnum, usb_dev->devnum, board->minor, i); } resume_exit: @@ -1667,7 +1648,7 @@ static int agilent_82357a_driver_resume(struct usb_interface *interface) } static struct usb_driver agilent_82357a_bus_driver = { - .name = "agilent_82357a_gpib", + .name = DRV_NAME, .probe = agilent_82357a_driver_probe, .disconnect = agilent_82357a_driver_disconnect, .suspend = agilent_82357a_driver_suspend, @@ -1680,19 +1661,18 @@ static int __init agilent_82357a_init_module(void) int i; int ret; - pr_info("agilent_82357a_gpib driver loading"); for (i = 0; i < MAX_NUM_82357A_INTERFACES; ++i) agilent_82357a_driver_interfaces[i] = NULL; ret = usb_register(&agilent_82357a_bus_driver); if (ret) { - pr_err("agilent_82357a: usb_register failed: error = %d\n", ret); + pr_err("usb_register failed: error = %d\n", ret); return ret; } ret = gpib_register_driver(&agilent_82357a_gpib_interface, THIS_MODULE); if (ret) { - pr_err("agilent_82357a: gpib_register_driver failed: error = %d\n", ret); + pr_err("gpib_register_driver failed: error = %d\n", ret); usb_deregister(&agilent_82357a_bus_driver); return ret; } @@ -1702,7 +1682,6 @@ static int __init agilent_82357a_init_module(void) static void __exit agilent_82357a_exit_module(void) { - pr_info("agilent_82357a_gpib driver unloading"); gpib_unregister_driver(&agilent_82357a_gpib_interface); usb_deregister(&agilent_82357a_bus_driver); }
diff --git a/drivers/staging/gpib/cb7210/Makefile b/drivers/staging/gpib/cb7210/Makefile index cda0725..d239ae8 100644 --- a/drivers/staging/gpib/cb7210/Makefile +++ b/drivers/staging/gpib/cb7210/Makefile
@@ -1,4 +1,3 @@ -ccflags-$(CONFIG_GPIB_PCMCIA) := -DGPIB_PCMCIA obj-$(CONFIG_GPIB_CB7210) += cb7210.o
diff --git a/drivers/staging/gpib/cb7210/cb7210.c b/drivers/staging/gpib/cb7210/cb7210.c index 4d22f64..6b22a33 100644 --- a/drivers/staging/gpib/cb7210/cb7210.c +++ b/drivers/staging/gpib/cb7210/cb7210.c
@@ -5,6 +5,10 @@ * copyright : (C) 2001, 2002 by Frank Mori Hess ***************************************************************************/ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#define dev_fmt pr_fmt +#define DRV_NAME KBUILD_MODNAME + #include "cb7210.h" #include <linux/ioport.h> #include <linux/sched.h> @@ -23,7 +27,10 @@ MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("GPIB driver Measurement Computing boards using cb7210.2 and cbi488.2"); -static inline int have_fifo_word(const struct cb7210_priv *cb_priv) +static int cb7210_read(struct gpib_board *board, uint8_t *buffer, size_t length, + int *end, size_t *bytes_read); + + static inline int have_fifo_word(const struct cb7210_priv *cb_priv) { if (((cb7210_read_byte(cb_priv, HS_STATUS)) & (HS_RX_MSB_NOT_EMPTY | HS_RX_LSB_NOT_EMPTY)) == @@ -33,7 +40,7 @@ static inline int have_fifo_word(const struct cb7210_priv *cb_priv) return 0; } -static inline void input_fifo_enable(gpib_board_t *board, int enable) +static inline void input_fifo_enable(struct gpib_board *board, int enable) { struct cb7210_priv *cb_priv = board->private_data; struct nec7210_priv *nec_priv = &cb_priv->nec7210_priv; @@ -69,7 +76,7 @@ static inline void input_fifo_enable(gpib_board_t *board, int enable) spin_unlock_irqrestore(&board->spinlock, flags); } -static int fifo_read(gpib_board_t *board, struct cb7210_priv *cb_priv, uint8_t *buffer, +static int fifo_read(struct gpib_board *board, struct cb7210_priv *cb_priv, uint8_t *buffer, size_t length, int *end, size_t *bytes_read) { ssize_t retval = 0; @@ -80,12 +87,12 @@ static int fifo_read(gpib_board_t *board, struct cb7210_priv *cb_priv, uint8_t * *bytes_read = 0; if (cb_priv->fifo_iobase == 0) { - pr_err("cb7210: fifo iobase is zero!\n"); + dev_err(board->gpib_dev, "fifo iobase is zero!\n"); return -EIO; } *end = 0; if (length <= cb7210_fifo_size) { - pr_err("cb7210: bug! %s with length < fifo size\n", __func__); + dev_err(board->gpib_dev, " bug! fifo read length < fifo size\n"); return -EINVAL; } @@ -100,7 +107,6 @@ static int fifo_read(gpib_board_t *board, struct cb7210_priv *cb_priv, uint8_t * test_bit(RECEIVED_END_BN, &nec_priv->state) || test_bit(DEV_CLEAR_BN, &nec_priv->state) || test_bit(TIMO_NUM, &board->status))) { - pr_warn("cb7210: fifo half full wait interrupted\n"); retval = -ERESTARTSYS; nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAI, 0); break; @@ -150,7 +156,6 @@ static int fifo_read(gpib_board_t *board, struct cb7210_priv *cb_priv, uint8_t * test_bit(RECEIVED_END_BN, &nec_priv->state) || test_bit(DEV_CLEAR_BN, &nec_priv->state) || test_bit(TIMO_NUM, &board->status))) { - pr_warn("cb7210: fifo half full wait interrupted\n"); retval = -ERESTARTSYS; } if (test_bit(TIMO_NUM, &board->status)) @@ -165,8 +170,8 @@ static int fifo_read(gpib_board_t *board, struct cb7210_priv *cb_priv, uint8_t * return retval; } -int cb7210_accel_read(gpib_board_t *board, uint8_t *buffer, - size_t length, int *end, size_t *bytes_read) +static int cb7210_accel_read(struct gpib_board *board, uint8_t *buffer, + size_t length, int *end, size_t *bytes_read) { ssize_t retval; struct cb7210_priv *cb_priv = board->private_data; @@ -185,7 +190,6 @@ int cb7210_accel_read(gpib_board_t *board, uint8_t *buffer, test_bit(READ_READY_BN, &nec_priv->state) || test_bit(DEV_CLEAR_BN, &nec_priv->state) || test_bit(TIMO_NUM, &board->status))) { - pr_warn("cb7210: read ready wait interrupted\n"); return -ERESTARTSYS; } if (test_bit(TIMO_NUM, &board->status)) @@ -225,7 +229,7 @@ static int output_fifo_empty(const struct cb7210_priv *cb_priv) return 0; } -static inline void output_fifo_enable(gpib_board_t *board, int enable) +static inline void output_fifo_enable(struct gpib_board *board, int enable) { struct cb7210_priv *cb_priv = board->private_data; struct nec7210_priv *nec_priv = &cb_priv->nec7210_priv; @@ -260,7 +264,8 @@ static inline void output_fifo_enable(gpib_board_t *board, int enable) spin_unlock_irqrestore(&board->spinlock, flags); } -static int fifo_write(gpib_board_t *board, uint8_t *buffer, size_t length, size_t *bytes_written) +static int fifo_write(struct gpib_board *board, uint8_t *buffer, size_t length, + size_t *bytes_written) { size_t count = 0; ssize_t retval = 0; @@ -271,7 +276,7 @@ static int fifo_write(gpib_board_t *board, uint8_t *buffer, size_t length, size_ *bytes_written = 0; if (cb_priv->fifo_iobase == 0) { - pr_err("cb7210: fifo iobase is zero!\n"); + dev_err(board->gpib_dev, "fifo iobase is zero!\n"); return -EINVAL; } if (length == 0) @@ -290,7 +295,6 @@ static int fifo_write(gpib_board_t *board, uint8_t *buffer, size_t length, size_ test_bit(DEV_CLEAR_BN, &nec_priv->state) || test_bit(BUS_ERROR_BN, &nec_priv->state) || test_bit(TIMO_NUM, &board->status))) { - pr_warn("cb7210: fifo wait interrupted\n"); retval = -ERESTARTSYS; break; } @@ -306,7 +310,7 @@ static int fifo_write(gpib_board_t *board, uint8_t *buffer, size_t length, size_ if (num_bytes + count > length) num_bytes = length - count; if (num_bytes % cb7210_fifo_width) { - pr_err("cb7210: bug! %s with odd number of bytes\n", __func__); + dev_err(board->gpib_dev, " bug! fifo write with odd number of bytes\n"); retval = -EINVAL; break; } @@ -331,7 +335,6 @@ static int fifo_write(gpib_board_t *board, uint8_t *buffer, size_t length, size_ test_bit(DEV_CLEAR_BN, &nec_priv->state) || test_bit(BUS_ERROR_BN, &nec_priv->state) || test_bit(TIMO_NUM, &board->status))) { - pr_err("cb7210: wait for last byte interrupted\n"); retval = -ERESTARTSYS; } if (test_bit(TIMO_NUM, &board->status)) @@ -347,8 +350,8 @@ static int fifo_write(gpib_board_t *board, uint8_t *buffer, size_t length, size_ return retval; } -int cb7210_accel_write(gpib_board_t *board, uint8_t *buffer, size_t length, int send_eoi, - size_t *bytes_written) +static int cb7210_accel_write(struct gpib_board *board, uint8_t *buffer, + size_t length, int send_eoi, size_t *bytes_written) { struct cb7210_priv *cb_priv = board->private_data; struct nec7210_priv *nec_priv = &cb_priv->nec7210_priv; @@ -375,39 +378,37 @@ int cb7210_accel_write(gpib_board_t *board, uint8_t *buffer, size_t length, int return retval; } -int cb7210_line_status(const gpib_board_t *board) +static int cb7210_line_status(const struct gpib_board *board) { - int status = ValidALL; + int status = VALID_ALL; int bsr_bits; struct cb7210_priv *cb_priv; - struct nec7210_priv *nec_priv; cb_priv = board->private_data; - nec_priv = &cb_priv->nec7210_priv; bsr_bits = cb7210_paged_read_byte(cb_priv, BUS_STATUS, BUS_STATUS_PAGE); if ((bsr_bits & BSR_REN_BIT) == 0) - status |= BusREN; + status |= BUS_REN; if ((bsr_bits & BSR_IFC_BIT) == 0) - status |= BusIFC; + status |= BUS_IFC; if ((bsr_bits & BSR_SRQ_BIT) == 0) - status |= BusSRQ; + status |= BUS_SRQ; if ((bsr_bits & BSR_EOI_BIT) == 0) - status |= BusEOI; + status |= BUS_EOI; if ((bsr_bits & BSR_NRFD_BIT) == 0) - status |= BusNRFD; + status |= BUS_NRFD; if ((bsr_bits & BSR_NDAC_BIT) == 0) - status |= BusNDAC; + status |= BUS_NDAC; if ((bsr_bits & BSR_DAV_BIT) == 0) - status |= BusDAV; + status |= BUS_DAV; if ((bsr_bits & BSR_ATN_BIT) == 0) - status |= BusATN; + status |= BUS_ATN; return status; } -unsigned int cb7210_t1_delay(gpib_board_t *board, unsigned int nano_sec) +static int cb7210_t1_delay(struct gpib_board *board, unsigned int nano_sec) { struct cb7210_priv *cb_priv = board->private_data; struct nec7210_priv *nec_priv = &cb_priv->nec7210_priv; @@ -424,16 +425,16 @@ unsigned int cb7210_t1_delay(gpib_board_t *board, unsigned int nano_sec) return retval; } -irqreturn_t cb7210_locked_internal_interrupt(gpib_board_t *board); +static irqreturn_t cb7210_locked_internal_interrupt(struct gpib_board *board); /* * GPIB interrupt service routines */ -irqreturn_t cb_pci_interrupt(int irq, void *arg) +static irqreturn_t cb_pci_interrupt(int irq, void *arg) { int bits; - gpib_board_t *board = arg; + struct gpib_board *board = arg; struct cb7210_priv *priv = board->private_data; // first task check if this is really our interrupt in a shared irq environment @@ -462,7 +463,7 @@ irqreturn_t cb_pci_interrupt(int irq, void *arg) return cb7210_locked_internal_interrupt(arg); } -irqreturn_t cb7210_internal_interrupt(gpib_board_t *board) +static irqreturn_t cb7210_internal_interrupt(struct gpib_board *board) { int hs_status, status1, status2; struct cb7210_priv *priv = board->private_data; @@ -479,7 +480,7 @@ irqreturn_t cb7210_internal_interrupt(gpib_board_t *board) status2 = read_byte(nec_priv, ISR2); nec7210_interrupt_have_status(board, nec_priv, status1, status2); - dev_dbg(board->gpib_dev, "cb7210: status 0x%x, mode 0x%x\n", hs_status, priv->hs_mode_bits); + dev_dbg(board->gpib_dev, "status 0x%x, mode 0x%x\n", hs_status, priv->hs_mode_bits); clear_bits = 0; @@ -516,7 +517,7 @@ irqreturn_t cb7210_internal_interrupt(gpib_board_t *board) return IRQ_HANDLED; } -irqreturn_t cb7210_locked_internal_interrupt(gpib_board_t *board) +static irqreturn_t cb7210_locked_internal_interrupt(struct gpib_board *board) { unsigned long flags; irqreturn_t retval; @@ -527,55 +528,57 @@ irqreturn_t cb7210_locked_internal_interrupt(gpib_board_t *board) return retval; } -irqreturn_t cb7210_interrupt(int irq, void *arg) +static irqreturn_t cb7210_interrupt(int irq, void *arg) { return cb7210_internal_interrupt(arg); } -static int cb_pci_attach(gpib_board_t *board, const gpib_board_config_t *config); -static int cb_isa_attach(gpib_board_t *board, const gpib_board_config_t *config); +static int cb_pci_attach(struct gpib_board *board, const gpib_board_config_t *config); +static int cb_isa_attach(struct gpib_board *board, const gpib_board_config_t *config); -static void cb_pci_detach(gpib_board_t *board); -static void cb_isa_detach(gpib_board_t *board); +static void cb_pci_detach(struct gpib_board *board); +static void cb_isa_detach(struct gpib_board *board); // wrappers for interface functions -int cb7210_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *end, size_t *bytes_read) +static int cb7210_read(struct gpib_board *board, uint8_t *buffer, size_t length, + int *end, size_t *bytes_read) { struct cb7210_priv *priv = board->private_data; return nec7210_read(board, &priv->nec7210_priv, buffer, length, end, bytes_read); } -int cb7210_write(gpib_board_t *board, uint8_t *buffer, size_t length, - int send_eoi, size_t *bytes_written) +static int cb7210_write(struct gpib_board *board, uint8_t *buffer, size_t length, + int send_eoi, size_t *bytes_written) { struct cb7210_priv *priv = board->private_data; return nec7210_write(board, &priv->nec7210_priv, buffer, length, send_eoi, bytes_written); } -int cb7210_command(gpib_board_t *board, uint8_t *buffer, size_t length, size_t *bytes_written) +static int cb7210_command(struct gpib_board *board, uint8_t *buffer, size_t length, + size_t *bytes_written) { struct cb7210_priv *priv = board->private_data; return nec7210_command(board, &priv->nec7210_priv, buffer, length, bytes_written); } -int cb7210_take_control(gpib_board_t *board, int synchronous) +static int cb7210_take_control(struct gpib_board *board, int synchronous) { struct cb7210_priv *priv = board->private_data; return nec7210_take_control(board, &priv->nec7210_priv, synchronous); } -int cb7210_go_to_standby(gpib_board_t *board) +static int cb7210_go_to_standby(struct gpib_board *board) { struct cb7210_priv *priv = board->private_data; return nec7210_go_to_standby(board, &priv->nec7210_priv); } -void cb7210_request_system_control(gpib_board_t *board, int request_control) +static void cb7210_request_system_control(struct gpib_board *board, int request_control) { struct cb7210_priv *priv = board->private_data; struct nec7210_priv *nec_priv = &priv->nec7210_priv; @@ -589,91 +592,91 @@ void cb7210_request_system_control(gpib_board_t *board, int request_control) nec7210_request_system_control(board, nec_priv, request_control); } -void cb7210_interface_clear(gpib_board_t *board, int assert) +static void cb7210_interface_clear(struct gpib_board *board, int assert) { struct cb7210_priv *priv = board->private_data; nec7210_interface_clear(board, &priv->nec7210_priv, assert); } -void cb7210_remote_enable(gpib_board_t *board, int enable) +static void cb7210_remote_enable(struct gpib_board *board, int enable) { struct cb7210_priv *priv = board->private_data; nec7210_remote_enable(board, &priv->nec7210_priv, enable); } -int cb7210_enable_eos(gpib_board_t *board, uint8_t eos_byte, int compare_8_bits) +static int cb7210_enable_eos(struct gpib_board *board, uint8_t eos_byte, int compare_8_bits) { struct cb7210_priv *priv = board->private_data; return nec7210_enable_eos(board, &priv->nec7210_priv, eos_byte, compare_8_bits); } -void cb7210_disable_eos(gpib_board_t *board) +static void cb7210_disable_eos(struct gpib_board *board) { struct cb7210_priv *priv = board->private_data; nec7210_disable_eos(board, &priv->nec7210_priv); } -unsigned int cb7210_update_status(gpib_board_t *board, unsigned int clear_mask) +static unsigned int cb7210_update_status(struct gpib_board *board, unsigned int clear_mask) { struct cb7210_priv *priv = board->private_data; return nec7210_update_status(board, &priv->nec7210_priv, clear_mask); } -int cb7210_primary_address(gpib_board_t *board, unsigned int address) +static int cb7210_primary_address(struct gpib_board *board, unsigned int address) { struct cb7210_priv *priv = board->private_data; return nec7210_primary_address(board, &priv->nec7210_priv, address); } -int cb7210_secondary_address(gpib_board_t *board, unsigned int address, int enable) +static int cb7210_secondary_address(struct gpib_board *board, unsigned int address, int enable) { struct cb7210_priv *priv = board->private_data; return nec7210_secondary_address(board, &priv->nec7210_priv, address, enable); } -int cb7210_parallel_poll(gpib_board_t *board, uint8_t *result) +static int cb7210_parallel_poll(struct gpib_board *board, uint8_t *result) { struct cb7210_priv *priv = board->private_data; return nec7210_parallel_poll(board, &priv->nec7210_priv, result); } -void cb7210_parallel_poll_configure(gpib_board_t *board, uint8_t configuration) +static void cb7210_parallel_poll_configure(struct gpib_board *board, uint8_t configuration) { struct cb7210_priv *priv = board->private_data; nec7210_parallel_poll_configure(board, &priv->nec7210_priv, configuration); } -void cb7210_parallel_poll_response(gpib_board_t *board, int ist) +static void cb7210_parallel_poll_response(struct gpib_board *board, int ist) { struct cb7210_priv *priv = board->private_data; nec7210_parallel_poll_response(board, &priv->nec7210_priv, ist); } -void cb7210_serial_poll_response(gpib_board_t *board, uint8_t status) +static void cb7210_serial_poll_response(struct gpib_board *board, uint8_t status) { struct cb7210_priv *priv = board->private_data; nec7210_serial_poll_response(board, &priv->nec7210_priv, status); } -uint8_t cb7210_serial_poll_status(gpib_board_t *board) +static uint8_t cb7210_serial_poll_status(struct gpib_board *board) { struct cb7210_priv *priv = board->private_data; return nec7210_serial_poll_status(board, &priv->nec7210_priv); } -void cb7210_return_to_local(gpib_board_t *board) +static void cb7210_return_to_local(struct gpib_board *board) { struct cb7210_priv *priv = board->private_data; struct nec7210_priv *nec_priv = &priv->nec7210_priv; @@ -849,27 +852,27 @@ static gpib_interface_t cb_isa_accel_interface = { .return_to_local = cb7210_return_to_local, }; -static int cb7210_allocate_private(gpib_board_t *board) +static int cb7210_allocate_private(struct gpib_board *board) { struct cb7210_priv *priv; board->private_data = kmalloc(sizeof(struct cb7210_priv), GFP_KERNEL); if (!board->private_data) - return -1; + return -ENOMEM; priv = board->private_data; memset(priv, 0, sizeof(struct cb7210_priv)); init_nec7210_private(&priv->nec7210_priv); return 0; } -void cb7210_generic_detach(gpib_board_t *board) +static void cb7210_generic_detach(struct gpib_board *board) { kfree(board->private_data); board->private_data = NULL; } // generic part of attach functions shared by all cb7210 boards -int cb7210_generic_attach(gpib_board_t *board) +static int cb7210_generic_attach(struct gpib_board *board) { struct cb7210_priv *cb_priv; struct nec7210_priv *nec_priv; @@ -887,7 +890,7 @@ int cb7210_generic_attach(gpib_board_t *board) return 0; } -int cb7210_init(struct cb7210_priv *cb_priv, gpib_board_t *board) +static int cb7210_init(struct cb7210_priv *cb_priv, struct gpib_board *board) { struct nec7210_priv *nec_priv = &cb_priv->nec7210_priv; @@ -917,13 +920,13 @@ int cb7210_init(struct cb7210_priv *cb_priv, gpib_board_t *board) /* poll so we can detect assertion of ATN */ if (gpib_request_pseudo_irq(board, cb_pci_interrupt)) { - pr_err("pc2_gpib: failed to allocate pseudo_irq\n"); + pr_err("failed to allocate pseudo_irq\n"); return -1; } return 0; } -int cb_pci_attach(gpib_board_t *board, const gpib_board_config_t *config) +static int cb_pci_attach(struct gpib_board *board, const gpib_board_config_t *config) { struct cb7210_priv *cb_priv; struct nec7210_priv *nec_priv; @@ -957,17 +960,17 @@ int cb_pci_attach(gpib_board_t *board, const gpib_board_config_t *config) } } if (!cb_priv->pci_device) { - pr_warn("cb7210: no supported boards found.\n"); - return -1; + dev_err(board->gpib_dev, "no supported boards found.\n"); + return -ENODEV; } if (pci_enable_device(cb_priv->pci_device)) { - pr_err("cb7210: error enabling pci device\n"); - return -1; + dev_err(board->gpib_dev, "error enabling pci device\n"); + return -EIO; } - if (pci_request_regions(cb_priv->pci_device, "cb7210")) - return -1; + if (pci_request_regions(cb_priv->pci_device, DRV_NAME)) + return -EBUSY; switch (cb_priv->pci_chip) { case PCI_CHIP_AMCC_S5933: cb_priv->amcc_iobase = pci_resource_start(cb_priv->pci_device, 0); @@ -979,13 +982,14 @@ int cb_pci_attach(gpib_board_t *board, const gpib_board_config_t *config) cb_priv->fifo_iobase = nec_priv->iobase; break; default: - pr_err("cb7210: bug! unhandled pci_chip=%i\n", cb_priv->pci_chip); + dev_err(board->gpib_dev, "bug! unhandled pci_chip=%i\n", cb_priv->pci_chip); return -EIO; } isr_flags |= IRQF_SHARED; - if (request_irq(cb_priv->pci_device->irq, cb_pci_interrupt, isr_flags, "cb7210", board)) { - pr_err("cb7210: can't request IRQ %d\n", cb_priv->pci_device->irq); - return -1; + if (request_irq(cb_priv->pci_device->irq, cb_pci_interrupt, isr_flags, DRV_NAME, board)) { + dev_err(board->gpib_dev, "can't request IRQ %d\n", + cb_priv->pci_device->irq); + return -EBUSY; } cb_priv->irq = cb_priv->pci_device->irq; @@ -1004,7 +1008,7 @@ int cb_pci_attach(gpib_board_t *board, const gpib_board_config_t *config) return cb7210_init(cb_priv, board); } -void cb_pci_detach(gpib_board_t *board) +static void cb_pci_detach(struct gpib_board *board) { struct cb7210_priv *cb_priv = board->private_data; struct nec7210_priv *nec_priv; @@ -1027,7 +1031,7 @@ void cb_pci_detach(gpib_board_t *board) cb7210_generic_detach(board); } -int cb_isa_attach(gpib_board_t *board, const gpib_board_config_t *config) +static int cb_isa_attach(struct gpib_board *board, const gpib_board_config_t *config) { int isr_flags = 0; struct cb7210_priv *cb_priv; @@ -1040,20 +1044,22 @@ int cb_isa_attach(gpib_board_t *board, const gpib_board_config_t *config) return retval; cb_priv = board->private_data; nec_priv = &cb_priv->nec7210_priv; - if (!request_region(config->ibbase, cb7210_iosize, "cb7210")) { - pr_err("gpib: ioports starting at 0x%x are already in use\n", config->ibbase); - return -EIO; + if (!request_region(config->ibbase, cb7210_iosize, DRV_NAME)) { + dev_err(board->gpib_dev, "ioports starting at 0x%x are already in use\n", + config->ibbase); + return -EBUSY; } nec_priv->iobase = config->ibbase; cb_priv->fifo_iobase = nec7210_iobase(cb_priv); bits = irq_bits(config->ibirq); if (bits == 0) - pr_err("board incapable of using irq %i, try 2-5, 7, 10, or 11\n", config->ibirq); + dev_err(board->gpib_dev, "board incapable of using irq %i, try 2-5, 7, 10, or 11\n", + config->ibirq); // install interrupt handler - if (request_irq(config->ibirq, cb7210_interrupt, isr_flags, "cb7210", board)) { - pr_err("gpib: can't request IRQ %d\n", config->ibirq); + if (request_irq(config->ibirq, cb7210_interrupt, isr_flags, DRV_NAME, board)) { + dev_err(board->gpib_dev, "failed to obtain IRQ %d\n", config->ibirq); return -EBUSY; } cb_priv->irq = config->ibirq; @@ -1061,7 +1067,7 @@ int cb_isa_attach(gpib_board_t *board, const gpib_board_config_t *config) return cb7210_init(cb_priv, board); } -void cb_isa_detach(gpib_board_t *board) +static void cb_isa_detach(struct gpib_board *board) { struct cb7210_priv *cb_priv = board->private_data; struct nec7210_priv *nec_priv; @@ -1093,7 +1099,7 @@ static const struct pci_device_id cb7210_pci_table[] = { MODULE_DEVICE_TABLE(pci, cb7210_pci_table); static struct pci_driver cb7210_pci_driver = { - .name = "cb7210", + .name = DRV_NAME, .id_table = cb7210_pci_table, .probe = &cb7210_pci_probe }; @@ -1106,7 +1112,7 @@ static struct pci_driver cb7210_pci_driver = { * pcmcia skeleton example (presumably David Hinds) ***************************************************************************/ -#ifdef GPIB_PCMCIA +#ifdef CONFIG_GPIB_PCMCIA #include <linux/kernel.h> #include <linux/ptrace.h> @@ -1117,23 +1123,6 @@ static struct pci_driver cb7210_pci_driver = { #include <pcmcia/ds.h> /* - * All the PCMCIA modules use PCMCIA_DEBUG to control debugging. If - * you do not define PCMCIA_DEBUG at all, all the debug code will be - * left out. If you compile with PCMCIA_DEBUG=0, the debug code will - * be present but disabled -- but it can then be enabled for specific - * modules at load time with a 'pc_debug=#' option to insmod. - */ - -#define PCMCIA_DEBUG 1 - -#ifdef PCMCIA_DEBUG -static int pc_debug = PCMCIA_DEBUG; -#define DEBUG(n, args...) do {if (pc_debug > (n)) pr_debug(args); } while (0) -#else -#define DEBUG(args...) -#endif - -/* * The event() function is this driver's Card Services event handler. * It will be called by Card Services when an appropriate card status * event is received. The config() and release() entry points are @@ -1144,8 +1133,8 @@ static int pc_debug = PCMCIA_DEBUG; static int cb_gpib_config(struct pcmcia_device *link); static void cb_gpib_release(struct pcmcia_device *link); -static int cb_pcmcia_attach(gpib_board_t *board, const gpib_board_config_t *config); -static void cb_pcmcia_detach(gpib_board_t *board); +static int cb_pcmcia_attach(struct gpib_board *board, const gpib_board_config_t *config); +static void cb_pcmcia_detach(struct gpib_board *board); /* * A linked list of "instances" of the gpib device. Each actual @@ -1178,7 +1167,7 @@ static struct pcmcia_device *curr_dev; struct local_info { struct pcmcia_device *p_dev; - gpib_board_t *dev; + struct gpib_board *dev; }; /* @@ -1197,8 +1186,6 @@ static int cb_gpib_probe(struct pcmcia_device *link) // int ret, i; - DEBUG(0, "%s(0x%p)\n", __func__, link); - /* Allocate space for private device-specific data */ info = kzalloc(sizeof(*info), GFP_KERNEL); if (!info) @@ -1236,9 +1223,7 @@ static int cb_gpib_probe(struct pcmcia_device *link) static void cb_gpib_remove(struct pcmcia_device *link) { struct local_info *info = link->priv; - //struct gpib_board_t *dev = info->dev; - - DEBUG(0, "%s(0x%p)\n", __func__, link); + //struct struct gpib_board *dev = info->dev; if (info->dev) cb_pcmcia_detach(info->dev); @@ -1267,7 +1252,6 @@ static int cb_gpib_config(struct pcmcia_device *link) handle = link; dev = link->priv; - DEBUG(0, "%s(0x%p)\n", __func__, link); retval = pcmcia_loop_config(link, &cb_gpib_config_iteration, NULL); if (retval) { @@ -1276,8 +1260,6 @@ static int cb_gpib_config(struct pcmcia_device *link) return -ENODEV; } - DEBUG(0, "gpib_cs: manufacturer: 0x%x card: 0x%x\n", link->manf_id, link->card_id); - /* * This actually configures the PCMCIA socket -- setting up * the I/O windows and the interrupt mapping. @@ -1289,7 +1271,6 @@ static int cb_gpib_config(struct pcmcia_device *link) return -ENODEV; } - pr_info("gpib device loaded\n"); return 0; } /* gpib_config */ @@ -1301,18 +1282,16 @@ static int cb_gpib_config(struct pcmcia_device *link) static void cb_gpib_release(struct pcmcia_device *link) { - DEBUG(0, "%s(0x%p)\n", __func__, link); pcmcia_disable_device(link); } static int cb_gpib_suspend(struct pcmcia_device *link) { //struct local_info *info = link->priv; - //struct gpib_board_t *dev = info->dev; - DEBUG(0, "%s(0x%p)\n", __func__, link); + //struct struct gpib_board *dev = info->dev; if (link->open) - pr_warn("Device still open ???\n"); + dev_warn(&link->dev, "Device still open\n"); //netif_device_detach(dev); return 0; @@ -1321,12 +1300,10 @@ static int cb_gpib_suspend(struct pcmcia_device *link) static int cb_gpib_resume(struct pcmcia_device *link) { //struct local_info *info = link->priv; - //struct gpib_board_t *dev = info->dev; - DEBUG(0, "%s(0x%p)\n", __func__, link); + //struct struct gpib_board *dev = info->dev; /*if (link->open) { * ni_gpib_probe(dev); / really? - * printk("Gpib resumed ???\n"); * //netif_device_attach(dev); * */ @@ -1342,8 +1319,8 @@ static struct pcmcia_device_id cb_pcmcia_ids[] = { MODULE_DEVICE_TABLE(pcmcia, cb_pcmcia_ids); static struct pcmcia_driver cb_gpib_cs_driver = { + .name = "cb_gpib_cs", .owner = THIS_MODULE, - .drv = { .name = "cb_gpib_cs", }, .id_table = cb_pcmcia_ids, .probe = cb_gpib_probe, .remove = cb_gpib_remove, @@ -1351,9 +1328,8 @@ static struct pcmcia_driver cb_gpib_cs_driver = { .resume = cb_gpib_resume, }; -void cb_pcmcia_cleanup_module(void) +static void cb_pcmcia_cleanup_module(void) { - DEBUG(0, "cb_gpib_cs: unloading\n"); pcmcia_unregister_driver(&cb_gpib_cs_driver); } @@ -1441,15 +1417,15 @@ static gpib_interface_t cb_pcmcia_accel_interface = { .return_to_local = cb7210_return_to_local, }; -int cb_pcmcia_attach(gpib_board_t *board, const gpib_board_config_t *config) +static int cb_pcmcia_attach(struct gpib_board *board, const gpib_board_config_t *config) { struct cb7210_priv *cb_priv; struct nec7210_priv *nec_priv; int retval; if (!curr_dev) { - pr_err("no cb pcmcia cards found\n"); - return -1; + dev_err(board->gpib_dev, "no cb pcmcia cards found\n"); + return -ENODEV; } retval = cb7210_generic_attach(board); @@ -1460,25 +1436,24 @@ int cb_pcmcia_attach(gpib_board_t *board, const gpib_board_config_t *config) nec_priv = &cb_priv->nec7210_priv; if (!request_region(curr_dev->resource[0]->start, resource_size(curr_dev->resource[0]), - "cb7210")) { - pr_err("gpib: ioports starting at 0x%lx are already in use\n", - (unsigned long)curr_dev->resource[0]->start); - return -EIO; + DRV_NAME)) { + dev_err(board->gpib_dev, "ioports starting at 0x%lx are already in use\n", + (unsigned long)curr_dev->resource[0]->start); + return -EBUSY; } nec_priv->iobase = curr_dev->resource[0]->start; cb_priv->fifo_iobase = curr_dev->resource[0]->start; - if (request_irq(curr_dev->irq, cb7210_interrupt, IRQF_SHARED, - "cb7210", board)) { - pr_err("cb7210: failed to request IRQ %d\n", curr_dev->irq); - return -1; + if (request_irq(curr_dev->irq, cb7210_interrupt, IRQF_SHARED, DRV_NAME, board)) { + dev_err(board->gpib_dev, "failed to request IRQ %d\n", curr_dev->irq); + return -EBUSY; } cb_priv->irq = curr_dev->irq; return cb7210_init(cb_priv, board); } -void cb_pcmcia_detach(gpib_board_t *board) +static void cb_pcmcia_detach(struct gpib_board *board) { struct cb7210_priv *cb_priv = board->private_data; struct nec7210_priv *nec_priv; @@ -1496,7 +1471,7 @@ void cb_pcmcia_detach(gpib_board_t *board) cb7210_generic_detach(board); } -#endif /* GPIB_PCMCIA */ +#endif /* CONFIG_GPIB_PCMCIA */ static int __init cb7210_init_module(void) { @@ -1504,75 +1479,75 @@ static int __init cb7210_init_module(void) ret = pci_register_driver(&cb7210_pci_driver); if (ret) { - pr_err("cb7210: pci_register_driver failed: error = %d\n", ret); + pr_err("pci_register_driver failed: error = %d\n", ret); return ret; } ret = gpib_register_driver(&cb_pci_interface, THIS_MODULE); if (ret) { - pr_err("cb7210: gpib_register_driver failed: error = %d\n", ret); + pr_err("gpib_register_driver failed: error = %d\n", ret); goto err_pci; } ret = gpib_register_driver(&cb_isa_interface, THIS_MODULE); if (ret) { - pr_err("cb7210: gpib_register_driver failed: error = %d\n", ret); + pr_err("gpib_register_driver failed: error = %d\n", ret); goto err_isa; } ret = gpib_register_driver(&cb_pci_accel_interface, THIS_MODULE); if (ret) { - pr_err("cb7210: gpib_register_driver failed: error = %d\n", ret); + pr_err("gpib_register_driver failed: error = %d\n", ret); goto err_pci_accel; } ret = gpib_register_driver(&cb_pci_unaccel_interface, THIS_MODULE); if (ret) { - pr_err("cb7210: gpib_register_driver failed: error = %d\n", ret); + pr_err("gpib_register_driver failed: error = %d\n", ret); goto err_pci_unaccel; } ret = gpib_register_driver(&cb_isa_accel_interface, THIS_MODULE); if (ret) { - pr_err("cb7210: gpib_register_driver failed: error = %d\n", ret); + pr_err("gpib_register_driver failed: error = %d\n", ret); goto err_isa_accel; } ret = gpib_register_driver(&cb_isa_unaccel_interface, THIS_MODULE); if (ret) { - pr_err("cb7210: gpib_register_driver failed: error = %d\n", ret); + pr_err("gpib_register_driver failed: error = %d\n", ret); goto err_isa_unaccel; } -#ifdef GPIB_PCMCIA +#ifdef CONFIG_GPIB_PCMCIA ret = gpib_register_driver(&cb_pcmcia_interface, THIS_MODULE); if (ret) { - pr_err("cb7210: gpib_register_driver failed: error = %d\n", ret); + pr_err("gpib_register_driver failed: error = %d\n", ret); goto err_pcmcia; } ret = gpib_register_driver(&cb_pcmcia_accel_interface, THIS_MODULE); if (ret) { - pr_err("cb7210: gpib_register_driver failed: error = %d\n", ret); + pr_err("gpib_register_driver failed: error = %d\n", ret); goto err_pcmcia_accel; } ret = gpib_register_driver(&cb_pcmcia_unaccel_interface, THIS_MODULE); if (ret) { - pr_err("cb7210: gpib_register_driver failed: error = %d\n", ret); + pr_err("gpib_register_driver failed: error = %d\n", ret); goto err_pcmcia_unaccel; } ret = pcmcia_register_driver(&cb_gpib_cs_driver); if (ret) { - pr_err("cb7210: pcmcia_register_driver failed: error = %d\n", ret); + pr_err("pcmcia_register_driver failed: error = %d\n", ret); goto err_pcmcia_driver; } #endif return 0; -#ifdef GPIB_PCMCIA +#ifdef CONFIG_GPIB_PCMCIA err_pcmcia_driver: gpib_unregister_driver(&cb_pcmcia_unaccel_interface); err_pcmcia_unaccel: @@ -1606,7 +1581,7 @@ static void __exit cb7210_exit_module(void) gpib_unregister_driver(&cb_pci_unaccel_interface); gpib_unregister_driver(&cb_isa_accel_interface); gpib_unregister_driver(&cb_isa_unaccel_interface); -#ifdef GPIB_PCMCIA +#ifdef CONFIG_GPIB_PCMCIA gpib_unregister_driver(&cb_pcmcia_interface); gpib_unregister_driver(&cb_pcmcia_accel_interface); gpib_unregister_driver(&cb_pcmcia_unaccel_interface);
diff --git a/drivers/staging/gpib/cb7210/cb7210.h b/drivers/staging/gpib/cb7210/cb7210.h index d56cd90..2108fe7 100644 --- a/drivers/staging/gpib/cb7210/cb7210.h +++ b/drivers/staging/gpib/cb7210/cb7210.h
@@ -36,51 +36,6 @@ struct cb7210_priv { unsigned in_fifo_half_full : 1; }; -// interrupt service routines -irqreturn_t cb_pci_interrupt(int irq, void *arg); -irqreturn_t cb7210_interrupt(int irq, void *arg); -irqreturn_t cb7210_internal_interrupt(gpib_board_t *board); - -// interface functions -int cb7210_read(gpib_board_t *board, uint8_t *buffer, size_t length, - int *end, size_t *bytes_read); -int cb7210_accel_read(gpib_board_t *board, uint8_t *buffer, size_t length, - int *end, size_t *bytes_read); -int cb7210_write(gpib_board_t *board, uint8_t *buffer, size_t length, - int send_eoi, size_t *bytes_written); -int cb7210_accel_write(gpib_board_t *board, uint8_t *buffer, size_t length, - int send_eoi, size_t *bytes_written); -int cb7210_command(gpib_board_t *board, uint8_t *buffer, size_t length, size_t *bytes_written); -int cb7210_take_control(gpib_board_t *board, int synchronous); -int cb7210_go_to_standby(gpib_board_t *board); -void cb7210_request_system_control(gpib_board_t *board, int request_control); -void cb7210_interface_clear(gpib_board_t *board, int assert); -void cb7210_remote_enable(gpib_board_t *board, int enable); -int cb7210_enable_eos(gpib_board_t *board, uint8_t eos_byte, - int compare_8_bits); -void cb7210_disable_eos(gpib_board_t *board); -unsigned int cb7210_update_status(gpib_board_t *board, unsigned int clear_mask); -int cb7210_primary_address(gpib_board_t *board, unsigned int address); -int cb7210_secondary_address(gpib_board_t *board, unsigned int address, - int enable); -int cb7210_parallel_poll(gpib_board_t *board, uint8_t *result); -void cb7210_serial_poll_response(gpib_board_t *board, uint8_t status); -uint8_t cb7210_serial_poll_status(gpib_board_t *board); -void cb7210_parallel_poll_configure(gpib_board_t *board, uint8_t configuration); -void cb7210_parallel_poll_response(gpib_board_t *board, int ist); -int cb7210_line_status(const gpib_board_t *board); -unsigned int cb7210_t1_delay(gpib_board_t *board, unsigned int nano_sec); -void cb7210_return_to_local(gpib_board_t *board); - -// utility functions -void cb7210_generic_detach(gpib_board_t *board); -int cb7210_generic_attach(gpib_board_t *board); -int cb7210_init(struct cb7210_priv *priv, gpib_board_t *board); - -// pcmcia init/cleanup -int cb_pcmcia_init_module(void); -void cb_pcmcia_cleanup_module(void); - // pci-gpib register offset static const int cb7210_reg_offset = 1;
diff --git a/drivers/staging/gpib/cec/cec.h b/drivers/staging/gpib/cec/cec.h index 040ca70..3ce2869 100644 --- a/drivers/staging/gpib/cec/cec.h +++ b/drivers/staging/gpib/cec/cec.h
@@ -16,34 +16,5 @@ struct cec_priv { unsigned int irq; }; -// interface functions -int cec_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *end, size_t *bytes_read); -int cec_write(gpib_board_t *board, uint8_t *buffer, size_t length, int send_eoi, - size_t *bytes_written); -int cec_command(gpib_board_t *board, uint8_t *buffer, size_t length, size_t *bytes_written); -int cec_take_control(gpib_board_t *board, int synchronous); -int cec_go_to_standby(gpib_board_t *board); -void cec_request_system_control(gpib_board_t *board, int request_control); -void cec_interface_clear(gpib_board_t *board, int assert); -void cec_remote_enable(gpib_board_t *board, int enable); -int cec_enable_eos(gpib_board_t *board, uint8_t eos_byte, int compare_8_bits); -void cec_disable_eos(gpib_board_t *board); -unsigned int cec_update_status(gpib_board_t *board, unsigned int clear_mask); -int cec_primary_address(gpib_board_t *board, unsigned int address); -int cec_secondary_address(gpib_board_t *board, unsigned int address, int enable); -int cec_parallel_poll(gpib_board_t *board, uint8_t *result); -void cec_parallel_poll_configure(gpib_board_t *board, uint8_t configuration); -void cec_parallel_poll_response(gpib_board_t *board, int ist); -void cec_serial_poll_response(gpib_board_t *board, uint8_t status); -void cec_return_to_local(gpib_board_t *board); - -// interrupt service routines -irqreturn_t cec_interrupt(int irq, void *arg); - -// utility functions -void cec_free_private(gpib_board_t *board); -int cec_generic_attach(gpib_board_t *board); -void cec_init(struct cec_priv *priv, const gpib_board_t *board); - // offset between consecutive nec7210 registers static const int cec_reg_offset = 1;
diff --git a/drivers/staging/gpib/cec/cec_gpib.c b/drivers/staging/gpib/cec/cec_gpib.c index d056cd1..a822fa4 100644 --- a/drivers/staging/gpib/cec/cec_gpib.c +++ b/drivers/staging/gpib/cec/cec_gpib.c
@@ -4,6 +4,10 @@ * copyright : (C) 2002 by Frank Mori Hess ***************************************************************************/ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#define dev_fmt pr_fmt +#define DRV_NAME KBUILD_MODNAME + #include "cec.h" #include <linux/pci.h> #include <linux/io.h> @@ -19,9 +23,9 @@ MODULE_DESCRIPTION("GPIB driver for CEC PCI and PCMCIA boards"); * GPIB interrupt service routines */ -irqreturn_t cec_interrupt(int irq, void *arg) +static irqreturn_t cec_interrupt(int irq, void *arg) { - gpib_board_t *board = arg; + struct gpib_board *board = arg; struct cec_priv *priv = board->private_data; unsigned long flags; irqreturn_t retval; @@ -36,146 +40,148 @@ irqreturn_t cec_interrupt(int irq, void *arg) #define CEC_DEV_ID 0x5cec #define CEC_SUBID 0x9050 -static int cec_pci_attach(gpib_board_t *board, const gpib_board_config_t *config); +static int cec_pci_attach(struct gpib_board *board, const gpib_board_config_t *config); -static void cec_pci_detach(gpib_board_t *board); +static void cec_pci_detach(struct gpib_board *board); // wrappers for interface functions -int cec_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *end, size_t *bytes_read) +static int cec_read(struct gpib_board *board, uint8_t *buffer, size_t length, int *end, + size_t *bytes_read) { struct cec_priv *priv = board->private_data; return nec7210_read(board, &priv->nec7210_priv, buffer, length, end, bytes_read); } -int cec_write(gpib_board_t *board, uint8_t *buffer, size_t length, int send_eoi, - size_t *bytes_written) +static int cec_write(struct gpib_board *board, uint8_t *buffer, size_t length, int send_eoi, + size_t *bytes_written) { struct cec_priv *priv = board->private_data; return nec7210_write(board, &priv->nec7210_priv, buffer, length, send_eoi, bytes_written); } -int cec_command(gpib_board_t *board, uint8_t *buffer, size_t length, size_t *bytes_written) +static int cec_command(struct gpib_board *board, uint8_t *buffer, + size_t length, size_t *bytes_written) { struct cec_priv *priv = board->private_data; return nec7210_command(board, &priv->nec7210_priv, buffer, length, bytes_written); } -int cec_take_control(gpib_board_t *board, int synchronous) +static int cec_take_control(struct gpib_board *board, int synchronous) { struct cec_priv *priv = board->private_data; return nec7210_take_control(board, &priv->nec7210_priv, synchronous); } -int cec_go_to_standby(gpib_board_t *board) +static int cec_go_to_standby(struct gpib_board *board) { struct cec_priv *priv = board->private_data; return nec7210_go_to_standby(board, &priv->nec7210_priv); } -void cec_request_system_control(gpib_board_t *board, int request_control) +static void cec_request_system_control(struct gpib_board *board, int request_control) { struct cec_priv *priv = board->private_data; nec7210_request_system_control(board, &priv->nec7210_priv, request_control); } -void cec_interface_clear(gpib_board_t *board, int assert) +static void cec_interface_clear(struct gpib_board *board, int assert) { struct cec_priv *priv = board->private_data; nec7210_interface_clear(board, &priv->nec7210_priv, assert); } -void cec_remote_enable(gpib_board_t *board, int enable) +static void cec_remote_enable(struct gpib_board *board, int enable) { struct cec_priv *priv = board->private_data; nec7210_remote_enable(board, &priv->nec7210_priv, enable); } -int cec_enable_eos(gpib_board_t *board, uint8_t eos_byte, int compare_8_bits) +static int cec_enable_eos(struct gpib_board *board, uint8_t eos_byte, int compare_8_bits) { struct cec_priv *priv = board->private_data; return nec7210_enable_eos(board, &priv->nec7210_priv, eos_byte, compare_8_bits); } -void cec_disable_eos(gpib_board_t *board) +static void cec_disable_eos(struct gpib_board *board) { struct cec_priv *priv = board->private_data; nec7210_disable_eos(board, &priv->nec7210_priv); } -unsigned int cec_update_status(gpib_board_t *board, unsigned int clear_mask) +static unsigned int cec_update_status(struct gpib_board *board, unsigned int clear_mask) { struct cec_priv *priv = board->private_data; return nec7210_update_status(board, &priv->nec7210_priv, clear_mask); } -int cec_primary_address(gpib_board_t *board, unsigned int address) +static int cec_primary_address(struct gpib_board *board, unsigned int address) { struct cec_priv *priv = board->private_data; return nec7210_primary_address(board, &priv->nec7210_priv, address); } -int cec_secondary_address(gpib_board_t *board, unsigned int address, int enable) +static int cec_secondary_address(struct gpib_board *board, unsigned int address, int enable) { struct cec_priv *priv = board->private_data; return nec7210_secondary_address(board, &priv->nec7210_priv, address, enable); } -int cec_parallel_poll(gpib_board_t *board, uint8_t *result) +static int cec_parallel_poll(struct gpib_board *board, uint8_t *result) { struct cec_priv *priv = board->private_data; return nec7210_parallel_poll(board, &priv->nec7210_priv, result); } -void cec_parallel_poll_configure(gpib_board_t *board, uint8_t config) +static void cec_parallel_poll_configure(struct gpib_board *board, uint8_t config) { struct cec_priv *priv = board->private_data; nec7210_parallel_poll_configure(board, &priv->nec7210_priv, config); } -void cec_parallel_poll_response(gpib_board_t *board, int ist) +static void cec_parallel_poll_response(struct gpib_board *board, int ist) { struct cec_priv *priv = board->private_data; nec7210_parallel_poll_response(board, &priv->nec7210_priv, ist); } -void cec_serial_poll_response(gpib_board_t *board, uint8_t status) +static void cec_serial_poll_response(struct gpib_board *board, uint8_t status) { struct cec_priv *priv = board->private_data; nec7210_serial_poll_response(board, &priv->nec7210_priv, status); } -static uint8_t cec_serial_poll_status(gpib_board_t *board) +static uint8_t cec_serial_poll_status(struct gpib_board *board) { struct cec_priv *priv = board->private_data; return nec7210_serial_poll_status(board, &priv->nec7210_priv); } -static unsigned int cec_t1_delay(gpib_board_t *board, unsigned int nano_sec) +static int cec_t1_delay(struct gpib_board *board, unsigned int nano_sec) { struct cec_priv *priv = board->private_data; return nec7210_t1_delay(board, &priv->nec7210_priv, nano_sec); } -void cec_return_to_local(gpib_board_t *board) +static void cec_return_to_local(struct gpib_board *board) { struct cec_priv *priv = board->private_data; @@ -210,7 +216,7 @@ static gpib_interface_t cec_pci_interface = { .return_to_local = cec_return_to_local, }; -static int cec_allocate_private(gpib_board_t *board) +static int cec_allocate_private(struct gpib_board *board) { struct cec_priv *priv; @@ -223,13 +229,13 @@ static int cec_allocate_private(gpib_board_t *board) return 0; } -void cec_free_private(gpib_board_t *board) +static void cec_free_private(struct gpib_board *board) { kfree(board->private_data); board->private_data = NULL; } -int cec_generic_attach(gpib_board_t *board) +static int cec_generic_attach(struct gpib_board *board) { struct cec_priv *cec_priv; struct nec7210_priv *nec_priv; @@ -247,7 +253,7 @@ int cec_generic_attach(gpib_board_t *board) return 0; } -void cec_init(struct cec_priv *cec_priv, const gpib_board_t *board) +static void cec_init(struct cec_priv *cec_priv, const struct gpib_board *board) { struct nec7210_priv *nec_priv = &cec_priv->nec7210_priv; @@ -259,7 +265,7 @@ void cec_init(struct cec_priv *cec_priv, const gpib_board_t *board) nec7210_board_online(nec_priv, board); } -int cec_pci_attach(gpib_board_t *board, const gpib_board_config_t *config) +static int cec_pci_attach(struct gpib_board *board, const gpib_board_config_t *config) { struct cec_priv *cec_priv; struct nec7210_priv *nec_priv; @@ -283,31 +289,29 @@ int cec_pci_attach(gpib_board_t *board, const gpib_board_config_t *config) break; } if (!cec_priv->pci_device) { - pr_err("gpib: no cec PCI board found\n"); - return -1; + dev_err(board->gpib_dev, "no cec PCI board found\n"); + return -ENODEV; } if (pci_enable_device(cec_priv->pci_device)) { - pr_err("error enabling pci device\n"); - return -1; + dev_err(board->gpib_dev, "error enabling pci device\n"); + return -EIO; } if (pci_request_regions(cec_priv->pci_device, "cec-gpib")) - return -1; + return -EBUSY; cec_priv->plx_iobase = pci_resource_start(cec_priv->pci_device, 1); - pr_info(" plx9050 base address 0x%lx\n", cec_priv->plx_iobase); - nec_priv->iobase = pci_resource_start(cec_priv->pci_device, 3); - pr_info(" nec7210 base address 0x%x\n", nec_priv->iobase); + nec_priv->iobase = pci_resource_start(cec_priv->pci_device, 3); isr_flags |= IRQF_SHARED; - if (request_irq(cec_priv->pci_device->irq, cec_interrupt, isr_flags, "pci-gpib", board)) { - pr_err("gpib: can't request IRQ %d\n", cec_priv->pci_device->irq); - return -1; + if (request_irq(cec_priv->pci_device->irq, cec_interrupt, isr_flags, DRV_NAME, board)) { + dev_err(board->gpib_dev, "failed to obtain IRQ %d\n", cec_priv->pci_device->irq); + return -EBUSY; } cec_priv->irq = cec_priv->pci_device->irq; if (gpib_request_pseudo_irq(board, cec_interrupt)) { - pr_err("cec: failed to allocate pseudo irq\n"); + dev_err(board->gpib_dev, "failed to allocate pseudo irq\n"); return -1; } cec_init(cec_priv, board); @@ -319,7 +323,7 @@ int cec_pci_attach(gpib_board_t *board, const gpib_board_config_t *config) return 0; } -void cec_pci_detach(gpib_board_t *board) +static void cec_pci_detach(struct gpib_board *board) { struct cec_priv *cec_priv = board->private_data; struct nec7210_priv *nec_priv; @@ -354,7 +358,7 @@ static const struct pci_device_id cec_pci_table[] = { MODULE_DEVICE_TABLE(pci, cec_pci_table); static struct pci_driver cec_pci_driver = { - .name = "cec_gpib", + .name = DRV_NAME, .id_table = cec_pci_table, .probe = &cec_pci_probe }; @@ -365,13 +369,13 @@ static int __init cec_init_module(void) result = pci_register_driver(&cec_pci_driver); if (result) { - pr_err("cec_gpib: pci_register_driver failed: error = %d\n", result); + pr_err("pci_register_driver failed: error = %d\n", result); return result; } result = gpib_register_driver(&cec_pci_interface, THIS_MODULE); if (result) { - pr_err("cec_gpib: gpib_register_driver failed: error = %d\n", result); + pr_err("gpib_register_driver failed: error = %d\n", result); return result; }
diff --git a/drivers/staging/gpib/common/gpib_os.c b/drivers/staging/gpib/common/gpib_os.c index 4901e66..8456b97 100644 --- a/drivers/staging/gpib/common/gpib_os.c +++ b/drivers/staging/gpib/common/gpib_os.c
@@ -5,6 +5,9 @@ *************************************************************************** */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#define dev_fmt pr_fmt + #include "ibsys.h" #include <linux/module.h> #include <linux/wait.h> @@ -23,53 +26,53 @@ MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("GPIB base support"); MODULE_ALIAS_CHARDEV_MAJOR(GPIB_CODE); -static int board_type_ioctl(gpib_file_private_t *file_priv, gpib_board_t *board, unsigned long arg); -static int read_ioctl(gpib_file_private_t *file_priv, gpib_board_t *board, +static int board_type_ioctl(gpib_file_private_t *file_priv, struct gpib_board *board, unsigned long arg); +static int read_ioctl(gpib_file_private_t *file_priv, struct gpib_board *board, unsigned long arg); -static int write_ioctl(gpib_file_private_t *file_priv, gpib_board_t *board, +static int write_ioctl(gpib_file_private_t *file_priv, struct gpib_board *board, unsigned long arg); -static int command_ioctl(gpib_file_private_t *file_priv, gpib_board_t *board, +static int command_ioctl(gpib_file_private_t *file_priv, struct gpib_board *board, unsigned long arg); -static int open_dev_ioctl(struct file *filep, gpib_board_t *board, unsigned long arg); -static int close_dev_ioctl(struct file *filep, gpib_board_t *board, unsigned long arg); -static int serial_poll_ioctl(gpib_board_t *board, unsigned long arg); -static int wait_ioctl(gpib_file_private_t *file_priv, gpib_board_t *board, unsigned long arg); -static int parallel_poll_ioctl(gpib_board_t *board, unsigned long arg); -static int online_ioctl(gpib_board_t *board, unsigned long arg); -static int remote_enable_ioctl(gpib_board_t *board, unsigned long arg); -static int take_control_ioctl(gpib_board_t *board, unsigned long arg); -static int line_status_ioctl(gpib_board_t *board, unsigned long arg); -static int pad_ioctl(gpib_board_t *board, gpib_file_private_t *file_priv, +static int open_dev_ioctl(struct file *filep, struct gpib_board *board, unsigned long arg); +static int close_dev_ioctl(struct file *filep, struct gpib_board *board, unsigned long arg); +static int serial_poll_ioctl(struct gpib_board *board, unsigned long arg); +static int wait_ioctl(gpib_file_private_t *file_priv, struct gpib_board *board, unsigned long arg); +static int parallel_poll_ioctl(struct gpib_board *board, unsigned long arg); +static int online_ioctl(struct gpib_board *board, unsigned long arg); +static int remote_enable_ioctl(struct gpib_board *board, unsigned long arg); +static int take_control_ioctl(struct gpib_board *board, unsigned long arg); +static int line_status_ioctl(struct gpib_board *board, unsigned long arg); +static int pad_ioctl(struct gpib_board *board, gpib_file_private_t *file_priv, unsigned long arg); -static int sad_ioctl(gpib_board_t *board, gpib_file_private_t *file_priv, +static int sad_ioctl(struct gpib_board *board, gpib_file_private_t *file_priv, unsigned long arg); -static int eos_ioctl(gpib_board_t *board, unsigned long arg); -static int request_service_ioctl(gpib_board_t *board, unsigned long arg); -static int request_service2_ioctl(gpib_board_t *board, unsigned long arg); +static int eos_ioctl(struct gpib_board *board, unsigned long arg); +static int request_service_ioctl(struct gpib_board *board, unsigned long arg); +static int request_service2_ioctl(struct gpib_board *board, unsigned long arg); static int iobase_ioctl(gpib_board_config_t *config, unsigned long arg); static int irq_ioctl(gpib_board_config_t *config, unsigned long arg); static int dma_ioctl(gpib_board_config_t *config, unsigned long arg); -static int autospoll_ioctl(gpib_board_t *board, gpib_file_private_t *file_priv, +static int autospoll_ioctl(struct gpib_board *board, gpib_file_private_t *file_priv, unsigned long arg); -static int mutex_ioctl(gpib_board_t *board, gpib_file_private_t *file_priv, +static int mutex_ioctl(struct gpib_board *board, gpib_file_private_t *file_priv, unsigned long arg); -static int timeout_ioctl(gpib_board_t *board, unsigned long arg); -static int status_bytes_ioctl(gpib_board_t *board, unsigned long arg); -static int board_info_ioctl(const gpib_board_t *board, unsigned long arg); -static int ppc_ioctl(gpib_board_t *board, unsigned long arg); -static int set_local_ppoll_mode_ioctl(gpib_board_t *board, unsigned long arg); -static int get_local_ppoll_mode_ioctl(gpib_board_t *board, unsigned long arg); -static int query_board_rsv_ioctl(gpib_board_t *board, unsigned long arg); -static int interface_clear_ioctl(gpib_board_t *board, unsigned long arg); +static int timeout_ioctl(struct gpib_board *board, unsigned long arg); +static int status_bytes_ioctl(struct gpib_board *board, unsigned long arg); +static int board_info_ioctl(const struct gpib_board *board, unsigned long arg); +static int ppc_ioctl(struct gpib_board *board, unsigned long arg); +static int set_local_ppoll_mode_ioctl(struct gpib_board *board, unsigned long arg); +static int get_local_ppoll_mode_ioctl(struct gpib_board *board, unsigned long arg); +static int query_board_rsv_ioctl(struct gpib_board *board, unsigned long arg); +static int interface_clear_ioctl(struct gpib_board *board, unsigned long arg); static int select_pci_ioctl(gpib_board_config_t *config, unsigned long arg); static int select_device_path_ioctl(gpib_board_config_t *config, unsigned long arg); -static int event_ioctl(gpib_board_t *board, unsigned long arg); -static int request_system_control_ioctl(gpib_board_t *board, unsigned long arg); -static int t1_delay_ioctl(gpib_board_t *board, unsigned long arg); +static int event_ioctl(struct gpib_board *board, unsigned long arg); +static int request_system_control_ioctl(struct gpib_board *board, unsigned long arg); +static int t1_delay_ioctl(struct gpib_board *board, unsigned long arg); -static int cleanup_open_devices(gpib_file_private_t *file_priv, gpib_board_t *board); +static int cleanup_open_devices(gpib_file_private_t *file_priv, struct gpib_board *board); -static int pop_gpib_event_nolock(gpib_board_t *board, gpib_event_queue_t *queue, short *event_type); +static int pop_gpib_event_nolock(struct gpib_board *board, gpib_event_queue_t *queue, short *event_type); /* * Timer functions @@ -79,18 +82,18 @@ static int pop_gpib_event_nolock(gpib_board_t *board, gpib_event_queue_t *queue, static void watchdog_timeout(struct timer_list *t) { - gpib_board_t *board = from_timer(board, t, timer); + struct gpib_board *board = from_timer(board, t, timer); set_bit(TIMO_NUM, &board->status); wake_up_interruptible(&board->wait); } /* install timer interrupt handler */ -void os_start_timer(gpib_board_t *board, unsigned int usec_timeout) +void os_start_timer(struct gpib_board *board, unsigned int usec_timeout) /* Starts the timeout task */ { if (timer_pending(&board->timer)) { - pr_err("gpib: bug! timer already running?\n"); + dev_err(board->gpib_dev, "bug! timer already running?\n"); return; } clear_bit(TIMO_NUM, &board->status); @@ -102,14 +105,14 @@ void os_start_timer(gpib_board_t *board, unsigned int usec_timeout) } } -void os_remove_timer(gpib_board_t *board) +void os_remove_timer(struct gpib_board *board) /* Removes the timeout task */ { if (timer_pending(&board->timer)) - del_timer_sync(&board->timer); + timer_delete_sync(&board->timer); } -int io_timed_out(gpib_board_t *board) +int io_timed_out(struct gpib_board *board) { if (test_bit(TIMO_NUM, &board->status)) return 1; @@ -137,10 +140,10 @@ static void pseudo_irq_handler(struct timer_list *t) mod_timer(&pseudo_irq->timer, jiffies + pseudo_irq_period()); } -int gpib_request_pseudo_irq(gpib_board_t *board, irqreturn_t (*handler)(int, void *)) +int gpib_request_pseudo_irq(struct gpib_board *board, irqreturn_t (*handler)(int, void *)) { if (timer_pending(&board->pseudo_irq.timer) || board->pseudo_irq.handler) { - pr_err("gpib: only one pseudo interrupt per board allowed\n"); + dev_err(board->gpib_dev, "only one pseudo interrupt per board allowed\n"); return -1; } @@ -156,11 +159,11 @@ int gpib_request_pseudo_irq(gpib_board_t *board, irqreturn_t (*handler)(int, voi } EXPORT_SYMBOL(gpib_request_pseudo_irq); -void gpib_free_pseudo_irq(gpib_board_t *board) +void gpib_free_pseudo_irq(struct gpib_board *board) { atomic_set(&board->pseudo_irq.active, 0); - del_timer_sync(&board->pseudo_irq.timer); + timer_delete_sync(&board->pseudo_irq.timer); board->pseudo_irq.handler = NULL; } EXPORT_SYMBOL(gpib_free_pseudo_irq); @@ -175,7 +178,7 @@ unsigned int num_status_bytes(const gpib_status_queue_t *dev) } // push status byte onto back of status byte fifo -int push_status_byte(gpib_board_t *board, gpib_status_queue_t *device, u8 poll_byte) +int push_status_byte(struct gpib_board *board, gpib_status_queue_t *device, u8 poll_byte) { struct list_head *head = &device->status_bytes; status_byte_t *status; @@ -209,7 +212,7 @@ int push_status_byte(gpib_board_t *board, gpib_status_queue_t *device, u8 poll_b } // pop status byte from front of status byte fifo -int pop_status_byte(gpib_board_t *board, gpib_status_queue_t *device, u8 *poll_byte) +int pop_status_byte(struct gpib_board *board, gpib_status_queue_t *device, u8 *poll_byte) { struct list_head *head = &device->status_bytes; struct list_head *front = head->next; @@ -240,7 +243,7 @@ int pop_status_byte(gpib_board_t *board, gpib_status_queue_t *device, u8 *poll_b return 0; } -gpib_status_queue_t *get_gpib_status_queue(gpib_board_t *board, unsigned int pad, int sad) +gpib_status_queue_t *get_gpib_status_queue(struct gpib_board *board, unsigned int pad, int sad) { gpib_status_queue_t *device; struct list_head *list_ptr; @@ -255,13 +258,11 @@ gpib_status_queue_t *get_gpib_status_queue(gpib_board_t *board, unsigned int pad return NULL; } -int get_serial_poll_byte(gpib_board_t *board, unsigned int pad, int sad, unsigned int usec_timeout, +int get_serial_poll_byte(struct gpib_board *board, unsigned int pad, int sad, unsigned int usec_timeout, uint8_t *poll_byte) { gpib_status_queue_t *device; - dev_dbg(board->gpib_dev, "%s:()\n", __func__); - device = get_gpib_status_queue(board, pad, sad); if (num_status_bytes(device)) return pop_status_byte(board, device, poll_byte); @@ -269,11 +270,10 @@ int get_serial_poll_byte(gpib_board_t *board, unsigned int pad, int sad, unsigne return dvrsp(board, pad, sad, usec_timeout, poll_byte); } -int autopoll_all_devices(gpib_board_t *board) +int autopoll_all_devices(struct gpib_board *board) { int retval; - dev_dbg(board->gpib_dev, "entering %s()\n", __func__); if (mutex_lock_interruptible(&board->user_mutex)) return -ERESTARTSYS; if (mutex_lock_interruptible(&board->big_gpib_mutex)) { @@ -290,7 +290,7 @@ int autopoll_all_devices(gpib_board_t *board) return retval; } - dev_dbg(board->gpib_dev, "%s complete\n", __func__); + dev_dbg(board->gpib_dev, "complete\n"); /* need to wake wait queue in case someone is * waiting on RQS */ @@ -301,15 +301,13 @@ int autopoll_all_devices(gpib_board_t *board) return retval; } -static int setup_serial_poll(gpib_board_t *board, unsigned int usec_timeout) +static int setup_serial_poll(struct gpib_board *board, unsigned int usec_timeout) { u8 cmd_string[8]; int i; size_t bytes_written; int ret; - dev_dbg(board->gpib_dev, "entering %s()\n", __func__); - os_start_timer(board, usec_timeout); ret = ibcac(board, 1, 1); if (ret < 0) { @@ -326,7 +324,7 @@ static int setup_serial_poll(gpib_board_t *board, unsigned int usec_timeout) ret = board->interface->command(board, cmd_string, i, &bytes_written); if (ret < 0 || bytes_written < i) { - pr_err("gpib: failed to setup serial poll\n"); + dev_dbg(board->gpib_dev, "failed to setup serial poll\n"); os_remove_timer(board); return -EIO; } @@ -335,7 +333,7 @@ static int setup_serial_poll(gpib_board_t *board, unsigned int usec_timeout) return 0; } -static int read_serial_poll_byte(gpib_board_t *board, unsigned int pad, +static int read_serial_poll_byte(struct gpib_board *board, unsigned int pad, int sad, unsigned int usec_timeout, uint8_t *result) { u8 cmd_string[8]; @@ -344,7 +342,7 @@ static int read_serial_poll_byte(gpib_board_t *board, unsigned int pad, int i; size_t nbytes; - dev_dbg(board->gpib_dev, "entering %s(), pad=%i sad=%i\n", __func__, pad, sad); + dev_dbg(board->gpib_dev, "entering pad=%i sad=%i\n", pad, sad); os_start_timer(board, usec_timeout); ret = ibcac(board, 1, 1); @@ -361,7 +359,7 @@ static int read_serial_poll_byte(gpib_board_t *board, unsigned int pad, ret = board->interface->command(board, cmd_string, i, &nbytes); if (ret < 0 || nbytes < i) { - pr_err("gpib: failed to setup serial poll\n"); + dev_err(board->gpib_dev, "failed to setup serial poll\n"); os_remove_timer(board); return -EIO; } @@ -371,7 +369,7 @@ static int read_serial_poll_byte(gpib_board_t *board, unsigned int pad, // read poll result ret = board->interface->read(board, result, 1, &end_flag, &nbytes); if (ret < 0 || nbytes < 1) { - pr_err("gpib: serial poll failed\n"); + dev_err(board->gpib_dev, "serial poll failed\n"); os_remove_timer(board); return -EIO; } @@ -380,14 +378,12 @@ static int read_serial_poll_byte(gpib_board_t *board, unsigned int pad, return 0; } -static int cleanup_serial_poll(gpib_board_t *board, unsigned int usec_timeout) +static int cleanup_serial_poll(struct gpib_board *board, unsigned int usec_timeout) { u8 cmd_string[8]; int ret; size_t bytes_written; - dev_dbg(board->gpib_dev, "entering %s()\n", __func__); - os_start_timer(board, usec_timeout); ret = ibcac(board, 1, 1); if (ret < 0) { @@ -399,7 +395,7 @@ static int cleanup_serial_poll(gpib_board_t *board, unsigned int usec_timeout) cmd_string[1] = UNT; ret = board->interface->command(board, cmd_string, 2, &bytes_written); if (ret < 0 || bytes_written < 2) { - pr_err("gpib: failed to disable serial poll\n"); + dev_err(board->gpib_dev, "failed to disable serial poll\n"); os_remove_timer(board); return -EIO; } @@ -408,7 +404,7 @@ static int cleanup_serial_poll(gpib_board_t *board, unsigned int usec_timeout) return 0; } -static int serial_poll_single(gpib_board_t *board, unsigned int pad, int sad, +static int serial_poll_single(struct gpib_board *board, unsigned int pad, int sad, unsigned int usec_timeout, uint8_t *result) { int retval, cleanup_retval; @@ -426,7 +422,7 @@ static int serial_poll_single(gpib_board_t *board, unsigned int pad, int sad, return 0; } -int serial_poll_all(gpib_board_t *board, unsigned int usec_timeout) +int serial_poll_all(struct gpib_board *board, unsigned int usec_timeout) { int retval = 0; struct list_head *cur; @@ -435,8 +431,6 @@ int serial_poll_all(gpib_board_t *board, unsigned int usec_timeout) u8 result; unsigned int num_bytes = 0; - dev_dbg(board->gpib_dev, "entering %s()\n", __func__); - head = &board->device_list; if (head->next == head) return 0; @@ -475,19 +469,19 @@ int serial_poll_all(gpib_board_t *board, unsigned int usec_timeout) * SPD and UNT are sent at the completion of the poll. */ -int dvrsp(gpib_board_t *board, unsigned int pad, int sad, +int dvrsp(struct gpib_board *board, unsigned int pad, int sad, unsigned int usec_timeout, uint8_t *result) { int status = ibstatus(board); int retval; if ((status & CIC) == 0) { - pr_err("gpib: not CIC during serial poll\n"); + dev_err(board->gpib_dev, "not CIC during serial poll\n"); return -1; } if (pad > MAX_GPIB_PRIMARY_ADDRESS || sad > MAX_GPIB_SECONDARY_ADDRESS || sad < -1) { - pr_err("gpib: bad address for serial poll"); + dev_err(board->gpib_dev, "bad address for serial poll"); return -1; } @@ -527,7 +521,7 @@ static int init_gpib_file_private(gpib_file_private_t *priv) int ibopen(struct inode *inode, struct file *filep) { unsigned int minor = iminor(inode); - gpib_board_t *board; + struct gpib_board *board; gpib_file_private_t *priv; if (minor >= GPIB_MAX_NUM_BOARDS) { @@ -544,20 +538,16 @@ int ibopen(struct inode *inode, struct file *filep) priv = filep->private_data; init_gpib_file_private((gpib_file_private_t *)filep->private_data); - dev_dbg(board->gpib_dev, "pid %i, gpib: opening minor %d\n", current->pid, minor); - if (board->use_count == 0) { int retval; retval = request_module("gpib%i", minor); - if (retval) { - dev_dbg(board->gpib_dev, "pid %i, gpib: request module returned %i\n", - current->pid, retval); - } + if (retval) + dev_dbg(board->gpib_dev, "request module returned %i\n", retval); } if (board->interface) { if (!try_module_get(board->provider_module)) { - pr_err("gpib: try_module_get() failed\n"); + dev_err(board->gpib_dev, "try_module_get() failed\n"); return -EIO; } board->use_count++; @@ -569,7 +559,7 @@ int ibopen(struct inode *inode, struct file *filep) int ibclose(struct inode *inode, struct file *filep) { unsigned int minor = iminor(inode); - gpib_board_t *board; + struct gpib_board *board; gpib_file_private_t *priv = filep->private_data; gpib_descriptor_t *desc; @@ -580,21 +570,19 @@ int ibclose(struct inode *inode, struct file *filep) board = &board_array[minor]; - dev_dbg(board->gpib_dev, "pid %i, closing minor %d\n", current->pid, minor); - if (priv) { desc = handle_to_descriptor(priv, 0); if (desc) { if (desc->autopoll_enabled) { - dev_dbg(board->gpib_dev, "pid %i, decrementing autospollers\n", - current->pid); + dev_dbg(board->gpib_dev, "decrementing autospollers\n"); if (board->autospollers > 0) board->autospollers--; else - pr_err("gpib: Attempt to decrement zero autospollers\n"); + dev_err(board->gpib_dev, + "Attempt to decrement zero autospollers\n"); } } else { - pr_err("gpib: Unexpected null gpib_descriptor\n"); + dev_err(board->gpib_dev, "Unexpected null gpib_descriptor\n"); } cleanup_open_devices(priv, board); @@ -617,7 +605,7 @@ int ibclose(struct inode *inode, struct file *filep) long ibioctl(struct file *filep, unsigned int cmd, unsigned long arg) { unsigned int minor = iminor(filep->f_path.dentry->d_inode); - gpib_board_t *board; + struct gpib_board *board; gpib_file_private_t *file_priv = filep->private_data; long retval = -ENOTTY; @@ -630,8 +618,8 @@ long ibioctl(struct file *filep, unsigned int cmd, unsigned long arg) if (mutex_lock_interruptible(&board->big_gpib_mutex)) return -ERESTARTSYS; - dev_dbg(board->gpib_dev, "pid %i, ioctl %d, interface=%s, use=%d, onl=%d\n", - current->pid, cmd & 0xff, + dev_dbg(board->gpib_dev, "ioctl %d, interface=%s, use=%d, onl=%d\n", + cmd & 0xff, board->interface ? board->interface->name : "", board->use_count, board->online); @@ -647,13 +635,13 @@ long ibioctl(struct file *filep, unsigned int cmd, unsigned long arg) break; } if (!board->interface) { - pr_err("gpib: no gpib board configured on /dev/gpib%i\n", minor); + dev_err(board->gpib_dev, "no gpib board configured\n"); retval = -ENODEV; goto done; } if (file_priv->got_module == 0) { if (!try_module_get(board->provider_module)) { - pr_err("gpib: try_module_get() failed\n"); + dev_err(board->gpib_dev, "try_module_get() failed\n"); retval = -EIO; goto done; } @@ -699,8 +687,6 @@ long ibioctl(struct file *filep, unsigned int cmd, unsigned long arg) } if (!board->online) { - pr_err("gpib: ioctl %i invalid for offline board\n", - cmd & 0xff); retval = -EINVAL; goto done; } @@ -737,8 +723,6 @@ long ibioctl(struct file *filep, unsigned int cmd, unsigned long arg) spin_lock(&board->locking_pid_spinlock); if (current->pid != board->locking_pid) { spin_unlock(&board->locking_pid_spinlock); - pr_err("gpib: need to hold board lock to perform ioctl %i\n", - cmd & 0xff); retval = -EPERM; goto done; } @@ -822,7 +806,7 @@ long ibioctl(struct file *filep, unsigned int cmd, unsigned long arg) return retval; } -static int board_type_ioctl(gpib_file_private_t *file_priv, gpib_board_t *board, unsigned long arg) +static int board_type_ioctl(gpib_file_private_t *file_priv, struct gpib_board *board, unsigned long arg) { struct list_head *list_ptr; board_type_ioctl_t cmd; @@ -830,10 +814,8 @@ static int board_type_ioctl(gpib_file_private_t *file_priv, gpib_board_t *board, if (!capable(CAP_SYS_ADMIN)) return -EPERM; - if (board->online) { - pr_err("gpib: can't change board type while board is online.\n"); + if (board->online) return -EBUSY; - } retval = copy_from_user(&cmd, (void __user *)arg, sizeof(board_type_ioctl_t)); if (retval) @@ -875,7 +857,7 @@ static int board_type_ioctl(gpib_file_private_t *file_priv, gpib_board_t *board, return -EINVAL; } -static int read_ioctl(gpib_file_private_t *file_priv, gpib_board_t *board, +static int read_ioctl(gpib_file_private_t *file_priv, struct gpib_board *board, unsigned long arg) { read_write_ioctl_t read_cmd; @@ -951,7 +933,7 @@ static int read_ioctl(gpib_file_private_t *file_priv, gpib_board_t *board, } static int command_ioctl(gpib_file_private_t *file_priv, - gpib_board_t *board, unsigned long arg) + struct gpib_board *board, unsigned long arg) { read_write_ioctl_t cmd; u8 __user *userbuf; @@ -1034,7 +1016,7 @@ static int command_ioctl(gpib_file_private_t *file_priv, return retval; } -static int write_ioctl(gpib_file_private_t *file_priv, gpib_board_t *board, +static int write_ioctl(gpib_file_private_t *file_priv, struct gpib_board *board, unsigned long arg) { read_write_ioctl_t write_cmd; @@ -1105,7 +1087,7 @@ static int write_ioctl(gpib_file_private_t *file_priv, gpib_board_t *board, return retval; } -static int status_bytes_ioctl(gpib_board_t *board, unsigned long arg) +static int status_bytes_ioctl(struct gpib_board *board, unsigned long arg) { gpib_status_queue_t *device; spoll_bytes_ioctl_t cmd; @@ -1128,7 +1110,7 @@ static int status_bytes_ioctl(gpib_board_t *board, unsigned long arg) return 0; } -static int increment_open_device_count(gpib_board_t *board, struct list_head *head, +static int increment_open_device_count(struct gpib_board *board, struct list_head *head, unsigned int pad, int sad) { struct list_head *list_ptr; @@ -1140,8 +1122,8 @@ static int increment_open_device_count(gpib_board_t *board, struct list_head *he for (list_ptr = head->next; list_ptr != head; list_ptr = list_ptr->next) { device = list_entry(list_ptr, gpib_status_queue_t, list); if (gpib_address_equal(device->pad, device->sad, pad, sad)) { - dev_dbg(board->gpib_dev, "pid %i, incrementing open count for pad %i, sad %i\n", - current->pid, device->pad, device->sad); + dev_dbg(board->gpib_dev, "incrementing open count for pad %i, sad %i\n", + device->pad, device->sad); device->reference_count++; return 0; } @@ -1158,13 +1140,12 @@ static int increment_open_device_count(gpib_board_t *board, struct list_head *he list_add(&device->list, head); - dev_dbg(board->gpib_dev, "pid %i, opened pad %i, sad %i\n", - current->pid, device->pad, device->sad); + dev_dbg(board->gpib_dev, "opened pad %i, sad %i\n", device->pad, device->sad); return 0; } -static int subtract_open_device_count(gpib_board_t *board, struct list_head *head, +static int subtract_open_device_count(struct gpib_board *board, struct list_head *head, unsigned int pad, int sad, unsigned int count) { gpib_status_queue_t *device; @@ -1173,33 +1154,33 @@ static int subtract_open_device_count(gpib_board_t *board, struct list_head *hea for (list_ptr = head->next; list_ptr != head; list_ptr = list_ptr->next) { device = list_entry(list_ptr, gpib_status_queue_t, list); if (gpib_address_equal(device->pad, device->sad, pad, sad)) { - dev_dbg(board->gpib_dev, "pid %i, decrementing open count for pad %i, sad %i\n", - current->pid, device->pad, device->sad); + dev_dbg(board->gpib_dev, "decrementing open count for pad %i, sad %i\n", + device->pad, device->sad); if (count > device->reference_count) { - pr_err("gpib: bug! in %s()\n", __func__); + dev_err(board->gpib_dev, "bug! in %s()\n", __func__); return -EINVAL; } device->reference_count -= count; if (device->reference_count == 0) { - dev_dbg(board->gpib_dev, "pid %i, closing pad %i, sad %i\n", - current->pid, device->pad, device->sad); + dev_dbg(board->gpib_dev, "closing pad %i, sad %i\n", + device->pad, device->sad); list_del(list_ptr); kfree(device); } return 0; } } - pr_err("gpib: bug! tried to close address that was never opened!\n"); + dev_err(board->gpib_dev, "bug! tried to close address that was never opened!\n"); return -EINVAL; } -static inline int decrement_open_device_count(gpib_board_t *board, struct list_head *head, +static inline int decrement_open_device_count(struct gpib_board *board, struct list_head *head, unsigned int pad, int sad) { return subtract_open_device_count(board, head, pad, sad, 1); } -static int cleanup_open_devices(gpib_file_private_t *file_priv, gpib_board_t *board) +static int cleanup_open_devices(gpib_file_private_t *file_priv, struct gpib_board *board) { int retval = 0; int i; @@ -1224,7 +1205,7 @@ static int cleanup_open_devices(gpib_file_private_t *file_priv, gpib_board_t *bo return 0; } -static int open_dev_ioctl(struct file *filep, gpib_board_t *board, unsigned long arg) +static int open_dev_ioctl(struct file *filep, struct gpib_board *board, unsigned long arg) { open_dev_ioctl_t open_dev_cmd; int retval; @@ -1274,7 +1255,7 @@ static int open_dev_ioctl(struct file *filep, gpib_board_t *board, unsigned long return 0; } -static int close_dev_ioctl(struct file *filep, gpib_board_t *board, unsigned long arg) +static int close_dev_ioctl(struct file *filep, struct gpib_board *board, unsigned long arg) { close_dev_ioctl_t cmd; gpib_file_private_t *file_priv = filep->private_data; @@ -1301,13 +1282,11 @@ static int close_dev_ioctl(struct file *filep, gpib_board_t *board, unsigned lon return 0; } -static int serial_poll_ioctl(gpib_board_t *board, unsigned long arg) +static int serial_poll_ioctl(struct gpib_board *board, unsigned long arg) { serial_poll_ioctl_t serial_cmd; int retval; - dev_dbg(board->gpib_dev, "pid %i, entering %s()\n", current->pid, __func__); - retval = copy_from_user(&serial_cmd, (void __user *)arg, sizeof(serial_cmd)); if (retval) return -EFAULT; @@ -1324,7 +1303,7 @@ static int serial_poll_ioctl(gpib_board_t *board, unsigned long arg) return 0; } -static int wait_ioctl(gpib_file_private_t *file_priv, gpib_board_t *board, +static int wait_ioctl(gpib_file_private_t *file_priv, struct gpib_board *board, unsigned long arg) { wait_ioctl_t wait_cmd; @@ -1351,7 +1330,7 @@ static int wait_ioctl(gpib_file_private_t *file_priv, gpib_board_t *board, return 0; } -static int parallel_poll_ioctl(gpib_board_t *board, unsigned long arg) +static int parallel_poll_ioctl(struct gpib_board *board, unsigned long arg) { u8 poll_byte; int retval; @@ -1367,7 +1346,7 @@ static int parallel_poll_ioctl(gpib_board_t *board, unsigned long arg) return 0; } -static int online_ioctl(gpib_board_t *board, unsigned long arg) +static int online_ioctl(struct gpib_board *board, unsigned long arg) { online_ioctl_t online_cmd; int retval; @@ -1411,7 +1390,7 @@ static int online_ioctl(gpib_board_t *board, unsigned long arg) return retval; } -static int remote_enable_ioctl(gpib_board_t *board, unsigned long arg) +static int remote_enable_ioctl(struct gpib_board *board, unsigned long arg) { int enable; int retval; @@ -1423,7 +1402,7 @@ static int remote_enable_ioctl(gpib_board_t *board, unsigned long arg) return ibsre(board, enable); } -static int take_control_ioctl(gpib_board_t *board, unsigned long arg) +static int take_control_ioctl(struct gpib_board *board, unsigned long arg) { int synchronous; int retval; @@ -1435,7 +1414,7 @@ static int take_control_ioctl(gpib_board_t *board, unsigned long arg) return ibcac(board, synchronous, 1); } -static int line_status_ioctl(gpib_board_t *board, unsigned long arg) +static int line_status_ioctl(struct gpib_board *board, unsigned long arg) { short lines; int retval; @@ -1451,7 +1430,7 @@ static int line_status_ioctl(gpib_board_t *board, unsigned long arg) return 0; } -static int pad_ioctl(gpib_board_t *board, gpib_file_private_t *file_priv, +static int pad_ioctl(struct gpib_board *board, gpib_file_private_t *file_priv, unsigned long arg) { pad_ioctl_t cmd; @@ -1487,7 +1466,7 @@ static int pad_ioctl(gpib_board_t *board, gpib_file_private_t *file_priv, return 0; } -static int sad_ioctl(gpib_board_t *board, gpib_file_private_t *file_priv, +static int sad_ioctl(struct gpib_board *board, gpib_file_private_t *file_priv, unsigned long arg) { sad_ioctl_t cmd; @@ -1522,7 +1501,7 @@ static int sad_ioctl(gpib_board_t *board, gpib_file_private_t *file_priv, return 0; } -static int eos_ioctl(gpib_board_t *board, unsigned long arg) +static int eos_ioctl(struct gpib_board *board, unsigned long arg) { eos_ioctl_t eos_cmd; int retval; @@ -1534,7 +1513,7 @@ static int eos_ioctl(gpib_board_t *board, unsigned long arg) return ibeos(board, eos_cmd.eos, eos_cmd.eos_flags); } -static int request_service_ioctl(gpib_board_t *board, unsigned long arg) +static int request_service_ioctl(struct gpib_board *board, unsigned long arg) { u8 status_byte; int retval; @@ -1546,7 +1525,7 @@ static int request_service_ioctl(gpib_board_t *board, unsigned long arg) return ibrsv2(board, status_byte, status_byte & request_service_bit); } -static int request_service2_ioctl(gpib_board_t *board, unsigned long arg) +static int request_service2_ioctl(struct gpib_board *board, unsigned long arg) { request_service2_t request_service2_cmd; int retval; @@ -1613,7 +1592,7 @@ static int dma_ioctl(gpib_board_config_t *config, unsigned long arg) return 0; } -static int autospoll_ioctl(gpib_board_t *board, gpib_file_private_t *file_priv, +static int autospoll_ioctl(struct gpib_board *board, gpib_file_private_t *file_priv, unsigned long arg) { autospoll_ioctl_t enable; @@ -1639,18 +1618,19 @@ static int autospoll_ioctl(gpib_board_t *board, gpib_file_private_t *file_priv, board->autospollers--; retval = 0; } else { - pr_err("gpib: tried to set number of autospollers negative\n"); + dev_err(board->gpib_dev, + "tried to set number of autospollers negative\n"); retval = -EINVAL; } } else { - pr_err("gpib: autopoll disable requested before enable\n"); + dev_err(board->gpib_dev, "autopoll disable requested before enable\n"); retval = -EINVAL; } } return retval; } -static int mutex_ioctl(gpib_board_t *board, gpib_file_private_t *file_priv, +static int mutex_ioctl(struct gpib_board *board, gpib_file_private_t *file_priv, unsigned long arg) { int retval, lock_mutex; @@ -1661,10 +1641,8 @@ static int mutex_ioctl(gpib_board_t *board, gpib_file_private_t *file_priv, if (lock_mutex) { retval = mutex_lock_interruptible(&board->user_mutex); - if (retval) { - pr_warn("gpib: ioctl interrupted while waiting on lock\n"); + if (retval) return -ERESTARTSYS; - } spin_lock(&board->locking_pid_spinlock); board->locking_pid = current->pid; @@ -1672,13 +1650,12 @@ static int mutex_ioctl(gpib_board_t *board, gpib_file_private_t *file_priv, atomic_set(&file_priv->holding_mutex, 1); - dev_dbg(board->gpib_dev, "pid %i, locked board %d mutex\n", - current->pid, board->minor); + dev_dbg(board->gpib_dev, "locked board mutex\n"); } else { spin_lock(&board->locking_pid_spinlock); if (current->pid != board->locking_pid) { - pr_err("gpib: bug! pid %i tried to release mutex held by pid %i\n", - current->pid, board->locking_pid); + dev_err(board->gpib_dev, "bug! pid %i tried to release mutex held by pid %i\n", + current->pid, board->locking_pid); spin_unlock(&board->locking_pid_spinlock); return -EPERM; } @@ -1688,13 +1665,12 @@ static int mutex_ioctl(gpib_board_t *board, gpib_file_private_t *file_priv, atomic_set(&file_priv->holding_mutex, 0); mutex_unlock(&board->user_mutex); - dev_dbg(board->gpib_dev, "pid %i, unlocked board %i mutex\n", - current->pid, board->minor); + dev_dbg(board->gpib_dev, "unlocked board mutex\n"); } return 0; } -static int timeout_ioctl(gpib_board_t *board, unsigned long arg) +static int timeout_ioctl(struct gpib_board *board, unsigned long arg) { unsigned int timeout; int retval; @@ -1704,12 +1680,12 @@ static int timeout_ioctl(gpib_board_t *board, unsigned long arg) return -EFAULT; board->usec_timeout = timeout; - dev_dbg(board->gpib_dev, "pid %i, timeout set to %i usec\n", current->pid, timeout); + dev_dbg(board->gpib_dev, "timeout set to %i usec\n", timeout); return 0; } -static int ppc_ioctl(gpib_board_t *board, unsigned long arg) +static int ppc_ioctl(struct gpib_board *board, unsigned long arg) { ppoll_config_ioctl_t cmd; int retval; @@ -1735,7 +1711,7 @@ static int ppc_ioctl(gpib_board_t *board, unsigned long arg) return 0; } -static int set_local_ppoll_mode_ioctl(gpib_board_t *board, unsigned long arg) +static int set_local_ppoll_mode_ioctl(struct gpib_board *board, unsigned long arg) { local_ppoll_mode_ioctl_t cmd; int retval; @@ -1744,17 +1720,15 @@ static int set_local_ppoll_mode_ioctl(gpib_board_t *board, unsigned long arg) if (retval) return -EFAULT; - if (!board->interface->local_parallel_poll_mode) { - pr_warn("gpib: local/remote parallel poll mode not supported by driver."); - return -EIO; - } + if (!board->interface->local_parallel_poll_mode) + return -ENOENT; board->local_ppoll_mode = cmd != 0; board->interface->local_parallel_poll_mode(board, board->local_ppoll_mode); return 0; } -static int get_local_ppoll_mode_ioctl(gpib_board_t *board, unsigned long arg) +static int get_local_ppoll_mode_ioctl(struct gpib_board *board, unsigned long arg) { local_ppoll_mode_ioctl_t cmd; int retval; @@ -1767,7 +1741,7 @@ static int get_local_ppoll_mode_ioctl(gpib_board_t *board, unsigned long arg) return 0; } -static int query_board_rsv_ioctl(gpib_board_t *board, unsigned long arg) +static int query_board_rsv_ioctl(struct gpib_board *board, unsigned long arg) { int status; int retval; @@ -1781,7 +1755,7 @@ static int query_board_rsv_ioctl(gpib_board_t *board, unsigned long arg) return 0; } -static int board_info_ioctl(const gpib_board_t *board, unsigned long arg) +static int board_info_ioctl(const struct gpib_board *board, unsigned long arg) { board_info_ioctl_t info; int retval; @@ -1804,7 +1778,7 @@ static int board_info_ioctl(const gpib_board_t *board, unsigned long arg) return 0; } -static int interface_clear_ioctl(gpib_board_t *board, unsigned long arg) +static int interface_clear_ioctl(struct gpib_board *board, unsigned long arg) { unsigned int usec_duration; int retval; @@ -1867,7 +1841,7 @@ unsigned int num_gpib_events(const gpib_event_queue_t *queue) return queue->num_events; } -static int push_gpib_event_nolock(gpib_board_t *board, short event_type) +static int push_gpib_event_nolock(struct gpib_board *board, short event_type) { gpib_event_queue_t *queue = &board->event_queue; struct list_head *head = &queue->event_head; @@ -1887,7 +1861,7 @@ static int push_gpib_event_nolock(gpib_board_t *board, short event_type) event = kmalloc(sizeof(gpib_event_t), GFP_ATOMIC); if (!event) { queue->dropped_event = 1; - pr_err("gpib: failed to allocate memory for event\n"); + dev_err(board->gpib_dev, "failed to allocate memory for event\n"); return -ENOMEM; } @@ -1905,7 +1879,7 @@ static int push_gpib_event_nolock(gpib_board_t *board, short event_type) } // push event onto back of event queue -int push_gpib_event(gpib_board_t *board, short event_type) +int push_gpib_event(struct gpib_board *board, short event_type) { unsigned long flags; int retval; @@ -1923,7 +1897,7 @@ int push_gpib_event(gpib_board_t *board, short event_type) } EXPORT_SYMBOL(push_gpib_event); -static int pop_gpib_event_nolock(gpib_board_t *board, gpib_event_queue_t *queue, short *event_type) +static int pop_gpib_event_nolock(struct gpib_board *board, gpib_event_queue_t *queue, short *event_type) { struct list_head *head = &queue->event_head; struct list_head *front = head->next; @@ -1957,7 +1931,7 @@ static int pop_gpib_event_nolock(gpib_board_t *board, gpib_event_queue_t *queue, } // pop event from front of event queue -int pop_gpib_event(gpib_board_t *board, gpib_event_queue_t *queue, short *event_type) +int pop_gpib_event(struct gpib_board *board, gpib_event_queue_t *queue, short *event_type) { unsigned long flags; int retval; @@ -1968,7 +1942,7 @@ int pop_gpib_event(gpib_board_t *board, gpib_event_queue_t *queue, short *event_ return retval; } -static int event_ioctl(gpib_board_t *board, unsigned long arg) +static int event_ioctl(struct gpib_board *board, unsigned long arg) { event_ioctl_t user_event; int retval; @@ -1987,7 +1961,7 @@ static int event_ioctl(gpib_board_t *board, unsigned long arg) return 0; } -static int request_system_control_ioctl(gpib_board_t *board, unsigned long arg) +static int request_system_control_ioctl(struct gpib_board *board, unsigned long arg) { rsc_ioctl_t request_control; int retval; @@ -2001,16 +1975,14 @@ static int request_system_control_ioctl(gpib_board_t *board, unsigned long arg) return 0; } -static int t1_delay_ioctl(gpib_board_t *board, unsigned long arg) +static int t1_delay_ioctl(struct gpib_board *board, unsigned long arg) { t1_delay_ioctl_t cmd; unsigned int delay; int retval; - if (!board->interface->t1_delay) { - pr_warn("gpib: t1 delay not implemented in driver!\n"); - return -EIO; - } + if (!board->interface->t1_delay) + return -ENOENT; retval = copy_from_user(&cmd, (void __user *)arg, sizeof(cmd)); if (retval) @@ -2018,8 +1990,11 @@ static int t1_delay_ioctl(gpib_board_t *board, unsigned long arg) delay = cmd; - board->t1_nano_sec = board->interface->t1_delay(board, delay); + retval = board->interface->t1_delay(board, delay); + if (retval < 0) + return retval; + board->t1_nano_sec = retval; return 0; } @@ -2032,7 +2007,7 @@ static const struct file_operations ib_fops = { .release = &ibclose, }; -gpib_board_t board_array[GPIB_MAX_NUM_BOARDS]; +struct gpib_board board_array[GPIB_MAX_NUM_BOARDS]; LIST_HEAD(registered_drivers); @@ -2067,7 +2042,7 @@ void gpib_unregister_driver(gpib_interface_t *interface) struct list_head *list_ptr; for (i = 0; i < GPIB_MAX_NUM_BOARDS; i++) { - gpib_board_t *board = &board_array[i]; + struct gpib_board *board = &board_array[i]; if (board->interface == interface) { if (board->use_count > 0) @@ -2087,7 +2062,6 @@ void gpib_unregister_driver(gpib_interface_t *interface) kfree(entry); } } - pr_info("gpib: unregistered %s interface\n", interface->name); } EXPORT_SYMBOL(gpib_unregister_driver); @@ -2098,7 +2072,7 @@ static void init_gpib_board_config(gpib_board_config_t *config) config->pci_slot = -1; } -void init_gpib_board(gpib_board_t *board) +void init_gpib_board(struct gpib_board *board) { board->interface = NULL; board->provider_module = NULL; @@ -2133,7 +2107,7 @@ void init_gpib_board(gpib_board_t *board) board->local_ppoll_mode = 0; } -int gpib_allocate_board(gpib_board_t *board) +int gpib_allocate_board(struct gpib_board *board) { if (!board->buffer) { board->buffer_length = 0x4000; @@ -2146,7 +2120,7 @@ int gpib_allocate_board(gpib_board_t *board) return 0; } -void gpib_deallocate_board(gpib_board_t *board) +void gpib_deallocate_board(struct gpib_board *board) { short dummy; @@ -2159,7 +2133,7 @@ void gpib_deallocate_board(gpib_board_t *board) pop_gpib_event(board, &board->event_queue, &dummy); } -static void init_board_array(gpib_board_t *board_array, unsigned int length) +static void init_board_array(struct gpib_board *board_array, unsigned int length) { int i; @@ -2184,7 +2158,7 @@ static int __init gpib_common_init_module(void) { int i; - pr_info("Linux-GPIB core driver\n"); + pr_info("GPIB core driver\n"); init_board_array(board_array, GPIB_MAX_NUM_BOARDS); if (register_chrdev(GPIB_CODE, "gpib", &ib_fops)) { pr_err("gpib: can't get major %d\n", GPIB_CODE);
diff --git a/drivers/staging/gpib/common/iblib.c b/drivers/staging/gpib/common/iblib.c index 5f6fa13..b297261 100644 --- a/drivers/staging/gpib/common/iblib.c +++ b/drivers/staging/gpib/common/iblib.c
@@ -4,6 +4,8 @@ * copyright : (C) 2001, 2002 by Frank Mori Hess ***************************************************************************/ +#define dev_fmt(fmt) KBUILD_MODNAME ": " fmt + #include "ibsys.h" #include <linux/delay.h> #include <linux/kthread.h> @@ -19,15 +21,13 @@ * If fallback_to_async is non-zero, try to take control asynchronously * if synchronous attempt fails. */ -int ibcac(gpib_board_t *board, int sync, int fallback_to_async) +int ibcac(struct gpib_board *board, int sync, int fallback_to_async) { int status = ibstatus(board); int retval; - if ((status & CIC) == 0) { - pr_err("gpib: not CIC during %s()\n", __func__); - return -1; - } + if ((status & CIC) == 0) + return -EINVAL; if (status & ATN) return 0; @@ -61,7 +61,7 @@ int ibcac(gpib_board_t *board, int sync, int fallback_to_async) * set the skip_check_for_command_acceptors flag in their * gpib_interface_struct to avoid useless overhead. */ -static int check_for_command_acceptors(gpib_board_t *board) +static int check_for_command_acceptors(struct gpib_board *board) { int lines; @@ -76,15 +76,8 @@ static int check_for_command_acceptors(gpib_board_t *board) if (lines < 0) return lines; - if (lines & ValidATN) { - if ((lines & BusATN) == 0) { - pr_err("gpib: ATN not asserted in %s()?", __func__); - return 0; - } - } - - if ((lines & ValidNRFD) && (lines & ValidNDAC)) { - if ((lines & BusNRFD) == 0 && (lines & BusNDAC) == 0) + if ((lines & VALID_NRFD) && (lines & VALID_NDAC)) { + if ((lines & BUS_NRFD) == 0 && (lines & BUS_NDAC) == 0) return -ENOTCONN; } @@ -103,7 +96,7 @@ static int check_for_command_acceptors(gpib_board_t *board) * must be called to initialize the GPIB and enable * the interface to leave the controller idle state. */ -int ibcmd(gpib_board_t *board, uint8_t *buf, size_t length, size_t *bytes_written) +int ibcmd(struct gpib_board *board, uint8_t *buf, size_t length, size_t *bytes_written) { ssize_t ret = 0; int status; @@ -112,10 +105,8 @@ int ibcmd(gpib_board_t *board, uint8_t *buf, size_t length, size_t *bytes_writte status = ibstatus(board); - if ((status & CIC) == 0) { - pr_err("gpib: cannot send command when not controller-in-charge\n"); - return -EIO; - } + if ((status & CIC) == 0) + return -EINVAL; os_start_timer(board, board->usec_timeout); @@ -140,26 +131,22 @@ int ibcmd(gpib_board_t *board, uint8_t *buf, size_t length, size_t *bytes_writte * active state, i.e., turn ATN off. */ -int ibgts(gpib_board_t *board) +int ibgts(struct gpib_board *board) { int status = ibstatus(board); int retval; - if ((status & CIC) == 0) { - pr_err("gpib: not CIC during %s()\n", __func__); - return -1; - } + if ((status & CIC) == 0) + return -EINVAL; retval = board->interface->go_to_standby(board); /* go to standby */ - if (retval < 0) - pr_err("gpib: error while going to standby\n"); board->interface->update_status(board, 0); return retval; } -static int autospoll_wait_should_wake_up(gpib_board_t *board) +static int autospoll_wait_should_wake_up(struct gpib_board *board) { int retval; @@ -175,7 +162,7 @@ static int autospoll_wait_should_wake_up(gpib_board_t *board) static int autospoll_thread(void *board_void) { - gpib_board_t *board = board_void; + struct gpib_board *board = board_void; int retval = 0; dev_dbg(board->gpib_dev, "entering autospoll thread\n"); @@ -200,20 +187,19 @@ static int autospoll_thread(void *board_void) retval = autopoll_all_devices(board); module_put(board->provider_module); } else { - pr_err("gpib%i: %s: try_module_get() failed!\n", board->minor, __func__); + dev_err(board->gpib_dev, "try_module_get() failed!\n"); } if (retval <= 0) { - pr_err("gpib%i: %s: stuck SRQ\n", board->minor, __func__); + dev_err(board->gpib_dev, "stuck SRQ\n"); atomic_set(&board->stuck_srq, 1); // XXX could be better set_bit(SRQI_NUM, &board->status); } } - pr_info("gpib%i: exiting autospoll thread\n", board->minor); return retval; } -int ibonline(gpib_board_t *board) +int ibonline(struct gpib_board *board) { int retval; @@ -230,7 +216,6 @@ int ibonline(gpib_board_t *board) retval = board->interface->attach(board, &board->config); if (retval < 0) { board->interface->detach(board); - pr_err("gpib: interface attach failed\n"); return retval; } /* nios2nommu on 2.6.11 uclinux kernel has weird problems @@ -241,19 +226,19 @@ int ibonline(gpib_board_t *board) "gpib%d_autospoll_kthread", board->minor); retval = IS_ERR(board->autospoll_task); if (retval) { - pr_err("gpib: failed to create autospoll thread\n"); + dev_err(board->gpib_dev, "failed to create autospoll thread\n"); board->interface->detach(board); return retval; } #endif board->online = 1; - dev_dbg(board->gpib_dev, "gpib: board online\n"); + dev_dbg(board->gpib_dev, "board online\n"); return 0; } /* XXX need to make sure board is generally not in use (grab board lock?) */ -int iboffline(gpib_board_t *board) +int iboffline(struct gpib_board *board) { int retval; @@ -265,14 +250,14 @@ int iboffline(gpib_board_t *board) if (board->autospoll_task && !IS_ERR(board->autospoll_task)) { retval = kthread_stop(board->autospoll_task); if (retval) - pr_err("gpib: kthread_stop returned %i\n", retval); + dev_err(board->gpib_dev, "kthread_stop returned %i\n", retval); board->autospoll_task = NULL; } board->interface->detach(board); gpib_deallocate_board(board); board->online = 0; - dev_dbg(board->gpib_dev, "gpib: board offline\n"); + dev_dbg(board->gpib_dev, "board offline\n"); return 0; } @@ -285,7 +270,7 @@ int iboffline(gpib_board_t *board) * Next LSB (bits 8-15) - STATUS lines mask (lines that are currently set). * */ -int iblines(const gpib_board_t *board, short *lines) +int iblines(const struct gpib_board *board, short *lines) { int retval; @@ -312,7 +297,7 @@ int iblines(const gpib_board_t *board, short *lines) * calling ibcmd. */ -int ibrd(gpib_board_t *board, uint8_t *buf, size_t length, int *end_flag, size_t *nbytes) +int ibrd(struct gpib_board *board, uint8_t *buf, size_t length, int *end_flag, size_t *nbytes) { ssize_t ret = 0; int retval; @@ -320,10 +305,8 @@ int ibrd(gpib_board_t *board, uint8_t *buf, size_t length, int *end_flag, size_t *nbytes = 0; *end_flag = 0; - if (length == 0) { - pr_warn("gpib: %s() called with zero length?\n", __func__); + if (length == 0) return 0; - } if (board->master) { retval = ibgts(board); @@ -338,10 +321,9 @@ int ibrd(gpib_board_t *board, uint8_t *buf, size_t length, int *end_flag, size_t do { ret = board->interface->read(board, buf, length - *nbytes, end_flag, &bytes_read); - if (ret < 0) { - pr_err("gpib read error\n"); + if (ret < 0) goto ibrd_out; - } + buf += bytes_read; *nbytes += bytes_read; if (need_resched()) @@ -361,7 +343,7 @@ int ibrd(gpib_board_t *board, uint8_t *buf, size_t length, int *end_flag, size_t * 1. Prior to conducting the poll the interface is placed * in the controller active state. */ -int ibrpp(gpib_board_t *board, uint8_t *result) +int ibrpp(struct gpib_board *board, uint8_t *result) { int retval = 0; @@ -370,15 +352,13 @@ int ibrpp(gpib_board_t *board, uint8_t *result) if (retval) return -1; - if (board->interface->parallel_poll(board, result)) { - pr_err("gpib: parallel poll failed\n"); - retval = -1; - } + retval = board->interface->parallel_poll(board, result); + os_remove_timer(board); return retval; } -int ibppc(gpib_board_t *board, uint8_t configuration) +int ibppc(struct gpib_board *board, uint8_t configuration) { configuration &= 0x1f; board->interface->parallel_poll_configure(board, configuration); @@ -387,15 +367,13 @@ int ibppc(gpib_board_t *board, uint8_t configuration) return 0; } -int ibrsv2(gpib_board_t *board, uint8_t status_byte, int new_reason_for_service) +int ibrsv2(struct gpib_board *board, uint8_t status_byte, int new_reason_for_service) { int board_status = ibstatus(board); const unsigned int MSS = status_byte & request_service_bit; - if ((board_status & CIC)) { - pr_err("gpib: interface requested service while CIC\n"); + if ((board_status & CIC)) return -EINVAL; - } if (MSS == 0 && new_reason_for_service) return -EINVAL; @@ -422,21 +400,17 @@ int ibrsv2(gpib_board_t *board, uint8_t status_byte, int new_reason_for_service) * ibcmd in order to initialize the bus and enable the * interface to leave the controller idle state. */ -int ibsic(gpib_board_t *board, unsigned int usec_duration) +int ibsic(struct gpib_board *board, unsigned int usec_duration) { - if (board->master == 0) { - pr_err("gpib: tried to assert IFC when not system controller\n"); - return -1; - } + if (board->master == 0) + return -EINVAL; if (usec_duration < 100) usec_duration = 100; - if (usec_duration > 1000) { + if (usec_duration > 1000) usec_duration = 1000; - pr_warn("gpib: warning, shortening long udelay\n"); - } - dev_dbg(board->gpib_dev, "sending interface clear\n"); + dev_dbg(board->gpib_dev, "sending interface clear, delay = %ius\n", usec_duration); board->interface->interface_clear(board, 1); udelay(usec_duration); board->interface->interface_clear(board, 0); @@ -444,26 +418,22 @@ int ibsic(gpib_board_t *board, unsigned int usec_duration) return 0; } -void ibrsc(gpib_board_t *board, int request_control) + /* FIXME make int */ +void ibrsc(struct gpib_board *board, int request_control) { board->master = request_control != 0; - if (!board->interface->request_system_control) { - pr_err("gpib: bug! driver does not implement request_system_control()\n"); - return; - } - board->interface->request_system_control(board, request_control); + if (board->interface->request_system_control) + board->interface->request_system_control(board, request_control); } /* * IBSRE * Send REN true if v is non-zero or false if v is zero. */ -int ibsre(gpib_board_t *board, int enable) +int ibsre(struct gpib_board *board, int enable) { - if (board->master == 0) { - pr_err("gpib: tried to set REN when not system controller\n"); - return -1; - } + if (board->master == 0) + return -EINVAL; board->interface->remote_enable(board, enable); /* set or clear REN */ if (!enable) @@ -477,12 +447,11 @@ int ibsre(gpib_board_t *board, int enable) * change the GPIB address of the interface board. The address * must be 0 through 30. ibonl resets the address to PAD. */ -int ibpad(gpib_board_t *board, unsigned int addr) +int ibpad(struct gpib_board *board, unsigned int addr) { - if (addr > MAX_GPIB_PRIMARY_ADDRESS) { - pr_err("gpib: invalid primary address %u\n", addr); - return -1; - } + if (addr > MAX_GPIB_PRIMARY_ADDRESS) + return -EINVAL; + board->pad = addr; if (board->online) board->interface->primary_address(board, board->pad); @@ -496,12 +465,10 @@ int ibpad(gpib_board_t *board, unsigned int addr) * The address must be 0 through 30, or negative disables. ibonl resets the * address to SAD. */ -int ibsad(gpib_board_t *board, int addr) +int ibsad(struct gpib_board *board, int addr) { - if (addr > MAX_GPIB_SECONDARY_ADDRESS) { - pr_err("gpib: invalid secondary address %i\n", addr); - return -1; - } + if (addr > MAX_GPIB_SECONDARY_ADDRESS) + return -EINVAL; board->sad = addr; if (board->online) { if (board->sad >= 0) @@ -519,14 +486,12 @@ int ibsad(gpib_board_t *board, int addr) * Set the end-of-string modes for I/O operations to v. * */ -int ibeos(gpib_board_t *board, int eos, int eosflags) +int ibeos(struct gpib_board *board, int eos, int eosflags) { int retval; - if (eosflags & ~EOS_MASK) { - pr_err("bad EOS modes\n"); + if (eosflags & ~EOS_MASK) return -EINVAL; - } if (eosflags & REOS) { retval = board->interface->enable_eos(board, eos, eosflags & BIN); } else { @@ -536,12 +501,12 @@ int ibeos(gpib_board_t *board, int eos, int eosflags) return retval; } -int ibstatus(gpib_board_t *board) +int ibstatus(struct gpib_board *board) { return general_ibstatus(board, NULL, 0, 0, NULL); } -int general_ibstatus(gpib_board_t *board, const gpib_status_queue_t *device, +int general_ibstatus(struct gpib_board *board, const gpib_status_queue_t *device, int clear_mask, int set_mask, gpib_descriptor_t *desc) { int status = 0; @@ -555,8 +520,8 @@ int general_ibstatus(gpib_board_t *board, const gpib_status_queue_t *device, status &= ~TIMO; /* get real SRQI status if we can */ if (iblines(board, &line_status) == 0) { - if ((line_status & ValidSRQ)) { - if ((line_status & BusSRQ)) + if ((line_status & VALID_SRQ)) { + if ((line_status & BUS_SRQ)) status |= SRQI; else status &= ~SRQI; @@ -587,7 +552,7 @@ int general_ibstatus(gpib_board_t *board, const gpib_status_queue_t *device, } struct wait_info { - gpib_board_t *board; + struct gpib_board *board; struct timer_list timer; int timed_out; unsigned long usec_timeout; @@ -611,7 +576,7 @@ static void init_wait_info(struct wait_info *winfo) static int wait_satisfied(struct wait_info *winfo, gpib_status_queue_t *status_queue, int wait_mask, int *status, gpib_descriptor_t *desc) { - gpib_board_t *board = winfo->board; + struct gpib_board *board = winfo->board; int temp_status; if (mutex_lock_interruptible(&board->big_gpib_mutex)) @@ -645,7 +610,7 @@ static void start_wait_timer(struct wait_info *winfo) static void remove_wait_timer(struct wait_info *winfo) { - del_timer_sync(&winfo->timer); + timer_delete_sync(&winfo->timer); destroy_timer_on_stack(&winfo->timer); } @@ -657,7 +622,7 @@ static void remove_wait_timer(struct wait_info *winfo) * If the mask is 0 then * no condition is waited for. */ -int ibwait(gpib_board_t *board, int wait_mask, int clear_mask, int set_mask, +int ibwait(struct gpib_board *board, int wait_mask, int clear_mask, int set_mask, int *status, unsigned long usec_timeout, gpib_descriptor_t *desc) { int retval = 0; @@ -712,15 +677,13 @@ int ibwait(gpib_board_t *board, int wait_mask, int clear_mask, int set_mask, * well as the interface board itself must be * addressed by calling ibcmd. */ -int ibwrt(gpib_board_t *board, uint8_t *buf, size_t cnt, int send_eoi, size_t *bytes_written) +int ibwrt(struct gpib_board *board, uint8_t *buf, size_t cnt, int send_eoi, size_t *bytes_written) { int ret = 0; int retval; - if (cnt == 0) { - pr_warn("gpib: %s() called with zero length?\n", __func__); + if (cnt == 0) return 0; - } if (board->master) { retval = ibgts(board);
diff --git a/drivers/staging/gpib/common/ibsys.h b/drivers/staging/gpib/common/ibsys.h index da20971..19960af 100644 --- a/drivers/staging/gpib/common/ibsys.h +++ b/drivers/staging/gpib/common/ibsys.h
@@ -19,13 +19,13 @@ #define MAX_GPIB_PRIMARY_ADDRESS 30 #define MAX_GPIB_SECONDARY_ADDRESS 31 -int gpib_allocate_board(gpib_board_t *board); -void gpib_deallocate_board(gpib_board_t *board); +int gpib_allocate_board(struct gpib_board *board); +void gpib_deallocate_board(struct gpib_board *board); unsigned int num_status_bytes(const gpib_status_queue_t *dev); -int push_status_byte(gpib_board_t *board, gpib_status_queue_t *device, uint8_t poll_byte); -int pop_status_byte(gpib_board_t *board, gpib_status_queue_t *device, uint8_t *poll_byte); -gpib_status_queue_t *get_gpib_status_queue(gpib_board_t *board, unsigned int pad, int sad); -int get_serial_poll_byte(gpib_board_t *board, unsigned int pad, int sad, +int push_status_byte(struct gpib_board *board, gpib_status_queue_t *device, uint8_t poll_byte); +int pop_status_byte(struct gpib_board *board, gpib_status_queue_t *device, uint8_t *poll_byte); +gpib_status_queue_t *get_gpib_status_queue(struct gpib_board *board, unsigned int pad, int sad); +int get_serial_poll_byte(struct gpib_board *board, unsigned int pad, int sad, unsigned int usec_timeout, uint8_t *poll_byte); -int autopoll_all_devices(gpib_board_t *board); +int autopoll_all_devices(struct gpib_board *board);
diff --git a/drivers/staging/gpib/eastwood/fluke_gpib.c b/drivers/staging/gpib/eastwood/fluke_gpib.c index 0304c5d..a6b1ac1 100644 --- a/drivers/staging/gpib/eastwood/fluke_gpib.c +++ b/drivers/staging/gpib/eastwood/fluke_gpib.c
@@ -7,6 +7,10 @@ * copyright: (C) 2006, 2010, 2015 Fluke Corporation ***************************************************************************/ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#define dev_fmt pr_fmt +#define DRV_NAME KBUILD_MODNAME + #include "fluke_gpib.h" #include "gpibP.h" @@ -20,11 +24,11 @@ MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("GPIB Driver for Fluke cda devices"); -static int fluke_attach_holdoff_all(gpib_board_t *board, const gpib_board_config_t *config); -static int fluke_attach_holdoff_end(gpib_board_t *board, const gpib_board_config_t *config); -static void fluke_detach(gpib_board_t *board); -static int fluke_config_dma(gpib_board_t *board, int output); -static irqreturn_t fluke_gpib_internal_interrupt(gpib_board_t *board); +static int fluke_attach_holdoff_all(struct gpib_board *board, const gpib_board_config_t *config); +static int fluke_attach_holdoff_end(struct gpib_board *board, const gpib_board_config_t *config); +static void fluke_detach(struct gpib_board *board); +static int fluke_config_dma(struct gpib_board *board, int output); +static irqreturn_t fluke_gpib_internal_interrupt(struct gpib_board *board); static struct platform_device *fluke_gpib_pdev; @@ -50,7 +54,7 @@ static void fluke_locking_write_byte(struct nec7210_priv *nec_priv, uint8_t byte } // wrappers for interface functions -static int fluke_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *end, +static int fluke_read(struct gpib_board *board, uint8_t *buffer, size_t length, int *end, size_t *bytes_read) { struct fluke_priv *priv = board->private_data; @@ -58,7 +62,7 @@ static int fluke_read(gpib_board_t *board, uint8_t *buffer, size_t length, int * return nec7210_read(board, &priv->nec7210_priv, buffer, length, end, bytes_read); } -static int fluke_write(gpib_board_t *board, uint8_t *buffer, size_t length, +static int fluke_write(struct gpib_board *board, uint8_t *buffer, size_t length, int send_eoi, size_t *bytes_written) { struct fluke_priv *priv = board->private_data; @@ -66,28 +70,29 @@ static int fluke_write(gpib_board_t *board, uint8_t *buffer, size_t length, return nec7210_write(board, &priv->nec7210_priv, buffer, length, send_eoi, bytes_written); } -static int fluke_command(gpib_board_t *board, uint8_t *buffer, size_t length, size_t *bytes_written) +static int fluke_command(struct gpib_board *board, uint8_t *buffer, + size_t length, size_t *bytes_written) { struct fluke_priv *priv = board->private_data; return nec7210_command(board, &priv->nec7210_priv, buffer, length, bytes_written); } -static int fluke_take_control(gpib_board_t *board, int synchronous) +static int fluke_take_control(struct gpib_board *board, int synchronous) { struct fluke_priv *priv = board->private_data; return nec7210_take_control(board, &priv->nec7210_priv, synchronous); } -static int fluke_go_to_standby(gpib_board_t *board) +static int fluke_go_to_standby(struct gpib_board *board) { struct fluke_priv *priv = board->private_data; return nec7210_go_to_standby(board, &priv->nec7210_priv); } -static void fluke_request_system_control(gpib_board_t *board, int request_control) +static void fluke_request_system_control(struct gpib_board *board, int request_control) { struct fluke_priv *priv = board->private_data; struct nec7210_priv *nec_priv = &priv->nec7210_priv; @@ -95,91 +100,91 @@ static void fluke_request_system_control(gpib_board_t *board, int request_contro nec7210_request_system_control(board, nec_priv, request_control); } -static void fluke_interface_clear(gpib_board_t *board, int assert) +static void fluke_interface_clear(struct gpib_board *board, int assert) { struct fluke_priv *priv = board->private_data; nec7210_interface_clear(board, &priv->nec7210_priv, assert); } -static void fluke_remote_enable(gpib_board_t *board, int enable) +static void fluke_remote_enable(struct gpib_board *board, int enable) { struct fluke_priv *priv = board->private_data; nec7210_remote_enable(board, &priv->nec7210_priv, enable); } -static int fluke_enable_eos(gpib_board_t *board, uint8_t eos_byte, int compare_8_bits) +static int fluke_enable_eos(struct gpib_board *board, uint8_t eos_byte, int compare_8_bits) { struct fluke_priv *priv = board->private_data; return nec7210_enable_eos(board, &priv->nec7210_priv, eos_byte, compare_8_bits); } -static void fluke_disable_eos(gpib_board_t *board) +static void fluke_disable_eos(struct gpib_board *board) { struct fluke_priv *priv = board->private_data; nec7210_disable_eos(board, &priv->nec7210_priv); } -static unsigned int fluke_update_status(gpib_board_t *board, unsigned int clear_mask) +static unsigned int fluke_update_status(struct gpib_board *board, unsigned int clear_mask) { struct fluke_priv *priv = board->private_data; return nec7210_update_status(board, &priv->nec7210_priv, clear_mask); } -static int fluke_primary_address(gpib_board_t *board, unsigned int address) +static int fluke_primary_address(struct gpib_board *board, unsigned int address) { struct fluke_priv *priv = board->private_data; return nec7210_primary_address(board, &priv->nec7210_priv, address); } -static int fluke_secondary_address(gpib_board_t *board, unsigned int address, int enable) +static int fluke_secondary_address(struct gpib_board *board, unsigned int address, int enable) { struct fluke_priv *priv = board->private_data; return nec7210_secondary_address(board, &priv->nec7210_priv, address, enable); } -static int fluke_parallel_poll(gpib_board_t *board, uint8_t *result) +static int fluke_parallel_poll(struct gpib_board *board, uint8_t *result) { struct fluke_priv *priv = board->private_data; return nec7210_parallel_poll(board, &priv->nec7210_priv, result); } -static void fluke_parallel_poll_configure(gpib_board_t *board, uint8_t configuration) +static void fluke_parallel_poll_configure(struct gpib_board *board, uint8_t configuration) { struct fluke_priv *priv = board->private_data; nec7210_parallel_poll_configure(board, &priv->nec7210_priv, configuration); } -static void fluke_parallel_poll_response(gpib_board_t *board, int ist) +static void fluke_parallel_poll_response(struct gpib_board *board, int ist) { struct fluke_priv *priv = board->private_data; nec7210_parallel_poll_response(board, &priv->nec7210_priv, ist); } -static void fluke_serial_poll_response(gpib_board_t *board, uint8_t status) +static void fluke_serial_poll_response(struct gpib_board *board, uint8_t status) { struct fluke_priv *priv = board->private_data; nec7210_serial_poll_response(board, &priv->nec7210_priv, status); } -static uint8_t fluke_serial_poll_status(gpib_board_t *board) +static uint8_t fluke_serial_poll_status(struct gpib_board *board) { struct fluke_priv *priv = board->private_data; return nec7210_serial_poll_status(board, &priv->nec7210_priv); } -static void fluke_return_to_local(gpib_board_t *board) +static void fluke_return_to_local(struct gpib_board *board) { struct fluke_priv *priv = board->private_data; struct nec7210_priv *nec_priv = &priv->nec7210_priv; @@ -189,39 +194,37 @@ static void fluke_return_to_local(gpib_board_t *board) write_byte(nec_priv, AUX_RTL, AUXMR); } -static int fluke_line_status(const gpib_board_t *board) +static int fluke_line_status(const struct gpib_board *board) { - int status = ValidALL; + int status = VALID_ALL; int bsr_bits; struct fluke_priv *e_priv; - struct nec7210_priv *nec_priv; e_priv = board->private_data; - nec_priv = &e_priv->nec7210_priv; bsr_bits = fluke_paged_read_byte(e_priv, BUS_STATUS, BUS_STATUS_PAGE); if ((bsr_bits & BSR_REN_BIT) == 0) - status |= BusREN; + status |= BUS_REN; if ((bsr_bits & BSR_IFC_BIT) == 0) - status |= BusIFC; + status |= BUS_IFC; if ((bsr_bits & BSR_SRQ_BIT) == 0) - status |= BusSRQ; + status |= BUS_SRQ; if ((bsr_bits & BSR_EOI_BIT) == 0) - status |= BusEOI; + status |= BUS_EOI; if ((bsr_bits & BSR_NRFD_BIT) == 0) - status |= BusNRFD; + status |= BUS_NRFD; if ((bsr_bits & BSR_NDAC_BIT) == 0) - status |= BusNDAC; + status |= BUS_NDAC; if ((bsr_bits & BSR_DAV_BIT) == 0) - status |= BusDAV; + status |= BUS_DAV; if ((bsr_bits & BSR_ATN_BIT) == 0) - status |= BusATN; + status |= BUS_ATN; return status; } -static unsigned int fluke_t1_delay(gpib_board_t *board, unsigned int nano_sec) +static int fluke_t1_delay(struct gpib_board *board, unsigned int nano_sec) { struct fluke_priv *e_priv = board->private_data; struct nec7210_priv *nec_priv = &e_priv->nec7210_priv; @@ -238,7 +241,7 @@ static unsigned int fluke_t1_delay(gpib_board_t *board, unsigned int nano_sec) return retval; } -static int lacs_or_read_ready(gpib_board_t *board) +static int lacs_or_read_ready(struct gpib_board *board) { const struct fluke_priv *e_priv = board->private_data; const struct nec7210_priv *nec_priv = &e_priv->nec7210_priv; @@ -254,7 +257,7 @@ static int lacs_or_read_ready(gpib_board_t *board) /* Wait until it is possible for a read to do something useful. This * is not essential, it only exists to prevent RFD holdoff from being released pointlessly. */ -static int wait_for_read(gpib_board_t *board) +static int wait_for_read(struct gpib_board *board) { struct fluke_priv *e_priv = board->private_data; struct nec7210_priv *nec_priv = &e_priv->nec7210_priv; @@ -263,9 +266,9 @@ static int wait_for_read(gpib_board_t *board) if (wait_event_interruptible(board->wait, lacs_or_read_ready(board) || test_bit(DEV_CLEAR_BN, &nec_priv->state) || - test_bit(TIMO_NUM, &board->status))) { + test_bit(TIMO_NUM, &board->status))) retval = -ERESTARTSYS; - } + if (test_bit(TIMO_NUM, &board->status)) retval = -ETIMEDOUT; if (test_and_clear_bit(DEV_CLEAR_BN, &nec_priv->state)) @@ -311,34 +314,30 @@ static int source_handshake_is_sids_or_sgns(struct fluke_priv *e_priv) * If the chip is SGNS it is probably waiting for a a byte to * be written to it. */ -static int wait_for_data_out_ready(gpib_board_t *board) +static int wait_for_data_out_ready(struct gpib_board *board) { struct fluke_priv *e_priv = board->private_data; struct nec7210_priv *nec_priv = &e_priv->nec7210_priv; int retval = 0; -// printk("%s: enter\n", __FUNCTION__); if (wait_event_interruptible(board->wait, (test_bit(TACS_NUM, &board->status) && source_handshake_is_sgns(e_priv)) || test_bit(DEV_CLEAR_BN, &nec_priv->state) || - test_bit(TIMO_NUM, &board->status))) { + test_bit(TIMO_NUM, &board->status))) retval = -ERESTARTSYS; - } if (test_bit(TIMO_NUM, &board->status)) retval = -ETIMEDOUT; if (test_and_clear_bit(DEV_CLEAR_BN, &nec_priv->state)) retval = -EINTR; -// printk("%s: exit, retval=%i\n", __FUNCTION__, retval); return retval; } -static int wait_for_sids_or_sgns(gpib_board_t *board) +static int wait_for_sids_or_sgns(struct gpib_board *board) { struct fluke_priv *e_priv = board->private_data; struct nec7210_priv *nec_priv = &e_priv->nec7210_priv; int retval = 0; -// printk("%s: enter\n", __FUNCTION__); if (wait_event_interruptible(board->wait, source_handshake_is_sids_or_sgns(e_priv) || @@ -350,19 +349,17 @@ static int wait_for_sids_or_sgns(gpib_board_t *board) retval = -ETIMEDOUT; if (test_and_clear_bit(DEV_CLEAR_BN, &nec_priv->state)) retval = -EINTR; -// printk("%s: exit, retval=%i\n", __FUNCTION__, retval); return retval; } static void fluke_dma_callback(void *arg) { - gpib_board_t *board = arg; + struct gpib_board *board = arg; struct fluke_priv *e_priv = board->private_data; struct nec7210_priv *nec_priv = &e_priv->nec7210_priv; unsigned long flags; spin_lock_irqsave(&board->spinlock, flags); -// printk("%s: enter\n", __FUNCTION__); nec7210_set_reg_bits(nec_priv, IMR1, HR_DOIE | HR_DIIE, HR_DOIE | HR_DIIE); wake_up_interruptible(&board->wait); @@ -370,11 +367,11 @@ static void fluke_dma_callback(void *arg) fluke_gpib_internal_interrupt(board); clear_bit(DMA_WRITE_IN_PROGRESS_BN, &nec_priv->state); clear_bit(DMA_READ_IN_PROGRESS_BN, &nec_priv->state); -// printk("%s: exit\n", __FUNCTION__); + spin_unlock_irqrestore(&board->spinlock, flags); } -static int fluke_dma_write(gpib_board_t *board, uint8_t *buffer, size_t length, +static int fluke_dma_write(struct gpib_board *board, uint8_t *buffer, size_t length, size_t *bytes_written) { struct fluke_priv *e_priv = board->private_data; @@ -385,7 +382,7 @@ static int fluke_dma_write(gpib_board_t *board, uint8_t *buffer, size_t length, struct dma_async_tx_descriptor *tx_desc; *bytes_written = 0; -// printk("%s: enter\n", __FUNCTION__); + if (WARN_ON_ONCE(length > e_priv->dma_buffer_size)) return -EFAULT; dmaengine_terminate_all(e_priv->dma_channel); @@ -403,7 +400,7 @@ static int fluke_dma_write(gpib_board_t *board, uint8_t *buffer, size_t length, tx_desc = dmaengine_prep_slave_single(e_priv->dma_channel, address, length, DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (!tx_desc) { - pr_err("fluke_gpib: failed to allocate dma transmit descriptor\n"); + dev_err(board->gpib_dev, "failed to allocate dma transmit descriptor\n"); retval = -ENOMEM; goto cleanup; } @@ -419,10 +416,8 @@ static int fluke_dma_write(gpib_board_t *board, uint8_t *buffer, size_t length, clear_bit(WRITE_READY_BN, &nec_priv->state); set_bit(DMA_WRITE_IN_PROGRESS_BN, &nec_priv->state); - // printk("%s: in spin lock\n", __FUNCTION__); spin_unlock_irqrestore(&board->spinlock, flags); -// printk("%s: waiting for write.\n", __FUNCTION__); // suspend until message is sent if (wait_event_interruptible(board->wait, ((readl(e_priv->write_transfer_counter) & @@ -430,7 +425,6 @@ static int fluke_dma_write(gpib_board_t *board, uint8_t *buffer, size_t length, test_bit(BUS_ERROR_BN, &nec_priv->state) || test_bit(DEV_CLEAR_BN, &nec_priv->state) || test_bit(TIMO_NUM, &board->status))) { - dev_dbg(board->gpib_dev, "gpib write interrupted!\n"); retval = -ERESTARTSYS; } if (test_bit(TIMO_NUM, &board->status)) @@ -459,11 +453,10 @@ static int fluke_dma_write(gpib_board_t *board, uint8_t *buffer, size_t length, cleanup: dma_unmap_single(board->dev, address, length, DMA_TO_DEVICE); -// printk("%s: exit, retval=%d\n", __FUNCTION__, retval); return retval; } -static int fluke_accel_write(gpib_board_t *board, uint8_t *buffer, size_t length, +static int fluke_accel_write(struct gpib_board *board, uint8_t *buffer, size_t length, int send_eoi, size_t *bytes_written) { struct fluke_priv *e_priv = board->private_data; @@ -474,7 +467,7 @@ static int fluke_accel_write(gpib_board_t *board, uint8_t *buffer, size_t length size_t dma_remainder = remainder; if (!e_priv->dma_channel) { - pr_err("fluke_gpib: No dma channel available, cannot do accel write."); + dev_err(board->gpib_dev, "No dma channel available, cannot do accel write."); return -ENXIO; } @@ -486,7 +479,6 @@ static int fluke_accel_write(gpib_board_t *board, uint8_t *buffer, size_t length if (send_eoi) --dma_remainder; -// printk("%s: entering while loop\n", __FUNCTION__); while (dma_remainder > 0) { size_t num_bytes; @@ -512,7 +504,7 @@ static int fluke_accel_write(gpib_board_t *board, uint8_t *buffer, size_t length //handle sending of last byte with eoi if (send_eoi) { size_t num_bytes; - // printk("%s: handling last byte\n", __FUNCTION__); + if (WARN_ON_ONCE(remainder != 1)) return -EFAULT; @@ -533,7 +525,6 @@ static int fluke_accel_write(gpib_board_t *board, uint8_t *buffer, size_t length return retval; remainder -= num_bytes; } -// printk("%s: bytes send=%i\n", __FUNCTION__, (int)(length - remainder)); return 0; } @@ -544,7 +535,7 @@ static int fluke_get_dma_residue(struct dma_chan *chan, dma_cookie_t cookie) result = dmaengine_pause(chan); if (result < 0) { - pr_err("fluke_gpib: dma pause failed?\n"); + pr_err("dma pause failed?\n"); return result; } dmaengine_tx_status(chan, cookie, &state); @@ -553,7 +544,7 @@ static int fluke_get_dma_residue(struct dma_chan *chan, dma_cookie_t cookie) return state.residue; } -static int fluke_dma_read(gpib_board_t *board, uint8_t *buffer, +static int fluke_dma_read(struct gpib_board *board, uint8_t *buffer, size_t length, int *end, size_t *bytes_read) { struct fluke_priv *e_priv = board->private_data; @@ -567,10 +558,6 @@ static int fluke_dma_read(gpib_board_t *board, uint8_t *buffer, int i; static const int timeout = 10; - // printk("%s: enter, bus_address=0x%x, length=%i\n", __FUNCTION__, - // (unsigned)bus_address, - // (int)length); - *bytes_read = 0; *end = 0; if (length == 0) @@ -589,7 +576,7 @@ static int fluke_dma_read(gpib_board_t *board, uint8_t *buffer, bus_address, length, DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (!tx_desc) { - pr_err("fluke_gpib: failed to allocate dma transmit descriptor\n"); + dev_err(board->gpib_dev, "failed to allocate dma transmit descriptor\n"); dma_unmap_single(NULL, bus_address, length, DMA_FROM_DEVICE); return -EIO; } @@ -608,14 +595,12 @@ static int fluke_dma_read(gpib_board_t *board, uint8_t *buffer, clear_bit(READ_READY_BN, &nec_priv->state); spin_unlock_irqrestore(&board->spinlock, flags); -// printk("waiting for data transfer.\n"); // wait for data to transfer if (wait_event_interruptible(board->wait, test_bit(DMA_READ_IN_PROGRESS_BN, &nec_priv->state) == 0 || test_bit(RECEIVED_END_BN, &nec_priv->state) || test_bit(DEV_CLEAR_BN, &nec_priv->state) || test_bit(TIMO_NUM, &board->status))) { - pr_warn("fluke: dma read wait interrupted\n"); retval = -ERESTARTSYS; } if (test_bit(TIMO_NUM, &board->status)) @@ -672,7 +657,7 @@ static int fluke_dma_read(gpib_board_t *board, uint8_t *buffer, return retval; } -static int fluke_accel_read(gpib_board_t *board, uint8_t *buffer, size_t length, +static int fluke_accel_read(struct gpib_board *board, uint8_t *buffer, size_t length, int *end, size_t *bytes_read) { struct fluke_priv *e_priv = board->private_data; @@ -682,10 +667,6 @@ static int fluke_accel_read(gpib_board_t *board, uint8_t *buffer, size_t length, int retval = 0; size_t dma_nbytes; -/* printk("%s: enter, buffer=0x%p, length=%i\n", __FUNCTION__, - * buffer, (int)length); - * printk("\t dma_buffer=0x%p\n", e_priv->dma_buffer); - */ *end = 0; *bytes_read = 0; @@ -699,7 +680,6 @@ static int fluke_accel_read(gpib_board_t *board, uint8_t *buffer, size_t length, nec7210_release_rfd_holdoff(board, nec_priv); -// printk("%s: entering while loop\n", __FUNCTION__); while (remain > 0) { transfer_size = (e_priv->dma_buffer_size < remain) ? e_priv->dma_buffer_size : remain; @@ -709,14 +689,12 @@ static int fluke_accel_read(gpib_board_t *board, uint8_t *buffer, size_t length, *bytes_read += dma_nbytes; if (*end) break; - if (retval < 0) { -// printk("%s: early exit, retval=%i\n", __FUNCTION__, (int)retval); + if (retval < 0) return retval; - } if (need_resched()) schedule(); } -// printk("%s: exit, retval=%i\n", __FUNCTION__, (int)retval); + return retval; } @@ -809,7 +787,7 @@ static gpib_interface_t fluke_interface = { .return_to_local = fluke_return_to_local, }; -irqreturn_t fluke_gpib_internal_interrupt(gpib_board_t *board) +irqreturn_t fluke_gpib_internal_interrupt(struct gpib_board *board) { int status0, status1, status2; struct fluke_priv *priv = board->private_data; @@ -830,13 +808,6 @@ irqreturn_t fluke_gpib_internal_interrupt(gpib_board_t *board) if (nec7210_interrupt_have_status(board, nec_priv, status1, status2) == IRQ_HANDLED) retval = IRQ_HANDLED; -/* - * if((status1 & nec_priv->reg_bits[IMR1]) || - * (status2 & (nec_priv->reg_bits[IMR2] & IMR2_ENABLE_INTR_MASK))) - * { - * printk("fluke: status1 0x%x, status2 0x%x\n", status1, status2); - * } - */ if (read_byte(nec_priv, ADR0) & DATA_IN_STATUS) { if (test_bit(RFD_HOLDOFF_BN, &nec_priv->state)) @@ -853,7 +824,7 @@ irqreturn_t fluke_gpib_internal_interrupt(gpib_board_t *board) static irqreturn_t fluke_gpib_interrupt(int irq, void *arg) { - gpib_board_t *board = arg; + struct gpib_board *board = arg; unsigned long flags; irqreturn_t retval; @@ -863,7 +834,7 @@ static irqreturn_t fluke_gpib_interrupt(int irq, void *arg) return retval; } -static int fluke_allocate_private(gpib_board_t *board) +static int fluke_allocate_private(struct gpib_board *board) { struct fluke_priv *priv; @@ -880,7 +851,7 @@ static int fluke_allocate_private(gpib_board_t *board) return 0; } -static void fluke_generic_detach(gpib_board_t *board) +static void fluke_generic_detach(struct gpib_board *board) { if (board->private_data) { struct fluke_priv *e_priv = board->private_data; @@ -892,7 +863,7 @@ static void fluke_generic_detach(gpib_board_t *board) } // generic part of attach functions shared by all cb7210 boards -static int fluke_generic_attach(gpib_board_t *board) +static int fluke_generic_attach(struct gpib_board *board) { struct fluke_priv *e_priv; struct nec7210_priv *nec_priv; @@ -912,7 +883,7 @@ static int fluke_generic_attach(gpib_board_t *board) return 0; } -static int fluke_config_dma(gpib_board_t *board, int output) +static int fluke_config_dma(struct gpib_board *board, int output) { struct fluke_priv *e_priv = board->private_data; struct dma_slave_config config; @@ -937,7 +908,7 @@ static int fluke_config_dma(gpib_board_t *board, int output) return dmaengine_slave_config(e_priv->dma_channel, &config); } -static int fluke_init(struct fluke_priv *e_priv, gpib_board_t *board, int handshake_mode) +static int fluke_init(struct fluke_priv *e_priv, struct gpib_board *board, int handshake_mode) { struct nec7210_priv *nec_priv = &e_priv->nec7210_priv; @@ -954,7 +925,7 @@ static int fluke_init(struct fluke_priv *e_priv, gpib_board_t *board, int handsh /* poll so we can detect ATN changes */ if (gpib_request_pseudo_irq(board, fluke_gpib_interrupt)) { - pr_err("fluke_gpib: failed to allocate pseudo_irq\n"); + dev_err(board->gpib_dev, "failed to allocate pseudo_irq\n"); return -EINVAL; } @@ -972,7 +943,7 @@ static bool gpib_dma_channel_filter(struct dma_chan *chan, void *filter_param) return chan->chan_id == 0; } -static int fluke_attach_impl(gpib_board_t *board, const gpib_board_config_t *config, +static int fluke_attach_impl(struct gpib_board *board, const gpib_board_config_t *config, unsigned int handshake_mode) { struct fluke_priv *e_priv; @@ -984,7 +955,7 @@ static int fluke_attach_impl(gpib_board_t *board, const gpib_board_config_t *con dma_cap_mask_t dma_cap; if (!fluke_gpib_pdev) { - pr_err("No gpib platform device was found, attach failed.\n"); + dev_err(board->gpib_dev, "No fluke device was found, attach failed.\n"); return -ENODEV; } @@ -999,7 +970,7 @@ static int fluke_attach_impl(gpib_board_t *board, const gpib_board_config_t *con res = platform_get_resource(fluke_gpib_pdev, IORESOURCE_MEM, 0); if (!res) { - dev_err(&fluke_gpib_pdev->dev, "Unable to locate mmio resource for cb7210 gpib\n"); + dev_err(&fluke_gpib_pdev->dev, "Unable to locate mmio resource\n"); return -ENODEV; } @@ -1012,10 +983,7 @@ static int fluke_attach_impl(gpib_board_t *board, const gpib_board_config_t *con e_priv->gpib_iomem_res = res; nec_priv->mmiobase = ioremap(e_priv->gpib_iomem_res->start, - resource_size(e_priv->gpib_iomem_res)); - pr_info("gpib: mmiobase %llx remapped to %p, length=%d\n", - (u64)e_priv->gpib_iomem_res->start, - nec_priv->mmiobase, (int)resource_size(e_priv->gpib_iomem_res)); + resource_size(e_priv->gpib_iomem_res)); if (!nec_priv->mmiobase) { dev_err(&fluke_gpib_pdev->dev, "Could not map I/O memory\n"); return -ENOMEM; @@ -1050,19 +1018,14 @@ static int fluke_attach_impl(gpib_board_t *board, const gpib_board_config_t *con e_priv->write_transfer_counter = ioremap(e_priv->write_transfer_counter_res->start, resource_size(e_priv->write_transfer_counter_res)); - pr_info("gpib: write transfer counter %lx remapped to %p, length=%d\n", - (unsigned long)e_priv->write_transfer_counter_res->start, - e_priv->write_transfer_counter, - (int)resource_size(e_priv->write_transfer_counter_res)); if (!e_priv->write_transfer_counter) { dev_err(&fluke_gpib_pdev->dev, "Could not map I/O memory\n"); return -ENOMEM; } irq = platform_get_irq(fluke_gpib_pdev, 0); - pr_info("gpib: irq %d\n", irq); if (irq < 0) { - dev_err(&fluke_gpib_pdev->dev, "fluke_gpib: request for IRQ failed\n"); + dev_err(&fluke_gpib_pdev->dev, "failed to obtain IRQ\n"); return -EBUSY; } retval = request_irq(irq, fluke_gpib_interrupt, isr_flags, fluke_gpib_pdev->name, board); @@ -1078,7 +1041,7 @@ static int fluke_attach_impl(gpib_board_t *board, const gpib_board_config_t *con dma_cap_set(DMA_SLAVE, dma_cap); e_priv->dma_channel = dma_request_channel(dma_cap, gpib_dma_channel_filter, NULL); if (!e_priv->dma_channel) { - pr_err("fluke_gpib: failed to allocate a dma channel.\n"); + dev_err(board->gpib_dev, "failed to allocate a dma channel.\n"); // we don't error out here because unaccel interface will still // work without dma } @@ -1086,17 +1049,17 @@ static int fluke_attach_impl(gpib_board_t *board, const gpib_board_config_t *con return fluke_init(e_priv, board, handshake_mode); } -int fluke_attach_holdoff_all(gpib_board_t *board, const gpib_board_config_t *config) +int fluke_attach_holdoff_all(struct gpib_board *board, const gpib_board_config_t *config) { return fluke_attach_impl(board, config, HR_HLDA); } -int fluke_attach_holdoff_end(gpib_board_t *board, const gpib_board_config_t *config) +int fluke_attach_holdoff_end(struct gpib_board *board, const gpib_board_config_t *config) { return fluke_attach_impl(board, config, HR_HLDE); } -void fluke_detach(gpib_board_t *board) +void fluke_detach(struct gpib_board *board) { struct fluke_priv *e_priv = board->private_data; struct nec7210_priv *nec_priv; @@ -1142,8 +1105,7 @@ MODULE_DEVICE_TABLE(of, fluke_gpib_of_match); static struct platform_driver fluke_gpib_platform_driver = { .driver = { - .name = "fluke_gpib", - .owner = THIS_MODULE, + .name = DRV_NAME, .of_match_table = fluke_gpib_of_match, }, .probe = &fluke_gpib_probe @@ -1155,25 +1117,25 @@ static int __init fluke_init_module(void) result = platform_driver_register(&fluke_gpib_platform_driver); if (result) { - pr_err("fluke_gpib: platform_driver_register failed: error = %d\n", result); + pr_err("platform_driver_register failed: error = %d\n", result); return result; } result = gpib_register_driver(&fluke_unaccel_interface, THIS_MODULE); if (result) { - pr_err("fluke_gpib: gpib_register_driver failed: error = %d\n", result); + pr_err("gpib_register_driver failed: error = %d\n", result); goto err_unaccel; } result = gpib_register_driver(&fluke_hybrid_interface, THIS_MODULE); if (result) { - pr_err("fluke_gpib: gpib_register_driver failed: error = %d\n", result); + pr_err("gpib_register_driver failed: error = %d\n", result); goto err_hybrid; } result = gpib_register_driver(&fluke_interface, THIS_MODULE); if (result) { - pr_err("fluke_gpib: gpib_register_driver failed: error = %d\n", result); + pr_err("gpib_register_driver failed: error = %d\n", result); goto err_interface; }
diff --git a/drivers/staging/gpib/fmh_gpib/fmh_gpib.c b/drivers/staging/gpib/fmh_gpib/fmh_gpib.c index f950e7c..53f4b3f 100644 --- a/drivers/staging/gpib/fmh_gpib/fmh_gpib.c +++ b/drivers/staging/gpib/fmh_gpib/fmh_gpib.c
@@ -12,6 +12,10 @@ * (C) 2017 Frank Mori Hess ***************************************************************************/ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#define dev_fmt pr_fmt +#define DRV_NAME KBUILD_MODNAME + #include "fmh_gpib.h" #include "gpibP.h" @@ -28,19 +32,21 @@ MODULE_DESCRIPTION("GPIB Driver for fmh_gpib_core"); MODULE_AUTHOR("Frank Mori Hess <fmh6jj@gmail.com>"); static irqreturn_t fmh_gpib_interrupt(int irq, void *arg); -static int fmh_gpib_attach_holdoff_all(gpib_board_t *board, const gpib_board_config_t *config); -static int fmh_gpib_attach_holdoff_end(gpib_board_t *board, const gpib_board_config_t *config); -static void fmh_gpib_detach(gpib_board_t *board); -static int fmh_gpib_pci_attach_holdoff_all(gpib_board_t *board, const gpib_board_config_t *config); -static int fmh_gpib_pci_attach_holdoff_end(gpib_board_t *board, const gpib_board_config_t *config); -static void fmh_gpib_pci_detach(gpib_board_t *board); -static int fmh_gpib_config_dma(gpib_board_t *board, int output); -static irqreturn_t fmh_gpib_internal_interrupt(gpib_board_t *board); +static int fmh_gpib_attach_holdoff_all(struct gpib_board *board, const gpib_board_config_t *config); +static int fmh_gpib_attach_holdoff_end(struct gpib_board *board, const gpib_board_config_t *config); +static void fmh_gpib_detach(struct gpib_board *board); +static int fmh_gpib_pci_attach_holdoff_all(struct gpib_board *board, + const gpib_board_config_t *config); +static int fmh_gpib_pci_attach_holdoff_end(struct gpib_board *board, + const gpib_board_config_t *config); +static void fmh_gpib_pci_detach(struct gpib_board *board); +static int fmh_gpib_config_dma(struct gpib_board *board, int output); +static irqreturn_t fmh_gpib_internal_interrupt(struct gpib_board *board); static struct platform_driver fmh_gpib_platform_driver; static struct pci_driver fmh_gpib_pci_driver; // wrappers for interface functions -static int fmh_gpib_read(gpib_board_t *board, uint8_t *buffer, size_t length, +static int fmh_gpib_read(struct gpib_board *board, uint8_t *buffer, size_t length, int *end, size_t *bytes_read) { struct fmh_priv *priv = board->private_data; @@ -48,7 +54,7 @@ static int fmh_gpib_read(gpib_board_t *board, uint8_t *buffer, size_t length, return nec7210_read(board, &priv->nec7210_priv, buffer, length, end, bytes_read); } -static int fmh_gpib_write(gpib_board_t *board, uint8_t *buffer, size_t length, +static int fmh_gpib_write(struct gpib_board *board, uint8_t *buffer, size_t length, int send_eoi, size_t *bytes_written) { struct fmh_priv *priv = board->private_data; @@ -56,7 +62,7 @@ static int fmh_gpib_write(gpib_board_t *board, uint8_t *buffer, size_t length, return nec7210_write(board, &priv->nec7210_priv, buffer, length, send_eoi, bytes_written); } -static int fmh_gpib_command(gpib_board_t *board, uint8_t *buffer, size_t length, +static int fmh_gpib_command(struct gpib_board *board, uint8_t *buffer, size_t length, size_t *bytes_written) { struct fmh_priv *priv = board->private_data; @@ -64,21 +70,21 @@ static int fmh_gpib_command(gpib_board_t *board, uint8_t *buffer, size_t length, return nec7210_command(board, &priv->nec7210_priv, buffer, length, bytes_written); } -static int fmh_gpib_take_control(gpib_board_t *board, int synchronous) +static int fmh_gpib_take_control(struct gpib_board *board, int synchronous) { struct fmh_priv *priv = board->private_data; return nec7210_take_control(board, &priv->nec7210_priv, synchronous); } -static int fmh_gpib_go_to_standby(gpib_board_t *board) +static int fmh_gpib_go_to_standby(struct gpib_board *board) { struct fmh_priv *priv = board->private_data; return nec7210_go_to_standby(board, &priv->nec7210_priv); } -static void fmh_gpib_request_system_control(gpib_board_t *board, int request_control) +static void fmh_gpib_request_system_control(struct gpib_board *board, int request_control) { struct fmh_priv *priv = board->private_data; struct nec7210_priv *nec_priv = &priv->nec7210_priv; @@ -86,77 +92,77 @@ static void fmh_gpib_request_system_control(gpib_board_t *board, int request_con nec7210_request_system_control(board, nec_priv, request_control); } -static void fmh_gpib_interface_clear(gpib_board_t *board, int assert) +static void fmh_gpib_interface_clear(struct gpib_board *board, int assert) { struct fmh_priv *priv = board->private_data; nec7210_interface_clear(board, &priv->nec7210_priv, assert); } -static void fmh_gpib_remote_enable(gpib_board_t *board, int enable) +static void fmh_gpib_remote_enable(struct gpib_board *board, int enable) { struct fmh_priv *priv = board->private_data; nec7210_remote_enable(board, &priv->nec7210_priv, enable); } -static int fmh_gpib_enable_eos(gpib_board_t *board, uint8_t eos_byte, int compare_8_bits) +static int fmh_gpib_enable_eos(struct gpib_board *board, uint8_t eos_byte, int compare_8_bits) { struct fmh_priv *priv = board->private_data; return nec7210_enable_eos(board, &priv->nec7210_priv, eos_byte, compare_8_bits); } -static void fmh_gpib_disable_eos(gpib_board_t *board) +static void fmh_gpib_disable_eos(struct gpib_board *board) { struct fmh_priv *priv = board->private_data; nec7210_disable_eos(board, &priv->nec7210_priv); } -static unsigned int fmh_gpib_update_status(gpib_board_t *board, unsigned int clear_mask) +static unsigned int fmh_gpib_update_status(struct gpib_board *board, unsigned int clear_mask) { struct fmh_priv *priv = board->private_data; return nec7210_update_status(board, &priv->nec7210_priv, clear_mask); } -static int fmh_gpib_primary_address(gpib_board_t *board, unsigned int address) +static int fmh_gpib_primary_address(struct gpib_board *board, unsigned int address) { struct fmh_priv *priv = board->private_data; return nec7210_primary_address(board, &priv->nec7210_priv, address); } -static int fmh_gpib_secondary_address(gpib_board_t *board, unsigned int address, int enable) +static int fmh_gpib_secondary_address(struct gpib_board *board, unsigned int address, int enable) { struct fmh_priv *priv = board->private_data; return nec7210_secondary_address(board, &priv->nec7210_priv, address, enable); } -static int fmh_gpib_parallel_poll(gpib_board_t *board, uint8_t *result) +static int fmh_gpib_parallel_poll(struct gpib_board *board, uint8_t *result) { struct fmh_priv *priv = board->private_data; return nec7210_parallel_poll(board, &priv->nec7210_priv, result); } -static void fmh_gpib_parallel_poll_configure(gpib_board_t *board, uint8_t configuration) +static void fmh_gpib_parallel_poll_configure(struct gpib_board *board, uint8_t configuration) { struct fmh_priv *priv = board->private_data; nec7210_parallel_poll_configure(board, &priv->nec7210_priv, configuration); } -static void fmh_gpib_parallel_poll_response(gpib_board_t *board, int ist) +static void fmh_gpib_parallel_poll_response(struct gpib_board *board, int ist) { struct fmh_priv *priv = board->private_data; nec7210_parallel_poll_response(board, &priv->nec7210_priv, ist); } -static void fmh_gpib_local_parallel_poll_mode(gpib_board_t *board, int local) +static void fmh_gpib_local_parallel_poll_mode(struct gpib_board *board, int local) { struct fmh_priv *priv = board->private_data; @@ -171,7 +177,7 @@ static void fmh_gpib_local_parallel_poll_mode(gpib_board_t *board, int local) } } -static void fmh_gpib_serial_poll_response2(gpib_board_t *board, uint8_t status, +static void fmh_gpib_serial_poll_response2(struct gpib_board *board, uint8_t status, int new_reason_for_service) { struct fmh_priv *priv = board->private_data; @@ -206,14 +212,14 @@ static void fmh_gpib_serial_poll_response2(gpib_board_t *board, uint8_t status, spin_unlock_irqrestore(&board->spinlock, flags); } -static uint8_t fmh_gpib_serial_poll_status(gpib_board_t *board) +static uint8_t fmh_gpib_serial_poll_status(struct gpib_board *board) { struct fmh_priv *priv = board->private_data; return nec7210_serial_poll_status(board, &priv->nec7210_priv); } -static void fmh_gpib_return_to_local(gpib_board_t *board) +static void fmh_gpib_return_to_local(struct gpib_board *board) { struct fmh_priv *priv = board->private_data; struct nec7210_priv *nec_priv = &priv->nec7210_priv; @@ -223,9 +229,9 @@ static void fmh_gpib_return_to_local(gpib_board_t *board) write_byte(nec_priv, AUX_RTL, AUXMR); } -static int fmh_gpib_line_status(const gpib_board_t *board) +static int fmh_gpib_line_status(const struct gpib_board *board) { - int status = ValidALL; + int status = VALID_ALL; int bsr_bits; struct fmh_priv *e_priv; struct nec7210_priv *nec_priv; @@ -236,26 +242,26 @@ static int fmh_gpib_line_status(const gpib_board_t *board) bsr_bits = read_byte(nec_priv, BUS_STATUS_REG); if ((bsr_bits & BSR_REN_BIT) == 0) - status |= BusREN; + status |= BUS_REN; if ((bsr_bits & BSR_IFC_BIT) == 0) - status |= BusIFC; + status |= BUS_IFC; if ((bsr_bits & BSR_SRQ_BIT) == 0) - status |= BusSRQ; + status |= BUS_SRQ; if ((bsr_bits & BSR_EOI_BIT) == 0) - status |= BusEOI; + status |= BUS_EOI; if ((bsr_bits & BSR_NRFD_BIT) == 0) - status |= BusNRFD; + status |= BUS_NRFD; if ((bsr_bits & BSR_NDAC_BIT) == 0) - status |= BusNDAC; + status |= BUS_NDAC; if ((bsr_bits & BSR_DAV_BIT) == 0) - status |= BusDAV; + status |= BUS_DAV; if ((bsr_bits & BSR_ATN_BIT) == 0) - status |= BusATN; + status |= BUS_ATN; return status; } -static unsigned int fmh_gpib_t1_delay(gpib_board_t *board, unsigned int nano_sec) +static int fmh_gpib_t1_delay(struct gpib_board *board, unsigned int nano_sec) { struct fmh_priv *e_priv = board->private_data; struct nec7210_priv *nec_priv = &e_priv->nec7210_priv; @@ -272,7 +278,7 @@ static unsigned int fmh_gpib_t1_delay(gpib_board_t *board, unsigned int nano_sec return retval; } -static int lacs_or_read_ready(gpib_board_t *board) +static int lacs_or_read_ready(struct gpib_board *board) { const struct fmh_priv *e_priv = board->private_data; const struct nec7210_priv *nec_priv = &e_priv->nec7210_priv; @@ -287,7 +293,7 @@ static int lacs_or_read_ready(gpib_board_t *board) return retval; } -static int wait_for_read(gpib_board_t *board) +static int wait_for_read(struct gpib_board *board) { struct fmh_priv *e_priv = board->private_data; struct nec7210_priv *nec_priv = &e_priv->nec7210_priv; @@ -306,7 +312,7 @@ static int wait_for_read(gpib_board_t *board) return retval; } -static int wait_for_rx_fifo_half_full_or_end(gpib_board_t *board) +static int wait_for_rx_fifo_half_full_or_end(struct gpib_board *board) { struct fmh_priv *e_priv = board->private_data; struct nec7210_priv *nec_priv = &e_priv->nec7210_priv; @@ -329,12 +335,11 @@ static int wait_for_rx_fifo_half_full_or_end(gpib_board_t *board) /* Wait until the gpib chip is ready to accept a data out byte. */ -static int wait_for_data_out_ready(gpib_board_t *board) +static int wait_for_data_out_ready(struct gpib_board *board) { struct fmh_priv *e_priv = board->private_data; struct nec7210_priv *nec_priv = &e_priv->nec7210_priv; int retval = 0; -// printk("%s: enter\n", __FUNCTION__); if (wait_event_interruptible(board->wait, (test_bit(TACS_NUM, &board->status) && @@ -348,19 +353,18 @@ static int wait_for_data_out_ready(gpib_board_t *board) retval = -ETIMEDOUT; if (test_and_clear_bit(DEV_CLEAR_BN, &nec_priv->state)) retval = -EINTR; -// printk("%s: exit, retval=%i\n", __FUNCTION__, retval); + return retval; } static void fmh_gpib_dma_callback(void *arg) { - gpib_board_t *board = arg; + struct gpib_board *board = arg; struct fmh_priv *e_priv = board->private_data; struct nec7210_priv *nec_priv = &e_priv->nec7210_priv; unsigned long flags; spin_lock_irqsave(&board->spinlock, flags); -// printk("%s: enter\n", __FUNCTION__); nec7210_set_reg_bits(nec_priv, IMR1, HR_DOIE | HR_DIIE, HR_DOIE | HR_DIIE); wake_up_interruptible(&board->wait); @@ -370,7 +374,6 @@ static void fmh_gpib_dma_callback(void *arg) clear_bit(DMA_WRITE_IN_PROGRESS_BN, &nec_priv->state); clear_bit(DMA_READ_IN_PROGRESS_BN, &nec_priv->state); - // printk("%s: exit\n", __FUNCTION__); spin_unlock_irqrestore(&board->spinlock, flags); } @@ -388,7 +391,7 @@ static int fmh_gpib_all_bytes_are_sent(struct fmh_priv *e_priv) return 1; } -static int fmh_gpib_dma_write(gpib_board_t *board, uint8_t *buffer, size_t length, +static int fmh_gpib_dma_write(struct gpib_board *board, uint8_t *buffer, size_t length, size_t *bytes_written) { struct fmh_priv *e_priv = board->private_data; @@ -399,14 +402,13 @@ static int fmh_gpib_dma_write(gpib_board_t *board, uint8_t *buffer, size_t lengt struct dma_async_tx_descriptor *tx_desc; *bytes_written = 0; -// printk("%s: enter\n", __FUNCTION__); if (WARN_ON_ONCE(length > e_priv->dma_buffer_size)) return -EFAULT; dmaengine_terminate_all(e_priv->dma_channel); memcpy(e_priv->dma_buffer, buffer, length); address = dma_map_single(board->dev, e_priv->dma_buffer, length, DMA_TO_DEVICE); if (dma_mapping_error(board->dev, address)) - pr_err("dma mapping error in dma write!\n"); + dev_err(board->gpib_dev, "dma mapping error in dma write!\n"); /* program dma controller */ retval = fmh_gpib_config_dma(board, 1); if (retval) @@ -415,7 +417,7 @@ static int fmh_gpib_dma_write(gpib_board_t *board, uint8_t *buffer, size_t lengt tx_desc = dmaengine_prep_slave_single(e_priv->dma_channel, address, length, DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (!tx_desc) { - pr_err("fmh_gpib_gpib: failed to allocate dma transmit descriptor\n"); + dev_err(board->gpib_dev, "failed to allocate dma transmit descriptor\n"); retval = -ENOMEM; goto cleanup; } @@ -432,19 +434,17 @@ static int fmh_gpib_dma_write(gpib_board_t *board, uint8_t *buffer, size_t lengt dma_async_issue_pending(e_priv->dma_channel); clear_bit(WRITE_READY_BN, &nec_priv->state); set_bit(DMA_WRITE_IN_PROGRESS_BN, &nec_priv->state); -// printk("%s: in spin lock\n", __FUNCTION__); + spin_unlock_irqrestore(&board->spinlock, flags); -// printk("%s: waiting for write.\n", __FUNCTION__); // suspend until message is sent if (wait_event_interruptible(board->wait, fmh_gpib_all_bytes_are_sent(e_priv) || test_bit(BUS_ERROR_BN, &nec_priv->state) || test_bit(DEV_CLEAR_BN, &nec_priv->state) || - test_bit(TIMO_NUM, &board->status))) { - dev_dbg(board->gpib_dev, "gpib write interrupted!\n"); + test_bit(TIMO_NUM, &board->status))) retval = -ERESTARTSYS; - } + if (test_bit(TIMO_NUM, &board->status)) retval = -ETIMEDOUT; if (test_and_clear_bit(DEV_CLEAR_BN, &nec_priv->state)) @@ -464,16 +464,12 @@ static int fmh_gpib_dma_write(gpib_board_t *board, uint8_t *buffer, size_t lengt fifo_xfer_counter_mask); if (WARN_ON_ONCE(*bytes_written > length)) return -EFAULT; - /* printk("length=%i, *bytes_written=%i, residue=%i, retval=%i\n", - * length, *bytes_written, get_dma_residue(e_priv->dma_channel), retval); - */ cleanup: dma_unmap_single(board->dev, address, length, DMA_TO_DEVICE); -// printk("%s: exit, retval=%d\n", __FUNCTION__, retval); return retval; } -static int fmh_gpib_accel_write(gpib_board_t *board, uint8_t *buffer, +static int fmh_gpib_accel_write(struct gpib_board *board, uint8_t *buffer, size_t length, int send_eoi, size_t *bytes_written) { struct fmh_priv *e_priv = board->private_data; @@ -484,7 +480,7 @@ static int fmh_gpib_accel_write(gpib_board_t *board, uint8_t *buffer, size_t dma_remainder = remainder; if (!e_priv->dma_channel) { - pr_err("fmh_gpib_gpib: No dma channel available, cannot do accel write."); + dev_err(board->gpib_dev, "No dma channel available, cannot do accel write."); return -ENXIO; } @@ -498,7 +494,6 @@ static int fmh_gpib_accel_write(gpib_board_t *board, uint8_t *buffer, if (send_eoi) --dma_remainder; -// printk("%s: entering while loop\n", __FUNCTION__); while (dma_remainder > 0) { size_t num_bytes; @@ -524,7 +519,7 @@ static int fmh_gpib_accel_write(gpib_board_t *board, uint8_t *buffer, //handle sending of last byte with eoi if (send_eoi) { size_t num_bytes; - // printk("%s: handling last byte\n", __FUNCTION__); + if (WARN_ON_ONCE(remainder != 1)) return -EFAULT; @@ -545,7 +540,6 @@ static int fmh_gpib_accel_write(gpib_board_t *board, uint8_t *buffer, return retval; remainder -= num_bytes; } -// printk("%s: bytes send=%i\n", __FUNCTION__, (int)(length - remainder)); return 0; } @@ -556,7 +550,7 @@ static int fmh_gpib_get_dma_residue(struct dma_chan *chan, dma_cookie_t cookie) result = dmaengine_pause(chan); if (result < 0) { - pr_err("fmh_gpib_gpib: dma pause failed?\n"); + pr_err("dma pause failed?\n"); return result; } dmaengine_tx_status(chan, cookie, &state); @@ -565,12 +559,11 @@ static int fmh_gpib_get_dma_residue(struct dma_chan *chan, dma_cookie_t cookie) return state.residue; } -static int wait_for_tx_fifo_half_empty(gpib_board_t *board) +static int wait_for_tx_fifo_half_empty(struct gpib_board *board) { struct fmh_priv *e_priv = board->private_data; struct nec7210_priv *nec_priv = &e_priv->nec7210_priv; int retval = 0; -// printk("%s: enter\n", __FUNCTION__); if (wait_event_interruptible(board->wait, (test_bit(TACS_NUM, &board->status) && @@ -584,14 +577,14 @@ static int wait_for_tx_fifo_half_empty(gpib_board_t *board) retval = -ETIMEDOUT; if (test_and_clear_bit(DEV_CLEAR_BN, &nec_priv->state)) retval = -EINTR; -// printk("%s: exit, retval=%i\n", __FUNCTION__, retval); + return retval; } /* supports writing a chunk of data whose length must fit into the hardware'd xfer counter, * called in a loop by fmh_gpib_fifo_write() */ -static int fmh_gpib_fifo_write_countable(gpib_board_t *board, uint8_t *buffer, +static int fmh_gpib_fifo_write_countable(struct gpib_board *board, uint8_t *buffer, size_t length, int send_eoi, size_t *bytes_written) { struct fmh_priv *e_priv = board->private_data; @@ -600,7 +593,6 @@ static int fmh_gpib_fifo_write_countable(gpib_board_t *board, uint8_t *buffer, unsigned int remainder; *bytes_written = 0; -// printk("%s: enter\n", __FUNCTION__); if (WARN_ON_ONCE(length > fifo_xfer_counter_mask)) return -EFAULT; @@ -635,10 +627,9 @@ static int fmh_gpib_fifo_write_countable(gpib_board_t *board, uint8_t *buffer, fmh_gpib_all_bytes_are_sent(e_priv) || test_bit(BUS_ERROR_BN, &nec_priv->state) || test_bit(DEV_CLEAR_BN, &nec_priv->state) || - test_bit(TIMO_NUM, &board->status))) { - dev_dbg(board->gpib_dev, "gpib write interrupted!\n"); + test_bit(TIMO_NUM, &board->status))) retval = -ERESTARTSYS; - } + if (test_bit(TIMO_NUM, &board->status)) retval = -ETIMEDOUT; if (test_and_clear_bit(DEV_CLEAR_BN, &nec_priv->state)) @@ -655,15 +646,11 @@ static int fmh_gpib_fifo_write_countable(gpib_board_t *board, uint8_t *buffer, fifo_xfer_counter_mask); if (WARN_ON_ONCE(*bytes_written > length)) return -EFAULT; - /* printk("length=%i, *bytes_written=%i, residue=%i, retval=%i\n", - * length, *bytes_written, get_dma_residue(e_priv->dma_channel), retval); - */ -// printk("%s: exit, retval=%d\n", __FUNCTION__, retval); return retval; } -static int fmh_gpib_fifo_write(gpib_board_t *board, uint8_t *buffer, size_t length, +static int fmh_gpib_fifo_write(struct gpib_board *board, uint8_t *buffer, size_t length, int send_eoi, size_t *bytes_written) { struct fmh_priv *e_priv = board->private_data; @@ -678,8 +665,6 @@ static int fmh_gpib_fifo_write(gpib_board_t *board, uint8_t *buffer, size_t leng clear_bit(DEV_CLEAR_BN, &nec_priv->state); // XXX FIXME -// printk("%s: entering while loop\n", __FUNCTION__); - while (remainder > 0) { size_t num_bytes; int last_pass; @@ -708,11 +693,11 @@ static int fmh_gpib_fifo_write(gpib_board_t *board, uint8_t *buffer, size_t leng if (need_resched()) schedule(); } -// printk("%s: bytes send=%i\n", __FUNCTION__, (int)(length - remainder)); + return retval; } -static int fmh_gpib_dma_read(gpib_board_t *board, uint8_t *buffer, +static int fmh_gpib_dma_read(struct gpib_board *board, uint8_t *buffer, size_t length, int *end, size_t *bytes_read) { struct fmh_priv *e_priv = board->private_data; @@ -725,10 +710,6 @@ static int fmh_gpib_dma_read(gpib_board_t *board, uint8_t *buffer, struct dma_async_tx_descriptor *tx_desc; dma_cookie_t dma_cookie; - // printk("%s: enter, bus_address=0x%x, length=%i\n", __FUNCTION__, - //(unsigned)bus_address, -// (int)length); - *bytes_read = 0; *end = 0; if (length == 0) @@ -737,7 +718,7 @@ static int fmh_gpib_dma_read(gpib_board_t *board, uint8_t *buffer, bus_address = dma_map_single(board->dev, e_priv->dma_buffer, length, DMA_FROM_DEVICE); if (dma_mapping_error(board->dev, bus_address)) - pr_err("dma mapping error in dma read!"); + dev_err(board->gpib_dev, "dma mapping error in dma read!"); /* program dma controller */ retval = fmh_gpib_config_dma(board, 0); @@ -749,7 +730,7 @@ static int fmh_gpib_dma_read(gpib_board_t *board, uint8_t *buffer, length, DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (!tx_desc) { - pr_err("fmh_gpib_gpib: failed to allocate dma transmit descriptor\n"); + dev_err(board->gpib_dev, "failed to allocate dma transmit descriptor\n"); dma_unmap_single(board->dev, bus_address, length, DMA_FROM_DEVICE); return -EIO; } @@ -769,7 +750,7 @@ static int fmh_gpib_dma_read(gpib_board_t *board, uint8_t *buffer, set_bit(DMA_READ_IN_PROGRESS_BN, &nec_priv->state); spin_unlock_irqrestore(&board->spinlock, flags); -// printk("waiting for data transfer.\n"); + // wait for data to transfer wait_retval = wait_event_interruptible(board->wait, test_bit(DMA_READ_IN_PROGRESS_BN, &nec_priv->state) @@ -777,10 +758,9 @@ static int fmh_gpib_dma_read(gpib_board_t *board, uint8_t *buffer, test_bit(RECEIVED_END_BN, &nec_priv->state) || test_bit(DEV_CLEAR_BN, &nec_priv->state) || test_bit(TIMO_NUM, &board->status)); - if (wait_retval) { - pr_warn("fmh_gpib: dma read wait interrupted\n"); + if (wait_retval) retval = -ERESTARTSYS; - } + if (test_bit(TIMO_NUM, &board->status)) retval = -ETIMEDOUT; if (test_bit(DEV_CLEAR_BN, &nec_priv->state)) @@ -825,13 +805,11 @@ static int fmh_gpib_dma_read(gpib_board_t *board, uint8_t *buffer, *end = 1; } spin_unlock_irqrestore(&board->spinlock, flags); -// printk("\tbytes_read=%i, residue=%i, end=%i, retval=%i, wait_retval=%i\n", -// *bytes_read, residue, *end, retval, wait_retval); return retval; } -static void fmh_gpib_release_rfd_holdoff(gpib_board_t *board, struct fmh_priv *e_priv) +static void fmh_gpib_release_rfd_holdoff(struct gpib_board *board, struct fmh_priv *e_priv) { struct nec7210_priv *nec_priv = &e_priv->nec7210_priv; unsigned int ext_status_1; @@ -868,7 +846,7 @@ static void fmh_gpib_release_rfd_holdoff(gpib_board_t *board, struct fmh_priv *e spin_unlock_irqrestore(&board->spinlock, flags); } -static int fmh_gpib_accel_read(gpib_board_t *board, uint8_t *buffer, size_t length, +static int fmh_gpib_accel_read(struct gpib_board *board, uint8_t *buffer, size_t length, int *end, size_t *bytes_read) { struct fmh_priv *e_priv = board->private_data; @@ -918,17 +896,13 @@ static int fmh_gpib_accel_read(gpib_board_t *board, uint8_t *buffer, size_t leng /* Read a chunk of data whose length is within the limits of the hardware's * xfer counter. Called in a loop from fmh_gpib_fifo_read(). */ -static int fmh_gpib_fifo_read_countable(gpib_board_t *board, uint8_t *buffer, +static int fmh_gpib_fifo_read_countable(struct gpib_board *board, uint8_t *buffer, size_t length, int *end, size_t *bytes_read) { struct fmh_priv *e_priv = board->private_data; struct nec7210_priv *nec_priv = &e_priv->nec7210_priv; int retval = 0; - // printk("%s: enter, bus_address=0x%x, length=%i\n", __FUNCTION__, - // (unsigned)bus_address, -// (int)length); - *bytes_read = 0; *end = 0; if (length == 0) @@ -977,13 +951,10 @@ static int fmh_gpib_fifo_read_countable(gpib_board_t *board, uint8_t *buffer, *end = 1; } -// printk("\tbytes_read=%i, end=%i, retval=%i, wait_retval=%i\n", -// *bytes_read, *end, retval, wait_retval); - return retval; } -static int fmh_gpib_fifo_read(gpib_board_t *board, uint8_t *buffer, size_t length, +static int fmh_gpib_fifo_read(struct gpib_board *board, uint8_t *buffer, size_t length, int *end, size_t *bytes_read) { struct fmh_priv *e_priv = board->private_data; @@ -1152,7 +1123,7 @@ static gpib_interface_t fmh_gpib_pci_unaccel_interface = { .return_to_local = fmh_gpib_return_to_local, }; -irqreturn_t fmh_gpib_internal_interrupt(gpib_board_t *board) +irqreturn_t fmh_gpib_internal_interrupt(struct gpib_board *board) { unsigned int status0, status1, status2, ext_status_1, fifo_status; struct fmh_priv *priv = board->private_data; @@ -1242,7 +1213,7 @@ irqreturn_t fmh_gpib_internal_interrupt(gpib_board_t *board) irqreturn_t fmh_gpib_interrupt(int irq, void *arg) { - gpib_board_t *board = arg; + struct gpib_board *board = arg; unsigned long flags; irqreturn_t retval; @@ -1252,7 +1223,7 @@ irqreturn_t fmh_gpib_interrupt(int irq, void *arg) return retval; } -static int fmh_gpib_allocate_private(gpib_board_t *board) +static int fmh_gpib_allocate_private(struct gpib_board *board) { struct fmh_priv *priv; @@ -1269,7 +1240,7 @@ static int fmh_gpib_allocate_private(gpib_board_t *board) return 0; } -static void fmh_gpib_generic_detach(gpib_board_t *board) +static void fmh_gpib_generic_detach(struct gpib_board *board) { if (board->private_data) { struct fmh_priv *e_priv = board->private_data; @@ -1283,7 +1254,7 @@ static void fmh_gpib_generic_detach(gpib_board_t *board) } // generic part of attach functions -static int fmh_gpib_generic_attach(gpib_board_t *board) +static int fmh_gpib_generic_attach(struct gpib_board *board) { struct fmh_priv *e_priv; struct nec7210_priv *nec_priv; @@ -1303,7 +1274,7 @@ static int fmh_gpib_generic_attach(gpib_board_t *board) return 0; } -static int fmh_gpib_config_dma(gpib_board_t *board, int output) +static int fmh_gpib_config_dma(struct gpib_board *board, int output) { struct fmh_priv *e_priv = board->private_data; struct dma_slave_config config; @@ -1333,7 +1304,7 @@ static int fmh_gpib_config_dma(gpib_board_t *board, int output) return dmaengine_slave_config(e_priv->dma_channel, &config); } -static int fmh_gpib_init(struct fmh_priv *e_priv, gpib_board_t *board, int handshake_mode) +static int fmh_gpib_init(struct fmh_priv *e_priv, struct gpib_board *board, int handshake_mode) { struct nec7210_priv *nec_priv = &e_priv->nec7210_priv; unsigned long flags; @@ -1376,11 +1347,11 @@ static int fmh_gpib_device_match(struct device *dev, const void *data) if (config->serial_number) return 0; - dev_notice(dev, "matched: %s\n", of_node_full_name(dev_of_node((dev)))); + dev_dbg(dev, "matched: %s\n", of_node_full_name(dev_of_node((dev)))); return 1; } -static int fmh_gpib_attach_impl(gpib_board_t *board, const gpib_board_config_t *config, +static int fmh_gpib_attach_impl(struct gpib_board *board, const gpib_board_config_t *config, unsigned int handshake_mode, int acquire_dma) { struct fmh_priv *e_priv; @@ -1393,7 +1364,7 @@ static int fmh_gpib_attach_impl(gpib_board_t *board, const gpib_board_config_t * board->dev = driver_find_device(&fmh_gpib_platform_driver.driver, NULL, (const void *)config, &fmh_gpib_device_match); if (!board->dev) { - pr_err("No matching fmh_gpib_core device was found, attach failed."); + dev_err(board->gpib_dev, "No matching fmh_gpib_core device was found, attach failed."); return -ENODEV; } // currently only used to mark the device as already attached @@ -1409,7 +1380,7 @@ static int fmh_gpib_attach_impl(gpib_board_t *board, const gpib_board_config_t * res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "gpib_control_status"); if (!res) { - dev_err(board->dev, "Unable to locate mmio resource for cb7210 gpib\n"); + dev_err(board->dev, "Unable to locate mmio resource\n"); return -ENODEV; } @@ -1422,13 +1393,13 @@ static int fmh_gpib_attach_impl(gpib_board_t *board, const gpib_board_config_t * e_priv->gpib_iomem_res = res; nec_priv->mmiobase = ioremap(e_priv->gpib_iomem_res->start, - resource_size(e_priv->gpib_iomem_res)); + resource_size(e_priv->gpib_iomem_res)); if (!nec_priv->mmiobase) { - dev_err(board->dev, "Could not map I/O memory for gpib\n"); + dev_err(board->dev, "Could not map I/O memory\n"); return -ENOMEM; } - dev_info(board->dev, "iobase %pr remapped to %p\n", - e_priv->gpib_iomem_res, nec_priv->mmiobase); + dev_dbg(board->dev, "iobase %pr remapped to %p\n", + e_priv->gpib_iomem_res, nec_priv->mmiobase); res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dma_fifos"); if (!res) { @@ -1448,14 +1419,13 @@ static int fmh_gpib_attach_impl(gpib_board_t *board, const gpib_board_config_t * dev_err(board->dev, "Could not map I/O memory for fifos\n"); return -ENOMEM; } - dev_info(board->dev, "dma fifos 0x%lx remapped to %p, length=%ld\n", - (unsigned long)e_priv->dma_port_res->start, e_priv->fifo_base, - (unsigned long)resource_size(e_priv->dma_port_res)); + dev_dbg(board->dev, "dma fifos 0x%lx remapped to %p, length=%ld\n", + (unsigned long)e_priv->dma_port_res->start, e_priv->fifo_base, + (unsigned long)resource_size(e_priv->dma_port_res)); irq = platform_get_irq(pdev, 0); - pr_info("gpib: irq %d\n", irq); if (irq < 0) { - dev_err(board->dev, "fmh_gpib_gpib: request for IRQ failed\n"); + dev_err(board->dev, "request for IRQ failed\n"); return -EBUSY; } retval = request_irq(irq, fmh_gpib_interrupt, IRQF_SHARED, pdev->name, board); @@ -1484,17 +1454,17 @@ static int fmh_gpib_attach_impl(gpib_board_t *board, const gpib_board_config_t * return fmh_gpib_init(e_priv, board, handshake_mode); } -int fmh_gpib_attach_holdoff_all(gpib_board_t *board, const gpib_board_config_t *config) +int fmh_gpib_attach_holdoff_all(struct gpib_board *board, const gpib_board_config_t *config) { return fmh_gpib_attach_impl(board, config, HR_HLDA, 0); } -int fmh_gpib_attach_holdoff_end(gpib_board_t *board, const gpib_board_config_t *config) +int fmh_gpib_attach_holdoff_end(struct gpib_board *board, const gpib_board_config_t *config) { return fmh_gpib_attach_impl(board, config, HR_HLDE, 1); } -void fmh_gpib_detach(gpib_board_t *board) +void fmh_gpib_detach(struct gpib_board *board) { struct fmh_priv *e_priv = board->private_data; struct nec7210_priv *nec_priv; @@ -1527,7 +1497,7 @@ void fmh_gpib_detach(gpib_board_t *board) fmh_gpib_generic_detach(board); } -static int fmh_gpib_pci_attach_impl(gpib_board_t *board, const gpib_board_config_t *config, +static int fmh_gpib_pci_attach_impl(struct gpib_board *board, const gpib_board_config_t *config, unsigned int handshake_mode) { struct fmh_priv *e_priv; @@ -1546,7 +1516,7 @@ static int fmh_gpib_pci_attach_impl(gpib_board_t *board, const gpib_board_config pci_device = gpib_pci_get_device(config, BOGUS_PCI_VENDOR_ID_FLUKE, BOGUS_PCI_DEVICE_ID_FLUKE_BLADERUNNER, NULL); if (!pci_device) { - pr_err("No matching fmh_gpib_core pci device was found, attach failed."); + dev_err(board->gpib_dev, "No matching fmh_gpib_core pci device was found, attach failed."); return -ENODEV; } board->dev = &pci_device->dev; @@ -1563,34 +1533,32 @@ static int fmh_gpib_pci_attach_impl(gpib_board_t *board, const gpib_board_config return -EIO; } e_priv->gpib_iomem_res = &pci_device->resource[gpib_control_status_pci_resource_index]; - e_priv->dma_port_res = &pci_device->resource[gpib_fifo_pci_resource_index]; + e_priv->dma_port_res = &pci_device->resource[gpib_fifo_pci_resource_index]; nec_priv->mmiobase = ioremap(pci_resource_start(pci_device, - gpib_control_status_pci_resource_index), - pci_resource_len(pci_device, - gpib_control_status_pci_resource_index)); - dev_info(board->dev, "base address for gpib control/status registers remapped to 0x%p\n", - nec_priv->mmiobase); + gpib_control_status_pci_resource_index), + pci_resource_len(pci_device, + gpib_control_status_pci_resource_index)); + dev_dbg(board->dev, "base address for gpib control/status registers remapped to 0x%p\n", + nec_priv->mmiobase); if (e_priv->dma_port_res->flags & IORESOURCE_MEM) { e_priv->fifo_base = ioremap(pci_resource_start(pci_device, gpib_fifo_pci_resource_index), pci_resource_len(pci_device, gpib_fifo_pci_resource_index)); - dev_info(board->dev, "base address for gpib fifo registers remapped to 0x%p\n", - e_priv->fifo_base); + dev_dbg(board->dev, "base address for gpib fifo registers remapped to 0x%p\n", + e_priv->fifo_base); } else { e_priv->fifo_base = NULL; - dev_info(board->dev, "hardware has no gpib fifo registers.\n"); + dev_dbg(board->dev, "hardware has no gpib fifo registers.\n"); } if (pci_device->irq) { retval = request_irq(pci_device->irq, fmh_gpib_interrupt, IRQF_SHARED, KBUILD_MODNAME, board); if (retval) { - dev_err(board->dev, - "cannot register interrupt handler err=%d\n", - retval); + dev_err(board->dev, "cannot register interrupt handler err=%d\n", retval); return retval; } } @@ -1602,12 +1570,12 @@ static int fmh_gpib_pci_attach_impl(gpib_board_t *board, const gpib_board_config return fmh_gpib_init(e_priv, board, handshake_mode); } -int fmh_gpib_pci_attach_holdoff_all(gpib_board_t *board, const gpib_board_config_t *config) +int fmh_gpib_pci_attach_holdoff_all(struct gpib_board *board, const gpib_board_config_t *config) { return fmh_gpib_pci_attach_impl(board, config, HR_HLDA); } -int fmh_gpib_pci_attach_holdoff_end(gpib_board_t *board, const gpib_board_config_t *config) +int fmh_gpib_pci_attach_holdoff_end(struct gpib_board *board, const gpib_board_config_t *config) { int retval; struct fmh_priv *e_priv; @@ -1615,13 +1583,13 @@ int fmh_gpib_pci_attach_holdoff_end(gpib_board_t *board, const gpib_board_config retval = fmh_gpib_pci_attach_impl(board, config, HR_HLDE); e_priv = board->private_data; if (retval == 0 && e_priv && e_priv->supports_fifo_interrupts == 0) { - pr_err("fmh_gpib: your fmh_gpib_core does not appear to support fifo interrupts. Try the fmh_gpib_pci_unaccel board type instead."); + dev_err(board->gpib_dev, "your fmh_gpib_core does not appear to support fifo interrupts. Try the fmh_gpib_pci_unaccel board type instead."); return -EIO; } return retval; } -void fmh_gpib_pci_detach(gpib_board_t *board) +void fmh_gpib_pci_detach(struct gpib_board *board) { struct fmh_priv *e_priv = board->private_data; struct nec7210_priv *nec_priv; @@ -1662,7 +1630,7 @@ MODULE_DEVICE_TABLE(of, fmh_gpib_of_match); static struct platform_driver fmh_gpib_platform_driver = { .driver = { - .name = "fmh_gpib", + .name = DRV_NAME, .owner = THIS_MODULE, .of_match_table = fmh_gpib_of_match, }, @@ -1681,7 +1649,7 @@ static const struct pci_device_id fmh_gpib_pci_match[] = { MODULE_DEVICE_TABLE(pci, fmh_gpib_pci_match); static struct pci_driver fmh_gpib_pci_driver = { - .name = "fmh_gpib", + .name = DRV_NAME, .id_table = fmh_gpib_pci_match, .probe = &fmh_gpib_pci_probe }; @@ -1692,37 +1660,37 @@ static int __init fmh_gpib_init_module(void) result = platform_driver_register(&fmh_gpib_platform_driver); if (result) { - pr_err("fmh_gpib: platform_driver_register failed: error = %d\n", result); + pr_err("platform_driver_register failed: error = %d\n", result); return result; } result = pci_register_driver(&fmh_gpib_pci_driver); if (result) { - pr_err("fmh_gpib: pci_register_driver failed: error = %d\n", result); + pr_err("pci_register_driver failed: error = %d\n", result); goto err_pci_driver; } result = gpib_register_driver(&fmh_gpib_unaccel_interface, THIS_MODULE); if (result) { - pr_err("fmh_gpib: gpib_register_driver failed: error = %d\n", result); + pr_err("gpib_register_driver failed: error = %d\n", result); goto err_unaccel; } result = gpib_register_driver(&fmh_gpib_interface, THIS_MODULE); if (result) { - pr_err("fmh_gpib: gpib_register_driver failed: error = %d\n", result); + pr_err("gpib_register_driver failed: error = %d\n", result); goto err_interface; } result = gpib_register_driver(&fmh_gpib_pci_unaccel_interface, THIS_MODULE); if (result) { - pr_err("fmh_gpib: gpib_register_driver failed: error = %d\n", result); + pr_err("gpib_register_driver failed: error = %d\n", result); goto err_pci_unaccel; } result = gpib_register_driver(&fmh_gpib_pci_interface, THIS_MODULE); if (result) { - pr_err("fmh_gpib: gpib_register_driver failed: error = %d\n", result); + pr_err("gpib_register_driver failed: error = %d\n", result); goto err_pci; }
diff --git a/drivers/staging/gpib/gpio/gpib_bitbang.c b/drivers/staging/gpib/gpio/gpib_bitbang.c index 828c99e..86bdd38 100644 --- a/drivers/staging/gpib/gpio/gpib_bitbang.c +++ b/drivers/staging/gpib/gpio/gpib_bitbang.c
@@ -25,6 +25,8 @@ * device support (non master operation) */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#define dev_fmt pr_fmt #define NAME KBUILD_MODNAME #define ENABLE_IRQ(IRQ, TYPE) irq_set_irq_type(IRQ, TYPE) @@ -41,7 +43,7 @@ */ #define dbg_printk(level, frm, ...) \ do { if (debug >= (level)) \ - pr_info("%s:%s - " frm, NAME, __func__, ## __VA_ARGS__); } \ + dev_dbg(board->gpib_dev, frm, ## __VA_ARGS__); } \ while (0) #define LINVAL gpiod_get_value(DAV), \ @@ -316,13 +318,14 @@ struct bb_priv { }; static inline long usec_diff(struct timespec64 *a, struct timespec64 *b); -static void bb_buffer_print(unsigned char *buffer, size_t length, int cmd, int eoi); +static void bb_buffer_print(struct gpib_board *board, unsigned char *buffer, size_t length, + int cmd, int eoi); static void set_data_lines(u8 byte); static u8 get_data_lines(void); static void set_data_lines_input(void); static void set_data_lines_output(void); static inline int check_for_eos(struct bb_priv *priv, uint8_t byte); -static void set_atn(struct bb_priv *priv, int atn_asserted); +static void set_atn(struct gpib_board *board, int atn_asserted); static inline void SET_DIR_WRITE(struct bb_priv *priv); static inline void SET_DIR_READ(struct bb_priv *priv); @@ -334,11 +337,7 @@ MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("GPIB helper functions for bitbanging I/O"); /**** global variables ****/ -#ifdef CONFIG_GPIB_DEBUG -static int debug = 1; -#else static int debug; -#endif module_param(debug, int, 0644); static char printable(char x) @@ -354,7 +353,7 @@ static char printable(char x) * * ***************************************************************************/ -static int bb_read(gpib_board_t *board, uint8_t *buffer, size_t length, +static int bb_read(struct gpib_board *board, uint8_t *buffer, size_t length, int *end, size_t *bytes_read) { struct bb_priv *priv = board->private_data; @@ -426,7 +425,7 @@ static int bb_read(gpib_board_t *board, uint8_t *buffer, size_t length, static irqreturn_t bb_DAV_interrupt(int irq, void *arg) { - gpib_board_t *board = arg; + struct gpib_board *board = arg; struct bb_priv *priv = board->private_data; int val; unsigned long flags; @@ -492,7 +491,7 @@ static irqreturn_t bb_DAV_interrupt(int irq, void *arg) * * ***************************************************************************/ -static int bb_write(gpib_board_t *board, uint8_t *buffer, size_t length, +static int bb_write(struct gpib_board *board, uint8_t *buffer, size_t length, int send_eoi, size_t *bytes_written) { unsigned long flags; @@ -508,7 +507,7 @@ static int bb_write(gpib_board_t *board, uint8_t *buffer, size_t length, board, mutex_is_locked(&board->user_mutex), length); if (debug > 1) - bb_buffer_print(buffer, length, priv->cmd, send_eoi); + bb_buffer_print(board, buffer, length, priv->cmd, send_eoi); priv->count = 0; priv->phase = 300; @@ -550,7 +549,6 @@ static int bb_write(gpib_board_t *board, uint8_t *buffer, size_t length, dbg_printk(1, "timeout after %zu/%zu at %d " LINFMT " eoi: %d\n", priv->w_cnt, length, priv->phase, LINVAL, send_eoi); } else { - // dbg_printk(1,"written %zu\n", priv->w_cnt); retval = priv->w_cnt; } } else { @@ -582,7 +580,7 @@ static int bb_write(gpib_board_t *board, uint8_t *buffer, size_t length, static irqreturn_t bb_NRFD_interrupt(int irq, void *arg) { - gpib_board_t *board = arg; + struct gpib_board *board = arg; struct bb_priv *priv = board->private_data; unsigned long flags; int nrfd; @@ -655,7 +653,7 @@ static irqreturn_t bb_NRFD_interrupt(int irq, void *arg) static irqreturn_t bb_NDAC_interrupt(int irq, void *arg) { - gpib_board_t *board = arg; + struct gpib_board *board = arg; struct bb_priv *priv = board->private_data; unsigned long flags; int ndac; @@ -716,7 +714,7 @@ static irqreturn_t bb_NDAC_interrupt(int irq, void *arg) static irqreturn_t bb_SRQ_interrupt(int irq, void *arg) { - gpib_board_t *board = arg; + struct gpib_board *board = arg; int val = gpiod_get_value(SRQ); @@ -730,7 +728,7 @@ static irqreturn_t bb_SRQ_interrupt(int irq, void *arg) return IRQ_HANDLED; } -static int bb_command(gpib_board_t *board, uint8_t *buffer, +static int bb_command(struct gpib_board *board, uint8_t *buffer, size_t length, size_t *bytes_written) { size_t ret; @@ -811,7 +809,8 @@ static char *cmd_string[32] = { "CFE" // 0x1f }; -static void bb_buffer_print(unsigned char *buffer, size_t length, int cmd, int eoi) +static void bb_buffer_print(struct gpib_board *board, unsigned char *buffer, size_t length, + int cmd, int eoi) { int i; @@ -843,11 +842,13 @@ static void bb_buffer_print(unsigned char *buffer, size_t length, int cmd, int e * STATUS Management * * * ***************************************************************************/ -static void set_atn(struct bb_priv *priv, int atn_asserted) +static void set_atn(struct gpib_board *board, int atn_asserted) { + struct bb_priv *priv = board->private_data; + if (priv->listener_state != listener_idle && priv->talker_state != talker_idle) { - dbg_printk(0, "listener/talker state machine conflict\n"); + dev_err(board->gpib_dev, "listener/talker state machine conflict\n"); } if (atn_asserted) { if (priv->listener_state == listener_active) @@ -866,22 +867,22 @@ static void set_atn(struct bb_priv *priv, int atn_asserted) priv->atn_asserted = atn_asserted; } -static int bb_take_control(gpib_board_t *board, int synchronous) +static int bb_take_control(struct gpib_board *board, int synchronous) { dbg_printk(2, "%d\n", synchronous); - set_atn(board->private_data, 1); + set_atn(board, 1); set_bit(CIC_NUM, &board->status); return 0; } -static int bb_go_to_standby(gpib_board_t *board) +static int bb_go_to_standby(struct gpib_board *board) { dbg_printk(2, "\n"); - set_atn(board->private_data, 0); + set_atn(board, 0); return 0; } -static void bb_request_system_control(gpib_board_t *board, int request_control) +static void bb_request_system_control(struct gpib_board *board, int request_control) { dbg_printk(2, "%d\n", request_control); if (request_control) { @@ -893,7 +894,7 @@ static void bb_request_system_control(gpib_board_t *board, int request_control) } } -static void bb_interface_clear(gpib_board_t *board, int assert) +static void bb_interface_clear(struct gpib_board *board, int assert) { struct bb_priv *priv = board->private_data; @@ -907,7 +908,7 @@ static void bb_interface_clear(gpib_board_t *board, int assert) } } -static void bb_remote_enable(gpib_board_t *board, int enable) +static void bb_remote_enable(struct gpib_board *board, int enable) { dbg_printk(2, "%d\n", enable); if (enable) { @@ -919,7 +920,7 @@ static void bb_remote_enable(gpib_board_t *board, int enable) } } -static int bb_enable_eos(gpib_board_t *board, uint8_t eos_byte, int compare_8_bits) +static int bb_enable_eos(struct gpib_board *board, uint8_t eos_byte, int compare_8_bits) { struct bb_priv *priv = board->private_data; @@ -932,7 +933,7 @@ static int bb_enable_eos(gpib_board_t *board, uint8_t eos_byte, int compare_8_bi return 0; } -static void bb_disable_eos(gpib_board_t *board) +static void bb_disable_eos(struct gpib_board *board) { struct bb_priv *priv = board->private_data; @@ -940,7 +941,7 @@ static void bb_disable_eos(gpib_board_t *board) priv->eos_flags &= ~REOS; } -static unsigned int bb_update_status(gpib_board_t *board, unsigned int clear_mask) +static unsigned int bb_update_status(struct gpib_board *board, unsigned int clear_mask) { struct bb_priv *priv = board->private_data; @@ -971,14 +972,14 @@ static unsigned int bb_update_status(gpib_board_t *board, unsigned int clear_mas return board->status; } -static int bb_primary_address(gpib_board_t *board, unsigned int address) +static int bb_primary_address(struct gpib_board *board, unsigned int address) { dbg_printk(2, "%d\n", address); board->pad = address; return 0; } -static int bb_secondary_address(gpib_board_t *board, unsigned int address, int enable) +static int bb_secondary_address(struct gpib_board *board, unsigned int address, int enable) { dbg_printk(2, "%d %d\n", address, enable); if (enable) @@ -986,33 +987,29 @@ static int bb_secondary_address(gpib_board_t *board, unsigned int address, int e return 0; } -static int bb_parallel_poll(gpib_board_t *board, uint8_t *result) +static int bb_parallel_poll(struct gpib_board *board, uint8_t *result) { - dbg_printk(1, "%s\n", "not implemented"); - return -EPERM; + return -ENOENT; } -static void bb_parallel_poll_configure(gpib_board_t *board, uint8_t config) -{ - dbg_printk(1, "%s\n", "not implemented"); -} - -static void bb_parallel_poll_response(gpib_board_t *board, int ist) +static void bb_parallel_poll_configure(struct gpib_board *board, uint8_t config) { } -static void bb_serial_poll_response(gpib_board_t *board, uint8_t status) +static void bb_parallel_poll_response(struct gpib_board *board, int ist) { - dbg_printk(1, "%s\n", "not implemented"); } -static uint8_t bb_serial_poll_status(gpib_board_t *board) +static void bb_serial_poll_response(struct gpib_board *board, uint8_t status) { - dbg_printk(1, "%s\n", "not implemented"); - return 0; // -ENOSYS; } -static unsigned int bb_t1_delay(gpib_board_t *board, unsigned int nano_sec) +static uint8_t bb_serial_poll_status(struct gpib_board *board) +{ + return 0; // -ENOENT; +} + +static int bb_t1_delay(struct gpib_board *board, unsigned int nano_sec) { struct bb_priv *priv = board->private_data; @@ -1028,33 +1025,30 @@ static unsigned int bb_t1_delay(gpib_board_t *board, unsigned int nano_sec) return priv->t1_delay; } -static void bb_return_to_local(gpib_board_t *board) +static void bb_return_to_local(struct gpib_board *board) { - dbg_printk(1, "%s\n", "not implemented"); } -static int bb_line_status(const gpib_board_t *board) +static int bb_line_status(const struct gpib_board *board) { - int line_status = ValidALL; - -// dbg_printk(1,"\n"); + int line_status = VALID_ALL; if (gpiod_get_value(REN) == 0) - line_status |= BusREN; + line_status |= BUS_REN; if (gpiod_get_value(IFC) == 0) - line_status |= BusIFC; + line_status |= BUS_IFC; if (gpiod_get_value(NDAC) == 0) - line_status |= BusNDAC; + line_status |= BUS_NDAC; if (gpiod_get_value(NRFD) == 0) - line_status |= BusNRFD; + line_status |= BUS_NRFD; if (gpiod_get_value(DAV) == 0) - line_status |= BusDAV; + line_status |= BUS_DAV; if (gpiod_get_value(EOI) == 0) - line_status |= BusEOI; + line_status |= BUS_EOI; if (gpiod_get_value(_ATN) == 0) - line_status |= BusATN; + line_status |= BUS_ATN; if (gpiod_get_value(SRQ) == 0) - line_status |= BusSRQ; + line_status |= BUS_SRQ; dbg_printk(2, "status lines: %4x\n", line_status); @@ -1067,7 +1061,7 @@ static int bb_line_status(const gpib_board_t *board) * * ***************************************************************************/ -static int allocate_private(gpib_board_t *board) +static int allocate_private(struct gpib_board *board) { board->private_data = kzalloc(sizeof(struct bb_priv), GFP_KERNEL); if (!board->private_data) @@ -1075,13 +1069,13 @@ static int allocate_private(gpib_board_t *board) return 0; } -static void free_private(gpib_board_t *board) +static void free_private(struct gpib_board *board) { kfree(board->private_data); board->private_data = NULL; } -static int bb_get_irq(gpib_board_t *board, char *name, +static int bb_get_irq(struct gpib_board *board, char *name, struct gpio_desc *gpio, int *irq, irq_handler_t handler, irq_handler_t thread_fn, unsigned long flags) { @@ -1091,11 +1085,11 @@ static int bb_get_irq(gpib_board_t *board, char *name, *irq = gpiod_to_irq(gpio); dbg_printk(2, "IRQ %s: %d\n", name, *irq); if (*irq < 0) { - dbg_printk(0, "gpib: can't get IRQ for %s\n", name); + dev_err(board->gpib_dev, "can't get IRQ for %s\n", name); return -1; } if (request_threaded_irq(*irq, handler, thread_fn, flags, name, board)) { - dbg_printk(0, "gpib: can't request IRQ for %s %d\n", name, *irq); + dev_err(board->gpib_dev, "can't request IRQ for %s %d\n", name, *irq); *irq = 0; return -1; } @@ -1103,7 +1097,7 @@ static int bb_get_irq(gpib_board_t *board, char *name, return 0; } -static void bb_free_irq(gpib_board_t *board, int *irq, char *name) +static void bb_free_irq(struct gpib_board *board, int *irq, char *name) { if (*irq) { free_irq(*irq, board); @@ -1124,7 +1118,7 @@ static void release_gpios(void) } } -static int allocate_gpios(gpib_board_t *board) +static int allocate_gpios(struct gpib_board *board) { int j, retval = 0; bool error = false; @@ -1163,8 +1157,8 @@ static int allocate_gpios(gpib_board_t *board) gpiod_add_lookup_table(lookup_table); goto try_again; } - dbg_printk(0, "Unable to obtain gpio descriptor for pin %d error %ld\n", - gpios_vector[j], PTR_ERR(desc)); + dev_err(board->gpib_dev, "Unable to obtain gpio descriptor for pin %d error %ld\n", + gpios_vector[j], PTR_ERR(desc)); error = true; break; } @@ -1182,7 +1176,7 @@ static int allocate_gpios(gpib_board_t *board) return retval; } -static void bb_detach(gpib_board_t *board) +static void bb_detach(struct gpib_board *board) { struct bb_priv *priv = board->private_data; @@ -1212,7 +1206,7 @@ static void bb_detach(gpib_board_t *board) free_private(board); } -static int bb_attach(gpib_board_t *board, const gpib_board_config_t *config) +static int bb_attach(struct gpib_board *board, const gpib_board_config_t *config) { struct bb_priv *priv; int retval = 0; @@ -1253,7 +1247,7 @@ static int bb_attach(gpib_board_t *board, const gpib_board_config_t *config) gpios_vector[&(DC) - &all_descriptors[0]] = -1; gpios_vector[&(ACT_LED) - &all_descriptors[0]] = -1; } else { - dbg_printk(0, "Unrecognized pin mapping.\n"); + dev_err(board->gpib_dev, "Unrecognized pin map %s\n", pin_map); goto bb_attach_fail; } dbg_printk(0, "Using pin map \"%s\" %s\n", pin_map, (sn7516x) ? @@ -1344,19 +1338,15 @@ static int __init bb_init_module(void) int result = gpib_register_driver(&bb_interface, THIS_MODULE); if (result) { - pr_err("gpib_bitbang: gpib_register_driver failed: error = %d\n", result); + pr_err("gpib_register_driver failed: error = %d\n", result); return result; } - dbg_printk(0, "module loaded with pin map \"%s\"%s\n", - pin_map, (sn7516x_used) ? " and SN7516x driver support" : ""); return 0; } static void __exit bb_exit_module(void) { - dbg_printk(0, "module unloaded!"); - gpib_unregister_driver(&bb_interface); }
diff --git a/drivers/staging/gpib/hp_82335/hp82335.c b/drivers/staging/gpib/hp_82335/hp82335.c index 700d1ba..fd23b1c 100644 --- a/drivers/staging/gpib/hp_82335/hp82335.c +++ b/drivers/staging/gpib/hp_82335/hp82335.c
@@ -8,6 +8,10 @@ * implement recovery from bus errors (if necessary) */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#define dev_fmt pr_fmt +#define DRV_NAME KBUILD_MODNAME + #include "hp82335.h" #include <linux/io.h> #include <linux/ioport.h> @@ -20,153 +24,155 @@ MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("GPIB driver for HP 82335 interface cards"); -static int hp82335_attach(gpib_board_t *board, const gpib_board_config_t *config); - -static void hp82335_detach(gpib_board_t *board); +static int hp82335_attach(struct gpib_board *board, const gpib_board_config_t *config); +static void hp82335_detach(struct gpib_board *board); +static irqreturn_t hp82335_interrupt(int irq, void *arg); // wrappers for interface functions -int hp82335_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *end, size_t *bytes_read) +static int hp82335_read(struct gpib_board *board, uint8_t *buffer, size_t length, + int *end, size_t *bytes_read) { struct hp82335_priv *priv = board->private_data; return tms9914_read(board, &priv->tms9914_priv, buffer, length, end, bytes_read); } -int hp82335_write(gpib_board_t *board, uint8_t *buffer, size_t length, int send_eoi, - size_t *bytes_written) +static int hp82335_write(struct gpib_board *board, uint8_t *buffer, size_t length, int send_eoi, + size_t *bytes_written) { struct hp82335_priv *priv = board->private_data; return tms9914_write(board, &priv->tms9914_priv, buffer, length, send_eoi, bytes_written); } -int hp82335_command(gpib_board_t *board, uint8_t *buffer, size_t length, size_t *bytes_written) +static int hp82335_command(struct gpib_board *board, uint8_t *buffer, size_t length, + size_t *bytes_written) { struct hp82335_priv *priv = board->private_data; return tms9914_command(board, &priv->tms9914_priv, buffer, length, bytes_written); } -int hp82335_take_control(gpib_board_t *board, int synchronous) +static int hp82335_take_control(struct gpib_board *board, int synchronous) { struct hp82335_priv *priv = board->private_data; return tms9914_take_control(board, &priv->tms9914_priv, synchronous); } -int hp82335_go_to_standby(gpib_board_t *board) +static int hp82335_go_to_standby(struct gpib_board *board) { struct hp82335_priv *priv = board->private_data; return tms9914_go_to_standby(board, &priv->tms9914_priv); } -void hp82335_request_system_control(gpib_board_t *board, int request_control) +static void hp82335_request_system_control(struct gpib_board *board, int request_control) { struct hp82335_priv *priv = board->private_data; tms9914_request_system_control(board, &priv->tms9914_priv, request_control); } -void hp82335_interface_clear(gpib_board_t *board, int assert) +static void hp82335_interface_clear(struct gpib_board *board, int assert) { struct hp82335_priv *priv = board->private_data; tms9914_interface_clear(board, &priv->tms9914_priv, assert); } -void hp82335_remote_enable(gpib_board_t *board, int enable) +static void hp82335_remote_enable(struct gpib_board *board, int enable) { struct hp82335_priv *priv = board->private_data; tms9914_remote_enable(board, &priv->tms9914_priv, enable); } -int hp82335_enable_eos(gpib_board_t *board, uint8_t eos_byte, int compare_8_bits) +static int hp82335_enable_eos(struct gpib_board *board, uint8_t eos_byte, int compare_8_bits) { struct hp82335_priv *priv = board->private_data; return tms9914_enable_eos(board, &priv->tms9914_priv, eos_byte, compare_8_bits); } -void hp82335_disable_eos(gpib_board_t *board) +static void hp82335_disable_eos(struct gpib_board *board) { struct hp82335_priv *priv = board->private_data; tms9914_disable_eos(board, &priv->tms9914_priv); } -unsigned int hp82335_update_status(gpib_board_t *board, unsigned int clear_mask) +static unsigned int hp82335_update_status(struct gpib_board *board, unsigned int clear_mask) { struct hp82335_priv *priv = board->private_data; return tms9914_update_status(board, &priv->tms9914_priv, clear_mask); } -int hp82335_primary_address(gpib_board_t *board, unsigned int address) +static int hp82335_primary_address(struct gpib_board *board, unsigned int address) { struct hp82335_priv *priv = board->private_data; return tms9914_primary_address(board, &priv->tms9914_priv, address); } -int hp82335_secondary_address(gpib_board_t *board, unsigned int address, int enable) +static int hp82335_secondary_address(struct gpib_board *board, unsigned int address, int enable) { struct hp82335_priv *priv = board->private_data; return tms9914_secondary_address(board, &priv->tms9914_priv, address, enable); } -int hp82335_parallel_poll(gpib_board_t *board, uint8_t *result) +static int hp82335_parallel_poll(struct gpib_board *board, uint8_t *result) { struct hp82335_priv *priv = board->private_data; return tms9914_parallel_poll(board, &priv->tms9914_priv, result); } -void hp82335_parallel_poll_configure(gpib_board_t *board, uint8_t config) +static void hp82335_parallel_poll_configure(struct gpib_board *board, uint8_t config) { struct hp82335_priv *priv = board->private_data; tms9914_parallel_poll_configure(board, &priv->tms9914_priv, config); } -void hp82335_parallel_poll_response(gpib_board_t *board, int ist) +static void hp82335_parallel_poll_response(struct gpib_board *board, int ist) { struct hp82335_priv *priv = board->private_data; tms9914_parallel_poll_response(board, &priv->tms9914_priv, ist); } -void hp82335_serial_poll_response(gpib_board_t *board, uint8_t status) +static void hp82335_serial_poll_response(struct gpib_board *board, uint8_t status) { struct hp82335_priv *priv = board->private_data; tms9914_serial_poll_response(board, &priv->tms9914_priv, status); } -static uint8_t hp82335_serial_poll_status(gpib_board_t *board) +static uint8_t hp82335_serial_poll_status(struct gpib_board *board) { struct hp82335_priv *priv = board->private_data; return tms9914_serial_poll_status(board, &priv->tms9914_priv); } -static int hp82335_line_status(const gpib_board_t *board) +static int hp82335_line_status(const struct gpib_board *board) { struct hp82335_priv *priv = board->private_data; return tms9914_line_status(board, &priv->tms9914_priv); } -static unsigned int hp82335_t1_delay(gpib_board_t *board, unsigned int nano_sec) +static int hp82335_t1_delay(struct gpib_board *board, unsigned int nano_sec) { struct hp82335_priv *priv = board->private_data; return tms9914_t1_delay(board, &priv->tms9914_priv, nano_sec); } -void hp82335_return_to_local(gpib_board_t *board) +static void hp82335_return_to_local(struct gpib_board *board) { struct hp82335_priv *priv = board->private_data; @@ -201,7 +207,7 @@ static gpib_interface_t hp82335_interface = { .return_to_local = hp82335_return_to_local, }; -int hp82335_allocate_private(gpib_board_t *board) +static int hp82335_allocate_private(struct gpib_board *board) { board->private_data = kzalloc(sizeof(struct hp82335_priv), GFP_KERNEL); if (!board->private_data) @@ -209,7 +215,7 @@ int hp82335_allocate_private(gpib_board_t *board) return 0; } -void hp82335_free_private(gpib_board_t *board) +static void hp82335_free_private(struct gpib_board *board) { kfree(board->private_data); board->private_data = NULL; @@ -237,7 +243,7 @@ static void hp82335_clear_interrupt(struct hp82335_priv *hp_priv) writeb(0, tms_priv->mmiobase + HPREG_INTR_CLEAR); } -int hp82335_attach(gpib_board_t *board, const gpib_board_config_t *config) +static int hp82335_attach(struct gpib_board *board, const gpib_board_config_t *config) { struct hp82335_priv *hp_priv; struct tms9914_priv *tms_priv; @@ -272,26 +278,23 @@ int hp82335_attach(gpib_board_t *board, const gpib_board_config_t *config) case 0xfc000: break; default: - pr_err("hp82335: invalid base io address 0x%u\n", config->ibbase); + dev_err(board->gpib_dev, "invalid base io address 0x%x\n", config->ibbase); return -EINVAL; } if (!request_mem_region(upper_iomem_base, hp82335_upper_iomem_size, "hp82335")) { - pr_err("hp82335: failed to allocate io memory region 0x%lx-0x%lx\n", - upper_iomem_base, upper_iomem_base + hp82335_upper_iomem_size - 1); + dev_err(board->gpib_dev, "failed to allocate io memory region 0x%lx-0x%lx\n", + upper_iomem_base, upper_iomem_base + hp82335_upper_iomem_size - 1); return -EBUSY; } hp_priv->raw_iobase = upper_iomem_base; tms_priv->mmiobase = ioremap(upper_iomem_base, hp82335_upper_iomem_size); - pr_info("hp82335: upper half of 82335 iomem region 0x%lx remapped to 0x%p\n", - hp_priv->raw_iobase, tms_priv->mmiobase); - retval = request_irq(config->ibirq, hp82335_interrupt, 0, "hp82335", board); + retval = request_irq(config->ibirq, hp82335_interrupt, 0, DRV_NAME, board); if (retval) { - pr_err("hp82335: can't request IRQ %d\n", config->ibirq); + dev_err(board->gpib_dev, "can't request IRQ %d\n", config->ibirq); return retval; } hp_priv->irq = config->ibirq; - pr_info("hp82335: IRQ %d\n", config->ibirq); tms9914_board_reset(tms_priv); @@ -304,7 +307,7 @@ int hp82335_attach(gpib_board_t *board, const gpib_board_config_t *config) return 0; } -void hp82335_detach(gpib_board_t *board) +static void hp82335_detach(struct gpib_board *board) { struct hp82335_priv *hp_priv = board->private_data; struct tms9914_priv *tms_priv; @@ -329,7 +332,7 @@ static int __init hp82335_init_module(void) int result = gpib_register_driver(&hp82335_interface, THIS_MODULE); if (result) { - pr_err("hp82335: gpib_register_driver failed: error = %d\n", result); + pr_err("gpib_register_driver failed: error = %d\n", result); return result; } @@ -348,10 +351,10 @@ module_exit(hp82335_exit_module); * GPIB interrupt service routines */ -irqreturn_t hp82335_interrupt(int irq, void *arg) +static irqreturn_t hp82335_interrupt(int irq, void *arg) { int status1, status2; - gpib_board_t *board = arg; + struct gpib_board *board = arg; struct hp82335_priv *priv = board->private_data; unsigned long flags; irqreturn_t retval;
diff --git a/drivers/staging/gpib/hp_82335/hp82335.h b/drivers/staging/gpib/hp_82335/hp82335.h index 4b185d7..0c252a7 100644 --- a/drivers/staging/gpib/hp_82335/hp82335.h +++ b/drivers/staging/gpib/hp_82335/hp82335.h
@@ -17,36 +17,6 @@ struct hp82335_priv { unsigned long raw_iobase; }; -// interface functions -int hp82335_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *end, size_t *bytes_read); -int hp82335_write(gpib_board_t *board, uint8_t *buffer, size_t length, - int send_eoi, size_t *bytes_written); -int hp82335_command(gpib_board_t *board, uint8_t *buffer, size_t length, size_t *bytes_written); -int hp82335_take_control(gpib_board_t *board, int synchronous); -int hp82335_go_to_standby(gpib_board_t *board); -void hp82335_request_system_control(gpib_board_t *board, int request_control); -void hp82335_interface_clear(gpib_board_t *board, int assert); -void hp82335_remote_enable(gpib_board_t *board, int enable); -int hp82335_enable_eos(gpib_board_t *board, uint8_t eos_byte, int - compare_8_bits); -void hp82335_disable_eos(gpib_board_t *board); -unsigned int hp82335_update_status(gpib_board_t *board, unsigned int clear_mask); -int hp82335_primary_address(gpib_board_t *board, unsigned int address); -int hp82335_secondary_address(gpib_board_t *board, unsigned int address, int - enable); -int hp82335_parallel_poll(gpib_board_t *board, uint8_t *result); -void hp82335_parallel_poll_configure(gpib_board_t *board, uint8_t config); -void hp82335_parallel_poll_response(gpib_board_t *board, int ist); -void hp82335_serial_poll_response(gpib_board_t *board, uint8_t status); -void hp82335_return_to_local(gpib_board_t *board); - -// interrupt service routines -irqreturn_t hp82335_interrupt(int irq, void *arg); - -// utility functions -int hp82335_allocate_private(gpib_board_t *board); -void hp82335_free_private(gpib_board_t *board); - // size of io memory region used static const int hp82335_rom_size = 0x2000; static const int hp82335_upper_iomem_size = 0x2000;
diff --git a/drivers/staging/gpib/hp_82341/hp_82341.c b/drivers/staging/gpib/hp_82341/hp_82341.c index 0ddae29..f52e673 100644 --- a/drivers/staging/gpib/hp_82341/hp_82341.c +++ b/drivers/staging/gpib/hp_82341/hp_82341.c
@@ -6,6 +6,10 @@ * copyright : (C) 2002, 2005 by Frank Mori Hess * ***************************************************************************/ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#define dev_fmt pr_fmt +#define DRV_NAME KBUILD_MODNAME + #include "hp_82341.h" #include <linux/delay.h> #include <linux/ioport.h> @@ -16,9 +20,17 @@ #include <linux/isapnp.h> MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("GPIB driver for hp 82341a/b/c/d boards"); -int hp_82341_accel_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *end, - size_t *bytes_read) +static unsigned short read_and_clear_event_status(struct gpib_board *board); +static void set_transfer_counter(struct hp_82341_priv *hp_priv, int count); +static int read_transfer_counter(struct hp_82341_priv *hp_priv); +static int hp_82341_write(struct gpib_board *board, uint8_t *buffer, size_t length, int send_eoi, + size_t *bytes_written); +static irqreturn_t hp_82341_interrupt(int irq, void *arg); + +static int hp_82341_accel_read(struct gpib_board *board, uint8_t *buffer, size_t length, int *end, + size_t *bytes_read) { struct hp_82341_priv *hp_priv = board->private_data; struct tms9914_priv *tms_priv = &hp_priv->tms9914_priv; @@ -50,7 +62,7 @@ int hp_82341_accel_read(gpib_board_t *board, uint8_t *buffer, size_t length, int retval = tms9914_read(board, tms_priv, buffer, 1, end, &num_bytes); *bytes_read += num_bytes; if (retval < 0) - pr_err("tms9914_read failed retval=%i\n", retval); + dev_err(board->gpib_dev, "tms9914_read failed retval=%i\n", retval); if (retval < 0 || *end) return retval; ++buffer; @@ -86,7 +98,6 @@ int hp_82341_accel_read(gpib_board_t *board, uint8_t *buffer, size_t length, int test_bit(DEV_CLEAR_BN, &tms_priv->state) || test_bit(TIMO_NUM, &board->status)); if (retval) { - pr_warn("%s: read wait interrupted\n", __func__); retval = -ERESTARTSYS; break; } @@ -111,12 +122,10 @@ int hp_82341_accel_read(gpib_board_t *board, uint8_t *buffer, size_t length, int tms_priv->holdoff_active = 1; } if (test_bit(TIMO_NUM, &board->status)) { - pr_debug("%s: minor %i: read timed out\n", __FILE__, board->minor); retval = -ETIMEDOUT; break; } if (test_bit(DEV_CLEAR_BN, &tms_priv->state)) { - pr_warn("%s: device clear interrupted read\n", __FILE__); retval = -EINTR; break; } @@ -138,7 +147,7 @@ int hp_82341_accel_read(gpib_board_t *board, uint8_t *buffer, size_t length, int return 0; } -static int restart_write_fifo(gpib_board_t *board, struct hp_82341_priv *hp_priv) +static int restart_write_fifo(struct gpib_board *board, struct hp_82341_priv *hp_priv) { struct tms9914_priv *tms_priv = &hp_priv->tms9914_priv; @@ -149,7 +158,7 @@ static int restart_write_fifo(gpib_board_t *board, struct hp_82341_priv *hp_priv //restart doesn't work if data holdoff is in effect status = tms9914_line_status(board, tms_priv); - if ((status & BusNRFD) == 0) { + if ((status & BUS_NRFD) == 0) { outb(RESTART_STREAM_BIT, hp_priv->iobase[0] + STREAM_STATUS_REG); return 0; } @@ -163,8 +172,8 @@ static int restart_write_fifo(gpib_board_t *board, struct hp_82341_priv *hp_priv return 0; } -int hp_82341_accel_write(gpib_board_t *board, uint8_t *buffer, size_t length, - int send_eoi, size_t *bytes_written) +static int hp_82341_accel_write(struct gpib_board *board, uint8_t *buffer, size_t length, + int send_eoi, size_t *bytes_written) { struct hp_82341_priv *hp_priv = board->private_data; struct tms9914_priv *tms_priv = &hp_priv->tms9914_priv; @@ -204,7 +213,7 @@ int hp_82341_accel_write(gpib_board_t *board, uint8_t *buffer, size_t length, outb(ENABLE_TI_BUFFER_BIT, hp_priv->iobase[3] + BUFFER_CONTROL_REG); retval = restart_write_fifo(board, hp_priv); if (retval < 0) { - pr_err("hp82341: failed to restart write stream\n"); + dev_err(board->gpib_dev, "failed to restart write stream\n"); break; } retval = wait_event_interruptible(board->wait, @@ -216,17 +225,14 @@ int hp_82341_accel_write(gpib_board_t *board, uint8_t *buffer, size_t length, outb(0, hp_priv->iobase[3] + BUFFER_CONTROL_REG); *bytes_written += block_size - read_transfer_counter(hp_priv); if (retval) { - pr_warn("%s: write wait interrupted\n", __FILE__); retval = -ERESTARTSYS; break; } if (test_bit(TIMO_NUM, &board->status)) { - pr_debug("%s: minor %i: write timed out\n", __FILE__, board->minor); retval = -ETIMEDOUT; break; } if (test_bit(DEV_CLEAR_BN, &tms_priv->state)) { - pr_warn("%s: device clear interrupted write\n", __FILE__); retval = -EINTR; break; } @@ -244,48 +250,50 @@ int hp_82341_accel_write(gpib_board_t *board, uint8_t *buffer, size_t length, return 0; } -static int hp_82341_attach(gpib_board_t *board, const gpib_board_config_t *config); +static int hp_82341_attach(struct gpib_board *board, const gpib_board_config_t *config); -static void hp_82341_detach(gpib_board_t *board); +static void hp_82341_detach(struct gpib_board *board); // wrappers for interface functions -int hp_82341_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *end, size_t *bytes_read) +static int hp_82341_read(struct gpib_board *board, uint8_t *buffer, size_t length, int *end, + size_t *bytes_read) { struct hp_82341_priv *priv = board->private_data; return tms9914_read(board, &priv->tms9914_priv, buffer, length, end, bytes_read); } -int hp_82341_write(gpib_board_t *board, uint8_t *buffer, size_t length, int send_eoi, - size_t *bytes_written) +static int hp_82341_write(struct gpib_board *board, uint8_t *buffer, size_t length, int send_eoi, + size_t *bytes_written) { struct hp_82341_priv *priv = board->private_data; return tms9914_write(board, &priv->tms9914_priv, buffer, length, send_eoi, bytes_written); } -int hp_82341_command(gpib_board_t *board, uint8_t *buffer, size_t length, size_t *bytes_written) +static int hp_82341_command(struct gpib_board *board, uint8_t *buffer, size_t length, + size_t *bytes_written) { struct hp_82341_priv *priv = board->private_data; return tms9914_command(board, &priv->tms9914_priv, buffer, length, bytes_written); } -int hp_82341_take_control(gpib_board_t *board, int synchronous) +static int hp_82341_take_control(struct gpib_board *board, int synchronous) { struct hp_82341_priv *priv = board->private_data; return tms9914_take_control(board, &priv->tms9914_priv, synchronous); } -int hp_82341_go_to_standby(gpib_board_t *board) +static int hp_82341_go_to_standby(struct gpib_board *board) { struct hp_82341_priv *priv = board->private_data; return tms9914_go_to_standby(board, &priv->tms9914_priv); } -void hp_82341_request_system_control(gpib_board_t *board, int request_control) +static void hp_82341_request_system_control(struct gpib_board *board, int request_control) { struct hp_82341_priv *priv = board->private_data; @@ -297,105 +305,105 @@ void hp_82341_request_system_control(gpib_board_t *board, int request_control) tms9914_request_system_control(board, &priv->tms9914_priv, request_control); } -void hp_82341_interface_clear(gpib_board_t *board, int assert) +static void hp_82341_interface_clear(struct gpib_board *board, int assert) { struct hp_82341_priv *priv = board->private_data; tms9914_interface_clear(board, &priv->tms9914_priv, assert); } -void hp_82341_remote_enable(gpib_board_t *board, int enable) +static void hp_82341_remote_enable(struct gpib_board *board, int enable) { struct hp_82341_priv *priv = board->private_data; tms9914_remote_enable(board, &priv->tms9914_priv, enable); } -int hp_82341_enable_eos(gpib_board_t *board, uint8_t eos_byte, int compare_8_bits) +static int hp_82341_enable_eos(struct gpib_board *board, uint8_t eos_byte, int compare_8_bits) { struct hp_82341_priv *priv = board->private_data; return tms9914_enable_eos(board, &priv->tms9914_priv, eos_byte, compare_8_bits); } -void hp_82341_disable_eos(gpib_board_t *board) +static void hp_82341_disable_eos(struct gpib_board *board) { struct hp_82341_priv *priv = board->private_data; tms9914_disable_eos(board, &priv->tms9914_priv); } -unsigned int hp_82341_update_status(gpib_board_t *board, unsigned int clear_mask) +static unsigned int hp_82341_update_status(struct gpib_board *board, unsigned int clear_mask) { struct hp_82341_priv *priv = board->private_data; return tms9914_update_status(board, &priv->tms9914_priv, clear_mask); } -int hp_82341_primary_address(gpib_board_t *board, unsigned int address) +static int hp_82341_primary_address(struct gpib_board *board, unsigned int address) { struct hp_82341_priv *priv = board->private_data; return tms9914_primary_address(board, &priv->tms9914_priv, address); } -int hp_82341_secondary_address(gpib_board_t *board, unsigned int address, int enable) +static int hp_82341_secondary_address(struct gpib_board *board, unsigned int address, int enable) { struct hp_82341_priv *priv = board->private_data; return tms9914_secondary_address(board, &priv->tms9914_priv, address, enable); } -int hp_82341_parallel_poll(gpib_board_t *board, uint8_t *result) +static int hp_82341_parallel_poll(struct gpib_board *board, uint8_t *result) { struct hp_82341_priv *priv = board->private_data; return tms9914_parallel_poll(board, &priv->tms9914_priv, result); } -void hp_82341_parallel_poll_configure(gpib_board_t *board, uint8_t config) +static void hp_82341_parallel_poll_configure(struct gpib_board *board, uint8_t config) { struct hp_82341_priv *priv = board->private_data; tms9914_parallel_poll_configure(board, &priv->tms9914_priv, config); } -void hp_82341_parallel_poll_response(gpib_board_t *board, int ist) +static void hp_82341_parallel_poll_response(struct gpib_board *board, int ist) { struct hp_82341_priv *priv = board->private_data; tms9914_parallel_poll_response(board, &priv->tms9914_priv, ist); } -void hp_82341_serial_poll_response(gpib_board_t *board, uint8_t status) +static void hp_82341_serial_poll_response(struct gpib_board *board, uint8_t status) { struct hp_82341_priv *priv = board->private_data; tms9914_serial_poll_response(board, &priv->tms9914_priv, status); } -static uint8_t hp_82341_serial_poll_status(gpib_board_t *board) +static uint8_t hp_82341_serial_poll_status(struct gpib_board *board) { struct hp_82341_priv *priv = board->private_data; return tms9914_serial_poll_status(board, &priv->tms9914_priv); } -static int hp_82341_line_status(const gpib_board_t *board) +static int hp_82341_line_status(const struct gpib_board *board) { struct hp_82341_priv *priv = board->private_data; return tms9914_line_status(board, &priv->tms9914_priv); } -static unsigned int hp_82341_t1_delay(gpib_board_t *board, unsigned int nano_sec) +static int hp_82341_t1_delay(struct gpib_board *board, unsigned int nano_sec) { struct hp_82341_priv *priv = board->private_data; return tms9914_t1_delay(board, &priv->tms9914_priv, nano_sec); } -void hp_82341_return_to_local(gpib_board_t *board) +static void hp_82341_return_to_local(struct gpib_board *board) { struct hp_82341_priv *priv = board->private_data; @@ -457,7 +465,7 @@ static gpib_interface_t hp_82341_interface = { .return_to_local = hp_82341_return_to_local, }; -int hp_82341_allocate_private(gpib_board_t *board) +static int hp_82341_allocate_private(struct gpib_board *board) { board->private_data = kzalloc(sizeof(struct hp_82341_priv), GFP_KERNEL); if (!board->private_data) @@ -465,7 +473,7 @@ int hp_82341_allocate_private(gpib_board_t *board) return 0; } -void hp_82341_free_private(gpib_board_t *board) +static void hp_82341_free_private(struct gpib_board *board) { kfree(board->private_data); board->private_data = NULL; @@ -486,21 +494,21 @@ static int hp_82341_find_isapnp_board(struct pnp_dev **dev) *dev = pnp_find_dev(NULL, ISAPNP_VENDOR('H', 'W', 'P'), ISAPNP_FUNCTION(0x1411), NULL); if (!*dev || !(*dev)->card) { - pr_err("hp_82341: failed to find isapnp board\n"); + pr_err("failed to find isapnp board\n"); return -ENODEV; } if (pnp_device_attach(*dev) < 0) { - pr_err("hp_82341: board already active, skipping\n"); + pr_err("board already active, skipping\n"); return -EBUSY; } if (pnp_activate_dev(*dev) < 0) { pnp_device_detach(*dev); - pr_err("hp_82341: failed to activate() atgpib/tnt, aborting\n"); + pr_err("failed to activate(), aborting\n"); return -EAGAIN; } if (!pnp_port_valid(*dev, 0) || !pnp_irq_valid(*dev, 0)) { pnp_device_detach(*dev); - pr_err("hp_82341: invalid port or irq for atgpib/tnt, aborting\n"); + pr_err("invalid port or irq, aborting\n"); return -ENOMEM; } return 0; @@ -521,7 +529,7 @@ static int xilinx_ready(struct hp_82341_priv *hp_priv) else return 0; default: - pr_err("hp_82341: %s: bug! unknown hw_version\n", __func__); + pr_err("bug! unknown hw_version\n"); break; } return 0; @@ -541,7 +549,7 @@ static int xilinx_done(struct hp_82341_priv *hp_priv) else return 0; default: - pr_err("hp_82341: %s: bug! unknown hw_version\n", __func__); + pr_err("bug! unknown hw_version\n"); break; } return 0; @@ -562,7 +570,7 @@ static int irq_valid(struct hp_82341_priv *hp_priv, int irq) case 15: return 1; default: - pr_err("hp_82341: invalid irq=%i for 82341C, irq must be 3, 5, 7, 9, 10, 11, 12, or 15.\n", + pr_err("invalid irq=%i for 82341C, irq must be 3, 5, 7, 9, 10, 11, 12, or 15.\n", irq); return 0; } @@ -570,7 +578,7 @@ static int irq_valid(struct hp_82341_priv *hp_priv, int irq) case HW_VERSION_82341D: return 1; default: - pr_err("hp_82341: %s: bug! unknown hw_version\n", __func__); + pr_err("bug! unknown hw_version\n"); break; } return 0; @@ -592,7 +600,7 @@ static int hp_82341_load_firmware_array(struct hp_82341_priv *hp_priv, usleep_range(10, 15); } if (j == timeout) { - pr_err("hp_82341: timed out waiting for Xilinx ready.\n"); + pr_err("timed out waiting for Xilinx ready.\n"); return -ETIMEDOUT; } outb(firmware_data[i], hp_priv->iobase[0] + XILINX_DATA_REG); @@ -605,7 +613,7 @@ static int hp_82341_load_firmware_array(struct hp_82341_priv *hp_priv, usleep_range(10, 15); } if (j == timeout) { - pr_err("hp_82341: timed out waiting for Xilinx done.\n"); + pr_err("timed out waiting for Xilinx done.\n"); return -ETIMEDOUT; } return 0; @@ -616,27 +624,27 @@ static int hp_82341_load_firmware(struct hp_82341_priv *hp_priv, const gpib_boar if (config->init_data_length == 0) { if (xilinx_done(hp_priv)) return 0; - pr_err("hp_82341: board needs be initialized with firmware upload.\n" + pr_err("board needs be initialized with firmware upload.\n" "\tUse the --init-data option of gpib_config.\n"); return -EINVAL; } switch (hp_priv->hw_version) { case HW_VERSION_82341C: if (config->init_data_length != hp_82341c_firmware_length) { - pr_err("hp_82341: bad firmware length=%i for 82341c (expected %i).\n", + pr_err("bad firmware length=%i for 82341c (expected %i).\n", config->init_data_length, hp_82341c_firmware_length); return -EINVAL; } break; case HW_VERSION_82341D: if (config->init_data_length != hp_82341d_firmware_length) { - pr_err("hp_82341: bad firmware length=%i for 82341d (expected %i).\n", + pr_err("bad firmware length=%i for 82341d (expected %i).\n", config->init_data_length, hp_82341d_firmware_length); return -EINVAL; } break; default: - pr_err("hp_82341: %s: bug! unknown hw_version\n", __func__); + pr_err("bug! unknown hw_version\n"); break; } return hp_82341_load_firmware_array(hp_priv, config->init_data, config->init_data_length); @@ -678,7 +686,7 @@ static int clear_xilinx(struct hp_82341_priv *hp_priv) return 0; } -int hp_82341_attach(gpib_board_t *board, const gpib_board_config_t *config) +static int hp_82341_attach(struct gpib_board *board, const gpib_board_config_t *config) { struct hp_82341_priv *hp_priv; struct tms9914_priv *tms_priv; @@ -714,13 +722,12 @@ int hp_82341_attach(gpib_board_t *board, const gpib_board_config_t *config) hp_priv->hw_version = HW_VERSION_82341C; hp_priv->io_region_offset = 0x400; } - pr_info("hp_82341: base io 0x%u\n", iobase); for (i = 0; i < hp_82341_num_io_regions; ++i) { start_addr = iobase + i * hp_priv->io_region_offset; - if (!request_region(start_addr, hp_82341_region_iosize, "hp_82341")) { - pr_err("hp_82341: failed to allocate io ports 0x%lx-0x%lx\n", - start_addr, - start_addr + hp_82341_region_iosize - 1); + if (!request_region(start_addr, hp_82341_region_iosize, DRV_NAME)) { + dev_err(board->gpib_dev, "failed to allocate io ports 0x%x-0x%x\n", + start_addr, + start_addr + hp_82341_region_iosize - 1); return -EIO; } hp_priv->iobase[i] = start_addr; @@ -730,7 +737,7 @@ int hp_82341_attach(gpib_board_t *board, const gpib_board_config_t *config) retval = isapnp_cfg_begin(hp_priv->pnp_dev->card->number, hp_priv->pnp_dev->number); if (retval < 0) { - pr_err("hp_82341: isapnp_cfg_begin returned error\n"); + dev_err(board->gpib_dev, "isapnp_cfg_begin returned error\n"); return retval; } isapnp_write_byte(PIO_DIRECTION_REG, HP_82341D_XILINX_READY_BIT | @@ -746,12 +753,11 @@ int hp_82341_attach(gpib_board_t *board, const gpib_board_config_t *config) return retval; if (irq_valid(hp_priv, irq) == 0) return -EINVAL; - if (request_irq(irq, hp_82341_interrupt, 0, "hp_82341", board)) { - pr_err("hp_82341: failed to allocate IRQ %d\n", irq); + if (request_irq(irq, hp_82341_interrupt, 0, DRV_NAME, board)) { + dev_err(board->gpib_dev, "failed to allocate IRQ %d\n", irq); return -EIO; } hp_priv->irq = irq; - pr_info("hp_82341: IRQ %d\n", irq); hp_priv->config_control_bits &= ~IRQ_SELECT_MASK; hp_priv->config_control_bits |= IRQ_SELECT_BITS(irq); outb(hp_priv->config_control_bits, hp_priv->iobase[0] + CONFIG_CONTROL_STATUS_REG); @@ -768,13 +774,11 @@ int hp_82341_attach(gpib_board_t *board, const gpib_board_config_t *config) hp_priv->iobase[0] + EVENT_STATUS_REG); tms9914_online(board, tms_priv); - pr_info("hp_82341: board id %x %x %x %x\n", inb(hp_priv->iobase[1] + ID0_REG), - inb(hp_priv->iobase[1] + ID1_REG), inb(hp_priv->iobase[2] + ID2_REG), - inb(hp_priv->iobase[2] + ID3_REG)); + return 0; } -void hp_82341_detach(gpib_board_t *board) +static void hp_82341_detach(struct gpib_board *board) { struct hp_82341_priv *hp_priv = board->private_data; struct tms9914_priv *tms_priv; @@ -799,11 +803,14 @@ void hp_82341_detach(gpib_board_t *board) hp_82341_free_private(board); } +#if 0 +/* unused, will be needed when the driver is turned into a pnp_driver */ static const struct pnp_device_id hp_82341_pnp_table[] = { {.id = "HWP1411"}, {.id = ""} }; MODULE_DEVICE_TABLE(pnp, hp_82341_pnp_table); +#endif static int __init hp_82341_init_module(void) { @@ -811,13 +818,13 @@ static int __init hp_82341_init_module(void) ret = gpib_register_driver(&hp_82341_unaccel_interface, THIS_MODULE); if (ret) { - pr_err("hp_82341: gpib_register_driver failed: error = %d\n", ret); + pr_err("gpib_register_driver failed: error = %d\n", ret); return ret; } ret = gpib_register_driver(&hp_82341_interface, THIS_MODULE); if (ret) { - pr_err("hp_82341: gpib_register_driver failed: error = %d\n", ret); + pr_err("gpib_register_driver failed: error = %d\n", ret); gpib_unregister_driver(&hp_82341_unaccel_interface); return ret; } @@ -837,7 +844,7 @@ module_exit(hp_82341_exit_module); /* * GPIB interrupt service routines */ -unsigned short read_and_clear_event_status(gpib_board_t *board) +static unsigned short read_and_clear_event_status(struct gpib_board *board) { struct hp_82341_priv *hp_priv = board->private_data; unsigned long flags; @@ -850,10 +857,10 @@ unsigned short read_and_clear_event_status(gpib_board_t *board) return status; } -irqreturn_t hp_82341_interrupt(int irq, void *arg) +static irqreturn_t hp_82341_interrupt(int irq, void *arg) { int status1, status2; - gpib_board_t *board = arg; + struct gpib_board *board = arg; struct hp_82341_priv *hp_priv = board->private_data; struct tms9914_priv *tms_priv = &hp_priv->tms9914_priv; unsigned long flags; @@ -862,7 +869,6 @@ irqreturn_t hp_82341_interrupt(int irq, void *arg) spin_lock_irqsave(&board->spinlock, flags); event_status = inb(hp_priv->iobase[0] + EVENT_STATUS_REG); -// printk("hp_82341: interrupt event_status=0x%x\n", event_status); if (event_status & INTERRUPT_PENDING_EVENT_BIT) retval = IRQ_HANDLED; //write-clear status bits @@ -877,15 +883,12 @@ irqreturn_t hp_82341_interrupt(int irq, void *arg) status1 = read_byte(tms_priv, ISR0); status2 = read_byte(tms_priv, ISR1); tms9914_interrupt_have_status(board, tms_priv, status1, status2); -/* printk("hp_82341: interrupt status1=0x%x status2=0x%x\n", - * status1, status2); - */ } spin_unlock_irqrestore(&board->spinlock, flags); return retval; } -int read_transfer_counter(struct hp_82341_priv *hp_priv) +static int read_transfer_counter(struct hp_82341_priv *hp_priv) { int lo, mid, value; @@ -896,7 +899,7 @@ int read_transfer_counter(struct hp_82341_priv *hp_priv) return value; } -void set_transfer_counter(struct hp_82341_priv *hp_priv, int count) +static void set_transfer_counter(struct hp_82341_priv *hp_priv, int count) { int complement = -count;
diff --git a/drivers/staging/gpib/hp_82341/hp_82341.h b/drivers/staging/gpib/hp_82341/hp_82341.h index 0065ebd9..370a3d4 100644 --- a/drivers/staging/gpib/hp_82341/hp_82341.h +++ b/drivers/staging/gpib/hp_82341/hp_82341.h
@@ -26,42 +26,6 @@ struct hp_82341_priv { enum hp_82341_hardware_version hw_version; }; - -// interface functions -int hp_82341_accel_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *end, - size_t *bytes_read); -int hp_82341_accel_write(gpib_board_t *board, uint8_t *buffer, size_t length, int send_eoi, - size_t *bytes_written); -int hp_82341_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *end, - size_t *bytes_read); -int hp_82341_write(gpib_board_t *board, uint8_t *buffer, size_t length, int send_eoi, - size_t *bytes_written); -int hp_82341_command(gpib_board_t *board, uint8_t *buffer, size_t length, size_t *bytes_written); -int hp_82341_take_control(gpib_board_t *board, int synchronous); -int hp_82341_go_to_standby(gpib_board_t *board); -void hp_82341_request_system_control(gpib_board_t *board, int request_control); -void hp_82341_interface_clear(gpib_board_t *board, int assert); -void hp_82341_remote_enable(gpib_board_t *board, int enable); -int hp_82341_enable_eos(gpib_board_t *board, uint8_t eos_byte, int - compare_8_bits); -void hp_82341_disable_eos(gpib_board_t *board); -unsigned int hp_82341_update_status(gpib_board_t *board, unsigned int clear_mask); -int hp_82341_primary_address(gpib_board_t *board, unsigned int address); -int hp_82341_secondary_address(gpib_board_t *board, unsigned int address, int - enable); -int hp_82341_parallel_poll(gpib_board_t *board, uint8_t *result); -void hp_82341_parallel_poll_configure(gpib_board_t *board, uint8_t config); -void hp_82341_parallel_poll_response(gpib_board_t *board, int ist); -void hp_82341_serial_poll_response(gpib_board_t *board, uint8_t status); -void hp_82341_return_to_local(gpib_board_t *board); - -// interrupt service routines -irqreturn_t hp_82341_interrupt(int irq, void *arg); - -// utility functions -int hp_82341_allocate_private(gpib_board_t *board); -void hp_82341_free_private(gpib_board_t *board); - static const int hp_82341_region_iosize = 0x8; static const int hp_82341_num_io_regions = 4; static const int hp_82341_fifo_size = 0xffe; @@ -199,7 +163,3 @@ enum hp_82341d_pnp_pio_bits { HP_82341D_LEGACY_MODE_BIT = 0x4, HP_82341D_NOT_PROG_BIT = 0x8, // clear to reinitialize xilinx }; - -unsigned short read_and_clear_event_status(gpib_board_t *board); -int read_transfer_counter(struct hp_82341_priv *hp_priv); -void set_transfer_counter(struct hp_82341_priv *hp_priv, int count);
diff --git a/drivers/staging/gpib/include/gpibP.h b/drivers/staging/gpib/include/gpibP.h index d35fdd3..0c71a03 100644 --- a/drivers/staging/gpib/include/gpibP.h +++ b/drivers/staging/gpib/include/gpibP.h
@@ -26,13 +26,13 @@ struct pci_dev *gpib_pci_get_subsys(const gpib_board_config_t *config, unsigned unsigned int device_id, unsigned int ss_vendor, unsigned int ss_device, struct pci_dev *from); unsigned int num_gpib_events(const gpib_event_queue_t *queue); -int push_gpib_event(gpib_board_t *board, short event_type); -int pop_gpib_event(gpib_board_t *board, gpib_event_queue_t *queue, short *event_type); -int gpib_request_pseudo_irq(gpib_board_t *board, irqreturn_t (*handler)(int, void *)); -void gpib_free_pseudo_irq(gpib_board_t *board); +int push_gpib_event(struct gpib_board *board, short event_type); +int pop_gpib_event(struct gpib_board *board, gpib_event_queue_t *queue, short *event_type); +int gpib_request_pseudo_irq(struct gpib_board *board, irqreturn_t (*handler)(int, void *)); +void gpib_free_pseudo_irq(struct gpib_board *board); int gpib_match_device_path(struct device *dev, const char *device_path_in); -extern gpib_board_t board_array[GPIB_MAX_NUM_BOARDS]; +extern struct gpib_board board_array[GPIB_MAX_NUM_BOARDS]; extern struct list_head registered_drivers;
diff --git a/drivers/staging/gpib/include/gpib_proto.h b/drivers/staging/gpib/include/gpib_proto.h index 1499f95..2c7dfc0 100644 --- a/drivers/staging/gpib/include/gpib_proto.h +++ b/drivers/staging/gpib/include/gpib_proto.h
@@ -10,11 +10,11 @@ int ibclose(struct inode *inode, struct file *file); long ibioctl(struct file *filep, unsigned int cmd, unsigned long arg); int osInit(void); void osReset(void); -void os_start_timer(gpib_board_t *board, unsigned int usec_timeout); -void os_remove_timer(gpib_board_t *board); +void os_start_timer(struct gpib_board *board, unsigned int usec_timeout); +void os_remove_timer(struct gpib_board *board); void osSendEOI(void); void osSendEOI(void); -void init_gpib_board(gpib_board_t *board); +void init_gpib_board(struct gpib_board *board); static inline unsigned long usec_to_jiffies(unsigned int usec) { unsigned long usec_per_jiffy = 1000000 / HZ; @@ -22,35 +22,35 @@ static inline unsigned long usec_to_jiffies(unsigned int usec) return 1 + (usec + usec_per_jiffy - 1) / usec_per_jiffy; }; -int serial_poll_all(gpib_board_t *board, unsigned int usec_timeout); +int serial_poll_all(struct gpib_board *board, unsigned int usec_timeout); void init_gpib_descriptor(gpib_descriptor_t *desc); -int dvrsp(gpib_board_t *board, unsigned int pad, int sad, +int dvrsp(struct gpib_board *board, unsigned int pad, int sad, unsigned int usec_timeout, uint8_t *result); -int ibAPWait(gpib_board_t *board, int pad); -int ibAPrsp(gpib_board_t *board, int padsad, char *spb); -void ibAPE(gpib_board_t *board, int pad, int v); -int ibcac(gpib_board_t *board, int sync, int fallback_to_async); -int ibcmd(gpib_board_t *board, uint8_t *buf, size_t length, size_t *bytes_written); -int ibgts(gpib_board_t *board); -int ibonline(gpib_board_t *board); -int iboffline(gpib_board_t *board); -int iblines(const gpib_board_t *board, short *lines); -int ibrd(gpib_board_t *board, uint8_t *buf, size_t length, int *end_flag, size_t *bytes_read); -int ibrpp(gpib_board_t *board, uint8_t *buf); -int ibrsv2(gpib_board_t *board, uint8_t status_byte, int new_reason_for_service); -void ibrsc(gpib_board_t *board, int request_control); -int ibsic(gpib_board_t *board, unsigned int usec_duration); -int ibsre(gpib_board_t *board, int enable); -int ibpad(gpib_board_t *board, unsigned int addr); -int ibsad(gpib_board_t *board, int addr); -int ibeos(gpib_board_t *board, int eos, int eosflags); -int ibwait(gpib_board_t *board, int wait_mask, int clear_mask, int set_mask, +int ibAPWait(struct gpib_board *board, int pad); +int ibAPrsp(struct gpib_board *board, int padsad, char *spb); +void ibAPE(struct gpib_board *board, int pad, int v); +int ibcac(struct gpib_board *board, int sync, int fallback_to_async); +int ibcmd(struct gpib_board *board, uint8_t *buf, size_t length, size_t *bytes_written); +int ibgts(struct gpib_board *board); +int ibonline(struct gpib_board *board); +int iboffline(struct gpib_board *board); +int iblines(const struct gpib_board *board, short *lines); +int ibrd(struct gpib_board *board, uint8_t *buf, size_t length, int *end_flag, size_t *bytes_read); +int ibrpp(struct gpib_board *board, uint8_t *buf); +int ibrsv2(struct gpib_board *board, uint8_t status_byte, int new_reason_for_service); +void ibrsc(struct gpib_board *board, int request_control); +int ibsic(struct gpib_board *board, unsigned int usec_duration); +int ibsre(struct gpib_board *board, int enable); +int ibpad(struct gpib_board *board, unsigned int addr); +int ibsad(struct gpib_board *board, int addr); +int ibeos(struct gpib_board *board, int eos, int eosflags); +int ibwait(struct gpib_board *board, int wait_mask, int clear_mask, int set_mask, int *status, unsigned long usec_timeout, gpib_descriptor_t *desc); -int ibwrt(gpib_board_t *board, uint8_t *buf, size_t cnt, int send_eoi, size_t *bytes_written); -int ibstatus(gpib_board_t *board); -int general_ibstatus(gpib_board_t *board, const gpib_status_queue_t *device, +int ibwrt(struct gpib_board *board, uint8_t *buf, size_t cnt, int send_eoi, size_t *bytes_written); +int ibstatus(struct gpib_board *board); +int general_ibstatus(struct gpib_board *board, const gpib_status_queue_t *device, int clear_mask, int set_mask, gpib_descriptor_t *desc); -int io_timed_out(gpib_board_t *board); -int ibppc(gpib_board_t *board, uint8_t configuration); +int io_timed_out(struct gpib_board *board); +int ibppc(struct gpib_board *board, uint8_t configuration); #endif /* GPIB_PROTO_INCLUDED */
diff --git a/drivers/staging/gpib/include/gpib_types.h b/drivers/staging/gpib/include/gpib_types.h index b41781a..2d9b9be 100644 --- a/drivers/staging/gpib/include/gpib_types.h +++ b/drivers/staging/gpib/include/gpib_types.h
@@ -23,7 +23,7 @@ #include <linux/interrupt.h> typedef struct gpib_interface_struct gpib_interface_t; -typedef struct gpib_board_struct gpib_board_t; +struct gpib_board; /* config parameters that are only used by driver attach functions */ typedef struct { @@ -55,9 +55,9 @@ struct gpib_interface_struct { /* name of board */ char *name; /* attach() initializes board and allocates resources */ - int (*attach)(gpib_board_t *board, const gpib_board_config_t *config); + int (*attach)(struct gpib_board *board, const gpib_board_config_t *config); /* detach() shuts down board and frees resources */ - void (*detach)(gpib_board_t *board); + void (*detach)(struct gpib_board *board); /* read() should read at most 'length' bytes from the bus into * 'buffer'. It should return when it fills the buffer or * encounters an END (EOI and or EOS if appropriate). It should set 'end' @@ -68,19 +68,19 @@ struct gpib_interface_struct { * return indicates error. * nbytes returns number of bytes read */ - int (*read)(gpib_board_t *board, uint8_t *buffer, size_t length, int *end, + int (*read)(struct gpib_board *board, uint8_t *buffer, size_t length, int *end, size_t *bytes_read); /* write() should write 'length' bytes from buffer to the bus. * If the boolean value send_eoi is nonzero, then EOI should * be sent along with the last byte. Returns number of bytes * written or negative value on error. */ - int (*write)(gpib_board_t *board, uint8_t *buffer, size_t length, int send_eoi, + int (*write)(struct gpib_board *board, uint8_t *buffer, size_t length, int send_eoi, size_t *bytes_written); /* command() writes the command bytes in 'buffer' to the bus * Returns zero on success or negative value on error. */ - int (*command)(gpib_board_t *board, uint8_t *buffer, size_t length, + int (*command)(struct gpib_board *board, uint8_t *buffer, size_t length, size_t *bytes_written); /* Take control (assert ATN). If 'asyncronous' is nonzero, take * control asyncronously (assert ATN immediately without waiting @@ -88,54 +88,54 @@ struct gpib_interface_struct { * until board becomes controller in charge. Returns zero no success, * nonzero on error. */ - int (*take_control)(gpib_board_t *board, int asyncronous); + int (*take_control)(struct gpib_board *board, int asyncronous); /* De-assert ATN. Returns zero on success, nonzer on error. */ - int (*go_to_standby)(gpib_board_t *board); + int (*go_to_standby)(struct gpib_board *board); /* request/release control of the IFC and REN lines (system controller) */ - void (*request_system_control)(gpib_board_t *board, int request_control); + void (*request_system_control)(struct gpib_board *board, int request_control); /* Asserts or de-asserts 'interface clear' (IFC) depending on * boolean value of 'assert' */ - void (*interface_clear)(gpib_board_t *board, int assert); + void (*interface_clear)(struct gpib_board *board, int assert); /* Sends remote enable command if 'enable' is nonzero, disables remote mode * if 'enable' is zero */ - void (*remote_enable)(gpib_board_t *board, int enable); + void (*remote_enable)(struct gpib_board *board, int enable); /* enable END for reads, when byte 'eos' is received. If * 'compare_8_bits' is nonzero, then all 8 bits are compared * with the eos bytes. Otherwise only the 7 least significant * bits are compared. */ - int (*enable_eos)(gpib_board_t *board, uint8_t eos, int compare_8_bits); + int (*enable_eos)(struct gpib_board *board, uint8_t eos, int compare_8_bits); /* disable END on eos byte (END on EOI only)*/ - void (*disable_eos)(gpib_board_t *board); + void (*disable_eos)(struct gpib_board *board); /* configure parallel poll */ - void (*parallel_poll_configure)(gpib_board_t *board, uint8_t configuration); + void (*parallel_poll_configure)(struct gpib_board *board, uint8_t configuration); /* conduct parallel poll */ - int (*parallel_poll)(gpib_board_t *board, uint8_t *result); + int (*parallel_poll)(struct gpib_board *board, uint8_t *result); /* set/clear ist (individual status bit) */ - void (*parallel_poll_response)(gpib_board_t *board, int ist); + void (*parallel_poll_response)(struct gpib_board *board, int ist); /* select local parallel poll configuration mode PP2 versus remote PP1 */ - void (*local_parallel_poll_mode)(gpib_board_t *board, int local); + void (*local_parallel_poll_mode)(struct gpib_board *board, int local); /* Returns current status of the bus lines. Should be set to * NULL if your board does not have the ability to query the * state of the bus lines. */ - int (*line_status)(const gpib_board_t *board); + int (*line_status)(const struct gpib_board *board); /* updates and returns the board's current status. * The meaning of the bits are specified in gpib_user.h * in the IBSTA section. The driver does not need to * worry about setting the CMPL, END, TIMO, or ERR bits. */ - unsigned int (*update_status)(gpib_board_t *board, unsigned int clear_mask); + unsigned int (*update_status)(struct gpib_board *board, unsigned int clear_mask); /* Sets primary address 0-30 for gpib interface card. */ - int (*primary_address)(gpib_board_t *board, unsigned int address); + int (*primary_address)(struct gpib_board *board, unsigned int address); /* Sets and enables, or disables secondary address 0-30 * for gpib interface card. */ - int (*secondary_address)(gpib_board_t *board, unsigned int address, + int (*secondary_address)(struct gpib_board *board, unsigned int address, int enable); /* Sets the byte the board should send in response to a serial poll. * This function should also start or stop requests for service via @@ -149,7 +149,7 @@ struct gpib_interface_struct { * by IEEE 488.2 section 11.3.3.4.3 "Allowed Coupled Control of * STB, reqt, and reqf". */ - void (*serial_poll_response)(gpib_board_t *board, uint8_t status_byte); + void (*serial_poll_response)(struct gpib_board *board, uint8_t status_byte); /* Sets the byte the board should send in response to a serial poll. * This function should also request service via IEEE 488.2 reqt/reqf * based on MSS (bit 6 of the status_byte) and new_reason_for_service. @@ -164,15 +164,15 @@ struct gpib_interface_struct { * If this method is left NULL by the driver, then the user library * function ibrsv2 will not work. */ - void (*serial_poll_response2)(gpib_board_t *board, uint8_t status_byte, + void (*serial_poll_response2)(struct gpib_board *board, uint8_t status_byte, int new_reason_for_service); /* returns the byte the board will send in response to a serial poll. */ - uint8_t (*serial_poll_status)(gpib_board_t *board); + uint8_t (*serial_poll_status)(struct gpib_board *board); /* adjust T1 delay */ - unsigned int (*t1_delay)(gpib_board_t *board, unsigned int nano_sec); + int (*t1_delay)(struct gpib_board *board, unsigned int nano_sec); /* go to local mode */ - void (*return_to_local)(gpib_board_t *board); + void (*return_to_local)(struct gpib_board *board); /* board does not support 7 bit eos comparisons */ unsigned no_7_bit_eos : 1; /* skip check for listeners before trying to send command bytes */ @@ -198,7 +198,7 @@ static inline void init_event_queue(gpib_event_queue_t *queue) struct gpib_pseudo_irq { struct timer_list timer; irqreturn_t (*handler)(int irq, void *arg); - gpib_board_t *board; + struct gpib_board *board; atomic_t active; }; @@ -216,11 +216,11 @@ typedef struct gpib_interface_list_struct { struct module *module; } gpib_interface_list_t; -/* One gpib_board_t is allocated for each physical board in the computer. +/* One struct gpib_board is allocated for each physical board in the computer. * It provides storage for variables local to each board, and interface * functions for performing operations on the board */ -struct gpib_board_struct { +struct gpib_board { /* functions used by this board */ gpib_interface_t *interface; /* Pointer to module whose use count we should increment when
diff --git a/drivers/staging/gpib/include/nec7210.h b/drivers/staging/gpib/include/nec7210.h index ca998c4..0698964 100644 --- a/drivers/staging/gpib/include/nec7210.h +++ b/drivers/staging/gpib/include/nec7210.h
@@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0 */ +//* SPDX-License-Identifier: GPL-2.0 */ /*************************************************************************** * copyright : (C) 2002 by Frank Mori Hess @@ -78,48 +78,48 @@ enum { }; // interface functions -int nec7210_read(gpib_board_t *board, struct nec7210_priv *priv, uint8_t *buffer, +int nec7210_read(struct gpib_board *board, struct nec7210_priv *priv, uint8_t *buffer, size_t length, int *end, size_t *bytes_read); -int nec7210_write(gpib_board_t *board, struct nec7210_priv *priv, uint8_t *buffer, +int nec7210_write(struct gpib_board *board, struct nec7210_priv *priv, uint8_t *buffer, size_t length, int send_eoi, size_t *bytes_written); -int nec7210_command(gpib_board_t *board, struct nec7210_priv *priv, uint8_t *buffer, +int nec7210_command(struct gpib_board *board, struct nec7210_priv *priv, uint8_t *buffer, size_t length, size_t *bytes_written); -int nec7210_take_control(gpib_board_t *board, struct nec7210_priv *priv, int syncronous); -int nec7210_go_to_standby(gpib_board_t *board, struct nec7210_priv *priv); -void nec7210_request_system_control(gpib_board_t *board, +int nec7210_take_control(struct gpib_board *board, struct nec7210_priv *priv, int syncronous); +int nec7210_go_to_standby(struct gpib_board *board, struct nec7210_priv *priv); +void nec7210_request_system_control(struct gpib_board *board, struct nec7210_priv *priv, int request_control); -void nec7210_interface_clear(gpib_board_t *board, struct nec7210_priv *priv, int assert); -void nec7210_remote_enable(gpib_board_t *board, struct nec7210_priv *priv, int enable); -int nec7210_enable_eos(gpib_board_t *board, struct nec7210_priv *priv, uint8_t eos_bytes, +void nec7210_interface_clear(struct gpib_board *board, struct nec7210_priv *priv, int assert); +void nec7210_remote_enable(struct gpib_board *board, struct nec7210_priv *priv, int enable); +int nec7210_enable_eos(struct gpib_board *board, struct nec7210_priv *priv, uint8_t eos_bytes, int compare_8_bits); -void nec7210_disable_eos(gpib_board_t *board, struct nec7210_priv *priv); -unsigned int nec7210_update_status(gpib_board_t *board, struct nec7210_priv *priv, +void nec7210_disable_eos(struct gpib_board *board, struct nec7210_priv *priv); +unsigned int nec7210_update_status(struct gpib_board *board, struct nec7210_priv *priv, unsigned int clear_mask); -unsigned int nec7210_update_status_nolock(gpib_board_t *board, struct nec7210_priv *priv); -int nec7210_primary_address(const gpib_board_t *board, +unsigned int nec7210_update_status_nolock(struct gpib_board *board, struct nec7210_priv *priv); +int nec7210_primary_address(const struct gpib_board *board, struct nec7210_priv *priv, unsigned int address); -int nec7210_secondary_address(const gpib_board_t *board, struct nec7210_priv *priv, +int nec7210_secondary_address(const struct gpib_board *board, struct nec7210_priv *priv, unsigned int address, int enable); -int nec7210_parallel_poll(gpib_board_t *board, struct nec7210_priv *priv, uint8_t *result); -void nec7210_serial_poll_response(gpib_board_t *board, struct nec7210_priv *priv, uint8_t status); -void nec7210_parallel_poll_configure(gpib_board_t *board, +int nec7210_parallel_poll(struct gpib_board *board, struct nec7210_priv *priv, uint8_t *result); +void nec7210_serial_poll_response(struct gpib_board *board, struct nec7210_priv *priv, uint8_t status); +void nec7210_parallel_poll_configure(struct gpib_board *board, struct nec7210_priv *priv, unsigned int configuration); -void nec7210_parallel_poll_response(gpib_board_t *board, +void nec7210_parallel_poll_response(struct gpib_board *board, struct nec7210_priv *priv, int ist); -uint8_t nec7210_serial_poll_status(gpib_board_t *board, +uint8_t nec7210_serial_poll_status(struct gpib_board *board, struct nec7210_priv *priv); -unsigned int nec7210_t1_delay(gpib_board_t *board, - struct nec7210_priv *priv, unsigned int nano_sec); -void nec7210_return_to_local(const gpib_board_t *board, struct nec7210_priv *priv); +int nec7210_t1_delay(struct gpib_board *board, + struct nec7210_priv *priv, unsigned int nano_sec); +void nec7210_return_to_local(const struct gpib_board *board, struct nec7210_priv *priv); // utility functions -void nec7210_board_reset(struct nec7210_priv *priv, const gpib_board_t *board); -void nec7210_board_online(struct nec7210_priv *priv, const gpib_board_t *board); +void nec7210_board_reset(struct nec7210_priv *priv, const struct gpib_board *board); +void nec7210_board_online(struct nec7210_priv *priv, const struct gpib_board *board); unsigned int nec7210_set_reg_bits(struct nec7210_priv *priv, unsigned int reg, unsigned int mask, unsigned int bits); -void nec7210_set_handshake_mode(gpib_board_t *board, struct nec7210_priv *priv, int mode); -void nec7210_release_rfd_holdoff(gpib_board_t *board, struct nec7210_priv *priv); -uint8_t nec7210_read_data_in(gpib_board_t *board, struct nec7210_priv *priv, int *end); +void nec7210_set_handshake_mode(struct gpib_board *board, struct nec7210_priv *priv, int mode); +void nec7210_release_rfd_holdoff(struct gpib_board *board, struct nec7210_priv *priv); +uint8_t nec7210_read_data_in(struct gpib_board *board, struct nec7210_priv *priv, int *end); // wrappers for io functions uint8_t nec7210_ioport_read_byte(struct nec7210_priv *priv, unsigned int register_num); @@ -134,8 +134,8 @@ void nec7210_locking_iomem_write_byte(struct nec7210_priv *priv, uint8_t data, unsigned int register_num); // interrupt service routine -irqreturn_t nec7210_interrupt(gpib_board_t *board, struct nec7210_priv *priv); -irqreturn_t nec7210_interrupt_have_status(gpib_board_t *board, +irqreturn_t nec7210_interrupt(struct gpib_board *board, struct nec7210_priv *priv); +irqreturn_t nec7210_interrupt_have_status(struct gpib_board *board, struct nec7210_priv *priv, int status1, int status2); #endif //_NEC7210_H
diff --git a/drivers/staging/gpib/include/tms9914.h b/drivers/staging/gpib/include/tms9914.h index d8c8d1c..424c95a 100644 --- a/drivers/staging/gpib/include/tms9914.h +++ b/drivers/staging/gpib/include/tms9914.h
@@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0 */ +//* SPDX-License-Identifier: GPL-2.0 */ /*************************************************************************** * copyright : (C) 2002 by Frank Mori Hess @@ -79,47 +79,47 @@ enum { }; // interface functions -int tms9914_read(gpib_board_t *board, struct tms9914_priv *priv, uint8_t *buffer, +int tms9914_read(struct gpib_board *board, struct tms9914_priv *priv, uint8_t *buffer, size_t length, int *end, size_t *bytes_read); -int tms9914_write(gpib_board_t *board, struct tms9914_priv *priv, uint8_t *buffer, +int tms9914_write(struct gpib_board *board, struct tms9914_priv *priv, uint8_t *buffer, size_t length, int send_eoi, size_t *bytes_written); -int tms9914_command(gpib_board_t *board, struct tms9914_priv *priv, uint8_t *buffer, +int tms9914_command(struct gpib_board *board, struct tms9914_priv *priv, uint8_t *buffer, size_t length, size_t *bytes_written); -int tms9914_take_control(gpib_board_t *board, struct tms9914_priv *priv, int syncronous); +int tms9914_take_control(struct gpib_board *board, struct tms9914_priv *priv, int syncronous); /* alternate version of tms9914_take_control which works around buggy tcs * implementation. */ -int tms9914_take_control_workaround(gpib_board_t *board, struct tms9914_priv *priv, +int tms9914_take_control_workaround(struct gpib_board *board, struct tms9914_priv *priv, int syncronous); -int tms9914_go_to_standby(gpib_board_t *board, struct tms9914_priv *priv); -void tms9914_request_system_control(gpib_board_t *board, struct tms9914_priv *priv, +int tms9914_go_to_standby(struct gpib_board *board, struct tms9914_priv *priv); +void tms9914_request_system_control(struct gpib_board *board, struct tms9914_priv *priv, int request_control); -void tms9914_interface_clear(gpib_board_t *board, struct tms9914_priv *priv, int assert); -void tms9914_remote_enable(gpib_board_t *board, struct tms9914_priv *priv, int enable); -int tms9914_enable_eos(gpib_board_t *board, struct tms9914_priv *priv, uint8_t eos_bytes, +void tms9914_interface_clear(struct gpib_board *board, struct tms9914_priv *priv, int assert); +void tms9914_remote_enable(struct gpib_board *board, struct tms9914_priv *priv, int enable); +int tms9914_enable_eos(struct gpib_board *board, struct tms9914_priv *priv, uint8_t eos_bytes, int compare_8_bits); -void tms9914_disable_eos(gpib_board_t *board, struct tms9914_priv *priv); -unsigned int tms9914_update_status(gpib_board_t *board, struct tms9914_priv *priv, +void tms9914_disable_eos(struct gpib_board *board, struct tms9914_priv *priv); +unsigned int tms9914_update_status(struct gpib_board *board, struct tms9914_priv *priv, unsigned int clear_mask); -int tms9914_primary_address(gpib_board_t *board, +int tms9914_primary_address(struct gpib_board *board, struct tms9914_priv *priv, unsigned int address); -int tms9914_secondary_address(gpib_board_t *board, struct tms9914_priv *priv, +int tms9914_secondary_address(struct gpib_board *board, struct tms9914_priv *priv, unsigned int address, int enable); -int tms9914_parallel_poll(gpib_board_t *board, struct tms9914_priv *priv, uint8_t *result); -void tms9914_parallel_poll_configure(gpib_board_t *board, +int tms9914_parallel_poll(struct gpib_board *board, struct tms9914_priv *priv, uint8_t *result); +void tms9914_parallel_poll_configure(struct gpib_board *board, struct tms9914_priv *priv, uint8_t config); -void tms9914_parallel_poll_response(gpib_board_t *board, +void tms9914_parallel_poll_response(struct gpib_board *board, struct tms9914_priv *priv, int ist); -void tms9914_serial_poll_response(gpib_board_t *board, struct tms9914_priv *priv, uint8_t status); -uint8_t tms9914_serial_poll_status(gpib_board_t *board, struct tms9914_priv *priv); -int tms9914_line_status(const gpib_board_t *board, struct tms9914_priv *priv); -unsigned int tms9914_t1_delay(gpib_board_t *board, struct tms9914_priv *priv, +void tms9914_serial_poll_response(struct gpib_board *board, struct tms9914_priv *priv, uint8_t status); +uint8_t tms9914_serial_poll_status(struct gpib_board *board, struct tms9914_priv *priv); +int tms9914_line_status(const struct gpib_board *board, struct tms9914_priv *priv); +unsigned int tms9914_t1_delay(struct gpib_board *board, struct tms9914_priv *priv, unsigned int nano_sec); -void tms9914_return_to_local(const gpib_board_t *board, struct tms9914_priv *priv); +void tms9914_return_to_local(const struct gpib_board *board, struct tms9914_priv *priv); // utility functions void tms9914_board_reset(struct tms9914_priv *priv); -void tms9914_online(gpib_board_t *board, struct tms9914_priv *priv); +void tms9914_online(struct gpib_board *board, struct tms9914_priv *priv); void tms9914_release_holdoff(struct tms9914_priv *priv); void tms9914_set_holdoff_mode(struct tms9914_priv *priv, enum tms9914_holdoff_mode mode); @@ -130,8 +130,8 @@ uint8_t tms9914_iomem_read_byte(struct tms9914_priv *priv, unsigned int register void tms9914_iomem_write_byte(struct tms9914_priv *priv, uint8_t data, unsigned int register_num); // interrupt service routine -irqreturn_t tms9914_interrupt(gpib_board_t *board, struct tms9914_priv *priv); -irqreturn_t tms9914_interrupt_have_status(gpib_board_t *board, struct tms9914_priv *priv, +irqreturn_t tms9914_interrupt(struct gpib_board *board, struct tms9914_priv *priv); +irqreturn_t tms9914_interrupt_have_status(struct gpib_board *board, struct tms9914_priv *priv, int status1, int status2); // tms9914 has 8 registers
diff --git a/drivers/staging/gpib/ines/Makefile b/drivers/staging/gpib/ines/Makefile index 6b6e480..88241f1 100644 --- a/drivers/staging/gpib/ines/Makefile +++ b/drivers/staging/gpib/ines/Makefile
@@ -1,4 +1,3 @@ -ccflags-$(CONFIG_GPIB_PCMCIA) := -DGPIB_PCMCIA obj-$(CONFIG_GPIB_INES) += ines_gpib.o
diff --git a/drivers/staging/gpib/ines/ines.h b/drivers/staging/gpib/ines/ines.h index 3918737..ff27f05 100644 --- a/drivers/staging/gpib/ines/ines.h +++ b/drivers/staging/gpib/ines/ines.h
@@ -36,41 +36,41 @@ struct ines_priv { }; // interface functions -int ines_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *end, size_t *bytes_read); -int ines_write(gpib_board_t *board, uint8_t *buffer, size_t length, +int ines_read(struct gpib_board *board, uint8_t *buffer, size_t length, int *end, size_t *bytes_read); +int ines_write(struct gpib_board *board, uint8_t *buffer, size_t length, int send_eoi, size_t *bytes_written); -int ines_accel_read(gpib_board_t *board, uint8_t *buffer, size_t length, +int ines_accel_read(struct gpib_board *board, uint8_t *buffer, size_t length, int *end, size_t *bytes_read); -int ines_accel_write(gpib_board_t *board, uint8_t *buffer, size_t length, +int ines_accel_write(struct gpib_board *board, uint8_t *buffer, size_t length, int send_eoi, size_t *bytes_written); -int ines_command(gpib_board_t *board, uint8_t *buffer, size_t length, size_t *bytes_written); -int ines_take_control(gpib_board_t *board, int synchronous); -int ines_go_to_standby(gpib_board_t *board); -void ines_request_system_control(gpib_board_t *board, int request_control); -void ines_interface_clear(gpib_board_t *board, int assert); -void ines_remote_enable(gpib_board_t *board, int enable); -int ines_enable_eos(gpib_board_t *board, uint8_t eos_byte, int compare_8_bits); -void ines_disable_eos(gpib_board_t *board); -unsigned int ines_update_status(gpib_board_t *board, unsigned int clear_mask); -int ines_primary_address(gpib_board_t *board, unsigned int address); -int ines_secondary_address(gpib_board_t *board, unsigned int address, int enable); -int ines_parallel_poll(gpib_board_t *board, uint8_t *result); -void ines_parallel_poll_configure(gpib_board_t *board, uint8_t config); -void ines_parallel_poll_response(gpib_board_t *board, int ist); -void ines_serial_poll_response(gpib_board_t *board, uint8_t status); -uint8_t ines_serial_poll_status(gpib_board_t *board); -int ines_line_status(const gpib_board_t *board); -unsigned int ines_t1_delay(gpib_board_t *board, unsigned int nano_sec); -void ines_return_to_local(gpib_board_t *board); +int ines_command(struct gpib_board *board, uint8_t *buffer, size_t length, size_t *bytes_written); +int ines_take_control(struct gpib_board *board, int synchronous); +int ines_go_to_standby(struct gpib_board *board); +void ines_request_system_control(struct gpib_board *board, int request_control); +void ines_interface_clear(struct gpib_board *board, int assert); +void ines_remote_enable(struct gpib_board *board, int enable); +int ines_enable_eos(struct gpib_board *board, uint8_t eos_byte, int compare_8_bits); +void ines_disable_eos(struct gpib_board *board); +unsigned int ines_update_status(struct gpib_board *board, unsigned int clear_mask); +int ines_primary_address(struct gpib_board *board, unsigned int address); +int ines_secondary_address(struct gpib_board *board, unsigned int address, int enable); +int ines_parallel_poll(struct gpib_board *board, uint8_t *result); +void ines_parallel_poll_configure(struct gpib_board *board, uint8_t config); +void ines_parallel_poll_response(struct gpib_board *board, int ist); +void ines_serial_poll_response(struct gpib_board *board, uint8_t status); +uint8_t ines_serial_poll_status(struct gpib_board *board); +int ines_line_status(const struct gpib_board *board); +int ines_t1_delay(struct gpib_board *board, unsigned int nano_sec); +void ines_return_to_local(struct gpib_board *board); // interrupt service routines irqreturn_t ines_pci_interrupt(int irq, void *arg); -irqreturn_t ines_interrupt(gpib_board_t *board); +irqreturn_t ines_interrupt(struct gpib_board *board); // utility functions -void ines_free_private(gpib_board_t *board); -int ines_generic_attach(gpib_board_t *board); -void ines_online(struct ines_priv *priv, const gpib_board_t *board, int use_accel); +void ines_free_private(struct gpib_board *board); +int ines_generic_attach(struct gpib_board *board); +void ines_online(struct ines_priv *priv, const struct gpib_board *board, int use_accel); void ines_set_xfer_counter(struct ines_priv *priv, unsigned int count); /* inb/outb wrappers */
diff --git a/drivers/staging/gpib/ines/ines_gpib.c b/drivers/staging/gpib/ines/ines_gpib.c index 22a05a2..d93eb05d 100644 --- a/drivers/staging/gpib/ines/ines_gpib.c +++ b/drivers/staging/gpib/ines/ines_gpib.c
@@ -5,6 +5,10 @@ * (C) 2002 by Frank Mori Hess ***************************************************************************/ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#define dev_fmt pr_fmt +#define DRV_NAME KBUILD_MODNAME + #include "ines.h" #include <linux/pci.h> @@ -21,34 +25,32 @@ MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("GPIB driver for Ines iGPIB 72010"); -int ines_line_status(const gpib_board_t *board) +int ines_line_status(const struct gpib_board *board) { - int status = ValidALL; + int status = VALID_ALL; int bcm_bits; struct ines_priv *ines_priv; - struct nec7210_priv *nec_priv; ines_priv = board->private_data; - nec_priv = &ines_priv->nec7210_priv; bcm_bits = ines_inb(ines_priv, BUS_CONTROL_MONITOR); if (bcm_bits & BCM_REN_BIT) - status |= BusREN; + status |= BUS_REN; if (bcm_bits & BCM_IFC_BIT) - status |= BusIFC; + status |= BUS_IFC; if (bcm_bits & BCM_SRQ_BIT) - status |= BusSRQ; + status |= BUS_SRQ; if (bcm_bits & BCM_EOI_BIT) - status |= BusEOI; + status |= BUS_EOI; if (bcm_bits & BCM_NRFD_BIT) - status |= BusNRFD; + status |= BUS_NRFD; if (bcm_bits & BCM_NDAC_BIT) - status |= BusNDAC; + status |= BUS_NDAC; if (bcm_bits & BCM_DAV_BIT) - status |= BusDAV; + status |= BUS_DAV; if (bcm_bits & BCM_ATN_BIT) - status |= BusATN; + status |= BUS_ATN; return status; } @@ -56,14 +58,14 @@ int ines_line_status(const gpib_board_t *board) void ines_set_xfer_counter(struct ines_priv *priv, unsigned int count) { if (count > 0xffff) { - pr_err("ines: bug! tried to set xfer counter > 0xffff\n"); + pr_err("bug! tried to set xfer counter > 0xffff\n"); return; } ines_outb(priv, (count >> 8) & 0xff, XFER_COUNT_UPPER); ines_outb(priv, count & 0xff, XFER_COUNT_LOWER); } -unsigned int ines_t1_delay(gpib_board_t *board, unsigned int nano_sec) +int ines_t1_delay(struct gpib_board *board, unsigned int nano_sec) { struct ines_priv *ines_priv = board->private_data; struct nec7210_priv *nec_priv = &ines_priv->nec7210_priv; @@ -93,7 +95,7 @@ static inline unsigned short num_in_fifo_bytes(struct ines_priv *ines_priv) return ines_inb(ines_priv, IN_FIFO_COUNT); } -static ssize_t pio_read(gpib_board_t *board, struct ines_priv *ines_priv, uint8_t *buffer, +static ssize_t pio_read(struct gpib_board *board, struct ines_priv *ines_priv, uint8_t *buffer, size_t length, size_t *nbytes) { ssize_t retval = 0; @@ -106,21 +108,18 @@ static ssize_t pio_read(gpib_board_t *board, struct ines_priv *ines_priv, uint8_ num_in_fifo_bytes(ines_priv) || test_bit(RECEIVED_END_BN, &nec_priv->state) || test_bit(DEV_CLEAR_BN, &nec_priv->state) || - test_bit(TIMO_NUM, &board->status))) { - pr_warn("gpib: pio read wait interrupted\n"); + test_bit(TIMO_NUM, &board->status))) return -ERESTARTSYS; - } + if (test_bit(TIMO_NUM, &board->status)) return -ETIMEDOUT; if (test_bit(DEV_CLEAR_BN, &nec_priv->state)) return -EINTR; num_fifo_bytes = num_in_fifo_bytes(ines_priv); - if (num_fifo_bytes + *nbytes > length) { - pr_warn("ines: counter allowed %li extra byte(s)\n", - (long)(num_fifo_bytes - (length - *nbytes))); + if (num_fifo_bytes + *nbytes > length) num_fifo_bytes = length - *nbytes; - } + for (i = 0; i < num_fifo_bytes; i++) buffer[(*nbytes)++] = read_byte(nec_priv, DIR); if (test_bit(RECEIVED_END_BN, &nec_priv->state) && @@ -134,7 +133,7 @@ static ssize_t pio_read(gpib_board_t *board, struct ines_priv *ines_priv, uint8_ return retval; } -int ines_accel_read(gpib_board_t *board, uint8_t *buffer, +int ines_accel_read(struct gpib_board *board, uint8_t *buffer, size_t length, int *end, size_t *bytes_read) { ssize_t retval = 0; @@ -191,7 +190,7 @@ static inline unsigned short num_out_fifo_bytes(struct ines_priv *ines_priv) return ines_inb(ines_priv, OUT_FIFO_COUNT); } -static int ines_write_wait(gpib_board_t *board, struct ines_priv *ines_priv, +static int ines_write_wait(struct gpib_board *board, struct ines_priv *ines_priv, unsigned int fifo_threshold) { struct nec7210_priv *nec_priv = &ines_priv->nec7210_priv; @@ -201,10 +200,9 @@ static int ines_write_wait(gpib_board_t *board, struct ines_priv *ines_priv, num_out_fifo_bytes(ines_priv) < fifo_threshold || test_bit(BUS_ERROR_BN, &nec_priv->state) || test_bit(DEV_CLEAR_BN, &nec_priv->state) || - test_bit(TIMO_NUM, &board->status))) { - dev_dbg(board->gpib_dev, "gpib write interrupted\n"); + test_bit(TIMO_NUM, &board->status))) return -ERESTARTSYS; - } + if (test_bit(BUS_ERROR_BN, &nec_priv->state)) return -EIO; if (test_bit(DEV_CLEAR_BN, &nec_priv->state)) @@ -215,7 +213,7 @@ static int ines_write_wait(gpib_board_t *board, struct ines_priv *ines_priv, return 0; } -int ines_accel_write(gpib_board_t *board, uint8_t *buffer, size_t length, +int ines_accel_write(struct gpib_board *board, uint8_t *buffer, size_t length, int send_eoi, size_t *bytes_written) { size_t count = 0; @@ -268,7 +266,7 @@ int ines_accel_write(gpib_board_t *board, uint8_t *buffer, size_t length, irqreturn_t ines_pci_interrupt(int irq, void *arg) { - gpib_board_t *board = arg; + struct gpib_board *board = arg; struct ines_priv *priv = board->private_data; struct nec7210_priv *nec_priv = &priv->nec7210_priv; @@ -283,7 +281,7 @@ irqreturn_t ines_pci_interrupt(int irq, void *arg) return ines_interrupt(board); } -irqreturn_t ines_interrupt(gpib_board_t *board) +irqreturn_t ines_interrupt(struct gpib_board *board) { struct ines_priv *priv = board->private_data; struct nec7210_priv *nec_priv = &priv->nec7210_priv; @@ -301,7 +299,7 @@ irqreturn_t ines_interrupt(gpib_board_t *board) wake++; } if (isr3_bits & FIFO_ERROR_BIT) - pr_err("ines gpib: fifo error\n"); + dev_err(board->gpib_dev, "fifo error\n"); if (isr3_bits & XFER_COUNT_BIT) wake++; @@ -315,12 +313,12 @@ irqreturn_t ines_interrupt(gpib_board_t *board) return IRQ_HANDLED; } -static int ines_pci_attach(gpib_board_t *board, const gpib_board_config_t *config); -static int ines_pci_accel_attach(gpib_board_t *board, const gpib_board_config_t *config); -static int ines_isa_attach(gpib_board_t *board, const gpib_board_config_t *config); +static int ines_pci_attach(struct gpib_board *board, const gpib_board_config_t *config); +static int ines_pci_accel_attach(struct gpib_board *board, const gpib_board_config_t *config); +static int ines_isa_attach(struct gpib_board *board, const gpib_board_config_t *config); -static void ines_pci_detach(gpib_board_t *board); -static void ines_isa_detach(gpib_board_t *board); +static void ines_pci_detach(struct gpib_board *board); +static void ines_isa_detach(struct gpib_board *board); enum ines_pci_vendor_ids { PCI_VENDOR_ID_INES_QUICKLOGIC = 0x16da @@ -395,7 +393,8 @@ static struct ines_pci_id pci_ids[] = { static const int num_pci_chips = ARRAY_SIZE(pci_ids); // wrappers for interface functions -int ines_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *end, size_t *bytes_read) +int ines_read(struct gpib_board *board, uint8_t *buffer, size_t length, + int *end, size_t *bytes_read) { struct ines_priv *priv = board->private_data; struct nec7210_priv *nec_priv = &priv->nec7210_priv; @@ -413,7 +412,7 @@ int ines_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *end, siz return retval; } -int ines_write(gpib_board_t *board, uint8_t *buffer, size_t length, int send_eoi, +int ines_write(struct gpib_board *board, uint8_t *buffer, size_t length, int send_eoi, size_t *bytes_written) { struct ines_priv *priv = board->private_data; @@ -421,119 +420,119 @@ int ines_write(gpib_board_t *board, uint8_t *buffer, size_t length, int send_eoi return nec7210_write(board, &priv->nec7210_priv, buffer, length, send_eoi, bytes_written); } -int ines_command(gpib_board_t *board, uint8_t *buffer, size_t length, size_t *bytes_written) +int ines_command(struct gpib_board *board, uint8_t *buffer, size_t length, size_t *bytes_written) { struct ines_priv *priv = board->private_data; return nec7210_command(board, &priv->nec7210_priv, buffer, length, bytes_written); } -int ines_take_control(gpib_board_t *board, int synchronous) +int ines_take_control(struct gpib_board *board, int synchronous) { struct ines_priv *priv = board->private_data; return nec7210_take_control(board, &priv->nec7210_priv, synchronous); } -int ines_go_to_standby(gpib_board_t *board) +int ines_go_to_standby(struct gpib_board *board) { struct ines_priv *priv = board->private_data; return nec7210_go_to_standby(board, &priv->nec7210_priv); } -void ines_request_system_control(gpib_board_t *board, int request_control) +void ines_request_system_control(struct gpib_board *board, int request_control) { struct ines_priv *priv = board->private_data; nec7210_request_system_control(board, &priv->nec7210_priv, request_control); } -void ines_interface_clear(gpib_board_t *board, int assert) +void ines_interface_clear(struct gpib_board *board, int assert) { struct ines_priv *priv = board->private_data; nec7210_interface_clear(board, &priv->nec7210_priv, assert); } -void ines_remote_enable(gpib_board_t *board, int enable) +void ines_remote_enable(struct gpib_board *board, int enable) { struct ines_priv *priv = board->private_data; nec7210_remote_enable(board, &priv->nec7210_priv, enable); } -int ines_enable_eos(gpib_board_t *board, uint8_t eos_byte, int compare_8_bits) +int ines_enable_eos(struct gpib_board *board, uint8_t eos_byte, int compare_8_bits) { struct ines_priv *priv = board->private_data; return nec7210_enable_eos(board, &priv->nec7210_priv, eos_byte, compare_8_bits); } -void ines_disable_eos(gpib_board_t *board) +void ines_disable_eos(struct gpib_board *board) { struct ines_priv *priv = board->private_data; nec7210_disable_eos(board, &priv->nec7210_priv); } -unsigned int ines_update_status(gpib_board_t *board, unsigned int clear_mask) +unsigned int ines_update_status(struct gpib_board *board, unsigned int clear_mask) { struct ines_priv *priv = board->private_data; return nec7210_update_status(board, &priv->nec7210_priv, clear_mask); } -int ines_primary_address(gpib_board_t *board, unsigned int address) +int ines_primary_address(struct gpib_board *board, unsigned int address) { struct ines_priv *priv = board->private_data; return nec7210_primary_address(board, &priv->nec7210_priv, address); } -int ines_secondary_address(gpib_board_t *board, unsigned int address, int enable) +int ines_secondary_address(struct gpib_board *board, unsigned int address, int enable) { struct ines_priv *priv = board->private_data; return nec7210_secondary_address(board, &priv->nec7210_priv, address, enable); } -int ines_parallel_poll(gpib_board_t *board, uint8_t *result) +int ines_parallel_poll(struct gpib_board *board, uint8_t *result) { struct ines_priv *priv = board->private_data; return nec7210_parallel_poll(board, &priv->nec7210_priv, result); } -void ines_parallel_poll_configure(gpib_board_t *board, uint8_t config) +void ines_parallel_poll_configure(struct gpib_board *board, uint8_t config) { struct ines_priv *priv = board->private_data; nec7210_parallel_poll_configure(board, &priv->nec7210_priv, config); } -void ines_parallel_poll_response(gpib_board_t *board, int ist) +void ines_parallel_poll_response(struct gpib_board *board, int ist) { struct ines_priv *priv = board->private_data; nec7210_parallel_poll_response(board, &priv->nec7210_priv, ist); } -void ines_serial_poll_response(gpib_board_t *board, uint8_t status) +void ines_serial_poll_response(struct gpib_board *board, uint8_t status) { struct ines_priv *priv = board->private_data; nec7210_serial_poll_response(board, &priv->nec7210_priv, status); } -uint8_t ines_serial_poll_status(gpib_board_t *board) +uint8_t ines_serial_poll_status(struct gpib_board *board) { struct ines_priv *priv = board->private_data; return nec7210_serial_poll_status(board, &priv->nec7210_priv); } -void ines_return_to_local(gpib_board_t *board) +void ines_return_to_local(struct gpib_board *board) { struct ines_priv *priv = board->private_data; @@ -652,7 +651,7 @@ static gpib_interface_t ines_isa_interface = { .return_to_local = ines_return_to_local, }; -static int ines_allocate_private(gpib_board_t *board) +static int ines_allocate_private(struct gpib_board *board) { struct ines_priv *priv; @@ -665,13 +664,13 @@ static int ines_allocate_private(gpib_board_t *board) return 0; } -void ines_free_private(gpib_board_t *board) +void ines_free_private(struct gpib_board *board) { kfree(board->private_data); board->private_data = NULL; } -int ines_generic_attach(gpib_board_t *board) +int ines_generic_attach(struct gpib_board *board) { struct ines_priv *ines_priv; struct nec7210_priv *nec_priv; @@ -691,7 +690,7 @@ int ines_generic_attach(gpib_board_t *board) return 0; } -void ines_online(struct ines_priv *ines_priv, const gpib_board_t *board, int use_accel) +void ines_online(struct ines_priv *ines_priv, const struct gpib_board *board, int use_accel) { struct nec7210_priv *nec_priv = &ines_priv->nec7210_priv; @@ -725,7 +724,7 @@ void ines_online(struct ines_priv *ines_priv, const gpib_board_t *board, int use nec7210_set_reg_bits(nec_priv, IMR1, HR_DOIE | HR_DIIE, 0); } -static int ines_common_pci_attach(gpib_board_t *board, const gpib_board_config_t *config) +static int ines_common_pci_attach(struct gpib_board *board, const gpib_board_config_t *config) { struct ines_priv *ines_priv; struct nec7210_priv *nec_priv; @@ -769,16 +768,16 @@ static int ines_common_pci_attach(gpib_board_t *board, const gpib_board_config_t } while (1); } if (!ines_priv->pci_device) { - pr_err("gpib: could not find ines PCI board\n"); + dev_err(board->gpib_dev, "could not find ines PCI board\n"); return -1; } if (pci_enable_device(ines_priv->pci_device)) { - pr_err("error enabling pci device\n"); + dev_err(board->gpib_dev, "error enabling pci device\n"); return -1; } - if (pci_request_regions(ines_priv->pci_device, "ines-gpib")) + if (pci_request_regions(ines_priv->pci_device, DRV_NAME)) return -1; nec_priv->iobase = pci_resource_start(ines_priv->pci_device, found_id.gpib_region); @@ -797,7 +796,7 @@ static int ines_common_pci_attach(gpib_board_t *board, const gpib_board_config_t case PCI_CHIP_QUICKLOGIC5030: break; default: - pr_err("gpib: unspecified chip type? (bug)\n"); + dev_err(board->gpib_dev, "unspecified chip type? (bug)\n"); nec_priv->iobase = 0; pci_release_regions(ines_priv->pci_device); return -1; @@ -813,8 +812,8 @@ static int ines_common_pci_attach(gpib_board_t *board, const gpib_board_config_t #endif isr_flags |= IRQF_SHARED; if (request_irq(ines_priv->pci_device->irq, ines_pci_interrupt, isr_flags, - "pci-gpib", board)) { - pr_err("gpib: can't request IRQ %d\n", ines_priv->pci_device->irq); + DRV_NAME, board)) { + dev_err(board->gpib_dev, "can't request IRQ %d\n", ines_priv->pci_device->irq); return -1; } ines_priv->irq = ines_priv->pci_device->irq; @@ -846,14 +845,14 @@ static int ines_common_pci_attach(gpib_board_t *board, const gpib_board_config_t case PCI_CHIP_QUICKLOGIC5030: break; default: - pr_err("gpib: unspecified chip type? (bug)\n"); + dev_err(board->gpib_dev, "unspecified chip type? (bug)\n"); return -1; } return 0; } -int ines_pci_attach(gpib_board_t *board, const gpib_board_config_t *config) +int ines_pci_attach(struct gpib_board *board, const gpib_board_config_t *config) { struct ines_priv *ines_priv; int retval; @@ -868,7 +867,7 @@ int ines_pci_attach(gpib_board_t *board, const gpib_board_config_t *config) return 0; } -int ines_pci_accel_attach(gpib_board_t *board, const gpib_board_config_t *config) +int ines_pci_accel_attach(struct gpib_board *board, const gpib_board_config_t *config) { struct ines_priv *ines_priv; int retval; @@ -885,7 +884,7 @@ int ines_pci_accel_attach(gpib_board_t *board, const gpib_board_config_t *config static const int ines_isa_iosize = 0x20; -int ines_isa_attach(gpib_board_t *board, const gpib_board_config_t *config) +int ines_isa_attach(struct gpib_board *board, const gpib_board_config_t *config) { struct ines_priv *ines_priv; struct nec7210_priv *nec_priv; @@ -899,15 +898,16 @@ int ines_isa_attach(gpib_board_t *board, const gpib_board_config_t *config) ines_priv = board->private_data; nec_priv = &ines_priv->nec7210_priv; - if (!request_region(config->ibbase, ines_isa_iosize, "ines_gpib")) { - pr_err("ines_gpib: ioports at 0x%x already in use\n", config->ibbase); - return -1; + if (!request_region(config->ibbase, ines_isa_iosize, DRV_NAME)) { + dev_err(board->gpib_dev, "ioports at 0x%x already in use\n", + config->ibbase); + return -EBUSY; } nec_priv->iobase = config->ibbase; nec_priv->offset = 1; nec7210_board_reset(nec_priv, board); - if (request_irq(config->ibirq, ines_pci_interrupt, isr_flags, "ines_gpib", board)) { - pr_err("ines_gpib: failed to allocate IRQ %d\n", config->ibirq); + if (request_irq(config->ibirq, ines_pci_interrupt, isr_flags, DRV_NAME, board)) { + dev_err(board->gpib_dev, "failed to allocate IRQ %d\n", config->ibirq); return -1; } ines_priv->irq = config->ibirq; @@ -915,7 +915,7 @@ int ines_isa_attach(gpib_board_t *board, const gpib_board_config_t *config) return 0; } -void ines_pci_detach(gpib_board_t *board) +void ines_pci_detach(struct gpib_board *board) { struct ines_priv *ines_priv = board->private_data; struct nec7210_priv *nec_priv; @@ -949,7 +949,7 @@ void ines_pci_detach(gpib_board_t *board) ines_free_private(board); } -void ines_isa_detach(gpib_board_t *board) +void ines_isa_detach(struct gpib_board *board) { struct ines_priv *ines_priv = board->private_data; struct nec7210_priv *nec_priv; @@ -977,7 +977,7 @@ static struct pci_driver ines_pci_driver = { .probe = &ines_pci_probe }; -#ifdef GPIB_PCMCIA +#ifdef CONFIG_GPIB_PCMCIA #include <linux/kernel.h> #include <linux/ptrace.h> @@ -988,13 +988,6 @@ static struct pci_driver ines_pci_driver = { #include <pcmcia/ds.h> #include <pcmcia/cisreg.h> -#ifdef PCMCIA_DEBUG -static int pc_debug = PCMCIA_DEBUG; -#define DEBUG(n, args...) do {if (pc_debug > (n)) pr_debug(args)} while (0) -#else -#define DEBUG(args...) -#endif - static const int ines_pcmcia_iosize = 0x20; /* The event() function is this driver's Card Services event handler. @@ -1007,11 +1000,11 @@ static const int ines_pcmcia_iosize = 0x20; static int ines_gpib_config(struct pcmcia_device *link); static void ines_gpib_release(struct pcmcia_device *link); -static int ines_pcmcia_attach(gpib_board_t *board, const gpib_board_config_t *config); -static int ines_pcmcia_accel_attach(gpib_board_t *board, const gpib_board_config_t *config); -static void ines_pcmcia_detach(gpib_board_t *board); +static int ines_pcmcia_attach(struct gpib_board *board, const gpib_board_config_t *config); +static int ines_pcmcia_accel_attach(struct gpib_board *board, const gpib_board_config_t *config); +static void ines_pcmcia_detach(struct gpib_board *board); static irqreturn_t ines_pcmcia_interrupt(int irq, void *arg); -static int ines_common_pcmcia_attach(gpib_board_t *board); +static int ines_common_pcmcia_attach(struct gpib_board *board); /* * A linked list of "instances" of the gpib device. Each actual * PCMCIA card corresponds to one device instance, and is described @@ -1043,7 +1036,7 @@ static struct pcmcia_device *curr_dev; struct local_info { struct pcmcia_device *p_dev; - gpib_board_t *dev; + struct gpib_board *dev; u_short manfid; u_short cardid; }; @@ -1063,8 +1056,6 @@ static int ines_gpib_probe(struct pcmcia_device *link) // int ret, i; - DEBUG(0, "%s(0x%p)\n", __func__ link); - /* Allocate space for private device-specific data */ info = kzalloc(sizeof(*info), GFP_KERNEL); if (!info) @@ -1096,9 +1087,7 @@ static int ines_gpib_probe(struct pcmcia_device *link) static void ines_gpib_remove(struct pcmcia_device *link) { struct local_info *info = link->priv; - //struct gpib_board_t *dev = info->dev; - - DEBUG(0, "%s(0x%p)\n", __func__, link); + //struct struct gpib_board *dev = info->dev; if (info->dev) ines_pcmcia_detach(info->dev); @@ -1125,7 +1114,6 @@ static int ines_gpib_config(struct pcmcia_device *link) void __iomem *virt; dev = link->priv; - DEBUG(0, "%s(0x%p)\n", __func__, link); retval = pcmcia_loop_config(link, &ines_gpib_config_iteration, NULL); if (retval) { @@ -1134,8 +1122,8 @@ static int ines_gpib_config(struct pcmcia_device *link) return -ENODEV; } - pr_debug("ines_cs: manufacturer: 0x%x card: 0x%x\n", - link->manf_id, link->card_id); + dev_dbg(&link->dev, "ines_cs: manufacturer: 0x%x card: 0x%x\n", + link->manf_id, link->card_id); /* for the ines card we have to setup the configuration registers in * attribute memory here @@ -1167,7 +1155,6 @@ static int ines_gpib_config(struct pcmcia_device *link) ines_gpib_release(link); return -ENODEV; } - pr_info("ines gpib device loaded\n"); return 0; } /* gpib_config */ @@ -1179,18 +1166,16 @@ static int ines_gpib_config(struct pcmcia_device *link) static void ines_gpib_release(struct pcmcia_device *link) { - DEBUG(0, "%s(0x%p)\n", __func__, link); pcmcia_disable_device(link); } /* gpib_release */ static int ines_gpib_suspend(struct pcmcia_device *link) { //struct local_info *info = link->priv; - //struct gpib_board_t *dev = info->dev; - DEBUG(0, "%s(0x%p)\n", __func__, link); + //struct struct gpib_board *dev = info->dev; if (link->open) - pr_err("Device still open ???\n"); + dev_err(&link->dev, "Device still open\n"); //netif_device_detach(dev); return 0; @@ -1199,12 +1184,10 @@ static int ines_gpib_suspend(struct pcmcia_device *link) static int ines_gpib_resume(struct pcmcia_device *link) { //struct local_info_t *info = link->priv; - //struct gpib_board_t *dev = info->dev; - DEBUG(0, "%s(0x%p)\n", __func__, link); + //struct struct gpib_board *dev = info->dev; /*if (link->open) { * ni_gpib_probe(dev); / really? - * printk("Gpib resumed ???\n"); * //netif_device_attach(dev); *} */ @@ -1229,7 +1212,6 @@ static struct pcmcia_driver ines_gpib_cs_driver = { void ines_pcmcia_cleanup_module(void) { - DEBUG(0, "ines_cs: unloading\n"); pcmcia_unregister_driver(&ines_gpib_cs_driver); } @@ -1319,19 +1301,19 @@ static gpib_interface_t ines_pcmcia_interface = { irqreturn_t ines_pcmcia_interrupt(int irq, void *arg) { - gpib_board_t *board = arg; + struct gpib_board *board = arg; return ines_interrupt(board); } -int ines_common_pcmcia_attach(gpib_board_t *board) +int ines_common_pcmcia_attach(struct gpib_board *board) { struct ines_priv *ines_priv; struct nec7210_priv *nec_priv; int retval; if (!curr_dev) { - pr_err("no ines pcmcia cards found\n"); + dev_err(board->gpib_dev, "no ines pcmcia cards found\n"); return -1; } @@ -1343,9 +1325,9 @@ int ines_common_pcmcia_attach(gpib_board_t *board) nec_priv = &ines_priv->nec7210_priv; if (!request_region(curr_dev->resource[0]->start, - resource_size(curr_dev->resource[0]), "ines_gpib")) { - pr_err("ines_gpib: ioports at 0x%lx already in use\n", - (unsigned long)(curr_dev->resource[0]->start)); + resource_size(curr_dev->resource[0]), DRV_NAME)) { + dev_err(board->gpib_dev, "ioports at 0x%lx already in use\n", + (unsigned long)(curr_dev->resource[0]->start)); return -1; } @@ -1355,7 +1337,7 @@ int ines_common_pcmcia_attach(gpib_board_t *board) if (request_irq(curr_dev->irq, ines_pcmcia_interrupt, IRQF_SHARED, "pcmcia-gpib", board)) { - pr_err("gpib: can't request IRQ %d\n", curr_dev->irq); + dev_err(board->gpib_dev, "can't request IRQ %d\n", curr_dev->irq); return -1; } ines_priv->irq = curr_dev->irq; @@ -1363,7 +1345,7 @@ int ines_common_pcmcia_attach(gpib_board_t *board) return 0; } -int ines_pcmcia_attach(gpib_board_t *board, const gpib_board_config_t *config) +int ines_pcmcia_attach(struct gpib_board *board, const gpib_board_config_t *config) { struct ines_priv *ines_priv; int retval; @@ -1378,7 +1360,7 @@ int ines_pcmcia_attach(gpib_board_t *board, const gpib_board_config_t *config) return 0; } -int ines_pcmcia_accel_attach(gpib_board_t *board, const gpib_board_config_t *config) +int ines_pcmcia_accel_attach(struct gpib_board *board, const gpib_board_config_t *config) { struct ines_priv *ines_priv; int retval; @@ -1393,7 +1375,7 @@ int ines_pcmcia_accel_attach(gpib_board_t *board, const gpib_board_config_t *con return 0; } -void ines_pcmcia_detach(gpib_board_t *board) +void ines_pcmcia_detach(struct gpib_board *board) { struct ines_priv *ines_priv = board->private_data; struct nec7210_priv *nec_priv; @@ -1410,7 +1392,7 @@ void ines_pcmcia_detach(gpib_board_t *board) ines_free_private(board); } -#endif /* GPIB_PCMCIA */ +#endif /* CONFIG_GPIB_PCMCIA */ static int __init ines_init_module(void) { @@ -1418,63 +1400,63 @@ static int __init ines_init_module(void) ret = pci_register_driver(&ines_pci_driver); if (ret) { - pr_err("ines_gpib: pci_register_driver failed: error = %d\n", ret); + pr_err("pci_register_driver failed: error = %d\n", ret); return ret; } ret = gpib_register_driver(&ines_pci_interface, THIS_MODULE); if (ret) { - pr_err("ines_gpib: gpib_register_driver failed: error = %d\n", ret); + pr_err("gpib_register_driver failed: error = %d\n", ret); goto err_pci; } ret = gpib_register_driver(&ines_pci_unaccel_interface, THIS_MODULE); if (ret) { - pr_err("ines_gpib: gpib_register_driver failed: error = %d\n", ret); + pr_err("gpib_register_driver failed: error = %d\n", ret); goto err_pci_unaccel; } ret = gpib_register_driver(&ines_pci_accel_interface, THIS_MODULE); if (ret) { - pr_err("ines_gpib: gpib_register_driver failed: error = %d\n", ret); + pr_err("gpib_register_driver failed: error = %d\n", ret); goto err_pci_accel; } ret = gpib_register_driver(&ines_isa_interface, THIS_MODULE); if (ret) { - pr_err("ines_gpib: gpib_register_driver failed: error = %d\n", ret); + pr_err("gpib_register_driver failed: error = %d\n", ret); goto err_isa; } -#ifdef GPIB_PCMCIA +#ifdef CONFIG_GPIB_PCMCIA ret = gpib_register_driver(&ines_pcmcia_interface, THIS_MODULE); if (ret) { - pr_err("ines_gpib: gpib_register_driver failed: error = %d\n", ret); + pr_err("gpib_register_driver failed: error = %d\n", ret); goto err_pcmcia; } ret = gpib_register_driver(&ines_pcmcia_unaccel_interface, THIS_MODULE); if (ret) { - pr_err("ines_gpib: gpib_register_driver failed: error = %d\n", ret); + pr_err("gpib_register_driver failed: error = %d\n", ret); goto err_pcmcia_unaccel; } ret = gpib_register_driver(&ines_pcmcia_accel_interface, THIS_MODULE); if (ret) { - pr_err("ines_gpib: gpib_register_driver failed: error = %d\n", ret); + pr_err("gpib_register_driver failed: error = %d\n", ret); goto err_pcmcia_accel; } ret = pcmcia_register_driver(&ines_gpib_cs_driver); if (ret) { - pr_err("ines_gpib: pcmcia_register_driver failed: error = %d\n", ret); + pr_err("pcmcia_register_driver failed: error = %d\n", ret); goto err_pcmcia_driver; } #endif return 0; -#ifdef GPIB_PCMCIA +#ifdef CONFIG_GPIB_PCMCIA err_pcmcia_driver: gpib_unregister_driver(&ines_pcmcia_accel_interface); err_pcmcia_accel:
diff --git a/drivers/staging/gpib/lpvo_usb_gpib/lpvo_usb_gpib.c b/drivers/staging/gpib/lpvo_usb_gpib/lpvo_usb_gpib.c index 85322af..faf96e9 100644 --- a/drivers/staging/gpib/lpvo_usb_gpib/lpvo_usb_gpib.c +++ b/drivers/staging/gpib/lpvo_usb_gpib/lpvo_usb_gpib.c
@@ -8,6 +8,10 @@ * copyright : (C) 2011 Marcello Carla' * ***************************************************************************/ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#define dev_fmt pr_fmt +#define NAME KBUILD_MODNAME + /* base module includes */ #include <linux/module.h> @@ -31,8 +35,6 @@ MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("GPIB driver for LPVO usb devices"); -#define NAME "lpvo_usb_gpib" - /* * Table of devices that work with this driver. * @@ -55,10 +57,11 @@ MODULE_DEVICE_TABLE(usb, skel_table); /* * *** Diagnostics and Debug *** - * + * To enable the diagnostic and debug messages either compile with DEBUG set + * or control via the dynamic debug mechanisms. * The module parameter "debug" controls the sending of debug messages to - * syslog. By default it is set to 0 or 1 according to GPIB_CONFIG_KERNEL_DEBUG. - * debug = 0: only register/deregister messages are generated + * syslog. By default it is set to 0 + * debug = 0: only attach/detach messages are sent * 1: every action is logged * 2: extended logging; each single exchanged byte is documented * (about twice the log volume of [1]) @@ -70,11 +73,15 @@ MODULE_DEVICE_TABLE(usb, skel_table); static int debug; module_param(debug, int, 0644); -#define DIA_LOG(level, format, ...) \ +#define DIA_LOG(level, format, ...) \ do { if (debug >= (level)) \ - pr_alert("%s:%s - " format, NAME, __func__, ## __VA_ARGS__); } \ + dev_dbg(board->gpib_dev, format, ## __VA_ARGS__); } \ while (0) +#define WQT wait_queue_entry_t +#define WQH head +#define WQE entry + /* standard and extended command sets of the usb-gpib adapter */ #define USB_GPIB_ON "\nIB\n" @@ -135,7 +142,7 @@ struct char_buf { /* used by one_char() routine */ }; struct usb_gpib_priv { /* private data to the device */ - u8 eos; /* eos character */ + u8 eos; /* eos character */ short eos_flags; /* eos mode */ int timeout; /* current value for timeout */ void *dev; /* the usb device private data structure */ @@ -143,42 +150,23 @@ struct usb_gpib_priv { /* private data to the device */ #define GPIB_DEV (((struct usb_gpib_priv *)board->private_data)->dev) -#define SHOW_STATUS(board) { \ - DIA_LOG(2, "# - board %p\n", board); \ - DIA_LOG(2, "# - buffer_length %d\n", board->buffer_length); \ - DIA_LOG(2, "# - status %lx\n", board->status); \ - DIA_LOG(2, "# - use_count %d\n", board->use_count); \ - DIA_LOG(2, "# - pad %x\n", board->pad); \ - DIA_LOG(2, "# - sad %x\n", board->sad); \ - DIA_LOG(2, "# - timeout %d\n", board->usec_timeout); \ - DIA_LOG(2, "# - ppc %d\n", board->parallel_poll_configuration); \ - DIA_LOG(2, "# - t1delay %d\n", board->t1_nano_sec); \ - DIA_LOG(2, "# - online %d\n", board->online); \ - DIA_LOG(2, "# - autopoll %d\n", board->autospollers); \ - DIA_LOG(2, "# - autopoll task %p\n", board->autospoll_task); \ - DIA_LOG(2, "# - minor %d\n", board->minor); \ - DIA_LOG(2, "# - master %d\n", board->master); \ - DIA_LOG(2, "# - list %d\n", board->ist); \ - } -/* - * n = 0; - * list_for_each (l, &board->device_list) n++; - * TTY_LOG ("%s:%s - devices in list %d\n", a, b, n); - */ - -/* - * TTY_LOG - write a message to the current work terminal (if any) - */ - -#define TTY_LOG(format, ...) { \ - char buf[128]; \ - struct tty_struct *tty = get_current_tty(); \ - if (tty) { \ - snprintf(buf, 128, format, __VA_ARGS__); \ - tty->driver->ops->write(tty, buf, strlen(buf)); \ - tty->driver->ops->write(tty, "\r", 1); \ - } \ - } +static void show_status(struct gpib_board *board) +{ + DIA_LOG(2, "# - buffer_length %d\n", board->buffer_length); + DIA_LOG(2, "# - status %lx\n", board->status); + DIA_LOG(2, "# - use_count %d\n", board->use_count); + DIA_LOG(2, "# - pad %x\n", board->pad); + DIA_LOG(2, "# - sad %x\n", board->sad); + DIA_LOG(2, "# - timeout %d\n", board->usec_timeout); + DIA_LOG(2, "# - ppc %d\n", board->parallel_poll_configuration); + DIA_LOG(2, "# - t1delay %d\n", board->t1_nano_sec); + DIA_LOG(2, "# - online %d\n", board->online); + DIA_LOG(2, "# - autopoll %d\n", board->autospollers); + DIA_LOG(2, "# - autopoll task %p\n", board->autospoll_task); + DIA_LOG(2, "# - minor %d\n", board->minor); + DIA_LOG(2, "# - master %d\n", board->master); + DIA_LOG(2, "# - list %d\n", board->ist); +} /* * GLOBAL VARIABLES: required for @@ -200,8 +188,8 @@ static struct mutex minors_lock; /* operations on usb_minors are to be prote struct usb_skel; static ssize_t skel_do_write(struct usb_skel *, const char *, size_t); static ssize_t skel_do_read(struct usb_skel *, char *, size_t); -static int skel_do_open(gpib_board_t *, int); -static int skel_do_release(gpib_board_t *); +static int skel_do_open(struct gpib_board *, int); +static int skel_do_release(struct gpib_board *); /* * usec_diff : take difference in MICROsec between two 'timespec' @@ -229,27 +217,7 @@ static inline int usec_diff(struct timespec64 *a, struct timespec64 *b) static int write_loop(void *dev, char *msg, int leng) { -// int nchar = 0, val; - -// do { - return skel_do_write(dev, msg, leng); - -// if (val < 1) { -// printk (KERN_ALERT "%s:%s - write error: %d %d/%d\n", -// NAME, __func__, val, nchar, leng); -// return -EIO; -// } -// nchar +=val; -// } while (nchar < leng); -// return leng; -} - -static char printable(char x) -{ - if (x < 32 || x > 126) - return ' '; - return x; } /** @@ -257,15 +225,15 @@ static char printable(char x) * * @board: the gpib_board_struct data area for this gpib interface * @msg: the byte sequence. - * @leng the byte sequence length; can be given as zero and is + * @leng: the byte sequence length; can be given as zero and is * computed automatically, but if 'msg' contains a zero byte, * it has to be given explicitly. */ -static int send_command(gpib_board_t *board, char *msg, int leng) +static int send_command(struct gpib_board *board, char *msg, int leng) { char buffer[64]; - int nchar, j; + int nchar; int retval; struct timespec64 before, after; @@ -280,17 +248,10 @@ static int send_command(gpib_board_t *board, char *msg, int leng) nchar = skel_do_read(GPIB_DEV, buffer, 64); if (nchar < 0) { - DIA_LOG(0, " return from read: %d\n", nchar); + dev_err(board->gpib_dev, " return from read: %d\n", nchar); return nchar; } else if (nchar != 1) { - for (j = 0 ; j < leng ; j++) { - DIA_LOG(0, " Irregular reply to command: %d %x %c\n", - j, msg[j], printable(msg[j])); - } - for (j = 0 ; j < nchar ; j++) { - DIA_LOG(0, " Irregular command reply: %d %x %c\n", - j, buffer[j] & 0xff, printable(buffer[j])); - } + dev_err(board->gpib_dev, " Irregular reply to command: %s\n", msg); return -EIO; } ktime_get_real_ts64 (&after); @@ -310,7 +271,7 @@ static int send_command(gpib_board_t *board, char *msg, int leng) * */ -static int set_control_line(gpib_board_t *board, int line, int value) +static int set_control_line(struct gpib_board *board, int line, int value) { char msg[] = USB_GPIB_SET_LINES; int retval; @@ -337,11 +298,11 @@ static int set_control_line(gpib_board_t *board, int line, int value) /* * one_char() - read one single byte from input buffer * - * @board: the gpib_board_struct data area for this gpib interface - * @char_buf: the routine private data structure + * @board: the gpib_board_struct data area for this gpib interface + * @char_buf: the routine private data structure */ -static int one_char(gpib_board_t *board, struct char_buf *b) +static int one_char(struct gpib_board *board, struct char_buf *b) { struct timespec64 before, after; @@ -360,13 +321,7 @@ static int one_char(gpib_board_t *board, struct char_buf *b) if (b->nchar > 0) { DIA_LOG(2, "--> %x\n", b->inbuf[b->last - b->nchar]); return b->inbuf[b->last - b->nchar--]; - } else if (b->nchar == 0) { - dev_alert(board->gpib_dev, "%s:%s - read returned EOF\n", NAME, __func__); - return -EIO; } - dev_alert(board->gpib_dev, "%s:%s - read error %d\n", NAME, __func__, b->nchar); - TTY_LOG("\n *** %s *** Read Error - %s\n", NAME, - "Reset the adapter with 'gpib_config'\n"); return -EIO; } @@ -381,7 +336,7 @@ static int one_char(gpib_board_t *board, struct char_buf *b) * not supported. */ -static void set_timeout(gpib_board_t *board) +static void set_timeout(struct gpib_board *board) { int n, val; char command[sizeof(USB_GPIB_TTMO) + 6]; @@ -406,12 +361,10 @@ static void set_timeout(gpib_board_t *board) val = send_command(board, command, 0); } - if (val != ACK) { - dev_alert(board->gpib_dev, "%s:%s - error in timeout set: <%s>\n", - NAME, __func__, command); - } else { + if (val != ACK) + dev_err(board->gpib_dev, "error in timeout set: <%s>\n", command); + else data->timeout = board->usec_timeout; - } } /* @@ -431,7 +384,7 @@ static void set_timeout(gpib_board_t *board) * detach() will be called. Always. */ -static int usb_gpib_attach(gpib_board_t *board, const gpib_board_config_t *config) +static int usb_gpib_attach(struct gpib_board *board, const gpib_board_config_t *config) { int retval, j; u32 base = config->ibbase; @@ -451,8 +404,6 @@ static int usb_gpib_attach(gpib_board_t *board, const gpib_board_config_t *confi if (config->device_path) { /* if config->device_path given, try that first */ - dev_alert(board->gpib_dev, "%s:%s - Looking for device_path: %s\n", - NAME, __func__, config->device_path); for (j = 0 ; j < MAX_DEV ; j++) { if ((assigned_usb_minors & 1 << j) == 0) continue; @@ -487,8 +438,7 @@ static int usb_gpib_attach(gpib_board_t *board, const gpib_board_config_t *confi mutex_unlock(&minors_lock); if (j == MAX_DEV) { - dev_alert(board->gpib_dev, "%s:%s - Requested device is not registered.\n", - NAME, __func__); + dev_err(board->gpib_dev, "Requested device is not registered.\n"); return -EIO; } @@ -501,13 +451,13 @@ static int usb_gpib_attach(gpib_board_t *board, const gpib_board_config_t *confi DIA_LOG(1, "Skel open: %d\n", retval); if (retval) { - TTY_LOG("%s:%s - skel open failed.\n", NAME, __func__); + dev_err(board->gpib_dev, "skel open failed.\n"); kfree(board->private_data); board->private_data = NULL; return -ENODEV; } - SHOW_STATUS(board); + show_status(board); retval = send_command(board, USB_GPIB_ON, 0); DIA_LOG(1, "USB_GPIB_ON returns %x\n", retval); @@ -541,8 +491,8 @@ static int usb_gpib_attach(gpib_board_t *board, const gpib_board_config_t *confi if (retval != ACK) return -EIO; - SHOW_STATUS(board); - TTY_LOG("Module '%s' has been sucesfully configured\n", NAME); + show_status(board); + DIA_LOG(0, "attached\n"); return 0; } @@ -553,13 +503,13 @@ static int usb_gpib_attach(gpib_board_t *board, const gpib_board_config_t *confi * */ -static void usb_gpib_detach(gpib_board_t *board) +static void usb_gpib_detach(struct gpib_board *board) { int retval; - SHOW_STATUS(board); + show_status(board); - DIA_LOG(0, "detaching %p\n", board); + DIA_LOG(0, "detaching\n"); if (board->private_data) { if (GPIB_DEV) { @@ -573,15 +523,14 @@ static void usb_gpib_detach(gpib_board_t *board) board->private_data = NULL; } - DIA_LOG(0, "done %p\n", board); - TTY_LOG("Module '%s' has been detached\n", NAME); + DIA_LOG(0, "detached\n"); } /* * Other functions follow in alphabetical order */ /* command */ -static int usb_gpib_command(gpib_board_t *board, +static int usb_gpib_command(struct gpib_board *board, u8 *buffer, size_t length, size_t *bytes_written) @@ -614,7 +563,7 @@ static int usb_gpib_command(gpib_board_t *board, * Cannot do nothing here, but remember for future use. */ -static void usb_gpib_disable_eos(gpib_board_t *board) +static void usb_gpib_disable_eos(struct gpib_board *board) { ((struct usb_gpib_priv *)board->private_data)->eos_flags &= ~REOS; DIA_LOG(1, "done: %x\n", @@ -630,7 +579,7 @@ static void usb_gpib_disable_eos(gpib_board_t *board) * */ -static int usb_gpib_enable_eos(gpib_board_t *board, +static int usb_gpib_enable_eos(struct gpib_board *board, u8 eos_byte, int compare_8_bits) { @@ -650,7 +599,7 @@ static int usb_gpib_enable_eos(gpib_board_t *board, * @board: the gpib_board data area for this gpib interface */ -static int usb_gpib_go_to_standby(gpib_board_t *board) +static int usb_gpib_go_to_standby(struct gpib_board *board) { int retval = set_control_line(board, IB_BUS_ATN, 0); @@ -665,14 +614,14 @@ static int usb_gpib_go_to_standby(gpib_board_t *board) * usb_gpib_interface_clear() - Assert or de-assert IFC * * @board: the gpib_board data area for this gpib interface - * assert: 1: assert IFC; 0: de-assert IFC + * @assert: 1: assert IFC; 0: de-assert IFC * * Currently on the assert request we issue the lpvo IBZ * command that cycles IFC low for 100 usec, then we ignore * the de-assert request. */ -static void usb_gpib_interface_clear(gpib_board_t *board, int assert) +static void usb_gpib_interface_clear(struct gpib_board *board, int assert) { int retval = 0; @@ -688,21 +637,16 @@ static void usb_gpib_interface_clear(gpib_board_t *board, int assert) } /** - * line_status() - Read the status of the bus lines. + * usb_gpib_line_status() - Read the status of the bus lines. * * @board: the gpib_board data area for this gpib interface * * We can read all lines. */ - -#define WQT wait_queue_entry_t -#define WQH head -#define WQE entry - -static int usb_gpib_line_status(const gpib_board_t *board) +static int usb_gpib_line_status(const struct gpib_board *board) { int buffer; - int line_status = ValidALL; /* all lines will be read */ + int line_status = VALID_ALL; /* all lines will be read */ struct list_head *p, *q; WQT *item; unsigned long flags; @@ -730,30 +674,29 @@ static int usb_gpib_line_status(const gpib_board_t *board) msleep(sleep); } - buffer = send_command((gpib_board_t *)board, USB_GPIB_STATUS, 0); + buffer = send_command((struct gpib_board *)board, USB_GPIB_STATUS, 0); if (buffer < 0) { - dev_alert(board->gpib_dev, "%s:%s - line status read failed with %d\n", - NAME, __func__, buffer); + dev_err(board->gpib_dev, "line status read failed with %d\n", buffer); return -1; } if ((buffer & 0x01) == 0) - line_status |= BusREN; + line_status |= BUS_REN; if ((buffer & 0x02) == 0) - line_status |= BusIFC; + line_status |= BUS_IFC; if ((buffer & 0x04) == 0) - line_status |= BusNDAC; + line_status |= BUS_NDAC; if ((buffer & 0x08) == 0) - line_status |= BusNRFD; + line_status |= BUS_NRFD; if ((buffer & 0x10) == 0) - line_status |= BusDAV; + line_status |= BUS_DAV; if ((buffer & 0x20) == 0) - line_status |= BusEOI; + line_status |= BUS_EOI; if ((buffer & 0x40) == 0) - line_status |= BusATN; + line_status |= BUS_ATN; if ((buffer & 0x80) == 0) - line_status |= BusSRQ; + line_status |= BUS_SRQ; DIA_LOG(1, "done with %x %x\n", buffer, line_status); @@ -762,7 +705,7 @@ static int usb_gpib_line_status(const gpib_board_t *board) /* parallel_poll */ -static int usb_gpib_parallel_poll(gpib_board_t *board, uint8_t *result) +static int usb_gpib_parallel_poll(struct gpib_board *board, uint8_t *result) { /* request parallel poll asserting ATN | EOI; * we suppose ATN already asserted @@ -773,27 +716,23 @@ static int usb_gpib_parallel_poll(gpib_board_t *board, uint8_t *result) DIA_LOG(1, "enter %p\n", board); retval = set_control_line(board, IB_BUS_EOI, 1); - if (retval != ACK) { - dev_alert(board->gpib_dev, "%s:%s - assert EOI failed\n", NAME, __func__); + if (retval != ACK) return -EIO; - } *result = send_command(board, USB_GPIB_READ_DATA, 0); DIA_LOG(1, "done with %x\n", *result); retval = set_control_line(board, IB_BUS_EOI, 0); - if (retval != 0x06) { - dev_alert(board->gpib_dev, "%s:%s - unassert EOI failed\n", NAME, __func__); + if (retval != 0x06) return -EIO; - } return 0; } /* read */ -static int usb_gpib_read(gpib_board_t *board, +static int usb_gpib_read(struct gpib_board *board, u8 *buffer, size_t length, int *end, @@ -866,8 +805,7 @@ static int usb_gpib_read(gpib_board_t *board, goto read_return; if (one_char(board, &b) != DLE || one_char(board, &b) != STX) { - dev_alert(board->gpib_dev, "%s:%s - wrong <DLE><STX> sequence\n", - NAME, __func__); + dev_err(board->gpib_dev, "wrong <DLE><STX> sequence\n"); retval = -EIO; goto read_return; } @@ -907,15 +845,12 @@ static int usb_gpib_read(gpib_board_t *board, retval = 0; goto read_return; } else { - dev_alert(board->gpib_dev, "%s:%s - %s %x\n", - NAME, __func__, - "Wrong end of message", c); + dev_err(board->gpib_dev, "wrong end of message %x", c); retval = -ETIME; goto read_return; } } else { - dev_alert(board->gpib_dev, "%s:%s - %s\n", NAME, __func__, - "lone <DLE> in stream"); + dev_err(board->gpib_dev, "lone <DLE> in stream"); retval = -EIO; goto read_return; } @@ -934,8 +869,7 @@ static int usb_gpib_read(gpib_board_t *board, c = one_char(board, &b); if (c == ACK) { if (MAX_READ_EXCESS - read_count > 1) - dev_alert(board->gpib_dev, "%s:%s - %s\n", NAME, __func__, - "small buffer - maybe some data lost"); + dev_dbg(board->gpib_dev, "small buffer - maybe some data lost"); retval = 0; goto read_return; } @@ -943,15 +877,13 @@ static int usb_gpib_read(gpib_board_t *board, } } - dev_alert(board->gpib_dev, "%s:%s - no input end - GPIB board in odd state\n", - NAME, __func__); + dev_err(board->gpib_dev, "no input end - board in odd state\n"); retval = -EIO; read_return: kfree(b.inbuf); - DIA_LOG(1, "done with byte/status: %d %x %d\n", - (int)*bytes_read, retval, *end); + DIA_LOG(1, "done with byte/status: %d %x %d\n", (int)*bytes_read, retval, *end); if (retval == 0 || retval == -ETIME) { if (send_command(board, USB_GPIB_UNTALK, sizeof(USB_GPIB_UNTALK)) == 0x06) @@ -964,21 +896,20 @@ static int usb_gpib_read(gpib_board_t *board, /* remote_enable */ -static void usb_gpib_remote_enable(gpib_board_t *board, int enable) +static void usb_gpib_remote_enable(struct gpib_board *board, int enable) { int retval; retval = set_control_line(board, IB_BUS_REN, enable ? 1 : 0); if (retval != ACK) - dev_alert(board->gpib_dev, "%s:%s - could not set REN line: %x\n", - NAME, __func__, retval); + dev_err(board->gpib_dev, "could not set REN line: %x\n", retval); DIA_LOG(1, "done with %x\n", retval); } /* request_system_control */ -static void usb_gpib_request_system_control(gpib_board_t *board, +static void usb_gpib_request_system_control(struct gpib_board *board, int request_control) { if (request_control) @@ -992,7 +923,7 @@ static void usb_gpib_request_system_control(gpib_board_t *board, /* take_control */ /* beware: the sync flag is ignored; what is its real meaning? */ -static int usb_gpib_take_control(gpib_board_t *board, int sync) +static int usb_gpib_take_control(struct gpib_board *board, int sync) { int retval; @@ -1007,7 +938,7 @@ static int usb_gpib_take_control(gpib_board_t *board, int sync) /* update_status */ -static unsigned int usb_gpib_update_status(gpib_board_t *board, +static unsigned int usb_gpib_update_status(struct gpib_board *board, unsigned int clear_mask) { /* There is nothing we can do here, I guess */ @@ -1022,7 +953,7 @@ static unsigned int usb_gpib_update_status(gpib_board_t *board, /* write */ /* beware: DLE characters are not escaped - can only send ASCII data */ -static int usb_gpib_write(gpib_board_t *board, +static int usb_gpib_write(struct gpib_board *board, u8 *buffer, size_t length, int send_eoi, @@ -1053,9 +984,8 @@ static int usb_gpib_write(gpib_board_t *board, *bytes_written = length; - if (send_command(board, USB_GPIB_UNLISTEN, sizeof(USB_GPIB_UNLISTEN)) - != 0x06) - return -EPIPE; + if (send_command(board, USB_GPIB_UNLISTEN, sizeof(USB_GPIB_UNLISTEN)) != 0x06) + return -EPIPE; return length; } @@ -1066,64 +996,56 @@ static int usb_gpib_write(gpib_board_t *board, /* parallel_poll configure */ -static void usb_gpib_parallel_poll_configure(gpib_board_t *board, +static void usb_gpib_parallel_poll_configure(struct gpib_board *board, uint8_t configuration) { - dev_alert(board->gpib_dev, "%s:%s - currently a NOP\n", NAME, __func__); } /* parallel_poll_response */ -static void usb_gpib_parallel_poll_response(gpib_board_t *board, int ist) +static void usb_gpib_parallel_poll_response(struct gpib_board *board, int ist) { - dev_alert(board->gpib_dev, "%s:%s - currently a NOP\n", NAME, __func__); } /* primary_address */ -static int usb_gpib_primary_address(gpib_board_t *board, unsigned int address) +static int usb_gpib_primary_address(struct gpib_board *board, unsigned int address) { - dev_alert(board->gpib_dev, "%s:%s - currently a NOP\n", NAME, __func__); return 0; } /* return_to_local */ -static void usb_gpib_return_to_local(gpib_board_t *board) +static void usb_gpib_return_to_local(struct gpib_board *board) { - dev_alert(board->gpib_dev, "%s:%s - currently a NOP\n", NAME, __func__); } /* secondary_address */ -static int usb_gpib_secondary_address(gpib_board_t *board, +static int usb_gpib_secondary_address(struct gpib_board *board, unsigned int address, int enable) { - dev_alert(board->gpib_dev, "%s:%s - currently a NOP\n", NAME, __func__); return 0; } /* serial_poll_response */ -static void usb_gpib_serial_poll_response(gpib_board_t *board, uint8_t status) +static void usb_gpib_serial_poll_response(struct gpib_board *board, uint8_t status) { - dev_alert(board->gpib_dev, "%s:%s - currently a NOP\n", NAME, __func__); } /* serial_poll_status */ -static uint8_t usb_gpib_serial_poll_status(gpib_board_t *board) +static uint8_t usb_gpib_serial_poll_status(struct gpib_board *board) { - dev_alert(board->gpib_dev, "%s:%s - currently a NOP\n", NAME, __func__); return 0; } /* t1_delay */ -static unsigned int usb_gpib_t1_delay(gpib_board_t *board, unsigned int nano_sec) +static int usb_gpib_t1_delay(struct gpib_board *board, unsigned int nano_sec) { - dev_alert(board->gpib_dev, "%s:%s - currently a NOP\n", NAME, __func__); return 0; } @@ -1181,7 +1103,7 @@ static int usb_gpib_init_module(struct usb_interface *interface) if (!assigned_usb_minors) { rv = gpib_register_driver(&usb_gpib_interface, THIS_MODULE); if (rv) { - pr_err("lpvo_usb_gpib: gpib_register_driver failed: error = %d\n", rv); + pr_err("gpib_register_driver failed: error = %d\n", rv); goto exit; } } else { @@ -1191,8 +1113,8 @@ static int usb_gpib_init_module(struct usb_interface *interface) for (j = 0 ; j < MAX_DEV ; j++) { if (usb_minors[j] == interface->minor && assigned_usb_minors & 1 << j) { - pr_alert("%s:%s - CODE BUG: USB minor %d registered at %d.\n", - NAME, __func__, interface->minor, j); + pr_err("CODE BUG: USB minor %d registered at %d.\n", + interface->minor, j); rv = -1; goto exit; } @@ -1207,13 +1129,11 @@ static int usb_gpib_init_module(struct usb_interface *interface) usb_minors[j] = interface->minor; lpvo_usb_interfaces[j] = interface; assigned_usb_minors |= mask; - DIA_LOG(0, "usb minor %d registered at %d\n", interface->minor, j); rv = 0; goto exit; } } - pr_alert("%s:%s - No slot available for interface %p minor %d\n", - NAME, __func__, interface, interface->minor); + pr_err("No slot available for interface %p minor %d\n", interface, interface->minor); rv = -1; exit: @@ -1235,7 +1155,7 @@ static void usb_gpib_exit_module(int minor) goto exit; } } - pr_alert("%s:%s - CODE BUG: USB minor %d not found.\n", NAME, __func__, minor); + pr_err("CODE BUG: USB minor %d not found.\n", minor); exit: mutex_unlock(&minors_lock); @@ -1267,7 +1187,7 @@ static int write_latency_timer(struct usb_device *udev) LATENCY_TIMER, LATENCY_CHANNEL, NULL, 0, WDR_TIMEOUT); if (rv < 0) - pr_alert("Unable to write latency timer: %i\n", rv); + dev_err(&udev->dev, "Unable to write latency timer: %i\n", rv); return rv; } @@ -1363,18 +1283,15 @@ static void skel_delete(struct kref *kref) * skel_do_open() - to be called by usb_gpib_attach */ -static int skel_do_open(gpib_board_t *board, int subminor) +static int skel_do_open(struct gpib_board *board, int subminor) { struct usb_skel *dev; struct usb_interface *interface; int retval = 0; - DIA_LOG(0, "Required minor: %d\n", subminor); - interface = usb_find_interface(&skel_driver, subminor); if (!interface) { - pr_err("%s - error, can't find device for minor %d\n", - __func__, subminor); + dev_err(board->gpib_dev, "can't find device for minor %d\n", subminor); retval = -ENODEV; goto exit; } @@ -1403,7 +1320,7 @@ static int skel_do_open(gpib_board_t *board, int subminor) * skel_do_release() - to be called by usb_gpib_detach */ -static int skel_do_release(gpib_board_t *board) +static int skel_do_release(struct gpib_board *board) { struct usb_skel *dev; @@ -1439,9 +1356,8 @@ static void skel_read_bulk_callback(struct urb *urb) if (!(urb->status == -ENOENT || urb->status == -ECONNRESET || urb->status == -ESHUTDOWN)) - dev_err(&dev->interface->dev, - "%s - nonzero read bulk status received: %d\n", - __func__, urb->status); + dev_err(&dev->interface->dev, "nonzero read bulk status received: %d\n", + urb->status); dev->errors = urb->status; } else { @@ -1478,9 +1394,7 @@ static int skel_do_read_io(struct usb_skel *dev, size_t count) /* do it */ rv = usb_submit_urb(dev->bulk_in_urb, GFP_KERNEL); if (rv < 0) { - dev_err(&dev->interface->dev, - "%s - failed submitting read urb, error %d\n", - __func__, rv); + dev_err(&dev->interface->dev, "failed submitting read urb, error %d\n", rv); rv = (rv == -ENOMEM) ? rv : -EIO; spin_lock_irq(&dev->err_lock); dev->ongoing_read = 0; @@ -1504,14 +1418,10 @@ static ssize_t skel_do_read(struct usb_skel *dev, char *buffer, size_t count) if (!dev->bulk_in_urb || !count) return 0; - DIA_LOG(1, "enter for %zu.\n", count); - restart: /* added to comply with ftdi timeout technique */ /* no concurrent readers */ - DIA_LOG(2, "restart with %zd %zd.\n", dev->bulk_in_filled, dev->bulk_in_copied); - rv = mutex_lock_interruptible(&dev->io_mutex); if (rv < 0) return rv; @@ -1527,8 +1437,6 @@ static ssize_t skel_do_read(struct usb_skel *dev, char *buffer, size_t count) ongoing_io = dev->ongoing_read; spin_unlock_irq(&dev->err_lock); - DIA_LOG(2, "retry with %d.\n", ongoing_io); - if (ongoing_io) { // /* nonblocking IO shall not wait */ // /* no file, no O_NONBLOCK; maybe provide when from user space */ @@ -1569,8 +1477,6 @@ static ssize_t skel_do_read(struct usb_skel *dev, char *buffer, size_t count) // size_t chunk = min(available, count); /* compute chunk later */ size_t chunk; - DIA_LOG(2, "we have data: %zu %zu.\n", dev->bulk_in_filled, dev->bulk_in_copied); - if (!available) { /* * all data has been used @@ -1596,12 +1502,6 @@ static ssize_t skel_do_read(struct usb_skel *dev, char *buffer, size_t count) */ if (dev->bulk_in_copied) { - int j; - - for (j = 0 ; j < dev->bulk_in_filled ; j++) { - pr_alert("copy -> %x %zu %x\n", - j, dev->bulk_in_copied, dev->bulk_in_buffer[j]); - } chunk = min(available, count); memcpy(buffer, dev->bulk_in_buffer + dev->bulk_in_copied, chunk); rv = chunk; @@ -1613,7 +1513,7 @@ static ssize_t skel_do_read(struct usb_skel *dev, char *buffer, size_t count) /* account for two bytes to be discarded */ chunk = min(available, count + 2); if (chunk < 2) { - pr_alert("BAD READ - chunk: %zu\n", chunk); + dev_err(&dev->udev->dev, "BAD READ - chunk: %zu\n", chunk); rv = -EIO; goto exit; } @@ -1633,8 +1533,6 @@ static ssize_t skel_do_read(struct usb_skel *dev, char *buffer, size_t count) // if (available < count) // skel_do_read_io(dev, dev->bulk_in_size); } else { - DIA_LOG(1, "no data - start read - copied: %zd.\n", dev->bulk_in_copied); - /* no data in the buffer */ rv = skel_do_read_io(dev, dev->bulk_in_size); if (rv < 0) @@ -1645,10 +1543,10 @@ static ssize_t skel_do_read(struct usb_skel *dev, char *buffer, size_t count) exit: mutex_unlock(&dev->io_mutex); if (rv == 2) - goto restart; /* ftdi chip returns two status bytes after a latency anyhow */ - DIA_LOG(1, "exit with %d.\n", rv); + goto restart; /* ftdi chip returns two status bytes after a latency anyhow */ + if (rv > 0) - return rv - 2; /* account for 2 discarded bytes in a valid buffer */ + return rv - 2; /* account for 2 discarded bytes in a valid buffer */ return rv; } @@ -1669,8 +1567,7 @@ static void skel_write_bulk_callback(struct urb *urb) urb->status == -ECONNRESET || urb->status == -ESHUTDOWN)) dev_err(&dev->interface->dev, - "%s - nonzero write bulk status received: %d\n", - __func__, urb->status); + "nonzero write bulk status received: %d\n", urb->status); spin_lock_irqsave(&dev->err_lock, flags); dev->errors = urb->status; @@ -1763,9 +1660,7 @@ static ssize_t skel_do_write(struct usb_skel *dev, const char *buffer, size_t co retval = usb_submit_urb(urb, GFP_KERNEL); mutex_unlock(&dev->io_mutex); if (retval) { - dev_err(&dev->interface->dev, - "%s - failed submitting write urb, error %d\n", - __func__, retval); + dev_err(&dev->interface->dev, "failed submitting write urb, error %d\n", retval); goto error_unanchor; } @@ -1831,8 +1726,7 @@ static int skel_open(struct inode *inode, struct file *file) interface = usb_find_interface(&skel_driver, subminor); if (!interface) { - pr_err("%s - error, can't find device for minor %d\n", - __func__, subminor); + pr_err("can't find device for minor %d\n", subminor); retval = -ENODEV; goto exit; } @@ -1895,8 +1789,6 @@ static ssize_t skel_read(struct file *file, char __user *buffer, size_t count, rv = skel_do_read(dev, buf, count); - pr_alert("%s - return with %zu\n", __func__, rv); - if (rv > 0) { if (copy_to_user(buffer, buf, rv)) { kfree(buf); @@ -2015,8 +1907,8 @@ static int skel_probe(struct usb_interface *interface, /* let the world know */ device_path = kobject_get_path(&dev->udev->dev.kobj, GFP_KERNEL); - pr_alert("%s:%s - New lpvo_usb_device -> bus: %d dev: %d path: %s\n", NAME, __func__, - dev->udev->bus->busnum, dev->udev->devnum, device_path); + dev_dbg(&interface->dev, "New lpvo_usb_device -> bus: %d dev: %d path: %s\n", + dev->udev->bus->busnum, dev->udev->devnum, device_path); kfree(device_path); #if USER_DEVICE @@ -2029,14 +1921,9 @@ static int skel_probe(struct usb_interface *interface, usb_set_intfdata(interface, NULL); goto error; } - - /* let the user know what node this device is now attached to */ - dev_info(&interface->dev, - "lpvo_usb_gpib device now attached to lpvo_raw%d", - interface->minor); #endif - write_latency_timer(dev->udev); /* adjust the latency timer */ + write_latency_timer(dev->udev); /* adjust the latency timer */ usb_gpib_init_module(interface); /* last, init the lpvo for this minor */ @@ -2073,8 +1960,6 @@ static void skel_disconnect(struct usb_interface *interface) /* decrement our usage count */ kref_put(&dev->kref, skel_delete); - - dev_info(&interface->dev, "USB lpvo_raw #%d now disconnected", minor); } static void skel_draw_down(struct usb_skel *dev)
diff --git a/drivers/staging/gpib/nec7210/nec7210.c b/drivers/staging/gpib/nec7210/nec7210.c index c9a837fa..846c0a3 100644 --- a/drivers/staging/gpib/nec7210/nec7210.c +++ b/drivers/staging/gpib/nec7210/nec7210.c
@@ -4,6 +4,8 @@ * copyright : (C) 2001, 2002 by Frank Mori Hess ***************************************************************************/ +#define dev_fmt(fmt) KBUILD_MODNAME ": " fmt + #include "board.h" #include <linux/ioport.h> #include <linux/sched.h> @@ -21,7 +23,7 @@ MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("GPIB library code for NEC uPD7210"); -int nec7210_enable_eos(gpib_board_t *board, struct nec7210_priv *priv, uint8_t eos_byte, +int nec7210_enable_eos(struct gpib_board *board, struct nec7210_priv *priv, uint8_t eos_byte, int compare_8_bits) { write_byte(priv, eos_byte, EOSR); @@ -35,14 +37,14 @@ int nec7210_enable_eos(gpib_board_t *board, struct nec7210_priv *priv, uint8_t e } EXPORT_SYMBOL(nec7210_enable_eos); -void nec7210_disable_eos(gpib_board_t *board, struct nec7210_priv *priv) +void nec7210_disable_eos(struct gpib_board *board, struct nec7210_priv *priv) { priv->auxa_bits &= ~HR_REOS; write_byte(priv, priv->auxa_bits, AUXMR); } EXPORT_SYMBOL(nec7210_disable_eos); -int nec7210_parallel_poll(gpib_board_t *board, struct nec7210_priv *priv, uint8_t *result) +int nec7210_parallel_poll(struct gpib_board *board, struct nec7210_priv *priv, uint8_t *result) { int ret; @@ -62,14 +64,14 @@ int nec7210_parallel_poll(gpib_board_t *board, struct nec7210_priv *priv, uint8_ } EXPORT_SYMBOL(nec7210_parallel_poll); -void nec7210_parallel_poll_configure(gpib_board_t *board, +void nec7210_parallel_poll_configure(struct gpib_board *board, struct nec7210_priv *priv, unsigned int configuration) { write_byte(priv, PPR | configuration, AUXMR); } EXPORT_SYMBOL(nec7210_parallel_poll_configure); -void nec7210_parallel_poll_response(gpib_board_t *board, struct nec7210_priv *priv, int ist) +void nec7210_parallel_poll_response(struct gpib_board *board, struct nec7210_priv *priv, int ist) { if (ist) write_byte(priv, AUX_SPPF, AUXMR); @@ -83,7 +85,8 @@ EXPORT_SYMBOL(nec7210_parallel_poll_response); * the 488.2 capability (for example with NI chips), or we need to implement the * 488.2 set srv state machine in the driver (if that is even viable). */ -void nec7210_serial_poll_response(gpib_board_t *board, struct nec7210_priv *priv, uint8_t status) +void nec7210_serial_poll_response(struct gpib_board *board, + struct nec7210_priv *priv, uint8_t status) { unsigned long flags; @@ -100,13 +103,13 @@ void nec7210_serial_poll_response(gpib_board_t *board, struct nec7210_priv *priv } EXPORT_SYMBOL(nec7210_serial_poll_response); -uint8_t nec7210_serial_poll_status(gpib_board_t *board, struct nec7210_priv *priv) +uint8_t nec7210_serial_poll_status(struct gpib_board *board, struct nec7210_priv *priv) { return read_byte(priv, SPSR); } EXPORT_SYMBOL(nec7210_serial_poll_status); -int nec7210_primary_address(const gpib_board_t *board, struct nec7210_priv *priv, +int nec7210_primary_address(const struct gpib_board *board, struct nec7210_priv *priv, unsigned int address) { // put primary address in address0 @@ -115,7 +118,7 @@ int nec7210_primary_address(const gpib_board_t *board, struct nec7210_priv *priv } EXPORT_SYMBOL(nec7210_primary_address); -int nec7210_secondary_address(const gpib_board_t *board, struct nec7210_priv *priv, +int nec7210_secondary_address(const struct gpib_board *board, struct nec7210_priv *priv, unsigned int address, int enable) { if (enable) { @@ -164,7 +167,7 @@ static void update_listener_state(struct nec7210_priv *priv, unsigned int addres } } -unsigned int nec7210_update_status_nolock(gpib_board_t *board, struct nec7210_priv *priv) +unsigned int nec7210_update_status_nolock(struct gpib_board *board, struct nec7210_priv *priv) { int address_status_bits; u8 spoll_status; @@ -198,7 +201,6 @@ unsigned int nec7210_update_status_nolock(gpib_board_t *board, struct nec7210_pr priv->srq_pending = 0; set_bit(SPOLL_NUM, &board->status); } -// dev_dbg(board->gpib_dev, "status 0x%x, state 0x%x\n", board->status, priv->state); /* we rely on the interrupt handler to set the * rest of the status bits @@ -208,7 +210,7 @@ unsigned int nec7210_update_status_nolock(gpib_board_t *board, struct nec7210_pr } EXPORT_SYMBOL(nec7210_update_status_nolock); -unsigned int nec7210_update_status(gpib_board_t *board, struct nec7210_priv *priv, +unsigned int nec7210_update_status(struct gpib_board *board, struct nec7210_priv *priv, unsigned int clear_mask) { unsigned long flags; @@ -233,7 +235,7 @@ unsigned int nec7210_set_reg_bits(struct nec7210_priv *priv, unsigned int reg, } EXPORT_SYMBOL(nec7210_set_reg_bits); -void nec7210_set_handshake_mode(gpib_board_t *board, struct nec7210_priv *priv, int mode) +void nec7210_set_handshake_mode(struct gpib_board *board, struct nec7210_priv *priv, int mode) { unsigned long flags; @@ -249,7 +251,7 @@ void nec7210_set_handshake_mode(gpib_board_t *board, struct nec7210_priv *priv, } EXPORT_SYMBOL(nec7210_set_handshake_mode); -uint8_t nec7210_read_data_in(gpib_board_t *board, struct nec7210_priv *priv, int *end) +uint8_t nec7210_read_data_in(struct gpib_board *board, struct nec7210_priv *priv, int *end) { unsigned long flags; u8 data; @@ -267,7 +269,7 @@ uint8_t nec7210_read_data_in(gpib_board_t *board, struct nec7210_priv *priv, int } EXPORT_SYMBOL(nec7210_read_data_in); -int nec7210_take_control(gpib_board_t *board, struct nec7210_priv *priv, int syncronous) +int nec7210_take_control(struct gpib_board *board, struct nec7210_priv *priv, int syncronous) { int i; const int timeout = 100; @@ -294,7 +296,7 @@ int nec7210_take_control(gpib_board_t *board, struct nec7210_priv *priv, int syn } EXPORT_SYMBOL(nec7210_take_control); -int nec7210_go_to_standby(gpib_board_t *board, struct nec7210_priv *priv) +int nec7210_go_to_standby(struct gpib_board *board, struct nec7210_priv *priv) { int i; const int timeout = 1000; @@ -319,10 +321,8 @@ int nec7210_go_to_standby(gpib_board_t *board, struct nec7210_priv *priv) if (adsr_bits & HR_NATN) break; } - if (i == HZ) { - pr_err("nec7210: error waiting for NATN\n"); + if (i == HZ) return -ETIMEDOUT; - } } clear_bit(COMMAND_READY_BN, &priv->state); @@ -330,7 +330,7 @@ int nec7210_go_to_standby(gpib_board_t *board, struct nec7210_priv *priv) } EXPORT_SYMBOL(nec7210_go_to_standby); -void nec7210_request_system_control(gpib_board_t *board, struct nec7210_priv *priv, +void nec7210_request_system_control(struct gpib_board *board, struct nec7210_priv *priv, int request_control) { if (request_control == 0) { @@ -341,7 +341,7 @@ void nec7210_request_system_control(gpib_board_t *board, struct nec7210_priv *pr } EXPORT_SYMBOL(nec7210_request_system_control); -void nec7210_interface_clear(gpib_board_t *board, struct nec7210_priv *priv, int assert) +void nec7210_interface_clear(struct gpib_board *board, struct nec7210_priv *priv, int assert) { if (assert) write_byte(priv, AUX_SIFC, AUXMR); @@ -350,7 +350,7 @@ void nec7210_interface_clear(gpib_board_t *board, struct nec7210_priv *priv, int } EXPORT_SYMBOL(nec7210_interface_clear); -void nec7210_remote_enable(gpib_board_t *board, struct nec7210_priv *priv, int enable) +void nec7210_remote_enable(struct gpib_board *board, struct nec7210_priv *priv, int enable) { if (enable) write_byte(priv, AUX_SREN, AUXMR); @@ -359,7 +359,7 @@ void nec7210_remote_enable(gpib_board_t *board, struct nec7210_priv *priv, int e } EXPORT_SYMBOL(nec7210_remote_enable); -void nec7210_release_rfd_holdoff(gpib_board_t *board, struct nec7210_priv *priv) +void nec7210_release_rfd_holdoff(struct gpib_board *board, struct nec7210_priv *priv) { unsigned long flags; @@ -373,8 +373,8 @@ void nec7210_release_rfd_holdoff(gpib_board_t *board, struct nec7210_priv *priv) } EXPORT_SYMBOL(nec7210_release_rfd_holdoff); -unsigned int nec7210_t1_delay(gpib_board_t *board, struct nec7210_priv *priv, - unsigned int nano_sec) +int nec7210_t1_delay(struct gpib_board *board, struct nec7210_priv *priv, + unsigned int nano_sec) { unsigned int retval; @@ -391,13 +391,13 @@ unsigned int nec7210_t1_delay(gpib_board_t *board, struct nec7210_priv *priv, } EXPORT_SYMBOL(nec7210_t1_delay); -void nec7210_return_to_local(const gpib_board_t *board, struct nec7210_priv *priv) +void nec7210_return_to_local(const struct gpib_board *board, struct nec7210_priv *priv) { write_byte(priv, AUX_RTL, AUXMR); } EXPORT_SYMBOL(nec7210_return_to_local); -static inline short nec7210_atn_has_changed(gpib_board_t *board, struct nec7210_priv *priv) +static inline short nec7210_atn_has_changed(struct gpib_board *board, struct nec7210_priv *priv) { short address_status_bits = read_byte(priv, ADSR); @@ -415,7 +415,7 @@ static inline short nec7210_atn_has_changed(gpib_board_t *board, struct nec7210_ return -1; } -int nec7210_command(gpib_board_t *board, struct nec7210_priv *priv, uint8_t +int nec7210_command(struct gpib_board *board, struct nec7210_priv *priv, uint8_t *buffer, size_t length, size_t *bytes_written) { int retval = 0; @@ -430,17 +430,14 @@ int nec7210_command(gpib_board_t *board, struct nec7210_priv *priv, uint8_t test_bit(COMMAND_READY_BN, &priv->state) || test_bit(BUS_ERROR_BN, &priv->state) || test_bit(TIMO_NUM, &board->status))) { - dev_dbg(board->gpib_dev, "gpib command wait interrupted\n"); + dev_dbg(board->gpib_dev, "command wait interrupted\n"); retval = -ERESTARTSYS; break; } if (test_bit(TIMO_NUM, &board->status)) break; - if (test_and_clear_bit(BUS_ERROR_BN, &priv->state)) { - pr_err("nec7210: bus error on command byte\n"); + if (test_and_clear_bit(BUS_ERROR_BN, &priv->state)) break; - } - spin_lock_irqsave(&board->spinlock, flags); clear_bit(COMMAND_READY_BN, &priv->state); write_byte(priv, buffer[*bytes_written], CDOR); @@ -454,24 +451,20 @@ int nec7210_command(gpib_board_t *board, struct nec7210_priv *priv, uint8_t // wait for last byte to get sent if (wait_event_interruptible(board->wait, test_bit(COMMAND_READY_BN, &priv->state) || test_bit(BUS_ERROR_BN, &priv->state) || - test_bit(TIMO_NUM, &board->status))) { - dev_dbg(board->gpib_dev, "gpib command wait interrupted\n"); + test_bit(TIMO_NUM, &board->status))) retval = -ERESTARTSYS; - } - if (test_bit(TIMO_NUM, &board->status)) { - dev_dbg(board->gpib_dev, "gpib command timed out\n"); + + if (test_bit(TIMO_NUM, &board->status)) retval = -ETIMEDOUT; - } - if (test_and_clear_bit(BUS_ERROR_BN, &priv->state)) { - pr_err("nec7210: bus error on command byte\n"); + + if (test_and_clear_bit(BUS_ERROR_BN, &priv->state)) retval = -EIO; - } return retval; } EXPORT_SYMBOL(nec7210_command); -static int pio_read(gpib_board_t *board, struct nec7210_priv *priv, uint8_t *buffer, +static int pio_read(struct gpib_board *board, struct nec7210_priv *priv, uint8_t *buffer, size_t length, int *end, size_t *bytes_read) { ssize_t retval = 0; @@ -484,7 +477,6 @@ static int pio_read(gpib_board_t *board, struct nec7210_priv *priv, uint8_t *buf test_bit(READ_READY_BN, &priv->state) || test_bit(DEV_CLEAR_BN, &priv->state) || test_bit(TIMO_NUM, &board->status))) { - dev_dbg(board->gpib_dev, "nec7210: pio read wait interrupted\n"); retval = -ERESTARTSYS; break; } @@ -503,12 +495,10 @@ static int pio_read(gpib_board_t *board, struct nec7210_priv *priv, uint8_t *buf break; } if (test_bit(TIMO_NUM, &board->status)) { - dev_dbg(board->gpib_dev, "interrupted by timeout\n"); retval = -ETIMEDOUT; break; } if (test_bit(DEV_CLEAR_BN, &priv->state)) { - dev_dbg(board->gpib_dev, "interrupted by device clear\n"); retval = -EINTR; break; } @@ -523,7 +513,7 @@ static int pio_read(gpib_board_t *board, struct nec7210_priv *priv, uint8_t *buf } #ifdef NEC_DMA -static ssize_t __dma_read(gpib_board_t *board, struct nec7210_priv *priv, size_t length) +static ssize_t __dma_read(struct gpib_board *board, struct nec7210_priv *priv, size_t length) { ssize_t retval = 0; size_t count = 0; @@ -557,10 +547,9 @@ static ssize_t __dma_read(gpib_board_t *board, struct nec7210_priv *priv, size_t if (wait_event_interruptible(board->wait, test_bit(DMA_READ_IN_PROGRESS_BN, &priv->state) == 0 || test_bit(DEV_CLEAR_BN, &priv->state) || - test_bit(TIMO_NUM, &board->status))) { - dev_dbg(board->gpib_dev, "nec7210: dma read wait interrupted\n"); + test_bit(TIMO_NUM, &board->status))) retval = -ERESTARTSYS; - } + if (test_bit(TIMO_NUM, &board->status)) retval = -ETIMEDOUT; if (test_bit(DEV_CLEAR_BN, &priv->state)) @@ -579,7 +568,7 @@ static ssize_t __dma_read(gpib_board_t *board, struct nec7210_priv *priv, size_t return retval ? retval : count; } -static ssize_t dma_read(gpib_board_t *board, struct nec7210_priv *priv, uint8_t *buffer, +static ssize_t dma_read(struct gpib_board *board, struct nec7210_priv *priv, uint8_t *buffer, size_t length) { size_t remain = length; @@ -606,7 +595,7 @@ static ssize_t dma_read(gpib_board_t *board, struct nec7210_priv *priv, uint8_t } #endif -int nec7210_read(gpib_board_t *board, struct nec7210_priv *priv, uint8_t *buffer, +int nec7210_read(struct gpib_board *board, struct nec7210_priv *priv, uint8_t *buffer, size_t length, int *end, size_t *bytes_read) { ssize_t retval = 0; @@ -627,7 +616,7 @@ int nec7210_read(gpib_board_t *board, struct nec7210_priv *priv, uint8_t *buffer } EXPORT_SYMBOL(nec7210_read); -static int pio_write_wait(gpib_board_t *board, struct nec7210_priv *priv, +static int pio_write_wait(struct gpib_board *board, struct nec7210_priv *priv, short wake_on_lacs, short wake_on_atn, short wake_on_bus_error) { // wait until byte is ready to be sent @@ -638,26 +627,22 @@ static int pio_write_wait(gpib_board_t *board, struct nec7210_priv *priv, (wake_on_bus_error && test_bit(BUS_ERROR_BN, &priv->state)) || (wake_on_lacs && test_bit(LACS_NUM, &board->status)) || (wake_on_atn && test_bit(ATN_NUM, &board->status)) || - test_bit(TIMO_NUM, &board->status))) { - dev_dbg(board->gpib_dev, "gpib write interrupted\n"); + test_bit(TIMO_NUM, &board->status))) return -ERESTARTSYS; - } - if (test_bit(TIMO_NUM, &board->status)) { - dev_dbg(board->gpib_dev, "nec7210: write timed out\n"); + + if (test_bit(TIMO_NUM, &board->status)) return -ETIMEDOUT; - } - if (test_bit(DEV_CLEAR_BN, &priv->state)) { - dev_dbg(board->gpib_dev, "nec7210: write interrupted by clear\n"); + + if (test_bit(DEV_CLEAR_BN, &priv->state)) return -EINTR; - } - if (wake_on_bus_error && test_and_clear_bit(BUS_ERROR_BN, &priv->state)) { - dev_dbg(board->gpib_dev, "nec7210: bus error on write\n"); + + if (wake_on_bus_error && test_and_clear_bit(BUS_ERROR_BN, &priv->state)) return -EIO; - } + return 0; } -static int pio_write(gpib_board_t *board, struct nec7210_priv *priv, uint8_t *buffer, +static int pio_write(struct gpib_board *board, struct nec7210_priv *priv, uint8_t *buffer, size_t length, size_t *bytes_written) { size_t last_count = 0; @@ -677,7 +662,6 @@ static int pio_write(gpib_board_t *board, struct nec7210_priv *priv, uint8_t *bu if (retval == -EIO) { /* resend last byte on bus error */ *bytes_written = last_count; - dev_dbg(board->gpib_dev, "resending %c\n", buffer[*bytes_written]); /* we can get unrecoverable bus errors, * so give up after a while */ @@ -701,7 +685,7 @@ static int pio_write(gpib_board_t *board, struct nec7210_priv *priv, uint8_t *bu } #ifdef NEC_DMA -static ssize_t __dma_write(gpib_board_t *board, struct nec7210_priv *priv, dma_addr_t address, +static ssize_t __dma_write(struct gpib_board *board, struct nec7210_priv *priv, dma_addr_t address, size_t length) { unsigned long flags, dma_irq_flags; @@ -733,10 +717,9 @@ static ssize_t __dma_write(gpib_board_t *board, struct nec7210_priv *priv, dma_a test_bit(DMA_WRITE_IN_PROGRESS_BN, &priv->state) == 0 || test_bit(BUS_ERROR_BN, &priv->state) || test_bit(DEV_CLEAR_BN, &priv->state) || - test_bit(TIMO_NUM, &board->status))) { - dev_dbg(board->gpib_dev, "gpib write interrupted!\n"); + test_bit(TIMO_NUM, &board->status))) retval = -ERESTARTSYS; - } + if (test_bit(TIMO_NUM, &board->status)) retval = -ETIMEDOUT; if (test_and_clear_bit(DEV_CLEAR_BN, &priv->state)) @@ -759,7 +742,7 @@ static ssize_t __dma_write(gpib_board_t *board, struct nec7210_priv *priv, dma_a return retval ? retval : length; } -static ssize_t dma_write(gpib_board_t *board, struct nec7210_priv *priv, uint8_t *buffer, +static ssize_t dma_write(struct gpib_board *board, struct nec7210_priv *priv, uint8_t *buffer, size_t length) { size_t remain = length; @@ -783,8 +766,9 @@ static ssize_t dma_write(gpib_board_t *board, struct nec7210_priv *priv, uint8_t return length - remain; } #endif -int nec7210_write(gpib_board_t *board, struct nec7210_priv *priv, uint8_t *buffer, size_t length, - int send_eoi, size_t *bytes_written) +int nec7210_write(struct gpib_board *board, struct nec7210_priv *priv, + uint8_t *buffer, size_t length, int send_eoi, + size_t *bytes_written) { int retval = 0; @@ -845,7 +829,7 @@ EXPORT_SYMBOL(nec7210_write); /* * interrupt service routine */ -irqreturn_t nec7210_interrupt(gpib_board_t *board, struct nec7210_priv *priv) +irqreturn_t nec7210_interrupt(struct gpib_board *board, struct nec7210_priv *priv) { int status1, status2; @@ -857,7 +841,7 @@ irqreturn_t nec7210_interrupt(gpib_board_t *board, struct nec7210_priv *priv) } EXPORT_SYMBOL(nec7210_interrupt); -irqreturn_t nec7210_interrupt_have_status(gpib_board_t *board, +irqreturn_t nec7210_interrupt_have_status(struct gpib_board *board, struct nec7210_priv *priv, int status1, int status2) { #ifdef NEC_DMA @@ -937,13 +921,8 @@ irqreturn_t nec7210_interrupt_have_status(gpib_board_t *board, set_bit(COMMAND_READY_BN, &priv->state); // command pass through received - if (status1 & HR_CPT) { - unsigned int command; - - command = read_byte(priv, CPTR) & gpib_command_mask; + if (status1 & HR_CPT) write_byte(priv, AUX_NVAL, AUXMR); -// printk("gpib: command pass through 0x%x\n", command); - } if (status1 & HR_ERR) set_bit(BUS_ERROR_BN, &priv->state); @@ -980,7 +959,7 @@ irqreturn_t nec7210_interrupt_have_status(gpib_board_t *board, } EXPORT_SYMBOL(nec7210_interrupt_have_status); -void nec7210_board_reset(struct nec7210_priv *priv, const gpib_board_t *board) +void nec7210_board_reset(struct nec7210_priv *priv, const struct gpib_board *board) { /* 7210 chip reset */ write_byte(priv, AUX_CR, AUXMR); @@ -1014,7 +993,7 @@ void nec7210_board_reset(struct nec7210_priv *priv, const gpib_board_t *board) } EXPORT_SYMBOL(nec7210_board_reset); -void nec7210_board_online(struct nec7210_priv *priv, const gpib_board_t *board) +void nec7210_board_online(struct nec7210_priv *priv, const struct gpib_board *board) { /* set GPIB address */ nec7210_primary_address(board, priv, board->pad);
diff --git a/drivers/staging/gpib/ni_usb/ni_usb_gpib.c b/drivers/staging/gpib/ni_usb/ni_usb_gpib.c index d0656dc..9f1b992 100644 --- a/drivers/staging/gpib/ni_usb/ni_usb_gpib.c +++ b/drivers/staging/gpib/ni_usb/ni_usb_gpib.c
@@ -5,6 +5,10 @@ * copyright : (C) 2004 by Frank Mori Hess ***************************************************************************/ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#define dev_fmt pr_fmt +#define DRV_NAME KBUILD_MODNAME + #include <linux/kernel.h> #include <linux/module.h> #include <linux/slab.h> @@ -20,7 +24,7 @@ MODULE_DESCRIPTION("GPIB driver for National Instruments USB devices"); static struct usb_interface *ni_usb_driver_interfaces[MAX_NUM_NI_USB_INTERFACES]; static int ni_usb_parse_status_block(const u8 *buffer, struct ni_usb_status_block *status); -static int ni_usb_set_interrupt_monitor(gpib_board_t *board, unsigned int monitored_bits); +static int ni_usb_set_interrupt_monitor(struct gpib_board *board, unsigned int monitored_bits); static void ni_usb_stop(struct ni_usb_priv *ni_priv); static DEFINE_MUTEX(ni_usb_hotplug_lock); @@ -75,7 +79,7 @@ static unsigned short ni_usb_timeout_code(unsigned int usec) */ else if (usec <= 1000000000) return 0x02; - pr_err("%s: bug? usec is greater than 1e9\n", __func__); + pr_err("bug? usec is greater than 1e9\n"); return 0xf0; } @@ -83,8 +87,6 @@ static void ni_usb_bulk_complete(struct urb *urb) { struct ni_usb_urb_ctx *context = urb->context; -// printk("debug: %s: status=0x%x, error_count=%i, actual_length=%i\n", __func__, -// urb->status, urb->error_count, urb->actual_length); complete(&context->complete); } @@ -134,11 +136,11 @@ static int ni_usb_nonblocking_send_bulk_msg(struct ni_usb_priv *ni_priv, void *d retval = usb_submit_urb(ni_priv->bulk_urb, GFP_KERNEL); if (retval) { - del_timer_sync(&ni_priv->bulk_timer); + timer_delete_sync(&ni_priv->bulk_timer); usb_free_urb(ni_priv->bulk_urb); ni_priv->bulk_urb = NULL; - dev_err(&usb_dev->dev, "%s: failed to submit bulk out urb, retval=%i\n", - __func__, retval); + dev_err(&usb_dev->dev, "failed to submit bulk out urb, retval=%i\n", + retval); mutex_unlock(&ni_priv->bulk_transfer_lock); return retval; } @@ -146,13 +148,13 @@ static int ni_usb_nonblocking_send_bulk_msg(struct ni_usb_priv *ni_priv, void *d wait_for_completion(&context->complete); // wait for ni_usb_bulk_complete if (context->timed_out) { usb_kill_urb(ni_priv->bulk_urb); - dev_err(&usb_dev->dev, "%s: killed urb due to timeout\n", __func__); + dev_err(&usb_dev->dev, "killed urb due to timeout\n"); retval = -ETIMEDOUT; } else { retval = ni_priv->bulk_urb->status; } - del_timer_sync(&ni_priv->bulk_timer); + timer_delete_sync(&ni_priv->bulk_timer); *actual_data_length = ni_priv->bulk_urb->actual_length; mutex_lock(&ni_priv->bulk_transfer_lock); usb_free_urb(ni_priv->bulk_urb); @@ -218,14 +220,12 @@ static int ni_usb_nonblocking_receive_bulk_msg(struct ni_usb_priv *ni_priv, if (timeout_msecs) mod_timer(&ni_priv->bulk_timer, jiffies + msecs_to_jiffies(timeout_msecs)); - //printk("%s: submitting urb\n", __func__); retval = usb_submit_urb(ni_priv->bulk_urb, GFP_KERNEL); if (retval) { - del_timer_sync(&ni_priv->bulk_timer); + timer_delete_sync(&ni_priv->bulk_timer); usb_free_urb(ni_priv->bulk_urb); ni_priv->bulk_urb = NULL; - dev_err(&usb_dev->dev, "%s: failed to submit bulk out urb, retval=%i\n", - __func__, retval); + dev_err(&usb_dev->dev, "failed to submit bulk in urb, retval=%i\n", retval); mutex_unlock(&ni_priv->bulk_transfer_lock); return retval; } @@ -250,13 +250,13 @@ static int ni_usb_nonblocking_receive_bulk_msg(struct ni_usb_priv *ni_priv, } if (context->timed_out) { usb_kill_urb(ni_priv->bulk_urb); - dev_err(&usb_dev->dev, "%s: killed urb due to timeout\n", __func__); + dev_err(&usb_dev->dev, "killed urb due to timeout\n"); retval = -ETIMEDOUT; } else { if (ni_priv->bulk_urb->status) retval = ni_priv->bulk_urb->status; } - del_timer_sync(&ni_priv->bulk_timer); + timer_delete_sync(&ni_priv->bulk_timer); *actual_data_length = ni_priv->bulk_urb->actual_length; mutex_lock(&ni_priv->bulk_transfer_lock); usb_free_urb(ni_priv->bulk_urb); @@ -310,7 +310,7 @@ static int ni_usb_receive_control_msg(struct ni_usb_priv *ni_priv, __u8 request, return retval; } -static void ni_usb_soft_update_status(gpib_board_t *board, unsigned int ni_usb_ibsta, +static void ni_usb_soft_update_status(struct gpib_board *board, unsigned int ni_usb_ibsta, unsigned int clear_mask) { static const unsigned int ni_usb_ibsta_mask = SRQI | ATN | CIC | REM | LACS | TACS | LOK; @@ -330,14 +330,14 @@ static void ni_usb_soft_update_status(gpib_board_t *board, unsigned int ni_usb_i ni_priv->monitored_ibsta_bits &= ~ni_usb_ibsta; need_monitoring_bits &= ~ni_priv->monitored_ibsta_bits; /* mm - monitored set */ spin_unlock_irqrestore(&board->spinlock, flags); - dev_dbg(&usb_dev->dev, "%s: need_monitoring_bits=0x%x\n", __func__, need_monitoring_bits); + dev_dbg(&usb_dev->dev, "need_monitoring_bits=0x%x\n", need_monitoring_bits); if (need_monitoring_bits & ~ni_usb_ibsta) ni_usb_set_interrupt_monitor(board, ni_usb_ibsta_monitor_mask); else if (need_monitoring_bits & ni_usb_ibsta) wake_up_interruptible(&board->wait); - dev_dbg(&usb_dev->dev, "%s: ni_usb_ibsta=0x%x\n", __func__, ni_usb_ibsta); + dev_dbg(&usb_dev->dev, "ibsta=0x%x\n", ni_usb_ibsta); } static int ni_usb_parse_status_block(const u8 *buffer, struct ni_usb_status_block *status) @@ -371,7 +371,7 @@ static int ni_usb_parse_register_read_block(const u8 *raw_data, unsigned int *re int k; if (raw_data[i++] != NIUSB_REGISTER_READ_DATA_START_ID) { - pr_err("%s: parse error: wrong start id\n", __func__); + pr_err("parse error: wrong start id\n"); unexpected = 1; } for (k = 0; k < results_per_chunk && j < num_results; ++k) @@ -380,18 +380,18 @@ static int ni_usb_parse_register_read_block(const u8 *raw_data, unsigned int *re while (i % 4) i++; if (raw_data[i++] != NIUSB_REGISTER_READ_DATA_END_ID) { - pr_err("%s: parse error: wrong end id\n", __func__); + pr_err("parse error: wrong end id\n"); unexpected = 1; } if (raw_data[i++] % results_per_chunk != num_results % results_per_chunk) { - pr_err("%s: parse error: wrong count=%i for NIUSB_REGISTER_READ_DATA_END\n", - __func__, (int)raw_data[i - 1]); + pr_err("parse error: wrong count=%i for NIUSB_REGISTER_READ_DATA_END\n", + (int)raw_data[i - 1]); unexpected = 1; } while (i % 4) { if (raw_data[i++] != 0) { - pr_err("%s: unexpected data: raw_data[%i]=0x%x, expected 0\n", - __func__, i - 1, (int)raw_data[i - 1]); + pr_err("unexpected data: raw_data[%i]=0x%x, expected 0\n", + i - 1, (int)raw_data[i - 1]); unexpected = 1; } } @@ -408,9 +408,8 @@ static int ni_usb_parse_termination_block(const u8 *buffer) buffer[i++] != 0x0 || buffer[i++] != 0x0 || buffer[i++] != 0x0) { - pr_err("%s: received unexpected termination block\n", __func__); - pr_err(" expected: 0x%x 0x%x 0x%x 0x%x\n", - NIUSB_TERM_ID, 0x0, 0x0, 0x0); + pr_err("received unexpected termination block\n"); + pr_err(" expected: 0x%x 0x%x 0x%x 0x%x\n", NIUSB_TERM_ID, 0x0, 0x0, 0x0); pr_err(" received: 0x%x 0x%x 0x%x 0x%x\n", buffer[i - 4], buffer[i - 3], buffer[i - 2], buffer[i - 1]); } @@ -427,7 +426,6 @@ static int parse_board_ibrd_readback(const u8 *raw_data, struct ni_usb_status_bl int i = 0; int j = 0; int k; - unsigned int adr1_bits; int num_data_blocks = 0; struct ni_usb_status_block register_write_status; int unexpected = 0; @@ -438,12 +436,12 @@ static int parse_board_ibrd_readback(const u8 *raw_data, struct ni_usb_status_bl } else if (raw_data[i] == NIUSB_IBRD_EXTENDED_DATA_ID) { data_block_length = ibrd_extended_data_block_length; if (raw_data[++i] != 0) { - pr_err("%s: unexpected data: raw_data[%i]=0x%x, expected 0\n", - __func__, i, (int)raw_data[i]); + pr_err("unexpected data: raw_data[%i]=0x%x, expected 0\n", + i, (int)raw_data[i]); unexpected = 1; } } else { - pr_err("%s: logic bug!\n", __func__); + pr_err("Unexpected NIUSB_IBRD ID\n"); return -EINVAL; } ++i; @@ -457,10 +455,10 @@ static int parse_board_ibrd_readback(const u8 *raw_data, struct ni_usb_status_bl } i += ni_usb_parse_status_block(&raw_data[i], status); if (status->id != NIUSB_IBRD_STATUS_ID) { - pr_err("%s: bug: status->id=%i, != ibrd_status_id\n", __func__, status->id); + pr_err("bug: status->id=%i, != ibrd_status_id\n", status->id); return -EIO; } - adr1_bits = raw_data[i++]; + i++; if (num_data_blocks) { *actual_bytes_read = (num_data_blocks - 1) * data_block_length + raw_data[i++]; } else { @@ -468,29 +466,28 @@ static int parse_board_ibrd_readback(const u8 *raw_data, struct ni_usb_status_bl *actual_bytes_read = 0; } if (*actual_bytes_read > j) - pr_err("%s: bug: discarded data. actual_bytes_read=%i, j=%i\n", - __func__, *actual_bytes_read, j); + pr_err("bug: discarded data. actual_bytes_read=%i, j=%i\n", *actual_bytes_read, j); for (k = 0; k < 2; k++) if (raw_data[i++] != 0) { - pr_err("%s: unexpected data: raw_data[%i]=0x%x, expected 0\n", - __func__, i - 1, (int)raw_data[i - 1]); + pr_err("unexpected data: raw_data[%i]=0x%x, expected 0\n", + i - 1, (int)raw_data[i - 1]); unexpected = 1; } i += ni_usb_parse_status_block(&raw_data[i], ®ister_write_status); if (register_write_status.id != NIUSB_REG_WRITE_ID) { - pr_err("%s: unexpected data: register write status id=0x%x, expected 0x%x\n", - __func__, register_write_status.id, NIUSB_REG_WRITE_ID); + pr_err("unexpected data: register write status id=0x%x, expected 0x%x\n", + register_write_status.id, NIUSB_REG_WRITE_ID); unexpected = 1; } if (raw_data[i++] != 2) { - pr_err("%s: unexpected data: register write count=%i, expected 2\n", - __func__, (int)raw_data[i - 1]); + pr_err("unexpected data: register write count=%i, expected 2\n", + (int)raw_data[i - 1]); unexpected = 1; } for (k = 0; k < 3; k++) if (raw_data[i++] != 0) { - pr_err("%s: unexpected data: raw_data[%i]=0x%x, expected 0\n", - __func__, i - 1, (int)raw_data[i - 1]); + pr_err("unexpected data: raw_data[%i]=0x%x, expected 0\n", + i - 1, (int)raw_data[i - 1]); unexpected = 1; } i += ni_usb_parse_termination_block(&raw_data[i]); @@ -530,18 +527,14 @@ static int ni_usb_write_registers(struct ni_usb_priv *ni_priv, out_data_length = num_writes * bytes_per_write + 0x10; out_data = kmalloc(out_data_length, GFP_KERNEL); - if (!out_data) { - dev_err(&usb_dev->dev, "%s: kmalloc failed\n", __func__); + if (!out_data) return -ENOMEM; - } i += ni_usb_bulk_register_write_header(&out_data[i], num_writes); for (j = 0; j < num_writes; j++) i += ni_usb_bulk_register_write(&out_data[i], writes[j]); while (i % 4) out_data[i++] = 0x00; i += ni_usb_bulk_termination(&out_data[i]); - if (i > out_data_length) - dev_err(&usb_dev->dev, "%s: bug! buffer overrun\n", __func__); mutex_lock(&ni_priv->addressed_transfer_lock); @@ -549,22 +542,21 @@ static int ni_usb_write_registers(struct ni_usb_priv *ni_priv, kfree(out_data); if (retval) { mutex_unlock(&ni_priv->addressed_transfer_lock); - dev_err(&usb_dev->dev, "%s: ni_usb_send_bulk_msg returned %i, bytes_written=%i, i=%i\n", - __func__, retval, bytes_written, i); + dev_err(&usb_dev->dev, "send_bulk_msg returned %i, bytes_written=%i, i=%i\n", + retval, bytes_written, i); return retval; } in_data = kmalloc(in_data_length, GFP_KERNEL); if (!in_data) { mutex_unlock(&ni_priv->addressed_transfer_lock); - dev_err(&usb_dev->dev, "%s: kmalloc failed\n", __func__); return -ENOMEM; } retval = ni_usb_receive_bulk_msg(ni_priv, in_data, in_data_length, &bytes_read, 1000, 0); if (retval || bytes_read != 16) { mutex_unlock(&ni_priv->addressed_transfer_lock); - dev_err(&usb_dev->dev, "%s: ni_usb_receive_bulk_msg returned %i, bytes_read=%i\n", - __func__, retval, bytes_read); + dev_err(&usb_dev->dev, "receive_bulk_msg returned %i, bytes_read=%i\n", + retval, bytes_read); ni_usb_dump_raw_block(in_data, bytes_read); kfree(in_data); return retval; @@ -576,18 +568,16 @@ static int ni_usb_write_registers(struct ni_usb_priv *ni_priv, //FIXME parse extra 09 status bits and termination kfree(in_data); if (status.id != NIUSB_REG_WRITE_ID) { - dev_err(&usb_dev->dev, "%s: parse error, id=0x%x != NIUSB_REG_WRITE_ID\n", - __func__, status.id); + dev_err(&usb_dev->dev, "parse error, id=0x%x != NIUSB_REG_WRITE_ID\n", status.id); return -EIO; } if (status.error_code) { - dev_err(&usb_dev->dev, "%s: nonzero error code 0x%x\n", - __func__, status.error_code); + dev_err(&usb_dev->dev, "nonzero error code 0x%x\n", status.error_code); return -EIO; } if (reg_writes_completed != num_writes) { - dev_err(&usb_dev->dev, "%s: reg_writes_completed=%i, num_writes=%i\n", - __func__, reg_writes_completed, num_writes); + dev_err(&usb_dev->dev, "reg_writes_completed=%i, num_writes=%i\n", + reg_writes_completed, num_writes); return -EIO; } if (ibsta) @@ -596,12 +586,12 @@ static int ni_usb_write_registers(struct ni_usb_priv *ni_priv, } // interface functions -static int ni_usb_read(gpib_board_t *board, uint8_t *buffer, size_t length, +static int ni_usb_read(struct gpib_board *board, uint8_t *buffer, size_t length, int *end, size_t *bytes_read) { int retval, parse_retval; struct ni_usb_priv *ni_priv = board->private_data; - struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface); + struct usb_device *usb_dev; u8 *out_data, *in_data; static const int out_data_length = 0x20; int in_data_length; @@ -614,10 +604,11 @@ static int ni_usb_read(gpib_board_t *board, uint8_t *buffer, size_t length, struct ni_usb_register reg; *bytes_read = 0; - if (length > max_read_length) { - length = max_read_length; - dev_err(&usb_dev->dev, "%s: read length too long\n", __func__); - } + if (!ni_priv->bus_interface) + return -ENODEV; + if (length > max_read_length) + return -EINVAL; + usb_dev = interface_to_usbdev(ni_priv->bus_interface); out_data = kmalloc(out_data_length, GFP_KERNEL); if (!out_data) return -ENOMEM; @@ -649,8 +640,8 @@ static int ni_usb_read(gpib_board_t *board, uint8_t *buffer, size_t length, if (retval || usb_bytes_written != i) { if (retval == 0) retval = -EIO; - dev_err(&usb_dev->dev, "%s: ni_usb_send_bulk_msg returned %i, usb_bytes_written=%i, i=%i\n", - __func__, retval, usb_bytes_written, i); + dev_err(&usb_dev->dev, "send_bulk_msg returned %i, usb_bytes_written=%i, i=%i\n", + retval, usb_bytes_written, i); mutex_unlock(&ni_priv->addressed_transfer_lock); return retval; } @@ -668,8 +659,8 @@ static int ni_usb_read(gpib_board_t *board, uint8_t *buffer, size_t length, if (retval == -ERESTARTSYS) { } else if (retval) { - dev_err(&usb_dev->dev, "%s: ni_usb_receive_bulk_msg returned %i, usb_bytes_read=%i\n", - __func__, retval, usb_bytes_read); + dev_err(&usb_dev->dev, "receive_bulk_msg returned %i, usb_bytes_read=%i\n", + retval, usb_bytes_read); kfree(in_data); return retval; } @@ -677,14 +668,14 @@ static int ni_usb_read(gpib_board_t *board, uint8_t *buffer, size_t length, if (parse_retval != usb_bytes_read) { if (parse_retval >= 0) parse_retval = -EIO; - dev_err(&usb_dev->dev, "%s: retval=%i usb_bytes_read=%i\n", - __func__, parse_retval, usb_bytes_read); + dev_err(&usb_dev->dev, "retval=%i usb_bytes_read=%i\n", + parse_retval, usb_bytes_read); kfree(in_data); return parse_retval; } if (actual_length != length - status.count) { - dev_err(&usb_dev->dev, "%s: actual_length=%i expected=%li\n", - __func__, actual_length, (long)(length - status.count)); + dev_err(&usb_dev->dev, "actual_length=%i expected=%li\n", + actual_length, (long)(length - status.count)); ni_usb_dump_raw_block(in_data, usb_bytes_read); } kfree(in_data); @@ -699,7 +690,7 @@ static int ni_usb_read(gpib_board_t *board, uint8_t *buffer, size_t length, break; case NIUSB_ATN_STATE_ERROR: retval = -EIO; - dev_err(&usb_dev->dev, "%s: read when ATN set\n", __func__); + dev_err(&usb_dev->dev, "read when ATN set\n"); break; case NIUSB_ADDRESSING_ERROR: retval = -EIO; @@ -708,12 +699,11 @@ static int ni_usb_read(gpib_board_t *board, uint8_t *buffer, size_t length, retval = -ETIMEDOUT; break; case NIUSB_EOSMODE_ERROR: - dev_err(&usb_dev->dev, "%s: driver bug, we should have been able to avoid NIUSB_EOSMODE_ERROR.\n", - __func__); + dev_err(&usb_dev->dev, "driver bug, we should have been able to avoid NIUSB_EOSMODE_ERROR.\n"); retval = -EINVAL; break; default: - dev_err(&usb_dev->dev, "%s: unknown error code=%i\n", __func__, status.error_code); + dev_err(&usb_dev->dev, "unknown error code=%i\n", status.error_code); retval = -EIO; break; } @@ -726,12 +716,12 @@ static int ni_usb_read(gpib_board_t *board, uint8_t *buffer, size_t length, return retval; } -static int ni_usb_write(gpib_board_t *board, uint8_t *buffer, size_t length, +static int ni_usb_write(struct gpib_board *board, uint8_t *buffer, size_t length, int send_eoi, size_t *bytes_written) { int retval; struct ni_usb_priv *ni_priv = board->private_data; - struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface); + struct usb_device *usb_dev; u8 *out_data, *in_data; int out_data_length; static const int in_data_length = 0x10; @@ -741,12 +731,11 @@ static int ni_usb_write(gpib_board_t *board, uint8_t *buffer, size_t length, struct ni_usb_status_block status; static const int max_write_length = 0xffff; - *bytes_written = 0; - if (length > max_write_length) { - length = max_write_length; - send_eoi = 0; - dev_err(&usb_dev->dev, "%s: write length too long\n", __func__); - } + if (!ni_priv->bus_interface) + return -ENODEV; + if (length > max_write_length) + return -EINVAL; + usb_dev = interface_to_usbdev(ni_priv->bus_interface); out_data_length = length + 0x10; out_data = kmalloc(out_data_length, GFP_KERNEL); if (!out_data) @@ -777,8 +766,8 @@ static int ni_usb_write(gpib_board_t *board, uint8_t *buffer, size_t length, kfree(out_data); if (retval || usb_bytes_written != i) { mutex_unlock(&ni_priv->addressed_transfer_lock); - dev_err(&usb_dev->dev, "%s: ni_usb_send_bulk_msg returned %i, usb_bytes_written=%i, i=%i\n", - __func__, retval, usb_bytes_written, i); + dev_err(&usb_dev->dev, "send_bulk_msg returned %i, usb_bytes_written=%i, i=%i\n", + retval, usb_bytes_written, i); return retval; } @@ -793,8 +782,8 @@ static int ni_usb_write(gpib_board_t *board, uint8_t *buffer, size_t length, mutex_unlock(&ni_priv->addressed_transfer_lock); if ((retval && retval != -ERESTARTSYS) || usb_bytes_read != 12) { - dev_err(&usb_dev->dev, "%s: ni_usb_receive_bulk_msg returned %i, usb_bytes_read=%i\n", - __func__, retval, usb_bytes_read); + dev_err(&usb_dev->dev, "receive_bulk_msg returned %i, usb_bytes_read=%i\n", + retval, usb_bytes_read); kfree(in_data); return retval; } @@ -810,8 +799,8 @@ static int ni_usb_write(gpib_board_t *board, uint8_t *buffer, size_t length, */ break; case NIUSB_ADDRESSING_ERROR: - dev_err(&usb_dev->dev, "%s: Addressing error retval %d error code=%i\n", - __func__, retval, status.error_code); + dev_err(&usb_dev->dev, "Addressing error retval %d error code=%i\n", + retval, status.error_code); retval = -ENXIO; break; case NIUSB_NO_LISTENER_ERROR: @@ -821,8 +810,7 @@ static int ni_usb_write(gpib_board_t *board, uint8_t *buffer, size_t length, retval = -ETIMEDOUT; break; default: - dev_err(&usb_dev->dev, "%s: unknown error code=%i\n", - __func__, status.error_code); + dev_err(&usb_dev->dev, "unknown error code=%i\n", status.error_code); retval = -EPIPE; break; } @@ -831,12 +819,12 @@ static int ni_usb_write(gpib_board_t *board, uint8_t *buffer, size_t length, return retval; } -static int ni_usb_command_chunk(gpib_board_t *board, uint8_t *buffer, size_t length, +static int ni_usb_command_chunk(struct gpib_board *board, uint8_t *buffer, size_t length, size_t *command_bytes_written) { int retval; struct ni_usb_priv *ni_priv = board->private_data; - struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface); + struct usb_device *usb_dev; u8 *out_data, *in_data; int out_data_length; static const int in_data_length = 0x10; @@ -848,8 +836,11 @@ static int ni_usb_command_chunk(gpib_board_t *board, uint8_t *buffer, size_t len static const int max_command_length = 0x10; *command_bytes_written = 0; + if (!ni_priv->bus_interface) + return -ENODEV; if (length > max_command_length) length = max_command_length; + usb_dev = interface_to_usbdev(ni_priv->bus_interface); out_data_length = length + 0x10; out_data = kmalloc(out_data_length, GFP_KERNEL); if (!out_data) @@ -873,8 +864,8 @@ static int ni_usb_command_chunk(gpib_board_t *board, uint8_t *buffer, size_t len kfree(out_data); if (retval || bytes_written != i) { mutex_unlock(&ni_priv->addressed_transfer_lock); - dev_err(&usb_dev->dev, "%s: ni_usb_send_bulk_msg returned %i, bytes_written=%i, i=%i\n", - __func__, retval, bytes_written, i); + dev_err(&usb_dev->dev, "send_bulk_msg returned %i, bytes_written=%i, i=%i\n", + retval, bytes_written, i); return retval; } @@ -890,8 +881,8 @@ static int ni_usb_command_chunk(gpib_board_t *board, uint8_t *buffer, size_t len mutex_unlock(&ni_priv->addressed_transfer_lock); if ((retval && retval != -ERESTARTSYS) || bytes_read != 12) { - dev_err(&usb_dev->dev, "%s: ni_usb_receive_bulk_msg returned %i, bytes_read=%i\n", - __func__, retval, bytes_read); + dev_err(&usb_dev->dev, "receive_bulk_msg returned %i, bytes_read=%i\n", + retval, bytes_read); kfree(in_data); return retval; } @@ -909,19 +900,19 @@ static int ni_usb_command_chunk(gpib_board_t *board, uint8_t *buffer, size_t len case NIUSB_NO_BUS_ERROR: return -ENOTCONN; case NIUSB_EOSMODE_ERROR: - dev_err(&usb_dev->dev, "%s: got eosmode error. Driver bug?\n", __func__); + dev_err(&usb_dev->dev, "got eosmode error. Driver bug?\n"); return -EIO; case NIUSB_TIMEOUT_ERROR: return -ETIMEDOUT; default: - dev_err(&usb_dev->dev, "%s: unknown error code=%i\n", __func__, status.error_code); + dev_err(&usb_dev->dev, "unknown error code=%i\n", status.error_code); return -EIO; } ni_usb_soft_update_status(board, status.ibsta, 0); return 0; } -static int ni_usb_command(gpib_board_t *board, uint8_t *buffer, size_t length, +static int ni_usb_command(struct gpib_board *board, uint8_t *buffer, size_t length, size_t *bytes_written) { size_t count; @@ -938,11 +929,11 @@ static int ni_usb_command(gpib_board_t *board, uint8_t *buffer, size_t length, return 0; } -static int ni_usb_take_control(gpib_board_t *board, int synchronous) +static int ni_usb_take_control(struct gpib_board *board, int synchronous) { int retval; struct ni_usb_priv *ni_priv = board->private_data; - struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface); + struct usb_device *usb_dev; u8 *out_data, *in_data; static const int out_data_length = 0x10; static const int in_data_length = 0x10; @@ -950,6 +941,9 @@ static int ni_usb_take_control(gpib_board_t *board, int synchronous) int i = 0; struct ni_usb_status_block status; + if (!ni_priv->bus_interface) + return -ENODEV; + usb_dev = interface_to_usbdev(ni_priv->bus_interface); out_data = kmalloc(out_data_length, GFP_KERNEL); if (!out_data) return -ENOMEM; @@ -968,15 +962,14 @@ static int ni_usb_take_control(gpib_board_t *board, int synchronous) kfree(out_data); if (retval || bytes_written != i) { mutex_unlock(&ni_priv->addressed_transfer_lock); - dev_err(&usb_dev->dev, "%s: ni_usb_send_bulk_msg returned %i, bytes_written=%i, i=%i\n", - __func__, retval, bytes_written, i); + dev_err(&usb_dev->dev, "send_bulk_msg returned %i, bytes_written=%i, i=%i\n", + retval, bytes_written, i); return retval; } in_data = kmalloc(in_data_length, GFP_KERNEL); if (!in_data) { mutex_unlock(&ni_priv->addressed_transfer_lock); - dev_err(&usb_dev->dev, "%s: kmalloc failed\n", __func__); return -ENOMEM; } retval = ni_usb_receive_bulk_msg(ni_priv, in_data, in_data_length, &bytes_read, 1000, 1); @@ -986,8 +979,8 @@ static int ni_usb_take_control(gpib_board_t *board, int synchronous) if ((retval && retval != -ERESTARTSYS) || bytes_read != 12) { if (retval == 0) retval = -EIO; - dev_err(&usb_dev->dev, "%s: ni_usb_receive_bulk_msg returned %i, bytes_read=%i\n", - __func__, retval, bytes_read); + dev_err(&usb_dev->dev, "receive_bulk_msg returned %i, bytes_read=%i\n", + retval, bytes_read); kfree(in_data); return retval; } @@ -997,11 +990,11 @@ static int ni_usb_take_control(gpib_board_t *board, int synchronous) return retval; } -static int ni_usb_go_to_standby(gpib_board_t *board) +static int ni_usb_go_to_standby(struct gpib_board *board) { int retval; struct ni_usb_priv *ni_priv = board->private_data; - struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface); + struct usb_device *usb_dev; u8 *out_data, *in_data; static const int out_data_length = 0x10; static const int in_data_length = 0x20; @@ -1009,6 +1002,9 @@ static int ni_usb_go_to_standby(gpib_board_t *board) int i = 0; struct ni_usb_status_block status; + if (!ni_priv->bus_interface) + return -ENODEV; + usb_dev = interface_to_usbdev(ni_priv->bus_interface); out_data = kmalloc(out_data_length, GFP_KERNEL); if (!out_data) return -ENOMEM; @@ -1025,15 +1021,14 @@ static int ni_usb_go_to_standby(gpib_board_t *board) kfree(out_data); if (retval || bytes_written != i) { mutex_unlock(&ni_priv->addressed_transfer_lock); - dev_err(&usb_dev->dev, "%s: ni_usb_send_bulk_msg returned %i, bytes_written=%i, i=%i\n", - __func__, retval, bytes_written, i); + dev_err(&usb_dev->dev, "send_bulk_msg returned %i, bytes_written=%i, i=%i\n", + retval, bytes_written, i); return retval; } in_data = kmalloc(in_data_length, GFP_KERNEL); if (!in_data) { mutex_unlock(&ni_priv->addressed_transfer_lock); - dev_err(&usb_dev->dev, "%s: kmalloc failed\n", __func__); return -ENOMEM; } retval = ni_usb_receive_bulk_msg(ni_priv, in_data, in_data_length, &bytes_read, 1000, 0); @@ -1041,29 +1036,31 @@ static int ni_usb_go_to_standby(gpib_board_t *board) mutex_unlock(&ni_priv->addressed_transfer_lock); if (retval || bytes_read != 12) { - dev_err(&usb_dev->dev, "%s: ni_usb_receive_bulk_msg returned %i, bytes_read=%i\n", - __func__, retval, bytes_read); + dev_err(&usb_dev->dev, "receive_bulk_msg returned %i, bytes_read=%i\n", + retval, bytes_read); kfree(in_data); return retval; } ni_usb_parse_status_block(in_data, &status); kfree(in_data); if (status.id != NIUSB_IBGTS_ID) - dev_err(&usb_dev->dev, "%s: bug: status.id 0x%x != INUSB_IBGTS_ID\n", - __func__, status.id); + dev_err(&usb_dev->dev, "bug: status.id 0x%x != INUSB_IBGTS_ID\n", status.id); ni_usb_soft_update_status(board, status.ibsta, 0); return 0; } -static void ni_usb_request_system_control(gpib_board_t *board, int request_control) +static void ni_usb_request_system_control(struct gpib_board *board, int request_control) { int retval; struct ni_usb_priv *ni_priv = board->private_data; - struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface); + struct usb_device *usb_dev; int i = 0; struct ni_usb_register writes[4]; unsigned int ibsta; + if (!ni_priv->bus_interface) + return; // -ENODEV; + usb_dev = interface_to_usbdev(ni_priv->bus_interface); if (request_control) { writes[i].device = NIUSB_SUBDEV_TNT4882; writes[i].address = CMDR; @@ -1093,7 +1090,7 @@ static void ni_usb_request_system_control(gpib_board_t *board, int request_contr } retval = ni_usb_write_registers(ni_priv, writes, i, &ibsta); if (retval < 0) { - dev_err(&usb_dev->dev, "%s: register write failed, retval=%i\n", __func__, retval); + dev_err(&usb_dev->dev, "register write failed, retval=%i\n", retval); return; // retval; } if (!request_control) @@ -1103,11 +1100,11 @@ static void ni_usb_request_system_control(gpib_board_t *board, int request_contr } //FIXME maybe the interface should have a "pulse interface clear" function that can return an error? -static void ni_usb_interface_clear(gpib_board_t *board, int assert) +static void ni_usb_interface_clear(struct gpib_board *board, int assert) { int retval; struct ni_usb_priv *ni_priv = board->private_data; - struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface); + struct usb_device *usb_dev; u8 *out_data, *in_data; static const int out_data_length = 0x10; static const int in_data_length = 0x10; @@ -1115,14 +1112,15 @@ static void ni_usb_interface_clear(gpib_board_t *board, int assert) int i = 0; struct ni_usb_status_block status; - // FIXME: we are going to pulse when assert is true, and ignore otherwise + if (!ni_priv->bus_interface) + return; // -ENODEV; + usb_dev = interface_to_usbdev(ni_priv->bus_interface); +// FIXME: we are going to pulse when assert is true, and ignore otherwise if (assert == 0) return; out_data = kmalloc(out_data_length, GFP_KERNEL); - if (!out_data) { - dev_err(&usb_dev->dev, "%s: kmalloc failed\n", __func__); + if (!out_data) return; - } out_data[i++] = NIUSB_IBSIC_ID; out_data[i++] = 0x0; out_data[i++] = 0x0; @@ -1131,8 +1129,8 @@ static void ni_usb_interface_clear(gpib_board_t *board, int assert) retval = ni_usb_send_bulk_msg(ni_priv, out_data, i, &bytes_written, 1000); kfree(out_data); if (retval || bytes_written != i) { - dev_err(&usb_dev->dev, "%s: ni_usb_send_bulk_msg returned %i, bytes_written=%i, i=%i\n", - __func__, retval, bytes_written, i); + dev_err(&usb_dev->dev, "send_bulk_msg returned %i, bytes_written=%i, i=%i\n", + retval, bytes_written, i); return; } in_data = kmalloc(in_data_length, GFP_KERNEL); @@ -1141,8 +1139,8 @@ static void ni_usb_interface_clear(gpib_board_t *board, int assert) retval = ni_usb_receive_bulk_msg(ni_priv, in_data, in_data_length, &bytes_read, 1000, 0); if (retval || bytes_read != 12) { - dev_err(&usb_dev->dev, "%s: ni_usb_receive_bulk_msg returned %i, bytes_read=%i\n", - __func__, retval, bytes_read); + dev_err(&usb_dev->dev, "receive_bulk_msg returned %i, bytes_read=%i\n", + retval, bytes_read); kfree(in_data); return; } @@ -1151,14 +1149,17 @@ static void ni_usb_interface_clear(gpib_board_t *board, int assert) ni_usb_soft_update_status(board, status.ibsta, 0); } -static void ni_usb_remote_enable(gpib_board_t *board, int enable) +static void ni_usb_remote_enable(struct gpib_board *board, int enable) { int retval; struct ni_usb_priv *ni_priv = board->private_data; - struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface); + struct usb_device *usb_dev; struct ni_usb_register reg; unsigned int ibsta; + if (!ni_priv->bus_interface) + return; // -ENODEV; + usb_dev = interface_to_usbdev(ni_priv->bus_interface); reg.device = NIUSB_SUBDEV_TNT4882; reg.address = nec7210_to_tnt4882_offset(AUXMR); if (enable) @@ -1167,7 +1168,7 @@ static void ni_usb_remote_enable(gpib_board_t *board, int enable) reg.value = AUX_CREN; retval = ni_usb_write_registers(ni_priv, ®, 1, &ibsta); if (retval < 0) { - dev_err(&usb_dev->dev, "%s: register write failed, retval=%i\n", __func__, retval); + dev_err(&usb_dev->dev, "register write failed, retval=%i\n", retval); return; //retval; } ni_priv->ren_state = enable; @@ -1175,7 +1176,7 @@ static void ni_usb_remote_enable(gpib_board_t *board, int enable) return;// 0; } -static int ni_usb_enable_eos(gpib_board_t *board, uint8_t eos_byte, int compare_8_bits) +static int ni_usb_enable_eos(struct gpib_board *board, uint8_t eos_byte, int compare_8_bits) { struct ni_usb_priv *ni_priv = board->private_data; @@ -1188,7 +1189,7 @@ static int ni_usb_enable_eos(gpib_board_t *board, uint8_t eos_byte, int compare_ return 0; } -static void ni_usb_disable_eos(gpib_board_t *board) +static void ni_usb_disable_eos(struct gpib_board *board) { struct ni_usb_priv *ni_priv = board->private_data; /* adapter gets unhappy if you don't zero all the bits @@ -1198,16 +1199,18 @@ static void ni_usb_disable_eos(gpib_board_t *board) ni_priv->eos_char = 0; } -static unsigned int ni_usb_update_status(gpib_board_t *board, unsigned int clear_mask) +static unsigned int ni_usb_update_status(struct gpib_board *board, unsigned int clear_mask) { int retval; struct ni_usb_priv *ni_priv = board->private_data; - struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface); + struct usb_device *usb_dev; static const int buffer_length = 8; u8 *buffer; struct ni_usb_status_block status; - //printk("%s: receive control pipe is %i\n", __func__, pipe); + if (!ni_priv->bus_interface) + return -ENODEV; + usb_dev = interface_to_usbdev(ni_priv->bus_interface); buffer = kmalloc(buffer_length, GFP_KERNEL); if (!buffer) return board->status; @@ -1216,7 +1219,7 @@ static unsigned int ni_usb_update_status(gpib_board_t *board, unsigned int clear USB_TYPE_VENDOR | USB_RECIP_DEVICE, 0x200, 0x0, buffer, buffer_length, 1000); if (retval != buffer_length) { - dev_err(&usb_dev->dev, "%s: usb_control_msg returned %i\n", __func__, retval); + dev_err(&usb_dev->dev, "usb_control_msg returned %i\n", retval); kfree(buffer); return board->status; } @@ -1235,7 +1238,6 @@ static void ni_usb_stop(struct ni_usb_priv *ni_priv) u8 *buffer; struct ni_usb_status_block status; - //printk("%s: receive control pipe is %i\n", __func__, pipe); buffer = kmalloc(buffer_length, GFP_KERNEL); if (!buffer) return; @@ -1244,7 +1246,7 @@ static void ni_usb_stop(struct ni_usb_priv *ni_priv) USB_TYPE_VENDOR | USB_RECIP_DEVICE, 0x0, 0x0, buffer, buffer_length, 1000); if (retval != buffer_length) { - dev_err(&usb_dev->dev, "%s: usb_control_msg returned %i\n", __func__, retval); + dev_err(&usb_dev->dev, "usb_control_msg returned %i\n", retval); kfree(buffer); return; } @@ -1252,15 +1254,18 @@ static void ni_usb_stop(struct ni_usb_priv *ni_priv) kfree(buffer); } -static int ni_usb_primary_address(gpib_board_t *board, unsigned int address) +static int ni_usb_primary_address(struct gpib_board *board, unsigned int address) { int retval; struct ni_usb_priv *ni_priv = board->private_data; - struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface); + struct usb_device *usb_dev; int i = 0; struct ni_usb_register writes[2]; unsigned int ibsta; + if (!ni_priv->bus_interface) + return -ENODEV; + usb_dev = interface_to_usbdev(ni_priv->bus_interface); writes[i].device = NIUSB_SUBDEV_TNT4882; writes[i].address = nec7210_to_tnt4882_offset(ADR); writes[i].value = address; @@ -1271,7 +1276,7 @@ static int ni_usb_primary_address(gpib_board_t *board, unsigned int address) i++; retval = ni_usb_write_registers(ni_priv, writes, i, &ibsta); if (retval < 0) { - dev_err(&usb_dev->dev, "%s: register write failed, retval=%i\n", __func__, retval); + dev_err(&usb_dev->dev, "register write failed, retval=%i\n", retval); return retval; } ni_usb_soft_update_status(board, ibsta, 0); @@ -1307,30 +1312,33 @@ static int ni_usb_write_sad(struct ni_usb_register *writes, int address, int ena return i; } -static int ni_usb_secondary_address(gpib_board_t *board, unsigned int address, int enable) +static int ni_usb_secondary_address(struct gpib_board *board, unsigned int address, int enable) { int retval; struct ni_usb_priv *ni_priv = board->private_data; - struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface); + struct usb_device *usb_dev; int i = 0; struct ni_usb_register writes[3]; unsigned int ibsta; + if (!ni_priv->bus_interface) + return -ENODEV; + usb_dev = interface_to_usbdev(ni_priv->bus_interface); i += ni_usb_write_sad(writes, address, enable); retval = ni_usb_write_registers(ni_priv, writes, i, &ibsta); if (retval < 0) { - dev_err(&usb_dev->dev, "%s: register write failed, retval=%i\n", __func__, retval); + dev_err(&usb_dev->dev, "register write failed, retval=%i\n", retval); return retval; } ni_usb_soft_update_status(board, ibsta, 0); return 0; } -static int ni_usb_parallel_poll(gpib_board_t *board, uint8_t *result) +static int ni_usb_parallel_poll(struct gpib_board *board, uint8_t *result) { int retval; struct ni_usb_priv *ni_priv = board->private_data; - struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface); + struct usb_device *usb_dev; u8 *out_data, *in_data; static const int out_data_length = 0x10; static const int in_data_length = 0x20; @@ -1339,6 +1347,9 @@ static int ni_usb_parallel_poll(gpib_board_t *board, uint8_t *result) int j = 0; struct ni_usb_status_block status; + if (!ni_priv->bus_interface) + return -ENODEV; + usb_dev = interface_to_usbdev(ni_priv->bus_interface); out_data = kmalloc(out_data_length, GFP_KERNEL); if (!out_data) return -ENOMEM; @@ -1353,8 +1364,8 @@ static int ni_usb_parallel_poll(gpib_board_t *board, uint8_t *result) kfree(out_data); if (retval || bytes_written != i) { - dev_err(&usb_dev->dev, "%s: ni_usb_send_bulk_msg returned %i, bytes_written=%i, i=%i\n", - __func__, retval, bytes_written, i); + dev_err(&usb_dev->dev, "send_bulk_msg returned %i, bytes_written=%i, i=%i\n", + retval, bytes_written, i); return retval; } in_data = kmalloc(in_data_length, GFP_KERNEL); @@ -1366,8 +1377,8 @@ static int ni_usb_parallel_poll(gpib_board_t *board, uint8_t *result) &bytes_read, 1000, 1); if (retval && retval != -ERESTARTSYS) { - dev_err(&usb_dev->dev, "%s: ni_usb_receive_bulk_msg returned %i, bytes_read=%i\n", - __func__, retval, bytes_read); + dev_err(&usb_dev->dev, "receive_bulk_msg returned %i, bytes_read=%i\n", + retval, bytes_read); kfree(in_data); return retval; } @@ -1378,37 +1389,43 @@ static int ni_usb_parallel_poll(gpib_board_t *board, uint8_t *result) return retval; } -static void ni_usb_parallel_poll_configure(gpib_board_t *board, uint8_t config) +static void ni_usb_parallel_poll_configure(struct gpib_board *board, uint8_t config) { int retval; struct ni_usb_priv *ni_priv = board->private_data; - struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface); + struct usb_device *usb_dev; int i = 0; struct ni_usb_register writes[1]; unsigned int ibsta; + if (!ni_priv->bus_interface) + return; // -ENODEV; + usb_dev = interface_to_usbdev(ni_priv->bus_interface); writes[i].device = NIUSB_SUBDEV_TNT4882; writes[i].address = nec7210_to_tnt4882_offset(AUXMR); writes[i].value = PPR | config; i++; retval = ni_usb_write_registers(ni_priv, writes, i, &ibsta); if (retval < 0) { - dev_err(&usb_dev->dev, "%s: register write failed, retval=%i\n", __func__, retval); + dev_err(&usb_dev->dev, "register write failed, retval=%i\n", retval); return;// retval; } ni_usb_soft_update_status(board, ibsta, 0); return;// 0; } -static void ni_usb_parallel_poll_response(gpib_board_t *board, int ist) +static void ni_usb_parallel_poll_response(struct gpib_board *board, int ist) { int retval; struct ni_usb_priv *ni_priv = board->private_data; - struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface); + struct usb_device *usb_dev; int i = 0; struct ni_usb_register writes[1]; unsigned int ibsta; + if (!ni_priv->bus_interface) + return; // -ENODEV; + usb_dev = interface_to_usbdev(ni_priv->bus_interface); writes[i].device = NIUSB_SUBDEV_TNT4882; writes[i].address = nec7210_to_tnt4882_offset(AUXMR); if (ist) @@ -1418,76 +1435,85 @@ static void ni_usb_parallel_poll_response(gpib_board_t *board, int ist) i++; retval = ni_usb_write_registers(ni_priv, writes, i, &ibsta); if (retval < 0) { - dev_err(&usb_dev->dev, "%s: register write failed, retval=%i\n", __func__, retval); + dev_err(&usb_dev->dev, "register write failed, retval=%i\n", retval); return;// retval; } ni_usb_soft_update_status(board, ibsta, 0); return;// 0; } -static void ni_usb_serial_poll_response(gpib_board_t *board, u8 status) +static void ni_usb_serial_poll_response(struct gpib_board *board, u8 status) { int retval; struct ni_usb_priv *ni_priv = board->private_data; - struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface); + struct usb_device *usb_dev; int i = 0; struct ni_usb_register writes[1]; unsigned int ibsta; + if (!ni_priv->bus_interface) + return; // -ENODEV; + usb_dev = interface_to_usbdev(ni_priv->bus_interface); writes[i].device = NIUSB_SUBDEV_TNT4882; writes[i].address = nec7210_to_tnt4882_offset(SPMR); writes[i].value = status; i++; retval = ni_usb_write_registers(ni_priv, writes, i, &ibsta); if (retval < 0) { - dev_err(&usb_dev->dev, "%s: register write failed, retval=%i\n", __func__, retval); + dev_err(&usb_dev->dev, "register write failed, retval=%i\n", retval); return;// retval; } ni_usb_soft_update_status(board, ibsta, 0); return;// 0; } -static uint8_t ni_usb_serial_poll_status(gpib_board_t *board) +static uint8_t ni_usb_serial_poll_status(struct gpib_board *board) { return 0; } -static void ni_usb_return_to_local(gpib_board_t *board) +static void ni_usb_return_to_local(struct gpib_board *board) { int retval; struct ni_usb_priv *ni_priv = board->private_data; - struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface); + struct usb_device *usb_dev; int i = 0; struct ni_usb_register writes[1]; unsigned int ibsta; + if (!ni_priv->bus_interface) + return; // -ENODEV; + usb_dev = interface_to_usbdev(ni_priv->bus_interface); writes[i].device = NIUSB_SUBDEV_TNT4882; writes[i].address = nec7210_to_tnt4882_offset(AUXMR); writes[i].value = AUX_RTL; i++; retval = ni_usb_write_registers(ni_priv, writes, i, &ibsta); if (retval < 0) { - dev_err(&usb_dev->dev, "%s: register write failed, retval=%i\n", __func__, retval); + dev_err(&usb_dev->dev, "register write failed, retval=%i\n", retval); return;// retval; } ni_usb_soft_update_status(board, ibsta, 0); return;// 0; } -static int ni_usb_line_status(const gpib_board_t *board) +static int ni_usb_line_status(const struct gpib_board *board) { int retval; struct ni_usb_priv *ni_priv = board->private_data; - struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface); + struct usb_device *usb_dev; u8 *out_data, *in_data; static const int out_data_length = 0x20; static const int in_data_length = 0x20; int bytes_written = 0, bytes_read = 0; int i = 0; unsigned int bsr_bits; - int line_status = ValidALL; + int line_status = VALID_ALL; // NI windows driver reads 0xd(HSSEL), 0xc (ARD0), 0x1f (BSR) + if (!ni_priv->bus_interface) + return -ENODEV; + usb_dev = interface_to_usbdev(ni_priv->bus_interface); out_data = kmalloc(out_data_length, GFP_KERNEL); if (!out_data) return -ENOMEM; @@ -1509,15 +1535,14 @@ static int ni_usb_line_status(const gpib_board_t *board) if (retval || bytes_written != i) { mutex_unlock(&ni_priv->addressed_transfer_lock); if (retval != -EAGAIN) - dev_err(&usb_dev->dev, "%s: ni_usb_send_bulk_msg returned %i, bytes_written=%i, i=%i\n", - __func__, retval, bytes_written, i); + dev_err(&usb_dev->dev, "send_bulk_msg returned %i, bytes_written=%i, i=%i\n", + retval, bytes_written, i); return retval; } in_data = kmalloc(in_data_length, GFP_KERNEL); if (!in_data) { mutex_unlock(&ni_priv->addressed_transfer_lock); - dev_err(&usb_dev->dev, "%s: kmalloc failed\n", __func__); return -ENOMEM; } retval = ni_usb_nonblocking_receive_bulk_msg(ni_priv, in_data, in_data_length, @@ -1527,8 +1552,8 @@ static int ni_usb_line_status(const gpib_board_t *board) if (retval) { if (retval != -EAGAIN) - dev_err(&usb_dev->dev, "%s: ni_usb_receive_bulk_msg returned %i, bytes_read=%i\n", - __func__, retval, bytes_read); + dev_err(&usb_dev->dev, "receive_bulk_msg returned %i, bytes_read=%i\n", + retval, bytes_read); kfree(in_data); return retval; } @@ -1536,21 +1561,21 @@ static int ni_usb_line_status(const gpib_board_t *board) ni_usb_parse_register_read_block(in_data, &bsr_bits, 1); kfree(in_data); if (bsr_bits & BCSR_REN_BIT) - line_status |= BusREN; + line_status |= BUS_REN; if (bsr_bits & BCSR_IFC_BIT) - line_status |= BusIFC; + line_status |= BUS_IFC; if (bsr_bits & BCSR_SRQ_BIT) - line_status |= BusSRQ; + line_status |= BUS_SRQ; if (bsr_bits & BCSR_EOI_BIT) - line_status |= BusEOI; + line_status |= BUS_EOI; if (bsr_bits & BCSR_NRFD_BIT) - line_status |= BusNRFD; + line_status |= BUS_NRFD; if (bsr_bits & BCSR_NDAC_BIT) - line_status |= BusNDAC; + line_status |= BUS_NDAC; if (bsr_bits & BCSR_DAV_BIT) - line_status |= BusDAV; + line_status |= BUS_DAV; if (bsr_bits & BCSR_ATN_BIT) - line_status |= BusATN; + line_status |= BUS_ATN; return line_status; } @@ -1591,28 +1616,31 @@ static int ni_usb_setup_t1_delay(struct ni_usb_register *reg, unsigned int nano_ return i; } -static unsigned int ni_usb_t1_delay(gpib_board_t *board, unsigned int nano_sec) +static int ni_usb_t1_delay(struct gpib_board *board, unsigned int nano_sec) { int retval; struct ni_usb_priv *ni_priv = board->private_data; - struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface); + struct usb_device *usb_dev; struct ni_usb_register writes[3]; unsigned int ibsta; unsigned int actual_ns; int i; + if (!ni_priv->bus_interface) + return -ENODEV; + usb_dev = interface_to_usbdev(ni_priv->bus_interface); i = ni_usb_setup_t1_delay(writes, nano_sec, &actual_ns); retval = ni_usb_write_registers(ni_priv, writes, i, &ibsta); if (retval < 0) { - dev_err(&usb_dev->dev, "%s: register write failed, retval=%i\n", __func__, retval); - return -1; //FIXME should change return type to int for error reporting + dev_err(&usb_dev->dev, "register write failed, retval=%i\n", retval); + return retval; } board->t1_nano_sec = actual_ns; ni_usb_soft_update_status(board, ibsta, 0); return actual_ns; } -static int ni_usb_allocate_private(gpib_board_t *board) +static int ni_usb_allocate_private(struct gpib_board *board) { struct ni_usb_priv *ni_priv; @@ -1635,7 +1663,7 @@ static void ni_usb_free_private(struct ni_usb_priv *ni_priv) } #define NUM_INIT_WRITES 26 -static int ni_usb_setup_init(gpib_board_t *board, struct ni_usb_register *writes) +static int ni_usb_setup_init(struct gpib_board *board, struct ni_usb_register *writes) { struct ni_usb_priv *ni_priv = board->private_data; struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface); @@ -1736,13 +1764,13 @@ static int ni_usb_setup_init(gpib_board_t *board, struct ni_usb_register *writes writes[i].value = AUX_CPPF; i++; if (i > NUM_INIT_WRITES) { - dev_err(&usb_dev->dev, "%s: bug!, buffer overrun, i=%i\n", __func__, i); + dev_err(&usb_dev->dev, "bug!, buffer overrun, i=%i\n", i); return 0; } return i; } -static int ni_usb_init(gpib_board_t *board) +static int ni_usb_init(struct gpib_board *board) { int retval; struct ni_usb_priv *ni_priv = board->private_data; @@ -1762,7 +1790,7 @@ static int ni_usb_init(gpib_board_t *board) return -EFAULT; kfree(writes); if (retval) { - dev_err(&usb_dev->dev, "%s: register write failed, retval=%i\n", __func__, retval); + dev_err(&usb_dev->dev, "register write failed, retval=%i\n", retval); return retval; } ni_usb_soft_update_status(board, ibsta, 0); @@ -1771,16 +1799,13 @@ static int ni_usb_init(gpib_board_t *board) static void ni_usb_interrupt_complete(struct urb *urb) { - gpib_board_t *board = urb->context; + struct gpib_board *board = urb->context; struct ni_usb_priv *ni_priv = board->private_data; struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface); int retval; struct ni_usb_status_block status; unsigned long flags; -// printk("debug: %s: status=0x%x, error_count=%i, actual_length=%i\n", __func__, -// urb->status, urb->error_count, urb->actual_length); - switch (urb->status) { /* success */ case 0: @@ -1793,26 +1818,24 @@ static void ni_usb_interrupt_complete(struct urb *urb) default: /* other error, resubmit */ retval = usb_submit_urb(ni_priv->interrupt_urb, GFP_ATOMIC); if (retval) - dev_err(&usb_dev->dev, "%s: failed to resubmit interrupt urb\n", __func__); + dev_err(&usb_dev->dev, "failed to resubmit interrupt urb\n"); return; } ni_usb_parse_status_block(urb->transfer_buffer, &status); -// printk("debug: ibsta=0x%x\n", status.ibsta); spin_lock_irqsave(&board->spinlock, flags); ni_priv->monitored_ibsta_bits &= ~status.ibsta; -// printk("debug: monitored_ibsta_bits=0x%x\n", ni_priv->monitored_ibsta_bits); spin_unlock_irqrestore(&board->spinlock, flags); wake_up_interruptible(&board->wait); retval = usb_submit_urb(ni_priv->interrupt_urb, GFP_ATOMIC); if (retval) - dev_err(&usb_dev->dev, "%s: failed to resubmit interrupt urb\n", __func__); + dev_err(&usb_dev->dev, "failed to resubmit interrupt urb\n"); } -static int ni_usb_set_interrupt_monitor(gpib_board_t *board, unsigned int monitored_bits) +static int ni_usb_set_interrupt_monitor(struct gpib_board *board, unsigned int monitored_bits) { int retval; struct ni_usb_priv *ni_priv = board->private_data; @@ -1821,22 +1844,20 @@ static int ni_usb_set_interrupt_monitor(gpib_board_t *board, unsigned int monito u8 *buffer; struct ni_usb_status_block status; unsigned long flags; - //printk("%s: receive control pipe is %i\n", __func__, pipe); + buffer = kmalloc(buffer_length, GFP_KERNEL); if (!buffer) return -ENOMEM; spin_lock_irqsave(&board->spinlock, flags); ni_priv->monitored_ibsta_bits = ni_usb_ibsta_monitor_mask & monitored_bits; -// dev_err(&usb_dev->dev, "debug: %s: monitored_ibsta_bits=0x%x\n", -// __func__, ni_priv->monitored_ibsta_bits); spin_unlock_irqrestore(&board->spinlock, flags); retval = ni_usb_receive_control_msg(ni_priv, NI_USB_WAIT_REQUEST, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 0x300, ni_usb_ibsta_monitor_mask & monitored_bits, buffer, buffer_length, 1000); if (retval != buffer_length) { - dev_err(&usb_dev->dev, "%s: usb_control_msg returned %i\n", __func__, retval); + dev_err(&usb_dev->dev, "usb_control_msg returned %i\n", retval); kfree(buffer); return -1; } @@ -1845,7 +1866,7 @@ static int ni_usb_set_interrupt_monitor(gpib_board_t *board, unsigned int monito return 0; } -static int ni_usb_setup_urbs(gpib_board_t *board) +static int ni_usb_setup_urbs(struct gpib_board *board) { struct ni_usb_priv *ni_priv = board->private_data; struct usb_device *usb_dev; @@ -1872,8 +1893,7 @@ static int ni_usb_setup_urbs(gpib_board_t *board) retval = usb_submit_urb(ni_priv->interrupt_urb, GFP_KERNEL); mutex_unlock(&ni_priv->interrupt_transfer_lock); if (retval) { - dev_err(&usb_dev->dev, "%s: failed to submit first interrupt urb, retval=%i\n", - __func__, retval); + dev_err(&usb_dev->dev, "failed to submit first interrupt urb, retval=%i\n", retval); return retval; } return 0; @@ -1904,7 +1924,6 @@ static int ni_usb_b_read_serial_number(struct ni_usb_priv *ni_priv) int j; unsigned int serial_number; -// printk("%s: %s\n", __func__); in_data = kmalloc(in_data_length, GFP_KERNEL); if (!in_data) return -ENOMEM; @@ -1924,20 +1943,19 @@ static int ni_usb_b_read_serial_number(struct ni_usb_priv *ni_priv) i += ni_usb_bulk_termination(&out_data[i]); retval = ni_usb_send_bulk_msg(ni_priv, out_data, out_data_length, &bytes_written, 1000); if (retval) { - dev_err(&usb_dev->dev, "%s: ni_usb_send_bulk_msg returned %i, bytes_written=%i, i=%li\n", - __func__, + dev_err(&usb_dev->dev, "send_bulk_msg returned %i, bytes_written=%i, i=%li\n", retval, bytes_written, (long)out_data_length); goto serial_out; } retval = ni_usb_receive_bulk_msg(ni_priv, in_data, in_data_length, &bytes_read, 1000, 0); if (retval) { - dev_err(&usb_dev->dev, "%s: ni_usb_receive_bulk_msg returned %i, bytes_read=%i\n", - __func__, retval, bytes_read); + dev_err(&usb_dev->dev, "receive_bulk_msg returned %i, bytes_read=%i\n", + retval, bytes_read); ni_usb_dump_raw_block(in_data, bytes_read); goto serial_out; } if (ARRAY_SIZE(results) < num_reads) { - dev_err(&usb_dev->dev, "Setup bug\n"); + dev_err(&usb_dev->dev, "serial number eetup bug\n"); retval = -EINVAL; goto serial_out; } @@ -1945,7 +1963,7 @@ static int ni_usb_b_read_serial_number(struct ni_usb_priv *ni_priv) serial_number = 0; for (j = 0; j < num_reads; ++j) serial_number |= (results[j] & 0xff) << (8 * j); - dev_info(&usb_dev->dev, "%s: board serial number is 0x%x\n", __func__, serial_number); + dev_dbg(&usb_dev->dev, "board serial number is 0x%x\n", serial_number); retval = 0; serial_out: kfree(in_data); @@ -1973,22 +1991,22 @@ static int ni_usb_hs_wait_for_ready(struct ni_usb_priv *ni_priv) USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 0x0, 0x0, buffer, buffer_size, 1000); if (retval < 0) { - dev_err(&usb_dev->dev, "%s: usb_control_msg request 0x%x returned %i\n", - __func__, NI_USB_SERIAL_NUMBER_REQUEST, retval); + dev_err(&usb_dev->dev, "usb_control_msg request 0x%x returned %i\n", + NI_USB_SERIAL_NUMBER_REQUEST, retval); goto ready_out; } j = 0; if (buffer[j] != NI_USB_SERIAL_NUMBER_REQUEST) { - dev_err(&usb_dev->dev, "%s: unexpected data: buffer[%i]=0x%x, expected 0x%x\n", - __func__, j, (int)buffer[j], NI_USB_SERIAL_NUMBER_REQUEST); + dev_err(&usb_dev->dev, "unexpected data: buffer[%i]=0x%x, expected 0x%x\n", + j, (int)buffer[j], NI_USB_SERIAL_NUMBER_REQUEST); unexpected = 1; } if (unexpected) ni_usb_dump_raw_block(buffer, retval); // NI-USB-HS+ pads the serial with 0x0 to make 16 bytes if (retval != 5 && retval != 16) { - dev_err(&usb_dev->dev, "%s: received unexpected number of bytes = %i, expected 5 or 16\n", - __func__, retval); + dev_err(&usb_dev->dev, "received unexpected number of bytes = %i, expected 5 or 16\n", + retval); ni_usb_dump_raw_block(buffer, retval); } serial_number = 0; @@ -1996,7 +2014,7 @@ static int ni_usb_hs_wait_for_ready(struct ni_usb_priv *ni_priv) serial_number |= (buffer[++j] << 8); serial_number |= (buffer[++j] << 16); serial_number |= (buffer[++j] << 24); - dev_info(&usb_dev->dev, "%s: board serial number is 0x%x\n", __func__, serial_number); + dev_dbg(&usb_dev->dev, "board serial number is 0x%x\n", serial_number); for (i = 0; i < timeout; ++i) { int ready = 0; @@ -2004,26 +2022,26 @@ static int ni_usb_hs_wait_for_ready(struct ni_usb_priv *ni_priv) USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 0x0, 0x0, buffer, buffer_size, 100); if (retval < 0) { - dev_err(&usb_dev->dev, "%s: usb_control_msg request 0x%x returned %i\n", - __func__, NI_USB_POLL_READY_REQUEST, retval); + dev_err(&usb_dev->dev, "usb_control_msg request 0x%x returned %i\n", + NI_USB_POLL_READY_REQUEST, retval); goto ready_out; } j = 0; unexpected = 0; if (buffer[j] != NI_USB_POLL_READY_REQUEST) { // [0] - dev_err(&usb_dev->dev, "%s: unexpected data: buffer[%i]=0x%x, expected 0x%x\n", - __func__, j, (int)buffer[j], NI_USB_POLL_READY_REQUEST); + dev_err(&usb_dev->dev, "unexpected data: buffer[%i]=0x%x, expected 0x%x\n", + j, (int)buffer[j], NI_USB_POLL_READY_REQUEST); unexpected = 1; } ++j; if (buffer[j] != 0x1 && buffer[j] != 0x0) { // [1] HS+ sends 0x0 - dev_err(&usb_dev->dev, "%s: unexpected data: buffer[%i]=0x%x, expected 0x1 or 0x0\n", - __func__, j, (int)buffer[j]); + dev_err(&usb_dev->dev, "unexpected data: buffer[%i]=0x%x, expected 0x1 or 0x0\n", + j, (int)buffer[j]); unexpected = 1; } if (buffer[++j] != 0x0) { // [2] - dev_err(&usb_dev->dev, "%s: unexpected data: buffer[%i]=0x%x, expected 0x%x\n", - __func__, j, (int)buffer[j], 0x0); + dev_err(&usb_dev->dev, "unexpected data: buffer[%i]=0x%x, expected 0x%x\n", + j, (int)buffer[j], 0x0); unexpected = 1; } ++j; @@ -2031,22 +2049,22 @@ static int ni_usb_hs_wait_for_ready(struct ni_usb_priv *ni_priv) // NI-USB-HS+ sends 0x0 if (buffer[j] != 0x1 && buffer[j] != 0x8 && buffer[j] != 0x7 && buffer[j] != 0x0) { // [3] - dev_err(&usb_dev->dev, "%s: unexpected data: buffer[%i]=0x%x, expected 0x0, 0x1, 0x7 or 0x8\n", - __func__, j, (int)buffer[j]); + dev_err(&usb_dev->dev, "unexpected data: buffer[%i]=0x%x, expected 0x0, 0x1, 0x7 or 0x8\n", + j, (int)buffer[j]); unexpected = 1; } ++j; // NI-USB-HS+ sends 0 here if (buffer[j] != 0x30 && buffer[j] != 0x0) { // [4] - dev_err(&usb_dev->dev, "%s: unexpected data: buffer[%i]=0x%x, expected 0x0 or 0x30\n", - __func__, j, (int)buffer[j]); + dev_err(&usb_dev->dev, "unexpected data: buffer[%i]=0x%x, expected 0x0 or 0x30\n", + j, (int)buffer[j]); unexpected = 1; } ++j; // MC usb-488 (and sometimes NI-USB-HS?) and NI-USB-HS+ sends 0x0 here if (buffer[j] != 0x1 && buffer[j] != 0x0) { // [5] - dev_err(&usb_dev->dev, "%s: unexpected data: buffer[%i]=0x%x, expected 0x1 or 0x0\n", - __func__, j, (int)buffer[j]); + dev_err(&usb_dev->dev, "unexpected data: buffer[%i]=0x%x, expected 0x1 or 0x0\n", + j, (int)buffer[j]); unexpected = 1; } if (buffer[++j] != 0x0) { // [6] @@ -2054,8 +2072,8 @@ static int ni_usb_hs_wait_for_ready(struct ni_usb_priv *ni_priv) // NI-USB-HS+ sends 0xf here if (buffer[j] != 0x2 && buffer[j] != 0xe && buffer[j] != 0xf && buffer[j] != 0x16) { - dev_err(&usb_dev->dev, "%s: unexpected data: buffer[%i]=0x%x, expected 0x2, 0xe, 0xf or 0x16\n", - __func__, j, (int)buffer[j]); + dev_err(&usb_dev->dev, "unexpected data: buffer[%i]=0x%x, expected 0x2, 0xe, 0xf or 0x16\n", + j, (int)buffer[j]); unexpected = 1; } } @@ -2064,30 +2082,30 @@ static int ni_usb_hs_wait_for_ready(struct ni_usb_priv *ni_priv) // MC usb-488 sends 0x5 here; MC usb-488A sends 0x6 here if (buffer[j] != 0x3 && buffer[j] != 0x5 && buffer[j] != 0x6 && buffer[j] != 0x8) { - dev_err(&usb_dev->dev, "%s: unexpected data: buffer[%i]=0x%x, expected 0x3 or 0x5, 0x6 or 0x08\n", - __func__, j, (int)buffer[j]); + dev_err(&usb_dev->dev, "unexpected data: buffer[%i]=0x%x, expected 0x3 or 0x5, 0x6 or 0x08\n", + j, (int)buffer[j]); unexpected = 1; } } ++j; if (buffer[j] != 0x0 && buffer[j] != 0x2) { // [8] MC usb-488 sends 0x2 here - dev_err(&usb_dev->dev, "%s: unexpected data: buffer[%i]=0x%x, expected 0x0 or 0x2\n", - __func__, j, (int)buffer[j]); + dev_err(&usb_dev->dev, " unexpected data: buffer[%i]=0x%x, expected 0x0 or 0x2\n", + j, (int)buffer[j]); unexpected = 1; } ++j; // MC usb-488A and NI-USB-HS sends 0x3 here; NI-USB-HS+ sends 0x30 here if (buffer[j] != 0x0 && buffer[j] != 0x3 && buffer[j] != 0x30) { // [9] - dev_err(&usb_dev->dev, "%s: unexpected data: buffer[%i]=0x%x, expected 0x0, 0x3 or 0x30\n", - __func__, j, (int)buffer[j]); + dev_err(&usb_dev->dev, "unexpected data: buffer[%i]=0x%x, expected 0x0, 0x3 or 0x30\n", + j, (int)buffer[j]); unexpected = 1; } if (buffer[++j] != 0x0) { ready = 1; if (buffer[j] != 0x96 && buffer[j] != 0x7 && buffer[j] != 0x6e) { // [10] MC usb-488 sends 0x7 here - dev_err(&usb_dev->dev, "%s: unexpected data: buffer[%i]=0x%x, expected 0x96, 0x07 or 0x6e\n", - __func__, j, (int)buffer[j]); + dev_err(&usb_dev->dev, "unexpected data: buffer[%i]=0x%x, expected 0x96, 0x07 or 0x6e\n", + j, (int)buffer[j]); unexpected = 1; } } @@ -2097,7 +2115,6 @@ static int ni_usb_hs_wait_for_ready(struct ni_usb_priv *ni_priv) break; retval = msleep_interruptible(msec_sleep_duration); if (retval) { - dev_err(&usb_dev->dev, "ni_usb_gpib: msleep interrupted\n"); retval = -ERESTARTSYS; goto ready_out; } @@ -2106,7 +2123,7 @@ static int ni_usb_hs_wait_for_ready(struct ni_usb_priv *ni_priv) ready_out: kfree(buffer); - dev_dbg(&usb_dev->dev, "%s: exit retval=%d\n", __func__, retval); + dev_dbg(&usb_dev->dev, "exit retval=%d\n", retval); return retval; } @@ -2134,14 +2151,14 @@ static int ni_usb_hs_plus_extra_init(struct ni_usb_priv *ni_priv) USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 0x0, 0x0, buffer, transfer_size, 1000); if (retval < 0) { - dev_err(&usb_dev->dev, "%s: usb_control_msg request 0x%x returned %i\n", - __func__, NI_USB_HS_PLUS_0x48_REQUEST, retval); + dev_err(&usb_dev->dev, "usb_control_msg request 0x%x returned %i\n", + NI_USB_HS_PLUS_0x48_REQUEST, retval); break; } // expected response data: 48 f3 30 00 00 00 00 00 00 00 00 00 00 00 00 00 if (buffer[0] != NI_USB_HS_PLUS_0x48_REQUEST) - dev_err(&usb_dev->dev, "%s: unexpected data: buffer[0]=0x%x, expected 0x%x\n", - __func__, (int)buffer[0], NI_USB_HS_PLUS_0x48_REQUEST); + dev_err(&usb_dev->dev, "unexpected data: buffer[0]=0x%x, expected 0x%x\n", + (int)buffer[0], NI_USB_HS_PLUS_0x48_REQUEST); transfer_size = 2; @@ -2149,14 +2166,14 @@ static int ni_usb_hs_plus_extra_init(struct ni_usb_priv *ni_priv) USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 0x1, 0x0, buffer, transfer_size, 1000); if (retval < 0) { - dev_err(&usb_dev->dev, "%s: usb_control_msg request 0x%x returned %i\n", - __func__, NI_USB_HS_PLUS_LED_REQUEST, retval); + dev_err(&usb_dev->dev, "usb_control_msg request 0x%x returned %i\n", + NI_USB_HS_PLUS_LED_REQUEST, retval); break; } // expected response data: 4b 00 if (buffer[0] != NI_USB_HS_PLUS_LED_REQUEST) - dev_err(&usb_dev->dev, "%s: unexpected data: buffer[0]=0x%x, expected 0x%x\n", - __func__, (int)buffer[0], NI_USB_HS_PLUS_LED_REQUEST); + dev_err(&usb_dev->dev, "unexpected data: buffer[0]=0x%x, expected 0x%x\n", + (int)buffer[0], NI_USB_HS_PLUS_LED_REQUEST); transfer_size = 9; @@ -2165,15 +2182,14 @@ static int ni_usb_hs_plus_extra_init(struct ni_usb_priv *ni_priv) USB_RECIP_INTERFACE, 0x0, 0x1, buffer, transfer_size, 1000); if (retval < 0) { - dev_err(&usb_dev->dev, "%s: usb_control_msg request 0x%x returned %i\n", - __func__, NI_USB_HS_PLUS_0xf8_REQUEST, retval); + dev_err(&usb_dev->dev, "usb_control_msg request 0x%x returned %i\n", + NI_USB_HS_PLUS_0xf8_REQUEST, retval); break; } // expected response data: f8 01 00 00 00 01 00 00 00 if (buffer[0] != NI_USB_HS_PLUS_0xf8_REQUEST) - dev_err(&usb_dev->dev, "%s: unexpected data: buffer[0]=0x%x, expected 0x%x\n", - __func__, (int)buffer[0], NI_USB_HS_PLUS_0xf8_REQUEST); - + dev_err(&usb_dev->dev, "unexpected data: buffer[0]=0x%x, expected 0x%x\n", + (int)buffer[0], NI_USB_HS_PLUS_0xf8_REQUEST); } while (0); // cleanup @@ -2189,10 +2205,10 @@ static inline int ni_usb_device_match(struct usb_interface *interface, return 1; } -static int ni_usb_attach(gpib_board_t *board, const gpib_board_config_t *config) +static int ni_usb_attach(struct gpib_board *board, const gpib_board_config_t *config) { int retval; - int i; + int i, index; struct ni_usb_priv *ni_priv; int product_id; struct usb_device *usb_dev; @@ -2211,19 +2227,17 @@ static int ni_usb_attach(gpib_board_t *board, const gpib_board_config_t *config) ni_priv->bus_interface = ni_usb_driver_interfaces[i]; usb_set_intfdata(ni_usb_driver_interfaces[i], board); usb_dev = interface_to_usbdev(ni_priv->bus_interface); - dev_info(&usb_dev->dev, - "bus %d dev num %d attached to gpib minor %d, NI usb interface %i\n", - usb_dev->bus->busnum, usb_dev->devnum, board->minor, i); + index = i; break; } } if (i == MAX_NUM_NI_USB_INTERFACES) { mutex_unlock(&ni_usb_hotplug_lock); - pr_err("No supported NI usb gpib adapters found, have you loaded its firmware?\n"); + dev_err(board->gpib_dev, "No supported adapters found, have you loaded its firmware?\n"); return -ENODEV; } if (usb_reset_configuration(interface_to_usbdev(ni_priv->bus_interface))) - dev_err(&usb_dev->dev, "ni_usb_gpib: usb_reset_configuration() failed.\n"); + dev_err(&usb_dev->dev, "usb_reset_configuration() failed.\n"); product_id = le16_to_cpu(usb_dev->descriptor.idProduct); ni_priv->product_id = product_id; @@ -2296,7 +2310,9 @@ static int ni_usb_attach(gpib_board_t *board, const gpib_board_config_t *config) } mutex_unlock(&ni_usb_hotplug_lock); - dev_info(&usb_dev->dev, "%s: attached\n", __func__); + dev_info(&usb_dev->dev, + "bus %d dev num %d attached to gpib%d, intf %i\n", + usb_dev->bus->busnum, usb_dev->devnum, board->minor, index); return retval; } @@ -2304,33 +2320,25 @@ static int ni_usb_shutdown_hardware(struct ni_usb_priv *ni_priv) { struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface); int retval; - int i = 0; struct ni_usb_register writes[2]; static const int writes_length = ARRAY_SIZE(writes); unsigned int ibsta; -// printk("%s: %s\n", __func__); - writes[i].device = NIUSB_SUBDEV_TNT4882; - writes[i].address = nec7210_to_tnt4882_offset(AUXMR); - writes[i].value = AUX_CR; - i++; - writes[i].device = NIUSB_SUBDEV_UNKNOWN3; - writes[i].address = 0x10; - writes[i].value = 0x0; - i++; - if (i > writes_length) { - dev_err(&usb_dev->dev, "%s: bug!, buffer overrun, i=%i\n", __func__, i); - return -EINVAL; - } - retval = ni_usb_write_registers(ni_priv, writes, i, &ibsta); + writes[0].device = NIUSB_SUBDEV_TNT4882; + writes[0].address = nec7210_to_tnt4882_offset(AUXMR); + writes[0].value = AUX_CR; + writes[1].device = NIUSB_SUBDEV_UNKNOWN3; + writes[1].address = 0x10; + writes[1].value = 0x0; + retval = ni_usb_write_registers(ni_priv, writes, writes_length, &ibsta); if (retval) { - dev_err(&usb_dev->dev, "%s: register write failed, retval=%i\n", __func__, retval); + dev_err(&usb_dev->dev, "register write failed, retval=%i\n", retval); return retval; } return 0; } -static void ni_usb_detach(gpib_board_t *board) +static void ni_usb_detach(struct gpib_board *board) { struct ni_usb_priv *ni_priv; @@ -2413,7 +2421,7 @@ static int ni_usb_driver_probe(struct usb_interface *interface, const struct usb if (i == MAX_NUM_NI_USB_INTERFACES) { usb_put_dev(usb_dev); mutex_unlock(&ni_usb_hotplug_lock); - dev_err(&usb_dev->dev, "%s: ni_usb_driver_interfaces[] full\n", __func__); + dev_err(&usb_dev->dev, "ni_usb_driver_interfaces[] full\n"); return -1; } path = kmalloc(path_length, GFP_KERNEL); @@ -2423,7 +2431,7 @@ static int ni_usb_driver_probe(struct usb_interface *interface, const struct usb return -ENOMEM; } usb_make_path(usb_dev, path, path_length); - dev_info(&usb_dev->dev, "ni_usb_gpib: probe succeeded for path: %s\n", path); + dev_info(&usb_dev->dev, "probe succeeded for path: %s\n", path); kfree(path); mutex_unlock(&ni_usb_hotplug_lock); return 0; @@ -2437,7 +2445,7 @@ static void ni_usb_driver_disconnect(struct usb_interface *interface) mutex_lock(&ni_usb_hotplug_lock); for (i = 0; i < MAX_NUM_NI_USB_INTERFACES; i++) { if (ni_usb_driver_interfaces[i] == interface) { - gpib_board_t *board = usb_get_intfdata(interface); + struct gpib_board *board = usb_get_intfdata(interface); if (board) { struct ni_usb_priv *ni_priv = board->private_data; @@ -2458,8 +2466,7 @@ static void ni_usb_driver_disconnect(struct usb_interface *interface) } } if (i == MAX_NUM_NI_USB_INTERFACES) - dev_err(&usb_dev->dev, "%s: unable to find interface in ni_usb_driver_interfaces[]? bug?\n", - __func__); + dev_err(&usb_dev->dev, "unable to find interface bug?\n"); usb_put_dev(usb_dev); mutex_unlock(&ni_usb_hotplug_lock); } @@ -2467,7 +2474,7 @@ static void ni_usb_driver_disconnect(struct usb_interface *interface) static int ni_usb_driver_suspend(struct usb_interface *interface, pm_message_t message) { struct usb_device *usb_dev = interface_to_usbdev(interface); - gpib_board_t *board; + struct gpib_board *board; int i, retval; mutex_lock(&ni_usb_hotplug_lock); @@ -2498,9 +2505,9 @@ static int ni_usb_driver_suspend(struct usb_interface *interface, pm_message_t m ni_usb_cleanup_urbs(ni_priv); mutex_unlock(&ni_priv->interrupt_transfer_lock); } - dev_info(&usb_dev->dev, - "bus %d dev num %d gpib minor %d, ni usb interface %i suspended\n", - usb_dev->bus->busnum, usb_dev->devnum, board->minor, i); + dev_dbg(&usb_dev->dev, + "bus %d dev num %d gpib%d, interface %i suspended\n", + usb_dev->bus->busnum, usb_dev->devnum, board->minor, i); } mutex_unlock(&ni_usb_hotplug_lock); @@ -2511,7 +2518,7 @@ static int ni_usb_driver_resume(struct usb_interface *interface) { struct usb_device *usb_dev = interface_to_usbdev(interface); - gpib_board_t *board; + struct gpib_board *board; int i, retval; mutex_lock(&ni_usb_hotplug_lock); @@ -2535,15 +2542,15 @@ static int ni_usb_driver_resume(struct usb_interface *interface) mutex_lock(&ni_priv->interrupt_transfer_lock); retval = usb_submit_urb(ni_priv->interrupt_urb, GFP_KERNEL); if (retval) { - dev_err(&usb_dev->dev, "%s: failed to resubmit interrupt urb, retval=%i\n", - __func__, retval); + dev_err(&usb_dev->dev, "resume failed to resubmit interrupt urb, retval=%i\n", + retval); mutex_unlock(&ni_priv->interrupt_transfer_lock); mutex_unlock(&ni_usb_hotplug_lock); return retval; } mutex_unlock(&ni_priv->interrupt_transfer_lock); } else { - dev_err(&usb_dev->dev, "%s: bug! int urb not set up\n", __func__); + dev_err(&usb_dev->dev, "bug! resume int urb not set up\n"); mutex_unlock(&ni_usb_hotplug_lock); return -EINVAL; } @@ -2600,9 +2607,9 @@ static int ni_usb_driver_resume(struct usb_interface *interface) if (ni_priv->ren_state) ni_usb_remote_enable(board, 1); - dev_info(&usb_dev->dev, - "bus %d dev num %d gpib minor %d, ni usb interface %i resumed\n", - usb_dev->bus->busnum, usb_dev->devnum, board->minor, i); + dev_dbg(&usb_dev->dev, + "bus %d dev num %d gpib%d, interface %i resumed\n", + usb_dev->bus->busnum, usb_dev->devnum, board->minor, i); } mutex_unlock(&ni_usb_hotplug_lock); @@ -2610,7 +2617,7 @@ static int ni_usb_driver_resume(struct usb_interface *interface) } static struct usb_driver ni_usb_bus_driver = { - .name = "ni_usb_gpib", + .name = DRV_NAME, .probe = ni_usb_driver_probe, .disconnect = ni_usb_driver_disconnect, .suspend = ni_usb_driver_suspend, @@ -2623,19 +2630,18 @@ static int __init ni_usb_init_module(void) int i; int ret; - pr_info("ni_usb_gpib driver loading\n"); for (i = 0; i < MAX_NUM_NI_USB_INTERFACES; i++) ni_usb_driver_interfaces[i] = NULL; ret = usb_register(&ni_usb_bus_driver); if (ret) { - pr_err("ni_usb_gpib: usb_register failed: error = %d\n", ret); + pr_err("usb_register failed: error = %d\n", ret); return ret; } ret = gpib_register_driver(&ni_usb_gpib_interface, THIS_MODULE); if (ret) { - pr_err("ni_usb_gpib: gpib_register_driver failed: error = %d\n", ret); + pr_err("gpib_register_driver failed: error = %d\n", ret); return ret; } @@ -2644,7 +2650,6 @@ static int __init ni_usb_init_module(void) static void __exit ni_usb_exit_module(void) { - pr_info("ni_usb_gpib driver unloading\n"); gpib_unregister_driver(&ni_usb_gpib_interface); usb_deregister(&ni_usb_bus_driver); }
diff --git a/drivers/staging/gpib/pc2/pc2_gpib.c b/drivers/staging/gpib/pc2/pc2_gpib.c index c0b07cb..96d3c09 100644 --- a/drivers/staging/gpib/pc2/pc2_gpib.c +++ b/drivers/staging/gpib/pc2/pc2_gpib.c
@@ -4,6 +4,9 @@ * copyright : (C) 2001, 2002 by Frank Mori Hess ***************************************************************************/ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#define dev_fmt pr_fmt + #include <linux/ioport.h> #include <linux/sched.h> #include <linux/module.h> @@ -49,22 +52,13 @@ static inline unsigned int CLEAR_INTR_REG(unsigned int irq) MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("GPIB driver for PC2/PC2a and compatible devices"); -static int pc2_attach(gpib_board_t *board, const gpib_board_config_t *config); -static int pc2a_attach(gpib_board_t *board, const gpib_board_config_t *config); -static int pc2a_cb7210_attach(gpib_board_t *board, const gpib_board_config_t *config); -static int pc2_2a_attach(gpib_board_t *board, const gpib_board_config_t *config); - -static void pc2_detach(gpib_board_t *board); -static void pc2a_detach(gpib_board_t *board); -static void pc2_2a_detach(gpib_board_t *board); - /* * GPIB interrupt service routines */ irqreturn_t pc2_interrupt(int irq, void *arg) { - gpib_board_t *board = arg; + struct gpib_board *board = arg; struct pc2_priv *priv = board->private_data; unsigned long flags; irqreturn_t retval; @@ -77,7 +71,7 @@ irqreturn_t pc2_interrupt(int irq, void *arg) irqreturn_t pc2a_interrupt(int irq, void *arg) { - gpib_board_t *board = arg; + struct gpib_board *board = arg; struct pc2_priv *priv = board->private_data; int status1, status2; unsigned long flags; @@ -96,7 +90,7 @@ irqreturn_t pc2a_interrupt(int irq, void *arg) } // wrappers for interface functions -static int pc2_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *end, +static int pc2_read(struct gpib_board *board, uint8_t *buffer, size_t length, int *end, size_t *bytes_read) { struct pc2_priv *priv = board->private_data; @@ -104,7 +98,7 @@ static int pc2_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *en return nec7210_read(board, &priv->nec7210_priv, buffer, length, end, bytes_read); } -static int pc2_write(gpib_board_t *board, uint8_t *buffer, size_t length, int send_eoi, +static int pc2_write(struct gpib_board *board, uint8_t *buffer, size_t length, int send_eoi, size_t *bytes_written) { struct pc2_priv *priv = board->private_data; @@ -112,132 +106,417 @@ static int pc2_write(gpib_board_t *board, uint8_t *buffer, size_t length, int se return nec7210_write(board, &priv->nec7210_priv, buffer, length, send_eoi, bytes_written); } -static int pc2_command(gpib_board_t *board, uint8_t *buffer, size_t length, size_t *bytes_written) +static int pc2_command(struct gpib_board *board, uint8_t *buffer, size_t length, size_t *bytes_written) { struct pc2_priv *priv = board->private_data; return nec7210_command(board, &priv->nec7210_priv, buffer, length, bytes_written); } -static int pc2_take_control(gpib_board_t *board, int synchronous) +static int pc2_take_control(struct gpib_board *board, int synchronous) { struct pc2_priv *priv = board->private_data; return nec7210_take_control(board, &priv->nec7210_priv, synchronous); } -static int pc2_go_to_standby(gpib_board_t *board) +static int pc2_go_to_standby(struct gpib_board *board) { struct pc2_priv *priv = board->private_data; return nec7210_go_to_standby(board, &priv->nec7210_priv); } -static void pc2_request_system_control(gpib_board_t *board, int request_control) +static void pc2_request_system_control(struct gpib_board *board, int request_control) { struct pc2_priv *priv = board->private_data; nec7210_request_system_control(board, &priv->nec7210_priv, request_control); } -static void pc2_interface_clear(gpib_board_t *board, int assert) +static void pc2_interface_clear(struct gpib_board *board, int assert) { struct pc2_priv *priv = board->private_data; nec7210_interface_clear(board, &priv->nec7210_priv, assert); } -static void pc2_remote_enable(gpib_board_t *board, int enable) +static void pc2_remote_enable(struct gpib_board *board, int enable) { struct pc2_priv *priv = board->private_data; nec7210_remote_enable(board, &priv->nec7210_priv, enable); } -static int pc2_enable_eos(gpib_board_t *board, uint8_t eos_byte, int compare_8_bits) +static int pc2_enable_eos(struct gpib_board *board, uint8_t eos_byte, int compare_8_bits) { struct pc2_priv *priv = board->private_data; return nec7210_enable_eos(board, &priv->nec7210_priv, eos_byte, compare_8_bits); } -static void pc2_disable_eos(gpib_board_t *board) +static void pc2_disable_eos(struct gpib_board *board) { struct pc2_priv *priv = board->private_data; nec7210_disable_eos(board, &priv->nec7210_priv); } -static unsigned int pc2_update_status(gpib_board_t *board, unsigned int clear_mask) +static unsigned int pc2_update_status(struct gpib_board *board, unsigned int clear_mask) { struct pc2_priv *priv = board->private_data; return nec7210_update_status(board, &priv->nec7210_priv, clear_mask); } -static int pc2_primary_address(gpib_board_t *board, unsigned int address) +static int pc2_primary_address(struct gpib_board *board, unsigned int address) { struct pc2_priv *priv = board->private_data; return nec7210_primary_address(board, &priv->nec7210_priv, address); } -static int pc2_secondary_address(gpib_board_t *board, unsigned int address, int enable) +static int pc2_secondary_address(struct gpib_board *board, unsigned int address, int enable) { struct pc2_priv *priv = board->private_data; return nec7210_secondary_address(board, &priv->nec7210_priv, address, enable); } -static int pc2_parallel_poll(gpib_board_t *board, uint8_t *result) +static int pc2_parallel_poll(struct gpib_board *board, uint8_t *result) { struct pc2_priv *priv = board->private_data; return nec7210_parallel_poll(board, &priv->nec7210_priv, result); } -static void pc2_parallel_poll_configure(gpib_board_t *board, uint8_t config) +static void pc2_parallel_poll_configure(struct gpib_board *board, uint8_t config) { struct pc2_priv *priv = board->private_data; nec7210_parallel_poll_configure(board, &priv->nec7210_priv, config); } -static void pc2_parallel_poll_response(gpib_board_t *board, int ist) +static void pc2_parallel_poll_response(struct gpib_board *board, int ist) { struct pc2_priv *priv = board->private_data; nec7210_parallel_poll_response(board, &priv->nec7210_priv, ist); } -static void pc2_serial_poll_response(gpib_board_t *board, uint8_t status) +static void pc2_serial_poll_response(struct gpib_board *board, uint8_t status) { struct pc2_priv *priv = board->private_data; nec7210_serial_poll_response(board, &priv->nec7210_priv, status); } -static uint8_t pc2_serial_poll_status(gpib_board_t *board) +static uint8_t pc2_serial_poll_status(struct gpib_board *board) { struct pc2_priv *priv = board->private_data; return nec7210_serial_poll_status(board, &priv->nec7210_priv); } -static unsigned int pc2_t1_delay(gpib_board_t *board, unsigned int nano_sec) +static int pc2_t1_delay(struct gpib_board *board, unsigned int nano_sec) { struct pc2_priv *priv = board->private_data; return nec7210_t1_delay(board, &priv->nec7210_priv, nano_sec); } -static void pc2_return_to_local(gpib_board_t *board) +static void pc2_return_to_local(struct gpib_board *board) { struct pc2_priv *priv = board->private_data; nec7210_return_to_local(board, &priv->nec7210_priv); } +static int allocate_private(struct gpib_board *board) +{ + struct pc2_priv *priv; + + board->private_data = kmalloc(sizeof(struct pc2_priv), GFP_KERNEL); + if (!board->private_data) + return -1; + priv = board->private_data; + memset(priv, 0, sizeof(struct pc2_priv)); + init_nec7210_private(&priv->nec7210_priv); + return 0; +} + +static void free_private(struct gpib_board *board) +{ + kfree(board->private_data); + board->private_data = NULL; +} + +static int pc2_generic_attach(struct gpib_board *board, const gpib_board_config_t *config, + enum nec7210_chipset chipset) +{ + struct pc2_priv *pc2_priv; + struct nec7210_priv *nec_priv; + + board->status = 0; + if (allocate_private(board)) + return -ENOMEM; + pc2_priv = board->private_data; + nec_priv = &pc2_priv->nec7210_priv; + nec_priv->read_byte = nec7210_ioport_read_byte; + nec_priv->write_byte = nec7210_ioport_write_byte; + nec_priv->type = chipset; + +#ifndef PC2_DMA + /* board->dev hasn't been initialized, so forget about DMA until this driver + * is adapted to use isa_register_driver. + */ + if (config->ibdma) + // driver needs to be adapted to use isa_register_driver to get a struct device* + dev_err(board->gpib_dev, "DMA disabled for pc2 gpib"); +#else + if (config->ibdma) { + nec_priv->dma_buffer_length = 0x1000; + nec_priv->dma_buffer = dma_alloc_coherent(board->dev, + nec_priv->dma_buffer_length, & + nec_priv->dma_buffer_addr, GFP_ATOMIC); + if (!nec_priv->dma_buffer) + return -ENOMEM; + + // request isa dma channel + if (request_dma(config->ibdma, "pc2")) { + dev_err(board->gpib_dev, "can't request DMA %d\n", config->ibdma); + return -1; + } + nec_priv->dma_channel = config->ibdma; + } +#endif + + return 0; +} + +static int pc2_attach(struct gpib_board *board, const gpib_board_config_t *config) +{ + int isr_flags = 0; + struct pc2_priv *pc2_priv; + struct nec7210_priv *nec_priv; + int retval; + + retval = pc2_generic_attach(board, config, NEC7210); + if (retval) + return retval; + + pc2_priv = board->private_data; + nec_priv = &pc2_priv->nec7210_priv; + nec_priv->offset = pc2_reg_offset; + + if (!request_region(config->ibbase, pc2_iosize, "pc2")) { + dev_err(board->gpib_dev, "ioports are already in use\n"); + return -EBUSY; + } + nec_priv->iobase = config->ibbase; + + nec7210_board_reset(nec_priv, board); + + // install interrupt handler + if (config->ibirq) { + if (request_irq(config->ibirq, pc2_interrupt, isr_flags, "pc2", board)) { + dev_err(board->gpib_dev, "can't request IRQ %d\n", config->ibirq); + return -EBUSY; + } + } + pc2_priv->irq = config->ibirq; + /* poll so we can detect assertion of ATN */ + if (gpib_request_pseudo_irq(board, pc2_interrupt)) { + dev_err(board->gpib_dev, "failed to allocate pseudo_irq\n"); + return -1; + } + /* set internal counter register for 8 MHz input clock */ + write_byte(nec_priv, ICR | 8, AUXMR); + + nec7210_board_online(nec_priv, board); + + return 0; +} + +static void pc2_detach(struct gpib_board *board) +{ + struct pc2_priv *pc2_priv = board->private_data; + struct nec7210_priv *nec_priv; + + if (pc2_priv) { + nec_priv = &pc2_priv->nec7210_priv; +#ifdef PC2_DMA + if (nec_priv->dma_channel) + free_dma(nec_priv->dma_channel); +#endif + gpib_free_pseudo_irq(board); + if (pc2_priv->irq) + free_irq(pc2_priv->irq, board); + if (nec_priv->iobase) { + nec7210_board_reset(nec_priv, board); + release_region(nec_priv->iobase, pc2_iosize); + } + if (nec_priv->dma_buffer) { + dma_free_coherent(board->dev, nec_priv->dma_buffer_length, + nec_priv->dma_buffer, nec_priv->dma_buffer_addr); + nec_priv->dma_buffer = NULL; + } + } + free_private(board); +} + +static int pc2a_common_attach(struct gpib_board *board, const gpib_board_config_t *config, + unsigned int num_registers, enum nec7210_chipset chipset) +{ + unsigned int i, j; + struct pc2_priv *pc2_priv; + struct nec7210_priv *nec_priv; + int retval; + + retval = pc2_generic_attach(board, config, chipset); + if (retval) + return retval; + + pc2_priv = board->private_data; + nec_priv = &pc2_priv->nec7210_priv; + nec_priv->offset = pc2a_reg_offset; + + switch (config->ibbase) { + case 0x02e1: + case 0x22e1: + case 0x42e1: + case 0x62e1: + break; + default: + dev_err(board->gpib_dev, "PCIIa base range invalid, must be one of 0x[0246]2e1, but is 0x%x\n", + config->ibbase); + return -1; + } + + if (config->ibirq) { + if (config->ibirq < 2 || config->ibirq > 7) { + dev_err(board->gpib_dev, "illegal interrupt level %i\n", + config->ibirq); + return -1; + } + } else { + dev_err(board->gpib_dev, "interrupt disabled, using polling mode (slow)\n"); + } +#ifdef CHECK_IOPORTS + unsigned int err = 0; + + for (i = 0; i < num_registers; i++) { + if (check_region(config->ibbase + i * pc2a_reg_offset, 1)) + err++; + } + if (config->ibirq && check_region(pc2a_clear_intr_iobase + config->ibirq, 1)) + err++; + if (err) { + dev_err(board->gpib_dev, "ioports are already in use"); + return -EBUSY; + } +#endif + for (i = 0; i < num_registers; i++) { + if (!request_region(config->ibbase + + i * pc2a_reg_offset, 1, "pc2a")) { + dev_err(board->gpib_dev, "ioports are already in use"); + for (j = 0; j < i; j++) + release_region(config->ibbase + + j * pc2a_reg_offset, 1); + return -EBUSY; + } + } + nec_priv->iobase = config->ibbase; + if (config->ibirq) { + if (!request_region(pc2a_clear_intr_iobase + config->ibirq, 1, "pc2a")) { + dev_err(board->gpib_dev, "ioports are already in use"); + return -1; + } + pc2_priv->clear_intr_addr = pc2a_clear_intr_iobase + config->ibirq; + if (request_irq(config->ibirq, pc2a_interrupt, 0, "pc2a", board)) { + dev_err(board->gpib_dev, "can't request IRQ %d\n", config->ibirq); + return -EBUSY; + } + } + pc2_priv->irq = config->ibirq; + /* poll so we can detect assertion of ATN */ + if (gpib_request_pseudo_irq(board, pc2_interrupt)) { + dev_err(board->gpib_dev, "failed to allocate pseudo_irq\n"); + return -1; + } + + // make sure interrupt is clear + if (pc2_priv->irq) + outb(0xff, CLEAR_INTR_REG(pc2_priv->irq)); + + nec7210_board_reset(nec_priv, board); + + /* set internal counter register for 8 MHz input clock */ + write_byte(nec_priv, ICR | 8, AUXMR); + + nec7210_board_online(nec_priv, board); + + return 0; +} + +static int pc2a_attach(struct gpib_board *board, const gpib_board_config_t *config) +{ + return pc2a_common_attach(board, config, pc2a_iosize, NEC7210); +} + +static int pc2a_cb7210_attach(struct gpib_board *board, const gpib_board_config_t *config) +{ + return pc2a_common_attach(board, config, pc2a_iosize, CB7210); +} + +static int pc2_2a_attach(struct gpib_board *board, const gpib_board_config_t *config) +{ + return pc2a_common_attach(board, config, pc2_2a_iosize, NAT4882); +} + +static void pc2a_common_detach(struct gpib_board *board, unsigned int num_registers) +{ + int i; + struct pc2_priv *pc2_priv = board->private_data; + struct nec7210_priv *nec_priv; + + if (pc2_priv) { + nec_priv = &pc2_priv->nec7210_priv; +#ifdef PC2_DMA + if (nec_priv->dma_channel) + free_dma(nec_priv->dma_channel); +#endif + gpib_free_pseudo_irq(board); + if (pc2_priv->irq) + free_irq(pc2_priv->irq, board); + if (nec_priv->iobase) { + nec7210_board_reset(nec_priv, board); + for (i = 0; i < num_registers; i++) + release_region(nec_priv->iobase + + i * pc2a_reg_offset, 1); + } + if (pc2_priv->clear_intr_addr) + release_region(pc2_priv->clear_intr_addr, 1); + if (nec_priv->dma_buffer) { + dma_free_coherent(board->dev, nec_priv->dma_buffer_length, + nec_priv->dma_buffer, + nec_priv->dma_buffer_addr); + nec_priv->dma_buffer = NULL; + } + } + free_private(board); +} + +static void pc2a_detach(struct gpib_board *board) +{ + pc2a_common_detach(board, pc2a_iosize); +} + +static void pc2_2a_detach(struct gpib_board *board) +{ + pc2a_common_detach(board, pc2_2a_iosize); +} + static gpib_interface_t pc2_interface = { .name = "pcII", .attach = pc2_attach, @@ -350,314 +629,31 @@ static gpib_interface_t pc2_2a_interface = { .return_to_local = pc2_return_to_local, }; -static int allocate_private(gpib_board_t *board) -{ - struct pc2_priv *priv; - - board->private_data = kmalloc(sizeof(struct pc2_priv), GFP_KERNEL); - if (!board->private_data) - return -1; - priv = board->private_data; - memset(priv, 0, sizeof(struct pc2_priv)); - init_nec7210_private(&priv->nec7210_priv); - return 0; -} - -static void free_private(gpib_board_t *board) -{ - kfree(board->private_data); - board->private_data = NULL; -} - -static int pc2_generic_attach(gpib_board_t *board, const gpib_board_config_t *config, - enum nec7210_chipset chipset) -{ - struct pc2_priv *pc2_priv; - struct nec7210_priv *nec_priv; - - board->status = 0; - if (allocate_private(board)) - return -ENOMEM; - pc2_priv = board->private_data; - nec_priv = &pc2_priv->nec7210_priv; - nec_priv->read_byte = nec7210_ioport_read_byte; - nec_priv->write_byte = nec7210_ioport_write_byte; - nec_priv->type = chipset; - -#ifndef PC2_DMA - /* board->dev hasn't been initialized, so forget about DMA until this driver - * is adapted to use isa_register_driver. - */ - if (config->ibdma) - pr_err("DMA disabled for pc2 gpib, driver needs to be adapted to use isa_register_driver to get a struct device*"); -#else - if (config->ibdma) { - nec_priv->dma_buffer_length = 0x1000; - nec_priv->dma_buffer = dma_alloc_coherent(board->dev, - nec_priv->dma_buffer_length, & - nec_priv->dma_buffer_addr, GFP_ATOMIC); - if (!nec_priv->dma_buffer) - return -ENOMEM; - - // request isa dma channel - if (request_dma(config->ibdma, "pc2")) { - pr_err("gpib: can't request DMA %d\n", config->ibdma); - return -1; - } - nec_priv->dma_channel = config->ibdma; - } -#endif - - return 0; -} - -int pc2_attach(gpib_board_t *board, const gpib_board_config_t *config) -{ - int isr_flags = 0; - struct pc2_priv *pc2_priv; - struct nec7210_priv *nec_priv; - int retval; - - retval = pc2_generic_attach(board, config, NEC7210); - if (retval) - return retval; - - pc2_priv = board->private_data; - nec_priv = &pc2_priv->nec7210_priv; - nec_priv->offset = pc2_reg_offset; - - if (!request_region(config->ibbase, pc2_iosize, "pc2")) { - pr_err("gpib: ioports are already in use\n"); - return -1; - } - nec_priv->iobase = config->ibbase; - - nec7210_board_reset(nec_priv, board); - - // install interrupt handler - if (config->ibirq) { - if (request_irq(config->ibirq, pc2_interrupt, isr_flags, "pc2", board)) { - pr_err("gpib: can't request IRQ %d\n", config->ibirq); - return -1; - } - } - pc2_priv->irq = config->ibirq; - /* poll so we can detect assertion of ATN */ - if (gpib_request_pseudo_irq(board, pc2_interrupt)) { - pr_err("pc2_gpib: failed to allocate pseudo_irq\n"); - return -1; - } - /* set internal counter register for 8 MHz input clock */ - write_byte(nec_priv, ICR | 8, AUXMR); - - nec7210_board_online(nec_priv, board); - - return 0; -} - -void pc2_detach(gpib_board_t *board) -{ - struct pc2_priv *pc2_priv = board->private_data; - struct nec7210_priv *nec_priv; - - if (pc2_priv) { - nec_priv = &pc2_priv->nec7210_priv; -#ifdef PC2_DMA - if (nec_priv->dma_channel) - free_dma(nec_priv->dma_channel); -#endif - gpib_free_pseudo_irq(board); - if (pc2_priv->irq) - free_irq(pc2_priv->irq, board); - if (nec_priv->iobase) { - nec7210_board_reset(nec_priv, board); - release_region(nec_priv->iobase, pc2_iosize); - } - if (nec_priv->dma_buffer) { - dma_free_coherent(board->dev, nec_priv->dma_buffer_length, - nec_priv->dma_buffer, nec_priv->dma_buffer_addr); - nec_priv->dma_buffer = NULL; - } - } - free_private(board); -} - -static int pc2a_common_attach(gpib_board_t *board, const gpib_board_config_t *config, - unsigned int num_registers, enum nec7210_chipset chipset) -{ - unsigned int i, j; - struct pc2_priv *pc2_priv; - struct nec7210_priv *nec_priv; - int retval; - - retval = pc2_generic_attach(board, config, chipset); - if (retval) - return retval; - - pc2_priv = board->private_data; - nec_priv = &pc2_priv->nec7210_priv; - nec_priv->offset = pc2a_reg_offset; - - switch (config->ibbase) { - case 0x02e1: - case 0x22e1: - case 0x42e1: - case 0x62e1: - break; - default: - pr_err("PCIIa base range invalid, must be one of 0x[0246]2e1, but is 0x%d\n", - config->ibbase); - return -1; - } - - if (config->ibirq) { - if (config->ibirq < 2 || config->ibirq > 7) { - pr_err("pc2_gpib: illegal interrupt level %i\n", config->ibirq); - return -1; - } - } else { - pr_err("pc2_gpib: interrupt disabled, using polling mode (slow)\n"); - } -#ifdef CHECK_IOPORTS - unsigned int err = 0; - - for (i = 0; i < num_registers; i++) { - if (check_region(config->ibbase + i * pc2a_reg_offset, 1)) - err++; - } - if (config->ibirq && check_region(pc2a_clear_intr_iobase + config->ibirq, 1)) - err++; - if (err) { - pr_err("gpib: ioports are already in use"); - return -1; - } -#endif - for (i = 0; i < num_registers; i++) { - if (!request_region(config->ibbase + - i * pc2a_reg_offset, 1, "pc2a")) { - pr_err("gpib: ioports are already in use"); - for (j = 0; j < i; j++) - release_region(config->ibbase + - j * pc2a_reg_offset, 1); - return -1; - } - } - nec_priv->iobase = config->ibbase; - if (config->ibirq) { - if (!request_region(pc2a_clear_intr_iobase + config->ibirq, 1, "pc2a")) { - pr_err("gpib: ioports are already in use"); - return -1; - } - pc2_priv->clear_intr_addr = pc2a_clear_intr_iobase + config->ibirq; - if (request_irq(config->ibirq, pc2a_interrupt, 0, "pc2a", board)) { - pr_err("gpib: can't request IRQ %d\n", config->ibirq); - return -1; - } - } - pc2_priv->irq = config->ibirq; - /* poll so we can detect assertion of ATN */ - if (gpib_request_pseudo_irq(board, pc2_interrupt)) { - pr_err("pc2_gpib: failed to allocate pseudo_irq\n"); - return -1; - } - - // make sure interrupt is clear - if (pc2_priv->irq) - outb(0xff, CLEAR_INTR_REG(pc2_priv->irq)); - - nec7210_board_reset(nec_priv, board); - - /* set internal counter register for 8 MHz input clock */ - write_byte(nec_priv, ICR | 8, AUXMR); - - nec7210_board_online(nec_priv, board); - - return 0; -} - -int pc2a_attach(gpib_board_t *board, const gpib_board_config_t *config) -{ - return pc2a_common_attach(board, config, pc2a_iosize, NEC7210); -} - -int pc2a_cb7210_attach(gpib_board_t *board, const gpib_board_config_t *config) -{ - return pc2a_common_attach(board, config, pc2a_iosize, CB7210); -} - -int pc2_2a_attach(gpib_board_t *board, const gpib_board_config_t *config) -{ - return pc2a_common_attach(board, config, pc2_2a_iosize, NAT4882); -} - -static void pc2a_common_detach(gpib_board_t *board, unsigned int num_registers) -{ - int i; - struct pc2_priv *pc2_priv = board->private_data; - struct nec7210_priv *nec_priv; - - if (pc2_priv) { - nec_priv = &pc2_priv->nec7210_priv; -#ifdef PC2_DMA - if (nec_priv->dma_channel) - free_dma(nec_priv->dma_channel); -#endif - gpib_free_pseudo_irq(board); - if (pc2_priv->irq) - free_irq(pc2_priv->irq, board); - if (nec_priv->iobase) { - nec7210_board_reset(nec_priv, board); - for (i = 0; i < num_registers; i++) - release_region(nec_priv->iobase + - i * pc2a_reg_offset, 1); - } - if (pc2_priv->clear_intr_addr) - release_region(pc2_priv->clear_intr_addr, 1); - if (nec_priv->dma_buffer) { - dma_free_coherent(board->dev, nec_priv->dma_buffer_length, - nec_priv->dma_buffer, - nec_priv->dma_buffer_addr); - nec_priv->dma_buffer = NULL; - } - } - free_private(board); -} - -void pc2a_detach(gpib_board_t *board) -{ - pc2a_common_detach(board, pc2a_iosize); -} - -void pc2_2a_detach(gpib_board_t *board) -{ - pc2a_common_detach(board, pc2_2a_iosize); -} - static int __init pc2_init_module(void) { int ret; ret = gpib_register_driver(&pc2_interface, THIS_MODULE); if (ret) { - pr_err("pc2_gpib: gpib_register_driver failed: error = %d\n", ret); + pr_err("gpib_register_driver failed: error = %d\n", ret); return ret; } ret = gpib_register_driver(&pc2a_interface, THIS_MODULE); if (ret) { - pr_err("pc2_gpib: gpib_register_driver failed: error = %d\n", ret); + pr_err("gpib_register_driver failed: error = %d\n", ret); goto err_pc2a; } ret = gpib_register_driver(&pc2a_cb7210_interface, THIS_MODULE); if (ret) { - pr_err("pc2_gpib: gpib_register_driver failed: error = %d\n", ret); + pr_err("gpib_register_driver failed: error = %d\n", ret); goto err_cb7210; } ret = gpib_register_driver(&pc2_2a_interface, THIS_MODULE); if (ret) { - pr_err("pc2_gpib: gpib_register_driver failed: error = %d\n", ret); + pr_err("gpib_register_driver failed: error = %d\n", ret); goto err_pc2_2a; }
diff --git a/drivers/staging/gpib/tms9914/tms9914.c b/drivers/staging/gpib/tms9914/tms9914.c index ec8e1d4..2abda9d 100644 --- a/drivers/staging/gpib/tms9914/tms9914.c +++ b/drivers/staging/gpib/tms9914/tms9914.c
@@ -4,6 +4,9 @@ * copyright : (C) 2001, 2002 by Frank Mori Hess ***************************************************************************/ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#define dev_fmt pr_fmt + #include <linux/ioport.h> #include <linux/sched.h> #include <linux/module.h> @@ -24,9 +27,9 @@ MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("GPIB library for tms9914"); -static unsigned int update_status_nolock(gpib_board_t *board, struct tms9914_priv *priv); +static unsigned int update_status_nolock(struct gpib_board *board, struct tms9914_priv *priv); -int tms9914_take_control(gpib_board_t *board, struct tms9914_priv *priv, int synchronous) +int tms9914_take_control(struct gpib_board *board, struct tms9914_priv *priv, int synchronous) { int i; const int timeout = 100; @@ -63,7 +66,7 @@ EXPORT_SYMBOL_GPL(tms9914_take_control); * The rest of the tms9914 based drivers still use tms9914_take_control * directly (which does issue tcs). */ -int tms9914_take_control_workaround(gpib_board_t *board, struct tms9914_priv *priv, int synchronous) +int tms9914_take_control_workaround(struct gpib_board *board, struct tms9914_priv *priv, int synchronous) { if (synchronous) return -ETIMEDOUT; @@ -71,7 +74,7 @@ int tms9914_take_control_workaround(gpib_board_t *board, struct tms9914_priv *pr } EXPORT_SYMBOL_GPL(tms9914_take_control_workaround); -int tms9914_go_to_standby(gpib_board_t *board, struct tms9914_priv *priv) +int tms9914_go_to_standby(struct gpib_board *board, struct tms9914_priv *priv) { int i; const int timeout = 1000; @@ -83,10 +86,8 @@ int tms9914_go_to_standby(gpib_board_t *board, struct tms9914_priv *priv) break; udelay(1); } - if (i == timeout) { - pr_err("error waiting for NATN\n"); + if (i == timeout) return -ETIMEDOUT; - } clear_bit(COMMAND_READY_BN, &priv->state); @@ -94,7 +95,7 @@ int tms9914_go_to_standby(gpib_board_t *board, struct tms9914_priv *priv) } EXPORT_SYMBOL_GPL(tms9914_go_to_standby); -void tms9914_interface_clear(gpib_board_t *board, struct tms9914_priv *priv, int assert) +void tms9914_interface_clear(struct gpib_board *board, struct tms9914_priv *priv, int assert) { if (assert) { write_byte(priv, AUX_SIC | AUX_CS, AUXCR); @@ -106,7 +107,7 @@ void tms9914_interface_clear(gpib_board_t *board, struct tms9914_priv *priv, int } EXPORT_SYMBOL_GPL(tms9914_interface_clear); -void tms9914_remote_enable(gpib_board_t *board, struct tms9914_priv *priv, int enable) +void tms9914_remote_enable(struct gpib_board *board, struct tms9914_priv *priv, int enable) { if (enable) write_byte(priv, AUX_SRE | AUX_CS, AUXCR); @@ -115,7 +116,7 @@ void tms9914_remote_enable(gpib_board_t *board, struct tms9914_priv *priv, int e } EXPORT_SYMBOL_GPL(tms9914_remote_enable); -void tms9914_request_system_control(gpib_board_t *board, struct tms9914_priv *priv, +void tms9914_request_system_control(struct gpib_board *board, struct tms9914_priv *priv, int request_control) { if (request_control) { @@ -127,7 +128,7 @@ void tms9914_request_system_control(gpib_board_t *board, struct tms9914_priv *pr } EXPORT_SYMBOL_GPL(tms9914_request_system_control); -unsigned int tms9914_t1_delay(gpib_board_t *board, struct tms9914_priv *priv, +unsigned int tms9914_t1_delay(struct gpib_board *board, struct tms9914_priv *priv, unsigned int nano_sec) { static const int clock_period = 200; // assuming 5Mhz input clock @@ -153,7 +154,7 @@ unsigned int tms9914_t1_delay(gpib_board_t *board, struct tms9914_priv *priv, } EXPORT_SYMBOL_GPL(tms9914_t1_delay); -void tms9914_return_to_local(const gpib_board_t *board, struct tms9914_priv *priv) +void tms9914_return_to_local(const struct gpib_board *board, struct tms9914_priv *priv) { write_byte(priv, AUX_RTL, AUXCR); } @@ -175,7 +176,7 @@ void tms9914_set_holdoff_mode(struct tms9914_priv *priv, enum tms9914_holdoff_mo write_byte(priv, AUX_HLDA | AUX_CS, AUXCR); break; default: - pr_err("%s: bug! bad holdoff mode %i\n", __func__, mode); + pr_err("bug! bad holdoff mode %i\n", mode); break; } priv->holdoff_mode = mode; @@ -191,7 +192,7 @@ void tms9914_release_holdoff(struct tms9914_priv *priv) } EXPORT_SYMBOL_GPL(tms9914_release_holdoff); -int tms9914_enable_eos(gpib_board_t *board, struct tms9914_priv *priv, uint8_t eos_byte, +int tms9914_enable_eos(struct gpib_board *board, struct tms9914_priv *priv, uint8_t eos_byte, int compare_8_bits) { priv->eos = eos_byte; @@ -202,13 +203,13 @@ int tms9914_enable_eos(gpib_board_t *board, struct tms9914_priv *priv, uint8_t e } EXPORT_SYMBOL(tms9914_enable_eos); -void tms9914_disable_eos(gpib_board_t *board, struct tms9914_priv *priv) +void tms9914_disable_eos(struct gpib_board *board, struct tms9914_priv *priv) { priv->eos_flags &= ~REOS; } EXPORT_SYMBOL(tms9914_disable_eos); -int tms9914_parallel_poll(gpib_board_t *board, struct tms9914_priv *priv, uint8_t *result) +int tms9914_parallel_poll(struct gpib_board *board, struct tms9914_priv *priv, uint8_t *result) { // execute parallel poll write_byte(priv, AUX_CS | AUX_RPP, AUXCR); @@ -233,7 +234,7 @@ static void set_ppoll_reg(struct tms9914_priv *priv, int enable, } } -void tms9914_parallel_poll_configure(gpib_board_t *board, +void tms9914_parallel_poll_configure(struct gpib_board *board, struct tms9914_priv *priv, uint8_t config) { priv->ppoll_enable = (config & PPC_DISABLE) == 0; @@ -243,14 +244,14 @@ void tms9914_parallel_poll_configure(gpib_board_t *board, } EXPORT_SYMBOL(tms9914_parallel_poll_configure); -void tms9914_parallel_poll_response(gpib_board_t *board, +void tms9914_parallel_poll_response(struct gpib_board *board, struct tms9914_priv *priv, int ist) { set_ppoll_reg(priv, priv->ppoll_enable, priv->ppoll_line, priv->ppoll_sense, ist); } EXPORT_SYMBOL(tms9914_parallel_poll_response); -void tms9914_serial_poll_response(gpib_board_t *board, struct tms9914_priv *priv, uint8_t status) +void tms9914_serial_poll_response(struct gpib_board *board, struct tms9914_priv *priv, uint8_t status) { unsigned long flags; @@ -265,7 +266,7 @@ void tms9914_serial_poll_response(gpib_board_t *board, struct tms9914_priv *priv } EXPORT_SYMBOL(tms9914_serial_poll_response); -uint8_t tms9914_serial_poll_status(gpib_board_t *board, struct tms9914_priv *priv) +uint8_t tms9914_serial_poll_status(struct gpib_board *board, struct tms9914_priv *priv) { u8 status; unsigned long flags; @@ -278,7 +279,7 @@ uint8_t tms9914_serial_poll_status(gpib_board_t *board, struct tms9914_priv *pri } EXPORT_SYMBOL(tms9914_serial_poll_status); -int tms9914_primary_address(gpib_board_t *board, struct tms9914_priv *priv, unsigned int address) +int tms9914_primary_address(struct gpib_board *board, struct tms9914_priv *priv, unsigned int address) { // put primary address in address0 write_byte(priv, address & ADDRESS_MASK, ADR); @@ -286,7 +287,7 @@ int tms9914_primary_address(gpib_board_t *board, struct tms9914_priv *priv, unsi } EXPORT_SYMBOL(tms9914_primary_address); -int tms9914_secondary_address(gpib_board_t *board, struct tms9914_priv *priv, +int tms9914_secondary_address(struct gpib_board *board, struct tms9914_priv *priv, unsigned int address, int enable) { if (enable) @@ -299,7 +300,7 @@ int tms9914_secondary_address(gpib_board_t *board, struct tms9914_priv *priv, } EXPORT_SYMBOL(tms9914_secondary_address); -unsigned int tms9914_update_status(gpib_board_t *board, struct tms9914_priv *priv, +unsigned int tms9914_update_status(struct gpib_board *board, struct tms9914_priv *priv, unsigned int clear_mask) { unsigned long flags; @@ -341,7 +342,7 @@ static void update_listener_state(struct tms9914_priv *priv, unsigned int addres } } -static unsigned int update_status_nolock(gpib_board_t *board, struct tms9914_priv *priv) +static unsigned int update_status_nolock(struct gpib_board *board, struct tms9914_priv *priv) { int address_status; int bsr_bits; @@ -387,29 +388,29 @@ static unsigned int update_status_nolock(gpib_board_t *board, struct tms9914_pri return board->status; } -int tms9914_line_status(const gpib_board_t *board, struct tms9914_priv *priv) +int tms9914_line_status(const struct gpib_board *board, struct tms9914_priv *priv) { int bsr_bits; - int status = ValidALL; + int status = VALID_ALL; bsr_bits = read_byte(priv, BSR); if (bsr_bits & BSR_REN_BIT) - status |= BusREN; + status |= BUS_REN; if (bsr_bits & BSR_IFC_BIT) - status |= BusIFC; + status |= BUS_IFC; if (bsr_bits & BSR_SRQ_BIT) - status |= BusSRQ; + status |= BUS_SRQ; if (bsr_bits & BSR_EOI_BIT) - status |= BusEOI; + status |= BUS_EOI; if (bsr_bits & BSR_NRFD_BIT) - status |= BusNRFD; + status |= BUS_NRFD; if (bsr_bits & BSR_NDAC_BIT) - status |= BusNDAC; + status |= BUS_NDAC; if (bsr_bits & BSR_DAV_BIT) - status |= BusDAV; + status |= BUS_DAV; if (bsr_bits & BSR_ATN_BIT) - status |= BusATN; + status |= BUS_ATN; return status; } @@ -432,15 +433,14 @@ static int check_for_eos(struct tms9914_priv *priv, uint8_t byte) return 0; } -static int wait_for_read_byte(gpib_board_t *board, struct tms9914_priv *priv) +static int wait_for_read_byte(struct gpib_board *board, struct tms9914_priv *priv) { if (wait_event_interruptible(board->wait, test_bit(READ_READY_BN, &priv->state) || test_bit(DEV_CLEAR_BN, &priv->state) || - test_bit(TIMO_NUM, &board->status))) { - pr_debug("gpib: pio read wait interrupted\n"); + test_bit(TIMO_NUM, &board->status))) return -ERESTARTSYS; - } + if (test_bit(TIMO_NUM, &board->status)) return -ETIMEDOUT; @@ -449,7 +449,7 @@ static int wait_for_read_byte(gpib_board_t *board, struct tms9914_priv *priv) return 0; } -static inline uint8_t tms9914_read_data_in(gpib_board_t *board, struct tms9914_priv *priv, int *end) +static inline uint8_t tms9914_read_data_in(struct gpib_board *board, struct tms9914_priv *priv, int *end) { unsigned long flags; u8 data; @@ -472,7 +472,7 @@ static inline uint8_t tms9914_read_data_in(gpib_board_t *board, struct tms9914_p case TMS9914_HOLDOFF_NONE: break; default: - pr_err("%s: bug! bad holdoff mode %i\n", __func__, priv->holdoff_mode); + dev_err(board->gpib_dev, "bug! bad holdoff mode %i\n", priv->holdoff_mode); break; } spin_unlock_irqrestore(&board->spinlock, flags); @@ -480,7 +480,7 @@ static inline uint8_t tms9914_read_data_in(gpib_board_t *board, struct tms9914_p return data; } -static int pio_read(gpib_board_t *board, struct tms9914_priv *priv, uint8_t *buffer, +static int pio_read(struct gpib_board *board, struct tms9914_priv *priv, uint8_t *buffer, size_t length, int *end, size_t *bytes_read) { ssize_t retval = 0; @@ -501,7 +501,7 @@ static int pio_read(gpib_board_t *board, struct tms9914_priv *priv, uint8_t *buf return retval; } -int tms9914_read(gpib_board_t *board, struct tms9914_priv *priv, uint8_t *buffer, +int tms9914_read(struct gpib_board *board, struct tms9914_priv *priv, uint8_t *buffer, size_t length, int *end, size_t *bytes_read) { ssize_t retval = 0; @@ -541,17 +541,16 @@ int tms9914_read(gpib_board_t *board, struct tms9914_priv *priv, uint8_t *buffer } EXPORT_SYMBOL(tms9914_read); -static int pio_write_wait(gpib_board_t *board, struct tms9914_priv *priv) +static int pio_write_wait(struct gpib_board *board, struct tms9914_priv *priv) { // wait until next byte is ready to be sent if (wait_event_interruptible(board->wait, test_bit(WRITE_READY_BN, &priv->state) || test_bit(BUS_ERROR_BN, &priv->state) || test_bit(DEV_CLEAR_BN, &priv->state) || - test_bit(TIMO_NUM, &board->status))) { - dev_dbg(board->gpib_dev, "gpib write interrupted!\n"); + test_bit(TIMO_NUM, &board->status))) return -ERESTARTSYS; - } + if (test_bit(TIMO_NUM, &board->status)) return -ETIMEDOUT; if (test_bit(BUS_ERROR_BN, &priv->state)) @@ -562,7 +561,7 @@ static int pio_write_wait(gpib_board_t *board, struct tms9914_priv *priv) return 0; } -static int pio_write(gpib_board_t *board, struct tms9914_priv *priv, uint8_t *buffer, +static int pio_write(struct gpib_board *board, struct tms9914_priv *priv, uint8_t *buffer, size_t length, size_t *bytes_written) { ssize_t retval = 0; @@ -586,7 +585,7 @@ static int pio_write(gpib_board_t *board, struct tms9914_priv *priv, uint8_t *bu return length; } -int tms9914_write(gpib_board_t *board, struct tms9914_priv *priv, uint8_t *buffer, size_t length, +int tms9914_write(struct gpib_board *board, struct tms9914_priv *priv, uint8_t *buffer, size_t length, int send_eoi, size_t *bytes_written) { ssize_t retval = 0; @@ -621,7 +620,7 @@ int tms9914_write(gpib_board_t *board, struct tms9914_priv *priv, uint8_t *buffe } EXPORT_SYMBOL(tms9914_write); -static void check_my_address_state(gpib_board_t *board, struct tms9914_priv *priv, int cmd_byte) +static void check_my_address_state(struct gpib_board *board, struct tms9914_priv *priv, int cmd_byte) { if (cmd_byte == MLA(board->pad)) { priv->primary_listen_addressed = 1; @@ -656,7 +655,7 @@ static void check_my_address_state(gpib_board_t *board, struct tms9914_priv *pri } } -int tms9914_command(gpib_board_t *board, struct tms9914_priv *priv, uint8_t *buffer, +int tms9914_command(struct gpib_board *board, struct tms9914_priv *priv, uint8_t *buffer, size_t length, size_t *bytes_written) { int retval = 0; @@ -667,10 +666,8 @@ int tms9914_command(gpib_board_t *board, struct tms9914_priv *priv, uint8_t *bu if (wait_event_interruptible(board->wait, test_bit(COMMAND_READY_BN, &priv->state) || - test_bit(TIMO_NUM, &board->status))) { - pr_debug("gpib command wait interrupted\n"); + test_bit(TIMO_NUM, &board->status))) break; - } if (test_bit(TIMO_NUM, &board->status)) break; @@ -695,7 +692,7 @@ int tms9914_command(gpib_board_t *board, struct tms9914_priv *priv, uint8_t *bu } EXPORT_SYMBOL(tms9914_command); -irqreturn_t tms9914_interrupt(gpib_board_t *board, struct tms9914_priv *priv) +irqreturn_t tms9914_interrupt(struct gpib_board *board, struct tms9914_priv *priv) { int status0, status1; @@ -706,7 +703,7 @@ irqreturn_t tms9914_interrupt(gpib_board_t *board, struct tms9914_priv *priv) } EXPORT_SYMBOL(tms9914_interrupt); -irqreturn_t tms9914_interrupt_have_status(gpib_board_t *board, struct tms9914_priv *priv, +irqreturn_t tms9914_interrupt_have_status(struct gpib_board *board, struct tms9914_priv *priv, int status0, int status1) { // record reception of END @@ -761,8 +758,6 @@ irqreturn_t tms9914_interrupt_have_status(gpib_board_t *board, struct tms9914_pr write_byte(priv, AUX_INVAL, AUXCR); } } else { - // printk("tms9914: unrecognized gpib command pass thru 0x%x\n", - // command_byte); // clear dac holdoff write_byte(priv, AUX_INVAL, AUXCR); } @@ -799,7 +794,7 @@ irqreturn_t tms9914_interrupt_have_status(gpib_board_t *board, struct tms9914_pr // check for being addressed with secondary addressing if (status1 & HR_APT) { if (board->sad < 0) - pr_err("tms9914: bug, APT interrupt without secondary addressing?\n"); + dev_err(board->gpib_dev, "bug, APT interrupt without secondary addressing?\n"); if ((read_byte(priv, CPTR) & gpib_command_mask) == MSA(board->sad)) write_byte(priv, AUX_VAL, AUXCR); else @@ -807,8 +802,8 @@ irqreturn_t tms9914_interrupt_have_status(gpib_board_t *board, struct tms9914_pr } if ((status0 & priv->imr0_bits) || (status1 & priv->imr1_bits)) { -// dev_dbg(board->gpib_dev, "isr0 0x%x, imr0 0x%x, isr1 0x%x, imr1 0x%x\n", -// status0, priv->imr0_bits, status1, priv->imr1_bits); + dev_dbg(board->gpib_dev, "isr0 0x%x, imr0 0x%x, isr1 0x%x, imr1 0x%x\n", + status0, priv->imr0_bits, status1, priv->imr1_bits); update_status_nolock(board, priv); wake_up_interruptible(&board->wait); } @@ -842,7 +837,7 @@ void tms9914_board_reset(struct tms9914_priv *priv) } EXPORT_SYMBOL_GPL(tms9914_board_reset); -void tms9914_online(gpib_board_t *board, struct tms9914_priv *priv) +void tms9914_online(struct gpib_board *board, struct tms9914_priv *priv) { /* set GPIB address */ tms9914_primary_address(board, priv, board->pad);
diff --git a/drivers/staging/gpib/tnt4882/Makefile b/drivers/staging/gpib/tnt4882/Makefile index a3c3fb9..fa1687a 100644 --- a/drivers/staging/gpib/tnt4882/Makefile +++ b/drivers/staging/gpib/tnt4882/Makefile
@@ -1,4 +1,3 @@ -ccflags-$(CONFIG_GPIB_PCMCIA) := -DGPIB_PCMCIA obj-$(CONFIG_GPIB_NI_PCI_ISA) += tnt4882.o tnt4882-objs := tnt4882_gpib.o mite.o
diff --git a/drivers/staging/gpib/tnt4882/mite.c b/drivers/staging/gpib/tnt4882/mite.c index ea64dde..847b96f 100644 --- a/drivers/staging/gpib/tnt4882/mite.c +++ b/drivers/staging/gpib/tnt4882/mite.c
@@ -88,7 +88,6 @@ int mite_setup(struct mite_struct *mite) pr_err("mite: failed to remap mite io memory address.\n"); return -ENOMEM; } - pr_info("mite: 0x%08lx mapped to %p\n", mite->mite_phys_addr, mite->mite_io_addr); addr = pci_resource_start(mite->pcidev, 1); mite->daq_phys_addr = addr; mite->daq_io_addr = ioremap(mite->daq_phys_addr, pci_resource_len(mite->pcidev, 1)); @@ -96,7 +95,6 @@ int mite_setup(struct mite_struct *mite) pr_err("mite: failed to remap daq io memory address.\n"); return -ENOMEM; } - pr_info("mite: daq: 0x%08lx mapped to %p\n", mite->daq_phys_addr, mite->daq_io_addr); writel(mite->daq_phys_addr | WENAB, mite->mite_io_addr + MITE_IODWBSR); mite->used = 1; return 0; @@ -133,18 +131,3 @@ void mite_unsetup(struct mite_struct *mite) } mite->used = 0; } - -void mite_list_devices(void) -{ - struct mite_struct *mite, *next; - - pr_info("Available NI PCI device IDs:"); - if (mite_devices) - for (mite = mite_devices; mite; mite = next) { - next = mite->next; - pr_info(" 0x%04x", mite_device_id(mite)); - if (mite->used) - pr_info("(used)"); - } - pr_info("\n"); -}
diff --git a/drivers/staging/gpib/tnt4882/tnt4882_gpib.c b/drivers/staging/gpib/tnt4882/tnt4882_gpib.c index b39ab2a..c35b084 100644 --- a/drivers/staging/gpib/tnt4882/tnt4882_gpib.c +++ b/drivers/staging/gpib/tnt4882/tnt4882_gpib.c
@@ -5,6 +5,10 @@ * copyright : (C) 2001, 2002 by Frank Mori Hess ***************************************************************************/ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#define dev_fmt pr_fmt +#define DRV_NAME KBUILD_MODNAME + #include <linux/ioport.h> #include <linux/sched.h> #include <linux/module.h> @@ -47,49 +51,7 @@ struct tnt4882_priv { unsigned short auxg_bits; // bits written to auxiliary register G }; -// interface functions -static int tnt4882_read(gpib_board_t *board, uint8_t *buffer, size_t length, - int *end, size_t *bytes_read); -static int tnt4882_accel_read(gpib_board_t *board, uint8_t *buffer, size_t length, - int *end, size_t *bytes_read); -static int tnt4882_write(gpib_board_t *board, uint8_t *buffer, size_t length, - int send_eoi, size_t *bytes_written); -static int tnt4882_accel_write(gpib_board_t *board, uint8_t *buffer, size_t length, - int send_eoi, size_t *bytes_written); -static int tnt4882_command(gpib_board_t *board, uint8_t *buffer, size_t length, - size_t *bytes_written); -static int tnt4882_command_unaccel(gpib_board_t *board, uint8_t *buffer, - size_t length, size_t *bytes_written); -static int tnt4882_take_control(gpib_board_t *board, int synchronous); -static int tnt4882_go_to_standby(gpib_board_t *board); -static void tnt4882_request_system_control(gpib_board_t *board, int request_control); -static void tnt4882_interface_clear(gpib_board_t *board, int assert); -static void tnt4882_remote_enable(gpib_board_t *board, int enable); -static int tnt4882_enable_eos(gpib_board_t *board, uint8_t eos_byte, int - compare_8_bits); -static void tnt4882_disable_eos(gpib_board_t *board); -static unsigned int tnt4882_update_status(gpib_board_t *board, unsigned int clear_mask); -static int tnt4882_primary_address(gpib_board_t *board, unsigned int address); -static int tnt4882_secondary_address(gpib_board_t *board, unsigned int address, - int enable); -static int tnt4882_parallel_poll(gpib_board_t *board, uint8_t *result); -static void tnt4882_parallel_poll_configure(gpib_board_t *board, uint8_t config); -static void tnt4882_parallel_poll_response(gpib_board_t *board, int ist); -static void tnt4882_serial_poll_response(gpib_board_t *board, uint8_t status); -static uint8_t tnt4882_serial_poll_status(gpib_board_t *board); -static int tnt4882_line_status(const gpib_board_t *board); -static unsigned int tnt4882_t1_delay(gpib_board_t *board, unsigned int nano_sec); -static void tnt4882_return_to_local(gpib_board_t *board); - -// interrupt service routines -static irqreturn_t tnt4882_internal_interrupt(gpib_board_t *board); -static irqreturn_t tnt4882_interrupt(int irq, void *arg); - -// utility functions -static int tnt4882_allocate_private(gpib_board_t *board); -static void tnt4882_free_private(gpib_board_t *board); -static void tnt4882_init(struct tnt4882_priv *tnt_priv, const gpib_board_t *board); -static void tnt4882_board_reset(struct tnt4882_priv *tnt_priv, gpib_board_t *board); +static irqreturn_t tnt4882_internal_interrupt(struct gpib_board *board); // register offset for nec7210 compatible registers static const int atgpib_reg_offset = 2; @@ -139,7 +101,6 @@ static inline unsigned short tnt_readb(struct tnt4882_priv *priv, unsigned long retval = 0; break; default: - pr_err("tnt4882: bug! unsupported ni_chipset\n"); retval = 0; break; } @@ -174,7 +135,6 @@ static inline void tnt_writeb(struct tnt4882_priv *priv, unsigned short value, u case NEC7210: break; default: - pr_err("tnt4882: bug! unsupported ni_chipset\n"); break; } break; @@ -188,9 +148,9 @@ static inline void tnt_writeb(struct tnt4882_priv *priv, unsigned short value, u MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("GPIB driver for National Instruments boards using tnt4882 or compatible chips"); -int tnt4882_line_status(const gpib_board_t *board) +static int tnt4882_line_status(const struct gpib_board *board) { - int status = ValidALL; + int status = VALID_ALL; int bcsr_bits; struct tnt4882_priv *tnt_priv; @@ -199,26 +159,26 @@ int tnt4882_line_status(const gpib_board_t *board) bcsr_bits = tnt_readb(tnt_priv, BSR); if (bcsr_bits & BCSR_REN_BIT) - status |= BusREN; + status |= BUS_REN; if (bcsr_bits & BCSR_IFC_BIT) - status |= BusIFC; + status |= BUS_IFC; if (bcsr_bits & BCSR_SRQ_BIT) - status |= BusSRQ; + status |= BUS_SRQ; if (bcsr_bits & BCSR_EOI_BIT) - status |= BusEOI; + status |= BUS_EOI; if (bcsr_bits & BCSR_NRFD_BIT) - status |= BusNRFD; + status |= BUS_NRFD; if (bcsr_bits & BCSR_NDAC_BIT) - status |= BusNDAC; + status |= BUS_NDAC; if (bcsr_bits & BCSR_DAV_BIT) - status |= BusDAV; + status |= BUS_DAV; if (bcsr_bits & BCSR_ATN_BIT) - status |= BusATN; + status |= BUS_ATN; return status; } -unsigned int tnt4882_t1_delay(gpib_board_t *board, unsigned int nano_sec) +static int tnt4882_t1_delay(struct gpib_board *board, unsigned int nano_sec) { struct tnt4882_priv *tnt_priv = board->private_data; struct nec7210_priv *nec_priv = &tnt_priv->nec7210_priv; @@ -291,7 +251,7 @@ static int drain_fifo_words(struct tnt4882_priv *tnt_priv, uint8_t *buffer, int return count; } -static void tnt4882_release_holdoff(gpib_board_t *board, struct tnt4882_priv *tnt_priv) +static void tnt4882_release_holdoff(struct gpib_board *board, struct tnt4882_priv *tnt_priv) { struct nec7210_priv *nec_priv = &tnt_priv->nec7210_priv; unsigned short sasr_bits; @@ -314,8 +274,8 @@ static void tnt4882_release_holdoff(gpib_board_t *board, struct tnt4882_priv *tn } } -int tnt4882_accel_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *end, - size_t *bytes_read) +static int tnt4882_accel_read(struct gpib_board *board, uint8_t *buffer, size_t length, int *end, + size_t *bytes_read) { size_t count = 0; ssize_t retval = 0; @@ -368,22 +328,18 @@ int tnt4882_accel_read(gpib_board_t *board, uint8_t *buffer, size_t length, int test_bit(DEV_CLEAR_BN, &nec_priv->state) || test_bit(ADR_CHANGE_BN, &nec_priv->state) || test_bit(TIMO_NUM, &board->status))) { - pr_err("tnt4882: read interrupted\n"); retval = -ERESTARTSYS; break; } if (test_bit(TIMO_NUM, &board->status)) { - //pr_info("tnt4882: minor %i read timed out\n", board->minor); retval = -ETIMEDOUT; break; } if (test_bit(DEV_CLEAR_BN, &nec_priv->state)) { - pr_err("tnt4882: device clear interrupted read\n"); retval = -EINTR; break; } if (test_bit(ADR_CHANGE_BN, &nec_priv->state)) { - pr_err("tnt4882: address change interrupted read\n"); retval = -EINTR; break; } @@ -410,20 +366,14 @@ int tnt4882_accel_read(gpib_board_t *board, uint8_t *buffer, size_t length, int test_bit(DEV_CLEAR_BN, &nec_priv->state) || test_bit(ADR_CHANGE_BN, &nec_priv->state) || test_bit(TIMO_NUM, &board->status))) { - pr_err("tnt4882: read interrupted\n"); retval = -ERESTARTSYS; } if (test_bit(TIMO_NUM, &board->status)) - //pr_info("tnt4882: read timed out\n"); retval = -ETIMEDOUT; - if (test_bit(DEV_CLEAR_BN, &nec_priv->state)) { - pr_err("tnt4882: device clear interrupted read\n"); + if (test_bit(DEV_CLEAR_BN, &nec_priv->state)) retval = -EINTR; - } - if (test_bit(ADR_CHANGE_BN, &nec_priv->state)) { - pr_err("tnt4882: address change interrupted read\n"); + if (test_bit(ADR_CHANGE_BN, &nec_priv->state)) retval = -EINTR; - } count += drain_fifo_words(tnt_priv, &buffer[count], length - count); if (fifo_byte_available(tnt_priv) && count < length) buffer[count++] = tnt_readb(tnt_priv, FIFOB); @@ -476,7 +426,7 @@ static unsigned int tnt_transfer_count(struct tnt4882_priv *tnt_priv) return -count; }; -static int write_wait(gpib_board_t *board, struct tnt4882_priv *tnt_priv, +static int write_wait(struct gpib_board *board, struct tnt4882_priv *tnt_priv, int wait_for_done, int send_commands) { struct nec7210_priv *nec_priv = &tnt_priv->nec7210_priv; @@ -486,26 +436,19 @@ static int write_wait(gpib_board_t *board, struct tnt4882_priv *tnt_priv, fifo_xfer_done(tnt_priv) || test_bit(BUS_ERROR_BN, &nec_priv->state) || test_bit(DEV_CLEAR_BN, &nec_priv->state) || - test_bit(TIMO_NUM, &board->status))) { - dev_dbg(board->gpib_dev, "gpib write interrupted\n"); + test_bit(TIMO_NUM, &board->status))) return -ERESTARTSYS; - } - if (test_bit(TIMO_NUM, &board->status)) { - pr_info("tnt4882: write timed out\n"); + + if (test_bit(TIMO_NUM, &board->status)) return -ETIMEDOUT; - } - if (test_and_clear_bit(BUS_ERROR_BN, &nec_priv->state)) { - pr_err("tnt4882: write bus error\n"); + if (test_and_clear_bit(BUS_ERROR_BN, &nec_priv->state)) return (send_commands) ? -ENOTCONN : -ECOMM; - } - if (test_bit(DEV_CLEAR_BN, &nec_priv->state)) { - pr_err("tnt4882: device clear interrupted write\n"); + if (test_bit(DEV_CLEAR_BN, &nec_priv->state)) return -EINTR; - } return 0; } -static int generic_write(gpib_board_t *board, uint8_t *buffer, size_t length, +static int generic_write(struct gpib_board *board, uint8_t *buffer, size_t length, int send_eoi, int send_commands, size_t *bytes_written) { size_t count = 0; @@ -596,18 +539,19 @@ static int generic_write(gpib_board_t *board, uint8_t *buffer, size_t length, return retval; } -int tnt4882_accel_write(gpib_board_t *board, uint8_t *buffer, size_t length, int send_eoi, - size_t *bytes_written) +static int tnt4882_accel_write(struct gpib_board *board, uint8_t *buffer, size_t length, int send_eoi, + size_t *bytes_written) { return generic_write(board, buffer, length, send_eoi, 0, bytes_written); } -int tnt4882_command(gpib_board_t *board, uint8_t *buffer, size_t length, size_t *bytes_written) +static int tnt4882_command(struct gpib_board *board, uint8_t *buffer, size_t length, + size_t *bytes_written) { return generic_write(board, buffer, length, 0, 1, bytes_written); } -irqreturn_t tnt4882_internal_interrupt(gpib_board_t *board) +static irqreturn_t tnt4882_internal_interrupt(struct gpib_board *board) { struct tnt4882_priv *priv = board->private_data; int isr0_bits, isr3_bits, imr3_bits; @@ -633,7 +577,7 @@ irqreturn_t tnt4882_internal_interrupt(gpib_board_t *board) if (isr3_bits & HR_DONE) priv->imr3_bits &= ~HR_DONE; if (isr3_bits & (HR_INTR | HR_TLCI)) { - dev_dbg(board->gpib_dev, "tnt4882: minor %i isr0 0x%x imr0 0x%x isr3 0x%x imr3 0x%x\n", + dev_dbg(board->gpib_dev, "minor %i isr0 0x%x imr0 0x%x isr3 0x%x imr3 0x%x\n", board->minor, isr0_bits, priv->imr0_bits, isr3_bits, imr3_bits); tnt_writeb(priv, priv->imr3_bits, IMR3); wake_up_interruptible(&board->wait); @@ -642,28 +586,14 @@ irqreturn_t tnt4882_internal_interrupt(gpib_board_t *board) return IRQ_HANDLED; } -irqreturn_t tnt4882_interrupt(int irq, void *arg) +static irqreturn_t tnt4882_interrupt(int irq, void *arg) { return tnt4882_internal_interrupt(arg); } -static int ni_tnt_isa_attach(gpib_board_t *board, const gpib_board_config_t *config); -static int ni_nat4882_isa_attach(gpib_board_t *board, const gpib_board_config_t *config); -static int ni_nec_isa_attach(gpib_board_t *board, const gpib_board_config_t *config); -static int ni_pci_attach(gpib_board_t *board, const gpib_board_config_t *config); - -static void ni_isa_detach(gpib_board_t *board); -static void ni_pci_detach(gpib_board_t *board); - -#ifdef GPIB_PCMCIA -static int ni_pcmcia_attach(gpib_board_t *board, const gpib_board_config_t *config); -static void ni_pcmcia_detach(gpib_board_t *board); -static int init_ni_gpib_cs(void); -static void __exit exit_ni_gpib_cs(void); -#endif - // wrappers for interface functions -int tnt4882_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *end, size_t *bytes_read) +static int tnt4882_read(struct gpib_board *board, uint8_t *buffer, size_t length, int *end, + size_t *bytes_read) { struct tnt4882_priv *priv = board->private_data; struct nec7210_priv *nec_priv = &priv->nec7210_priv; @@ -682,37 +612,37 @@ int tnt4882_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *end, return retval; } -int tnt4882_write(gpib_board_t *board, uint8_t *buffer, size_t length, int send_eoi, - size_t *bytes_written) +static int tnt4882_write(struct gpib_board *board, uint8_t *buffer, size_t length, int send_eoi, + size_t *bytes_written) { struct tnt4882_priv *priv = board->private_data; return nec7210_write(board, &priv->nec7210_priv, buffer, length, send_eoi, bytes_written); } -int tnt4882_command_unaccel(gpib_board_t *board, uint8_t *buffer, - size_t length, size_t *bytes_written) +static int tnt4882_command_unaccel(struct gpib_board *board, uint8_t *buffer, + size_t length, size_t *bytes_written) { struct tnt4882_priv *priv = board->private_data; return nec7210_command(board, &priv->nec7210_priv, buffer, length, bytes_written); } -int tnt4882_take_control(gpib_board_t *board, int synchronous) +static int tnt4882_take_control(struct gpib_board *board, int synchronous) { struct tnt4882_priv *priv = board->private_data; return nec7210_take_control(board, &priv->nec7210_priv, synchronous); } -int tnt4882_go_to_standby(gpib_board_t *board) +static int tnt4882_go_to_standby(struct gpib_board *board) { struct tnt4882_priv *priv = board->private_data; return nec7210_go_to_standby(board, &priv->nec7210_priv); } -void tnt4882_request_system_control(gpib_board_t *board, int request_control) +static void tnt4882_request_system_control(struct gpib_board *board, int request_control) { struct tnt4882_priv *priv = board->private_data; @@ -727,44 +657,43 @@ void tnt4882_request_system_control(gpib_board_t *board, int request_control) } } -void tnt4882_interface_clear(gpib_board_t *board, int assert) +static void tnt4882_interface_clear(struct gpib_board *board, int assert) { struct tnt4882_priv *priv = board->private_data; nec7210_interface_clear(board, &priv->nec7210_priv, assert); } -void tnt4882_remote_enable(gpib_board_t *board, int enable) +static void tnt4882_remote_enable(struct gpib_board *board, int enable) { struct tnt4882_priv *priv = board->private_data; nec7210_remote_enable(board, &priv->nec7210_priv, enable); } -int tnt4882_enable_eos(gpib_board_t *board, uint8_t eos_byte, int compare_8_bits) +static int tnt4882_enable_eos(struct gpib_board *board, uint8_t eos_byte, int compare_8_bits) { struct tnt4882_priv *priv = board->private_data; return nec7210_enable_eos(board, &priv->nec7210_priv, eos_byte, compare_8_bits); } -void tnt4882_disable_eos(gpib_board_t *board) +static void tnt4882_disable_eos(struct gpib_board *board) { struct tnt4882_priv *priv = board->private_data; nec7210_disable_eos(board, &priv->nec7210_priv); } -unsigned int tnt4882_update_status(gpib_board_t *board, unsigned int clear_mask) +static unsigned int tnt4882_update_status(struct gpib_board *board, unsigned int clear_mask) { unsigned long flags; u8 line_status; - unsigned int retval; struct tnt4882_priv *priv = board->private_data; spin_lock_irqsave(&board->spinlock, flags); board->status &= ~clear_mask; - retval = nec7210_update_status_nolock(board, &priv->nec7210_priv); + nec7210_update_status_nolock(board, &priv->nec7210_priv); /* set / clear SRQ state since it is not cleared by interrupt */ line_status = tnt_readb(priv, BSR); if (line_status & BCSR_SRQ_BIT) @@ -775,22 +704,21 @@ unsigned int tnt4882_update_status(gpib_board_t *board, unsigned int clear_mask) return board->status; } -int tnt4882_primary_address(gpib_board_t *board, unsigned int address) +static int tnt4882_primary_address(struct gpib_board *board, unsigned int address) { struct tnt4882_priv *priv = board->private_data; return nec7210_primary_address(board, &priv->nec7210_priv, address); } -int tnt4882_secondary_address(gpib_board_t *board, unsigned int address, int enable) +static int tnt4882_secondary_address(struct gpib_board *board, unsigned int address, int enable) { struct tnt4882_priv *priv = board->private_data; return nec7210_secondary_address(board, &priv->nec7210_priv, address, enable); } -int tnt4882_parallel_poll(gpib_board_t *board, uint8_t *result) - +static int tnt4882_parallel_poll(struct gpib_board *board, uint8_t *result) { struct tnt4882_priv *tnt_priv = board->private_data; @@ -807,7 +735,7 @@ int tnt4882_parallel_poll(gpib_board_t *board, uint8_t *result) } } -void tnt4882_parallel_poll_configure(gpib_board_t *board, uint8_t config) +static void tnt4882_parallel_poll_configure(struct gpib_board *board, uint8_t config) { struct tnt4882_priv *priv = board->private_data; @@ -825,7 +753,7 @@ void tnt4882_parallel_poll_configure(gpib_board_t *board, uint8_t config) } } -void tnt4882_parallel_poll_response(gpib_board_t *board, int ist) +static void tnt4882_parallel_poll_response(struct gpib_board *board, int ist) { struct tnt4882_priv *priv = board->private_data; @@ -835,14 +763,14 @@ void tnt4882_parallel_poll_response(gpib_board_t *board, int ist) /* this is just used by the old nec7210 isa interfaces, the newer * boards use tnt4882_serial_poll_response2 */ -void tnt4882_serial_poll_response(gpib_board_t *board, uint8_t status) +static void tnt4882_serial_poll_response(struct gpib_board *board, uint8_t status) { struct tnt4882_priv *priv = board->private_data; nec7210_serial_poll_response(board, &priv->nec7210_priv, status); } -static void tnt4882_serial_poll_response2(gpib_board_t *board, uint8_t status, +static void tnt4882_serial_poll_response2(struct gpib_board *board, uint8_t status, int new_reason_for_service) { struct tnt4882_priv *priv = board->private_data; @@ -876,20 +804,318 @@ static void tnt4882_serial_poll_response2(gpib_board_t *board, uint8_t status, spin_unlock_irqrestore(&board->spinlock, flags); } -uint8_t tnt4882_serial_poll_status(gpib_board_t *board) +static uint8_t tnt4882_serial_poll_status(struct gpib_board *board) { struct tnt4882_priv *priv = board->private_data; return nec7210_serial_poll_status(board, &priv->nec7210_priv); } -void tnt4882_return_to_local(gpib_board_t *board) +static void tnt4882_return_to_local(struct gpib_board *board) { struct tnt4882_priv *priv = board->private_data; nec7210_return_to_local(board, &priv->nec7210_priv); } +static void tnt4882_board_reset(struct tnt4882_priv *tnt_priv, struct gpib_board *board) +{ + struct nec7210_priv *nec_priv = &tnt_priv->nec7210_priv; + + tnt_priv->imr0_bits = 0; + tnt_writeb(tnt_priv, tnt_priv->imr0_bits, IMR0); + tnt_priv->imr3_bits = 0; + tnt_writeb(tnt_priv, tnt_priv->imr3_bits, IMR3); + tnt_readb(tnt_priv, IMR0); + tnt_readb(tnt_priv, IMR3); + nec7210_board_reset(nec_priv, board); +} + +static int tnt4882_allocate_private(struct gpib_board *board) +{ + struct tnt4882_priv *tnt_priv; + + board->private_data = kmalloc(sizeof(struct tnt4882_priv), GFP_KERNEL); + if (!board->private_data) + return -1; + tnt_priv = board->private_data; + memset(tnt_priv, 0, sizeof(struct tnt4882_priv)); + init_nec7210_private(&tnt_priv->nec7210_priv); + return 0; +} + +static void tnt4882_free_private(struct gpib_board *board) +{ + kfree(board->private_data); + board->private_data = NULL; +} + +static void tnt4882_init(struct tnt4882_priv *tnt_priv, const struct gpib_board *board) +{ + struct nec7210_priv *nec_priv = &tnt_priv->nec7210_priv; + + /* Turbo488 software reset */ + tnt_writeb(tnt_priv, SOFT_RESET, CMDR); + udelay(1); + + // turn off one-chip mode + tnt_writeb(tnt_priv, NODMA, HSSEL); + tnt_writeb(tnt_priv, 0, ACCWR); + // make sure we are in 7210 mode + tnt_writeb(tnt_priv, AUX_7210, AUXCR); + udelay(1); + // registers might be swapped, so write it to the swapped address too + tnt_writeb(tnt_priv, AUX_7210, SWAPPED_AUXCR); + udelay(1); + // turn on one-chip mode + if (nec_priv->type == TNT4882 || nec_priv->type == TNT5004) + tnt_writeb(tnt_priv, NODMA | TNT_ONE_CHIP_BIT, HSSEL); + else + tnt_writeb(tnt_priv, NODMA, HSSEL); + + nec7210_board_reset(nec_priv, board); + // read-clear isr0 + tnt_readb(tnt_priv, ISR0); + + // enable passing of nat4882 interrupts + tnt_priv->imr3_bits = HR_TLCI; + tnt_writeb(tnt_priv, tnt_priv->imr3_bits, IMR3); + + // enable interrupt + tnt_writeb(tnt_priv, 0x1, INTRT); + + // force immediate holdoff + write_byte(&tnt_priv->nec7210_priv, AUX_HLDI, AUXMR); + + set_bit(RFD_HOLDOFF_BN, &nec_priv->state); + + tnt_priv->auxg_bits = AUXRG | NTNL_BIT; + write_byte(&tnt_priv->nec7210_priv, tnt_priv->auxg_bits, AUXMR); + + nec7210_board_online(nec_priv, board); + // enable interface clear interrupt for event queue + tnt_priv->imr0_bits = TNT_IMR0_ALWAYS_BITS | TNT_ATNI_BIT | TNT_IFCIE_BIT; + tnt_writeb(tnt_priv, tnt_priv->imr0_bits, IMR0); +} + +static int ni_pci_attach(struct gpib_board *board, const gpib_board_config_t *config) +{ + struct tnt4882_priv *tnt_priv; + struct nec7210_priv *nec_priv; + int isr_flags = IRQF_SHARED; + int retval; + struct mite_struct *mite; + + board->status = 0; + + if (tnt4882_allocate_private(board)) + return -ENOMEM; + tnt_priv = board->private_data; + nec_priv = &tnt_priv->nec7210_priv; + nec_priv->type = TNT4882; + nec_priv->read_byte = nec7210_locking_iomem_read_byte; + nec_priv->write_byte = nec7210_locking_iomem_write_byte; + nec_priv->offset = atgpib_reg_offset; + + if (!mite_devices) + return -ENODEV; + + for (mite = mite_devices; mite; mite = mite->next) { + short found_board; + + if (mite->used) + continue; + if (config->pci_bus >= 0 && config->pci_bus != mite->pcidev->bus->number) + continue; + if (config->pci_slot >= 0 && config->pci_slot != PCI_SLOT(mite->pcidev->devfn)) + continue; + switch (mite_device_id(mite)) { + case PCI_DEVICE_ID_NI_GPIB: + case PCI_DEVICE_ID_NI_GPIB_PLUS: + case PCI_DEVICE_ID_NI_GPIB_PLUS2: + case PCI_DEVICE_ID_NI_PXIGPIB: + case PCI_DEVICE_ID_NI_PMCGPIB: + case PCI_DEVICE_ID_NI_PCIEGPIB: + case PCI_DEVICE_ID_NI_PCIE2GPIB: +// support for Measurement Computing PCI-488 + case PCI_DEVICE_ID_MC_PCI488: + case PCI_DEVICE_ID_CEC_NI_GPIB: + found_board = 1; + break; + default: + found_board = 0; + break; + } + if (found_board) + break; + } + if (!mite) + return -ENODEV; + + tnt_priv->mite = mite; + retval = mite_setup(tnt_priv->mite); + if (retval < 0) + return retval; + + nec_priv->mmiobase = tnt_priv->mite->daq_io_addr; + + // get irq + retval = request_irq(mite_irq(tnt_priv->mite), tnt4882_interrupt, isr_flags, "ni-pci-gpib", + board); + if (retval) { + dev_err(board->gpib_dev, "failed to obtain pci irq %d\n", mite_irq(tnt_priv->mite)); + return retval; + } + tnt_priv->irq = mite_irq(tnt_priv->mite); + + // TNT5004 detection + switch (tnt_readb(tnt_priv, CSR) & 0xf0) { + case 0x30: + nec_priv->type = TNT4882; + break; + case 0x40: + nec_priv->type = TNT5004; + break; + } + tnt4882_init(tnt_priv, board); + + return 0; +} + +static void ni_pci_detach(struct gpib_board *board) +{ + struct tnt4882_priv *tnt_priv = board->private_data; + struct nec7210_priv *nec_priv; + + if (tnt_priv) { + nec_priv = &tnt_priv->nec7210_priv; + + if (nec_priv->mmiobase) + tnt4882_board_reset(tnt_priv, board); + if (tnt_priv->irq) + free_irq(tnt_priv->irq, board); + if (tnt_priv->mite) + mite_unsetup(tnt_priv->mite); + } + tnt4882_free_private(board); +} + +static int ni_isapnp_find(struct pnp_dev **dev) +{ + *dev = pnp_find_dev(NULL, ISAPNP_VENDOR_ID_NI, + ISAPNP_FUNCTION(ISAPNP_ID_NI_ATGPIB_TNT), NULL); + if (!*dev || !(*dev)->card) + return -ENODEV; + if (pnp_device_attach(*dev) < 0) + return -EBUSY; + if (pnp_activate_dev(*dev) < 0) { + pnp_device_detach(*dev); + return -EAGAIN; + } + if (!pnp_port_valid(*dev, 0) || !pnp_irq_valid(*dev, 0)) { + pnp_device_detach(*dev); + return -EINVAL; + } + return 0; +} + +static int ni_isa_attach_common(struct gpib_board *board, const gpib_board_config_t *config, + enum nec7210_chipset chipset) +{ + struct tnt4882_priv *tnt_priv; + struct nec7210_priv *nec_priv; + int isr_flags = 0; + u32 iobase; + int irq; + int retval; + + board->status = 0; + + if (tnt4882_allocate_private(board)) + return -ENOMEM; + tnt_priv = board->private_data; + nec_priv = &tnt_priv->nec7210_priv; + nec_priv->type = chipset; + nec_priv->read_byte = nec7210_locking_ioport_read_byte; + nec_priv->write_byte = nec7210_locking_ioport_write_byte; + nec_priv->offset = atgpib_reg_offset; + + // look for plug-n-play board + if (config->ibbase == 0) { + struct pnp_dev *dev; + + retval = ni_isapnp_find(&dev); + if (retval < 0) + return retval; + tnt_priv->pnp_dev = dev; + iobase = pnp_port_start(dev, 0); + irq = pnp_irq(dev, 0); + } else { + iobase = config->ibbase; + irq = config->ibirq; + } + // allocate ioports + if (!request_region(iobase, atgpib_iosize, "atgpib")) + return -EBUSY; + + nec_priv->mmiobase = ioport_map(iobase, atgpib_iosize); + if (!nec_priv->mmiobase) + return -EBUSY; + + // get irq + retval = request_irq(irq, tnt4882_interrupt, isr_flags, "atgpib", board); + if (retval) { + dev_err(board->gpib_dev, "failed to request ISA irq %d\n", irq); + return retval; + } + tnt_priv->irq = irq; + + tnt4882_init(tnt_priv, board); + + return 0; +} + +static int ni_tnt_isa_attach(struct gpib_board *board, const gpib_board_config_t *config) +{ + return ni_isa_attach_common(board, config, TNT4882); +} + +static int ni_nat4882_isa_attach(struct gpib_board *board, const gpib_board_config_t *config) +{ + return ni_isa_attach_common(board, config, NAT4882); +} + +static int ni_nec_isa_attach(struct gpib_board *board, const gpib_board_config_t *config) +{ + return ni_isa_attach_common(board, config, NEC7210); +} + +static void ni_isa_detach(struct gpib_board *board) +{ + struct tnt4882_priv *tnt_priv = board->private_data; + struct nec7210_priv *nec_priv; + + if (tnt_priv) { + nec_priv = &tnt_priv->nec7210_priv; + if (nec_priv->iobase) + tnt4882_board_reset(tnt_priv, board); + if (tnt_priv->irq) + free_irq(tnt_priv->irq, board); + if (nec_priv->mmiobase) + ioport_unmap(nec_priv->mmiobase); + if (nec_priv->iobase) + release_region(nec_priv->iobase, atgpib_iosize); + if (tnt_priv->pnp_dev) + pnp_device_detach(tnt_priv->pnp_dev); + } + tnt4882_free_private(board); +} + +static int tnt4882_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) +{ + return 0; +} + static gpib_interface_t ni_pci_interface = { .name = "ni_pci", .attach = ni_pci_attach, @@ -1114,7 +1340,435 @@ static gpib_interface_t ni_nec_isa_accel_interface = { .return_to_local = tnt4882_return_to_local, }; -#ifdef GPIB_PCMCIA +static const struct pci_device_id tnt4882_pci_table[] = { + {PCI_DEVICE(PCI_VENDOR_ID_NATINST, PCI_DEVICE_ID_NI_GPIB)}, + {PCI_DEVICE(PCI_VENDOR_ID_NATINST, PCI_DEVICE_ID_NI_GPIB_PLUS)}, + {PCI_DEVICE(PCI_VENDOR_ID_NATINST, PCI_DEVICE_ID_NI_GPIB_PLUS2)}, + {PCI_DEVICE(PCI_VENDOR_ID_NATINST, PCI_DEVICE_ID_NI_PXIGPIB)}, + {PCI_DEVICE(PCI_VENDOR_ID_NATINST, PCI_DEVICE_ID_NI_PMCGPIB)}, + {PCI_DEVICE(PCI_VENDOR_ID_NATINST, PCI_DEVICE_ID_NI_PCIEGPIB)}, + {PCI_DEVICE(PCI_VENDOR_ID_NATINST, PCI_DEVICE_ID_NI_PCIE2GPIB)}, + // support for Measurement Computing PCI-488 + {PCI_DEVICE(PCI_VENDOR_ID_NATINST, PCI_DEVICE_ID_MC_PCI488)}, + {PCI_DEVICE(PCI_VENDOR_ID_NATINST, PCI_DEVICE_ID_CEC_NI_GPIB)}, + { 0 } +}; +MODULE_DEVICE_TABLE(pci, tnt4882_pci_table); + +static struct pci_driver tnt4882_pci_driver = { + .name = DRV_NAME, + .id_table = tnt4882_pci_table, + .probe = &tnt4882_pci_probe +}; + +#if 0 +/* unused, will be needed when the driver is turned into a pnp_driver */ +static const struct pnp_device_id tnt4882_pnp_table[] = { + {.id = "NICC601"}, + {.id = ""} +}; +MODULE_DEVICE_TABLE(pnp, tnt4882_pnp_table); +#endif + +#ifdef CONFIG_GPIB_PCMCIA +static gpib_interface_t ni_pcmcia_interface; +static gpib_interface_t ni_pcmcia_accel_interface; +static int __init init_ni_gpib_cs(void); +static void __exit exit_ni_gpib_cs(void); +#endif + +static int __init tnt4882_init_module(void) +{ + int result; + + result = pci_register_driver(&tnt4882_pci_driver); + if (result) { + pr_err("pci_register_driver failed: error = %d\n", result); + return result; + } + + result = gpib_register_driver(&ni_isa_interface, THIS_MODULE); + if (result) { + pr_err("gpib_register_driver failed: error = %d\n", result); + goto err_isa; + } + + result = gpib_register_driver(&ni_isa_accel_interface, THIS_MODULE); + if (result) { + pr_err("gpib_register_driver failed: error = %d\n", result); + goto err_isa_accel; + } + + result = gpib_register_driver(&ni_nat4882_isa_interface, THIS_MODULE); + if (result) { + pr_err("gpib_register_driver failed: error = %d\n", result); + goto err_nat4882_isa; + } + + result = gpib_register_driver(&ni_nat4882_isa_accel_interface, THIS_MODULE); + if (result) { + pr_err("gpib_register_driver failed: error = %d\n", result); + goto err_nat4882_isa_accel; + } + + result = gpib_register_driver(&ni_nec_isa_interface, THIS_MODULE); + if (result) { + pr_err("gpib_register_driver failed: error = %d\n", result); + goto err_nec_isa; + } + + result = gpib_register_driver(&ni_nec_isa_accel_interface, THIS_MODULE); + if (result) { + pr_err("gpib_register_driver failed: error = %d\n", result); + goto err_nec_isa_accel; + } + + result = gpib_register_driver(&ni_pci_interface, THIS_MODULE); + if (result) { + pr_err("gpib_register_driver failed: error = %d\n", result); + goto err_pci; + } + + result = gpib_register_driver(&ni_pci_accel_interface, THIS_MODULE); + if (result) { + pr_err("gpib_register_driver failed: error = %d\n", result); + goto err_pci_accel; + } + +#ifdef CONFIG_GPIB_PCMCIA + result = gpib_register_driver(&ni_pcmcia_interface, THIS_MODULE); + if (result) { + pr_err("gpib_register_driver failed: error = %d\n", result); + goto err_pcmcia; + } + + result = gpib_register_driver(&ni_pcmcia_accel_interface, THIS_MODULE); + if (result) { + pr_err("gpib_register_driver failed: error = %d\n", result); + goto err_pcmcia_accel; + } + + result = init_ni_gpib_cs(); + if (result) { + pr_err("pcmcia_register_driver failed: error = %d\n", result); + goto err_pcmcia_driver; + } +#endif + + mite_init(); + + return 0; + +#ifdef CONFIG_GPIB_PCMCIA +err_pcmcia_driver: + gpib_unregister_driver(&ni_pcmcia_accel_interface); +err_pcmcia_accel: + gpib_unregister_driver(&ni_pcmcia_interface); +err_pcmcia: +#endif + gpib_unregister_driver(&ni_pci_accel_interface); +err_pci_accel: + gpib_unregister_driver(&ni_pci_interface); +err_pci: + gpib_unregister_driver(&ni_nec_isa_accel_interface); +err_nec_isa_accel: + gpib_unregister_driver(&ni_nec_isa_interface); +err_nec_isa: + gpib_unregister_driver(&ni_nat4882_isa_accel_interface); +err_nat4882_isa_accel: + gpib_unregister_driver(&ni_nat4882_isa_interface); +err_nat4882_isa: + gpib_unregister_driver(&ni_isa_accel_interface); +err_isa_accel: + gpib_unregister_driver(&ni_isa_interface); +err_isa: + pci_unregister_driver(&tnt4882_pci_driver); + + return result; +} + +static void __exit tnt4882_exit_module(void) +{ + gpib_unregister_driver(&ni_isa_interface); + gpib_unregister_driver(&ni_isa_accel_interface); + gpib_unregister_driver(&ni_nat4882_isa_interface); + gpib_unregister_driver(&ni_nat4882_isa_accel_interface); + gpib_unregister_driver(&ni_nec_isa_interface); + gpib_unregister_driver(&ni_nec_isa_accel_interface); + gpib_unregister_driver(&ni_pci_interface); + gpib_unregister_driver(&ni_pci_accel_interface); +#ifdef CONFIG_GPIB_PCMCIA + gpib_unregister_driver(&ni_pcmcia_interface); + gpib_unregister_driver(&ni_pcmcia_accel_interface); + exit_ni_gpib_cs(); +#endif + + mite_cleanup(); + + pci_unregister_driver(&tnt4882_pci_driver); +} + +#ifdef CONFIG_GPIB_PCMCIA + +#include <linux/kernel.h> +#include <linux/moduleparam.h> +#include <linux/ptrace.h> +#include <linux/timer.h> +#include <linux/ioport.h> +#include <linux/io.h> + +#include <pcmcia/cistpl.h> +#include <pcmcia/cisreg.h> +#include <pcmcia/ds.h> + +static int ni_gpib_config(struct pcmcia_device *link); +static void ni_gpib_release(struct pcmcia_device *link); +static void ni_pcmcia_detach(struct gpib_board *board); + +/* + * A linked list of "instances" of the dummy device. Each actual + * PCMCIA card corresponds to one device instance, and is described + * by one dev_link_t structure (defined in ds.h). + * + * You may not want to use a linked list for this -- for example, the + * memory card driver uses an array of dev_link_t pointers, where minor + * device numbers are used to derive the corresponding array index. + * + * I think this dev_list is obsolete but the pointer is needed to keep + * the module instance for the ni_pcmcia_attach function. + */ + +static struct pcmcia_device *curr_dev; + +struct local_info_t { + struct pcmcia_device *p_dev; + struct gpib_board *dev; + int stop; + struct bus_operations *bus; +}; + +/* + * ni_gpib_probe() creates an "instance" of the driver, allocating + * local data structures for one device. The device is registered + * with Card Services. + */ + +static int ni_gpib_probe(struct pcmcia_device *link) +{ + struct local_info_t *info; + //struct struct gpib_board *dev; + + /* Allocate space for private device-specific data */ + info = kzalloc(sizeof(*info), GFP_KERNEL); + if (!info) + return -ENOMEM; + + info->p_dev = link; + link->priv = info; + + /* + * General socket configuration defaults can go here. In this + * client, we assume very little, and rely on the CIS for almost + * everything. In most clients, many details (i.e., number, sizes, + * and attributes of IO windows) are fixed by the nature of the + * device, and can be hard-wired here. + */ + link->config_flags = CONF_ENABLE_IRQ | CONF_AUTO_SET_IO; + + /* Register with Card Services */ + curr_dev = link; + return ni_gpib_config(link); +} + +/* + * This deletes a driver "instance". The device is de-registered + * with Card Services. If it has been released, all local data + * structures are freed. Otherwise, the structures will be freed + * when the device is released. + */ +static void ni_gpib_remove(struct pcmcia_device *link) +{ + struct local_info_t *info = link->priv; + //struct struct gpib_board *dev = info->dev; + + if (info->dev) + ni_pcmcia_detach(info->dev); + ni_gpib_release(link); + + //free_netdev(dev); + kfree(info); +} + +static int ni_gpib_config_iteration(struct pcmcia_device *link, void *priv_data) +{ + int retval; + + retval = pcmcia_request_io(link); + if (retval != 0) + return retval; + + return 0; +} + +/* + * ni_gpib_config() is scheduled to run after a CARD_INSERTION event + * is received, to configure the PCMCIA socket, and to make the + * device available to the system. + */ +static int ni_gpib_config(struct pcmcia_device *link) +{ + //struct local_info_t *info = link->priv; + //struct gpib_board *dev = info->dev; + int last_ret; + + last_ret = pcmcia_loop_config(link, &ni_gpib_config_iteration, NULL); + if (last_ret) { + dev_warn(&link->dev, "no configuration found\n"); + ni_gpib_release(link); + return last_ret; + } + + last_ret = pcmcia_enable_device(link); + if (last_ret) { + ni_gpib_release(link); + return last_ret; + } + return 0; +} /* ni_gpib_config */ + +/* + * After a card is removed, ni_gpib_release() will unregister the + * device, and release the PCMCIA configuration. If the device is + * still open, this will be postponed until it is closed. + */ +static void ni_gpib_release(struct pcmcia_device *link) +{ + pcmcia_disable_device(link); +} /* ni_gpib_release */ + +static int ni_gpib_suspend(struct pcmcia_device *link) +{ + //struct local_info_t *info = link->priv; + //struct struct gpib_board *dev = info->dev; + + if (link->open) + dev_warn(&link->dev, "Device still open\n"); + //netif_device_detach(dev); + + return 0; +} + +static int ni_gpib_resume(struct pcmcia_device *link) +{ + //struct local_info_t *info = link->priv; + //struct struct gpib_board *dev = info->dev; + + /*if (link->open) { + * ni_gpib_probe(dev); / really? + * //netif_device_attach(dev); + *} + */ + return ni_gpib_config(link); +} + +static struct pcmcia_device_id ni_pcmcia_ids[] = { + PCMCIA_DEVICE_MANF_CARD(0x010b, 0x4882), + PCMCIA_DEVICE_MANF_CARD(0x010b, 0x0c71), // NI PCMCIA-GPIB+ + PCMCIA_DEVICE_NULL +}; + +MODULE_DEVICE_TABLE(pcmcia, ni_pcmcia_ids); + +static struct pcmcia_driver ni_gpib_cs_driver = { + .name = "ni_gpib_cs", + .owner = THIS_MODULE, + .drv = { .name = "ni_gpib_cs", }, + .id_table = ni_pcmcia_ids, + .probe = ni_gpib_probe, + .remove = ni_gpib_remove, + .suspend = ni_gpib_suspend, + .resume = ni_gpib_resume, +}; + +static int __init init_ni_gpib_cs(void) +{ + return pcmcia_register_driver(&ni_gpib_cs_driver); +} + +static void __exit exit_ni_gpib_cs(void) +{ + pcmcia_unregister_driver(&ni_gpib_cs_driver); +} + +static const int pcmcia_gpib_iosize = 32; + +static int ni_pcmcia_attach(struct gpib_board *board, const gpib_board_config_t *config) +{ + struct local_info_t *info; + struct tnt4882_priv *tnt_priv; + struct nec7210_priv *nec_priv; + int isr_flags = IRQF_SHARED; + int retval; + + if (!curr_dev) + return -ENODEV; + + info = curr_dev->priv; + info->dev = board; + + board->status = 0; + + if (tnt4882_allocate_private(board)) + return -ENOMEM; + + tnt_priv = board->private_data; + nec_priv = &tnt_priv->nec7210_priv; + nec_priv->type = TNT4882; + nec_priv->read_byte = nec7210_locking_ioport_read_byte; + nec_priv->write_byte = nec7210_locking_ioport_write_byte; + nec_priv->offset = atgpib_reg_offset; + + if (!request_region(curr_dev->resource[0]->start, resource_size(curr_dev->resource[0]), + DRV_NAME)) + return -ENOMEM; + + nec_priv->mmiobase = ioport_map(curr_dev->resource[0]->start, + resource_size(curr_dev->resource[0])); + if (!nec_priv->mmiobase) + return -ENOMEM; + + // get irq + retval = request_irq(curr_dev->irq, tnt4882_interrupt, isr_flags, DRV_NAME, board); + if (retval) { + dev_err(board->gpib_dev, "failed to obtain PCMCIA irq %d\n", curr_dev->irq); + return retval; + } + tnt_priv->irq = curr_dev->irq; + + tnt4882_init(tnt_priv, board); + + return 0; +} + +static void ni_pcmcia_detach(struct gpib_board *board) +{ + struct tnt4882_priv *tnt_priv = board->private_data; + struct nec7210_priv *nec_priv; + + if (tnt_priv) { + nec_priv = &tnt_priv->nec7210_priv; + if (tnt_priv->irq) + free_irq(tnt_priv->irq, board); + if (nec_priv->mmiobase) + ioport_unmap(nec_priv->mmiobase); + if (nec_priv->iobase) { + tnt4882_board_reset(tnt_priv, board); + release_region(nec_priv->iobase, pcmcia_gpib_iosize); + } + } + tnt4882_free_private(board); +} + static gpib_interface_t ni_pcmcia_interface = { .name = "ni_pcmcia", .attach = ni_pcmcia_attach, @@ -1170,778 +1824,8 @@ static gpib_interface_t ni_pcmcia_accel_interface = { .t1_delay = tnt4882_t1_delay, .return_to_local = tnt4882_return_to_local, }; -#endif -void tnt4882_board_reset(struct tnt4882_priv *tnt_priv, gpib_board_t *board) -{ - struct nec7210_priv *nec_priv = &tnt_priv->nec7210_priv; - - tnt_priv->imr0_bits = 0; - tnt_writeb(tnt_priv, tnt_priv->imr0_bits, IMR0); - tnt_priv->imr3_bits = 0; - tnt_writeb(tnt_priv, tnt_priv->imr3_bits, IMR3); - tnt_readb(tnt_priv, IMR0); - tnt_readb(tnt_priv, IMR3); - nec7210_board_reset(nec_priv, board); -} - -int tnt4882_allocate_private(gpib_board_t *board) -{ - struct tnt4882_priv *tnt_priv; - - board->private_data = kmalloc(sizeof(struct tnt4882_priv), GFP_KERNEL); - if (!board->private_data) - return -1; - tnt_priv = board->private_data; - memset(tnt_priv, 0, sizeof(struct tnt4882_priv)); - init_nec7210_private(&tnt_priv->nec7210_priv); - return 0; -} - -void tnt4882_free_private(gpib_board_t *board) -{ - kfree(board->private_data); - board->private_data = NULL; -} - -void tnt4882_init(struct tnt4882_priv *tnt_priv, const gpib_board_t *board) -{ - struct nec7210_priv *nec_priv = &tnt_priv->nec7210_priv; - - /* Turbo488 software reset */ - tnt_writeb(tnt_priv, SOFT_RESET, CMDR); - udelay(1); - - // turn off one-chip mode - tnt_writeb(tnt_priv, NODMA, HSSEL); - tnt_writeb(tnt_priv, 0, ACCWR); - // make sure we are in 7210 mode - tnt_writeb(tnt_priv, AUX_7210, AUXCR); - udelay(1); - // registers might be swapped, so write it to the swapped address too - tnt_writeb(tnt_priv, AUX_7210, SWAPPED_AUXCR); - udelay(1); - // turn on one-chip mode - if (nec_priv->type == TNT4882 || nec_priv->type == TNT5004) - tnt_writeb(tnt_priv, NODMA | TNT_ONE_CHIP_BIT, HSSEL); - else - tnt_writeb(tnt_priv, NODMA, HSSEL); - - nec7210_board_reset(nec_priv, board); - // read-clear isr0 - tnt_readb(tnt_priv, ISR0); - - // enable passing of nat4882 interrupts - tnt_priv->imr3_bits = HR_TLCI; - tnt_writeb(tnt_priv, tnt_priv->imr3_bits, IMR3); - - // enable interrupt - tnt_writeb(tnt_priv, 0x1, INTRT); - - // force immediate holdoff - write_byte(&tnt_priv->nec7210_priv, AUX_HLDI, AUXMR); - - set_bit(RFD_HOLDOFF_BN, &nec_priv->state); - - tnt_priv->auxg_bits = AUXRG | NTNL_BIT; - write_byte(&tnt_priv->nec7210_priv, tnt_priv->auxg_bits, AUXMR); - - nec7210_board_online(nec_priv, board); - // enable interface clear interrupt for event queue - tnt_priv->imr0_bits = TNT_IMR0_ALWAYS_BITS | TNT_ATNI_BIT | TNT_IFCIE_BIT; - tnt_writeb(tnt_priv, tnt_priv->imr0_bits, IMR0); -} - -int ni_pci_attach(gpib_board_t *board, const gpib_board_config_t *config) -{ - struct tnt4882_priv *tnt_priv; - struct nec7210_priv *nec_priv; - int isr_flags = IRQF_SHARED; - int retval; - struct mite_struct *mite; - - board->status = 0; - - if (tnt4882_allocate_private(board)) - return -ENOMEM; - tnt_priv = board->private_data; - nec_priv = &tnt_priv->nec7210_priv; - nec_priv->type = TNT4882; - nec_priv->read_byte = nec7210_locking_iomem_read_byte; - nec_priv->write_byte = nec7210_locking_iomem_write_byte; - nec_priv->offset = atgpib_reg_offset; - - if (!mite_devices) { - pr_err("no National Instruments PCI boards found\n"); - return -1; - } - - for (mite = mite_devices; mite; mite = mite->next) { - short found_board; - - if (mite->used) - continue; - if (config->pci_bus >= 0 && config->pci_bus != mite->pcidev->bus->number) - continue; - if (config->pci_slot >= 0 && config->pci_slot != PCI_SLOT(mite->pcidev->devfn)) - continue; - switch (mite_device_id(mite)) { - case PCI_DEVICE_ID_NI_GPIB: - case PCI_DEVICE_ID_NI_GPIB_PLUS: - case PCI_DEVICE_ID_NI_GPIB_PLUS2: - case PCI_DEVICE_ID_NI_PXIGPIB: - case PCI_DEVICE_ID_NI_PMCGPIB: - case PCI_DEVICE_ID_NI_PCIEGPIB: - case PCI_DEVICE_ID_NI_PCIE2GPIB: -// support for Measurement Computing PCI-488 - case PCI_DEVICE_ID_MC_PCI488: - case PCI_DEVICE_ID_CEC_NI_GPIB: - found_board = 1; - break; - default: - found_board = 0; - break; - } - if (found_board) - break; - } - if (!mite) { - pr_err("no NI PCI-GPIB boards found\n"); - return -1; - } - tnt_priv->mite = mite; - retval = mite_setup(tnt_priv->mite); - if (retval < 0) { - pr_err("tnt4882: error setting up mite.\n"); - return retval; - } - - nec_priv->mmiobase = tnt_priv->mite->daq_io_addr; - - // get irq - if (request_irq(mite_irq(tnt_priv->mite), tnt4882_interrupt, isr_flags, - "ni-pci-gpib", board)) { - pr_err("gpib: can't request IRQ %d\n", mite_irq(tnt_priv->mite)); - return -1; - } - tnt_priv->irq = mite_irq(tnt_priv->mite); - pr_info("tnt4882: irq %i\n", tnt_priv->irq); - - // TNT5004 detection - switch (tnt_readb(tnt_priv, CSR) & 0xf0) { - case 0x30: - nec_priv->type = TNT4882; - pr_info("tnt4882: TNT4882 chipset detected\n"); - break; - case 0x40: - nec_priv->type = TNT5004; - pr_info("tnt4882: TNT5004 chipset detected\n"); - break; - } - tnt4882_init(tnt_priv, board); - - return 0; -} - -void ni_pci_detach(gpib_board_t *board) -{ - struct tnt4882_priv *tnt_priv = board->private_data; - struct nec7210_priv *nec_priv; - - if (tnt_priv) { - nec_priv = &tnt_priv->nec7210_priv; - - if (nec_priv->mmiobase) - tnt4882_board_reset(tnt_priv, board); - if (tnt_priv->irq) - free_irq(tnt_priv->irq, board); - if (tnt_priv->mite) - mite_unsetup(tnt_priv->mite); - } - tnt4882_free_private(board); -} - -static int ni_isapnp_find(struct pnp_dev **dev) -{ - *dev = pnp_find_dev(NULL, ISAPNP_VENDOR_ID_NI, - ISAPNP_FUNCTION(ISAPNP_ID_NI_ATGPIB_TNT), NULL); - if (!*dev || !(*dev)->card) { - pr_err("tnt4882: failed to find isapnp board\n"); - return -ENODEV; - } - if (pnp_device_attach(*dev) < 0) { - pr_err("tnt4882: atgpib/tnt board already active, skipping\n"); - return -EBUSY; - } - if (pnp_activate_dev(*dev) < 0) { - pnp_device_detach(*dev); - pr_err("tnt4882: failed to activate() atgpib/tnt, aborting\n"); - return -EAGAIN; - } - if (!pnp_port_valid(*dev, 0) || !pnp_irq_valid(*dev, 0)) { - pnp_device_detach(*dev); - pr_err("tnt4882: invalid port or irq for atgpib/tnt, aborting\n"); - return -ENOMEM; - } - return 0; -} - -static int ni_isa_attach_common(gpib_board_t *board, const gpib_board_config_t *config, - enum nec7210_chipset chipset) -{ - struct tnt4882_priv *tnt_priv; - struct nec7210_priv *nec_priv; - int isr_flags = 0; - u32 iobase; - int irq; - - board->status = 0; - - if (tnt4882_allocate_private(board)) - return -ENOMEM; - tnt_priv = board->private_data; - nec_priv = &tnt_priv->nec7210_priv; - nec_priv->type = chipset; - nec_priv->read_byte = nec7210_locking_ioport_read_byte; - nec_priv->write_byte = nec7210_locking_ioport_write_byte; - nec_priv->offset = atgpib_reg_offset; - - // look for plug-n-play board - if (config->ibbase == 0) { - struct pnp_dev *dev; - int retval; - - retval = ni_isapnp_find(&dev); - if (retval < 0) - return retval; - tnt_priv->pnp_dev = dev; - iobase = pnp_port_start(dev, 0); - irq = pnp_irq(dev, 0); - } else { - iobase = config->ibbase; - irq = config->ibirq; - } - // allocate ioports - if (!request_region(iobase, atgpib_iosize, "atgpib")) { - pr_err("tnt4882: failed to allocate ioports\n"); - return -1; - } - nec_priv->mmiobase = ioport_map(iobase, atgpib_iosize); - if (!nec_priv->mmiobase) - return -1; - - // get irq - if (request_irq(irq, tnt4882_interrupt, isr_flags, "atgpib", board)) { - pr_err("gpib: can't request IRQ %d\n", irq); - return -1; - } - tnt_priv->irq = irq; - - tnt4882_init(tnt_priv, board); - - return 0; -} - -int ni_tnt_isa_attach(gpib_board_t *board, const gpib_board_config_t *config) -{ - return ni_isa_attach_common(board, config, TNT4882); -} - -int ni_nat4882_isa_attach(gpib_board_t *board, const gpib_board_config_t *config) -{ - return ni_isa_attach_common(board, config, NAT4882); -} - -int ni_nec_isa_attach(gpib_board_t *board, const gpib_board_config_t *config) -{ - return ni_isa_attach_common(board, config, NEC7210); -} - -void ni_isa_detach(gpib_board_t *board) -{ - struct tnt4882_priv *tnt_priv = board->private_data; - struct nec7210_priv *nec_priv; - - if (tnt_priv) { - nec_priv = &tnt_priv->nec7210_priv; - if (nec_priv->iobase) - tnt4882_board_reset(tnt_priv, board); - if (tnt_priv->irq) - free_irq(tnt_priv->irq, board); - if (nec_priv->mmiobase) - ioport_unmap(nec_priv->mmiobase); - if (nec_priv->iobase) - release_region(nec_priv->iobase, atgpib_iosize); - if (tnt_priv->pnp_dev) - pnp_device_detach(tnt_priv->pnp_dev); - } - tnt4882_free_private(board); -} - -static int tnt4882_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) -{ - return 0; -} - -static const struct pci_device_id tnt4882_pci_table[] = { - {PCI_DEVICE(PCI_VENDOR_ID_NATINST, PCI_DEVICE_ID_NI_GPIB)}, - {PCI_DEVICE(PCI_VENDOR_ID_NATINST, PCI_DEVICE_ID_NI_GPIB_PLUS)}, - {PCI_DEVICE(PCI_VENDOR_ID_NATINST, PCI_DEVICE_ID_NI_GPIB_PLUS2)}, - {PCI_DEVICE(PCI_VENDOR_ID_NATINST, PCI_DEVICE_ID_NI_PXIGPIB)}, - {PCI_DEVICE(PCI_VENDOR_ID_NATINST, PCI_DEVICE_ID_NI_PMCGPIB)}, - {PCI_DEVICE(PCI_VENDOR_ID_NATINST, PCI_DEVICE_ID_NI_PCIEGPIB)}, - {PCI_DEVICE(PCI_VENDOR_ID_NATINST, PCI_DEVICE_ID_NI_PCIE2GPIB)}, - // support for Measurement Computing PCI-488 - {PCI_DEVICE(PCI_VENDOR_ID_NATINST, PCI_DEVICE_ID_MC_PCI488)}, - {PCI_DEVICE(PCI_VENDOR_ID_NATINST, PCI_DEVICE_ID_CEC_NI_GPIB)}, - { 0 } -}; -MODULE_DEVICE_TABLE(pci, tnt4882_pci_table); - -static struct pci_driver tnt4882_pci_driver = { - .name = "tnt4882", - .id_table = tnt4882_pci_table, - .probe = &tnt4882_pci_probe -}; - -static const struct pnp_device_id tnt4882_pnp_table[] = { - {.id = "NICC601"}, - {.id = ""} -}; -MODULE_DEVICE_TABLE(pnp, tnt4882_pnp_table); - -static int __init tnt4882_init_module(void) -{ - int result; - - result = pci_register_driver(&tnt4882_pci_driver); - if (result) { - pr_err("tnt4882_gpib: pci_register_driver failed: error = %d\n", result); - return result; - } - - result = gpib_register_driver(&ni_isa_interface, THIS_MODULE); - if (result) { - pr_err("tnt4882_gpib: gpib_register_driver failed: error = %d\n", result); - goto err_isa; - } - - result = gpib_register_driver(&ni_isa_accel_interface, THIS_MODULE); - if (result) { - pr_err("tnt4882_gpib: gpib_register_driver failed: error = %d\n", result); - goto err_isa_accel; - } - - result = gpib_register_driver(&ni_nat4882_isa_interface, THIS_MODULE); - if (result) { - pr_err("tnt4882_gpib: gpib_register_driver failed: error = %d\n", result); - goto err_nat4882_isa; - } - - result = gpib_register_driver(&ni_nat4882_isa_accel_interface, THIS_MODULE); - if (result) { - pr_err("tnt4882_gpib: gpib_register_driver failed: error = %d\n", result); - goto err_nat4882_isa_accel; - } - - result = gpib_register_driver(&ni_nec_isa_interface, THIS_MODULE); - if (result) { - pr_err("tnt4882_gpib: gpib_register_driver failed: error = %d\n", result); - goto err_nec_isa; - } - - result = gpib_register_driver(&ni_nec_isa_accel_interface, THIS_MODULE); - if (result) { - pr_err("tnt4882_gpib: gpib_register_driver failed: error = %d\n", result); - goto err_nec_isa_accel; - } - - result = gpib_register_driver(&ni_pci_interface, THIS_MODULE); - if (result) { - pr_err("tnt4882_gpib: gpib_register_driver failed: error = %d\n", result); - goto err_pci; - } - - result = gpib_register_driver(&ni_pci_accel_interface, THIS_MODULE); - if (result) { - pr_err("tnt4882_gpib: gpib_register_driver failed: error = %d\n", result); - goto err_pci_accel; - } - -#ifdef GPIB_PCMCIA - result = gpib_register_driver(&ni_pcmcia_interface, THIS_MODULE); - if (result) { - pr_err("tnt4882_gpib: gpib_register_driver failed: error = %d\n", result); - goto err_pcmcia; - } - - result = gpib_register_driver(&ni_pcmcia_accel_interface, THIS_MODULE); - if (result) { - pr_err("tnt4882_gpib: gpib_register_driver failed: error = %d\n", result); - goto err_pcmcia_accel; - } - - result = init_ni_gpib_cs(); - if (result) { - pr_err("tnt4882_gpib: pcmcia_register_driver failed: error = %d\n", result); - goto err_pcmcia_driver; - } -#endif - - mite_init(); - mite_list_devices(); - - return 0; - -#ifdef GPIB_PCMCIA -err_pcmcia_driver: - gpib_unregister_driver(&ni_pcmcia_accel_interface); -err_pcmcia_accel: - gpib_unregister_driver(&ni_pcmcia_interface); -err_pcmcia: -#endif - gpib_unregister_driver(&ni_pci_accel_interface); -err_pci_accel: - gpib_unregister_driver(&ni_pci_interface); -err_pci: - gpib_unregister_driver(&ni_nec_isa_accel_interface); -err_nec_isa_accel: - gpib_unregister_driver(&ni_nec_isa_interface); -err_nec_isa: - gpib_unregister_driver(&ni_nat4882_isa_accel_interface); -err_nat4882_isa_accel: - gpib_unregister_driver(&ni_nat4882_isa_interface); -err_nat4882_isa: - gpib_unregister_driver(&ni_isa_accel_interface); -err_isa_accel: - gpib_unregister_driver(&ni_isa_interface); -err_isa: - pci_unregister_driver(&tnt4882_pci_driver); - - return result; -} - -static void __exit tnt4882_exit_module(void) -{ - gpib_unregister_driver(&ni_isa_interface); - gpib_unregister_driver(&ni_isa_accel_interface); - gpib_unregister_driver(&ni_nat4882_isa_interface); - gpib_unregister_driver(&ni_nat4882_isa_accel_interface); - gpib_unregister_driver(&ni_nec_isa_interface); - gpib_unregister_driver(&ni_nec_isa_accel_interface); - gpib_unregister_driver(&ni_pci_interface); - gpib_unregister_driver(&ni_pci_accel_interface); -#ifdef GPIB_PCMCIA - gpib_unregister_driver(&ni_pcmcia_interface); - gpib_unregister_driver(&ni_pcmcia_accel_interface); - exit_ni_gpib_cs(); -#endif - - mite_cleanup(); - - pci_unregister_driver(&tnt4882_pci_driver); -} - -#ifdef GPIB_PCMCIA - -#include <linux/kernel.h> -#include <linux/moduleparam.h> -#include <linux/ptrace.h> -#include <linux/timer.h> -#include <linux/ioport.h> -#include <linux/io.h> - -#include <pcmcia/cistpl.h> -#include <pcmcia/cisreg.h> -#include <pcmcia/ds.h> - -/* - * All the PCMCIA modules use PCMCIA_DEBUG to control debugging. If - * you do not define PCMCIA_DEBUG at all, all the debug code will be - * left out. If you compile with PCMCIA_DEBUG=0, the debug code will - * be present but disabled -- but it can then be enabled for specific - * modules at load time with a 'pc_debug=#' option to insmod. - */ -#define PCMCIA_DEBUG 1 -#ifdef PCMCIA_DEBUG -static int pc_debug = PCMCIA_DEBUG; -module_param(pc_debug, int, 0); -#define DEBUG(n, args...) \ - do {if (pc_debug > (n)) \ - pr_debug(args); } \ - while (0) -#else -#define DEBUG(args...) -#endif - -static int ni_gpib_config(struct pcmcia_device *link); -static void ni_gpib_release(struct pcmcia_device *link); -static int ni_pcmcia_attach(gpib_board_t *board, const gpib_board_config_t *config); -static void ni_pcmcia_detach(gpib_board_t *board); - -/* - * A linked list of "instances" of the dummy device. Each actual - * PCMCIA card corresponds to one device instance, and is described - * by one dev_link_t structure (defined in ds.h). - * - * You may not want to use a linked list for this -- for example, the - * memory card driver uses an array of dev_link_t pointers, where minor - * device numbers are used to derive the corresponding array index. - * - * I think this dev_list is obsolete but the pointer is needed to keep - * the module instance for the ni_pcmcia_attach function. - */ - -static struct pcmcia_device *curr_dev; - -struct local_info_t { - struct pcmcia_device *p_dev; - gpib_board_t *dev; - int stop; - struct bus_operations *bus; -}; - -/* - * ni_gpib_probe() creates an "instance" of the driver, allocating - * local data structures for one device. The device is registered - * with Card Services. - */ - -static int ni_gpib_probe(struct pcmcia_device *link) -{ - struct local_info_t *info; - //struct gpib_board_t *dev; - - DEBUG(0, "%s(0x%p)\n", __func__, link); - - /* Allocate space for private device-specific data */ - info = kzalloc(sizeof(*info), GFP_KERNEL); - if (!info) - return -ENOMEM; - - info->p_dev = link; - link->priv = info; - - /* - * General socket configuration defaults can go here. In this - * client, we assume very little, and rely on the CIS for almost - * everything. In most clients, many details (i.e., number, sizes, - * and attributes of IO windows) are fixed by the nature of the - * device, and can be hard-wired here. - */ - link->config_flags = CONF_ENABLE_IRQ | CONF_AUTO_SET_IO; - - /* Register with Card Services */ - curr_dev = link; - return ni_gpib_config(link); -} - -/* - * This deletes a driver "instance". The device is de-registered - * with Card Services. If it has been released, all local data - * structures are freed. Otherwise, the structures will be freed - * when the device is released. - */ -static void ni_gpib_remove(struct pcmcia_device *link) -{ - struct local_info_t *info = link->priv; - //struct gpib_board_t *dev = info->dev; - - DEBUG(0, "%s(%p)\n", __func__, link); - - if (info->dev) - ni_pcmcia_detach(info->dev); - ni_gpib_release(link); - - //free_netdev(dev); - kfree(info); -} - -static int ni_gpib_config_iteration(struct pcmcia_device *link, void *priv_data) -{ - int retval; - - retval = pcmcia_request_io(link); - if (retval != 0) - return retval; - - return 0; -} - -/* - * ni_gpib_config() is scheduled to run after a CARD_INSERTION event - * is received, to configure the PCMCIA socket, and to make the - * device available to the system. - */ -static int ni_gpib_config(struct pcmcia_device *link) -{ - //struct local_info_t *info = link->priv; - //gpib_board_t *dev = info->dev; - int last_ret; - - DEBUG(0, "%s(0x%p)\n", __func__, link); - - last_ret = pcmcia_loop_config(link, &ni_gpib_config_iteration, NULL); - if (last_ret) { - dev_warn(&link->dev, "no configuration found\n"); - ni_gpib_release(link); - return last_ret; - } - - last_ret = pcmcia_enable_device(link); - if (last_ret) { - ni_gpib_release(link); - return last_ret; - } - return 0; -} /* ni_gpib_config */ - -/* - * After a card is removed, ni_gpib_release() will unregister the - * device, and release the PCMCIA configuration. If the device is - * still open, this will be postponed until it is closed. - */ -static void ni_gpib_release(struct pcmcia_device *link) -{ - DEBUG(0, "%s(0x%p)\n", __func__, link); - pcmcia_disable_device(link); -} /* ni_gpib_release */ - -static int ni_gpib_suspend(struct pcmcia_device *link) -{ - //struct local_info_t *info = link->priv; - //struct gpib_board_t *dev = info->dev; - DEBUG(0, "%s(0x%p)\n", __func__, link); - - if (link->open) - pr_err("Device still open ???\n"); - //netif_device_detach(dev); - - return 0; -} - -static int ni_gpib_resume(struct pcmcia_device *link) -{ - //struct local_info_t *info = link->priv; - //struct gpib_board_t *dev = info->dev; - DEBUG(0, "%s(0x%p)\n", __func__, link); - - /*if (link->open) { - * ni_gpib_probe(dev); / really? - * printk("Gpib resumed ???\n"); - * //netif_device_attach(dev); - *} - */ - return ni_gpib_config(link); -} - -static struct pcmcia_device_id ni_pcmcia_ids[] = { - PCMCIA_DEVICE_MANF_CARD(0x010b, 0x4882), - PCMCIA_DEVICE_MANF_CARD(0x010b, 0x0c71), // NI PCMCIA-GPIB+ - PCMCIA_DEVICE_NULL -}; - -MODULE_DEVICE_TABLE(pcmcia, ni_pcmcia_ids); - -static struct pcmcia_driver ni_gpib_cs_driver = { - .name = "ni_gpib_cs", - .owner = THIS_MODULE, - .drv = { .name = "ni_gpib_cs", }, - .id_table = ni_pcmcia_ids, - .probe = ni_gpib_probe, - .remove = ni_gpib_remove, - .suspend = ni_gpib_suspend, - .resume = ni_gpib_resume, -}; - -int __init init_ni_gpib_cs(void) -{ - return pcmcia_register_driver(&ni_gpib_cs_driver); -} - -void __exit exit_ni_gpib_cs(void) -{ - DEBUG(0, "ni_gpib_cs: unloading\n"); - pcmcia_unregister_driver(&ni_gpib_cs_driver); -} - -static const int pcmcia_gpib_iosize = 32; - -int ni_pcmcia_attach(gpib_board_t *board, const gpib_board_config_t *config) -{ - struct local_info_t *info; - struct tnt4882_priv *tnt_priv; - struct nec7210_priv *nec_priv; - int isr_flags = IRQF_SHARED; - - DEBUG(0, "%s(0x%p)\n", __func__, board); - - if (!curr_dev) { - pr_err("gpib: no NI PCMCIA board found\n"); - return -1; - } - - info = curr_dev->priv; - info->dev = board; - - board->status = 0; - - if (tnt4882_allocate_private(board)) - return -ENOMEM; - tnt_priv = board->private_data; - nec_priv = &tnt_priv->nec7210_priv; - nec_priv->type = TNT4882; - nec_priv->read_byte = nec7210_locking_ioport_read_byte; - nec_priv->write_byte = nec7210_locking_ioport_write_byte; - nec_priv->offset = atgpib_reg_offset; - - DEBUG(0, "ioport1 window attributes: 0x%lx\n", curr_dev->resource[0]->flags); - if (!request_region(curr_dev->resource[0]->start, resource_size(curr_dev->resource[0]), - "tnt4882")) { - pr_err("gpib: ioports starting at 0x%lx are already in use\n", - (unsigned long)curr_dev->resource[0]->start); - return -EIO; - } - - nec_priv->mmiobase = ioport_map(curr_dev->resource[0]->start, - resource_size(curr_dev->resource[0])); - if (!nec_priv->mmiobase) - return -1; - - // get irq - if (request_irq(curr_dev->irq, tnt4882_interrupt, isr_flags, "tnt4882", board)) { - pr_err("gpib: can't request IRQ %d\n", curr_dev->irq); - return -1; - } - tnt_priv->irq = curr_dev->irq; - - tnt4882_init(tnt_priv, board); - - return 0; -} - -void ni_pcmcia_detach(gpib_board_t *board) -{ - struct tnt4882_priv *tnt_priv = board->private_data; - struct nec7210_priv *nec_priv; - - DEBUG(0, "%s(0x%p)\n", __func__, board); - - if (tnt_priv) { - nec_priv = &tnt_priv->nec7210_priv; - if (tnt_priv->irq) - free_irq(tnt_priv->irq, board); - if (nec_priv->mmiobase) - ioport_unmap(nec_priv->mmiobase); - if (nec_priv->iobase) { - tnt4882_board_reset(tnt_priv, board); - release_region(nec_priv->iobase, pcmcia_gpib_iosize); - } - } - tnt4882_free_private(board); -} - -#endif // GPIB_PCMCIA +#endif // CONFIG_GPIB_PCMCIA module_init(tnt4882_init_module); module_exit(tnt4882_exit_module);
diff --git a/drivers/staging/gpib/uapi/gpib_user.h b/drivers/staging/gpib/uapi/gpib_user.h index 0896a55..5ff4588 100644 --- a/drivers/staging/gpib/uapi/gpib_user.h +++ b/drivers/staging/gpib/uapi/gpib_user.h
@@ -106,26 +106,15 @@ enum eos_flags { /* GPIB Bus Control Lines bit vector */ enum bus_control_line { - ValidDAV = 0x01, - ValidNDAC = 0x02, - ValidNRFD = 0x04, - ValidIFC = 0x08, - ValidREN = 0x10, - ValidSRQ = 0x20, - ValidATN = 0x40, - ValidEOI = 0x80, - ValidALL = 0xff, - BusDAV = 0x0100, /* DAV line status bit */ - BusNDAC = 0x0200, /* NDAC line status bit */ - BusNRFD = 0x0400, /* NRFD line status bit */ - BusIFC = 0x0800, /* IFC line status bit */ - BusREN = 0x1000, /* REN line status bit */ - BusSRQ = 0x2000, /* SRQ line status bit */ - BusATN = 0x4000, /* ATN line status bit */ - BusEOI = 0x8000 /* EOI line status bit */ -}; - -enum old_bus_control_line { + VALID_DAV = 0x01, + VALID_NDAC = 0x02, + VALID_NRFD = 0x04, + VALID_IFC = 0x08, + VALID_REN = 0x10, + VALID_SRQ = 0x20, + VALID_ATN = 0x40, + VALID_EOI = 0x80, + VALID_ALL = 0xff, BUS_DAV = 0x0100, /* DAV line status bit */ BUS_NDAC = 0x0200, /* NDAC line status bit */ BUS_NRFD = 0x0400, /* NRFD line status bit */
diff --git a/drivers/staging/greybus/uart.c b/drivers/staging/greybus/uart.c index 8eab94c..308ed1c 100644 --- a/drivers/staging/greybus/uart.c +++ b/drivers/staging/greybus/uart.c
@@ -948,7 +948,8 @@ static int gb_tty_init(void) { int retval = 0; - gb_tty_driver = tty_alloc_driver(GB_NUM_MINORS, 0); + gb_tty_driver = tty_alloc_driver(GB_NUM_MINORS, TTY_DRIVER_REAL_RAW | + TTY_DRIVER_DYNAMIC_DEV); if (IS_ERR(gb_tty_driver)) { pr_err("Can not allocate tty driver\n"); retval = -ENOMEM; @@ -961,7 +962,6 @@ static int gb_tty_init(void) gb_tty_driver->minor_start = 0; gb_tty_driver->type = TTY_DRIVER_TYPE_SERIAL; gb_tty_driver->subtype = SERIAL_TYPE_NORMAL; - gb_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; gb_tty_driver->init_termios = tty_std_termios; gb_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
diff --git a/drivers/staging/media/imx/imx-ic-prpencvf.c b/drivers/staging/media/imx/imx-ic-prpencvf.c index 17fd980..2855ba2 100644 --- a/drivers/staging/media/imx/imx-ic-prpencvf.c +++ b/drivers/staging/media/imx/imx-ic-prpencvf.c
@@ -781,7 +781,7 @@ static void prp_stop(struct prp_priv *priv) imx_media_free_dma_buf(ic_priv->ipu_dev, &priv->underrun_buf); /* cancel the EOF timeout timer */ - del_timer_sync(&priv->eof_timeout_timer); + timer_delete_sync(&priv->eof_timeout_timer); prp_put_ipu_resources(priv); }
diff --git a/drivers/staging/media/imx/imx-media-csi.c b/drivers/staging/media/imx/imx-media-csi.c index 3edbc57..f1d7fce 100644 --- a/drivers/staging/media/imx/imx-media-csi.c +++ b/drivers/staging/media/imx/imx-media-csi.c
@@ -695,7 +695,7 @@ static void csi_idmac_stop(struct csi_priv *priv) imx_media_free_dma_buf(priv->dev, &priv->underrun_buf); /* cancel the EOF timeout timer */ - del_timer_sync(&priv->eof_timeout_timer); + timer_delete_sync(&priv->eof_timeout_timer); csi_idmac_put_ipu_resources(priv); }
diff --git a/drivers/staging/rtl8723bs/Kconfig b/drivers/staging/rtl8723bs/Kconfig index 8d48c61..353e6ee 100644 --- a/drivers/staging/rtl8723bs/Kconfig +++ b/drivers/staging/rtl8723bs/Kconfig
@@ -4,6 +4,7 @@ depends on WLAN && MMC && CFG80211 depends on m select CRYPTO + select CRYPTO_LIB_AES select CRYPTO_LIB_ARC4 help This option enables support for RTL8723BS SDIO drivers, such as
diff --git a/drivers/staging/rtl8723bs/core/rtw_ap.c b/drivers/staging/rtl8723bs/core/rtw_ap.c index a6dc88d..50022bb 100644 --- a/drivers/staging/rtl8723bs/core/rtw_ap.c +++ b/drivers/staging/rtl8723bs/core/rtw_ap.c
@@ -324,7 +324,7 @@ void add_RATid(struct adapter *padapter, struct sta_info *psta, u8 rssi_level) { unsigned char sta_band = 0, shortGIrate = false; unsigned int tx_ra_bitmap = 0; - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); + struct mlme_priv *pmlmepriv = &padapter->mlmepriv; struct wlan_bssid_ex *pcur_network = (struct wlan_bssid_ex *)&pmlmepriv->cur_network.network; @@ -372,9 +372,9 @@ void update_bmc_sta(struct adapter *padapter) unsigned char network_type; int supportRateNum = 0; unsigned int tx_ra_bitmap = 0; - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); - struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + struct mlme_priv *pmlmepriv = &padapter->mlmepriv; + struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; + struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; struct wlan_bssid_ex *pcur_network = (struct wlan_bssid_ex *)&pmlmepriv->cur_network.network; struct sta_info *psta = rtw_get_bcmc_stainfo(padapter); @@ -451,9 +451,9 @@ void update_bmc_sta(struct adapter *padapter) void update_sta_info_apmode(struct adapter *padapter, struct sta_info *psta) { - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); + struct mlme_priv *pmlmepriv = &padapter->mlmepriv; struct security_priv *psecuritypriv = &padapter->securitypriv; - struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); + struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; struct ht_priv *phtpriv_ap = &pmlmepriv->htpriv; struct ht_priv *phtpriv_sta = &psta->htpriv; u8 cur_ldpc_cap = 0, cur_stbc_cap = 0, cur_beamform_cap = 0; @@ -563,10 +563,10 @@ void update_sta_info_apmode(struct adapter *padapter, struct sta_info *psta) static void update_ap_info(struct adapter *padapter, struct sta_info *psta) { - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); + struct mlme_priv *pmlmepriv = &padapter->mlmepriv; struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)&pmlmepriv->cur_network.network; - struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); + struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; struct ht_priv *phtpriv_ap = &pmlmepriv->htpriv; psta->wireless_mode = pmlmeext->cur_wireless_mode; @@ -609,7 +609,7 @@ static void update_hw_ht_param(struct adapter *padapter) unsigned char max_AMPDU_len; unsigned char min_MPDU_spacing; struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; /* handle A-MPDU parameter field * @@ -645,13 +645,13 @@ void start_bss_network(struct adapter *padapter) u32 acparm; int ie_len; struct registry_priv *pregpriv = &padapter->registrypriv; - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); - struct security_priv *psecuritypriv = &(padapter->securitypriv); + struct mlme_priv *pmlmepriv = &padapter->mlmepriv; + struct security_priv *psecuritypriv = &padapter->securitypriv; struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)&pmlmepriv->cur_network.network; - struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - struct wlan_bssid_ex *pnetwork_mlmeext = &(pmlmeinfo->network); + struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; + struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; + struct wlan_bssid_ex *pnetwork_mlmeext = &pmlmeinfo->network; struct HT_info_element *pht_info = NULL; u8 cbw40_enable = 0; @@ -823,7 +823,7 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len) u8 WMM_PARA_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01}; struct registry_priv *pregistrypriv = &padapter->registrypriv; struct security_priv *psecuritypriv = &padapter->securitypriv; - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); + struct mlme_priv *pmlmepriv = &padapter->mlmepriv; struct wlan_bssid_ex *pbss_network = (struct wlan_bssid_ex *)&pmlmepriv->cur_network.network; u8 *ie = pbss_network->ies; @@ -845,7 +845,7 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len) pbss_network->rssi = 0; - memcpy(pbss_network->mac_address, myid(&(padapter->eeprompriv)), ETH_ALEN); + memcpy(pbss_network->mac_address, myid(&padapter->eeprompriv), ETH_ALEN); /* beacon interval */ p = rtw_get_beacon_interval_from_ie(ie);/* ie + 8; 8: TimeStamp, 2: Beacon Interval 2:Capability */ @@ -1186,7 +1186,7 @@ int rtw_acl_add_sta(struct adapter *padapter, u8 *addr) if ((NUM_ACL - 1) < pacl_list->num) return (-1); - spin_lock_bh(&(pacl_node_q->lock)); + spin_lock_bh(&pacl_node_q->lock); phead = get_list_head(pacl_node_q); list_for_each(plist, phead) { @@ -1200,12 +1200,12 @@ int rtw_acl_add_sta(struct adapter *padapter, u8 *addr) } } - spin_unlock_bh(&(pacl_node_q->lock)); + spin_unlock_bh(&pacl_node_q->lock); if (added) return ret; - spin_lock_bh(&(pacl_node_q->lock)); + spin_lock_bh(&pacl_node_q->lock); for (i = 0; i < NUM_ACL; i++) { paclnode = &pacl_list->aclnode[i]; @@ -1225,7 +1225,7 @@ int rtw_acl_add_sta(struct adapter *padapter, u8 *addr) } } - spin_unlock_bh(&(pacl_node_q->lock)); + spin_unlock_bh(&pacl_node_q->lock); return ret; } @@ -1238,7 +1238,7 @@ void rtw_acl_remove_sta(struct adapter *padapter, u8 *addr) struct wlan_acl_pool *pacl_list = &pstapriv->acl_list; struct __queue *pacl_node_q = &pacl_list->acl_node_q; - spin_lock_bh(&(pacl_node_q->lock)); + spin_lock_bh(&pacl_node_q->lock); phead = get_list_head(pacl_node_q); list_for_each_safe(plist, tmp, phead) { @@ -1258,7 +1258,7 @@ void rtw_acl_remove_sta(struct adapter *padapter, u8 *addr) } } - spin_unlock_bh(&(pacl_node_q->lock)); + spin_unlock_bh(&pacl_node_q->lock); } @@ -1308,7 +1308,7 @@ static int rtw_ap_set_key( u8 keylen; struct cmd_obj *pcmd; struct setkey_parm *psetkeyparm; - struct cmd_priv *pcmdpriv = &(padapter->cmdpriv); + struct cmd_priv *pcmdpriv = &padapter->cmdpriv; int res = _SUCCESS; pcmd = rtw_zmalloc(sizeof(struct cmd_obj)); @@ -1345,7 +1345,7 @@ static int rtw_ap_set_key( keylen = 16; } - memcpy(&(psetkeyparm->key[0]), key, keylen); + memcpy(&psetkeyparm->key[0], key, keylen); pcmd->cmdcode = _SetKey_CMD_; pcmd->parmbuf = (u8 *)psetkeyparm; @@ -1397,10 +1397,10 @@ static void update_bcn_fixed_ie(struct adapter *padapter) static void update_bcn_erpinfo_ie(struct adapter *padapter) { - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); - struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - struct wlan_bssid_ex *pnetwork = &(pmlmeinfo->network); + struct mlme_priv *pmlmepriv = &padapter->mlmepriv; + struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; + struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; + struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network; unsigned char *p, *ie = pnetwork->ies; u32 len = 0; @@ -1461,10 +1461,10 @@ static void update_bcn_wps_ie(struct adapter *padapter) u8 *pbackup_remainder_ie = NULL; uint wps_ielen = 0, wps_offset, remainder_ielen; - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); - struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - struct wlan_bssid_ex *pnetwork = &(pmlmeinfo->network); + struct mlme_priv *pmlmepriv = &padapter->mlmepriv; + struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; + struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; + struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network; unsigned char *ie = pnetwork->ies; u32 ielen = pnetwork->ie_length; @@ -1537,8 +1537,8 @@ void update_beacon(struct adapter *padapter, u8 ie_id, u8 *oui, u8 tx) if (!padapter) return; - pmlmepriv = &(padapter->mlmepriv); - pmlmeext = &(padapter->mlmeextpriv); + pmlmepriv = &padapter->mlmepriv; + pmlmeext = &padapter->mlmeextpriv; /* pmlmeinfo = &(pmlmeext->mlmext_info); */ if (!pmlmeext->bstart_bss) @@ -1619,7 +1619,7 @@ static int rtw_ht_operation_update(struct adapter *padapter) { u16 cur_op_mode, new_op_mode; int op_mode_changes = 0; - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); + struct mlme_priv *pmlmepriv = &padapter->mlmepriv; struct ht_priv *phtpriv_ap = &pmlmepriv->htpriv; if (pmlmepriv->htpriv.ht_option) @@ -1703,8 +1703,8 @@ void associated_clients_update(struct adapter *padapter, u8 updated) void bss_cap_update_on_sta_join(struct adapter *padapter, struct sta_info *psta) { u8 beacon_updated = false; - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); - struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); + struct mlme_priv *pmlmepriv = &padapter->mlmepriv; + struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; if (!(psta->flags & WLAN_STA_SHORT_PREAMBLE)) { if (!psta->no_short_preamble_set) { @@ -1823,8 +1823,8 @@ void bss_cap_update_on_sta_join(struct adapter *padapter, struct sta_info *psta) u8 bss_cap_update_on_sta_leave(struct adapter *padapter, struct sta_info *psta) { u8 beacon_updated = false; - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); - struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); + struct mlme_priv *pmlmepriv = &padapter->mlmepriv; + struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; if (!psta) return beacon_updated; @@ -1932,7 +1932,7 @@ void rtw_sta_flush(struct adapter *padapter) struct sta_info *psta = NULL; struct sta_priv *pstapriv = &padapter->stapriv; struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; if ((pmlmeinfo->state & 0x03) != WIFI_FW_AP_STATE) @@ -1962,7 +1962,7 @@ void rtw_sta_flush(struct adapter *padapter) void sta_info_update(struct adapter *padapter, struct sta_info *psta) { int flags = psta->flags; - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); + struct mlme_priv *pmlmepriv = &padapter->mlmepriv; /* update wmm cap. */ if (WLAN_STA_WME & flags) @@ -1991,7 +1991,7 @@ void sta_info_update(struct adapter *padapter, struct sta_info *psta) void ap_sta_info_defer_update(struct adapter *padapter, struct sta_info *psta) { struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; if (psta->state & _FW_LINKED) { pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta; @@ -2006,7 +2006,7 @@ void rtw_ap_restore_network(struct adapter *padapter) struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; struct sta_priv *pstapriv = &padapter->stapriv; struct sta_info *psta; - struct security_priv *psecuritypriv = &(padapter->securitypriv); + struct security_priv *psecuritypriv = &padapter->securitypriv; struct list_head *phead, *plist; u8 chk_alive_num = 0; char chk_alive_list[NUM_STA]; @@ -2072,7 +2072,7 @@ void rtw_ap_restore_network(struct adapter *padapter) void start_ap_mode(struct adapter *padapter) { int i; - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); + struct mlme_priv *pmlmepriv = &padapter->mlmepriv; struct sta_priv *pstapriv = &padapter->stapriv; struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; struct wlan_acl_pool *pacl_list = &pstapriv->acl_list; @@ -2109,7 +2109,7 @@ void start_ap_mode(struct adapter *padapter) pmlmepriv->p2p_probe_resp_ie = NULL; /* for ACL */ - INIT_LIST_HEAD(&(pacl_list->acl_node_q.queue)); + INIT_LIST_HEAD(&pacl_list->acl_node_q.queue); pacl_list->num = 0; pacl_list->mode = 0; for (i = 0; i < NUM_ACL; i++) { @@ -2124,7 +2124,7 @@ void stop_ap_mode(struct adapter *padapter) struct rtw_wlan_acl_node *paclnode; struct sta_info *psta = NULL; struct sta_priv *pstapriv = &padapter->stapriv; - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); + struct mlme_priv *pmlmepriv = &padapter->mlmepriv; struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; struct wlan_acl_pool *pacl_list = &pstapriv->acl_list; struct __queue *pacl_node_q = &pacl_list->acl_node_q; @@ -2142,7 +2142,7 @@ void stop_ap_mode(struct adapter *padapter) padapter->securitypriv.ndisencryptstatus = Ndis802_11WEPDisabled; /* for ACL */ - spin_lock_bh(&(pacl_node_q->lock)); + spin_lock_bh(&pacl_node_q->lock); phead = get_list_head(pacl_node_q); list_for_each_safe(plist, tmp, phead) { paclnode = list_entry(plist, struct rtw_wlan_acl_node, list); @@ -2155,7 +2155,7 @@ void stop_ap_mode(struct adapter *padapter) pacl_list->num--; } } - spin_unlock_bh(&(pacl_node_q->lock)); + spin_unlock_bh(&pacl_node_q->lock); rtw_sta_flush(padapter);
diff --git a/drivers/staging/rtl8723bs/core/rtw_cmd.c b/drivers/staging/rtl8723bs/core/rtw_cmd.c index 64ce33c..1c9e8b0 100644 --- a/drivers/staging/rtl8723bs/core/rtw_cmd.c +++ b/drivers/staging/rtl8723bs/core/rtw_cmd.c
@@ -1846,7 +1846,7 @@ void rtw_createbss_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd) if (pcmd->res != H2C_SUCCESS) _set_timer(&pmlmepriv->assoc_timer, 1); - del_timer_sync(&pmlmepriv->assoc_timer); + timer_delete_sync(&pmlmepriv->assoc_timer); spin_lock_bh(&pmlmepriv->lock);
diff --git a/drivers/staging/rtl8723bs/core/rtw_mlme.c b/drivers/staging/rtl8723bs/core/rtw_mlme.c index 5ded183..58de0c2 100644 --- a/drivers/staging/rtl8723bs/core/rtw_mlme.c +++ b/drivers/staging/rtl8723bs/core/rtw_mlme.c
@@ -681,7 +681,7 @@ void rtw_surveydone_event_callback(struct adapter *adapter, u8 *pbuf) if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) { spin_unlock_bh(&pmlmepriv->lock); - del_timer_sync(&pmlmepriv->scan_to_timer); + timer_delete_sync(&pmlmepriv->scan_to_timer); spin_lock_bh(&pmlmepriv->lock); _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY); } @@ -1166,7 +1166,7 @@ void rtw_joinbss_event_prehandle(struct adapter *adapter, u8 *pbuf) spin_unlock_bh(&pmlmepriv->lock); /* s5. Cancel assoc_timer */ - del_timer_sync(&pmlmepriv->assoc_timer); + timer_delete_sync(&pmlmepriv->assoc_timer); spin_lock_bh(&pmlmepriv->lock); } else { spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
diff --git a/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c b/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c index 952ce6d..3d36b6f 100644 --- a/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c +++ b/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c
@@ -412,9 +412,9 @@ void free_mlme_ext_priv(struct mlme_ext_priv *pmlmeext) return; if (padapter->bDriverStopped) { - del_timer_sync(&pmlmeext->survey_timer); - del_timer_sync(&pmlmeext->link_timer); - /* del_timer_sync(&pmlmeext->ADDBA_timer); */ + timer_delete_sync(&pmlmeext->survey_timer); + timer_delete_sync(&pmlmeext->link_timer); + /* timer_delete_sync(&pmlmeext->ADDBA_timer); */ } } @@ -1390,7 +1390,7 @@ unsigned int OnAssocRsp(struct adapter *padapter, union recv_frame *precv_frame) if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) return _SUCCESS; - del_timer_sync(&pmlmeext->link_timer); + timer_delete_sync(&pmlmeext->link_timer); /* status */ status = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN + 2)); @@ -1862,7 +1862,7 @@ unsigned int OnAction_sa_query(struct adapter *padapter, union recv_frame *precv break; case 1: /* SA Query rsp */ - del_timer_sync(&pmlmeext->sa_query_timer); + timer_delete_sync(&pmlmeext->sa_query_timer); break; default: break; @@ -4185,7 +4185,7 @@ void start_clnt_auth(struct adapter *padapter) struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - del_timer_sync(&pmlmeext->link_timer); + timer_delete_sync(&pmlmeext->link_timer); pmlmeinfo->state &= (~WIFI_FW_AUTH_NULL); pmlmeinfo->state |= WIFI_FW_AUTH_STATE; @@ -4210,7 +4210,7 @@ void start_clnt_assoc(struct adapter *padapter) struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - del_timer_sync(&pmlmeext->link_timer); + timer_delete_sync(&pmlmeext->link_timer); pmlmeinfo->state &= (~(WIFI_FW_AUTH_NULL | WIFI_FW_AUTH_STATE)); pmlmeinfo->state |= (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE); @@ -4792,7 +4792,7 @@ static void rtw_mlmeext_disconnect(struct adapter *padapter) flush_all_cam_entry(padapter); - del_timer_sync(&pmlmeext->link_timer); + timer_delete_sync(&pmlmeext->link_timer); /* pmlmepriv->LinkDetectInfo.TrafficBusyState = false; */ pmlmepriv->LinkDetectInfo.TrafficTransitionCount = 0; @@ -5268,7 +5268,7 @@ u8 createbss_hdl(struct adapter *padapter, u8 *pbuf) /* rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain)); */ /* cancel link timer */ - del_timer_sync(&pmlmeext->link_timer); + timer_delete_sync(&pmlmeext->link_timer); /* clear CAM */ flush_all_cam_entry(padapter); @@ -5312,7 +5312,7 @@ u8 join_cmd_hdl(struct adapter *padapter, u8 *pbuf) /* clear CAM */ flush_all_cam_entry(padapter); - del_timer_sync(&pmlmeext->link_timer); + timer_delete_sync(&pmlmeext->link_timer); /* set MSR to nolink -> infra. mode */ /* Set_MSR(padapter, _HW_STATE_NOLINK_); */ @@ -5425,7 +5425,7 @@ u8 join_cmd_hdl(struct adapter *padapter, u8 *pbuf) set_channel_bwmode(padapter, ch, offset, bw); /* cancel link timer */ - del_timer_sync(&pmlmeext->link_timer); + timer_delete_sync(&pmlmeext->link_timer); start_clnt_join(padapter);
diff --git a/drivers/staging/rtl8723bs/core/rtw_recv.c b/drivers/staging/rtl8723bs/core/rtw_recv.c index a389ba5..895116e 100644 --- a/drivers/staging/rtl8723bs/core/rtw_recv.c +++ b/drivers/staging/rtl8723bs/core/rtw_recv.c
@@ -1893,7 +1893,7 @@ static int recv_indicatepkt_reorder(struct adapter *padapter, union recv_frame * spin_unlock_bh(&ppending_recvframe_queue->lock); } else { spin_unlock_bh(&ppending_recvframe_queue->lock); - del_timer_sync(&preorder_ctrl->reordering_ctrl_timer); + timer_delete_sync(&preorder_ctrl->reordering_ctrl_timer); } return _SUCCESS;
diff --git a/drivers/staging/rtl8723bs/core/rtw_sta_mgt.c b/drivers/staging/rtl8723bs/core/rtw_sta_mgt.c index 1b72f21..1d2b53c 100644 --- a/drivers/staging/rtl8723bs/core/rtw_sta_mgt.c +++ b/drivers/staging/rtl8723bs/core/rtw_sta_mgt.c
@@ -158,7 +158,7 @@ u32 _rtw_free_sta_priv(struct sta_priv *pstapriv) for (i = 0; i < 16 ; i++) { preorder_ctrl = &psta->recvreorder_ctrl[i]; - del_timer_sync(&preorder_ctrl->reordering_ctrl_timer); + timer_delete_sync(&preorder_ctrl->reordering_ctrl_timer); } } } @@ -343,7 +343,7 @@ u32 rtw_free_stainfo(struct adapter *padapter, struct sta_info *psta) /* _rtw_init_sta_xmit_priv(&psta->sta_xmitpriv); */ /* _rtw_init_sta_recv_priv(&psta->sta_recvpriv); */ - del_timer_sync(&psta->addba_retry_timer); + timer_delete_sync(&psta->addba_retry_timer); /* for A-MPDU Rx reordering buffer control, cancel reordering_ctrl_timer */ for (i = 0; i < 16 ; i++) { @@ -354,7 +354,7 @@ u32 rtw_free_stainfo(struct adapter *padapter, struct sta_info *psta) preorder_ctrl = &psta->recvreorder_ctrl[i]; - del_timer_sync(&preorder_ctrl->reordering_ctrl_timer); + timer_delete_sync(&preorder_ctrl->reordering_ctrl_timer); ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue;
diff --git a/drivers/staging/rtl8723bs/hal/hal_com.c b/drivers/staging/rtl8723bs/hal/hal_com.c index b41ec89..1213a91 100644 --- a/drivers/staging/rtl8723bs/hal/hal_com.c +++ b/drivers/staging/rtl8723bs/hal/hal_com.c
@@ -884,6 +884,9 @@ static u32 Array_kfreemap[] = { 0xfc, 0x0, }; +#define REG_RF_BB_GAIN_OFFSET 0x7f +//#define RF_GAIN_OFFSET_MASK 0xfffff + void rtw_bb_rf_gain_offset(struct adapter *padapter) { u8 value = padapter->eeprompriv.EEPROMRFGainOffset;
diff --git a/drivers/staging/rtl8723bs/hal/sdio_ops.c b/drivers/staging/rtl8723bs/hal/sdio_ops.c index 21e9f18..8736c12 100644 --- a/drivers/staging/rtl8723bs/hal/sdio_ops.c +++ b/drivers/staging/rtl8723bs/hal/sdio_ops.c
@@ -871,7 +871,7 @@ void sd_int_dpc(struct adapter *adapter) } if (hal->sdio_hisr & SDIO_HISR_CPWM1) { - del_timer_sync(&(pwrctl->pwr_rpwm_timer)); + timer_delete_sync(&(pwrctl->pwr_rpwm_timer)); SdioLocalCmd52Read1Byte(adapter, SDIO_REG_HCPWM1_8723B);
diff --git a/drivers/staging/rtl8723bs/include/osdep_intf.h b/drivers/staging/rtl8723bs/include/osdep_intf.h index 73199be..83a2559 100644 --- a/drivers/staging/rtl8723bs/include/osdep_intf.h +++ b/drivers/staging/rtl8723bs/include/osdep_intf.h
@@ -8,33 +8,6 @@ #ifndef __OSDEP_INTF_H_ #define __OSDEP_INTF_H_ - -struct intf_priv { - - u8 *intf_dev; - u32 max_iosz; /* USB2.0: 128, USB1.1: 64, SDIO:64 */ - u32 max_xmitsz; /* USB2.0: unlimited, SDIO:512 */ - u32 max_recvsz; /* USB2.0: unlimited, SDIO:512 */ - - volatile u8 *io_rwmem; - volatile u8 *allocated_io_rwmem; - u32 io_wsz; /* unit: 4bytes */ - u32 io_rsz;/* unit: 4bytes */ - u8 intf_status; - - void (*_bus_io)(u8 *priv); - -/* -Under Sync. IRP (SDIO/USB) -A protection mechanism is necessary for the io_rwmem(read/write protocol) - -Under Async. IRP (SDIO/USB) -The protection mechanism is through the pending queue. -*/ - - struct mutex ioctl_mutex; -}; - struct dvobj_priv *devobj_init(void); void devobj_deinit(struct dvobj_priv *pdvobj);
diff --git a/drivers/staging/rtl8723bs/include/rtl8723b_hal.h b/drivers/staging/rtl8723bs/include/rtl8723b_hal.h index e6d6e9de..a4a1447 100644 --- a/drivers/staging/rtl8723bs/include/rtl8723b_hal.h +++ b/drivers/staging/rtl8723bs/include/rtl8723b_hal.h
@@ -15,7 +15,6 @@ #include "rtl8723b_recv.h" #include "rtl8723b_xmit.h" #include "rtl8723b_cmd.h" -#include "rtw_mp.h" #include "hal_pwr_seq.h" #include "Hal8192CPhyReg.h" #include "hal_phy_cfg.h"
diff --git a/drivers/staging/rtl8723bs/include/rtw_io.h b/drivers/staging/rtl8723bs/include/rtw_io.h index 0ee87be..adf1de4 100644 --- a/drivers/staging/rtl8723bs/include/rtw_io.h +++ b/drivers/staging/rtl8723bs/include/rtw_io.h
@@ -8,16 +8,7 @@ #ifndef _RTW_IO_H_ #define _RTW_IO_H_ -/* - For prompt mode accessing, caller shall free io_req - Otherwise, io_handler will free io_req -*/ - -/* below is for the intf_option bit definition... */ - -struct intf_priv; struct intf_hdl; -struct io_queue; struct _io_ops { u8 (*_read8)(struct intf_hdl *pintfhdl, u32 addr); @@ -36,8 +27,6 @@ struct _io_ops { void (*_read_mem)(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *pmem); void (*_write_mem)(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *pmem); - void (*_sync_irp_protocol_rw)(struct io_queue *pio_q); - u32 (*_read_interrupt)(struct intf_hdl *pintfhdl, u32 addr); u32 (*_read_port)(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *pmem); @@ -49,18 +38,6 @@ struct _io_ops { void (*_write_port_cancel)(struct intf_hdl *pintfhdl); }; -struct io_req { - struct list_head list; - u32 addr; - volatile u32 val; - u32 command; - u32 status; - u8 *pbuf; - - void (*_async_io_callback)(struct adapter *padater, struct io_req *pio_req, u8 *cnxt); - u8 *cnxt; -}; - struct intf_hdl { struct adapter *padapter; struct dvobj_priv *pintf_dev;/* pointer to &(padapter->dvobjpriv); */ @@ -74,21 +51,6 @@ struct intf_hdl { int rtw_inc_and_chk_continual_io_error(struct dvobj_priv *dvobj); void rtw_reset_continual_io_error(struct dvobj_priv *dvobj); -/* -Below is the data structure used by _io_handler - -*/ - -struct io_queue { - spinlock_t lock; - struct list_head free_ioreqs; - struct list_head pending; /* The io_req list that will be served in the single protocol read/write. */ - struct list_head processing; - u8 *free_ioreqs_buf; /* 4-byte aligned */ - u8 *pallocated_free_ioreqs_buf; - struct intf_hdl intf; -}; - struct io_priv { struct adapter *padapter; @@ -97,20 +59,6 @@ struct io_priv { }; -extern uint ioreq_flush(struct adapter *adapter, struct io_queue *ioqueue); -extern void sync_ioreq_enqueue(struct io_req *preq, struct io_queue *ioqueue); -extern uint sync_ioreq_flush(struct adapter *adapter, struct io_queue *ioqueue); - - -extern uint free_ioreq(struct io_req *preq, struct io_queue *pio_queue); -extern struct io_req *alloc_ioreq(struct io_queue *pio_q); - -extern uint register_intf_hdl(u8 *dev, struct intf_hdl *pintfhdl); -extern void unregister_intf_hdl(struct intf_hdl *pintfhdl); - -extern void _rtw_attrib_read(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem); -extern void _rtw_attrib_write(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem); - extern u8 rtw_read8(struct adapter *adapter, u32 addr); extern u16 rtw_read16(struct adapter *adapter, u32 addr); extern u32 rtw_read32(struct adapter *adapter, u32 addr); @@ -121,46 +69,6 @@ extern int rtw_write32(struct adapter *adapter, u32 addr, u32 val); extern u32 rtw_write_port(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem); -extern void rtw_write_scsi(struct adapter *adapter, u32 cnt, u8 *pmem); - -/* ioreq */ -extern void ioreq_read8(struct adapter *adapter, u32 addr, u8 *pval); -extern void ioreq_read16(struct adapter *adapter, u32 addr, u16 *pval); -extern void ioreq_read32(struct adapter *adapter, u32 addr, u32 *pval); -extern void ioreq_write8(struct adapter *adapter, u32 addr, u8 val); -extern void ioreq_write16(struct adapter *adapter, u32 addr, u16 val); -extern void ioreq_write32(struct adapter *adapter, u32 addr, u32 val); - - -extern uint async_read8(struct adapter *adapter, u32 addr, u8 *pbuff, - void (*_async_io_callback)(struct adapter *padater, struct io_req *pio_req, u8 *cnxt), u8 *cnxt); -extern uint async_read16(struct adapter *adapter, u32 addr, u8 *pbuff, - void (*_async_io_callback)(struct adapter *padater, struct io_req *pio_req, u8 *cnxt), u8 *cnxt); -extern uint async_read32(struct adapter *adapter, u32 addr, u8 *pbuff, - void (*_async_io_callback)(struct adapter *padater, struct io_req *pio_req, u8 *cnxt), u8 *cnxt); - -extern void async_read_mem(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem); -extern void async_read_port(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem); - -extern void async_write8(struct adapter *adapter, u32 addr, u8 val, - void (*_async_io_callback)(struct adapter *padater, struct io_req *pio_req, u8 *cnxt), u8 *cnxt); -extern void async_write16(struct adapter *adapter, u32 addr, u16 val, - void (*_async_io_callback)(struct adapter *padater, struct io_req *pio_req, u8 *cnxt), u8 *cnxt); -extern void async_write32(struct adapter *adapter, u32 addr, u32 val, - void (*_async_io_callback)(struct adapter *padater, struct io_req *pio_req, u8 *cnxt), u8 *cnxt); - -extern void async_write_mem(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem); -extern void async_write_port(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem); - - int rtw_init_io_priv(struct adapter *padapter, void (*set_intf_ops)(struct adapter *padapter, struct _io_ops *pops)); - -extern uint alloc_io_queue(struct adapter *adapter); -extern void free_io_queue(struct adapter *adapter); -extern void async_bus_io(struct io_queue *pio_q); -extern void bus_sync_io(struct io_queue *pio_q); -extern u32 _ioreq2rwmem(struct io_queue *pio_q); -extern void dev_power_down(struct adapter *Adapter, u8 bpwrup); - #endif /* _RTL8711_IO_H_ */
diff --git a/drivers/staging/rtl8723bs/include/rtw_mp.h b/drivers/staging/rtl8723bs/include/rtw_mp.h deleted file mode 100644 index 5a1cbd2..0000000 --- a/drivers/staging/rtl8723bs/include/rtw_mp.h +++ /dev/null
@@ -1,341 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - ******************************************************************************/ -#ifndef _RTW_MP_H_ -#define _RTW_MP_H_ - -#define MAX_MP_XMITBUF_SZ 2048 - -struct mp_xmit_frame { - struct list_head list; - - struct pkt_attrib attrib; - - struct sk_buff *pkt; - - int frame_tag; - - struct adapter *padapter; - - uint mem[(MAX_MP_XMITBUF_SZ >> 2)]; -}; - -struct mp_wiparam { - u32 bcompleted; - u32 act_type; - u32 io_offset; - u32 io_value; -}; - -struct mp_tx { - u8 stop; - u32 count, sended; - u8 payload; - struct pkt_attrib attrib; - /* struct tx_desc desc; */ - /* u8 resvdtx[7]; */ - u8 desc[TXDESC_SIZE]; - u8 *pallocated_buf; - u8 *buf; - u32 buf_size, write_size; - void *PktTxThread; -}; - -#define MP_MAX_LINES 1000 -#define MP_MAX_LINES_BYTES 256 - -typedef void (*MPT_WORK_ITEM_HANDLER)(void *Adapter); -struct mpt_context { - /* Indicate if we have started Mass Production Test. */ - bool bMassProdTest; - - /* Indicate if the driver is unloading or unloaded. */ - bool bMptDrvUnload; - - struct timer_list MPh2c_timeout_timer; -/* Event used to sync H2c for BT control */ - - bool MptH2cRspEvent; - bool MptBtC2hEvent; - bool bMPh2c_timeout; - - /* 8190 PCI does not support NDIS_WORK_ITEM. */ - /* Work Item for Mass Production Test. */ - /* NDIS_WORK_ITEM MptWorkItem; */ -/* RT_WORK_ITEM MptWorkItem; */ - /* Event used to sync the case unloading driver and MptWorkItem is still in progress. */ -/* NDIS_EVENT MptWorkItemEvent; */ - /* To protect the following variables. */ -/* NDIS_SPIN_LOCK MptWorkItemSpinLock; */ - /* Indicate a MptWorkItem is scheduled and not yet finished. */ - bool bMptWorkItemInProgress; - /* An instance which implements function and context of MptWorkItem. */ - MPT_WORK_ITEM_HANDLER CurrMptAct; - - /* 1 =Start, 0 =Stop from UI. */ - u32 MptTestStart; - /* _TEST_MODE, defined in MPT_Req2.h */ - u32 MptTestItem; - /* Variable needed in each implementation of CurrMptAct. */ - u32 MptActType; /* Type of action performed in CurrMptAct. */ - /* The Offset of IO operation is depend of MptActType. */ - u32 MptIoOffset; - /* The Value of IO operation is depend of MptActType. */ - u32 MptIoValue; - /* The RfPath of IO operation is depend of MptActType. */ - u32 MptRfPath; - - enum wireless_mode MptWirelessModeToSw; /* Wireless mode to switch. */ - u8 MptChannelToSw; /* Channel to switch. */ - u8 MptInitGainToSet; /* Initial gain to set. */ - u32 MptBandWidth; /* bandwidth to switch. */ - u32 MptRateIndex; /* rate index. */ - /* Register value kept for Single Carrier Tx test. */ - u8 btMpCckTxPower; - /* Register value kept for Single Carrier Tx test. */ - u8 btMpOfdmTxPower; - /* For MP Tx Power index */ - u8 TxPwrLevel[2]; /* rf-A, rf-B */ - u32 RegTxPwrLimit; - /* Content of RCR Register for Mass Production Test. */ - u32 MptRCR; - /* true if we only receive packets with specific pattern. */ - bool bMptFilterPattern; - /* Rx OK count, statistics used in Mass Production Test. */ - u32 MptRxOkCnt; - /* Rx CRC32 error count, statistics used in Mass Production Test. */ - u32 MptRxCrcErrCnt; - - bool bCckContTx; /* true if we are in CCK Continuous Tx test. */ - bool bOfdmContTx; /* true if we are in OFDM Continuous Tx test. */ - bool bStartContTx; /* true if we have start Continuous Tx test. */ - /* true if we are in Single Carrier Tx test. */ - bool bSingleCarrier; - /* true if we are in Carrier Suppression Tx Test. */ - bool bCarrierSuppression; - /* true if we are in Single Tone Tx test. */ - bool bSingleTone; - - /* ACK counter asked by K.Y.. */ - bool bMptEnableAckCounter; - u32 MptAckCounter; - - /* SD3 Willis For 8192S to save 1T/2T RF table for ACUT Only fro ACUT delete later ~~~! */ - /* s8 BufOfLines[2][MAX_LINES_HWCONFIG_TXT][MAX_BYTES_LINE_HWCONFIG_TXT]; */ - /* s8 BufOfLines[2][MP_MAX_LINES][MP_MAX_LINES_BYTES]; */ - /* s32 RfReadLine[2]; */ - - u8 APK_bound[2]; /* for APK path A/path B */ - bool bMptIndexEven; - - u8 backup0xc50; - u8 backup0xc58; - u8 backup0xc30; - u8 backup0x52_RF_A; - u8 backup0x52_RF_B; - - u32 backup0x58_RF_A; - u32 backup0x58_RF_B; - - u8 h2cReqNum; - u8 c2hBuf[32]; - - u8 btInBuf[100]; - u32 mptOutLen; - u8 mptOutBuf[100]; - -}; -/* endif */ - -/* define RTPRIV_IOCTL_MP (SIOCIWFIRSTPRIV + 0x17) */ -enum { - WRITE_REG = 1, - READ_REG, - WRITE_RF, - READ_RF, - MP_START, - MP_STOP, - MP_RATE, - MP_CHANNEL, - MP_BANDWIDTH, - MP_TXPOWER, - MP_ANT_TX, - MP_ANT_RX, - MP_CTX, - MP_QUERY, - MP_ARX, - MP_PSD, - MP_PWRTRK, - MP_THER, - MP_IOCTL, - EFUSE_GET, - EFUSE_SET, - MP_RESET_STATS, - MP_DUMP, - MP_PHYPARA, - MP_SetRFPathSwh, - MP_QueryDrvStats, - MP_SetBT, - CTA_TEST, - MP_DISABLE_BT_COEXIST, - MP_PwrCtlDM, - MP_NULL, - MP_GET_TXPOWER_INX, -}; - -struct mp_priv { - struct adapter *papdater; - - /* Testing Flag */ - u32 mode;/* 0 for normal type packet, 1 for loopback packet (16bytes TXCMD) */ - - u32 prev_fw_state; - - /* OID cmd handler */ - struct mp_wiparam workparam; -/* u8 act_in_progress; */ - - /* Tx Section */ - u8 TID; - u32 tx_pktcount; - u32 pktInterval; - struct mp_tx tx; - - /* Rx Section */ - u32 rx_bssidpktcount; - u32 rx_pktcount; - u32 rx_pktcount_filter_out; - u32 rx_crcerrpktcount; - u32 rx_pktloss; - bool rx_bindicatePkt; - struct recv_stat rxstat; - - /* RF/BB relative */ - u8 channel; - u8 bandwidth; - u8 prime_channel_offset; - u8 txpoweridx; - u8 txpoweridx_b; - u8 rateidx; - u32 preamble; -/* u8 modem; */ - u32 CrystalCap; -/* u32 curr_crystalcap; */ - - u16 antenna_tx; - u16 antenna_rx; -/* u8 curr_rfpath; */ - - u8 check_mp_pkt; - - u8 bSetTxPower; -/* uint ForcedDataRate; */ - u8 mp_dm; - u8 mac_filter[ETH_ALEN]; - u8 bmac_filter; - - struct wlan_network mp_network; - NDIS_802_11_MAC_ADDRESS network_macaddr; - - u8 *pallocated_mp_xmitframe_buf; - u8 *pmp_xmtframe_buf; - struct __queue free_mp_xmitqueue; - u32 free_mp_xmitframe_cnt; - bool bSetRxBssid; - bool bTxBufCkFail; - - struct mpt_context MptCtx; - - u8 *TXradomBuffer; -}; - -/* Hardware Registers */ -extern u8 mpdatarate[NumRates]; - -#define MAX_TX_PWR_INDEX_N_MODE 64 /* 0x3F */ - -#define REG_RF_BB_GAIN_OFFSET 0x7f -#define RF_GAIN_OFFSET_MASK 0xfffff - -/* */ -/* struct mp_xmit_frame *alloc_mp_xmitframe(struct mp_priv *pmp_priv); */ -/* int free_mp_xmitframe(struct xmit_priv *pxmitpriv, struct mp_xmit_frame *pmp_xmitframe); */ - -s32 init_mp_priv(struct adapter *padapter); -void free_mp_priv(struct mp_priv *pmp_priv); -s32 MPT_InitializeAdapter(struct adapter *padapter, u8 Channel); -void MPT_DeInitAdapter(struct adapter *padapter); -s32 mp_start_test(struct adapter *padapter); -void mp_stop_test(struct adapter *padapter); - -u32 _read_rfreg(struct adapter *padapter, u8 rfpath, u32 addr, u32 bitmask); -void _write_rfreg(struct adapter *padapter, u8 rfpath, u32 addr, u32 bitmask, u32 val); - -u32 read_macreg(struct adapter *padapter, u32 addr, u32 sz); -void write_macreg(struct adapter *padapter, u32 addr, u32 val, u32 sz); - -void SetChannel(struct adapter *padapter); -void SetBandwidth(struct adapter *padapter); -int SetTxPower(struct adapter *padapter); -void SetAntennaPathPower(struct adapter *padapter); -void SetDataRate(struct adapter *padapter); - -void SetAntenna(struct adapter *padapter); - -s32 SetThermalMeter(struct adapter *padapter, u8 target_ther); -void GetThermalMeter(struct adapter *padapter, u8 *value); - -void SetContinuousTx(struct adapter *padapter, u8 bStart); -void SetSingleCarrierTx(struct adapter *padapter, u8 bStart); -void SetSingleToneTx(struct adapter *padapter, u8 bStart); -void SetCarrierSuppressionTx(struct adapter *padapter, u8 bStart); -void PhySetTxPowerLevel(struct adapter *padapter); - -void fill_txdesc_for_mp(struct adapter *padapter, u8 *ptxdesc); -void SetPacketTx(struct adapter *padapter); -void SetPacketRx(struct adapter *padapter, u8 bStartRx); - -void ResetPhyRxPktCount(struct adapter *padapter); -u32 GetPhyRxPktReceived(struct adapter *padapter); -u32 GetPhyRxPktCRC32Error(struct adapter *padapter); - -s32 SetPowerTracking(struct adapter *padapter, u8 enable); -void GetPowerTracking(struct adapter *padapter, u8 *enable); - -u32 mp_query_psd(struct adapter *padapter, u8 *data); - -void Hal_SetAntenna(struct adapter *padapter); -void Hal_SetBandwidth(struct adapter *padapter); - -void Hal_SetTxPower(struct adapter *padapter); -void Hal_SetCarrierSuppressionTx(struct adapter *padapter, u8 bStart); -void Hal_SetSingleToneTx(struct adapter *padapter, u8 bStart); -void Hal_SetSingleCarrierTx(struct adapter *padapter, u8 bStart); -void Hal_SetContinuousTx(struct adapter *padapter, u8 bStart); - -void Hal_SetDataRate(struct adapter *padapter); -void Hal_SetChannel(struct adapter *padapter); -void Hal_SetAntennaPathPower(struct adapter *padapter); -s32 Hal_SetThermalMeter(struct adapter *padapter, u8 target_ther); -s32 Hal_SetPowerTracking(struct adapter *padapter, u8 enable); -void Hal_GetPowerTracking(struct adapter *padapter, u8 *enable); -void Hal_GetThermalMeter(struct adapter *padapter, u8 *value); -void Hal_mpt_SwitchRfSetting(struct adapter *padapter); -void Hal_MPT_CCKTxPowerAdjust(struct adapter *Adapter, bool bInCH14); -void Hal_MPT_CCKTxPowerAdjustbyIndex(struct adapter *padapter, bool beven); -void Hal_SetCCKTxPower(struct adapter *padapter, u8 *TxPower); -void Hal_SetOFDMTxPower(struct adapter *padapter, u8 *TxPower); -void Hal_TriggerRFThermalMeter(struct adapter *padapter); -u8 Hal_ReadRFThermalMeter(struct adapter *padapter); -void Hal_SetCCKContinuousTx(struct adapter *padapter, u8 bStart); -void Hal_SetOFDMContinuousTx(struct adapter *padapter, u8 bStart); -void Hal_ProSetCrystalCap(struct adapter *padapter, u32 CrystalCapVal); -void MP_PHY_SetRFPathSwitch(struct adapter *padapter, bool bMain); -u32 mpt_ProQueryCalTxPower(struct adapter *padapter, u8 RfPath); -void MPT_PwrCtlDM(struct adapter *padapter, u32 bstart); -u8 MptToMgntRate(u32 MptRateIdx); - -#endif /* _RTW_MP_H_ */
diff --git a/drivers/staging/rtl8723bs/os_dep/os_intfs.c b/drivers/staging/rtl8723bs/os_dep/os_intfs.c index 738a601..0248dff 100644 --- a/drivers/staging/rtl8723bs/os_dep/os_intfs.c +++ b/drivers/staging/rtl8723bs/os_dep/os_intfs.c
@@ -697,18 +697,18 @@ u8 rtw_init_drv_sw(struct adapter *padapter) void rtw_cancel_all_timer(struct adapter *padapter) { - del_timer_sync(&padapter->mlmepriv.assoc_timer); + timer_delete_sync(&padapter->mlmepriv.assoc_timer); - del_timer_sync(&padapter->mlmepriv.scan_to_timer); + timer_delete_sync(&padapter->mlmepriv.scan_to_timer); - del_timer_sync(&padapter->mlmepriv.dynamic_chk_timer); + timer_delete_sync(&padapter->mlmepriv.dynamic_chk_timer); - del_timer_sync(&(adapter_to_pwrctl(padapter)->pwr_state_check_timer)); + timer_delete_sync(&(adapter_to_pwrctl(padapter)->pwr_state_check_timer)); - del_timer_sync(&padapter->mlmepriv.set_scan_deny_timer); + timer_delete_sync(&padapter->mlmepriv.set_scan_deny_timer); rtw_clear_scan_deny(padapter); - del_timer_sync(&padapter->recvpriv.signal_stat_timer); + timer_delete_sync(&padapter->recvpriv.signal_stat_timer); /* cancel dm timer */ rtw_hal_dm_deinit(padapter); @@ -724,8 +724,6 @@ u8 rtw_free_drv_sw(struct adapter *padapter) rtw_free_mlme_priv(&padapter->mlmepriv); - /* free_io_queue(padapter); */ - _rtw_free_xmit_priv(&padapter->xmitpriv); _rtw_free_sta_priv(&padapter->stapriv); /* will free bcmc_stainfo here */
diff --git a/drivers/staging/sm750fb/ddk750_chip.c b/drivers/staging/sm750fb/ddk750_chip.c index 02860d3..025dae3 100644 --- a/drivers/staging/sm750fb/ddk750_chip.c +++ b/drivers/staging/sm750fb/ddk750_chip.c
@@ -228,8 +228,8 @@ int ddk750_init_hw(struct initchip_param *p_init_param) reg = peek32(VGA_CONFIGURATION); reg |= (VGA_CONFIGURATION_PLL | VGA_CONFIGURATION_MODE); poke32(VGA_CONFIGURATION, reg); +#ifdef CONFIG_X86 } else { -#if defined(__i386__) || defined(__x86_64__) /* set graphic mode via IO method */ outb_p(0x88, 0x3d4); outb_p(0x06, 0x3d5);
diff --git a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c index deec33f..b839b50 100644 --- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c +++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
@@ -658,8 +658,6 @@ static const struct vb2_ops bcm2835_mmal_video_qops = { .buf_queue = buffer_queue, .start_streaming = start_streaming, .stop_streaming = stop_streaming, - .wait_prepare = vb2_ops_wait_prepare, - .wait_finish = vb2_ops_wait_finish, }; /* ------------------------------------------------------------------
diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c index a4e83e5..5dbf8d5 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
@@ -97,13 +97,6 @@ struct vchiq_arm_state { * tracked separately with the state. */ int peer_use_count; - - /* - * Flag to indicate that the first vchiq connect has made it through. - * This means that both sides should be fully ready, and we should - * be able to suspend after this point. - */ - int first_connect; }; static int @@ -271,7 +264,7 @@ static int vchiq_platform_init(struct platform_device *pdev, struct vchiq_state return -ENXIO; } - dev_dbg(&pdev->dev, "arm: vchiq_init - done (slots %pK, phys %pad)\n", + dev_dbg(&pdev->dev, "arm: vchiq_init - done (slots %p, phys %pad)\n", vchiq_slot_zero, &slot_phys); mutex_init(&drv_mgmt->connected_mutex); @@ -280,34 +273,25 @@ static int vchiq_platform_init(struct platform_device *pdev, struct vchiq_state return 0; } -int -vchiq_platform_init_state(struct vchiq_state *state) -{ - struct vchiq_arm_state *platform_state; - - platform_state = devm_kzalloc(state->dev, sizeof(*platform_state), GFP_KERNEL); - if (!platform_state) - return -ENOMEM; - - rwlock_init(&platform_state->susp_res_lock); - - init_completion(&platform_state->ka_evt); - atomic_set(&platform_state->ka_use_count, 0); - atomic_set(&platform_state->ka_use_ack_count, 0); - atomic_set(&platform_state->ka_release_count, 0); - - platform_state->state = state; - - state->platform_state = (struct opaque_platform_state *)platform_state; - - return 0; -} - static struct vchiq_arm_state *vchiq_platform_get_arm_state(struct vchiq_state *state) { return (struct vchiq_arm_state *)state->platform_state; } +static void +vchiq_platform_uninit(struct vchiq_drv_mgmt *mgmt) +{ + struct vchiq_arm_state *arm_state; + + kthread_stop(mgmt->state.sync_thread); + kthread_stop(mgmt->state.recycle_thread); + kthread_stop(mgmt->state.slot_handler_thread); + + arm_state = vchiq_platform_get_arm_state(&mgmt->state); + if (!IS_ERR_OR_NULL(arm_state->ka_thread)) + kthread_stop(arm_state->ka_thread); +} + void vchiq_dump_platform_state(struct seq_file *f) { seq_puts(f, " Platform: 2835 (VC master)\n"); @@ -368,7 +352,7 @@ void free_bulk_waiter(struct vchiq_instance *instance) &instance->bulk_waiter_list, list) { list_del(&waiter->list); dev_dbg(instance->state->dev, - "arm: bulk_waiter - cleaned up %pK for pid %d\n", + "arm: bulk_waiter - cleaned up %p for pid %d\n", waiter, waiter->pid); kfree(waiter); } @@ -622,7 +606,7 @@ vchiq_blocking_bulk_transfer(struct vchiq_instance *instance, unsigned int handl mutex_lock(&instance->bulk_waiter_list_mutex); list_add(&waiter->list, &instance->bulk_waiter_list); mutex_unlock(&instance->bulk_waiter_list_mutex); - dev_dbg(instance->state->dev, "arm: saved bulk_waiter %pK for pid %d\n", + dev_dbg(instance->state->dev, "arm: saved bulk_waiter %p for pid %d\n", waiter, current->pid); } @@ -998,6 +982,39 @@ vchiq_keepalive_thread_func(void *v) } int +vchiq_platform_init_state(struct vchiq_state *state) +{ + struct vchiq_arm_state *platform_state; + char threadname[16]; + + platform_state = devm_kzalloc(state->dev, sizeof(*platform_state), GFP_KERNEL); + if (!platform_state) + return -ENOMEM; + + snprintf(threadname, sizeof(threadname), "vchiq-keep/%d", + state->id); + platform_state->ka_thread = kthread_create(&vchiq_keepalive_thread_func, + (void *)state, threadname); + if (IS_ERR(platform_state->ka_thread)) { + dev_err(state->dev, "couldn't create thread %s\n", threadname); + return PTR_ERR(platform_state->ka_thread); + } + + rwlock_init(&platform_state->susp_res_lock); + + init_completion(&platform_state->ka_evt); + atomic_set(&platform_state->ka_use_count, 0); + atomic_set(&platform_state->ka_use_ack_count, 0); + atomic_set(&platform_state->ka_release_count, 0); + + platform_state->state = state; + + state->platform_state = (struct opaque_platform_state *)platform_state; + + return 0; +} + +int vchiq_use_internal(struct vchiq_state *state, struct vchiq_service *service, enum USE_TYPE_E use_type) { @@ -1312,37 +1329,19 @@ vchiq_check_service(struct vchiq_service *service) return ret; } +void vchiq_platform_connected(struct vchiq_state *state) +{ + struct vchiq_arm_state *arm_state = vchiq_platform_get_arm_state(state); + + wake_up_process(arm_state->ka_thread); +} + void vchiq_platform_conn_state_changed(struct vchiq_state *state, enum vchiq_connstate oldstate, enum vchiq_connstate newstate) { - struct vchiq_arm_state *arm_state = vchiq_platform_get_arm_state(state); - char threadname[16]; - dev_dbg(state->dev, "suspend: %d: %s->%s\n", state->id, get_conn_state_name(oldstate), get_conn_state_name(newstate)); - if (state->conn_state != VCHIQ_CONNSTATE_CONNECTED) - return; - - write_lock_bh(&arm_state->susp_res_lock); - if (arm_state->first_connect) { - write_unlock_bh(&arm_state->susp_res_lock); - return; - } - - arm_state->first_connect = 1; - write_unlock_bh(&arm_state->susp_res_lock); - snprintf(threadname, sizeof(threadname), "vchiq-keep/%d", - state->id); - arm_state->ka_thread = kthread_create(&vchiq_keepalive_thread_func, - (void *)state, - threadname); - if (IS_ERR(arm_state->ka_thread)) { - dev_err(state->dev, "suspend: Couldn't create thread %s\n", - threadname); - } else { - wake_up_process(arm_state->ka_thread); - } } static const struct of_device_id vchiq_of_match[] = { @@ -1386,8 +1385,6 @@ static int vchiq_probe(struct platform_device *pdev) return ret; } - vchiq_debugfs_init(&mgmt->state); - dev_dbg(&pdev->dev, "arm: platform initialised - version %d (min %d)\n", VCHIQ_VERSION, VCHIQ_VERSION_MIN); @@ -1398,9 +1395,12 @@ static int vchiq_probe(struct platform_device *pdev) ret = vchiq_register_chrdev(&pdev->dev); if (ret) { dev_err(&pdev->dev, "arm: Failed to initialize vchiq cdev\n"); + vchiq_platform_uninit(mgmt); return ret; } + vchiq_debugfs_init(&mgmt->state); + bcm2835_audio = vchiq_device_register(&pdev->dev, "bcm2835-audio"); bcm2835_camera = vchiq_device_register(&pdev->dev, "bcm2835-camera"); @@ -1410,19 +1410,12 @@ static int vchiq_probe(struct platform_device *pdev) static void vchiq_remove(struct platform_device *pdev) { struct vchiq_drv_mgmt *mgmt = dev_get_drvdata(&pdev->dev); - struct vchiq_arm_state *arm_state; vchiq_device_unregister(bcm2835_audio); vchiq_device_unregister(bcm2835_camera); vchiq_debugfs_deinit(); vchiq_deregister_chrdev(); - - kthread_stop(mgmt->state.sync_thread); - kthread_stop(mgmt->state.recycle_thread); - kthread_stop(mgmt->state.slot_handler_thread); - - arm_state = vchiq_platform_get_arm_state(&mgmt->state); - kthread_stop(arm_state->ka_thread); + vchiq_platform_uninit(mgmt); } static struct platform_driver vchiq_driver = {
diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c index 8d5795d..e7b0c80 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c
@@ -470,7 +470,7 @@ make_service_callback(struct vchiq_service *service, enum vchiq_reason reason, cb_userdata = bulk->cb_userdata; } - dev_dbg(service->state->dev, "core: %d: callback:%d (%s, %pK, %pK %pK)\n", + dev_dbg(service->state->dev, "core: %d: callback:%d (%s, %p, %p %p)\n", service->state->id, service->localport, reason_names[reason], header, cb_data, cb_userdata); status = service->base.callback(service->instance, reason, header, service->handle, @@ -778,7 +778,7 @@ process_free_data_message(struct vchiq_state *state, u32 *service_found, complete("a->quota_event); } else if (count == 0) { dev_err(state->dev, - "core: service %d message_use_count=%d (header %pK, msgid %x, header->msgid %x, header->size %x)\n", + "core: service %d message_use_count=%d (header %p, msgid %x, header->msgid %x, header->size %x)\n", port, quota->message_use_count, header, msgid, header->msgid, header->size); WARN(1, "invalid message use count\n"); @@ -799,11 +799,11 @@ process_free_data_message(struct vchiq_state *state, u32 *service_found, * it has dropped below its quota */ complete("a->quota_event); - dev_dbg(state->dev, "core: %d: pfq:%d %x@%pK - slot_use->%d\n", + dev_dbg(state->dev, "core: %d: pfq:%d %x@%p - slot_use->%d\n", state->id, port, header->size, header, count - 1); } else { dev_err(state->dev, - "core: service %d slot_use_count=%d (header %pK, msgid %x, header->msgid %x, header->size %x)\n", + "core: service %d slot_use_count=%d (header %p, msgid %x, header->msgid %x, header->size %x)\n", port, count, header, msgid, header->msgid, header->size); WARN(1, "bad slot use count\n"); } @@ -845,7 +845,7 @@ process_free_queue(struct vchiq_state *state, u32 *service_found, */ rmb(); - dev_dbg(state->dev, "core: %d: pfq %d=%pK %x %x\n", + dev_dbg(state->dev, "core: %d: pfq %d=%p %x %x\n", state->id, slot_index, data, local->slot_queue_recycle, slot_queue_available); @@ -868,7 +868,7 @@ process_free_queue(struct vchiq_state *state, u32 *service_found, pos += calc_stride(header->size); if (pos > VCHIQ_SLOT_SIZE) { dev_err(state->dev, - "core: pfq - pos %x: header %pK, msgid %x, header->msgid %x, header->size %x\n", + "core: pfq - pos %x: header %p, msgid %x, header->msgid %x, header->size %x\n", pos, header, msgid, header->msgid, header->size); WARN(1, "invalid slot position\n"); } @@ -1060,7 +1060,7 @@ queue_message(struct vchiq_state *state, struct vchiq_service *service, int tx_end_index; int slot_use_count; - dev_dbg(state->dev, "core: %d: qm %s@%pK,%zx (%d->%d)\n", + dev_dbg(state->dev, "core: %d: qm %s@%p,%zx (%d->%d)\n", state->id, msg_type_str(VCHIQ_MSG_TYPE(msgid)), header, size, VCHIQ_MSG_SRCPORT(msgid), VCHIQ_MSG_DSTPORT(msgid)); @@ -1117,7 +1117,7 @@ queue_message(struct vchiq_state *state, struct vchiq_service *service, VCHIQ_SERVICE_STATS_INC(service, ctrl_tx_count); VCHIQ_SERVICE_STATS_ADD(service, ctrl_tx_bytes, size); } else { - dev_dbg(state->dev, "core: %d: qm %s@%pK,%zx (%d->%d)\n", + dev_dbg(state->dev, "core: %d: qm %s@%p,%zx (%d->%d)\n", state->id, msg_type_str(VCHIQ_MSG_TYPE(msgid)), header, size, VCHIQ_MSG_SRCPORT(msgid), VCHIQ_MSG_DSTPORT(msgid)); if (size != 0) { @@ -1204,7 +1204,7 @@ queue_message_sync(struct vchiq_state *state, struct vchiq_service *service, state->id, oldmsgid); } - dev_dbg(state->dev, "sync: %d: qms %s@%pK,%x (%d->%d)\n", + dev_dbg(state->dev, "sync: %d: qms %s@%p,%x (%d->%d)\n", state->id, msg_type_str(VCHIQ_MSG_TYPE(msgid)), header, size, VCHIQ_MSG_SRCPORT(msgid), VCHIQ_MSG_DSTPORT(msgid)); @@ -1539,7 +1539,7 @@ create_pagelist(struct vchiq_instance *instance, struct vchiq_bulk *bulk) pagelist = dma_alloc_coherent(instance->state->dev, pagelist_size, &dma_addr, GFP_KERNEL); - dev_dbg(instance->state->dev, "arm: %pK\n", pagelist); + dev_dbg(instance->state->dev, "arm: %p\n", pagelist); if (!pagelist) return NULL; @@ -1692,7 +1692,7 @@ free_pagelist(struct vchiq_instance *instance, struct vchiq_pagelist_info *pagel unsigned int num_pages = pagelistinfo->num_pages; unsigned int cache_line_size; - dev_dbg(instance->state->dev, "arm: %pK, %d\n", pagelistinfo->pagelist, actual); + dev_dbg(instance->state->dev, "arm: %p, %d\n", pagelistinfo->pagelist, actual); drv_mgmt = dev_get_drvdata(instance->state->dev); @@ -1849,7 +1849,7 @@ parse_open(struct vchiq_state *state, struct vchiq_header *header) payload = (struct vchiq_open_payload *)header->data; fourcc = payload->fourcc; - dev_dbg(state->dev, "core: %d: prs OPEN@%pK (%d->'%p4cc')\n", + dev_dbg(state->dev, "core: %d: prs OPEN@%p (%d->'%p4cc')\n", state->id, header, localport, &fourcc); service = get_listening_service(state, fourcc); @@ -1976,14 +1976,14 @@ parse_message(struct vchiq_state *state, struct vchiq_header *header) service = get_connected_service(state, remoteport); if (service) dev_warn(state->dev, - "core: %d: prs %s@%pK (%d->%d) - found connected service %d\n", + "core: %d: prs %s@%p (%d->%d) - found connected service %d\n", state->id, msg_type_str(type), header, remoteport, localport, service->localport); } if (!service) { dev_err(state->dev, - "core: %d: prs %s@%pK (%d->%d) - invalid/closed service %d\n", + "core: %d: prs %s@%p (%d->%d) - invalid/closed service %d\n", state->id, msg_type_str(type), header, remoteport, localport, localport); goto skip_message; @@ -2003,7 +2003,7 @@ parse_message(struct vchiq_state *state, struct vchiq_header *header) if (((unsigned long)header & VCHIQ_SLOT_MASK) + calc_stride(size) > VCHIQ_SLOT_SIZE) { - dev_err(state->dev, "core: header %pK (msgid %x) - size %x too big for slot\n", + dev_err(state->dev, "core: header %p (msgid %x) - size %x too big for slot\n", header, (unsigned int)msgid, (unsigned int)size); WARN(1, "oversized for slot\n"); } @@ -2022,7 +2022,7 @@ parse_message(struct vchiq_state *state, struct vchiq_header *header) service->peer_version = payload->version; } dev_dbg(state->dev, - "core: %d: prs OPENACK@%pK,%x (%d->%d) v:%d\n", + "core: %d: prs OPENACK@%p,%x (%d->%d) v:%d\n", state->id, header, size, remoteport, localport, service->peer_version); if (service->srvstate == VCHIQ_SRVSTATE_OPENING) { @@ -2037,7 +2037,7 @@ parse_message(struct vchiq_state *state, struct vchiq_header *header) case VCHIQ_MSG_CLOSE: WARN_ON(size); /* There should be no data */ - dev_dbg(state->dev, "core: %d: prs CLOSE@%pK (%d->%d)\n", + dev_dbg(state->dev, "core: %d: prs CLOSE@%p (%d->%d)\n", state->id, header, remoteport, localport); mark_service_closing_internal(service, 1); @@ -2049,7 +2049,7 @@ parse_message(struct vchiq_state *state, struct vchiq_header *header) &service->base.fourcc, service->localport, service->remoteport); break; case VCHIQ_MSG_DATA: - dev_dbg(state->dev, "core: %d: prs DATA@%pK,%x (%d->%d)\n", + dev_dbg(state->dev, "core: %d: prs DATA@%p,%x (%d->%d)\n", state->id, header, size, remoteport, localport); if ((service->remoteport == remoteport) && @@ -2069,7 +2069,7 @@ parse_message(struct vchiq_state *state, struct vchiq_header *header) } break; case VCHIQ_MSG_CONNECT: - dev_dbg(state->dev, "core: %d: prs CONNECT@%pK\n", + dev_dbg(state->dev, "core: %d: prs CONNECT@%p\n", state->id, header); state->version_common = ((struct vchiq_slot_zero *) state->slot_data)->version; @@ -2102,7 +2102,7 @@ parse_message(struct vchiq_state *state, struct vchiq_header *header) if ((int)(queue->remote_insert - queue->local_insert) >= 0) { dev_err(state->dev, - "core: %d: prs %s@%pK (%d->%d) unexpected (ri=%d,li=%d)\n", + "core: %d: prs %s@%p (%d->%d) unexpected (ri=%d,li=%d)\n", state->id, msg_type_str(type), header, remoteport, localport, queue->remote_insert, queue->local_insert); mutex_unlock(&service->bulk_mutex); @@ -2120,7 +2120,7 @@ parse_message(struct vchiq_state *state, struct vchiq_header *header) bulk->actual = *(int *)header->data; queue->remote_insert++; - dev_dbg(state->dev, "core: %d: prs %s@%pK (%d->%d) %x@%pad\n", + dev_dbg(state->dev, "core: %d: prs %s@%p (%d->%d) %x@%pad\n", state->id, msg_type_str(type), header, remoteport, localport, bulk->actual, &bulk->dma_addr); @@ -2140,12 +2140,12 @@ parse_message(struct vchiq_state *state, struct vchiq_header *header) } break; case VCHIQ_MSG_PADDING: - dev_dbg(state->dev, "core: %d: prs PADDING@%pK,%x\n", + dev_dbg(state->dev, "core: %d: prs PADDING@%p,%x\n", state->id, header, size); break; case VCHIQ_MSG_PAUSE: /* If initiated, signal the application thread */ - dev_dbg(state->dev, "core: %d: prs PAUSE@%pK,%x\n", + dev_dbg(state->dev, "core: %d: prs PAUSE@%p,%x\n", state->id, header, size); if (state->conn_state == VCHIQ_CONNSTATE_PAUSED) { dev_err(state->dev, "core: %d: PAUSE received in state PAUSED\n", @@ -2162,7 +2162,7 @@ parse_message(struct vchiq_state *state, struct vchiq_header *header) vchiq_set_conn_state(state, VCHIQ_CONNSTATE_PAUSED); break; case VCHIQ_MSG_RESUME: - dev_dbg(state->dev, "core: %d: prs RESUME@%pK,%x\n", + dev_dbg(state->dev, "core: %d: prs RESUME@%p,%x\n", state->id, header, size); /* Release the slot mutex */ mutex_unlock(&state->slot_mutex); @@ -2179,7 +2179,7 @@ parse_message(struct vchiq_state *state, struct vchiq_header *header) break; default: - dev_err(state->dev, "core: %d: prs invalid msgid %x@%pK,%x\n", + dev_err(state->dev, "core: %d: prs invalid msgid %x@%p,%x\n", state->id, msgid, header, size); WARN(1, "invalid message\n"); break; @@ -2400,7 +2400,7 @@ sync_func(void *v) if (!service) { dev_err(state->dev, - "sync: %d: sf %s@%pK (%d->%d) - invalid/closed service %d\n", + "sync: %d: sf %s@%p (%d->%d) - invalid/closed service %d\n", state->id, msg_type_str(type), header, remoteport, localport, localport); release_message_sync(state, header); @@ -2422,7 +2422,7 @@ sync_func(void *v) header->data; service->peer_version = payload->version; } - dev_err(state->dev, "sync: %d: sf OPENACK@%pK,%x (%d->%d) v:%d\n", + dev_err(state->dev, "sync: %d: sf OPENACK@%p,%x (%d->%d) v:%d\n", state->id, header, size, remoteport, localport, service->peer_version); if (service->srvstate == VCHIQ_SRVSTATE_OPENING) { @@ -2435,7 +2435,7 @@ sync_func(void *v) break; case VCHIQ_MSG_DATA: - dev_dbg(state->dev, "sync: %d: sf DATA@%pK,%x (%d->%d)\n", + dev_dbg(state->dev, "sync: %d: sf DATA@%p,%x (%d->%d)\n", state->id, header, size, remoteport, localport); if ((service->remoteport == remoteport) && @@ -2449,7 +2449,7 @@ sync_func(void *v) break; default: - dev_err(state->dev, "sync: error: %d: sf unexpected msgid %x@%pK,%x\n", + dev_err(state->dev, "sync: error: %d: sf unexpected msgid %x@%p,%x\n", state->id, msgid, header, size); release_message_sync(state, header); break; @@ -2926,13 +2926,13 @@ release_service_messages(struct vchiq_service *service) int port = VCHIQ_MSG_DSTPORT(msgid); if ((port == service->localport) && (msgid & VCHIQ_MSGID_CLAIMED)) { - dev_dbg(state->dev, "core: fsi - hdr %pK\n", header); + dev_dbg(state->dev, "core: fsi - hdr %p\n", header); release_slot(state, slot_info, header, NULL); } pos += calc_stride(header->size); if (pos > VCHIQ_SLOT_SIZE) { dev_err(state->dev, - "core: fsi - pos %x: header %pK, msgid %x, header->msgid %x, header->size %x\n", + "core: fsi - pos %x: header %p, msgid %x, header->msgid %x, header->size %x\n", pos, header, msgid, header->msgid, header->size); WARN(1, "invalid slot position\n"); } @@ -3091,7 +3091,7 @@ vchiq_bulk_xfer_queue_msg_killable(struct vchiq_service *service, */ wmb(); - dev_dbg(state->dev, "core: %d: bt (%d->%d) %cx %x@%pad %pK\n", + dev_dbg(state->dev, "core: %d: bt (%d->%d) %cx %x@%pad %p\n", state->id, service->localport, service->remoteport, dir_char, bulk->size, &bulk->dma_addr, bulk->cb_data); @@ -3343,6 +3343,7 @@ vchiq_connect_internal(struct vchiq_state *state, struct vchiq_instance *instanc return -EAGAIN; vchiq_set_conn_state(state, VCHIQ_CONNSTATE_CONNECTED); + vchiq_platform_connected(state); complete(&state->connect); }
diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h index 9b4e766..3b5c061 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h
@@ -575,6 +575,8 @@ int vchiq_send_remote_use(struct vchiq_state *state); int vchiq_send_remote_use_active(struct vchiq_state *state); +void vchiq_platform_connected(struct vchiq_state *state); + void vchiq_platform_conn_state_changed(struct vchiq_state *state, enum vchiq_connstate oldstate, enum vchiq_connstate newstate);
diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_dev.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_dev.c index 454f434..3b20ba5 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_dev.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_dev.c
@@ -270,7 +270,7 @@ static int vchiq_ioc_dequeue_message(struct vchiq_instance *instance, } } else { dev_err(service->state->dev, - "arm: header %pK: bufsize %x < size %x\n", + "arm: header %p: bufsize %x < size %x\n", header, args->bufsize, header->size); WARN(1, "invalid size\n"); ret = -EMSGSIZE; @@ -328,7 +328,7 @@ static int vchiq_irq_queue_bulk_tx_rx(struct vchiq_instance *instance, ret = -ESRCH; goto out; } - dev_dbg(service->state->dev, "arm: found bulk_waiter %pK for pid %d\n", + dev_dbg(service->state->dev, "arm: found bulk_waiter %p for pid %d\n", waiter, current->pid); status = vchiq_bulk_xfer_waiting(instance, args->handle, @@ -366,7 +366,7 @@ static int vchiq_irq_queue_bulk_tx_rx(struct vchiq_instance *instance, mutex_lock(&instance->bulk_waiter_list_mutex); list_add(&waiter->list, &instance->bulk_waiter_list); mutex_unlock(&instance->bulk_waiter_list_mutex); - dev_dbg(service->state->dev, "arm: saved bulk_waiter %pK for pid %d\n", + dev_dbg(service->state->dev, "arm: saved bulk_waiter %p for pid %d\n", waiter, current->pid); ret = put_user(mode_waiting, mode); @@ -512,7 +512,7 @@ static int vchiq_ioc_await_completion(struct vchiq_instance *instance, /* This must be a VCHIQ-style service */ if (args->msgbufsize < msglen) { dev_err(service->state->dev, - "arm: header %pK: msgbufsize %x < msglen %x\n", + "arm: header %p: msgbufsize %x < msglen %x\n", header, args->msgbufsize, msglen); WARN(1, "invalid message size\n"); if (ret == 0) @@ -588,7 +588,7 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) long ret = 0; int i, rc; - dev_dbg(instance->state->dev, "arm: instance %pK, cmd %s, arg %lx\n", instance, + dev_dbg(instance->state->dev, "arm: instance %p, cmd %s, arg %lx\n", instance, ((_IOC_TYPE(cmd) == VCHIQ_IOC_MAGIC) && (_IOC_NR(cmd) <= VCHIQ_IOC_MAX)) ? ioctl_names[_IOC_NR(cmd)] : "<invalid>", arg); @@ -874,12 +874,12 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) if (!status && (ret < 0) && (ret != -EINTR) && (ret != -EWOULDBLOCK)) { dev_dbg(instance->state->dev, - "arm: ioctl instance %pK, cmd %s -> status %d, %ld\n", + "arm: ioctl instance %p, cmd %s -> status %d, %ld\n", instance, (_IOC_NR(cmd) <= VCHIQ_IOC_MAX) ? ioctl_names[_IOC_NR(cmd)] : "<invalid>", status, ret); } else { dev_dbg(instance->state->dev, - "arm: ioctl instance %pK, cmd %s -> status %d\n, %ld\n", + "arm: ioctl instance %p, cmd %s -> status %d\n, %ld\n", instance, (_IOC_NR(cmd) <= VCHIQ_IOC_MAX) ? ioctl_names[_IOC_NR(cmd)] : "<invalid>", status, ret); }
diff --git a/drivers/target/iscsi/iscsi_target_erl0.c b/drivers/target/iscsi/iscsi_target_erl0.c index 07e9cf4..f0d7eeb 100644 --- a/drivers/target/iscsi/iscsi_target_erl0.c +++ b/drivers/target/iscsi/iscsi_target_erl0.c
@@ -810,7 +810,7 @@ int iscsit_stop_time2retain_timer(struct iscsit_session *sess) sess->time2retain_timer_flags |= ISCSI_TF_STOP; spin_unlock(&se_tpg->session_lock); - del_timer_sync(&sess->time2retain_timer); + timer_delete_sync(&sess->time2retain_timer); spin_lock(&se_tpg->session_lock); sess->time2retain_timer_flags &= ~ISCSI_TF_RUNNING;
diff --git a/drivers/target/iscsi/iscsi_target_erl1.c b/drivers/target/iscsi/iscsi_target_erl1.c index d9a6242..e7c3c4c 100644 --- a/drivers/target/iscsi/iscsi_target_erl1.c +++ b/drivers/target/iscsi/iscsi_target_erl1.c
@@ -1227,7 +1227,7 @@ void iscsit_stop_dataout_timer(struct iscsit_cmd *cmd) cmd->dataout_timer_flags |= ISCSI_TF_STOP; spin_unlock_bh(&cmd->dataout_timeout_lock); - del_timer_sync(&cmd->dataout_timer); + timer_delete_sync(&cmd->dataout_timer); spin_lock_bh(&cmd->dataout_timeout_lock); cmd->dataout_timer_flags &= ~ISCSI_TF_RUNNING;
diff --git a/drivers/target/iscsi/iscsi_target_util.c b/drivers/target/iscsi/iscsi_target_util.c index ed2dadb..0bd62ab 100644 --- a/drivers/target/iscsi/iscsi_target_util.c +++ b/drivers/target/iscsi/iscsi_target_util.c
@@ -922,7 +922,7 @@ void iscsit_stop_nopin_response_timer(struct iscsit_conn *conn) conn->nopin_response_timer_flags |= ISCSI_TF_STOP; spin_unlock_bh(&conn->nopin_timer_lock); - del_timer_sync(&conn->nopin_response_timer); + timer_delete_sync(&conn->nopin_response_timer); spin_lock_bh(&conn->nopin_timer_lock); conn->nopin_response_timer_flags &= ~ISCSI_TF_RUNNING; @@ -989,7 +989,7 @@ void iscsit_stop_nopin_timer(struct iscsit_conn *conn) conn->nopin_timer_flags |= ISCSI_TF_STOP; spin_unlock_bh(&conn->nopin_timer_lock); - del_timer_sync(&conn->nopin_timer); + timer_delete_sync(&conn->nopin_timer); spin_lock_bh(&conn->nopin_timer_lock); conn->nopin_timer_flags &= ~ISCSI_TF_RUNNING;
diff --git a/drivers/target/target_core_user.c b/drivers/target/target_core_user.c index 0f5d820..43872cc 100644 --- a/drivers/target/target_core_user.c +++ b/drivers/target/target_core_user.c
@@ -1232,7 +1232,7 @@ static void tcmu_set_next_deadline(struct list_head *queue, cmd = list_first_entry(queue, struct tcmu_cmd, queue_entry); mod_timer(timer, cmd->deadline); } else - del_timer(timer); + timer_delete(timer); } static int @@ -2321,8 +2321,8 @@ static void tcmu_destroy_device(struct se_device *dev) { struct tcmu_dev *udev = TCMU_DEV(dev); - del_timer_sync(&udev->cmd_timer); - del_timer_sync(&udev->qfull_timer); + timer_delete_sync(&udev->cmd_timer); + timer_delete_sync(&udev->qfull_timer); mutex_lock(&root_udev_mutex); list_del(&udev->node); @@ -2408,7 +2408,7 @@ static void tcmu_reset_ring(struct tcmu_dev *udev, u8 err_level) tcmu_flush_dcache_range(mb, sizeof(*mb)); clear_bit(TCMU_DEV_BIT_BROKEN, &udev->flags); - del_timer(&udev->cmd_timer); + timer_delete(&udev->cmd_timer); /* * ring is empty and qfull queue never contains aborted commands.
diff --git a/drivers/thunderbolt/retimer.c b/drivers/thunderbolt/retimer.c index 1f25529..361fece 100644 --- a/drivers/thunderbolt/retimer.c +++ b/drivers/thunderbolt/retimer.c
@@ -93,9 +93,11 @@ static int tb_retimer_nvm_add(struct tb_retimer *rt) if (ret) goto err_nvm; - ret = tb_nvm_add_non_active(nvm, nvm_write); - if (ret) - goto err_nvm; + if (!rt->no_nvm_upgrade) { + ret = tb_nvm_add_non_active(nvm, nvm_write); + if (ret) + goto err_nvm; + } rt->nvm = nvm; dev_dbg(&rt->dev, "NVM version %x.%x\n", nvm->major, nvm->minor);
diff --git a/drivers/thunderbolt/tb.c b/drivers/thunderbolt/tb.c index 390abcf..8c527af 100644 --- a/drivers/thunderbolt/tb.c +++ b/drivers/thunderbolt/tb.c
@@ -1305,12 +1305,16 @@ static void tb_scan_port(struct tb_port *port) goto out_rpm_put; } - tb_retimer_scan(port, true); - sw = tb_switch_alloc(port->sw->tb, &port->sw->dev, tb_downstream_route(port)); if (IS_ERR(sw)) { /* + * Make the downstream retimers available even if there + * is no router connected. + */ + tb_retimer_scan(port, true); + + /* * If there is an error accessing the connected switch * it may be connected to another domain. Also we allow * the other domain to be connected to a max depth switch. @@ -1360,6 +1364,14 @@ static void tb_scan_port(struct tb_port *port) tb_configure_link(port, upstream_port, sw); /* + * Scan for downstream retimers. We only scan them after the + * router has been enumerated to avoid issues with certain + * Pluggable devices that expect the host to enumerate them + * within certain timeout. + */ + tb_retimer_scan(port, true); + + /* * CL0s and CL1 are enabled and supported together. * Silently ignore CLx enabling in case CLx is not supported. */
diff --git a/drivers/thunderbolt/tunnel.c b/drivers/thunderbolt/tunnel.c index 717b31d..76254ed 100644 --- a/drivers/thunderbolt/tunnel.c +++ b/drivers/thunderbolt/tunnel.c
@@ -2229,19 +2229,15 @@ struct tb_tunnel *tb_tunnel_alloc_usb3(struct tb *tb, struct tb_port *up, path = tb_path_alloc(tb, down, TB_USB3_HOPID, up, TB_USB3_HOPID, 0, "USB3 Down"); - if (!path) { - tb_tunnel_put(tunnel); - return NULL; - } + if (!path) + goto err_free; tb_usb3_init_path(path); tunnel->paths[TB_USB3_PATH_DOWN] = path; path = tb_path_alloc(tb, up, TB_USB3_HOPID, down, TB_USB3_HOPID, 0, "USB3 Up"); - if (!path) { - tb_tunnel_put(tunnel); - return NULL; - } + if (!path) + goto err_free; tb_usb3_init_path(path); tunnel->paths[TB_USB3_PATH_UP] = path; @@ -2258,6 +2254,10 @@ struct tb_tunnel *tb_tunnel_alloc_usb3(struct tb *tb, struct tb_port *up, } return tunnel; + +err_free: + tb_tunnel_put(tunnel); + return NULL; } /**
diff --git a/drivers/tty/Kconfig b/drivers/tty/Kconfig index 7fb81bb..149f3d5 100644 --- a/drivers/tty/Kconfig +++ b/drivers/tty/Kconfig
@@ -210,7 +210,7 @@ config MOXA_INTELLIO tristate "Moxa Intellio support" - depends on SERIAL_NONSTANDARD && (ISA || EISA || PCI) + depends on SERIAL_NONSTANDARD && PCI select FW_LOADER help Say Y here if you have a Moxa Intellio multiport serial card.
diff --git a/drivers/tty/ipwireless/hardware.c b/drivers/tty/ipwireless/hardware.c index 001ec31..c13f523 100644 --- a/drivers/tty/ipwireless/hardware.c +++ b/drivers/tty/ipwireless/hardware.c
@@ -1496,7 +1496,7 @@ static void __handle_setup_get_version_rsp(struct ipw_hardware *hw) static void handle_setup_get_version_rsp(struct ipw_hardware *hw, unsigned char vers_no) { - del_timer(&hw->setup_timer); + timer_delete(&hw->setup_timer); hw->initializing = 0; printk(KERN_INFO IPWIRELESS_PCCARD_NAME ": card is ready.\n"); @@ -1721,7 +1721,7 @@ void ipwireless_stop_interrupts(struct ipw_hardware *hw) if (!hw->shutting_down) { /* Tell everyone we are going down. */ hw->shutting_down = 1; - del_timer(&hw->setup_timer); + timer_delete(&hw->setup_timer); /* Prevent the hardware from sending any more interrupts */ do_close_hardware(hw);
diff --git a/drivers/tty/mips_ejtag_fdc.c b/drivers/tty/mips_ejtag_fdc.c index 58b28be..fa47bfcf 100644 --- a/drivers/tty/mips_ejtag_fdc.c +++ b/drivers/tty/mips_ejtag_fdc.c
@@ -1031,7 +1031,7 @@ static int mips_ejtag_fdc_tty_probe(struct mips_cdmm_device *dev) raw_spin_unlock_irq(&priv->lock); } else { priv->removing = true; - del_timer_sync(&priv->poll_timer); + timer_delete_sync(&priv->poll_timer); } kthread_stop(priv->thread); err_destroy_ports: @@ -1061,7 +1061,7 @@ static int mips_ejtag_fdc_tty_cpu_down(struct mips_cdmm_device *dev) raw_spin_unlock_irq(&priv->lock); } else { priv->removing = true; - del_timer_sync(&priv->poll_timer); + timer_delete_sync(&priv->poll_timer); } kthread_stop(priv->thread);
diff --git a/drivers/tty/moxa.c b/drivers/tty/moxa.c index ebaada8..329b30f 100644 --- a/drivers/tty/moxa.c +++ b/drivers/tty/moxa.c
@@ -43,15 +43,6 @@ #include <linux/ratelimit.h> #include <asm/io.h> -#include <linux/uaccess.h> - -#define MOXA 0x400 -#define MOXA_GET_IQUEUE (MOXA + 1) /* get input buffered count */ -#define MOXA_GET_OQUEUE (MOXA + 2) /* get output buffered count */ -#define MOXA_GETDATACOUNT (MOXA + 23) -#define MOXA_GET_IOQUEUE (MOXA + 27) -#define MOXA_FLUSH_QUEUE (MOXA + 28) -#define MOXA_GETMSTATUS (MOXA + 65) /* * System Configuration @@ -347,8 +338,6 @@ #define MX_PARMARK 0xA0 #define MX_PARSPACE 0x20 -#define MOXA_VERSION "6.0k" - #define MOXA_FW_HDRLEN 32 #define MOXAMAJOR 172 @@ -357,33 +346,21 @@ #define MAX_PORTS_PER_BOARD 32 /* Don't change this value */ #define MAX_PORTS (MAX_BOARDS * MAX_PORTS_PER_BOARD) -#define MOXA_IS_320(brd) ((brd)->boardType == MOXA_BOARD_C320_ISA || \ - (brd)->boardType == MOXA_BOARD_C320_PCI) - -/* - * Define the Moxa PCI vendor and device IDs. - */ -#define MOXA_BUS_TYPE_ISA 0 -#define MOXA_BUS_TYPE_PCI 1 +#define MOXA_IS_320(brd) ((brd)->boardType == MOXA_BOARD_C320_PCI) enum { MOXA_BOARD_C218_PCI = 1, - MOXA_BOARD_C218_ISA, MOXA_BOARD_C320_PCI, - MOXA_BOARD_C320_ISA, MOXA_BOARD_CP204J, }; static char *moxa_brdname[] = { "C218 Turbo PCI series", - "C218 Turbo ISA series", "C320 Turbo PCI series", - "C320 Turbo ISA series", "CP-204J series", }; -#ifdef CONFIG_PCI static const struct pci_device_id moxa_pcibrds[] = { { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_C218), .driver_data = MOXA_BOARD_C218_PCI }, @@ -394,14 +371,12 @@ static const struct pci_device_id moxa_pcibrds[] = { { 0 } }; MODULE_DEVICE_TABLE(pci, moxa_pcibrds); -#endif /* CONFIG_PCI */ struct moxa_port; static struct moxa_board_conf { int boardType; int numPorts; - int busType; unsigned int ready; @@ -413,19 +388,6 @@ static struct moxa_board_conf { void __iomem *intTable; } moxa_boards[MAX_BOARDS]; -struct mxser_mstatus { - tcflag_t cflag; - int cts; - int dsr; - int ri; - int dcd; -}; - -struct moxaq_str { - int inq; - int outq; -}; - struct moxa_port { struct tty_port port; struct moxa_board_conf *board; @@ -440,12 +402,6 @@ struct moxa_port { u8 lowChkFlag; }; -struct mon_str { - int tick; - int rxcnt[MAX_PORTS]; - int txcnt[MAX_PORTS]; -}; - /* statusflags */ #define TXSTOPPED 1 #define LOWWAIT 2 @@ -455,17 +411,11 @@ struct mon_str { #define WAKEUP_CHARS 256 static int ttymajor = MOXAMAJOR; -static struct mon_str moxaLog; static unsigned int moxaFuncTout = HZ / 2; static unsigned int moxaLowWaterChk; static DEFINE_MUTEX(moxa_openlock); static DEFINE_SPINLOCK(moxa_lock); -static unsigned long baseaddr[MAX_BOARDS]; -static unsigned int type[MAX_BOARDS]; -static unsigned int numports[MAX_BOARDS]; -static struct tty_port moxa_service_port; - MODULE_AUTHOR("William Chen"); MODULE_DESCRIPTION("MOXA Intellio Family Multiport Board Device Driver"); MODULE_LICENSE("GPL"); @@ -473,13 +423,6 @@ MODULE_FIRMWARE("c218tunx.cod"); MODULE_FIRMWARE("cp204unx.cod"); MODULE_FIRMWARE("c320tunx.cod"); -module_param_array(type, uint, NULL, 0); -MODULE_PARM_DESC(type, "card type: C218=2, C320=4"); -module_param_hw_array(baseaddr, ulong, ioport, NULL, 0); -MODULE_PARM_DESC(baseaddr, "base address"); -module_param_array(numports, uint, NULL, 0); -MODULE_PARM_DESC(numports, "numports (ignored for C218)"); - module_param(ttymajor, int, 0); /* @@ -583,104 +526,6 @@ static void moxa_low_water_check(void __iomem *ofsAddr) * TTY operations */ -static int moxa_ioctl(struct tty_struct *tty, - unsigned int cmd, unsigned long arg) -{ - struct moxa_port *ch = tty->driver_data; - void __user *argp = (void __user *)arg; - int status, ret = 0; - - if (tty->index == MAX_PORTS) { - if (cmd != MOXA_GETDATACOUNT && cmd != MOXA_GET_IOQUEUE && - cmd != MOXA_GETMSTATUS) - return -EINVAL; - } else if (!ch) - return -ENODEV; - - switch (cmd) { - case MOXA_GETDATACOUNT: - moxaLog.tick = jiffies; - if (copy_to_user(argp, &moxaLog, sizeof(moxaLog))) - ret = -EFAULT; - break; - case MOXA_FLUSH_QUEUE: - MoxaPortFlushData(ch, arg); - break; - case MOXA_GET_IOQUEUE: { - struct moxaq_str __user *argm = argp; - struct moxaq_str tmp; - struct moxa_port *p; - unsigned int i, j; - - for (i = 0; i < MAX_BOARDS; i++) { - p = moxa_boards[i].ports; - for (j = 0; j < MAX_PORTS_PER_BOARD; j++, p++, argm++) { - memset(&tmp, 0, sizeof(tmp)); - spin_lock_bh(&moxa_lock); - if (moxa_boards[i].ready) { - tmp.inq = MoxaPortRxQueue(p); - tmp.outq = MoxaPortTxQueue(p); - } - spin_unlock_bh(&moxa_lock); - if (copy_to_user(argm, &tmp, sizeof(tmp))) - return -EFAULT; - } - } - break; - } case MOXA_GET_OQUEUE: - status = MoxaPortTxQueue(ch); - ret = put_user(status, (unsigned long __user *)argp); - break; - case MOXA_GET_IQUEUE: - status = MoxaPortRxQueue(ch); - ret = put_user(status, (unsigned long __user *)argp); - break; - case MOXA_GETMSTATUS: { - struct mxser_mstatus __user *argm = argp; - struct mxser_mstatus tmp; - struct moxa_port *p; - unsigned int i, j; - - for (i = 0; i < MAX_BOARDS; i++) { - p = moxa_boards[i].ports; - for (j = 0; j < MAX_PORTS_PER_BOARD; j++, p++, argm++) { - struct tty_struct *ttyp; - memset(&tmp, 0, sizeof(tmp)); - spin_lock_bh(&moxa_lock); - if (!moxa_boards[i].ready) { - spin_unlock_bh(&moxa_lock); - goto copy; - } - - status = MoxaPortLineStatus(p); - spin_unlock_bh(&moxa_lock); - - if (status & 1) - tmp.cts = 1; - if (status & 2) - tmp.dsr = 1; - if (status & 4) - tmp.dcd = 1; - - ttyp = tty_port_tty_get(&p->port); - if (!ttyp) - tmp.cflag = p->cflag; - else - tmp.cflag = ttyp->termios.c_cflag; - tty_kref_put(ttyp); -copy: - if (copy_to_user(argm, &tmp, sizeof(tmp))) - return -EFAULT; - } - } - break; - } - default: - ret = -ENOIOCTLCMD; - } - return ret; -} - static int moxa_break_ctl(struct tty_struct *tty, int state) { struct moxa_port *port = tty->driver_data; @@ -697,7 +542,6 @@ static const struct tty_operations moxa_ops = { .write_room = moxa_write_room, .flush_buffer = moxa_flush_buffer, .chars_in_buffer = moxa_chars_in_buffer, - .ioctl = moxa_ioctl, .set_termios = moxa_set_termios, .stop = moxa_stop, .start = moxa_start, @@ -725,7 +569,6 @@ static DEFINE_TIMER(moxaTimer, moxa_poll); static int moxa_check_fw_model(struct moxa_board_conf *brd, u8 model) { switch (brd->boardType) { - case MOXA_BOARD_C218_ISA: case MOXA_BOARD_C218_PCI: if (model != 1) goto err; @@ -769,7 +612,6 @@ static int moxa_load_bios(struct moxa_board_conf *brd, const u8 *buf, msleep(2000); switch (brd->boardType) { - case MOXA_BOARD_C218_ISA: case MOXA_BOARD_C218_PCI: tmp = readw(baseAddr + C218_key); if (tmp != C218_KeyCode) @@ -833,7 +675,6 @@ static int moxa_real_load_code(struct moxa_board_conf *brd, const void *ptr, switch (brd->boardType) { case MOXA_BOARD_CP204J: - case MOXA_BOARD_C218_ISA: case MOXA_BOARD_C218_PCI: key = C218_key; loadbuf = C218_LoadBuf; @@ -898,15 +739,9 @@ static int moxa_real_load_code(struct moxa_board_conf *brd, const void *ptr, return -EIO; if (MOXA_IS_320(brd)) { - if (brd->busType == MOXA_BUS_TYPE_PCI) { /* ASIC board */ - writew(0x3800, baseAddr + TMS320_PORT1); - writew(0x3900, baseAddr + TMS320_PORT2); - writew(28499, baseAddr + TMS320_CLOCK); - } else { - writew(0x3200, baseAddr + TMS320_PORT1); - writew(0x3400, baseAddr + TMS320_PORT2); - writew(19999, baseAddr + TMS320_CLOCK); - } + writew(0x3800, baseAddr + TMS320_PORT1); + writew(0x3900, baseAddr + TMS320_PORT2); + writew(28499, baseAddr + TMS320_CLOCK); } writew(1, baseAddr + Disable_IRQ); writew(0, baseAddr + Magic_no); @@ -957,7 +792,6 @@ static int moxa_load_code(struct moxa_board_conf *brd, const void *ptr, return retval; switch (brd->boardType) { - case MOXA_BOARD_C218_ISA: case MOXA_BOARD_C218_PCI: case MOXA_BOARD_CP204J: port = brd->ports; @@ -1141,7 +975,6 @@ static int moxa_init_board(struct moxa_board_conf *brd, struct device *dev) } switch (brd->boardType) { - case MOXA_BOARD_C218_ISA: case MOXA_BOARD_C218_PCI: file = "c218tunx.cod"; break; @@ -1227,7 +1060,6 @@ static void moxa_board_deinit(struct moxa_board_conf *brd) kfree(brd->ports); } -#ifdef CONFIG_PCI static int moxa_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { @@ -1270,7 +1102,6 @@ static int moxa_pci_probe(struct pci_dev *pdev, board->boardType = board_type; switch (board_type) { - case MOXA_BOARD_C218_ISA: case MOXA_BOARD_C218_PCI: board->numPorts = 8; break; @@ -1282,7 +1113,6 @@ static int moxa_pci_probe(struct pci_dev *pdev, board->numPorts = 0; break; } - board->busType = MOXA_BUS_TYPE_PCI; retval = moxa_init_board(board, &pdev->dev); if (retval) @@ -1318,21 +1148,12 @@ static struct pci_driver moxa_pci_driver = { .probe = moxa_pci_probe, .remove = moxa_pci_remove }; -#endif /* CONFIG_PCI */ static int __init moxa_init(void) { - unsigned int isabrds = 0; int retval = 0; - struct moxa_board_conf *brd = moxa_boards; - unsigned int i; - printk(KERN_INFO "MOXA Intellio family driver version %s\n", - MOXA_VERSION); - - tty_port_init(&moxa_service_port); - - moxaDriver = tty_alloc_driver(MAX_PORTS + 1, + moxaDriver = tty_alloc_driver(MAX_PORTS, TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV); if (IS_ERR(moxaDriver)) @@ -1348,8 +1169,6 @@ static int __init moxa_init(void) moxaDriver->init_termios.c_ispeed = 9600; moxaDriver->init_termios.c_ospeed = 9600; tty_set_operations(moxaDriver, &moxa_ops); - /* Having one more port only for ioctls is ugly */ - tty_port_link_device(&moxa_service_port, moxaDriver, MAX_PORTS); if (tty_register_driver(moxaDriver)) { printk(KERN_ERR "can't register MOXA Smartio tty driver!\n"); @@ -1357,66 +1176,18 @@ static int __init moxa_init(void) return -1; } - /* Find the boards defined from module args. */ - - for (i = 0; i < MAX_BOARDS; i++) { - if (!baseaddr[i]) - break; - if (type[i] == MOXA_BOARD_C218_ISA || - type[i] == MOXA_BOARD_C320_ISA) { - pr_debug("Moxa board %2d: %s board(baseAddr=%lx)\n", - isabrds + 1, moxa_brdname[type[i] - 1], - baseaddr[i]); - brd->boardType = type[i]; - brd->numPorts = type[i] == MOXA_BOARD_C218_ISA ? 8 : - numports[i]; - brd->busType = MOXA_BUS_TYPE_ISA; - brd->basemem = ioremap(baseaddr[i], 0x4000); - if (!brd->basemem) { - printk(KERN_ERR "MOXA: can't remap %lx\n", - baseaddr[i]); - continue; - } - if (moxa_init_board(brd, NULL)) { - iounmap(brd->basemem); - brd->basemem = NULL; - continue; - } - - printk(KERN_INFO "MOXA isa board found at 0x%.8lx and " - "ready (%u ports, firmware loaded)\n", - baseaddr[i], brd->numPorts); - - brd++; - isabrds++; - } - } - -#ifdef CONFIG_PCI retval = pci_register_driver(&moxa_pci_driver); - if (retval) { + if (retval) printk(KERN_ERR "Can't register MOXA pci driver!\n"); - if (isabrds) - retval = 0; - } -#endif return retval; } static void __exit moxa_exit(void) { - unsigned int i; - -#ifdef CONFIG_PCI pci_unregister_driver(&moxa_pci_driver); -#endif - for (i = 0; i < MAX_BOARDS; i++) /* ISA boards */ - if (moxa_boards[i].ready) - moxa_board_deinit(&moxa_boards[i]); - - del_timer_sync(&moxaTimer); + timer_delete_sync(&moxaTimer); tty_unregister_driver(moxaDriver); tty_driver_kref_put(moxaDriver); @@ -1457,9 +1228,6 @@ static int moxa_open(struct tty_struct *tty, struct file *filp) int port; port = tty->index; - if (port == MAX_PORTS) { - return capable(CAP_SYS_ADMIN) ? 0 : -EPERM; - } if (mutex_lock_interruptible(&moxa_openlock)) return -ERESTARTSYS; brd = &moxa_boards[port / MAX_PORTS_PER_BOARD]; @@ -2182,7 +1950,6 @@ static ssize_t MoxaPortWriteData(struct tty_struct *tty, const u8 *buffer, c = (head > tail) ? (head - tail - 1) : (head - tail + tx_mask); if (c > len) c = len; - moxaLog.txcnt[port->port.tty->index] += c; total = c; if (spage == epage) { bufhead = readw(ofsAddr + Ofs_txb); @@ -2224,7 +1991,6 @@ static ssize_t MoxaPortWriteData(struct tty_struct *tty, const u8 *buffer, static int MoxaPortReadData(struct moxa_port *port) { - struct tty_struct *tty = port->port.tty; void __iomem *baseAddr, *ofsAddr, *ofs; u8 *dst; unsigned int count, len, total; @@ -2243,7 +2009,6 @@ static int MoxaPortReadData(struct moxa_port *port) return 0; total = count; - moxaLog.rxcnt[tty->index] += total; if (spage == epage) { bufhead = readw(ofsAddr + Ofs_rxb); writew(spage, baseAddr + Control_reg); @@ -2331,8 +2096,6 @@ static int moxa_get_serial_info(struct tty_struct *tty, { struct moxa_port *info = tty->driver_data; - if (tty->index == MAX_PORTS) - return -EINVAL; if (!info) return -ENODEV; mutex_lock(&info->port.mutex); @@ -2352,8 +2115,6 @@ static int moxa_set_serial_info(struct tty_struct *tty, struct moxa_port *info = tty->driver_data; unsigned int close_delay; - if (tty->index == MAX_PORTS) - return -EINVAL; if (!info) return -ENODEV;
diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c index 363afe1..40a336e 100644 --- a/drivers/tty/n_gsm.c +++ b/drivers/tty/n_gsm.c
@@ -1941,7 +1941,7 @@ static void gsm_control_response(struct gsm_mux *gsm, unsigned int command, /* Does the reply match our command */ if (ctrl != NULL && (command == ctrl->cmd || command == CMD_NSC)) { /* Our command was replied to, kill the retry timer */ - del_timer(&gsm->t2_timer); + timer_delete(&gsm->t2_timer); gsm->pending_cmd = NULL; /* Rejected by the other end */ if (command == CMD_NSC) @@ -2131,7 +2131,7 @@ static int gsm_control_wait(struct gsm_mux *gsm, struct gsm_control *control) static void gsm_dlci_close(struct gsm_dlci *dlci) { - del_timer(&dlci->t1); + timer_delete(&dlci->t1); if (debug & DBG_ERRORS) pr_debug("DLCI %d goes closed.\n", dlci->addr); dlci->state = DLCI_CLOSED; @@ -2144,7 +2144,7 @@ static void gsm_dlci_close(struct gsm_dlci *dlci) tty_port_set_initialized(&dlci->port, false); wake_up_interruptible(&dlci->port.open_wait); } else { - del_timer(&dlci->gsm->ka_timer); + timer_delete(&dlci->gsm->ka_timer); dlci->gsm->dead = true; } /* A DLCI 0 close is a MUX termination so we need to kick that @@ -2166,7 +2166,7 @@ static void gsm_dlci_open(struct gsm_dlci *dlci) /* Note that SABM UA .. SABM UA first UA lost can mean that we go open -> open */ - del_timer(&dlci->t1); + timer_delete(&dlci->t1); /* This will let a tty open continue */ dlci->state = DLCI_OPEN; dlci->constipated = false; @@ -3144,9 +3144,9 @@ static void gsm_cleanup_mux(struct gsm_mux *gsm, bool disc) } /* Finish outstanding timers, making sure they are done */ - del_timer_sync(&gsm->kick_timer); - del_timer_sync(&gsm->t2_timer); - del_timer_sync(&gsm->ka_timer); + timer_delete_sync(&gsm->kick_timer); + timer_delete_sync(&gsm->t2_timer); + timer_delete_sync(&gsm->ka_timer); /* Finish writing to ldisc */ flush_work(&gsm->tx_work);
diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 5e9ca43..6af3f3a 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c
@@ -56,6 +56,8 @@ */ #define WAKEUP_CHARS 256 +#define N_TTY_BUF_SIZE 4096 + /* * This defines the low- and high-watermarks for throttling and * unthrottling the TTY driver. These watermarks are used for @@ -79,14 +81,6 @@ #define ECHO_BLOCK 256 #define ECHO_DISCARD_WATERMARK N_TTY_BUF_SIZE - (ECHO_BLOCK + 32) - -#undef N_TTY_TRACE -#ifdef N_TTY_TRACE -# define n_tty_trace(f, args...) trace_printk(f, ##args) -#else -# define n_tty_trace(f, args...) no_printk(f, ##args) -#endif - struct n_tty_data { /* producer-published */ size_t read_head; @@ -486,18 +480,13 @@ static int do_output_char(u8 c, struct tty_struct *tty, int space) static int process_output(u8 c, struct tty_struct *tty) { struct n_tty_data *ldata = tty->disc_data; - int space, retval; - mutex_lock(&ldata->output_lock); + guard(mutex)(&ldata->output_lock); - space = tty_write_room(tty); - retval = do_output_char(c, tty, space); - - mutex_unlock(&ldata->output_lock); - if (retval < 0) + if (do_output_char(c, tty, tty_write_room(tty)) < 0) return -1; - else - return 0; + + return 0; } /** @@ -522,17 +511,15 @@ static ssize_t process_output_block(struct tty_struct *tty, const u8 *buf, unsigned int nr) { struct n_tty_data *ldata = tty->disc_data; - int space; - int i; + unsigned int space, i; const u8 *cp; - mutex_lock(&ldata->output_lock); + guard(mutex)(&ldata->output_lock); space = tty_write_room(tty); - if (space <= 0) { - mutex_unlock(&ldata->output_lock); - return space; - } + if (space == 0) + return 0; + if (nr > space) nr = space; @@ -544,18 +531,18 @@ static ssize_t process_output_block(struct tty_struct *tty, if (O_ONLRET(tty)) ldata->column = 0; if (O_ONLCR(tty)) - goto break_out; + goto do_write; ldata->canon_column = ldata->column; break; case '\r': if (O_ONOCR(tty) && ldata->column == 0) - goto break_out; + goto do_write; if (O_OCRNL(tty)) - goto break_out; + goto do_write; ldata->canon_column = ldata->column = 0; break; case '\t': - goto break_out; + goto do_write; case '\b': if (ldata->column > 0) ldata->column--; @@ -563,18 +550,15 @@ static ssize_t process_output_block(struct tty_struct *tty, default: if (!iscntrl(c)) { if (O_OLCUC(tty)) - goto break_out; + goto do_write; if (!is_continuation(c, tty)) ldata->column++; } break; } } -break_out: - i = tty->ops->write(tty, buf, i); - - mutex_unlock(&ldata->output_lock); - return i; +do_write: + return tty->ops->write(tty, buf, i); } static int n_tty_process_echo_ops(struct tty_struct *tty, size_t *tail, @@ -696,7 +680,7 @@ static int n_tty_process_echo_ops(struct tty_struct *tty, size_t *tail, static size_t __process_echoes(struct tty_struct *tty) { struct n_tty_data *ldata = tty->disc_data; - int space, old_space; + unsigned int space, old_space; size_t tail; u8 c; @@ -2034,9 +2018,6 @@ static bool canon_copy_from_read_buf(const struct tty_struct *tty, u8 **kbp, tail = MASK(ldata->read_tail); size = min_t(size_t, tail + n, N_TTY_BUF_SIZE); - n_tty_trace("%s: nr:%zu tail:%zu n:%zu size:%zu\n", - __func__, *nr, tail, n, size); - eol = find_next_bit(ldata->read_flags, size, tail); more = n - (size - tail); if (eol == N_TTY_BUF_SIZE && more) { @@ -2054,9 +2035,6 @@ static bool canon_copy_from_read_buf(const struct tty_struct *tty, u8 **kbp, if (!found || read_buf(ldata, eol) != __DISABLED_CHAR) n = c; - n_tty_trace("%s: eol:%zu found:%d n:%zu c:%zu tail:%zu more:%zu\n", - __func__, eol, found, n, c, tail, more); - tty_copy(tty, *kbp, tail, n); *kbp += n; *nr -= n; @@ -2133,6 +2111,66 @@ static int job_control(struct tty_struct *tty, struct file *file) return __tty_check_change(tty, SIGTTIN); } +/* + * We still hold the atomic_read_lock and the termios_rwsem, and can just + * continue to copy data. + */ +static ssize_t n_tty_continue_cookie(struct tty_struct *tty, u8 *kbuf, + size_t nr, void **cookie) +{ + struct n_tty_data *ldata = tty->disc_data; + u8 *kb = kbuf; + + if (ldata->icanon && !L_EXTPROC(tty)) { + /* + * If we have filled the user buffer, see if we should skip an + * EOF character before releasing the lock and returning done. + */ + if (!nr) + canon_skip_eof(ldata); + else if (canon_copy_from_read_buf(tty, &kb, &nr)) + return kb - kbuf; + } else { + if (copy_from_read_buf(tty, &kb, &nr)) + return kb - kbuf; + } + + /* No more data - release locks and stop retries */ + n_tty_kick_worker(tty); + n_tty_check_unthrottle(tty); + up_read(&tty->termios_rwsem); + mutex_unlock(&ldata->atomic_read_lock); + *cookie = NULL; + + return kb - kbuf; +} + +static int n_tty_wait_for_input(struct tty_struct *tty, struct file *file, + struct wait_queue_entry *wait, long *timeout) +{ + if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) + return -EIO; + if (tty_hung_up_p(file)) + return 0; + /* + * Abort readers for ttys which never actually get hung up. + * See __tty_hangup(). + */ + if (test_bit(TTY_HUPPING, &tty->flags)) + return 0; + if (!*timeout) + return 0; + if (tty_io_nonblock(tty, file)) + return -EAGAIN; + if (signal_pending(current)) + return -ERESTARTSYS; + + up_read(&tty->termios_rwsem); + *timeout = wait_woken(wait, TASK_INTERRUPTIBLE, *timeout); + down_read(&tty->termios_rwsem); + + return 1; +} /** * n_tty_read - read function for tty @@ -2166,36 +2204,9 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, u8 *kbuf, bool packet; size_t old_tail; - /* - * Is this a continuation of a read started earler? - * - * If so, we still hold the atomic_read_lock and the - * termios_rwsem, and can just continue to copy data. - */ - if (*cookie) { - if (ldata->icanon && !L_EXTPROC(tty)) { - /* - * If we have filled the user buffer, see - * if we should skip an EOF character before - * releasing the lock and returning done. - */ - if (!nr) - canon_skip_eof(ldata); - else if (canon_copy_from_read_buf(tty, &kb, &nr)) - return kb - kbuf; - } else { - if (copy_from_read_buf(tty, &kb, &nr)) - return kb - kbuf; - } - - /* No more data - release locks and stop retries */ - n_tty_kick_worker(tty); - n_tty_check_unthrottle(tty); - up_read(&tty->termios_rwsem); - mutex_unlock(&ldata->atomic_read_lock); - *cookie = NULL; - return kb - kbuf; - } + /* Is this a continuation of a read started earlier? */ + if (*cookie) + return n_tty_continue_cookie(tty, kbuf, nr, cookie); retval = job_control(tty, file); if (retval < 0) @@ -2250,34 +2261,12 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, u8 *kbuf, tty_buffer_flush_work(tty->port); down_read(&tty->termios_rwsem); if (!input_available_p(tty, 0)) { - if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) { - retval = -EIO; + int ret = n_tty_wait_for_input(tty, file, &wait, + &timeout); + if (ret <= 0) { + retval = ret; break; } - if (tty_hung_up_p(file)) - break; - /* - * Abort readers for ttys which never actually - * get hung up. See __tty_hangup(). - */ - if (test_bit(TTY_HUPPING, &tty->flags)) - break; - if (!timeout) - break; - if (tty_io_nonblock(tty, file)) { - retval = -EAGAIN; - break; - } - if (signal_pending(current)) { - retval = -ERESTARTSYS; - break; - } - up_read(&tty->termios_rwsem); - - timeout = wait_woken(&wait, TASK_INTERRUPTIBLE, - timeout); - - down_read(&tty->termios_rwsem); continue; } } @@ -2292,21 +2281,8 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, u8 *kbuf, nr--; } - /* - * Copy data, and if there is more to be had - * and we have nothing more to wait for, then - * let's mark us for retries. - * - * NOTE! We return here with both the termios_sem - * and atomic_read_lock still held, the retries - * will release them when done. - */ - if (copy_from_read_buf(tty, &kb, &nr) && kb - kbuf >= minimum) { -more_to_be_read: - remove_wait_queue(&tty->read_wait, &wait); - *cookie = cookie; - return kb - kbuf; - } + if (copy_from_read_buf(tty, &kb, &nr) && kb - kbuf >= minimum) + goto more_to_be_read; } n_tty_check_unthrottle(tty); @@ -2333,6 +2309,18 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, u8 *kbuf, retval = kb - kbuf; return retval; +more_to_be_read: + /* + * There is more to be had and we have nothing more to wait for, so + * let's mark us for retries. + * + * NOTE! We return here with both the termios_sem and atomic_read_lock + * still held, the retries will release them when done. + */ + remove_wait_queue(&tty->read_wait, &wait); + *cookie = cookie; + + return kb - kbuf; } /**
diff --git a/drivers/tty/serdev/core.c b/drivers/tty/serdev/core.c index ebf0bbc..eb2a2e5 100644 --- a/drivers/tty/serdev/core.c +++ b/drivers/tty/serdev/core.c
@@ -316,17 +316,6 @@ void serdev_device_write_flush(struct serdev_device *serdev) } EXPORT_SYMBOL_GPL(serdev_device_write_flush); -int serdev_device_write_room(struct serdev_device *serdev) -{ - struct serdev_controller *ctrl = serdev->ctrl; - - if (!ctrl || !ctrl->ops->write_room) - return 0; - - return serdev->ctrl->ops->write_room(ctrl); -} -EXPORT_SYMBOL_GPL(serdev_device_write_room); - unsigned int serdev_device_set_baudrate(struct serdev_device *serdev, unsigned int speed) { struct serdev_controller *ctrl = serdev->ctrl;
diff --git a/drivers/tty/serdev/serdev-ttyport.c b/drivers/tty/serdev/serdev-ttyport.c index 3d7ae7f..bab1b14 100644 --- a/drivers/tty/serdev/serdev-ttyport.c +++ b/drivers/tty/serdev/serdev-ttyport.c
@@ -92,14 +92,6 @@ static void ttyport_write_flush(struct serdev_controller *ctrl) tty_driver_flush_buffer(tty); } -static int ttyport_write_room(struct serdev_controller *ctrl) -{ - struct serport *serport = serdev_controller_get_drvdata(ctrl); - struct tty_struct *tty = serport->tty; - - return tty_write_room(tty); -} - static int ttyport_open(struct serdev_controller *ctrl) { struct serport *serport = serdev_controller_get_drvdata(ctrl); @@ -259,7 +251,6 @@ static int ttyport_break_ctl(struct serdev_controller *ctrl, unsigned int break_ static const struct serdev_controller_ops ctrl_ops = { .write_buf = ttyport_write_buf, .write_flush = ttyport_write_flush, - .write_room = ttyport_write_room, .open = ttyport_open, .close = ttyport_close, .set_flow_control = ttyport_set_flow_control,
diff --git a/drivers/tty/serial/8250/8250_aspeed_vuart.c b/drivers/tty/serial/8250/8250_aspeed_vuart.c index e5da9ce..3924470 100644 --- a/drivers/tty/serial/8250/8250_aspeed_vuart.c +++ b/drivers/tty/serial/8250/8250_aspeed_vuart.c
@@ -550,7 +550,7 @@ static void aspeed_vuart_remove(struct platform_device *pdev) { struct aspeed_vuart *vuart = platform_get_drvdata(pdev); - del_timer_sync(&vuart->unthrottle_timer); + timer_delete_sync(&vuart->unthrottle_timer); aspeed_vuart_set_enabled(vuart, false); serial8250_unregister_port(vuart->line); sysfs_remove_group(&vuart->dev->kobj, &aspeed_vuart_attr_group);
diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c index 6f676bb..5a56f85 100644 --- a/drivers/tty/serial/8250/8250_core.c +++ b/drivers/tty/serial/8250/8250_core.c
@@ -298,7 +298,7 @@ static void univ8250_release_irq(struct uart_8250_port *up) { struct uart_port *port = &up->port; - del_timer_sync(&up->timer); + timer_delete_sync(&up->timer); up->timer.function = serial8250_timeout; if (port->irq) serial_unlink_irq_chain(up);
diff --git a/drivers/tty/serial/8250/8250_dma.c b/drivers/tty/serial/8250/8250_dma.c index f245a84..bdd26c9 100644 --- a/drivers/tty/serial/8250/8250_dma.c +++ b/drivers/tty/serial/8250/8250_dma.c
@@ -162,7 +162,7 @@ void serial8250_tx_dma_flush(struct uart_8250_port *p) */ dma->tx_size = 0; - dmaengine_terminate_async(dma->rxchan); + dmaengine_terminate_async(dma->txchan); } int serial8250_rx_dma(struct uart_8250_port *p)
diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c index 6afcf27..1902f29 100644 --- a/drivers/tty/serial/8250/8250_dw.c +++ b/drivers/tty/serial/8250/8250_dw.c
@@ -107,11 +107,23 @@ static inline int dw8250_modify_msr(struct uart_port *p, int offset, int value) return value; } +/* + * This function is being called as part of the uart_port::serial_out() + * routine. Hence, it must not call serial_port_out() or serial_out() + * against the modified registers here, i.e. LCR. + */ static void dw8250_force_idle(struct uart_port *p) { struct uart_8250_port *up = up_to_u8250p(p); unsigned int lsr; + /* + * The following call currently performs serial_out() + * against the FCR register. Because it differs to LCR + * there will be no infinite loop, but if it ever gets + * modified, we might need a new custom version of it + * that avoids infinite recursion. + */ serial8250_clear_and_reinit_fifos(up); /* @@ -120,14 +132,19 @@ static void dw8250_force_idle(struct uart_port *p) * enabled. */ if (up->fcr & UART_FCR_ENABLE_FIFO) { - lsr = p->serial_in(p, UART_LSR); + lsr = serial_port_in(p, UART_LSR); if (!(lsr & UART_LSR_DR)) return; } - (void)p->serial_in(p, UART_RX); + serial_port_in(p, UART_RX); } +/* + * This function is being called as part of the uart_port::serial_out() + * routine. Hence, it must not call serial_port_out() or serial_out() + * against the modified registers here, i.e. LCR. + */ static void dw8250_check_lcr(struct uart_port *p, int offset, int value) { struct dw8250_data *d = to_dw8250_data(p->private_data); @@ -139,7 +156,7 @@ static void dw8250_check_lcr(struct uart_port *p, int offset, int value) /* Make sure LCR write wasn't ignored */ while (tries--) { - unsigned int lcr = p->serial_in(p, offset); + unsigned int lcr = serial_port_in(p, offset); if ((value & ~UART_LCR_SPAR) == (lcr & ~UART_LCR_SPAR)) return; @@ -260,7 +277,7 @@ static int dw8250_handle_irq(struct uart_port *p) { struct uart_8250_port *up = up_to_u8250p(p); struct dw8250_data *d = to_dw8250_data(p->private_data); - unsigned int iir = p->serial_in(p, UART_IIR); + unsigned int iir = serial_port_in(p, UART_IIR); bool rx_timeout = (iir & 0x3f) == UART_IIR_RX_TIMEOUT; unsigned int quirks = d->pdata->quirks; unsigned int status; @@ -281,7 +298,7 @@ static int dw8250_handle_irq(struct uart_port *p) status = serial_lsr_in(up); if (!(status & (UART_LSR_DR | UART_LSR_BI))) - (void) p->serial_in(p, UART_RX); + serial_port_in(p, UART_RX); uart_port_unlock_irqrestore(p, flags); } @@ -303,7 +320,7 @@ static int dw8250_handle_irq(struct uart_port *p) if ((iir & UART_IIR_BUSY) == UART_IIR_BUSY) { /* Clear the USR */ - (void)p->serial_in(p, d->pdata->usr_reg); + serial_port_in(p, d->pdata->usr_reg); return 1; } @@ -390,7 +407,7 @@ static void dw8250_set_termios(struct uart_port *p, struct ktermios *termios, static void dw8250_set_ldisc(struct uart_port *p, struct ktermios *termios) { struct uart_8250_port *up = up_to_u8250p(p); - unsigned int mcr = p->serial_in(p, UART_MCR); + unsigned int mcr = serial_port_in(p, UART_MCR); if (up->capabilities & UART_CAP_IRDA) { if (termios->c_line == N_IRDA) @@ -398,7 +415,7 @@ static void dw8250_set_ldisc(struct uart_port *p, struct ktermios *termios) else mcr &= ~DW_UART_MCR_SIRE; - p->serial_out(p, UART_MCR, mcr); + serial_port_out(p, UART_MCR, mcr); } serial8250_do_set_ldisc(p, termios); } @@ -421,6 +438,18 @@ static bool dw8250_idma_filter(struct dma_chan *chan, void *param) return param == chan->device->dev; } +static void dw8250_setup_dma_filter(struct uart_port *p, struct dw8250_data *data) +{ + /* Platforms with iDMA 64-bit */ + if (platform_get_resource_byname(to_platform_device(p->dev), IORESOURCE_MEM, "lpss_priv")) { + data->data.dma.rx_param = p->dev->parent; + data->data.dma.tx_param = p->dev->parent; + data->data.dma.fn = dw8250_idma_filter; + } else { + data->data.dma.fn = dw8250_fallback_dma_filter; + } +} + static u32 dw8250_rzn1_get_dmacr_burst(int max_burst) { if (max_burst >= 8) @@ -459,8 +488,8 @@ static void dw8250_prepare_rx_dma(struct uart_8250_port *p) static void dw8250_quirks(struct uart_port *p, struct dw8250_data *data) { - unsigned int quirks = data->pdata ? data->pdata->quirks : 0; - u32 cpr_value = data->pdata ? data->pdata->cpr_value : 0; + unsigned int quirks = data->pdata->quirks; + u32 cpr_value = data->pdata->cpr_value; if (quirks & DW_UART_QUIRK_CPR_VALUE) data->data.cpr_value = cpr_value; @@ -491,14 +520,6 @@ static void dw8250_quirks(struct uart_port *p, struct dw8250_data *data) p->serial_in = dw8250_serial_in32; data->uart_16550_compatible = true; } - - /* Platforms with iDMA 64-bit */ - if (platform_get_resource_byname(to_platform_device(p->dev), - IORESOURCE_MEM, "lpss_priv")) { - data->data.dma.rx_param = p->dev->parent; - data->data.dma.tx_param = p->dev->parent; - data->data.dma.fn = dw8250_idma_filter; - } } static void dw8250_reset_control_assert(void *data) @@ -520,7 +541,6 @@ static int dw8250_probe(struct platform_device *pdev) return dev_err_probe(dev, -EINVAL, "no registers defined\n"); spin_lock_init(&p->lock); - p->handle_irq = dw8250_handle_irq; p->pm = dw8250_do_pm; p->type = PORT_8250; p->flags = UPF_FIXED_PORT; @@ -532,13 +552,8 @@ static int dw8250_probe(struct platform_device *pdev) if (!data) return -ENOMEM; - data->data.dma.fn = dw8250_fallback_dma_filter; - data->pdata = device_get_match_data(p->dev); p->private_data = &data->data; - data->uart_16550_compatible = device_property_read_bool(dev, - "snps,uart-16550-compatible"); - p->mapbase = regs->start; p->mapsize = resource_size(regs); @@ -626,11 +641,19 @@ static int dw8250_probe(struct platform_device *pdev) if (err) return err; - dw8250_quirks(p, data); + data->uart_16550_compatible = device_property_read_bool(dev, "snps,uart-16550-compatible"); + + data->pdata = device_get_match_data(p->dev); + if (data->pdata) + dw8250_quirks(p, data); /* If the Busy Functionality is not implemented, don't handle it */ if (data->uart_16550_compatible) p->handle_irq = NULL; + else if (data->pdata) + p->handle_irq = dw8250_handle_irq; + + dw8250_setup_dma_filter(p, data); if (!data->skip_autocfg) dw8250_setup_port(p);
diff --git a/drivers/tty/serial/8250/8250_fsl.c b/drivers/tty/serial/8250/8250_fsl.c index 1b7bd55..649ae5c 100644 --- a/drivers/tty/serial/8250/8250_fsl.c +++ b/drivers/tty/serial/8250/8250_fsl.c
@@ -32,7 +32,7 @@ int fsl8250_handle_irq(struct uart_port *port) uart_port_lock_irqsave(&up->port, &flags); - iir = port->serial_in(port, UART_IIR); + iir = serial_port_in(port, UART_IIR); if (iir & UART_IIR_NO_INT) { uart_port_unlock_irqrestore(&up->port, flags); return 0; @@ -54,12 +54,12 @@ int fsl8250_handle_irq(struct uart_port *port) if (unlikely((iir & UART_IIR_ID) == UART_IIR_RLSI && (up->lsr_saved_flags & UART_LSR_BI))) { up->lsr_saved_flags &= ~UART_LSR_BI; - port->serial_in(port, UART_RX); + serial_port_in(port, UART_RX); uart_port_unlock_irqrestore(&up->port, flags); return 1; } - lsr = orig_lsr = up->port.serial_in(&up->port, UART_LSR); + lsr = orig_lsr = serial_port_in(port, UART_LSR); /* Process incoming characters first */ if ((lsr & (UART_LSR_DR | UART_LSR_BI)) && @@ -71,7 +71,7 @@ int fsl8250_handle_irq(struct uart_port *port) if ((orig_lsr & UART_LSR_OE) && (up->overrun_backoff_time_ms > 0)) { unsigned long delay; - up->ier = port->serial_in(port, UART_IER); + up->ier = serial_port_in(port, UART_IER); if (up->ier & (UART_IER_RLSI | UART_IER_RDI)) { port->ops->stop_rx(port); } else {
diff --git a/drivers/tty/serial/8250/8250_ni.c b/drivers/tty/serial/8250/8250_ni.c new file mode 100644 index 0000000..b10a42d --- /dev/null +++ b/drivers/tty/serial/8250/8250_ni.c
@@ -0,0 +1,461 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * NI 16550 UART Driver + * + * The National Instruments (NI) 16550 is a UART that is compatible with the + * TL16C550C and OX16C950B register interfaces, but has additional functions + * for RS-485 transceiver control. This driver implements support for the + * additional functionality on top of the standard serial8250 core. + * + * Copyright 2012-2023 National Instruments Corporation + */ + +#include <linux/acpi.h> +#include <linux/bitfield.h> +#include <linux/device.h> +#include <linux/io.h> +#include <linux/init.h> +#include <linux/module.h> +#include <linux/property.h> +#include <linux/clk.h> + +#include "8250.h" + +/* Extra bits in UART_ACR */ +#define NI16550_ACR_AUTO_DTR_EN BIT(4) + +/* TFS - TX FIFO Size */ +#define NI16550_TFS_OFFSET 0x0C +/* RFS - RX FIFO Size */ +#define NI16550_RFS_OFFSET 0x0D + +/* PMR - Port Mode Register */ +#define NI16550_PMR_OFFSET 0x0E +/* PMR[1:0] - Port Capabilities */ +#define NI16550_PMR_CAP_MASK GENMASK(1, 0) +#define NI16550_PMR_NOT_IMPL FIELD_PREP(NI16550_PMR_CAP_MASK, 0) /* not implemented */ +#define NI16550_PMR_CAP_RS232 FIELD_PREP(NI16550_PMR_CAP_MASK, 1) /* RS-232 capable */ +#define NI16550_PMR_CAP_RS485 FIELD_PREP(NI16550_PMR_CAP_MASK, 2) /* RS-485 capable */ +#define NI16550_PMR_CAP_DUAL FIELD_PREP(NI16550_PMR_CAP_MASK, 3) /* dual-port */ +/* PMR[4] - Interface Mode */ +#define NI16550_PMR_MODE_MASK GENMASK(4, 4) +#define NI16550_PMR_MODE_RS232 FIELD_PREP(NI16550_PMR_MODE_MASK, 0) /* currently 232 */ +#define NI16550_PMR_MODE_RS485 FIELD_PREP(NI16550_PMR_MODE_MASK, 1) /* currently 485 */ + +/* PCR - Port Control Register */ +/* + * Wire Mode | Tx enabled? | Rx enabled? + * ---------------|----------------------|-------------------------- + * PCR_RS422 | Always | Always + * PCR_ECHO_RS485 | When DTR asserted | Always + * PCR_DTR_RS485 | When DTR asserted | Disabled when TX enabled + * PCR_AUTO_RS485 | When data in TX FIFO | Disabled when TX enabled + */ +#define NI16550_PCR_OFFSET 0x0F +#define NI16550_PCR_WIRE_MODE_MASK GENMASK(1, 0) +#define NI16550_PCR_RS422 FIELD_PREP(NI16550_PCR_WIRE_MODE_MASK, 0) +#define NI16550_PCR_ECHO_RS485 FIELD_PREP(NI16550_PCR_WIRE_MODE_MASK, 1) +#define NI16550_PCR_DTR_RS485 FIELD_PREP(NI16550_PCR_WIRE_MODE_MASK, 2) +#define NI16550_PCR_AUTO_RS485 FIELD_PREP(NI16550_PCR_WIRE_MODE_MASK, 3) +#define NI16550_PCR_TXVR_ENABLE_BIT BIT(3) +#define NI16550_PCR_RS485_TERMINATION_BIT BIT(6) + +/* flags for ni16550_device_info */ +#define NI_HAS_PMR BIT(0) + +struct ni16550_device_info { + u32 uartclk; + u8 prescaler; + u8 flags; +}; + +struct ni16550_data { + int line; + struct clk *clk; +}; + +static int ni16550_enable_transceivers(struct uart_port *port) +{ + u8 pcr; + + pcr = port->serial_in(port, NI16550_PCR_OFFSET); + pcr |= NI16550_PCR_TXVR_ENABLE_BIT; + dev_dbg(port->dev, "enable transceivers: write pcr: 0x%02x\n", pcr); + port->serial_out(port, NI16550_PCR_OFFSET, pcr); + + return 0; +} + +static int ni16550_disable_transceivers(struct uart_port *port) +{ + u8 pcr; + + pcr = port->serial_in(port, NI16550_PCR_OFFSET); + pcr &= ~NI16550_PCR_TXVR_ENABLE_BIT; + dev_dbg(port->dev, "disable transceivers: write pcr: 0x%02x\n", pcr); + port->serial_out(port, NI16550_PCR_OFFSET, pcr); + + return 0; +} + +static int ni16550_rs485_config(struct uart_port *port, + struct ktermios *termios, + struct serial_rs485 *rs485) +{ + struct uart_8250_port *up = container_of(port, struct uart_8250_port, port); + u8 pcr; + + pcr = serial_in(up, NI16550_PCR_OFFSET); + pcr &= ~NI16550_PCR_WIRE_MODE_MASK; + + if ((rs485->flags & SER_RS485_MODE_RS422) || + !(rs485->flags & SER_RS485_ENABLED)) { + /* RS-422 */ + pcr |= NI16550_PCR_RS422; + up->acr &= ~NI16550_ACR_AUTO_DTR_EN; + } else { + /* RS-485 2-wire Auto */ + pcr |= NI16550_PCR_AUTO_RS485; + up->acr |= NI16550_ACR_AUTO_DTR_EN; + } + + dev_dbg(port->dev, "config rs485: write pcr: 0x%02x, acr: %02x\n", pcr, up->acr); + serial_out(up, NI16550_PCR_OFFSET, pcr); + serial_icr_write(up, UART_ACR, up->acr); + + return 0; +} + +static bool is_pmr_rs232_mode(struct uart_8250_port *up) +{ + u8 pmr = serial_in(up, NI16550_PMR_OFFSET); + u8 pmr_mode = pmr & NI16550_PMR_MODE_MASK; + u8 pmr_cap = pmr & NI16550_PMR_CAP_MASK; + + /* + * If the PMR is not implemented, then by default NI UARTs are + * connected to RS-485 transceivers + */ + if (pmr_cap == NI16550_PMR_NOT_IMPL) + return false; + + if (pmr_cap == NI16550_PMR_CAP_DUAL) + /* + * If the port is dual-mode capable, then read the mode bit + * to know the current mode + */ + return pmr_mode == NI16550_PMR_MODE_RS232; + /* + * If it is not dual-mode capable, then decide based on the + * capability + */ + return pmr_cap == NI16550_PMR_CAP_RS232; +} + +static void ni16550_config_prescaler(struct uart_8250_port *up, + u8 prescaler) +{ + /* + * Page in the Enhanced Mode Registers + * Sets EFR[4] for Enhanced Mode. + */ + u8 lcr_value; + u8 efr_value; + + lcr_value = serial_in(up, UART_LCR); + serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); + + efr_value = serial_in(up, UART_EFR); + efr_value |= UART_EFR_ECB; + + serial_out(up, UART_EFR, efr_value); + + /* Page out the Enhanced Mode Registers */ + serial_out(up, UART_LCR, lcr_value); + + /* Set prescaler to CPR register. */ + serial_out(up, UART_SCR, UART_CPR); + serial_out(up, UART_ICR, prescaler); +} + +static const struct serial_rs485 ni16550_rs485_supported = { + .flags = SER_RS485_ENABLED | SER_RS485_MODE_RS422 | SER_RS485_RTS_ON_SEND | + SER_RS485_RTS_AFTER_SEND, + /* + * delay_rts_* and RX_DURING_TX are not supported. + * + * RTS_{ON,AFTER}_SEND are supported, but ignored; the transceiver + * is connected in only one way and we don't need userspace to tell + * us, but want to retain compatibility with applications that do. + */ +}; + +static void ni16550_rs485_setup(struct uart_port *port) +{ + port->rs485_config = ni16550_rs485_config; + port->rs485_supported = ni16550_rs485_supported; + /* + * The hardware comes up by default in 2-wire auto mode and we + * set the flags to represent that + */ + port->rs485.flags = SER_RS485_ENABLED | SER_RS485_RTS_ON_SEND; +} + +static int ni16550_port_startup(struct uart_port *port) +{ + int ret; + + ret = serial8250_do_startup(port); + if (ret) + return ret; + + return ni16550_enable_transceivers(port); +} + +static void ni16550_port_shutdown(struct uart_port *port) +{ + ni16550_disable_transceivers(port); + + serial8250_do_shutdown(port); +} + +static int ni16550_get_regs(struct platform_device *pdev, + struct uart_port *port) +{ + struct resource *regs; + + regs = platform_get_resource(pdev, IORESOURCE_IO, 0); + if (regs) { + port->iotype = UPIO_PORT; + port->iobase = regs->start; + + return 0; + } + + regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (regs) { + port->iotype = UPIO_MEM; + port->mapbase = regs->start; + port->mapsize = resource_size(regs); + port->flags |= UPF_IOREMAP; + + port->membase = devm_ioremap(&pdev->dev, port->mapbase, + port->mapsize); + if (!port->membase) + return -ENOMEM; + + return 0; + } + + dev_err(&pdev->dev, "no registers defined\n"); + return -EINVAL; +} + +/* + * Very old implementations don't have the TFS or RFS registers + * defined, so we may read all-0s or all-1s. For such devices, + * assume a FIFO size of 128. + */ +static u8 ni16550_read_fifo_size(struct uart_8250_port *uart, int reg) +{ + u8 value = serial_in(uart, reg); + + if (value == 0x00 || value == 0xFF) + return 128; + + return value; +} + +static void ni16550_set_mctrl(struct uart_port *port, unsigned int mctrl) +{ + struct uart_8250_port *up = up_to_u8250p(port); + + up->mcr |= UART_MCR_CLKSEL; + serial8250_do_set_mctrl(port, mctrl); +} + +static int ni16550_probe(struct platform_device *pdev) +{ + const struct ni16550_device_info *info; + struct device *dev = &pdev->dev; + struct uart_8250_port uart = {}; + unsigned int txfifosz, rxfifosz; + unsigned int prescaler = 0; + struct ni16550_data *data; + const char *portmode; + bool rs232_property; + int ret; + int irq; + + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + spin_lock_init(&uart.port.lock); + + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return irq; + + ret = ni16550_get_regs(pdev, &uart.port); + if (ret < 0) + return ret; + + /* early setup so that serial_in()/serial_out() work */ + serial8250_set_defaults(&uart); + + info = device_get_match_data(dev); + + uart.port.dev = dev; + uart.port.irq = irq; + uart.port.irqflags = IRQF_SHARED; + uart.port.flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF + | UPF_FIXED_PORT | UPF_FIXED_TYPE; + uart.port.startup = ni16550_port_startup; + uart.port.shutdown = ni16550_port_shutdown; + + /* + * Hardware instantiation of FIFO sizes are held in registers. + */ + txfifosz = ni16550_read_fifo_size(&uart, NI16550_TFS_OFFSET); + rxfifosz = ni16550_read_fifo_size(&uart, NI16550_RFS_OFFSET); + + dev_dbg(dev, "NI 16550 has TX FIFO size %u, RX FIFO size %u\n", + txfifosz, rxfifosz); + + uart.port.type = PORT_16550A; + uart.port.fifosize = txfifosz; + uart.tx_loadsz = txfifosz; + uart.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10; + uart.capabilities = UART_CAP_FIFO | UART_CAP_AFE | UART_CAP_EFR; + + /* + * Declaration of the base clock frequency can come from one of: + * - static declaration in this driver (for older ACPI IDs) + * - a "clock-frquency" ACPI + */ + if (info->uartclk) + uart.port.uartclk = info->uartclk; + if (device_property_read_u32(dev, "clock-frequency", + &uart.port.uartclk)) { + data->clk = devm_clk_get_enabled(dev, NULL); + if (!IS_ERR(data->clk)) + uart.port.uartclk = clk_get_rate(data->clk); + } + + if (!uart.port.uartclk) { + dev_err(dev, "unable to determine clock frequency!\n"); + ret = -ENODEV; + goto err; + } + + if (info->prescaler) + prescaler = info->prescaler; + device_property_read_u32(dev, "clock-prescaler", &prescaler); + + if (prescaler != 0) { + uart.port.set_mctrl = ni16550_set_mctrl; + ni16550_config_prescaler(&uart, (u8)prescaler); + } + + /* + * The determination of whether or not this is an RS-485 or RS-232 port + * can come from the PMR (if present), otherwise we're solely an RS-485 + * port. + * + * This is a device-specific property, and there are old devices in the + * field using "transceiver" as an ACPI property, so we have to check + * for that as well. + */ + if (!device_property_read_string(dev, "transceiver", &portmode)) { + rs232_property = strncmp(portmode, "RS-232", 6) == 0; + + dev_dbg(dev, "port is in %s mode (via device property)\n", + rs232_property ? "RS-232" : "RS-485"); + } else if (info->flags & NI_HAS_PMR) { + rs232_property = is_pmr_rs232_mode(&uart); + + dev_dbg(dev, "port is in %s mode (via PMR)\n", + rs232_property ? "RS-232" : "RS-485"); + } else { + rs232_property = 0; + + dev_dbg(dev, "port is fixed as RS-485\n"); + } + + if (!rs232_property) { + /* + * Neither the 'transceiver' property nor the PMR indicate + * that this is an RS-232 port, so it must be an RS-485 one. + */ + ni16550_rs485_setup(&uart.port); + } + + ret = serial8250_register_8250_port(&uart); + if (ret < 0) + goto err; + data->line = ret; + + platform_set_drvdata(pdev, data); + return 0; + +err: + return ret; +} + +static void ni16550_remove(struct platform_device *pdev) +{ + struct ni16550_data *data = platform_get_drvdata(pdev); + + serial8250_unregister_port(data->line); +} + +#ifdef CONFIG_ACPI +/* NI 16550 RS-485 Interface */ +static const struct ni16550_device_info nic7750 = { + .uartclk = 33333333, +}; + +/* NI CVS-145x RS-485 Interface */ +static const struct ni16550_device_info nic7772 = { + .uartclk = 1843200, + .flags = NI_HAS_PMR, +}; + +/* NI cRIO-904x RS-485 Interface */ +static const struct ni16550_device_info nic792b = { + /* Sets UART clock rate to 22.222 MHz with 1.125 prescale */ + .uartclk = 22222222, + .prescaler = 0x09, +}; + +/* NI sbRIO 96x8 RS-232/485 Interfaces */ +static const struct ni16550_device_info nic7a69 = { + /* Set UART clock rate to 29.629 MHz with 1.125 prescale */ + .uartclk = 29629629, + .prescaler = 0x09, +}; +static const struct acpi_device_id ni16550_acpi_match[] = { + { "NIC7750", (kernel_ulong_t)&nic7750 }, + { "NIC7772", (kernel_ulong_t)&nic7772 }, + { "NIC792B", (kernel_ulong_t)&nic792b }, + { "NIC7A69", (kernel_ulong_t)&nic7a69 }, + { }, +}; +MODULE_DEVICE_TABLE(acpi, ni16550_acpi_match); +#endif + +static struct platform_driver ni16550_driver = { + .driver = { + .name = "ni16550", + .acpi_match_table = ACPI_PTR(ni16550_acpi_match), + }, + .probe = ni16550_probe, + .remove = ni16550_remove, +}; + +module_platform_driver(ni16550_driver); + +MODULE_AUTHOR("Emerson Electric Co."); +MODULE_DESCRIPTION("NI 16550 Driver"); +MODULE_LICENSE("GPL");
diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c index c2b75e3..2a0ce11f 100644 --- a/drivers/tty/serial/8250/8250_omap.c +++ b/drivers/tty/serial/8250/8250_omap.c
@@ -692,7 +692,7 @@ static irqreturn_t omap8250_irq(int irq, void *dev_id) /* Synchronize UART_IER access against the console. */ uart_port_lock(port); - up->ier = port->serial_in(port, UART_IER); + up->ier = serial_port_in(port, UART_IER); if (up->ier & (UART_IER_RLSI | UART_IER_RDI)) { port->ops->stop_rx(port); } else {
diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index df4d0d8..73c2001 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c
@@ -2728,6 +2728,22 @@ static struct pci_serial_quirk pci_serial_quirks[] = { .setup = pci_oxsemi_tornado_setup, }, { + .vendor = PCI_VENDOR_ID_INTASHIELD, + .device = 0x4026, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_oxsemi_tornado_init, + .setup = pci_oxsemi_tornado_setup, + }, + { + .vendor = PCI_VENDOR_ID_INTASHIELD, + .device = 0x4021, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_oxsemi_tornado_init, + .setup = pci_oxsemi_tornado_setup, + }, + { .vendor = PCI_VENDOR_ID_INTEL, .device = 0x8811, .subvendor = PCI_ANY_ID, @@ -5253,6 +5269,14 @@ static const struct pci_device_id serial_pci_tbl[] = { PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_b2_2_115200 }, + { PCI_VENDOR_ID_INTASHIELD, 0x0BA2, + PCI_ANY_ID, PCI_ANY_ID, + 0, 0, + pbn_b2_2_115200 }, + { PCI_VENDOR_ID_INTASHIELD, 0x0BA3, + PCI_ANY_ID, PCI_ANY_ID, + 0, 0, + pbn_b2_2_115200 }, /* * Brainboxes UC-235/246 */ @@ -5373,6 +5397,14 @@ static const struct pci_device_id serial_pci_tbl[] = { PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_b2_4_115200 }, + { PCI_VENDOR_ID_INTASHIELD, 0x0C42, + PCI_ANY_ID, PCI_ANY_ID, + 0, 0, + pbn_b2_4_115200 }, + { PCI_VENDOR_ID_INTASHIELD, 0x0C43, + PCI_ANY_ID, PCI_ANY_ID, + 0, 0, + pbn_b2_4_115200 }, /* * Brainboxes UC-420 */ @@ -5599,6 +5631,20 @@ static const struct pci_device_id serial_pci_tbl[] = { PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_oxsemi_1_15625000 }, + /* + * Brainboxes XC-235 + */ + { PCI_VENDOR_ID_INTASHIELD, 0x4026, + PCI_ANY_ID, PCI_ANY_ID, + 0, 0, + pbn_oxsemi_1_15625000 }, + /* + * Brainboxes XC-475 + */ + { PCI_VENDOR_ID_INTASHIELD, 0x4021, + PCI_ANY_ID, PCI_ANY_ID, + 0, 0, + pbn_oxsemi_1_15625000 }, /* * Perle PCI-RAS cards
diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index c57f448..8ac452c 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c
@@ -1678,7 +1678,7 @@ static void serial8250_disable_ms(struct uart_port *port) if (up->bugs & UART_BUG_NOMSR) return; - mctrl_gpio_disable_ms(up->gpios); + mctrl_gpio_disable_ms_no_sync(up->gpios); up->ier &= ~UART_IER_MSI; serial_port_out(port, UART_IER, up->ier); @@ -2406,28 +2406,26 @@ int serial8250_do_startup(struct uart_port *port) * test if we receive TX irq. This way, we'll never enable * UART_BUG_TXEN. */ - if (up->port.quirks & UPQ_NO_TXEN_TEST) - goto dont_test_tx_en; + if (!(up->port.quirks & UPQ_NO_TXEN_TEST)) { + /* + * Do a quick test to see if we receive an interrupt when we + * enable the TX irq. + */ + serial_port_out(port, UART_IER, UART_IER_THRI); + lsr = serial_port_in(port, UART_LSR); + iir = serial_port_in(port, UART_IIR); + serial_port_out(port, UART_IER, 0); - /* - * Do a quick test to see if we receive an interrupt when we enable - * the TX irq. - */ - serial_port_out(port, UART_IER, UART_IER_THRI); - lsr = serial_port_in(port, UART_LSR); - iir = serial_port_in(port, UART_IIR); - serial_port_out(port, UART_IER, 0); - - if (lsr & UART_LSR_TEMT && iir & UART_IIR_NO_INT) { - if (!(up->bugs & UART_BUG_TXEN)) { - up->bugs |= UART_BUG_TXEN; - dev_dbg(port->dev, "enabling bad tx status workarounds\n"); + if (lsr & UART_LSR_TEMT && iir & UART_IIR_NO_INT) { + if (!(up->bugs & UART_BUG_TXEN)) { + up->bugs |= UART_BUG_TXEN; + dev_dbg(port->dev, "enabling bad tx status workarounds\n"); + } + } else { + up->bugs &= ~UART_BUG_TXEN; } - } else { - up->bugs &= ~UART_BUG_TXEN; } -dont_test_tx_en: uart_port_unlock_irqrestore(port, flags); /* @@ -2968,7 +2966,6 @@ static int serial8250_request_std_resource(struct uart_8250_port *up) { unsigned int size = serial8250_port_size(up); struct uart_port *port = &up->port; - int ret = 0; switch (port->iotype) { case UPIO_AU: @@ -2977,32 +2974,28 @@ static int serial8250_request_std_resource(struct uart_8250_port *up) case UPIO_MEM32BE: case UPIO_MEM16: case UPIO_MEM: - if (!port->mapbase) { - ret = -EINVAL; - break; - } + if (!port->mapbase) + return -EINVAL; - if (!request_mem_region(port->mapbase, size, "serial")) { - ret = -EBUSY; - break; - } + if (!request_mem_region(port->mapbase, size, "serial")) + return -EBUSY; if (port->flags & UPF_IOREMAP) { port->membase = ioremap(port->mapbase, size); if (!port->membase) { release_mem_region(port->mapbase, size); - ret = -ENOMEM; + return -ENOMEM; } } - break; - + return 0; case UPIO_HUB6: case UPIO_PORT: if (!request_region(port->iobase, size, "serial")) - ret = -EBUSY; - break; + return -EBUSY; + return 0; } - return ret; + + return 0; } static void serial8250_release_std_resource(struct uart_8250_port *up)
diff --git a/drivers/tty/serial/8250/8250_rsa.c b/drivers/tty/serial/8250/8250_rsa.c index dfaa613..82f2593 100644 --- a/drivers/tty/serial/8250/8250_rsa.c +++ b/drivers/tty/serial/8250/8250_rsa.c
@@ -16,30 +16,27 @@ static unsigned int probe_rsa_count; static int rsa8250_request_resource(struct uart_8250_port *up) { - unsigned long start = UART_RSA_BASE << up->port.regshift; - unsigned int size = 8 << up->port.regshift; struct uart_port *port = &up->port; - int ret = -EINVAL; + unsigned long start = UART_RSA_BASE << port->regshift; + unsigned int size = 8 << port->regshift; switch (port->iotype) { case UPIO_HUB6: case UPIO_PORT: start += port->iobase; - if (request_region(start, size, "serial-rsa")) - ret = 0; - else - ret = -EBUSY; - break; + if (!request_region(start, size, "serial-rsa")) + return -EBUSY; + return 0; + default: + return -EINVAL; } - - return ret; } static void rsa8250_release_resource(struct uart_8250_port *up) { - unsigned long offset = UART_RSA_BASE << up->port.regshift; - unsigned int size = 8 << up->port.regshift; struct uart_port *port = &up->port; + unsigned long offset = UART_RSA_BASE << port->regshift; + unsigned int size = 8 << port->regshift; switch (port->iotype) { case UPIO_HUB6:
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig index 55d26d1..bd3d636 100644 --- a/drivers/tty/serial/8250/Kconfig +++ b/drivers/tty/serial/8250/Kconfig
@@ -569,6 +569,19 @@ including DMA support and high accuracy BAUD rates, say Y to this option. If unsure, say N. +config SERIAL_8250_NI + tristate "NI 16550 based serial port" + depends on SERIAL_8250 + depends on (X86 && ACPI) || COMPILE_TEST + help + This driver supports the integrated serial ports on National + Instruments (NI) controller hardware. This is required for all NI + controller models with onboard RS-485 or dual-mode RS-485/RS-232 + ports. + + To compile this driver as a module, choose M here: the module + will be called 8250_ni. + config SERIAL_OF_PLATFORM tristate "Devicetree based probing for 8250 ports" depends on SERIAL_8250 && OF
diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile index 1516de6..b04eeda 100644 --- a/drivers/tty/serial/8250/Makefile +++ b/drivers/tty/serial/8250/Makefile
@@ -40,6 +40,7 @@ obj-$(CONFIG_SERIAL_8250_MEN_MCB) += 8250_men_mcb.o obj-$(CONFIG_SERIAL_8250_MID) += 8250_mid.o obj-$(CONFIG_SERIAL_8250_MT6577) += 8250_mtk.o +obj-$(CONFIG_SERIAL_8250_NI) += 8250_ni.o obj-$(CONFIG_SERIAL_OF_PLATFORM) += 8250_of.o obj-$(CONFIG_SERIAL_8250_OMAP) += 8250_omap.o obj-$(CONFIG_SERIAL_8250_PARISC) += 8250_parisc.o
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index 976dae3..79a8186 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig
@@ -179,25 +179,6 @@ Say Y if you have an external 8250/16C550 UART. If unsure, say N. -config SERIAL_KGDB_NMI - bool "Serial console over KGDB NMI debugger port" - depends on KGDB_SERIAL_CONSOLE - help - This special driver allows you to temporary use NMI debugger port - as a normal console (assuming that the port is attached to KGDB). - - Unlike KDB's disable_nmi command, with this driver you are always - able to go back to the debugger using KGDB escape sequence ($3#33). - This is because this console driver processes the input in NMI - context, and thus is able to intercept the magic sequence. - - Note that since the console interprets input and uses polling - communication methods, for things like PPP you still must fully - detach debugger port from the KGDB NMI (i.e. disable_nmi), and - use raw console. - - If unsure, say N. - config SERIAL_MESON tristate "Meson serial port support" depends on ARCH_MESON || COMPILE_TEST @@ -306,6 +287,29 @@ If unsure, say Y. +config SERIAL_TEGRA_UTC + tristate "NVIDIA Tegra UART Trace Controller" + depends on ARCH_TEGRA || COMPILE_TEST + select SERIAL_CORE + help + Support for Tegra UTC (UART Trace controller) client serial port. + + UTC is a HW based serial port that allows multiplexing multiple data + streams of up to 16 UTC clients into a single hardware serial port. + +config SERIAL_TEGRA_UTC_CONSOLE + bool "Support for console on a Tegra UTC serial port" + depends on SERIAL_TEGRA_UTC + select SERIAL_CORE_CONSOLE + default SERIAL_TEGRA_UTC + help + If you say Y here, it will be possible to use a Tegra UTC client as + the system console (the system console is the device which receives + all kernel messages and warnings and which allows logins in single + user mode). + + If unsure, say Y. + config SERIAL_MAX3100 tristate "MAX3100/3110/3111/3222 support" depends on SPI
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile index 6ff74f0..d58d9f7 100644 --- a/drivers/tty/serial/Makefile +++ b/drivers/tty/serial/Makefile
@@ -86,6 +86,7 @@ obj-$(CONFIG_SERIAL_SUNPLUS) += sunplus-uart.o obj-$(CONFIG_SERIAL_TEGRA) += serial-tegra.o obj-$(CONFIG_SERIAL_TEGRA_TCU) += tegra-tcu.o +obj-$(CONFIG_SERIAL_TEGRA_UTC) += tegra-utc.o obj-$(CONFIG_SERIAL_TIMBERDALE) += timbuart.o obj-$(CONFIG_SERIAL_TXX9) += serial_txx9.o obj-$(CONFIG_SERIAL_UARTLITE) += uartlite.o @@ -96,6 +97,5 @@ # GPIOLIB helpers for modem control lines obj-$(CONFIG_SERIAL_MCTRL_GPIO) += serial_mctrl_gpio.o -obj-$(CONFIG_SERIAL_KGDB_NMI) += kgdb_nmi.o obj-$(CONFIG_KGDB_SERIAL_CONSOLE) += kgdboc.o obj-$(CONFIG_SERIAL_NUVOTON_MA35D1) += ma35d1_serial.o
diff --git a/drivers/tty/serial/altera_uart.c b/drivers/tty/serial/altera_uart.c index 1759137..011f386 100644 --- a/drivers/tty/serial/altera_uart.c +++ b/drivers/tty/serial/altera_uart.c
@@ -339,7 +339,7 @@ static void altera_uart_shutdown(struct uart_port *port) if (port->irq) free_irq(port->irq, port); else - del_timer_sync(&pp->tmr); + timer_delete_sync(&pp->tmr); } static const char *altera_uart_type(struct uart_port *port)
diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index 98f178b..11d6509 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c
@@ -272,6 +272,7 @@ struct uart_amba_port { enum pl011_rs485_tx_state rs485_tx_state; struct hrtimer trigger_start_tx; struct hrtimer trigger_stop_tx; + bool console_line_ended; #ifdef CONFIG_DMA_ENGINE /* DMA stuff */ unsigned int dmacr; /* dma control reg */ @@ -1083,7 +1084,7 @@ static void pl011_dma_rx_poll(struct timer_list *t) uap->dmarx.running = false; dmaengine_terminate_all(rxchan); - del_timer(&uap->dmarx.timer); + timer_delete(&uap->dmarx.timer); } else { mod_timer(&uap->dmarx.timer, jiffies + msecs_to_jiffies(uap->dmarx.poll_rate)); @@ -1198,7 +1199,7 @@ static void pl011_dma_shutdown(struct uart_amba_port *uap) pl011_dmabuf_free(uap->dmarx.chan, &uap->dmarx.dbuf_a, DMA_FROM_DEVICE); pl011_dmabuf_free(uap->dmarx.chan, &uap->dmarx.dbuf_b, DMA_FROM_DEVICE); if (uap->dmarx.poll_rate) - del_timer_sync(&uap->dmarx.timer); + timer_delete_sync(&uap->dmarx.timer); uap->using_rx_dma = false; } } @@ -2366,50 +2367,7 @@ static void pl011_console_putchar(struct uart_port *port, unsigned char ch) while (pl011_read(uap, REG_FR) & UART01x_FR_TXFF) cpu_relax(); pl011_write(ch, uap, REG_DR); -} - -static void -pl011_console_write(struct console *co, const char *s, unsigned int count) -{ - struct uart_amba_port *uap = amba_ports[co->index]; - unsigned int old_cr = 0, new_cr; - unsigned long flags; - int locked = 1; - - clk_enable(uap->clk); - - if (oops_in_progress) - locked = uart_port_trylock_irqsave(&uap->port, &flags); - else - uart_port_lock_irqsave(&uap->port, &flags); - - /* - * First save the CR then disable the interrupts - */ - if (!uap->vendor->always_enabled) { - old_cr = pl011_read(uap, REG_CR); - new_cr = old_cr & ~UART011_CR_CTSEN; - new_cr |= UART01x_CR_UARTEN | UART011_CR_TXE; - pl011_write(new_cr, uap, REG_CR); - } - - uart_console_write(&uap->port, s, count, pl011_console_putchar); - - /* - * Finally, wait for transmitter to become empty and restore the - * TCR. Allow feature register bits to be inverted to work around - * errata. - */ - while ((pl011_read(uap, REG_FR) ^ uap->vendor->inv_fr) - & uap->vendor->fr_busy) - cpu_relax(); - if (!uap->vendor->always_enabled) - pl011_write(old_cr, uap, REG_CR); - - if (locked) - uart_port_unlock_irqrestore(&uap->port, flags); - - clk_disable(uap->clk); + uap->console_line_ended = (ch == '\n'); } static void pl011_console_get_options(struct uart_amba_port *uap, int *baud, @@ -2472,6 +2430,8 @@ static int pl011_console_setup(struct console *co, char *options) if (ret) return ret; + uap->console_line_ended = true; + if (dev_get_platdata(uap->port.dev)) { struct amba_pl011_data *plat; @@ -2555,14 +2515,105 @@ static int pl011_console_match(struct console *co, char *name, int idx, return -ENODEV; } +static void +pl011_console_write_atomic(struct console *co, struct nbcon_write_context *wctxt) +{ + struct uart_amba_port *uap = amba_ports[co->index]; + unsigned int old_cr = 0; + + if (!nbcon_enter_unsafe(wctxt)) + return; + + clk_enable(uap->clk); + + if (!uap->vendor->always_enabled) { + old_cr = pl011_read(uap, REG_CR); + pl011_write((old_cr & ~UART011_CR_CTSEN) | (UART01x_CR_UARTEN | UART011_CR_TXE), + uap, REG_CR); + } + + if (!uap->console_line_ended) + uart_console_write(&uap->port, "\n", 1, pl011_console_putchar); + uart_console_write(&uap->port, wctxt->outbuf, wctxt->len, pl011_console_putchar); + + while ((pl011_read(uap, REG_FR) ^ uap->vendor->inv_fr) & uap->vendor->fr_busy) + cpu_relax(); + + if (!uap->vendor->always_enabled) + pl011_write(old_cr, uap, REG_CR); + + clk_disable(uap->clk); + + nbcon_exit_unsafe(wctxt); +} + +static void +pl011_console_write_thread(struct console *co, struct nbcon_write_context *wctxt) +{ + struct uart_amba_port *uap = amba_ports[co->index]; + unsigned int old_cr = 0; + + if (!nbcon_enter_unsafe(wctxt)) + return; + + clk_enable(uap->clk); + + if (!uap->vendor->always_enabled) { + old_cr = pl011_read(uap, REG_CR); + pl011_write((old_cr & ~UART011_CR_CTSEN) | (UART01x_CR_UARTEN | UART011_CR_TXE), + uap, REG_CR); + } + + if (nbcon_exit_unsafe(wctxt)) { + int i; + unsigned int len = READ_ONCE(wctxt->len); + + for (i = 0; i < len; i++) { + if (!nbcon_enter_unsafe(wctxt)) + break; + uart_console_write(&uap->port, wctxt->outbuf + i, 1, pl011_console_putchar); + if (!nbcon_exit_unsafe(wctxt)) + break; + } + } + + while (!nbcon_enter_unsafe(wctxt)) + nbcon_reacquire_nobuf(wctxt); + + while ((pl011_read(uap, REG_FR) ^ uap->vendor->inv_fr) & uap->vendor->fr_busy) + cpu_relax(); + + if (!uap->vendor->always_enabled) + pl011_write(old_cr, uap, REG_CR); + + clk_disable(uap->clk); + + nbcon_exit_unsafe(wctxt); +} + +static void +pl011_console_device_lock(struct console *co, unsigned long *flags) +{ + __uart_port_lock_irqsave(&amba_ports[co->index]->port, flags); +} + +static void +pl011_console_device_unlock(struct console *co, unsigned long flags) +{ + __uart_port_unlock_irqrestore(&amba_ports[co->index]->port, flags); +} + static struct uart_driver amba_reg; static struct console amba_console = { .name = "ttyAMA", - .write = pl011_console_write, .device = uart_console_device, .setup = pl011_console_setup, .match = pl011_console_match, - .flags = CON_PRINTBUFFER | CON_ANYTIME, + .write_atomic = pl011_console_write_atomic, + .write_thread = pl011_console_write_thread, + .device_lock = pl011_console_device_lock, + .device_unlock = pl011_console_device_unlock, + .flags = CON_PRINTBUFFER | CON_ANYTIME | CON_NBCON, .index = -1, .data = &amba_reg, }; @@ -3000,7 +3051,7 @@ static const struct of_device_id sbsa_uart_of_match[] = { }; MODULE_DEVICE_TABLE(of, sbsa_uart_of_match); -static const struct acpi_device_id __maybe_unused sbsa_uart_acpi_match[] = { +static const struct acpi_device_id sbsa_uart_acpi_match[] = { { "ARMH0011", 0 }, { "ARMHB000", 0 }, {}, @@ -3013,8 +3064,8 @@ static struct platform_driver arm_sbsa_uart_platform_driver = { .driver = { .name = "sbsa-uart", .pm = &pl011_dev_pm_ops, - .of_match_table = of_match_ptr(sbsa_uart_of_match), - .acpi_match_table = ACPI_PTR(sbsa_uart_acpi_match), + .of_match_table = sbsa_uart_of_match, + .acpi_match_table = sbsa_uart_acpi_match, .suppress_bind_attrs = IS_BUILTIN(CONFIG_SERIAL_AMBA_PL011), }, };
diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index f44f9d2..18dba50 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c
@@ -700,7 +700,7 @@ static void atmel_disable_ms(struct uart_port *port) atmel_port->ms_irq_enabled = false; - mctrl_gpio_disable_ms(atmel_port->gpios); + mctrl_gpio_disable_ms_no_sync(atmel_port->gpios); if (!mctrl_gpio_to_gpiod(atmel_port->gpios, UART_GPIO_CTS)) idr |= ATMEL_US_CTSIC; @@ -2017,7 +2017,7 @@ static void atmel_shutdown(struct uart_port *port) * Prevent any tasklets being scheduled during * cleanup */ - del_timer_sync(&atmel_port->uart_timer); + timer_delete_sync(&atmel_port->uart_timer); /* Make sure that no interrupt is on the fly */ synchronize_irq(port->irq);
diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c index c91b9d9..fe5aed9 100644 --- a/drivers/tty/serial/fsl_lpuart.c +++ b/drivers/tty/serial/fsl_lpuart.c
@@ -441,36 +441,36 @@ static unsigned int lpuart_get_baud_clk_rate(struct lpuart_port *sport) static void lpuart_stop_tx(struct uart_port *port) { - unsigned char temp; + u8 cr2; - temp = readb(port->membase + UARTCR2); - temp &= ~(UARTCR2_TIE | UARTCR2_TCIE); - writeb(temp, port->membase + UARTCR2); + cr2 = readb(port->membase + UARTCR2); + cr2 &= ~(UARTCR2_TIE | UARTCR2_TCIE); + writeb(cr2, port->membase + UARTCR2); } static void lpuart32_stop_tx(struct uart_port *port) { - unsigned long temp; + u32 ctrl; - temp = lpuart32_read(port, UARTCTRL); - temp &= ~(UARTCTRL_TIE | UARTCTRL_TCIE); - lpuart32_write(port, temp, UARTCTRL); + ctrl = lpuart32_read(port, UARTCTRL); + ctrl &= ~(UARTCTRL_TIE | UARTCTRL_TCIE); + lpuart32_write(port, ctrl, UARTCTRL); } static void lpuart_stop_rx(struct uart_port *port) { - unsigned char temp; + u8 cr2; - temp = readb(port->membase + UARTCR2); - writeb(temp & ~UARTCR2_RE, port->membase + UARTCR2); + cr2 = readb(port->membase + UARTCR2); + writeb(cr2 & ~UARTCR2_RE, port->membase + UARTCR2); } static void lpuart32_stop_rx(struct uart_port *port) { - unsigned long temp; + u32 ctrl; - temp = lpuart32_read(port, UARTCTRL); - lpuart32_write(port, temp & ~UARTCTRL_RE, UARTCTRL); + ctrl = lpuart32_read(port, UARTCTRL); + lpuart32_write(port, ctrl & ~UARTCTRL_RE, UARTCTRL); } static void lpuart_dma_tx(struct lpuart_port *sport) @@ -581,7 +581,7 @@ static int lpuart_dma_tx_request(struct uart_port *port) ret = dmaengine_slave_config(sport->dma_tx_chan, &dma_tx_sconfig); if (ret) { - dev_err(sport->port.dev, + dev_err(port->dev, "DMA slave config failed, err = %d\n", ret); return ret; } @@ -599,7 +599,7 @@ static void lpuart_flush_buffer(struct uart_port *port) { struct lpuart_port *sport = container_of(port, struct lpuart_port, port); struct dma_chan *chan = sport->dma_tx_chan; - u32 val; + u32 fifo; if (sport->lpuart_dma_tx_use) { if (sport->dma_tx_in_progress) { @@ -611,13 +611,13 @@ static void lpuart_flush_buffer(struct uart_port *port) } if (lpuart_is_32(sport)) { - val = lpuart32_read(&sport->port, UARTFIFO); - val |= UARTFIFO_TXFLUSH | UARTFIFO_RXFLUSH; - lpuart32_write(&sport->port, val, UARTFIFO); + fifo = lpuart32_read(port, UARTFIFO); + fifo |= UARTFIFO_TXFLUSH | UARTFIFO_RXFLUSH; + lpuart32_write(port, fifo, UARTFIFO); } else { - val = readb(sport->port.membase + UARTCFIFO); - val |= UARTCFIFO_TXFLUSH | UARTCFIFO_RXFLUSH; - writeb(val, sport->port.membase + UARTCFIFO); + fifo = readb(port->membase + UARTCFIFO); + fifo |= UARTCFIFO_TXFLUSH | UARTCFIFO_RXFLUSH; + writeb(fifo, port->membase + UARTCFIFO); } } @@ -639,38 +639,36 @@ static void lpuart32_wait_bit_set(struct uart_port *port, unsigned int offset, static int lpuart_poll_init(struct uart_port *port) { - struct lpuart_port *sport = container_of(port, - struct lpuart_port, port); unsigned long flags; - unsigned char temp; + u8 fifo; - sport->port.fifosize = 0; + port->fifosize = 0; - uart_port_lock_irqsave(&sport->port, &flags); + uart_port_lock_irqsave(port, &flags); /* Disable Rx & Tx */ - writeb(0, sport->port.membase + UARTCR2); + writeb(0, port->membase + UARTCR2); - temp = readb(sport->port.membase + UARTPFIFO); + fifo = readb(port->membase + UARTPFIFO); /* Enable Rx and Tx FIFO */ - writeb(temp | UARTPFIFO_RXFE | UARTPFIFO_TXFE, - sport->port.membase + UARTPFIFO); + writeb(fifo | UARTPFIFO_RXFE | UARTPFIFO_TXFE, + port->membase + UARTPFIFO); /* flush Tx and Rx FIFO */ writeb(UARTCFIFO_TXFLUSH | UARTCFIFO_RXFLUSH, - sport->port.membase + UARTCFIFO); + port->membase + UARTCFIFO); /* explicitly clear RDRF */ - if (readb(sport->port.membase + UARTSR1) & UARTSR1_RDRF) { - readb(sport->port.membase + UARTDR); - writeb(UARTSFIFO_RXUF, sport->port.membase + UARTSFIFO); + if (readb(port->membase + UARTSR1) & UARTSR1_RDRF) { + readb(port->membase + UARTDR); + writeb(UARTSFIFO_RXUF, port->membase + UARTSFIFO); } - writeb(0, sport->port.membase + UARTTWFIFO); - writeb(1, sport->port.membase + UARTRWFIFO); + writeb(0, port->membase + UARTTWFIFO); + writeb(1, port->membase + UARTRWFIFO); /* Enable Rx and Tx */ - writeb(UARTCR2_RE | UARTCR2_TE, sport->port.membase + UARTCR2); - uart_port_unlock_irqrestore(&sport->port, flags); + writeb(UARTCR2_RE | UARTCR2_TE, port->membase + UARTCR2); + uart_port_unlock_irqrestore(port, flags); return 0; } @@ -693,33 +691,32 @@ static int lpuart_poll_get_char(struct uart_port *port) static int lpuart32_poll_init(struct uart_port *port) { unsigned long flags; - struct lpuart_port *sport = container_of(port, struct lpuart_port, port); - u32 temp; + u32 fifo; - sport->port.fifosize = 0; + port->fifosize = 0; - uart_port_lock_irqsave(&sport->port, &flags); + uart_port_lock_irqsave(port, &flags); /* Disable Rx & Tx */ - lpuart32_write(&sport->port, 0, UARTCTRL); + lpuart32_write(port, 0, UARTCTRL); - temp = lpuart32_read(&sport->port, UARTFIFO); + fifo = lpuart32_read(port, UARTFIFO); /* Enable Rx and Tx FIFO */ - lpuart32_write(&sport->port, temp | UARTFIFO_RXFE | UARTFIFO_TXFE, UARTFIFO); + lpuart32_write(port, fifo | UARTFIFO_RXFE | UARTFIFO_TXFE, UARTFIFO); /* flush Tx and Rx FIFO */ - lpuart32_write(&sport->port, UARTFIFO_TXFLUSH | UARTFIFO_RXFLUSH, UARTFIFO); + lpuart32_write(port, UARTFIFO_TXFLUSH | UARTFIFO_RXFLUSH, UARTFIFO); /* explicitly clear RDRF */ - if (lpuart32_read(&sport->port, UARTSTAT) & UARTSTAT_RDRF) { - lpuart32_read(&sport->port, UARTDATA); - lpuart32_write(&sport->port, UARTFIFO_RXUF, UARTFIFO); + if (lpuart32_read(port, UARTSTAT) & UARTSTAT_RDRF) { + lpuart32_read(port, UARTDATA); + lpuart32_write(port, UARTFIFO_RXUF, UARTFIFO); } /* Enable Rx and Tx */ - lpuart32_write(&sport->port, UARTCTRL_RE | UARTCTRL_TE, UARTCTRL); - uart_port_unlock_irqrestore(&sport->port, flags); + lpuart32_write(port, UARTCTRL_RE | UARTCTRL_TE, UARTCTRL); + uart_port_unlock_irqrestore(port, flags); return 0; } @@ -752,7 +749,7 @@ static inline void lpuart_transmit_buffer(struct lpuart_port *sport) static inline void lpuart32_transmit_buffer(struct lpuart_port *sport) { struct tty_port *tport = &sport->port.state->port; - unsigned long txcnt; + u32 txcnt; unsigned char c; if (sport->port.x_char) { @@ -789,10 +786,10 @@ static void lpuart_start_tx(struct uart_port *port) { struct lpuart_port *sport = container_of(port, struct lpuart_port, port); - unsigned char temp; + u8 cr2; - temp = readb(port->membase + UARTCR2); - writeb(temp | UARTCR2_TIE, port->membase + UARTCR2); + cr2 = readb(port->membase + UARTCR2); + writeb(cr2 | UARTCR2_TIE, port->membase + UARTCR2); if (sport->lpuart_dma_tx_use) { if (!lpuart_stopped_or_empty(port)) @@ -806,14 +803,14 @@ static void lpuart_start_tx(struct uart_port *port) static void lpuart32_start_tx(struct uart_port *port) { struct lpuart_port *sport = container_of(port, struct lpuart_port, port); - unsigned long temp; + u32 ctrl; if (sport->lpuart_dma_tx_use) { if (!lpuart_stopped_or_empty(port)) lpuart_dma_tx(sport); } else { - temp = lpuart32_read(port, UARTCTRL); - lpuart32_write(port, temp | UARTCTRL_TIE, UARTCTRL); + ctrl = lpuart32_read(port, UARTCTRL); + lpuart32_write(port, ctrl | UARTCTRL_TIE, UARTCTRL); if (lpuart32_read(port, UARTSTAT) & UARTSTAT_TDRE) lpuart32_transmit_buffer(sport); @@ -839,8 +836,8 @@ static unsigned int lpuart_tx_empty(struct uart_port *port) { struct lpuart_port *sport = container_of(port, struct lpuart_port, port); - unsigned char sr1 = readb(port->membase + UARTSR1); - unsigned char sfifo = readb(port->membase + UARTSFIFO); + u8 sr1 = readb(port->membase + UARTSR1); + u8 sfifo = readb(port->membase + UARTSFIFO); if (sport->dma_tx_in_progress) return 0; @@ -855,9 +852,9 @@ static unsigned int lpuart32_tx_empty(struct uart_port *port) { struct lpuart_port *sport = container_of(port, struct lpuart_port, port); - unsigned long stat = lpuart32_read(port, UARTSTAT); - unsigned long sfifo = lpuart32_read(port, UARTFIFO); - unsigned long ctrl = lpuart32_read(port, UARTCTRL); + u32 stat = lpuart32_read(port, UARTSTAT); + u32 sfifo = lpuart32_read(port, UARTFIFO); + u32 ctrl = lpuart32_read(port, UARTCTRL); if (sport->dma_tx_in_progress) return 0; @@ -884,7 +881,7 @@ static void lpuart_rxint(struct lpuart_port *sport) { unsigned int flg, ignored = 0, overrun = 0; struct tty_port *port = &sport->port.state->port; - unsigned char rx, sr; + u8 rx, sr; uart_port_lock(&sport->port); @@ -961,7 +958,7 @@ static void lpuart32_rxint(struct lpuart_port *sport) { unsigned int flg, ignored = 0; struct tty_port *port = &sport->port.state->port; - unsigned long rx, sr; + u32 rx, sr; bool is_break; uart_port_lock(&sport->port); @@ -1039,7 +1036,7 @@ static void lpuart32_rxint(struct lpuart_port *sport) static irqreturn_t lpuart_int(int irq, void *dev_id) { struct lpuart_port *sport = dev_id; - unsigned char sts; + u8 sts; sts = readb(sport->port.membase + UARTSR1); @@ -1113,7 +1110,7 @@ static void lpuart_copy_rx_to_tty(struct lpuart_port *sport) int count, copied; if (lpuart_is_32(sport)) { - unsigned long sr = lpuart32_read(&sport->port, UARTSTAT); + u32 sr = lpuart32_read(&sport->port, UARTSTAT); if (sr & (UARTSTAT_PE | UARTSTAT_FE)) { /* Clear the error flags */ @@ -1125,10 +1122,10 @@ static void lpuart_copy_rx_to_tty(struct lpuart_port *sport) sport->port.icount.frame++; } } else { - unsigned char sr = readb(sport->port.membase + UARTSR1); + u8 sr = readb(sport->port.membase + UARTSR1); if (sr & (UARTSR1_PE | UARTSR1_FE)) { - unsigned char cr2; + u8 cr2; /* Disable receiver during this operation... */ cr2 = readb(sport->port.membase + UARTCR2); @@ -1279,7 +1276,7 @@ static void lpuart32_dma_idleint(struct lpuart_port *sport) static irqreturn_t lpuart32_int(int irq, void *dev_id) { struct lpuart_port *sport = dev_id; - unsigned long sts, rxcount; + u32 sts, rxcount; sts = lpuart32_read(&sport->port, UARTSTAT); rxcount = lpuart32_read(&sport->port, UARTWATER); @@ -1411,12 +1408,12 @@ static inline int lpuart_start_rx_dma(struct lpuart_port *sport) dma_async_issue_pending(chan); if (lpuart_is_32(sport)) { - unsigned long temp = lpuart32_read(&sport->port, UARTBAUD); + u32 baud = lpuart32_read(&sport->port, UARTBAUD); - lpuart32_write(&sport->port, temp | UARTBAUD_RDMAE, UARTBAUD); + lpuart32_write(&sport->port, baud | UARTBAUD_RDMAE, UARTBAUD); if (sport->dma_idle_int) { - unsigned long ctrl = lpuart32_read(&sport->port, UARTCTRL); + u32 ctrl = lpuart32_read(&sport->port, UARTCTRL); lpuart32_write(&sport->port, ctrl | UARTCTRL_ILIE, UARTCTRL); } @@ -1436,7 +1433,7 @@ static void lpuart_dma_rx_free(struct uart_port *port) dmaengine_terminate_sync(chan); if (!sport->dma_idle_int) - del_timer_sync(&sport->lpuart_timer); + timer_delete_sync(&sport->lpuart_timer); dma_unmap_sg(chan->device->dev, &sport->rx_sgl, 1, DMA_FROM_DEVICE); kfree(sport->rx_ring.buf); @@ -1449,12 +1446,9 @@ static void lpuart_dma_rx_free(struct uart_port *port) static int lpuart_config_rs485(struct uart_port *port, struct ktermios *termios, struct serial_rs485 *rs485) { - struct lpuart_port *sport = container_of(port, - struct lpuart_port, port); - - u8 modem = readb(sport->port.membase + UARTMODEM) & + u8 modem = readb(port->membase + UARTMODEM) & ~(UARTMODEM_TXRTSPOL | UARTMODEM_TXRTSE); - writeb(modem, sport->port.membase + UARTMODEM); + writeb(modem, port->membase + UARTMODEM); if (rs485->flags & SER_RS485_ENABLED) { /* Enable auto RS-485 RTS mode */ @@ -1472,19 +1466,29 @@ static int lpuart_config_rs485(struct uart_port *port, struct ktermios *termios, modem &= ~UARTMODEM_TXRTSPOL; } - writeb(modem, sport->port.membase + UARTMODEM); + writeb(modem, port->membase + UARTMODEM); return 0; } static int lpuart32_config_rs485(struct uart_port *port, struct ktermios *termios, struct serial_rs485 *rs485) { - struct lpuart_port *sport = container_of(port, - struct lpuart_port, port); - - unsigned long modem = lpuart32_read(&sport->port, UARTMODIR) + u32 modem = lpuart32_read(port, UARTMODIR) & ~(UARTMODIR_TXRTSPOL | UARTMODIR_TXRTSE); - lpuart32_write(&sport->port, modem, UARTMODIR); + u32 ctrl; + + /* TXRTSE and TXRTSPOL only can be changed when transmitter is disabled. */ + ctrl = lpuart32_read(port, UARTCTRL); + if (ctrl & UARTCTRL_TE) { + /* wait for the transmit engine to complete */ + lpuart32_wait_bit_set(port, UARTSTAT, UARTSTAT_TC); + lpuart32_write(port, ctrl & ~UARTCTRL_TE, UARTCTRL); + + while (lpuart32_read(port, UARTCTRL) & UARTCTRL_TE) + cpu_relax(); + } + + lpuart32_write(port, modem, UARTMODIR); if (rs485->flags & SER_RS485_ENABLED) { /* Enable auto RS-485 RTS mode */ @@ -1502,17 +1506,21 @@ static int lpuart32_config_rs485(struct uart_port *port, struct ktermios *termio modem &= ~UARTMODIR_TXRTSPOL; } - lpuart32_write(&sport->port, modem, UARTMODIR); + lpuart32_write(port, modem, UARTMODIR); + + if (ctrl & UARTCTRL_TE) + lpuart32_write(port, ctrl, UARTCTRL); + return 0; } static unsigned int lpuart_get_mctrl(struct uart_port *port) { unsigned int mctrl = 0; - u8 reg; + u8 cr1; - reg = readb(port->membase + UARTCR1); - if (reg & UARTCR1_LOOPS) + cr1 = readb(port->membase + UARTCR1); + if (cr1 & UARTCR1_LOOPS) mctrl |= TIOCM_LOOP; return mctrl; @@ -1521,10 +1529,10 @@ static unsigned int lpuart_get_mctrl(struct uart_port *port) static unsigned int lpuart32_get_mctrl(struct uart_port *port) { unsigned int mctrl = TIOCM_CAR | TIOCM_DSR | TIOCM_CTS; - u32 reg; + u32 ctrl; - reg = lpuart32_read(port, UARTCTRL); - if (reg & UARTCTRL_LOOPS) + ctrl = lpuart32_read(port, UARTCTRL); + if (ctrl & UARTCTRL_LOOPS) mctrl |= TIOCM_LOOP; return mctrl; @@ -1532,49 +1540,49 @@ static unsigned int lpuart32_get_mctrl(struct uart_port *port) static void lpuart_set_mctrl(struct uart_port *port, unsigned int mctrl) { - u8 reg; + u8 cr1; - reg = readb(port->membase + UARTCR1); + cr1 = readb(port->membase + UARTCR1); /* for internal loopback we need LOOPS=1 and RSRC=0 */ - reg &= ~(UARTCR1_LOOPS | UARTCR1_RSRC); + cr1 &= ~(UARTCR1_LOOPS | UARTCR1_RSRC); if (mctrl & TIOCM_LOOP) - reg |= UARTCR1_LOOPS; + cr1 |= UARTCR1_LOOPS; - writeb(reg, port->membase + UARTCR1); + writeb(cr1, port->membase + UARTCR1); } static void lpuart32_set_mctrl(struct uart_port *port, unsigned int mctrl) { - u32 reg; + u32 ctrl; - reg = lpuart32_read(port, UARTCTRL); + ctrl = lpuart32_read(port, UARTCTRL); /* for internal loopback we need LOOPS=1 and RSRC=0 */ - reg &= ~(UARTCTRL_LOOPS | UARTCTRL_RSRC); + ctrl &= ~(UARTCTRL_LOOPS | UARTCTRL_RSRC); if (mctrl & TIOCM_LOOP) - reg |= UARTCTRL_LOOPS; + ctrl |= UARTCTRL_LOOPS; - lpuart32_write(port, reg, UARTCTRL); + lpuart32_write(port, ctrl, UARTCTRL); } static void lpuart_break_ctl(struct uart_port *port, int break_state) { - unsigned char temp; + u8 cr2; - temp = readb(port->membase + UARTCR2) & ~UARTCR2_SBK; + cr2 = readb(port->membase + UARTCR2) & ~UARTCR2_SBK; if (break_state != 0) - temp |= UARTCR2_SBK; + cr2 |= UARTCR2_SBK; - writeb(temp, port->membase + UARTCR2); + writeb(cr2, port->membase + UARTCR2); } static void lpuart32_break_ctl(struct uart_port *port, int break_state) { - unsigned long temp; + u32 ctrl; - temp = lpuart32_read(port, UARTCTRL); + ctrl = lpuart32_read(port, UARTCTRL); /* * LPUART IP now has two known bugs, one is CTS has higher priority than the @@ -1591,23 +1599,22 @@ static void lpuart32_break_ctl(struct uart_port *port, int break_state) * Disable the transmitter to prevent any data from being sent out * during break, then invert the TX line to send break. */ - temp &= ~UARTCTRL_TE; - lpuart32_write(port, temp, UARTCTRL); - temp |= UARTCTRL_TXINV; - lpuart32_write(port, temp, UARTCTRL); + ctrl &= ~UARTCTRL_TE; + lpuart32_write(port, ctrl, UARTCTRL); + ctrl |= UARTCTRL_TXINV; + lpuart32_write(port, ctrl, UARTCTRL); } else { /* Disable the TXINV to turn off break and re-enable transmitter. */ - temp &= ~UARTCTRL_TXINV; - lpuart32_write(port, temp, UARTCTRL); - temp |= UARTCTRL_TE; - lpuart32_write(port, temp, UARTCTRL); + ctrl &= ~UARTCTRL_TXINV; + lpuart32_write(port, ctrl, UARTCTRL); + ctrl |= UARTCTRL_TE; + lpuart32_write(port, ctrl, UARTCTRL); } } static void lpuart_setup_watermark(struct lpuart_port *sport) { - unsigned char val, cr2; - unsigned char cr2_saved; + u8 fifo, cr2, cr2_saved; cr2 = readb(sport->port.membase + UARTCR2); cr2_saved = cr2; @@ -1615,8 +1622,8 @@ static void lpuart_setup_watermark(struct lpuart_port *sport) UARTCR2_RIE | UARTCR2_RE); writeb(cr2, sport->port.membase + UARTCR2); - val = readb(sport->port.membase + UARTPFIFO); - writeb(val | UARTPFIFO_TXFE | UARTPFIFO_RXFE, + fifo = readb(sport->port.membase + UARTPFIFO); + writeb(fifo | UARTPFIFO_TXFE | UARTPFIFO_RXFE, sport->port.membase + UARTPFIFO); /* flush Tx and Rx FIFO */ @@ -1640,7 +1647,7 @@ static void lpuart_setup_watermark(struct lpuart_port *sport) static void lpuart_setup_watermark_enable(struct lpuart_port *sport) { - unsigned char cr2; + u8 cr2; lpuart_setup_watermark(sport); @@ -1651,8 +1658,7 @@ static void lpuart_setup_watermark_enable(struct lpuart_port *sport) static void lpuart32_setup_watermark(struct lpuart_port *sport) { - unsigned long val, ctrl; - unsigned long ctrl_saved; + u32 val, ctrl, ctrl_saved; ctrl = lpuart32_read(&sport->port, UARTCTRL); ctrl_saved = ctrl; @@ -1687,14 +1693,14 @@ static void lpuart32_setup_watermark(struct lpuart_port *sport) static void lpuart32_setup_watermark_enable(struct lpuart_port *sport) { - u32 temp; + u32 ctrl; lpuart32_setup_watermark(sport); - temp = lpuart32_read(&sport->port, UARTCTRL); - temp |= UARTCTRL_RE | UARTCTRL_TE; - temp |= FIELD_PREP(UARTCTRL_IDLECFG, 0x7); - lpuart32_write(&sport->port, temp, UARTCTRL); + ctrl = lpuart32_read(&sport->port, UARTCTRL); + ctrl |= UARTCTRL_RE | UARTCTRL_TE; + ctrl |= FIELD_PREP(UARTCTRL_IDLECFG, 0x7); + lpuart32_write(&sport->port, ctrl, UARTCTRL); } static void rx_dma_timer_init(struct lpuart_port *sport) @@ -1761,7 +1767,7 @@ static void lpuart_tx_dma_startup(struct lpuart_port *sport) static void lpuart_rx_dma_startup(struct lpuart_port *sport) { int ret; - unsigned char cr3; + u8 cr3; if (uart_console(&sport->port)) goto err; @@ -1811,16 +1817,16 @@ static void lpuart_hw_setup(struct lpuart_port *sport) static int lpuart_startup(struct uart_port *port) { struct lpuart_port *sport = container_of(port, struct lpuart_port, port); - unsigned char temp; + u8 fifo; /* determine FIFO size and enable FIFO mode */ - temp = readb(sport->port.membase + UARTPFIFO); + fifo = readb(port->membase + UARTPFIFO); - sport->txfifo_size = UARTFIFO_DEPTH((temp >> UARTPFIFO_TXSIZE_OFF) & + sport->txfifo_size = UARTFIFO_DEPTH((fifo >> UARTPFIFO_TXSIZE_OFF) & UARTPFIFO_FIFOSIZE_MASK); - sport->port.fifosize = sport->txfifo_size; + port->fifosize = sport->txfifo_size; - sport->rxfifo_size = UARTFIFO_DEPTH((temp >> UARTPFIFO_RXSIZE_OFF) & + sport->rxfifo_size = UARTFIFO_DEPTH((fifo >> UARTPFIFO_RXSIZE_OFF) & UARTPFIFO_FIFOSIZE_MASK); lpuart_request_dma(sport); @@ -1831,24 +1837,24 @@ static int lpuart_startup(struct uart_port *port) static void lpuart32_hw_disable(struct lpuart_port *sport) { - unsigned long temp; + u32 ctrl; - temp = lpuart32_read(&sport->port, UARTCTRL); - temp &= ~(UARTCTRL_RIE | UARTCTRL_ILIE | UARTCTRL_RE | + ctrl = lpuart32_read(&sport->port, UARTCTRL); + ctrl &= ~(UARTCTRL_RIE | UARTCTRL_ILIE | UARTCTRL_RE | UARTCTRL_TIE | UARTCTRL_TE); - lpuart32_write(&sport->port, temp, UARTCTRL); + lpuart32_write(&sport->port, ctrl, UARTCTRL); } static void lpuart32_configure(struct lpuart_port *sport) { - unsigned long temp; + u32 ctrl; - temp = lpuart32_read(&sport->port, UARTCTRL); + ctrl = lpuart32_read(&sport->port, UARTCTRL); if (!sport->lpuart_dma_rx_use) - temp |= UARTCTRL_RIE | UARTCTRL_ILIE; + ctrl |= UARTCTRL_RIE | UARTCTRL_ILIE; if (!sport->lpuart_dma_tx_use) - temp |= UARTCTRL_TIE; - lpuart32_write(&sport->port, temp, UARTCTRL); + ctrl |= UARTCTRL_TIE; + lpuart32_write(&sport->port, ctrl, UARTCTRL); } static void lpuart32_hw_setup(struct lpuart_port *sport) @@ -1871,16 +1877,16 @@ static void lpuart32_hw_setup(struct lpuart_port *sport) static int lpuart32_startup(struct uart_port *port) { struct lpuart_port *sport = container_of(port, struct lpuart_port, port); - unsigned long temp; + u32 fifo; /* determine FIFO size */ - temp = lpuart32_read(&sport->port, UARTFIFO); + fifo = lpuart32_read(port, UARTFIFO); - sport->txfifo_size = UARTFIFO_DEPTH((temp >> UARTFIFO_TXSIZE_OFF) & + sport->txfifo_size = UARTFIFO_DEPTH((fifo >> UARTFIFO_TXSIZE_OFF) & UARTFIFO_FIFOSIZE_MASK); - sport->port.fifosize = sport->txfifo_size; + port->fifosize = sport->txfifo_size; - sport->rxfifo_size = UARTFIFO_DEPTH((temp >> UARTFIFO_RXSIZE_OFF) & + sport->rxfifo_size = UARTFIFO_DEPTH((fifo >> UARTFIFO_RXSIZE_OFF) & UARTFIFO_FIFOSIZE_MASK); /* @@ -1891,7 +1897,7 @@ static int lpuart32_startup(struct uart_port *port) if (is_layerscape_lpuart(sport)) { sport->rxfifo_size = 16; sport->txfifo_size = 16; - sport->port.fifosize = sport->txfifo_size; + port->fifosize = sport->txfifo_size; } lpuart_request_dma(sport); @@ -1925,16 +1931,16 @@ static void lpuart_dma_shutdown(struct lpuart_port *sport) static void lpuart_shutdown(struct uart_port *port) { struct lpuart_port *sport = container_of(port, struct lpuart_port, port); - unsigned char temp; + u8 cr2; unsigned long flags; uart_port_lock_irqsave(port, &flags); /* disable Rx/Tx and interrupts */ - temp = readb(port->membase + UARTCR2); - temp &= ~(UARTCR2_TE | UARTCR2_RE | + cr2 = readb(port->membase + UARTCR2); + cr2 &= ~(UARTCR2_TE | UARTCR2_RE | UARTCR2_TIE | UARTCR2_TCIE | UARTCR2_RIE); - writeb(temp, port->membase + UARTCR2); + writeb(cr2, port->membase + UARTCR2); uart_port_unlock_irqrestore(port, flags); @@ -1945,14 +1951,14 @@ static void lpuart32_shutdown(struct uart_port *port) { struct lpuart_port *sport = container_of(port, struct lpuart_port, port); - unsigned long temp; + u32 temp; unsigned long flags; uart_port_lock_irqsave(port, &flags); /* clear status */ - temp = lpuart32_read(&sport->port, UARTSTAT); - lpuart32_write(&sport->port, temp, UARTSTAT); + temp = lpuart32_read(port, UARTSTAT); + lpuart32_write(port, temp, UARTSTAT); /* disable Rx/Tx DMA */ temp = lpuart32_read(port, UARTBAUD); @@ -1981,17 +1987,17 @@ lpuart_set_termios(struct uart_port *port, struct ktermios *termios, { struct lpuart_port *sport = container_of(port, struct lpuart_port, port); unsigned long flags; - unsigned char cr1, old_cr1, old_cr2, cr3, cr4, bdh, modem; + u8 cr1, old_cr1, old_cr2, cr3, cr4, bdh, modem; unsigned int baud; unsigned int old_csize = old ? old->c_cflag & CSIZE : CS8; unsigned int sbr, brfa; - cr1 = old_cr1 = readb(sport->port.membase + UARTCR1); - old_cr2 = readb(sport->port.membase + UARTCR2); - cr3 = readb(sport->port.membase + UARTCR3); - cr4 = readb(sport->port.membase + UARTCR4); - bdh = readb(sport->port.membase + UARTBDH); - modem = readb(sport->port.membase + UARTMODEM); + cr1 = old_cr1 = readb(port->membase + UARTCR1); + old_cr2 = readb(port->membase + UARTCR2); + cr3 = readb(port->membase + UARTCR3); + cr4 = readb(port->membase + UARTCR4); + bdh = readb(port->membase + UARTBDH); + modem = readb(port->membase + UARTMODEM); /* * only support CS8 and CS7, and for CS7 must enable PE. * supported mode: @@ -2023,7 +2029,7 @@ lpuart_set_termios(struct uart_port *port, struct ktermios *termios, * When auto RS-485 RTS mode is enabled, * hardware flow control need to be disabled. */ - if (sport->port.rs485.flags & SER_RS485_ENABLED) + if (port->rs485.flags & SER_RS485_ENABLED) termios->c_cflag &= ~CRTSCTS; if (termios->c_cflag & CRTSCTS) @@ -2064,59 +2070,59 @@ lpuart_set_termios(struct uart_port *port, struct ktermios *termios, * Need to update the Ring buffer length according to the selected * baud rate and restart Rx DMA path. * - * Since timer function acqures sport->port.lock, need to stop before - * acquring same lock because otherwise del_timer_sync() can deadlock. + * Since timer function acqures port->lock, need to stop before + * acquring same lock because otherwise timer_delete_sync() can deadlock. */ if (old && sport->lpuart_dma_rx_use) - lpuart_dma_rx_free(&sport->port); + lpuart_dma_rx_free(port); - uart_port_lock_irqsave(&sport->port, &flags); + uart_port_lock_irqsave(port, &flags); - sport->port.read_status_mask = 0; + port->read_status_mask = 0; if (termios->c_iflag & INPCK) - sport->port.read_status_mask |= UARTSR1_FE | UARTSR1_PE; + port->read_status_mask |= UARTSR1_FE | UARTSR1_PE; if (termios->c_iflag & (IGNBRK | BRKINT | PARMRK)) - sport->port.read_status_mask |= UARTSR1_FE; + port->read_status_mask |= UARTSR1_FE; /* characters to ignore */ - sport->port.ignore_status_mask = 0; + port->ignore_status_mask = 0; if (termios->c_iflag & IGNPAR) - sport->port.ignore_status_mask |= UARTSR1_PE; + port->ignore_status_mask |= UARTSR1_PE; if (termios->c_iflag & IGNBRK) { - sport->port.ignore_status_mask |= UARTSR1_FE; + port->ignore_status_mask |= UARTSR1_FE; /* * if we're ignoring parity and break indicators, * ignore overruns too (for real raw support). */ if (termios->c_iflag & IGNPAR) - sport->port.ignore_status_mask |= UARTSR1_OR; + port->ignore_status_mask |= UARTSR1_OR; } /* update the per-port timeout */ uart_update_timeout(port, termios->c_cflag, baud); /* wait transmit engin complete */ - lpuart_wait_bit_set(&sport->port, UARTSR1, UARTSR1_TC); + lpuart_wait_bit_set(port, UARTSR1, UARTSR1_TC); /* disable transmit and receive */ writeb(old_cr2 & ~(UARTCR2_TE | UARTCR2_RE), - sport->port.membase + UARTCR2); + port->membase + UARTCR2); - sbr = sport->port.uartclk / (16 * baud); - brfa = ((sport->port.uartclk - (16 * sbr * baud)) * 2) / baud; + sbr = port->uartclk / (16 * baud); + brfa = ((port->uartclk - (16 * sbr * baud)) * 2) / baud; bdh &= ~UARTBDH_SBR_MASK; bdh |= (sbr >> 8) & 0x1F; cr4 &= ~UARTCR4_BRFA_MASK; brfa &= UARTCR4_BRFA_MASK; - writeb(cr4 | brfa, sport->port.membase + UARTCR4); - writeb(bdh, sport->port.membase + UARTBDH); - writeb(sbr & 0xFF, sport->port.membase + UARTBDL); - writeb(cr3, sport->port.membase + UARTCR3); - writeb(cr1, sport->port.membase + UARTCR1); - writeb(modem, sport->port.membase + UARTMODEM); + writeb(cr4 | brfa, port->membase + UARTCR4); + writeb(bdh, port->membase + UARTBDH); + writeb(sbr & 0xFF, port->membase + UARTBDL); + writeb(cr3, port->membase + UARTCR3); + writeb(cr1, port->membase + UARTCR1); + writeb(modem, port->membase + UARTMODEM); /* restore control register */ - writeb(old_cr2, sport->port.membase + UARTCR2); + writeb(old_cr2, port->membase + UARTCR2); if (old && sport->lpuart_dma_rx_use) { if (!lpuart_start_rx_dma(sport)) @@ -2125,14 +2131,14 @@ lpuart_set_termios(struct uart_port *port, struct ktermios *termios, sport->lpuart_dma_rx_use = false; } - uart_port_unlock_irqrestore(&sport->port, flags); + uart_port_unlock_irqrestore(port, flags); } static void __lpuart32_serial_setbrg(struct uart_port *port, unsigned int baudrate, bool use_rx_dma, bool use_tx_dma) { - u32 sbr, osr, baud_diff, tmp_osr, tmp_sbr, tmp_diff, tmp; + u32 sbr, osr, baud_diff, tmp_osr, tmp_sbr, tmp_diff, baud; u32 clk = port->uartclk; /* @@ -2161,9 +2167,9 @@ static void __lpuart32_serial_setbrg(struct uart_port *port, tmp_diff = clk / (tmp_osr * tmp_sbr) - baudrate; /* select best values between sbr and sbr+1 */ - tmp = clk / (tmp_osr * (tmp_sbr + 1)); - if (tmp_diff > (baudrate - tmp)) { - tmp_diff = baudrate - tmp; + baud = clk / (tmp_osr * (tmp_sbr + 1)); + if (tmp_diff > (baudrate - baud)) { + tmp_diff = baudrate - baud; tmp_sbr++; } @@ -2185,23 +2191,23 @@ static void __lpuart32_serial_setbrg(struct uart_port *port, dev_warn(port->dev, "unacceptable baud rate difference of more than 3%%\n"); - tmp = lpuart32_read(port, UARTBAUD); + baud = lpuart32_read(port, UARTBAUD); if ((osr > 3) && (osr < 8)) - tmp |= UARTBAUD_BOTHEDGE; + baud |= UARTBAUD_BOTHEDGE; - tmp &= ~(UARTBAUD_OSR_MASK << UARTBAUD_OSR_SHIFT); - tmp |= ((osr-1) & UARTBAUD_OSR_MASK) << UARTBAUD_OSR_SHIFT; + baud &= ~(UARTBAUD_OSR_MASK << UARTBAUD_OSR_SHIFT); + baud |= ((osr-1) & UARTBAUD_OSR_MASK) << UARTBAUD_OSR_SHIFT; - tmp &= ~UARTBAUD_SBR_MASK; - tmp |= sbr & UARTBAUD_SBR_MASK; + baud &= ~UARTBAUD_SBR_MASK; + baud |= sbr & UARTBAUD_SBR_MASK; if (!use_rx_dma) - tmp &= ~UARTBAUD_RDMAE; + baud &= ~UARTBAUD_RDMAE; if (!use_tx_dma) - tmp &= ~UARTBAUD_TDMAE; + baud &= ~UARTBAUD_TDMAE; - lpuart32_write(port, tmp, UARTBAUD); + lpuart32_write(port, baud, UARTBAUD); } static void lpuart32_serial_setbrg(struct lpuart_port *sport, @@ -2219,13 +2225,13 @@ lpuart32_set_termios(struct uart_port *port, struct ktermios *termios, { struct lpuart_port *sport = container_of(port, struct lpuart_port, port); unsigned long flags; - unsigned long ctrl, old_ctrl, bd, modem; + u32 ctrl, old_ctrl, bd, modem; unsigned int baud; unsigned int old_csize = old ? old->c_cflag & CSIZE : CS8; - ctrl = old_ctrl = lpuart32_read(&sport->port, UARTCTRL); - bd = lpuart32_read(&sport->port, UARTBAUD); - modem = lpuart32_read(&sport->port, UARTMODIR); + ctrl = old_ctrl = lpuart32_read(port, UARTCTRL); + bd = lpuart32_read(port, UARTBAUD); + modem = lpuart32_read(port, UARTMODIR); sport->is_cs7 = false; /* * only support CS8 and CS7 @@ -2259,7 +2265,7 @@ lpuart32_set_termios(struct uart_port *port, struct ktermios *termios, * When auto RS-485 RTS mode is enabled, * hardware flow control need to be disabled. */ - if (sport->port.rs485.flags & SER_RS485_ENABLED) + if (port->rs485.flags & SER_RS485_ENABLED) termios->c_cflag &= ~CRTSCTS; if (termios->c_cflag & CRTSCTS) @@ -2309,59 +2315,61 @@ lpuart32_set_termios(struct uart_port *port, struct ktermios *termios, * Need to update the Ring buffer length according to the selected * baud rate and restart Rx DMA path. * - * Since timer function acqures sport->port.lock, need to stop before - * acquring same lock because otherwise del_timer_sync() can deadlock. + * Since timer function acqures port->lock, need to stop before + * acquring same lock because otherwise timer_delete_sync() can deadlock. */ if (old && sport->lpuart_dma_rx_use) - lpuart_dma_rx_free(&sport->port); + lpuart_dma_rx_free(port); - uart_port_lock_irqsave(&sport->port, &flags); + uart_port_lock_irqsave(port, &flags); - sport->port.read_status_mask = 0; + port->read_status_mask = 0; if (termios->c_iflag & INPCK) - sport->port.read_status_mask |= UARTSTAT_FE | UARTSTAT_PE; + port->read_status_mask |= UARTSTAT_FE | UARTSTAT_PE; if (termios->c_iflag & (IGNBRK | BRKINT | PARMRK)) - sport->port.read_status_mask |= UARTSTAT_FE; + port->read_status_mask |= UARTSTAT_FE; /* characters to ignore */ - sport->port.ignore_status_mask = 0; + port->ignore_status_mask = 0; if (termios->c_iflag & IGNPAR) - sport->port.ignore_status_mask |= UARTSTAT_PE; + port->ignore_status_mask |= UARTSTAT_PE; if (termios->c_iflag & IGNBRK) { - sport->port.ignore_status_mask |= UARTSTAT_FE; + port->ignore_status_mask |= UARTSTAT_FE; /* * if we're ignoring parity and break indicators, * ignore overruns too (for real raw support). */ if (termios->c_iflag & IGNPAR) - sport->port.ignore_status_mask |= UARTSTAT_OR; + port->ignore_status_mask |= UARTSTAT_OR; } /* update the per-port timeout */ uart_update_timeout(port, termios->c_cflag, baud); /* + * disable CTS to ensure the transmit engine is not blocked by the flow + * control when there is dirty data in TX FIFO + */ + lpuart32_write(port, modem & ~UARTMODIR_TXCTSE, UARTMODIR); + + /* * LPUART Transmission Complete Flag may never be set while queuing a break * character, so skip waiting for transmission complete when UARTCTRL_SBK is * asserted. */ - if (!(old_ctrl & UARTCTRL_SBK)) { - lpuart32_write(&sport->port, 0, UARTMODIR); - lpuart32_wait_bit_set(&sport->port, UARTSTAT, UARTSTAT_TC); - } + if (!(old_ctrl & UARTCTRL_SBK)) + lpuart32_wait_bit_set(port, UARTSTAT, UARTSTAT_TC); /* disable transmit and receive */ - lpuart32_write(&sport->port, old_ctrl & ~(UARTCTRL_TE | UARTCTRL_RE), + lpuart32_write(port, old_ctrl & ~(UARTCTRL_TE | UARTCTRL_RE), UARTCTRL); - lpuart32_write(&sport->port, bd, UARTBAUD); + lpuart32_write(port, bd, UARTBAUD); lpuart32_serial_setbrg(sport, baud); - /* disable CTS before enabling UARTCTRL_TE to avoid pending idle preamble */ - lpuart32_write(&sport->port, modem & ~UARTMODIR_TXCTSE, UARTMODIR); /* restore control register */ - lpuart32_write(&sport->port, ctrl, UARTCTRL); + lpuart32_write(port, ctrl, UARTCTRL); /* re-enable the CTS if needed */ - lpuart32_write(&sport->port, modem, UARTMODIR); + lpuart32_write(port, modem, UARTMODIR); if ((ctrl & (UARTCTRL_PE | UARTCTRL_M)) == UARTCTRL_PE) sport->is_cs7 = true; @@ -2373,7 +2381,7 @@ lpuart32_set_termios(struct uart_port *port, struct ktermios *termios, sport->lpuart_dma_rx_use = false; } - uart_port_unlock_irqrestore(&sport->port, flags); + uart_port_unlock_irqrestore(port, flags); } static const char *lpuart_type(struct uart_port *port) @@ -2486,7 +2494,7 @@ static void lpuart_console_write(struct console *co, const char *s, unsigned int count) { struct lpuart_port *sport = lpuart_ports[co->index]; - unsigned char old_cr2, cr2; + u8 old_cr2, cr2; unsigned long flags; int locked = 1; @@ -2516,7 +2524,7 @@ static void lpuart32_console_write(struct console *co, const char *s, unsigned int count) { struct lpuart_port *sport = lpuart_ports[co->index]; - unsigned long old_cr, cr; + u32 old_cr, cr; unsigned long flags; int locked = 1; @@ -2550,7 +2558,7 @@ static void __init lpuart_console_get_options(struct lpuart_port *sport, int *baud, int *parity, int *bits) { - unsigned char cr, bdh, bdl, brfa; + u8 cr, bdh, bdl, brfa; unsigned int sbr, uartclk, baud_raw; cr = readb(sport->port.membase + UARTCR2); @@ -2599,7 +2607,7 @@ static void __init lpuart32_console_get_options(struct lpuart_port *sport, int *baud, int *parity, int *bits) { - unsigned long cr, bd; + u32 cr, bd; unsigned int sbr, uartclk, baud_raw; cr = lpuart32_read(&sport->port, UARTCTRL); @@ -2805,13 +2813,13 @@ static int lpuart_global_reset(struct lpuart_port *sport) { struct uart_port *port = &sport->port; void __iomem *global_addr; - unsigned long ctrl, bd; + u32 ctrl, bd; unsigned int val = 0; int ret; ret = clk_prepare_enable(sport->ipg_clk); if (ret) { - dev_err(sport->port.dev, "failed to enable uart ipg clk: %d\n", ret); + dev_err(port->dev, "failed to enable uart ipg clk: %d\n", ret); return ret; } @@ -2822,10 +2830,10 @@ static int lpuart_global_reset(struct lpuart_port *sport) */ ctrl = lpuart32_read(port, UARTCTRL); if (ctrl & UARTCTRL_TE) { - bd = lpuart32_read(&sport->port, UARTBAUD); + bd = lpuart32_read(port, UARTBAUD); if (read_poll_timeout(lpuart32_tx_empty, val, val, 1, 100000, false, port)) { - dev_warn(sport->port.dev, + dev_warn(port->dev, "timeout waiting for transmit engine to complete\n"); clk_disable_unprepare(sport->ipg_clk); return 0; @@ -2954,7 +2962,7 @@ static int lpuart_probe(struct platform_device *pdev) goto failed_attach_port; ret = devm_request_irq(&pdev->dev, sport->port.irq, handler, 0, - DRIVER_NAME, sport); + dev_name(&pdev->dev), sport); if (ret) goto failed_irq_request; @@ -3011,7 +3019,7 @@ static int lpuart_runtime_resume(struct device *dev) static void serial_lpuart_enable_wakeup(struct lpuart_port *sport, bool on) { - unsigned int val, baud; + u32 val, baud; if (lpuart_is_32(sport)) { val = lpuart32_read(&sport->port, UARTCTRL); @@ -3076,7 +3084,7 @@ static int lpuart_suspend_noirq(struct device *dev) static int lpuart_resume_noirq(struct device *dev) { struct lpuart_port *sport = dev_get_drvdata(dev); - unsigned int val; + u32 stat; pinctrl_pm_select_default_state(dev); @@ -3085,8 +3093,8 @@ static int lpuart_resume_noirq(struct device *dev) /* clear the wakeup flags */ if (lpuart_is_32(sport)) { - val = lpuart32_read(&sport->port, UARTSTAT); - lpuart32_write(&sport->port, val, UARTSTAT); + stat = lpuart32_read(&sport->port, UARTSTAT); + lpuart32_write(&sport->port, stat, UARTSTAT); } } @@ -3096,7 +3104,8 @@ static int lpuart_resume_noirq(struct device *dev) static int lpuart_suspend(struct device *dev) { struct lpuart_port *sport = dev_get_drvdata(dev); - unsigned long temp, flags; + u32 temp; + unsigned long flags; uart_suspend_port(&lpuart_reg, &sport->port); @@ -3176,7 +3185,7 @@ static void lpuart_console_fixup(struct lpuart_port *sport) * in VLLS mode, or restore console setting here. */ if (is_imx7ulp_lpuart(sport) && lpuart_uport_is_active(sport) && - console_suspend_enabled && uart_console(&sport->port)) { + console_suspend_enabled && uart_console(uport)) { mutex_lock(&port->mutex); memset(&termios, 0, sizeof(struct ktermios));
diff --git a/drivers/tty/serial/icom.c b/drivers/tty/serial/icom.c index 29e4283..7fb995a 100644 --- a/drivers/tty/serial/icom.c +++ b/drivers/tty/serial/icom.c
@@ -1764,11 +1764,10 @@ static int icom_probe(struct pci_dev *dev, goto probe_exit1; } - /* save off irq and request irq line */ - retval = request_irq(dev->irq, icom_interrupt, IRQF_SHARED, ICOM_DRIVER_NAME, (void *)icom_adapter); - if (retval) { - goto probe_exit2; - } + /* save off irq and request irq line */ + retval = request_irq(dev->irq, icom_interrupt, IRQF_SHARED, ICOM_DRIVER_NAME, icom_adapter); + if (retval) + goto probe_exit2; retval = icom_load_ports(icom_adapter);
diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index 9a1afe4..e4b6f1b 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c
@@ -1608,7 +1608,7 @@ static void imx_uart_shutdown(struct uart_port *port) imx_uart_dma_exit(sport); } - mctrl_gpio_disable_ms(sport->gpios); + mctrl_gpio_disable_ms_sync(sport->gpios); uart_port_lock_irqsave(&sport->port, &flags); ucr2 = imx_uart_readl(sport, UCR2); @@ -1619,7 +1619,7 @@ static void imx_uart_shutdown(struct uart_port *port) /* * Stop our timer. */ - del_timer_sync(&sport->timer); + timer_delete_sync(&sport->timer); /* * Disable all interrupts, port and break condition. @@ -1752,7 +1752,7 @@ imx_uart_set_termios(struct uart_port *port, struct ktermios *termios, old_csize = CS8; } - del_timer_sync(&sport->timer); + timer_delete_sync(&sport->timer); /* * Ask the core to calculate the divisor for us.
diff --git a/drivers/tty/serial/kgdb_nmi.c b/drivers/tty/serial/kgdb_nmi.c deleted file mode 100644 index 2833708..0000000 --- a/drivers/tty/serial/kgdb_nmi.c +++ /dev/null
@@ -1,280 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * KGDB NMI serial console - * - * Copyright 2010 Google, Inc. - * Arve Hjønnevåg <arve@android.com> - * Colin Cross <ccross@android.com> - * Copyright 2012 Linaro Ltd. - * Anton Vorontsov <anton.vorontsov@linaro.org> - */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/compiler.h> -#include <linux/slab.h> -#include <linux/errno.h> -#include <linux/atomic.h> -#include <linux/console.h> -#include <linux/tty.h> -#include <linux/tty_driver.h> -#include <linux/tty_flip.h> -#include <linux/serial_core.h> -#include <linux/interrupt.h> -#include <linux/hrtimer.h> -#include <linux/tick.h> -#include <linux/kfifo.h> -#include <linux/kgdb.h> -#include <linux/kdb.h> - -static atomic_t kgdb_nmi_num_readers = ATOMIC_INIT(0); - -static int kgdb_nmi_console_setup(struct console *co, char *options) -{ - arch_kgdb_ops.enable_nmi(1); - - /* The NMI console uses the dbg_io_ops to issue console messages. To - * avoid duplicate messages during kdb sessions we must inform kdb's - * I/O utilities that messages sent to the console will automatically - * be displayed on the dbg_io. - */ - dbg_io_ops->cons = co; - - return 0; -} - -static void kgdb_nmi_console_write(struct console *co, const char *s, uint c) -{ - int i; - - for (i = 0; i < c; i++) - dbg_io_ops->write_char(s[i]); -} - -static struct tty_driver *kgdb_nmi_tty_driver; - -static struct tty_driver *kgdb_nmi_console_device(struct console *co, int *idx) -{ - *idx = co->index; - return kgdb_nmi_tty_driver; -} - -static struct console kgdb_nmi_console = { - .name = "ttyNMI", - .setup = kgdb_nmi_console_setup, - .write = kgdb_nmi_console_write, - .device = kgdb_nmi_console_device, - .flags = CON_PRINTBUFFER | CON_ANYTIME, - .index = -1, -}; - -/* - * This is usually the maximum rate on debug ports. We make fifo large enough - * to make copy-pasting to the terminal usable. - */ -#define KGDB_NMI_BAUD 115200 -#define KGDB_NMI_FIFO_SIZE roundup_pow_of_two(KGDB_NMI_BAUD / 8 / HZ) - -struct kgdb_nmi_tty_priv { - struct tty_port port; - struct timer_list timer; - STRUCT_KFIFO(char, KGDB_NMI_FIFO_SIZE) fifo; -}; - -static struct tty_port *kgdb_nmi_port; - -/* - * The tasklet is cheap, it does not cause wakeups when reschedules itself, - * instead it waits for the next tick. - */ -static void kgdb_nmi_tty_receiver(struct timer_list *t) -{ - struct kgdb_nmi_tty_priv *priv = from_timer(priv, t, timer); - char ch; - - priv->timer.expires = jiffies + (HZ/100); - add_timer(&priv->timer); - - if (likely(!atomic_read(&kgdb_nmi_num_readers) || - !kfifo_len(&priv->fifo))) - return; - - while (kfifo_out(&priv->fifo, &ch, 1)) - tty_insert_flip_char(&priv->port, ch, TTY_NORMAL); - tty_flip_buffer_push(&priv->port); -} - -static int kgdb_nmi_tty_activate(struct tty_port *port, struct tty_struct *tty) -{ - struct kgdb_nmi_tty_priv *priv = - container_of(port, struct kgdb_nmi_tty_priv, port); - - kgdb_nmi_port = port; - priv->timer.expires = jiffies + (HZ/100); - add_timer(&priv->timer); - - return 0; -} - -static void kgdb_nmi_tty_shutdown(struct tty_port *port) -{ - struct kgdb_nmi_tty_priv *priv = - container_of(port, struct kgdb_nmi_tty_priv, port); - - del_timer(&priv->timer); - kgdb_nmi_port = NULL; -} - -static const struct tty_port_operations kgdb_nmi_tty_port_ops = { - .activate = kgdb_nmi_tty_activate, - .shutdown = kgdb_nmi_tty_shutdown, -}; - -static int kgdb_nmi_tty_install(struct tty_driver *drv, struct tty_struct *tty) -{ - struct kgdb_nmi_tty_priv *priv; - int ret; - - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - - INIT_KFIFO(priv->fifo); - timer_setup(&priv->timer, kgdb_nmi_tty_receiver, 0); - tty_port_init(&priv->port); - priv->port.ops = &kgdb_nmi_tty_port_ops; - tty->driver_data = priv; - - ret = tty_port_install(&priv->port, drv, tty); - if (ret) { - pr_err("%s: can't install tty port: %d\n", __func__, ret); - goto err; - } - return 0; -err: - tty_port_destroy(&priv->port); - kfree(priv); - return ret; -} - -static void kgdb_nmi_tty_cleanup(struct tty_struct *tty) -{ - struct kgdb_nmi_tty_priv *priv = tty->driver_data; - - tty->driver_data = NULL; - tty_port_destroy(&priv->port); - kfree(priv); -} - -static int kgdb_nmi_tty_open(struct tty_struct *tty, struct file *file) -{ - struct kgdb_nmi_tty_priv *priv = tty->driver_data; - unsigned int mode = file->f_flags & O_ACCMODE; - int ret; - - ret = tty_port_open(&priv->port, tty, file); - if (!ret && (mode == O_RDONLY || mode == O_RDWR)) - atomic_inc(&kgdb_nmi_num_readers); - - return ret; -} - -static void kgdb_nmi_tty_close(struct tty_struct *tty, struct file *file) -{ - struct kgdb_nmi_tty_priv *priv = tty->driver_data; - unsigned int mode = file->f_flags & O_ACCMODE; - - if (mode == O_RDONLY || mode == O_RDWR) - atomic_dec(&kgdb_nmi_num_readers); - - tty_port_close(&priv->port, tty, file); -} - -static void kgdb_nmi_tty_hangup(struct tty_struct *tty) -{ - struct kgdb_nmi_tty_priv *priv = tty->driver_data; - - tty_port_hangup(&priv->port); -} - -static unsigned int kgdb_nmi_tty_write_room(struct tty_struct *tty) -{ - /* Actually, we can handle any amount as we use polled writes. */ - return 2048; -} - -static ssize_t kgdb_nmi_tty_write(struct tty_struct *tty, const u8 *buf, - size_t c) -{ - int i; - - for (i = 0; i < c; i++) - dbg_io_ops->write_char(buf[i]); - return c; -} - -static const struct tty_operations kgdb_nmi_tty_ops = { - .open = kgdb_nmi_tty_open, - .close = kgdb_nmi_tty_close, - .install = kgdb_nmi_tty_install, - .cleanup = kgdb_nmi_tty_cleanup, - .hangup = kgdb_nmi_tty_hangup, - .write_room = kgdb_nmi_tty_write_room, - .write = kgdb_nmi_tty_write, -}; - -int kgdb_register_nmi_console(void) -{ - int ret; - - if (!arch_kgdb_ops.enable_nmi) - return 0; - - kgdb_nmi_tty_driver = tty_alloc_driver(1, TTY_DRIVER_REAL_RAW); - if (IS_ERR(kgdb_nmi_tty_driver)) { - pr_err("%s: cannot allocate tty\n", __func__); - return PTR_ERR(kgdb_nmi_tty_driver); - } - kgdb_nmi_tty_driver->driver_name = "ttyNMI"; - kgdb_nmi_tty_driver->name = "ttyNMI"; - kgdb_nmi_tty_driver->num = 1; - kgdb_nmi_tty_driver->type = TTY_DRIVER_TYPE_SERIAL; - kgdb_nmi_tty_driver->subtype = SERIAL_TYPE_NORMAL; - kgdb_nmi_tty_driver->init_termios = tty_std_termios; - tty_termios_encode_baud_rate(&kgdb_nmi_tty_driver->init_termios, - KGDB_NMI_BAUD, KGDB_NMI_BAUD); - tty_set_operations(kgdb_nmi_tty_driver, &kgdb_nmi_tty_ops); - - ret = tty_register_driver(kgdb_nmi_tty_driver); - if (ret) { - pr_err("%s: can't register tty driver: %d\n", __func__, ret); - goto err_drv_reg; - } - - register_console(&kgdb_nmi_console); - - return 0; -err_drv_reg: - tty_driver_kref_put(kgdb_nmi_tty_driver); - return ret; -} -EXPORT_SYMBOL_GPL(kgdb_register_nmi_console); - -int kgdb_unregister_nmi_console(void) -{ - int ret; - - if (!arch_kgdb_ops.enable_nmi) - return 0; - arch_kgdb_ops.enable_nmi(0); - - ret = unregister_console(&kgdb_nmi_console); - if (ret) - return ret; - - tty_unregister_driver(kgdb_nmi_tty_driver); - tty_driver_kref_put(kgdb_nmi_tty_driver); - - return 0; -} -EXPORT_SYMBOL_GPL(kgdb_unregister_nmi_console);
diff --git a/drivers/tty/serial/kgdboc.c b/drivers/tty/serial/kgdboc.c index 58ea1e1..85f6c5a 100644 --- a/drivers/tty/serial/kgdboc.c +++ b/drivers/tty/serial/kgdboc.c
@@ -186,8 +186,6 @@ static void cleanup_kgdboc(void) if (configured != 1) return; - if (kgdb_unregister_nmi_console()) - return; kgdboc_unregister_kbd(); kgdb_unregister_io_module(&kgdboc_io_ops); } @@ -250,16 +248,10 @@ static int configure_kgdboc(void) if (err) goto noconfig; - err = kgdb_register_nmi_console(); - if (err) - goto nmi_con_failed; - configured = 1; return 0; -nmi_con_failed: - kgdb_unregister_io_module(&kgdboc_io_ops); noconfig: kgdboc_unregister_kbd(); configured = 0;
diff --git a/drivers/tty/serial/liteuart.c b/drivers/tty/serial/liteuart.c index 6c13cf1a..3a0960c 100644 --- a/drivers/tty/serial/liteuart.c +++ b/drivers/tty/serial/liteuart.c
@@ -96,7 +96,7 @@ static void liteuart_stop_rx(struct uart_port *port) struct liteuart_port *uart = to_liteuart_port(port); /* just delete timer */ - del_timer(&uart->timer); + timer_delete(&uart->timer); } static void liteuart_rx_chars(struct uart_port *port) @@ -220,7 +220,7 @@ static void liteuart_shutdown(struct uart_port *port) if (port->irq) free_irq(port->irq, port); else - del_timer_sync(&uart->timer); + timer_delete_sync(&uart->timer); } static void liteuart_set_termios(struct uart_port *port, struct ktermios *new,
diff --git a/drivers/tty/serial/ma35d1_serial.c b/drivers/tty/serial/ma35d1_serial.c index 8dcad52..285b0fe 100644 --- a/drivers/tty/serial/ma35d1_serial.c +++ b/drivers/tty/serial/ma35d1_serial.c
@@ -799,7 +799,7 @@ static struct platform_driver ma35d1serial_driver = { .resume = ma35d1serial_resume, .driver = { .name = "ma35d1-uart", - .of_match_table = of_match_ptr(ma35d1_serial_of_match), + .of_match_table = ma35d1_serial_of_match, }, };
diff --git a/drivers/tty/serial/max3100.c b/drivers/tty/serial/max3100.c index cde5f1c..f2dd836 100644 --- a/drivers/tty/serial/max3100.c +++ b/drivers/tty/serial/max3100.c
@@ -506,7 +506,7 @@ max3100_set_termios(struct uart_port *port, struct ktermios *termios, MAX3100_STATUS_PE | MAX3100_STATUS_FE | MAX3100_STATUS_OE; - del_timer_sync(&s->timer); + timer_delete_sync(&s->timer); uart_update_timeout(port, termios->c_cflag, baud); spin_lock(&s->conf_lock); @@ -532,7 +532,7 @@ static void max3100_shutdown(struct uart_port *port) s->force_end_work = 1; - del_timer_sync(&s->timer); + timer_delete_sync(&s->timer); if (s->workqueue) { destroy_workqueue(s->workqueue);
diff --git a/drivers/tty/serial/mpc52xx_uart.c b/drivers/tty/serial/mpc52xx_uart.c index 2204cc3..37eb701 100644 --- a/drivers/tty/serial/mpc52xx_uart.c +++ b/drivers/tty/serial/mpc52xx_uart.c
@@ -1351,7 +1351,6 @@ static const struct uart_ops mpc52xx_uart_ops = { .startup = mpc52xx_uart_startup, .shutdown = mpc52xx_uart_shutdown, .set_termios = mpc52xx_uart_set_termios, -/* .pm = mpc52xx_uart_pm, Not supported yet */ .type = mpc52xx_uart_type, .release_port = mpc52xx_uart_release_port, .request_port = mpc52xx_uart_request_port,
diff --git a/drivers/tty/serial/mux.c b/drivers/tty/serial/mux.c index 85ce1e9..b417fae 100644 --- a/drivers/tty/serial/mux.c +++ b/drivers/tty/serial/mux.c
@@ -563,7 +563,7 @@ static void __exit mux_exit(void) { /* Delete the Mux timer. */ if(port_cnt > 0) { - del_timer_sync(&mux_timer); + timer_delete_sync(&mux_timer); #ifdef CONFIG_SERIAL_MUX_CONSOLE unregister_console(&mux_console); #endif
diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c index c7cee5f..508e8c6 100644 --- a/drivers/tty/serial/pch_uart.c +++ b/drivers/tty/serial/pch_uart.c
@@ -1515,7 +1515,6 @@ static const struct uart_ops pch_uart_ops = { .startup = pch_uart_startup, .shutdown = pch_uart_shutdown, .set_termios = pch_uart_set_termios, -/* .pm = pch_uart_pm, Not supported yet */ .type = pch_uart_type, .release_port = pch_uart_release_port, .request_port = pch_uart_request_port,
diff --git a/drivers/tty/serial/sa1100.c b/drivers/tty/serial/sa1100.c index 3c34027..8587ebb 100644 --- a/drivers/tty/serial/sa1100.c +++ b/drivers/tty/serial/sa1100.c
@@ -369,7 +369,7 @@ static void sa1100_shutdown(struct uart_port *port) /* * Stop our timer. */ - del_timer_sync(&sport->timer); + timer_delete_sync(&sport->timer); /* * Free the interrupt @@ -421,7 +421,7 @@ sa1100_set_termios(struct uart_port *port, struct ktermios *termios, baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); quot = uart_get_divisor(port, baud); - del_timer_sync(&sport->timer); + timer_delete_sync(&sport->timer); uart_port_lock_irqsave(&sport->port, &flags);
diff --git a/drivers/tty/serial/sccnxp.c b/drivers/tty/serial/sccnxp.c index 4c851da..553e3c1 100644 --- a/drivers/tty/serial/sccnxp.c +++ b/drivers/tty/serial/sccnxp.c
@@ -1033,7 +1033,7 @@ static void sccnxp_remove(struct platform_device *pdev) if (!s->poll) devm_free_irq(&pdev->dev, s->irq, s); else - del_timer_sync(&s->timer); + timer_delete_sync(&s->timer); for (i = 0; i < s->uart.nr; i++) uart_remove_one_port(&s->uart, &s->port[i]);
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index d46650e..8866997 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c
@@ -895,8 +895,8 @@ static int uart_set_info(struct tty_struct *tty, struct tty_port *port, { struct uart_port *uport = uart_port_check(state); unsigned long new_port; - unsigned int change_irq, change_port, closing_wait; - unsigned int old_custom_divisor, close_delay; + unsigned int old_custom_divisor, close_delay, closing_wait; + bool change_irq, change_port; upf_t old_flags, new_flags; int retval; @@ -2013,9 +2013,8 @@ static const char *uart_type(struct uart_port *port) #ifdef CONFIG_PROC_FS -static void uart_line_info(struct seq_file *m, struct uart_driver *drv, int i) +static void uart_line_info(struct seq_file *m, struct uart_state *state) { - struct uart_state *state = drv->state + i; struct tty_port *port = &state->port; enum uart_pm_state pm_state; struct uart_port *uport; @@ -2100,7 +2099,7 @@ static int uart_proc_show(struct seq_file *m, void *v) seq_printf(m, "serinfo:1.0 driver%s%s revision:%s\n", "", "", ""); for (i = 0; i < drv->nr; i++) - uart_line_info(m, drv, i); + uart_line_info(m, drv->state + i); return 0; } #endif @@ -3156,7 +3155,6 @@ static int serial_core_add_one_port(struct uart_driver *drv, struct uart_port *u if (uport->cons && uport->dev) of_console_check(uport->dev->of_node, uport->cons->name, uport->line); - tty_port_link_device(port, drv->tty_driver, uport->line); uart_configure_port(drv, state, uport); port->console = uart_console(uport);
diff --git a/drivers/tty/serial/serial_mctrl_gpio.c b/drivers/tty/serial/serial_mctrl_gpio.c index 8855688..7b02c5c 100644 --- a/drivers/tty/serial/serial_mctrl_gpio.c +++ b/drivers/tty/serial/serial_mctrl_gpio.c
@@ -217,7 +217,7 @@ static irqreturn_t mctrl_gpio_irq_handle(int irq, void *context) * * This will get the {cts,rts,...}-gpios from device tree if they are present * and request them, set direction etc, and return an allocated structure. - * `devm_*` functions are used, so there's no need to call mctrl_gpio_free(). + * `devm_*` functions are used, so there's no need to explicitly free. * As this sets up the irq handling, make sure to not handle changes to the * gpio input lines in your driver, too. */ @@ -268,32 +268,6 @@ struct mctrl_gpios *mctrl_gpio_init(struct uart_port *port, unsigned int idx) EXPORT_SYMBOL_GPL(mctrl_gpio_init); /** - * mctrl_gpio_free - explicitly free uart gpios - * @dev: uart port's device - * @gpios: gpios structure to be freed - * - * This will free the requested gpios in mctrl_gpio_init(). As `devm_*` - * functions are used, there's generally no need to call this function. - */ -void mctrl_gpio_free(struct device *dev, struct mctrl_gpios *gpios) -{ - enum mctrl_gpio_idx i; - - if (gpios == NULL) - return; - - for (i = 0; i < UART_GPIO_MAX; i++) { - if (gpios->irq[i]) - devm_free_irq(gpios->port->dev, gpios->irq[i], gpios); - - if (gpios->gpio[i]) - devm_gpiod_put(dev, gpios->gpio[i]); - } - devm_kfree(dev, gpios); -} -EXPORT_SYMBOL_GPL(mctrl_gpio_free); - -/** * mctrl_gpio_enable_ms - enable irqs and handling of changes to the ms lines * @gpios: gpios to enable */ @@ -322,11 +296,7 @@ void mctrl_gpio_enable_ms(struct mctrl_gpios *gpios) } EXPORT_SYMBOL_GPL(mctrl_gpio_enable_ms); -/** - * mctrl_gpio_disable_ms - disable irqs and handling of changes to the ms lines - * @gpios: gpios to disable - */ -void mctrl_gpio_disable_ms(struct mctrl_gpios *gpios) +static void mctrl_gpio_disable_ms(struct mctrl_gpios *gpios, bool sync) { enum mctrl_gpio_idx i; @@ -342,10 +312,34 @@ void mctrl_gpio_disable_ms(struct mctrl_gpios *gpios) if (!gpios->irq[i]) continue; - disable_irq(gpios->irq[i]); + if (sync) + disable_irq(gpios->irq[i]); + else + disable_irq_nosync(gpios->irq[i]); } } -EXPORT_SYMBOL_GPL(mctrl_gpio_disable_ms); + +/** + * mctrl_gpio_disable_ms_sync - disable irqs and handling of changes to the ms + * lines, and wait for any pending IRQ to be processed + * @gpios: gpios to disable + */ +void mctrl_gpio_disable_ms_sync(struct mctrl_gpios *gpios) +{ + mctrl_gpio_disable_ms(gpios, true); +} +EXPORT_SYMBOL_GPL(mctrl_gpio_disable_ms_sync); + +/** + * mctrl_gpio_disable_ms_no_sync - disable irqs and handling of changes to the + * ms lines, and return immediately + * @gpios: gpios to disable + */ +void mctrl_gpio_disable_ms_no_sync(struct mctrl_gpios *gpios) +{ + mctrl_gpio_disable_ms(gpios, false); +} +EXPORT_SYMBOL_GPL(mctrl_gpio_disable_ms_no_sync); void mctrl_gpio_enable_irq_wake(struct mctrl_gpios *gpios) {
diff --git a/drivers/tty/serial/serial_mctrl_gpio.h b/drivers/tty/serial/serial_mctrl_gpio.h index fc76910..961e4ba 100644 --- a/drivers/tty/serial/serial_mctrl_gpio.h +++ b/drivers/tty/serial/serial_mctrl_gpio.h
@@ -59,7 +59,7 @@ struct gpio_desc *mctrl_gpio_to_gpiod(struct mctrl_gpios *gpios, /* * Request and set direction of modem control line GPIOs and set up irq * handling. - * devm_* functions are used, so there's no need to call mctrl_gpio_free(). + * devm_* functions are used, so there's no need to explicitly free. * Returns a pointer to the allocated mctrl structure if ok, -ENOMEM on * allocation error. */ @@ -67,7 +67,7 @@ struct mctrl_gpios *mctrl_gpio_init(struct uart_port *port, unsigned int idx); /* * Request and set direction of modem control line GPIOs. - * devm_* functions are used, so there's no need to call mctrl_gpio_free(). + * devm_* functions are used, so there's no need to explicitly free. * Returns a pointer to the allocated mctrl structure if ok, -ENOMEM on * allocation error. */ @@ -75,21 +75,21 @@ struct mctrl_gpios *mctrl_gpio_init_noauto(struct device *dev, unsigned int idx); /* - * Free the mctrl_gpios structure. - * Normally, this function will not be called, as the GPIOs will - * be disposed of by the resource management code. - */ -void mctrl_gpio_free(struct device *dev, struct mctrl_gpios *gpios); - -/* * Enable gpio interrupts to report status line changes. */ void mctrl_gpio_enable_ms(struct mctrl_gpios *gpios); /* - * Disable gpio interrupts to report status line changes. + * Disable gpio interrupts to report status line changes, and block until + * any corresponding IRQ is processed */ -void mctrl_gpio_disable_ms(struct mctrl_gpios *gpios); +void mctrl_gpio_disable_ms_sync(struct mctrl_gpios *gpios); + +/* + * Disable gpio interrupts to report status line changes, and return + * immediately + */ +void mctrl_gpio_disable_ms_no_sync(struct mctrl_gpios *gpios); /* * Enable gpio wakeup interrupts to enable wake up source. @@ -139,16 +139,15 @@ struct mctrl_gpios *mctrl_gpio_init_noauto(struct device *dev, unsigned int idx) return NULL; } -static inline -void mctrl_gpio_free(struct device *dev, struct mctrl_gpios *gpios) -{ -} - static inline void mctrl_gpio_enable_ms(struct mctrl_gpios *gpios) { } -static inline void mctrl_gpio_disable_ms(struct mctrl_gpios *gpios) +static inline void mctrl_gpio_disable_ms_sync(struct mctrl_gpios *gpios) +{ +} + +static inline void mctrl_gpio_disable_ms_no_sync(struct mctrl_gpios *gpios) { }
diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index b72c3bc..7e7813c 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c
@@ -104,6 +104,20 @@ struct plat_sci_reg { u8 offset, size; }; +struct sci_suspend_regs { + u16 scdl; + u16 sccks; + u16 scsmr; + u16 scscr; + u16 scfcr; + u16 scsptr; + u16 hssrr; + u16 scpcr; + u16 scpdr; + u8 scbrr; + u8 semr; +}; + struct sci_port_params { const struct plat_sci_reg regs[SCIx_NR_REGS]; unsigned int fifosize; @@ -134,6 +148,8 @@ struct sci_port { struct dma_chan *chan_tx; struct dma_chan *chan_rx; + struct reset_control *rstc; + #ifdef CONFIG_SERIAL_SH_SCI_DMA struct dma_chan *chan_tx_saved; struct dma_chan *chan_rx_saved; @@ -153,6 +169,7 @@ struct sci_port { int rx_trigger; struct timer_list rx_fifo_timer; int rx_fifo_timeout; + struct sci_suspend_regs suspend_regs; u16 hscif_tot; bool has_rtscts; @@ -2297,7 +2314,7 @@ static void sci_shutdown(struct uart_port *port) dev_dbg(port->dev, "%s(%d)\n", __func__, port->line); s->autorts = false; - mctrl_gpio_disable_ms(to_sci_port(port)->gpios); + mctrl_gpio_disable_ms_sync(to_sci_port(port)->gpios); uart_port_lock_irqsave(port, &flags); sci_stop_rx(port); @@ -2320,7 +2337,7 @@ static void sci_shutdown(struct uart_port *port) #endif if (s->rx_trigger > 1 && s->rx_fifo_timeout > 0) - del_timer_sync(&s->rx_fifo_timer); + timer_delete_sync(&s->rx_fifo_timer); sci_free_irq(s); sci_free_dma(port); } @@ -3373,6 +3390,7 @@ static struct plat_sci_port *sci_parse_dt(struct platform_device *pdev, } sp = &sci_ports[id]; + sp->rstc = rstc; *dev_id = id; p->type = SCI_OF_TYPE(data); @@ -3545,13 +3563,77 @@ static int sci_probe(struct platform_device *dev) return 0; } +static void sci_console_save(struct sci_port *s) +{ + struct sci_suspend_regs *regs = &s->suspend_regs; + struct uart_port *port = &s->port; + + if (sci_getreg(port, SCDL)->size) + regs->scdl = sci_serial_in(port, SCDL); + if (sci_getreg(port, SCCKS)->size) + regs->sccks = sci_serial_in(port, SCCKS); + if (sci_getreg(port, SCSMR)->size) + regs->scsmr = sci_serial_in(port, SCSMR); + if (sci_getreg(port, SCSCR)->size) + regs->scscr = sci_serial_in(port, SCSCR); + if (sci_getreg(port, SCFCR)->size) + regs->scfcr = sci_serial_in(port, SCFCR); + if (sci_getreg(port, SCSPTR)->size) + regs->scsptr = sci_serial_in(port, SCSPTR); + if (sci_getreg(port, SCBRR)->size) + regs->scbrr = sci_serial_in(port, SCBRR); + if (sci_getreg(port, HSSRR)->size) + regs->hssrr = sci_serial_in(port, HSSRR); + if (sci_getreg(port, SCPCR)->size) + regs->scpcr = sci_serial_in(port, SCPCR); + if (sci_getreg(port, SCPDR)->size) + regs->scpdr = sci_serial_in(port, SCPDR); + if (sci_getreg(port, SEMR)->size) + regs->semr = sci_serial_in(port, SEMR); +} + +static void sci_console_restore(struct sci_port *s) +{ + struct sci_suspend_regs *regs = &s->suspend_regs; + struct uart_port *port = &s->port; + + if (sci_getreg(port, SCDL)->size) + sci_serial_out(port, SCDL, regs->scdl); + if (sci_getreg(port, SCCKS)->size) + sci_serial_out(port, SCCKS, regs->sccks); + if (sci_getreg(port, SCSMR)->size) + sci_serial_out(port, SCSMR, regs->scsmr); + if (sci_getreg(port, SCSCR)->size) + sci_serial_out(port, SCSCR, regs->scscr); + if (sci_getreg(port, SCFCR)->size) + sci_serial_out(port, SCFCR, regs->scfcr); + if (sci_getreg(port, SCSPTR)->size) + sci_serial_out(port, SCSPTR, regs->scsptr); + if (sci_getreg(port, SCBRR)->size) + sci_serial_out(port, SCBRR, regs->scbrr); + if (sci_getreg(port, HSSRR)->size) + sci_serial_out(port, HSSRR, regs->hssrr); + if (sci_getreg(port, SCPCR)->size) + sci_serial_out(port, SCPCR, regs->scpcr); + if (sci_getreg(port, SCPDR)->size) + sci_serial_out(port, SCPDR, regs->scpdr); + if (sci_getreg(port, SEMR)->size) + sci_serial_out(port, SEMR, regs->semr); +} + static __maybe_unused int sci_suspend(struct device *dev) { struct sci_port *sport = dev_get_drvdata(dev); - if (sport) + if (sport) { uart_suspend_port(&sci_uart_driver, &sport->port); + if (!console_suspend_enabled && uart_console(&sport->port)) + sci_console_save(sport); + else + return reset_control_assert(sport->rstc); + } + return 0; } @@ -3559,8 +3641,18 @@ static __maybe_unused int sci_resume(struct device *dev) { struct sci_port *sport = dev_get_drvdata(dev); - if (sport) + if (sport) { + if (!console_suspend_enabled && uart_console(&sport->port)) { + sci_console_restore(sport); + } else { + int ret = reset_control_deassert(sport->rstc); + + if (ret) + return ret; + } + uart_resume_port(&sci_uart_driver, &sport->port); + } return 0; }
diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c index 1ec5d8c..ad06b76 100644 --- a/drivers/tty/serial/stm32-usart.c +++ b/drivers/tty/serial/stm32-usart.c
@@ -944,7 +944,7 @@ static void stm32_usart_enable_ms(struct uart_port *port) static void stm32_usart_disable_ms(struct uart_port *port) { - mctrl_gpio_disable_ms(to_stm32_port(port)->gpios); + mctrl_gpio_disable_ms_sync(to_stm32_port(port)->gpios); } /* Transmit stop */ @@ -965,10 +965,8 @@ static void stm32_usart_start_tx(struct uart_port *port) { struct tty_port *tport = &port->state->port; - if (kfifo_is_empty(&tport->xmit_fifo) && !port->x_char) { - stm32_usart_rs485_rts_disable(port); + if (kfifo_is_empty(&tport->xmit_fifo) && !port->x_char) return; - } stm32_usart_rs485_rts_enable(port);
diff --git a/drivers/tty/serial/sunsu.c b/drivers/tty/serial/sunsu.c index 7f0fef0..383141f 100644 --- a/drivers/tty/serial/sunsu.c +++ b/drivers/tty/serial/sunsu.c
@@ -151,16 +151,6 @@ static void serial_out(struct uart_sunsu_port *up, int offset, int value) } /* - * We used to support using pause I/O for certain machines. We - * haven't supported this for a while, but just in case it's badly - * needed for certain old 386 machines, I've left these #define's - * in.... - */ -#define serial_inp(up, offset) serial_in(up, offset) -#define serial_outp(up, offset, value) serial_out(up, offset, value) - - -/* * For the 16C950 */ static void serial_icr_write(struct uart_sunsu_port *up, int offset, int value) @@ -169,20 +159,6 @@ static void serial_icr_write(struct uart_sunsu_port *up, int offset, int value) serial_out(up, UART_ICR, value); } -#if 0 /* Unused currently */ -static unsigned int serial_icr_read(struct uart_sunsu_port *up, int offset) -{ - unsigned int value; - - serial_icr_write(up, UART_ACR, up->acr | UART_ACR_ICRRD); - serial_out(up, UART_SCR, offset); - value = serial_in(up, UART_ICR); - serial_icr_write(up, UART_ACR, up->acr); - - return value; -} -#endif - #ifdef CONFIG_SERIAL_8250_RSA /* * Attempts to turn on the RSA FIFO. Returns zero on failure. @@ -193,12 +169,12 @@ static int __enable_rsa(struct uart_sunsu_port *up) unsigned char mode; int result; - mode = serial_inp(up, UART_RSA_MSR); + mode = serial_in(up, UART_RSA_MSR); result = mode & UART_RSA_MSR_FIFO; if (!result) { - serial_outp(up, UART_RSA_MSR, mode | UART_RSA_MSR_FIFO); - mode = serial_inp(up, UART_RSA_MSR); + serial_out(up, UART_RSA_MSR, mode | UART_RSA_MSR_FIFO); + mode = serial_in(up, UART_RSA_MSR); result = mode & UART_RSA_MSR_FIFO; } @@ -217,7 +193,7 @@ static void enable_rsa(struct uart_sunsu_port *up) uart_port_unlock_irq(&up->port); } if (up->port.uartclk == SERIAL_RSA_BAUD_BASE * 16) - serial_outp(up, UART_RSA_FRR, 0); + serial_out(up, UART_RSA_FRR, 0); } } @@ -236,12 +212,12 @@ static void disable_rsa(struct uart_sunsu_port *up) up->port.uartclk == SERIAL_RSA_BAUD_BASE * 16) { uart_port_lock_irq(&up->port); - mode = serial_inp(up, UART_RSA_MSR); + mode = serial_in(up, UART_RSA_MSR); result = !(mode & UART_RSA_MSR_FIFO); if (!result) { - serial_outp(up, UART_RSA_MSR, mode & ~UART_RSA_MSR_FIFO); - mode = serial_inp(up, UART_RSA_MSR); + serial_out(up, UART_RSA_MSR, mode & ~UART_RSA_MSR_FIFO); + mode = serial_in(up, UART_RSA_MSR); result = !(mode & UART_RSA_MSR_FIFO); } @@ -326,7 +302,7 @@ receive_chars(struct uart_sunsu_port *up, unsigned char *status) int saw_console_brk = 0; do { - ch = serial_inp(up, UART_RX); + ch = serial_in(up, UART_RX); flag = TTY_NORMAL; up->port.icount.rx++; @@ -387,7 +363,7 @@ receive_chars(struct uart_sunsu_port *up, unsigned char *status) */ tty_insert_flip_char(port, 0, TTY_OVERRUN); ignore_char: - *status = serial_inp(up, UART_LSR); + *status = serial_in(up, UART_LSR); } while ((*status & UART_LSR_DR) && (max_count-- > 0)); if (saw_console_brk) @@ -401,7 +377,7 @@ static void transmit_chars(struct uart_sunsu_port *up) int count; if (up->port.x_char) { - serial_outp(up, UART_TX, up->port.x_char); + serial_out(up, UART_TX, up->port.x_char); up->port.icount.tx++; up->port.x_char = 0; return; @@ -460,7 +436,7 @@ static irqreturn_t sunsu_serial_interrupt(int irq, void *dev_id) uart_port_lock_irqsave(&up->port, &flags); do { - status = serial_inp(up, UART_LSR); + status = serial_in(up, UART_LSR); if (status & UART_LSR_DR) receive_chars(up, &status); check_modem_status(up); @@ -498,7 +474,7 @@ static void sunsu_change_mouse_baud(struct uart_sunsu_port *up) static void receive_kbd_ms_chars(struct uart_sunsu_port *up, int is_break) { do { - unsigned char ch = serial_inp(up, UART_RX); + unsigned char ch = serial_in(up, UART_RX); /* Stop-A is handled by drivers/char/keyboard.c now. */ if (up->su_type == SU_PORT_KBD) { @@ -530,7 +506,7 @@ static irqreturn_t sunsu_kbd_ms_interrupt(int irq, void *dev_id) struct uart_sunsu_port *up = dev_id; if (!(serial_in(up, UART_IIR) & UART_IIR_NO_INT)) { - unsigned char status = serial_inp(up, UART_LSR); + unsigned char status = serial_in(up, UART_LSR); if ((status & UART_LSR_DR) || (status & UART_LSR_BI)) receive_kbd_ms_chars(up, (status & UART_LSR_BI) != 0); @@ -619,14 +595,14 @@ static int sunsu_startup(struct uart_port *port) if (up->port.type == PORT_16C950) { /* Wake up and initialize UART */ up->acr = 0; - serial_outp(up, UART_LCR, 0xBF); - serial_outp(up, UART_EFR, UART_EFR_ECB); - serial_outp(up, UART_IER, 0); - serial_outp(up, UART_LCR, 0); + serial_out(up, UART_LCR, 0xBF); + serial_out(up, UART_EFR, UART_EFR_ECB); + serial_out(up, UART_IER, 0); + serial_out(up, UART_LCR, 0); serial_icr_write(up, UART_CSR, 0); /* Reset the UART */ - serial_outp(up, UART_LCR, 0xBF); - serial_outp(up, UART_EFR, UART_EFR_ECB); - serial_outp(up, UART_LCR, 0); + serial_out(up, UART_LCR, 0xBF); + serial_out(up, UART_EFR, UART_EFR_ECB); + serial_out(up, UART_LCR, 0); } #ifdef CONFIG_SERIAL_8250_RSA @@ -642,19 +618,19 @@ static int sunsu_startup(struct uart_port *port) * (they will be reenabled in set_termios()) */ if (uart_config[up->port.type].flags & UART_CLEAR_FIFO) { - serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO); - serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO | + serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO); + serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT); - serial_outp(up, UART_FCR, 0); + serial_out(up, UART_FCR, 0); } /* * Clear the interrupt registers. */ - (void) serial_inp(up, UART_LSR); - (void) serial_inp(up, UART_RX); - (void) serial_inp(up, UART_IIR); - (void) serial_inp(up, UART_MSR); + (void) serial_in(up, UART_LSR); + (void) serial_in(up, UART_RX); + (void) serial_in(up, UART_IIR); + (void) serial_in(up, UART_MSR); /* * At this point, there's no way the LSR could still be 0xff; @@ -662,7 +638,7 @@ static int sunsu_startup(struct uart_port *port) * here. */ if (!(up->port.flags & UPF_BUGGY_UART) && - (serial_inp(up, UART_LSR) == 0xff)) { + (serial_in(up, UART_LSR) == 0xff)) { printk("ttyS%d: LSR safety check engaged!\n", up->port.line); return -ENODEV; } @@ -682,7 +658,7 @@ static int sunsu_startup(struct uart_port *port) /* * Now, initialize the UART */ - serial_outp(up, UART_LCR, UART_LCR_WLEN8); + serial_out(up, UART_LCR, UART_LCR_WLEN8); uart_port_lock_irqsave(&up->port, &flags); @@ -697,7 +673,7 @@ static int sunsu_startup(struct uart_port *port) * anyway, so we don't enable them here. */ up->ier = UART_IER_RLSI | UART_IER_RDI; - serial_outp(up, UART_IER, up->ier); + serial_out(up, UART_IER, up->ier); if (up->port.flags & UPF_FOURPORT) { unsigned int icp; @@ -712,10 +688,10 @@ static int sunsu_startup(struct uart_port *port) /* * And clear the interrupt registers again for luck. */ - (void) serial_inp(up, UART_LSR); - (void) serial_inp(up, UART_RX); - (void) serial_inp(up, UART_IIR); - (void) serial_inp(up, UART_MSR); + (void) serial_in(up, UART_LSR); + (void) serial_in(up, UART_RX); + (void) serial_in(up, UART_IIR); + (void) serial_in(up, UART_MSR); return 0; } @@ -730,7 +706,7 @@ static void sunsu_shutdown(struct uart_port *port) * Disable interrupts from this port */ up->ier = 0; - serial_outp(up, UART_IER, 0); + serial_out(up, UART_IER, 0); uart_port_lock_irqsave(&up->port, &flags); if (up->port.flags & UPF_FOURPORT) { @@ -746,11 +722,11 @@ static void sunsu_shutdown(struct uart_port *port) /* * Disable break condition and FIFOs */ - serial_out(up, UART_LCR, serial_inp(up, UART_LCR) & ~UART_LCR_SBC); - serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO | + serial_out(up, UART_LCR, serial_in(up, UART_LCR) & ~UART_LCR_SBC); + serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT); - serial_outp(up, UART_FCR, 0); + serial_out(up, UART_FCR, 0); #ifdef CONFIG_SERIAL_8250_RSA /* @@ -872,22 +848,22 @@ sunsu_change_speed(struct uart_port *port, unsigned int cflag, serial_out(up, UART_IER, up->ier); if (uart_config[up->port.type].flags & UART_STARTECH) { - serial_outp(up, UART_LCR, 0xBF); - serial_outp(up, UART_EFR, cflag & CRTSCTS ? UART_EFR_CTS :0); + serial_out(up, UART_LCR, 0xBF); + serial_out(up, UART_EFR, cflag & CRTSCTS ? UART_EFR_CTS :0); } - serial_outp(up, UART_LCR, cval | UART_LCR_DLAB);/* set DLAB */ - serial_outp(up, UART_DLL, quot & 0xff); /* LS of divisor */ - serial_outp(up, UART_DLM, quot >> 8); /* MS of divisor */ + serial_out(up, UART_LCR, cval | UART_LCR_DLAB);/* set DLAB */ + serial_out(up, UART_DLL, quot & 0xff); /* LS of divisor */ + serial_out(up, UART_DLM, quot >> 8); /* MS of divisor */ if (up->port.type == PORT_16750) - serial_outp(up, UART_FCR, fcr); /* set fcr */ - serial_outp(up, UART_LCR, cval); /* reset DLAB */ + serial_out(up, UART_FCR, fcr); /* set fcr */ + serial_out(up, UART_LCR, cval); /* reset DLAB */ up->lcr = cval; /* Save LCR */ if (up->port.type != PORT_16750) { if (fcr & UART_FCR_ENABLE_FIFO) { /* emulated UARTs (Lucent Venus 167x) need two steps */ - serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO); + serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO); } - serial_outp(up, UART_FCR, fcr); /* set fcr */ + serial_out(up, UART_FCR, fcr); /* set fcr */ } up->cflag = cflag; @@ -1051,18 +1027,18 @@ static void sunsu_autoconfig(struct uart_sunsu_port *up) * 0x80 is a non-existent port; which should be safe since * include/asm/io.h also makes this assumption. */ - scratch = serial_inp(up, UART_IER); - serial_outp(up, UART_IER, 0); + scratch = serial_in(up, UART_IER); + serial_out(up, UART_IER, 0); #ifdef __i386__ outb(0xff, 0x080); #endif - scratch2 = serial_inp(up, UART_IER); - serial_outp(up, UART_IER, 0x0f); + scratch2 = serial_in(up, UART_IER); + serial_out(up, UART_IER, 0x0f); #ifdef __i386__ outb(0, 0x080); #endif - scratch3 = serial_inp(up, UART_IER); - serial_outp(up, UART_IER, scratch); + scratch3 = serial_in(up, UART_IER); + serial_out(up, UART_IER, scratch); if (scratch2 != 0 || scratch3 != 0x0F) goto out; /* We failed; there's nothing here */ } @@ -1080,16 +1056,16 @@ static void sunsu_autoconfig(struct uart_sunsu_port *up) * that conflicts with COM 1-4 --- we hope! */ if (!(up->port.flags & UPF_SKIP_TEST)) { - serial_outp(up, UART_MCR, UART_MCR_LOOP | 0x0A); - status1 = serial_inp(up, UART_MSR) & 0xF0; - serial_outp(up, UART_MCR, save_mcr); + serial_out(up, UART_MCR, UART_MCR_LOOP | 0x0A); + status1 = serial_in(up, UART_MSR) & 0xF0; + serial_out(up, UART_MCR, save_mcr); if (status1 != 0x90) goto out; /* We failed loopback test */ } - serial_outp(up, UART_LCR, 0xBF); /* set up for StarTech test */ - serial_outp(up, UART_EFR, 0); /* EFR is the same as FCR */ - serial_outp(up, UART_LCR, 0); - serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO); + serial_out(up, UART_LCR, 0xBF); /* set up for StarTech test */ + serial_out(up, UART_EFR, 0); /* EFR is the same as FCR */ + serial_out(up, UART_LCR, 0); + serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO); scratch = serial_in(up, UART_IIR) >> 6; switch (scratch) { case 0: @@ -1107,19 +1083,19 @@ static void sunsu_autoconfig(struct uart_sunsu_port *up) } if (up->port.type == PORT_16550A) { /* Check for Startech UART's */ - serial_outp(up, UART_LCR, UART_LCR_DLAB); + serial_out(up, UART_LCR, UART_LCR_DLAB); if (serial_in(up, UART_EFR) == 0) { up->port.type = PORT_16650; } else { - serial_outp(up, UART_LCR, 0xBF); + serial_out(up, UART_LCR, 0xBF); if (serial_in(up, UART_EFR) == 0) up->port.type = PORT_16650V2; } } if (up->port.type == PORT_16550A) { /* Check for TI 16750 */ - serial_outp(up, UART_LCR, save_lcr | UART_LCR_DLAB); - serial_outp(up, UART_FCR, + serial_out(up, UART_LCR, save_lcr | UART_LCR_DLAB); + serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE); scratch = serial_in(up, UART_IIR) >> 5; if (scratch == 7) { @@ -1129,24 +1105,24 @@ static void sunsu_autoconfig(struct uart_sunsu_port *up) * mode if the UART_FCR7_64BYTE bit was set * while UART_LCR_DLAB was latched. */ - serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO); - serial_outp(up, UART_LCR, 0); - serial_outp(up, UART_FCR, + serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO); + serial_out(up, UART_LCR, 0); + serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE); scratch = serial_in(up, UART_IIR) >> 5; if (scratch == 6) up->port.type = PORT_16750; } - serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO); + serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO); } - serial_outp(up, UART_LCR, save_lcr); + serial_out(up, UART_LCR, save_lcr); if (up->port.type == PORT_16450) { scratch = serial_in(up, UART_SCR); - serial_outp(up, UART_SCR, 0xa5); + serial_out(up, UART_SCR, 0xa5); status1 = serial_in(up, UART_SCR); - serial_outp(up, UART_SCR, 0x5a); + serial_out(up, UART_SCR, 0x5a); status2 = serial_in(up, UART_SCR); - serial_outp(up, UART_SCR, scratch); + serial_out(up, UART_SCR, scratch); if ((status1 != 0xa5) || (status2 != 0x5a)) up->port.type = PORT_8250; @@ -1163,15 +1139,15 @@ static void sunsu_autoconfig(struct uart_sunsu_port *up) */ #ifdef CONFIG_SERIAL_8250_RSA if (up->port.type == PORT_RSA) - serial_outp(up, UART_RSA_FRR, 0); + serial_out(up, UART_RSA_FRR, 0); #endif - serial_outp(up, UART_MCR, save_mcr); - serial_outp(up, UART_FCR, (UART_FCR_ENABLE_FIFO | + serial_out(up, UART_MCR, save_mcr); + serial_out(up, UART_FCR, (UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT)); - serial_outp(up, UART_FCR, 0); + serial_out(up, UART_FCR, 0); (void)serial_in(up, UART_RX); - serial_outp(up, UART_IER, 0); + serial_out(up, UART_IER, 0); out: uart_port_unlock_irqrestore(&up->port, flags);
diff --git a/drivers/tty/serial/tegra-utc.c b/drivers/tty/serial/tegra-utc.c new file mode 100644 index 0000000..39b14fe --- /dev/null +++ b/drivers/tty/serial/tegra-utc.c
@@ -0,0 +1,625 @@ +// SPDX-License-Identifier: GPL-2.0-only +// SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// NVIDIA Tegra UTC (UART Trace Controller) driver. + +#include <linux/bits.h> +#include <linux/console.h> +#include <linux/container_of.h> +#include <linux/device.h> +#include <linux/err.h> +#include <linux/iopoll.h> +#include <linux/kfifo.h> +#include <linux/module.h> +#include <linux/mod_devicetable.h> +#include <linux/property.h> +#include <linux/platform_device.h> +#include <linux/serial.h> +#include <linux/serial_core.h> +#include <linux/slab.h> +#include <linux/tty.h> +#include <linux/tty_flip.h> +#include <linux/types.h> + +#define TEGRA_UTC_ENABLE 0x000 +#define TEGRA_UTC_ENABLE_CLIENT_ENABLE BIT(0) + +#define TEGRA_UTC_FIFO_THRESHOLD 0x008 + +#define TEGRA_UTC_COMMAND 0x00c +#define TEGRA_UTC_COMMAND_RESET BIT(0) +#define TEGRA_UTC_COMMAND_FLUSH BIT(1) + +#define TEGRA_UTC_DATA 0x020 + +#define TEGRA_UTC_FIFO_STATUS 0x100 +#define TEGRA_UTC_FIFO_EMPTY BIT(0) +#define TEGRA_UTC_FIFO_FULL BIT(1) +#define TEGRA_UTC_FIFO_REQ BIT(2) +#define TEGRA_UTC_FIFO_OVERFLOW BIT(3) +#define TEGRA_UTC_FIFO_TIMEOUT BIT(4) + +#define TEGRA_UTC_FIFO_OCCUPANCY 0x104 + +#define TEGRA_UTC_INTR_STATUS 0x108 +#define TEGRA_UTC_INTR_SET 0x10c +#define TEGRA_UTC_INTR_MASK 0x110 +#define TEGRA_UTC_INTR_CLEAR 0x114 +#define TEGRA_UTC_INTR_EMPTY BIT(0) +#define TEGRA_UTC_INTR_FULL BIT(1) +#define TEGRA_UTC_INTR_REQ BIT(2) +#define TEGRA_UTC_INTR_OVERFLOW BIT(3) +#define TEGRA_UTC_INTR_TIMEOUT BIT(4) + +#define TEGRA_UTC_UART_NR 16 + +#define TEGRA_UTC_INTR_COMMON (TEGRA_UTC_INTR_REQ | TEGRA_UTC_INTR_FULL | TEGRA_UTC_INTR_EMPTY) + +struct tegra_utc_port { +#if IS_ENABLED(CONFIG_SERIAL_TEGRA_UTC_CONSOLE) + struct console console; +#endif + struct uart_port port; + + void __iomem *rx_base; + void __iomem *tx_base; + + u32 tx_irqmask; + u32 rx_irqmask; + + unsigned int fifosize; + u32 tx_threshold; + u32 rx_threshold; +}; + +static u32 tegra_utc_rx_readl(struct tegra_utc_port *tup, unsigned int offset) +{ + void __iomem *addr = tup->rx_base + offset; + + return readl_relaxed(addr); +} + +static void tegra_utc_rx_writel(struct tegra_utc_port *tup, u32 val, unsigned int offset) +{ + void __iomem *addr = tup->rx_base + offset; + + writel_relaxed(val, addr); +} + +static u32 tegra_utc_tx_readl(struct tegra_utc_port *tup, unsigned int offset) +{ + void __iomem *addr = tup->tx_base + offset; + + return readl_relaxed(addr); +} + +static void tegra_utc_tx_writel(struct tegra_utc_port *tup, u32 val, unsigned int offset) +{ + void __iomem *addr = tup->tx_base + offset; + + writel_relaxed(val, addr); +} + +static void tegra_utc_enable_tx_irq(struct tegra_utc_port *tup) +{ + tup->tx_irqmask = TEGRA_UTC_INTR_REQ; + + tegra_utc_tx_writel(tup, tup->tx_irqmask, TEGRA_UTC_INTR_MASK); + tegra_utc_tx_writel(tup, tup->tx_irqmask, TEGRA_UTC_INTR_SET); +} + +static void tegra_utc_disable_tx_irq(struct tegra_utc_port *tup) +{ + tup->tx_irqmask = 0x0; + + tegra_utc_tx_writel(tup, tup->tx_irqmask, TEGRA_UTC_INTR_MASK); + tegra_utc_tx_writel(tup, tup->tx_irqmask, TEGRA_UTC_INTR_SET); +} + +static void tegra_utc_stop_tx(struct uart_port *port) +{ + struct tegra_utc_port *tup = container_of(port, struct tegra_utc_port, port); + + tegra_utc_disable_tx_irq(tup); +} + +static void tegra_utc_init_tx(struct tegra_utc_port *tup) +{ + /* Disable TX. */ + tegra_utc_tx_writel(tup, 0x0, TEGRA_UTC_ENABLE); + + /* Update the FIFO Threshold. */ + tegra_utc_tx_writel(tup, tup->tx_threshold, TEGRA_UTC_FIFO_THRESHOLD); + + /* Clear and mask all the interrupts. */ + tegra_utc_tx_writel(tup, TEGRA_UTC_INTR_COMMON, TEGRA_UTC_INTR_CLEAR); + tegra_utc_disable_tx_irq(tup); + + /* Enable TX. */ + tegra_utc_tx_writel(tup, TEGRA_UTC_ENABLE_CLIENT_ENABLE, TEGRA_UTC_ENABLE); +} + +static void tegra_utc_init_rx(struct tegra_utc_port *tup) +{ + tup->rx_irqmask = TEGRA_UTC_INTR_REQ | TEGRA_UTC_INTR_TIMEOUT; + + tegra_utc_rx_writel(tup, TEGRA_UTC_COMMAND_RESET, TEGRA_UTC_COMMAND); + tegra_utc_rx_writel(tup, tup->rx_threshold, TEGRA_UTC_FIFO_THRESHOLD); + + /* Clear all the pending interrupts. */ + tegra_utc_rx_writel(tup, TEGRA_UTC_INTR_TIMEOUT | TEGRA_UTC_INTR_OVERFLOW | + TEGRA_UTC_INTR_COMMON, TEGRA_UTC_INTR_CLEAR); + tegra_utc_rx_writel(tup, tup->rx_irqmask, TEGRA_UTC_INTR_MASK); + tegra_utc_rx_writel(tup, tup->rx_irqmask, TEGRA_UTC_INTR_SET); + + /* Enable RX. */ + tegra_utc_rx_writel(tup, TEGRA_UTC_ENABLE_CLIENT_ENABLE, TEGRA_UTC_ENABLE); +} + +static bool tegra_utc_tx_chars(struct tegra_utc_port *tup) +{ + struct uart_port *port = &tup->port; + unsigned int pending; + u8 c; + + pending = uart_port_tx(port, c, + !(tegra_utc_tx_readl(tup, TEGRA_UTC_FIFO_STATUS) & TEGRA_UTC_FIFO_FULL), + tegra_utc_tx_writel(tup, c, TEGRA_UTC_DATA)); + + return pending; +} + +static void tegra_utc_rx_chars(struct tegra_utc_port *tup) +{ + struct tty_port *port = &tup->port.state->port; + unsigned int max_chars = 256; + u32 status; + int sysrq; + u32 ch; + + while (max_chars--) { + status = tegra_utc_rx_readl(tup, TEGRA_UTC_FIFO_STATUS); + if (status & TEGRA_UTC_FIFO_EMPTY) + break; + + ch = tegra_utc_rx_readl(tup, TEGRA_UTC_DATA); + tup->port.icount.rx++; + + if (status & TEGRA_UTC_FIFO_OVERFLOW) + tup->port.icount.overrun++; + + uart_port_unlock(&tup->port); + sysrq = uart_handle_sysrq_char(&tup->port, ch); + uart_port_lock(&tup->port); + + if (!sysrq) + tty_insert_flip_char(port, ch, TTY_NORMAL); + } + + tty_flip_buffer_push(port); +} + +static irqreturn_t tegra_utc_isr(int irq, void *dev_id) +{ + struct tegra_utc_port *tup = dev_id; + unsigned int handled = 0; + u32 status; + + uart_port_lock(&tup->port); + + /* Process RX_REQ and RX_TIMEOUT interrupts. */ + do { + status = tegra_utc_rx_readl(tup, TEGRA_UTC_INTR_STATUS) & tup->rx_irqmask; + if (status) { + tegra_utc_rx_writel(tup, tup->rx_irqmask, TEGRA_UTC_INTR_CLEAR); + tegra_utc_rx_chars(tup); + handled = 1; + } + } while (status); + + /* Process TX_REQ interrupt. */ + do { + status = tegra_utc_tx_readl(tup, TEGRA_UTC_INTR_STATUS) & tup->tx_irqmask; + if (status) { + tegra_utc_tx_writel(tup, tup->tx_irqmask, TEGRA_UTC_INTR_CLEAR); + tegra_utc_tx_chars(tup); + handled = 1; + } + } while (status); + + uart_port_unlock(&tup->port); + + return IRQ_RETVAL(handled); +} + +static unsigned int tegra_utc_tx_empty(struct uart_port *port) +{ + struct tegra_utc_port *tup = container_of(port, struct tegra_utc_port, port); + + return tegra_utc_tx_readl(tup, TEGRA_UTC_FIFO_OCCUPANCY) ? 0 : TIOCSER_TEMT; +} + +static void tegra_utc_set_mctrl(struct uart_port *port, unsigned int mctrl) +{ +} + +static unsigned int tegra_utc_get_mctrl(struct uart_port *port) +{ + return 0; +} + +static void tegra_utc_start_tx(struct uart_port *port) +{ + struct tegra_utc_port *tup = container_of(port, struct tegra_utc_port, port); + + if (tegra_utc_tx_chars(tup)) + tegra_utc_enable_tx_irq(tup); +} + +static void tegra_utc_stop_rx(struct uart_port *port) +{ + struct tegra_utc_port *tup = container_of(port, struct tegra_utc_port, port); + + tup->rx_irqmask = 0x0; + tegra_utc_rx_writel(tup, tup->rx_irqmask, TEGRA_UTC_INTR_MASK); + tegra_utc_rx_writel(tup, tup->rx_irqmask, TEGRA_UTC_INTR_SET); +} + +static void tegra_utc_hw_init(struct tegra_utc_port *tup) +{ + tegra_utc_init_tx(tup); + tegra_utc_init_rx(tup); +} + +static int tegra_utc_startup(struct uart_port *port) +{ + struct tegra_utc_port *tup = container_of(port, struct tegra_utc_port, port); + int ret; + + tegra_utc_hw_init(tup); + + /* Interrupt is dedicated to this UTC client. */ + ret = request_irq(port->irq, tegra_utc_isr, 0, dev_name(port->dev), tup); + if (ret < 0) + dev_err(port->dev, "failed to register interrupt handler\n"); + + return ret; +} + +static void tegra_utc_shutdown(struct uart_port *port) +{ + struct tegra_utc_port *tup = container_of(port, struct tegra_utc_port, port); + + tegra_utc_rx_writel(tup, 0x0, TEGRA_UTC_ENABLE); + free_irq(port->irq, tup); +} + +static void tegra_utc_set_termios(struct uart_port *port, struct ktermios *termios, + const struct ktermios *old) +{ + /* The Tegra UTC clients supports only 8-N-1 configuration without HW flow control */ + termios->c_cflag &= ~(CSIZE | CSTOPB | PARENB | PARODD); + termios->c_cflag &= ~(CMSPAR | CRTSCTS); + termios->c_cflag |= CS8 | CLOCAL; +} + +#ifdef CONFIG_CONSOLE_POLL + +static int tegra_utc_poll_init(struct uart_port *port) +{ + struct tegra_utc_port *tup = container_of(port, struct tegra_utc_port, port); + + tegra_utc_hw_init(tup); + return 0; +} + +static int tegra_utc_get_poll_char(struct uart_port *port) +{ + struct tegra_utc_port *tup = container_of(port, struct tegra_utc_port, port); + + if (tegra_utc_rx_readl(tup, TEGRA_UTC_FIFO_STATUS) & TEGRA_UTC_FIFO_EMPTY) + return NO_POLL_CHAR; + + return tegra_utc_rx_readl(tup, TEGRA_UTC_DATA); +} + +static void tegra_utc_put_poll_char(struct uart_port *port, unsigned char ch) +{ + struct tegra_utc_port *tup = container_of(port, struct tegra_utc_port, port); + u32 val; + + read_poll_timeout_atomic(tegra_utc_tx_readl, val, !(val & TEGRA_UTC_FIFO_FULL), + 0, USEC_PER_SEC, false, tup, TEGRA_UTC_FIFO_STATUS); + + tegra_utc_tx_writel(tup, ch, TEGRA_UTC_DATA); +} + +#endif + +static const struct uart_ops tegra_utc_uart_ops = { + .tx_empty = tegra_utc_tx_empty, + .set_mctrl = tegra_utc_set_mctrl, + .get_mctrl = tegra_utc_get_mctrl, + .stop_tx = tegra_utc_stop_tx, + .start_tx = tegra_utc_start_tx, + .stop_rx = tegra_utc_stop_rx, + .startup = tegra_utc_startup, + .shutdown = tegra_utc_shutdown, + .set_termios = tegra_utc_set_termios, +#ifdef CONFIG_CONSOLE_POLL + .poll_init = tegra_utc_poll_init, + .poll_get_char = tegra_utc_get_poll_char, + .poll_put_char = tegra_utc_put_poll_char, +#endif +}; + +#if IS_ENABLED(CONFIG_SERIAL_TEGRA_UTC_CONSOLE) +#define TEGRA_UTC_DEFAULT_FIFO_THRESHOLD 4 +#define TEGRA_UTC_EARLYCON_MAX_BURST_SIZE 128 + +static void tegra_utc_putc(struct uart_port *port, unsigned char c) +{ + writel(c, port->membase + TEGRA_UTC_DATA); +} + +static void tegra_utc_early_write(struct console *con, const char *s, unsigned int n) +{ + struct earlycon_device *dev = con->data; + + while (n) { + u32 burst_size = TEGRA_UTC_EARLYCON_MAX_BURST_SIZE; + + burst_size -= readl(dev->port.membase + TEGRA_UTC_FIFO_OCCUPANCY); + if (n < burst_size) + burst_size = n; + + uart_console_write(&dev->port, s, burst_size, tegra_utc_putc); + + n -= burst_size; + s += burst_size; + } +} + +static int __init tegra_utc_early_console_setup(struct earlycon_device *device, const char *opt) +{ + if (!device->port.membase) + return -ENODEV; + + /* Configure TX */ + writel(TEGRA_UTC_COMMAND_FLUSH | TEGRA_UTC_COMMAND_RESET, + device->port.membase + TEGRA_UTC_COMMAND); + writel(TEGRA_UTC_DEFAULT_FIFO_THRESHOLD, device->port.membase + TEGRA_UTC_FIFO_THRESHOLD); + + /* Clear and mask all the interrupts. */ + writel(TEGRA_UTC_INTR_COMMON, device->port.membase + TEGRA_UTC_INTR_CLEAR); + + writel(0x0, device->port.membase + TEGRA_UTC_INTR_MASK); + writel(0x0, device->port.membase + TEGRA_UTC_INTR_SET); + + /* Enable TX. */ + writel(TEGRA_UTC_ENABLE_CLIENT_ENABLE, device->port.membase + TEGRA_UTC_ENABLE); + + device->con->write = tegra_utc_early_write; + + return 0; +} +OF_EARLYCON_DECLARE(tegra_utc, "nvidia,tegra264-utc", tegra_utc_early_console_setup); + +static void tegra_utc_console_putchar(struct uart_port *port, unsigned char ch) +{ + struct tegra_utc_port *tup = container_of(port, struct tegra_utc_port, port); + + tegra_utc_tx_writel(tup, ch, TEGRA_UTC_DATA); +} + +static void tegra_utc_console_write_atomic(struct console *cons, struct nbcon_write_context *wctxt) +{ + struct tegra_utc_port *tup = container_of(cons, struct tegra_utc_port, console); + unsigned int len; + char *outbuf; + + if (!nbcon_enter_unsafe(wctxt)) + return; + + outbuf = wctxt->outbuf; + len = wctxt->len; + + while (len) { + u32 burst_size = tup->fifosize; + + burst_size -= tegra_utc_tx_readl(tup, TEGRA_UTC_FIFO_OCCUPANCY); + if (len < burst_size) + burst_size = len; + + uart_console_write(&tup->port, outbuf, burst_size, tegra_utc_console_putchar); + + outbuf += burst_size; + len -= burst_size; + }; + + nbcon_exit_unsafe(wctxt); +} + +static void tegra_utc_console_write_thread(struct console *cons, struct nbcon_write_context *wctxt) +{ + struct tegra_utc_port *tup = container_of(cons, struct tegra_utc_port, console); + unsigned int len = READ_ONCE(wctxt->len); + unsigned int i; + u32 val; + + for (i = 0; i < len; i++) { + if (!nbcon_enter_unsafe(wctxt)) + break; + + read_poll_timeout_atomic(tegra_utc_tx_readl, val, !(val & TEGRA_UTC_FIFO_FULL), + 0, USEC_PER_SEC, false, tup, TEGRA_UTC_FIFO_STATUS); + uart_console_write(&tup->port, wctxt->outbuf + i, 1, tegra_utc_console_putchar); + + if (!nbcon_exit_unsafe(wctxt)) + break; + } +} + +static void tegra_utc_console_device_lock(struct console *cons, unsigned long *flags) +{ + struct tegra_utc_port *tup = container_of(cons, struct tegra_utc_port, console); + struct uart_port *port = &tup->port; + + __uart_port_lock_irqsave(port, flags); +} + +static void tegra_utc_console_device_unlock(struct console *cons, unsigned long flags) +{ + struct tegra_utc_port *tup = container_of(cons, struct tegra_utc_port, console); + struct uart_port *port = &tup->port; + + __uart_port_unlock_irqrestore(port, flags); +} + +static int tegra_utc_console_setup(struct console *cons, char *options) +{ + struct tegra_utc_port *tup = container_of(cons, struct tegra_utc_port, console); + + tegra_utc_init_tx(tup); + + return 0; +} +#endif + +static struct uart_driver tegra_utc_driver = { + .driver_name = "tegra-utc", + .dev_name = "ttyUTC", + .nr = TEGRA_UTC_UART_NR, +}; + +static int tegra_utc_setup_port(struct device *dev, struct tegra_utc_port *tup) +{ + tup->port.dev = dev; + tup->port.fifosize = tup->fifosize; + tup->port.flags = UPF_BOOT_AUTOCONF; + tup->port.iotype = UPIO_MEM; + tup->port.ops = &tegra_utc_uart_ops; + tup->port.type = PORT_TEGRA_TCU; + tup->port.private_data = tup; + +#if IS_ENABLED(CONFIG_SERIAL_TEGRA_UTC_CONSOLE) + strscpy(tup->console.name, "ttyUTC", sizeof(tup->console.name)); + tup->console.write_atomic = tegra_utc_console_write_atomic; + tup->console.write_thread = tegra_utc_console_write_thread; + tup->console.device_lock = tegra_utc_console_device_lock; + tup->console.device_unlock = tegra_utc_console_device_unlock; + tup->console.device = uart_console_device; + tup->console.setup = tegra_utc_console_setup; + tup->console.flags = CON_PRINTBUFFER | CON_NBCON; + tup->console.data = &tegra_utc_driver; +#endif + + return uart_read_port_properties(&tup->port); +} + +static int tegra_utc_register_port(struct tegra_utc_port *tup) +{ + int ret; + + ret = uart_add_one_port(&tegra_utc_driver, &tup->port); + if (ret) + return ret; + +#if IS_ENABLED(CONFIG_SERIAL_TEGRA_UTC_CONSOLE) + register_console(&tup->console); +#endif + + return 0; +} + +static int tegra_utc_probe(struct platform_device *pdev) +{ + const unsigned int *soc_fifosize; + struct device *dev = &pdev->dev; + struct tegra_utc_port *tup; + int ret; + + tup = devm_kzalloc(dev, sizeof(*tup), GFP_KERNEL); + if (!tup) + return -ENOMEM; + + ret = device_property_read_u32(dev, "tx-threshold", &tup->tx_threshold); + if (ret) + return dev_err_probe(dev, ret, "missing %s property\n", "tx-threshold"); + + ret = device_property_read_u32(dev, "rx-threshold", &tup->rx_threshold); + if (ret) + return dev_err_probe(dev, ret, "missing %s property\n", "rx-threshold"); + + soc_fifosize = device_get_match_data(dev); + tup->fifosize = *soc_fifosize; + + tup->tx_base = devm_platform_ioremap_resource_byname(pdev, "tx"); + if (IS_ERR(tup->tx_base)) + return PTR_ERR(tup->tx_base); + + tup->rx_base = devm_platform_ioremap_resource_byname(pdev, "rx"); + if (IS_ERR(tup->rx_base)) + return PTR_ERR(tup->rx_base); + + ret = tegra_utc_setup_port(dev, tup); + if (ret) + dev_err_probe(dev, ret, "failed to setup uart port\n"); + + platform_set_drvdata(pdev, tup); + + return tegra_utc_register_port(tup); +} + +static void tegra_utc_remove(struct platform_device *pdev) +{ + struct tegra_utc_port *tup = platform_get_drvdata(pdev); + +#if IS_ENABLED(CONFIG_SERIAL_TEGRA_UTC_CONSOLE) + unregister_console(&tup->console); +#endif + uart_remove_one_port(&tegra_utc_driver, &tup->port); +} + +static const unsigned int tegra264_utc_soc = 128; + +static const struct of_device_id tegra_utc_of_match[] = { + { .compatible = "nvidia,tegra264-utc", .data = &tegra264_utc_soc }, + {} +}; +MODULE_DEVICE_TABLE(of, tegra_utc_of_match); + +static struct platform_driver tegra_utc_platform_driver = { + .probe = tegra_utc_probe, + .remove = tegra_utc_remove, + .driver = { + .name = "tegra-utc", + .of_match_table = tegra_utc_of_match, + }, +}; + +static int __init tegra_utc_init(void) +{ + int ret; + + ret = uart_register_driver(&tegra_utc_driver); + if (ret) + return ret; + + ret = platform_driver_register(&tegra_utc_platform_driver); + if (ret) + uart_unregister_driver(&tegra_utc_driver); + + return ret; +} +module_init(tegra_utc_init); + +static void __exit tegra_utc_exit(void) +{ + platform_driver_unregister(&tegra_utc_platform_driver); + uart_unregister_driver(&tegra_utc_driver); +} +module_exit(tegra_utc_exit); + +MODULE_AUTHOR("Kartik Rajput <kkartik@nvidia.com>"); +MODULE_DESCRIPTION("Tegra UART Trace Controller"); +MODULE_LICENSE("GPL");
diff --git a/drivers/tty/synclink_gt.c b/drivers/tty/synclink_gt.c index bd8d92e..4c703f4 100644 --- a/drivers/tty/synclink_gt.c +++ b/drivers/tty/synclink_gt.c
@@ -2220,7 +2220,7 @@ static void isr_txeom(struct slgt_info *info, unsigned short status) } info->tx_active = false; - del_timer(&info->tx_timer); + timer_delete(&info->tx_timer); if (info->params.mode != MGSL_MODE_ASYNC && info->drop_rts_on_tx_done) { info->signals &= ~SerialSignal_RTS; @@ -2375,8 +2375,8 @@ static void shutdown(struct slgt_info *info) wake_up_interruptible(&info->status_event_wait_q); wake_up_interruptible(&info->event_wait_q); - del_timer_sync(&info->tx_timer); - del_timer_sync(&info->rx_timer); + timer_delete_sync(&info->tx_timer); + timer_delete_sync(&info->rx_timer); kfree(info->tx_buf); info->tx_buf = NULL; @@ -3955,7 +3955,7 @@ static void tx_stop(struct slgt_info *info) { unsigned short val; - del_timer(&info->tx_timer); + timer_delete(&info->tx_timer); tdma_reset(info);
diff --git a/drivers/tty/sysrq.c b/drivers/tty/sysrq.c index f85ce02..6853c46 100644 --- a/drivers/tty/sysrq.c +++ b/drivers/tty/sysrq.c
@@ -743,7 +743,7 @@ static void sysrq_detect_reset_sequence(struct sysrq_state *state, */ if (value && state->reset_seq_cnt) { state->reset_canceled = true; - del_timer(&state->keyreset_timer); + timer_delete(&state->keyreset_timer); } } else if (value == 0) { /* @@ -751,7 +751,7 @@ static void sysrq_detect_reset_sequence(struct sysrq_state *state, * to be pressed and held for the reset timeout * to hold. */ - del_timer(&state->keyreset_timer); + timer_delete(&state->keyreset_timer); if (--state->reset_seq_cnt == 0) state->reset_canceled = false;
diff --git a/drivers/tty/tty_audit.c b/drivers/tty/tty_audit.c index 1d81eeef..7554233 100644 --- a/drivers/tty/tty_audit.c +++ b/drivers/tty/tty_audit.c
@@ -12,12 +12,14 @@ #include <linux/tty.h> #include "tty.h" +#define TTY_AUDIT_BUF_SIZE 4096 + struct tty_audit_buf { struct mutex mutex; /* Protects all data below */ dev_t dev; /* The TTY which the data is from */ bool icanon; size_t valid; - u8 *data; /* Allocated size N_TTY_BUF_SIZE */ + u8 *data; /* Allocated size TTY_AUDIT_BUF_SIZE */ }; static struct tty_audit_buf *tty_audit_buf_ref(void) @@ -37,7 +39,7 @@ static struct tty_audit_buf *tty_audit_buf_alloc(void) if (!buf) goto err; - buf->data = kmalloc(N_TTY_BUF_SIZE, GFP_KERNEL); + buf->data = kmalloc(TTY_AUDIT_BUF_SIZE, GFP_KERNEL); if (!buf->data) goto err_buf; @@ -235,14 +237,14 @@ void tty_audit_add_data(const struct tty_struct *tty, const void *data, do { size_t run; - run = N_TTY_BUF_SIZE - buf->valid; + run = TTY_AUDIT_BUF_SIZE - buf->valid; if (run > size) run = size; memcpy(buf->data + buf->valid, data, run); buf->valid += run; data += run; size -= run; - if (buf->valid == N_TTY_BUF_SIZE) + if (buf->valid == TTY_AUDIT_BUF_SIZE) tty_audit_buf_push(buf); } while (size != 0); mutex_unlock(&buf->mutex);
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 449dbd2..ca9b7d7 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c
@@ -3329,10 +3329,12 @@ EXPORT_SYMBOL(tty_unregister_device); * __tty_alloc_driver - allocate tty driver * @lines: count of lines this driver can handle at most * @owner: module which is responsible for this driver - * @flags: some of %TTY_DRIVER_ flags, will be set in driver->flags + * @flags: some of enum tty_driver_flag, will be set in driver->flags * - * This should not be called directly, some of the provided macros should be - * used instead. Use IS_ERR() and friends on @retval. + * This should not be called directly, tty_alloc_driver() should be used + * instead. + * + * Returns: struct tty_driver or a PTR-encoded error (use IS_ERR() and friends). */ struct tty_driver *__tty_alloc_driver(unsigned int lines, struct module *owner, unsigned long flags)
diff --git a/drivers/tty/tty_ldsem.c b/drivers/tty/tty_ldsem.c index 3be428c..4e18031 100644 --- a/drivers/tty/tty_ldsem.c +++ b/drivers/tty/tty_ldsem.c
@@ -367,23 +367,6 @@ int __sched ldsem_down_write(struct ld_semaphore *sem, long timeout) } /* - * trylock for writing -- returns 1 if successful, 0 if contention - */ -int ldsem_down_write_trylock(struct ld_semaphore *sem) -{ - long count = atomic_long_read(&sem->count); - - while ((count & LDSEM_ACTIVE_MASK) == 0) { - if (atomic_long_try_cmpxchg(&sem->count, &count, count + LDSEM_WRITE_BIAS)) { - rwsem_acquire(&sem->dep_map, 0, 1, _RET_IP_); - lock_acquired(&sem->dep_map, _RET_IP_); - return 1; - } - } - return 0; -} - -/* * release a read lock */ void ldsem_up_read(struct ld_semaphore *sem)
diff --git a/drivers/tty/vcc.c b/drivers/tty/vcc.c index 5b625f2..7ac3048 100644 --- a/drivers/tty/vcc.c +++ b/drivers/tty/vcc.c
@@ -683,8 +683,8 @@ static void vcc_remove(struct vio_dev *vdev) { struct vcc_port *port = dev_get_drvdata(&vdev->dev); - del_timer_sync(&port->rx_timer); - del_timer_sync(&port->tx_timer); + timer_delete_sync(&port->rx_timer); + timer_delete_sync(&port->tx_timer); /* If there's a process with the device open, do a synchronous * hangup of the TTY. This *may* cause the process to call close @@ -700,7 +700,7 @@ static void vcc_remove(struct vio_dev *vdev) tty_unregister_device(vcc_tty_driver, port->index); - del_timer_sync(&port->vio.timer); + timer_delete_sync(&port->vio.timer); vio_ldc_free(&port->vio); sysfs_remove_group(&vdev->dev.kobj, &vcc_attribute_group); dev_set_drvdata(&vdev->dev, NULL);
diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c index 804355d..ae92e6a 100644 --- a/drivers/tty/vt/keyboard.c +++ b/drivers/tty/vt/keyboard.c
@@ -275,7 +275,7 @@ static DEFINE_TIMER(kd_mksound_timer, kd_nosound); void kd_mksound(unsigned int hz, unsigned int ticks) { - del_timer_sync(&kd_mksound_timer); + timer_delete_sync(&kd_mksound_timer); input_handler_for_each_handle(&kbd_handler, &hz, kd_sound_helper);
diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index be5564e..f5642b3 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c
@@ -4501,7 +4501,7 @@ void do_blank_screen(int entering_gfx) } hide_cursor(vc); - del_timer_sync(&console_timer); + timer_delete_sync(&console_timer); blank_timer_expired = 0; save_screen(vc); @@ -4606,7 +4606,7 @@ void poke_blanked_console(void) /* This isn't perfectly race free, but a race here would be mostly harmless, * at worst, we'll do a spurious blank and it's unlikely */ - del_timer(&console_timer); + timer_delete(&console_timer); blank_timer_expired = 0; if (ignore_poke || !vc_cons[fg_console].d || vc_cons[fg_console].d->vc_mode == KD_GRAPHICS)
diff --git a/drivers/usb/atm/cxacru.c b/drivers/usb/atm/cxacru.c index 47d06af..c6b9ad1 100644 --- a/drivers/usb/atm/cxacru.c +++ b/drivers/usb/atm/cxacru.c
@@ -597,7 +597,7 @@ static int cxacru_start_wait_urb(struct urb *urb, struct completion *done, timer_setup_on_stack(&timer.timer, cxacru_timeout_kill, 0); mod_timer(&timer.timer, jiffies + msecs_to_jiffies(CMD_TIMEOUT)); wait_for_completion(done); - del_timer_sync(&timer.timer); + timer_delete_sync(&timer.timer); destroy_timer_on_stack(&timer.timer); if (actual_length)
diff --git a/drivers/usb/atm/speedtch.c b/drivers/usb/atm/speedtch.c index 973548b..27e3d35 100644 --- a/drivers/usb/atm/speedtch.c +++ b/drivers/usb/atm/speedtch.c
@@ -612,7 +612,7 @@ static void speedtch_handle_int(struct urb *int_urb) } if ((count == 6) && !memcmp(up_int, instance->int_data, 6)) { - del_timer(&instance->status_check_timer); + timer_delete(&instance->status_check_timer); atm_info(usbatm, "DSL line goes up\n"); } else if ((count == 6) && !memcmp(down_int, instance->int_data, 6)) { atm_info(usbatm, "DSL line goes down\n"); @@ -688,7 +688,7 @@ static void speedtch_atm_stop(struct usbatm_data *usbatm, struct atm_dev *atm_de atm_dbg(usbatm, "%s entered\n", __func__); - del_timer_sync(&instance->status_check_timer); + timer_delete_sync(&instance->status_check_timer); /* * Since resubmit_timer and int_urb can schedule themselves and @@ -697,14 +697,14 @@ static void speedtch_atm_stop(struct usbatm_data *usbatm, struct atm_dev *atm_de instance->int_urb = NULL; /* signal shutdown */ mb(); usb_kill_urb(int_urb); - del_timer_sync(&instance->resubmit_timer); + timer_delete_sync(&instance->resubmit_timer); /* * At this point, speedtch_handle_int and speedtch_resubmit_int * can run or be running, but instance->int_urb == NULL means that * they will not reschedule */ usb_kill_urb(int_urb); - del_timer_sync(&instance->resubmit_timer); + timer_delete_sync(&instance->resubmit_timer); usb_free_urb(int_urb); flush_work(&instance->status_check_work);
diff --git a/drivers/usb/atm/usbatm.c b/drivers/usb/atm/usbatm.c index d1e622b..a6a05e8 100644 --- a/drivers/usb/atm/usbatm.c +++ b/drivers/usb/atm/usbatm.c
@@ -1237,8 +1237,8 @@ void usbatm_usb_disconnect(struct usb_interface *intf) for (i = 0; i < num_rcv_urbs + num_snd_urbs; i++) usb_kill_urb(instance->urbs[i]); - del_timer_sync(&instance->rx_channel.delay); - del_timer_sync(&instance->tx_channel.delay); + timer_delete_sync(&instance->rx_channel.delay); + timer_delete_sync(&instance->tx_channel.delay); /* turn usbatm_[rt]x_process into something close to a no-op */ /* no need to take the spinlock */
diff --git a/drivers/usb/cdns3/cdns3-gadget.c b/drivers/usb/cdns3/cdns3-gadget.c index fd1beb1..694aa14 100644 --- a/drivers/usb/cdns3/cdns3-gadget.c +++ b/drivers/usb/cdns3/cdns3-gadget.c
@@ -3468,7 +3468,7 @@ __must_hold(&cdns->lock) return 0; } -static int cdns3_gadget_resume(struct cdns *cdns, bool hibernated) +static int cdns3_gadget_resume(struct cdns *cdns, bool lost_power) { struct cdns3_device *priv_dev = cdns->gadget_dev; @@ -3476,7 +3476,7 @@ static int cdns3_gadget_resume(struct cdns *cdns, bool hibernated) return 0; cdns3_gadget_config(priv_dev); - if (hibernated) + if (lost_power) writel(USB_CONF_DEVEN, &priv_dev->regs->usb_conf); return 0;
diff --git a/drivers/usb/cdns3/cdns3-ti.c b/drivers/usb/cdns3/cdns3-ti.c index 040bb91..302ebf6 100644 --- a/drivers/usb/cdns3/cdns3-ti.c +++ b/drivers/usb/cdns3/cdns3-ti.c
@@ -58,6 +58,7 @@ struct cdns_ti { unsigned vbus_divider:1; struct clk *usb2_refclk; struct clk *lpm_clk; + int usb2_refclk_rate_code; }; static const int cdns_ti_rate_table[] = { /* in KHZ */ @@ -98,15 +99,50 @@ static const struct of_dev_auxdata cdns_ti_auxdata[] = { {}, }; +static void cdns_ti_reset_and_init_hw(struct cdns_ti *data) +{ + u32 reg; + + /* assert RESET */ + reg = cdns_ti_readl(data, USBSS_W1); + reg &= ~USBSS_W1_PWRUP_RST; + cdns_ti_writel(data, USBSS_W1, reg); + + /* set static config */ + reg = cdns_ti_readl(data, USBSS_STATIC_CONFIG); + reg &= ~USBSS1_STATIC_PLL_REF_SEL_MASK; + reg |= data->usb2_refclk_rate_code << USBSS1_STATIC_PLL_REF_SEL_SHIFT; + + reg &= ~USBSS1_STATIC_VBUS_SEL_MASK; + if (data->vbus_divider) + reg |= 1 << USBSS1_STATIC_VBUS_SEL_SHIFT; + + cdns_ti_writel(data, USBSS_STATIC_CONFIG, reg); + reg = cdns_ti_readl(data, USBSS_STATIC_CONFIG); + + /* set USB2_ONLY mode if requested */ + reg = cdns_ti_readl(data, USBSS_W1); + if (data->usb2_only) + reg |= USBSS_W1_USB2_ONLY; + + /* set default modestrap */ + reg |= USBSS_W1_MODESTRAP_SEL; + reg &= ~USBSS_W1_MODESTRAP_MASK; + reg |= USBSS_MODESTRAP_MODE_NONE << USBSS_W1_MODESTRAP_SHIFT; + cdns_ti_writel(data, USBSS_W1, reg); + + /* de-assert RESET */ + reg |= USBSS_W1_PWRUP_RST; + cdns_ti_writel(data, USBSS_W1, reg); +} + static int cdns_ti_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct device_node *node = pdev->dev.of_node; struct cdns_ti *data; - int error; - u32 reg; - int rate_code, i; unsigned long rate; + int error, i; data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); if (!data) @@ -146,7 +182,17 @@ static int cdns_ti_probe(struct platform_device *pdev) return -EINVAL; } - rate_code = i; + data->usb2_refclk_rate_code = i; + data->vbus_divider = device_property_read_bool(dev, "ti,vbus-divider"); + data->usb2_only = device_property_read_bool(dev, "ti,usb2-only"); + + /* + * The call below to pm_runtime_get_sync() MIGHT reset hardware, if it + * detects it as uninitialised. We want to enforce a reset at probe, + * and so do it manually here. This means the first runtime_resume() + * will be a no-op. + */ + cdns_ti_reset_and_init_hw(data); pm_runtime_enable(dev); error = pm_runtime_get_sync(dev); @@ -155,40 +201,6 @@ static int cdns_ti_probe(struct platform_device *pdev) goto err; } - /* assert RESET */ - reg = cdns_ti_readl(data, USBSS_W1); - reg &= ~USBSS_W1_PWRUP_RST; - cdns_ti_writel(data, USBSS_W1, reg); - - /* set static config */ - reg = cdns_ti_readl(data, USBSS_STATIC_CONFIG); - reg &= ~USBSS1_STATIC_PLL_REF_SEL_MASK; - reg |= rate_code << USBSS1_STATIC_PLL_REF_SEL_SHIFT; - - reg &= ~USBSS1_STATIC_VBUS_SEL_MASK; - data->vbus_divider = device_property_read_bool(dev, "ti,vbus-divider"); - if (data->vbus_divider) - reg |= 1 << USBSS1_STATIC_VBUS_SEL_SHIFT; - - cdns_ti_writel(data, USBSS_STATIC_CONFIG, reg); - reg = cdns_ti_readl(data, USBSS_STATIC_CONFIG); - - /* set USB2_ONLY mode if requested */ - reg = cdns_ti_readl(data, USBSS_W1); - data->usb2_only = device_property_read_bool(dev, "ti,usb2-only"); - if (data->usb2_only) - reg |= USBSS_W1_USB2_ONLY; - - /* set default modestrap */ - reg |= USBSS_W1_MODESTRAP_SEL; - reg &= ~USBSS_W1_MODESTRAP_MASK; - reg |= USBSS_MODESTRAP_MODE_NONE << USBSS_W1_MODESTRAP_SHIFT; - cdns_ti_writel(data, USBSS_W1, reg); - - /* de-assert RESET */ - reg |= USBSS_W1_PWRUP_RST; - cdns_ti_writel(data, USBSS_W1, reg); - error = of_platform_populate(node, NULL, cdns_ti_auxdata, dev); if (error) { dev_err(dev, "failed to create children: %d\n", error); @@ -224,6 +236,24 @@ static void cdns_ti_remove(struct platform_device *pdev) platform_set_drvdata(pdev, NULL); } +static int cdns_ti_runtime_resume(struct device *dev) +{ + const u32 mask = USBSS_W1_PWRUP_RST | USBSS_W1_MODESTRAP_SEL; + struct cdns_ti *data = dev_get_drvdata(dev); + u32 w1; + + w1 = cdns_ti_readl(data, USBSS_W1); + if ((w1 & mask) != mask) + cdns_ti_reset_and_init_hw(data); + + return 0; +} + +static const struct dev_pm_ops cdns_ti_pm_ops = { + RUNTIME_PM_OPS(NULL, cdns_ti_runtime_resume, NULL) + SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) +}; + static const struct of_device_id cdns_ti_of_match[] = { { .compatible = "ti,j721e-usb", }, { .compatible = "ti,am64-usb", }, @@ -237,6 +267,7 @@ static struct platform_driver cdns_ti_driver = { .driver = { .name = "cdns3-ti", .of_match_table = cdns_ti_of_match, + .pm = pm_ptr(&cdns_ti_pm_ops), }, };
diff --git a/drivers/usb/cdns3/cdnsp-gadget.c b/drivers/usb/cdns3/cdnsp-gadget.c index 97edf76..87f3108 100644 --- a/drivers/usb/cdns3/cdnsp-gadget.c +++ b/drivers/usb/cdns3/cdnsp-gadget.c
@@ -1974,7 +1974,7 @@ static int cdnsp_gadget_suspend(struct cdns *cdns, bool do_wakeup) return 0; } -static int cdnsp_gadget_resume(struct cdns *cdns, bool hibernated) +static int cdnsp_gadget_resume(struct cdns *cdns, bool lost_power) { struct cdnsp_device *pdev = cdns->gadget_dev; enum usb_device_speed max_speed;
diff --git a/drivers/usb/cdns3/core.c b/drivers/usb/cdns3/core.c index 98980a2..1243a5c 100644 --- a/drivers/usb/cdns3/core.c +++ b/drivers/usb/cdns3/core.c
@@ -524,11 +524,12 @@ EXPORT_SYMBOL_GPL(cdns_suspend); int cdns_resume(struct cdns *cdns) { + bool power_lost = cdns_power_is_lost(cdns); enum usb_role real_role; bool role_changed = false; int ret = 0; - if (cdns_power_is_lost(cdns)) { + if (power_lost) { if (!cdns->role_sw) { real_role = cdns_hw_role_state_machine(cdns); if (real_role != cdns->role) { @@ -551,7 +552,7 @@ int cdns_resume(struct cdns *cdns) } if (cdns->roles[cdns->role]->resume) - cdns->roles[cdns->role]->resume(cdns, cdns_power_is_lost(cdns)); + cdns->roles[cdns->role]->resume(cdns, power_lost); return 0; }
diff --git a/drivers/usb/cdns3/core.h b/drivers/usb/cdns3/core.h index 57d4734..921cccf 100644 --- a/drivers/usb/cdns3/core.h +++ b/drivers/usb/cdns3/core.h
@@ -30,7 +30,7 @@ struct cdns_role_driver { int (*start)(struct cdns *cdns); void (*stop)(struct cdns *cdns); int (*suspend)(struct cdns *cdns, bool do_wakeup); - int (*resume)(struct cdns *cdns, bool hibernated); + int (*resume)(struct cdns *cdns, bool lost_power); const char *name; #define CDNS_ROLE_STATE_INACTIVE 0 #define CDNS_ROLE_STATE_ACTIVE 1
diff --git a/drivers/usb/cdns3/host.c b/drivers/usb/cdns3/host.c index 7ba760e..f0df114 100644 --- a/drivers/usb/cdns3/host.c +++ b/drivers/usb/cdns3/host.c
@@ -138,6 +138,16 @@ static void cdns_host_exit(struct cdns *cdns) cdns_drd_host_off(cdns); } +static int cdns_host_resume(struct cdns *cdns, bool power_lost) +{ + struct usb_hcd *hcd = platform_get_drvdata(cdns->host_dev); + struct xhci_plat_priv *priv = hcd_to_xhci_priv(hcd); + + priv->power_lost = power_lost; + + return 0; +} + int cdns_host_init(struct cdns *cdns) { struct cdns_role_driver *rdrv; @@ -148,6 +158,7 @@ int cdns_host_init(struct cdns *cdns) rdrv->start = __cdns_host_init; rdrv->stop = cdns_host_exit; + rdrv->resume = cdns_host_resume; rdrv->state = CDNS_ROLE_STATE_INACTIVE; rdrv->name = "host";
diff --git a/drivers/usb/chipidea/usbmisc_imx.c b/drivers/usb/chipidea/usbmisc_imx.c index 1394881..6243d80 100644 --- a/drivers/usb/chipidea/usbmisc_imx.c +++ b/drivers/usb/chipidea/usbmisc_imx.c
@@ -440,7 +440,7 @@ static int usbmisc_imx6q_init(struct imx_usbmisc_data *data) else if (data->oc_pol_configured) reg &= ~MX6_BM_OVER_CUR_POLARITY; } - /* If the polarity is not set keep it as setup by the bootlader */ + /* If the polarity is not set keep it as setup by the bootloader */ if (data->pwr_pol == 1) reg |= MX6_BM_PWR_POLARITY; writel(reg, usbmisc->base + data->index * 4); @@ -645,7 +645,7 @@ static int usbmisc_imx7d_init(struct imx_usbmisc_data *data) else if (data->oc_pol_configured) reg &= ~MX6_BM_OVER_CUR_POLARITY; } - /* If the polarity is not set keep it as setup by the bootlader */ + /* If the polarity is not set keep it as setup by the bootloader */ if (data->pwr_pol == 1) reg |= MX6_BM_PWR_POLARITY; writel(reg, usbmisc->base); @@ -939,7 +939,7 @@ static int usbmisc_imx7ulp_init(struct imx_usbmisc_data *data) else if (data->oc_pol_configured) reg &= ~MX6_BM_OVER_CUR_POLARITY; } - /* If the polarity is not set keep it as setup by the bootlader */ + /* If the polarity is not set keep it as setup by the bootloader */ if (data->pwr_pol == 1) reg |= MX6_BM_PWR_POLARITY; @@ -1185,7 +1185,7 @@ int imx_usbmisc_suspend(struct imx_usbmisc_data *data, bool wakeup) if (usbmisc->ops->hsic_set_clk && data->hsic) ret = usbmisc->ops->hsic_set_clk(data, false); if (ret) { - dev_err(data->dev, "set_wakeup failed, ret=%d\n", ret); + dev_err(data->dev, "hsic_set_clk failed, ret=%d\n", ret); return ret; } @@ -1224,7 +1224,7 @@ int imx_usbmisc_resume(struct imx_usbmisc_data *data, bool wakeup) if (usbmisc->ops->hsic_set_clk && data->hsic) ret = usbmisc->ops->hsic_set_clk(data, true); if (ret) { - dev_err(data->dev, "set_wakeup failed, ret=%d\n", ret); + dev_err(data->dev, "hsic_set_clk failed, ret=%d\n", ret); goto hsic_set_clk_fail; }
diff --git a/drivers/usb/common/usb-conn-gpio.c b/drivers/usb/common/usb-conn-gpio.c index aa710b5..1e36be2 100644 --- a/drivers/usb/common/usb-conn-gpio.c +++ b/drivers/usb/common/usb-conn-gpio.c
@@ -158,7 +158,7 @@ static int usb_conn_psy_register(struct usb_conn_info *info) struct device *dev = info->dev; struct power_supply_desc *desc = &info->desc; struct power_supply_config cfg = { - .of_node = dev->of_node, + .fwnode = dev_fwnode(dev), }; desc->name = "usb-charger";
diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c index f7bf8d1..13bd4ec 100644 --- a/drivers/usb/core/config.c +++ b/drivers/usb/core/config.c
@@ -64,6 +64,37 @@ static void usb_parse_ssp_isoc_endpoint_companion(struct device *ddev, memcpy(&ep->ssp_isoc_ep_comp, desc, USB_DT_SSP_ISOC_EP_COMP_SIZE); } +static void usb_parse_eusb2_isoc_endpoint_companion(struct device *ddev, + int cfgno, int inum, int asnum, struct usb_host_endpoint *ep, + unsigned char *buffer, int size) +{ + struct usb_eusb2_isoc_ep_comp_descriptor *desc; + struct usb_descriptor_header *h; + + /* + * eUSB2 isochronous endpoint companion descriptor for this endpoint + * shall be declared before the next endpoint or interface descriptor + */ + while (size >= USB_DT_EUSB2_ISOC_EP_COMP_SIZE) { + h = (struct usb_descriptor_header *)buffer; + + if (h->bDescriptorType == USB_DT_EUSB2_ISOC_ENDPOINT_COMP) { + desc = (struct usb_eusb2_isoc_ep_comp_descriptor *)buffer; + ep->eusb2_isoc_ep_comp = *desc; + return; + } + if (h->bDescriptorType == USB_DT_ENDPOINT || + h->bDescriptorType == USB_DT_INTERFACE) + break; + + buffer += h->bLength; + size -= h->bLength; + } + + dev_notice(ddev, "No eUSB2 isoc ep %d companion for config %d interface %d altsetting %d\n", + ep->desc.bEndpointAddress, cfgno, inum, asnum); +} + static void usb_parse_ss_endpoint_companion(struct device *ddev, int cfgno, int inum, int asnum, struct usb_host_endpoint *ep, unsigned char *buffer, int size) @@ -258,8 +289,10 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int n, i, j, retval; unsigned int maxp; const unsigned short *maxpacket_maxes; + u16 bcdUSB; d = (struct usb_endpoint_descriptor *) buffer; + bcdUSB = le16_to_cpu(udev->descriptor.bcdUSB); buffer += d->bLength; size -= d->bLength; @@ -409,15 +442,17 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, /* * Validate the wMaxPacketSize field. - * Some devices have isochronous endpoints in altsetting 0; - * the USB-2 spec requires such endpoints to have wMaxPacketSize = 0 - * (see the end of section 5.6.3), so don't warn about them. + * eUSB2 devices (see USB 2.0 Double Isochronous IN ECN 9.6.6 Endpoint) + * and devices with isochronous endpoints in altsetting 0 (see USB 2.0 + * end of section 5.6.3) have wMaxPacketSize = 0. + * So don't warn about those. */ maxp = le16_to_cpu(endpoint->desc.wMaxPacketSize); - if (maxp == 0 && !(usb_endpoint_xfer_isoc(d) && asnum == 0)) { + + if (maxp == 0 && bcdUSB != 0x0220 && + !(usb_endpoint_xfer_isoc(d) && asnum == 0)) dev_notice(ddev, "config %d interface %d altsetting %d endpoint 0x%X has invalid wMaxPacketSize 0\n", cfgno, inum, asnum, d->bEndpointAddress); - } /* Find the highest legal maxpacket size for this endpoint */ i = 0; /* additional transactions per microframe */ @@ -465,6 +500,12 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, maxp); } + /* Parse a possible eUSB2 periodic endpoint companion descriptor */ + if (bcdUSB == 0x0220 && d->wMaxPacketSize == 0 && + (usb_endpoint_xfer_isoc(d) || usb_endpoint_xfer_int(d))) + usb_parse_eusb2_isoc_endpoint_companion(ddev, cfgno, inum, asnum, + endpoint, buffer, size); + /* Parse a possible SuperSpeed endpoint companion descriptor */ if (udev->speed >= USB_SPEED_SUPER) usb_parse_ss_endpoint_companion(ddev, cfgno,
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index a75cf1f..a63c793 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c
@@ -842,7 +842,7 @@ static int usb_rh_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) } else { /* Status URB */ if (!hcd->uses_new_polling) - del_timer (&hcd->rh_timer); + timer_delete(&hcd->rh_timer); if (urb == hcd->status_urb) { hcd->status_urb = NULL; usb_hcd_unlink_urb_from_ep(hcd, urb); @@ -1609,7 +1609,7 @@ int usb_hcd_unlink_urb (struct urb *urb, int status) if (retval == 0) retval = -EINPROGRESS; else if (retval != -EIDRM && retval != -EBUSY) - dev_dbg(&udev->dev, "hcd_unlink_urb %pK fail %d\n", + dev_dbg(&udev->dev, "hcd_unlink_urb %p fail %d\n", urb, retval); usb_put_dev(udev); } @@ -1786,7 +1786,7 @@ void usb_hcd_flush_endpoint(struct usb_device *udev, /* kick hcd */ unlink1(hcd, urb, -ESHUTDOWN); dev_dbg (hcd->self.controller, - "shutdown urb %pK ep%d%s-%s\n", + "shutdown urb %p ep%d%s-%s\n", urb, usb_endpoint_num(&ep->desc), is_in ? "in" : "out", usb_ep_type_string(usb_endpoint_type(&ep->desc))); @@ -2768,14 +2768,14 @@ static void usb_stop_hcd(struct usb_hcd *hcd) { hcd->rh_pollable = 0; clear_bit(HCD_FLAG_POLL_RH, &hcd->flags); - del_timer_sync(&hcd->rh_timer); + timer_delete_sync(&hcd->rh_timer); hcd->driver->stop(hcd); hcd->state = HC_STATE_HALT; /* In case the HCD restarted the timer, stop it again. */ clear_bit(HCD_FLAG_POLL_RH, &hcd->flags); - del_timer_sync(&hcd->rh_timer); + timer_delete_sync(&hcd->rh_timer); } /**
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index dcba428..0e1dd6e 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c
@@ -1385,7 +1385,7 @@ static void hub_quiesce(struct usb_hub *hub, enum hub_quiescing_type type) } /* Stop hub_wq and related activity */ - del_timer_sync(&hub->irq_urb_retry); + timer_delete_sync(&hub->irq_urb_retry); usb_kill_urb(hub->urb); if (hub->has_indicators) cancel_delayed_work_sync(&hub->leds); @@ -4708,8 +4708,6 @@ void usb_ep0_reinit(struct usb_device *udev) } EXPORT_SYMBOL_GPL(usb_ep0_reinit); -#define usb_sndaddr0pipe() (PIPE_CONTROL << 30) - static int hub_set_address(struct usb_device *udev, int devnum) { int retval; @@ -4733,7 +4731,7 @@ static int hub_set_address(struct usb_device *udev, int devnum) if (hcd->driver->address_device) retval = hcd->driver->address_device(hcd, udev, timeout_ms); else - retval = usb_control_msg(udev, usb_sndaddr0pipe(), + retval = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), USB_REQ_SET_ADDRESS, 0, devnum, 0, NULL, 0, timeout_ms); if (retval == 0) {
diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c index 7576920..5e52a354 100644 --- a/drivers/usb/core/urb.c +++ b/drivers/usb/core/urb.c
@@ -376,7 +376,7 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags) if (!urb || !urb->complete) return -EINVAL; if (urb->hcpriv) { - WARN_ONCE(1, "URB %pK submitted while active\n", urb); + WARN_ONCE(1, "URB %p submitted while active\n", urb); return -EBUSY; }
diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c index 9919ab7..c3d2431 100644 --- a/drivers/usb/dwc2/core.c +++ b/drivers/usb/dwc2/core.c
@@ -43,6 +43,7 @@ int dwc2_backup_global_registers(struct dwc2_hsotg *hsotg) /* Backup global regs */ gr = &hsotg->gr_backup; + gr->gintsts = dwc2_readl(hsotg, GINTSTS); gr->gotgctl = dwc2_readl(hsotg, GOTGCTL); gr->gintmsk = dwc2_readl(hsotg, GINTMSK); gr->gahbcfg = dwc2_readl(hsotg, GAHBCFG);
diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h index 2bd74f3..34127b8 100644 --- a/drivers/usb/dwc2/core.h +++ b/drivers/usb/dwc2/core.h
@@ -667,6 +667,7 @@ struct dwc2_hw_params { /** * struct dwc2_gregs_backup - Holds global registers state before * entering partial power down + * @gintsts: Backup of GINTSTS register * @gotgctl: Backup of GOTGCTL register * @gintmsk: Backup of GINTMSK register * @gahbcfg: Backup of GAHBCFG register @@ -683,6 +684,7 @@ struct dwc2_hw_params { * @valid: True if registers values backuped. */ struct dwc2_gregs_backup { + u32 gintsts; u32 gotgctl; u32 gintmsk; u32 gahbcfg; @@ -1127,6 +1129,9 @@ struct dwc2_hsotg { #define DWC2_FS_IOT_ID 0x55310000 #define DWC2_HS_IOT_ID 0x55320000 +#define DWC2_RESTORE_DCTL BIT(0) +#define DWC2_RESTORE_DCFG BIT(1) + #if IS_ENABLED(CONFIG_USB_DWC2_HOST) || IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE) union dwc2_hcd_internal_flags { u32 d32; @@ -1420,7 +1425,7 @@ int dwc2_hsotg_set_test_mode(struct dwc2_hsotg *hsotg, int testmode); #define dwc2_is_device_connected(hsotg) (hsotg->connected) #define dwc2_is_device_enabled(hsotg) (hsotg->enabled) int dwc2_backup_device_registers(struct dwc2_hsotg *hsotg); -int dwc2_restore_device_registers(struct dwc2_hsotg *hsotg, int remote_wakeup); +int dwc2_restore_device_registers(struct dwc2_hsotg *hsotg, unsigned int flags); int dwc2_gadget_enter_hibernation(struct dwc2_hsotg *hsotg); int dwc2_gadget_exit_hibernation(struct dwc2_hsotg *hsotg, int rem_wakeup, int reset); @@ -1435,6 +1440,9 @@ int dwc2_hsotg_tx_fifo_total_depth(struct dwc2_hsotg *hsotg); int dwc2_hsotg_tx_fifo_average_depth(struct dwc2_hsotg *hsotg); void dwc2_gadget_init_lpm(struct dwc2_hsotg *hsotg); void dwc2_gadget_program_ref_clk(struct dwc2_hsotg *hsotg); +int dwc2_gadget_backup_critical_registers(struct dwc2_hsotg *hsotg); +int dwc2_gadget_restore_critical_registers(struct dwc2_hsotg *hsotg, + unsigned int flags); static inline void dwc2_clear_fifo_map(struct dwc2_hsotg *hsotg) { hsotg->fifo_map = 0; } #else @@ -1459,7 +1467,7 @@ static inline int dwc2_hsotg_set_test_mode(struct dwc2_hsotg *hsotg, static inline int dwc2_backup_device_registers(struct dwc2_hsotg *hsotg) { return 0; } static inline int dwc2_restore_device_registers(struct dwc2_hsotg *hsotg, - int remote_wakeup) + unsigned int flags) { return 0; } static inline int dwc2_gadget_enter_hibernation(struct dwc2_hsotg *hsotg) { return 0; } @@ -1482,6 +1490,11 @@ static inline int dwc2_hsotg_tx_fifo_average_depth(struct dwc2_hsotg *hsotg) { return 0; } static inline void dwc2_gadget_init_lpm(struct dwc2_hsotg *hsotg) {} static inline void dwc2_gadget_program_ref_clk(struct dwc2_hsotg *hsotg) {} +static inline int dwc2_gadget_backup_critical_registers(struct dwc2_hsotg *hsotg) +{ return 0; } +static inline int dwc2_gadget_restore_critical_registers(struct dwc2_hsotg *hsotg, + unsigned int flags) +{ return 0; } static inline void dwc2_clear_fifo_map(struct dwc2_hsotg *hsotg) {} #endif @@ -1505,6 +1518,8 @@ int dwc2_host_exit_partial_power_down(struct dwc2_hsotg *hsotg, void dwc2_host_enter_clock_gating(struct dwc2_hsotg *hsotg); void dwc2_host_exit_clock_gating(struct dwc2_hsotg *hsotg, int rem_wakeup); bool dwc2_host_can_poweroff_phy(struct dwc2_hsotg *dwc2); +int dwc2_host_backup_critical_registers(struct dwc2_hsotg *hsotg); +int dwc2_host_restore_critical_registers(struct dwc2_hsotg *hsotg); static inline void dwc2_host_schedule_phy_reset(struct dwc2_hsotg *hsotg) { schedule_work(&hsotg->phy_reset_work); } #else @@ -1544,6 +1559,10 @@ static inline void dwc2_host_exit_clock_gating(struct dwc2_hsotg *hsotg, int rem_wakeup) {} static inline bool dwc2_host_can_poweroff_phy(struct dwc2_hsotg *dwc2) { return false; } +static inline int dwc2_host_backup_critical_registers(struct dwc2_hsotg *hsotg) +{ return 0; } +static inline int dwc2_host_restore_critical_registers(struct dwc2_hsotg *hsotg) +{ return 0; } static inline void dwc2_host_schedule_phy_reset(struct dwc2_hsotg *hsotg) {} #endif
diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c index bd4c788..300ea49 100644 --- a/drivers/usb/dwc2/gadget.c +++ b/drivers/usb/dwc2/gadget.c
@@ -5204,11 +5204,11 @@ int dwc2_backup_device_registers(struct dwc2_hsotg *hsotg) * if controller power were disabled. * * @hsotg: Programming view of the DWC_otg controller - * @remote_wakeup: Indicates whether resume is initiated by Device or Host. + * @flags: Defines which registers should be restored. * * Return: 0 if successful, negative error code otherwise */ -int dwc2_restore_device_registers(struct dwc2_hsotg *hsotg, int remote_wakeup) +int dwc2_restore_device_registers(struct dwc2_hsotg *hsotg, unsigned int flags) { struct dwc2_dregs_backup *dr; int i; @@ -5224,7 +5224,10 @@ int dwc2_restore_device_registers(struct dwc2_hsotg *hsotg, int remote_wakeup) } dr->valid = false; - if (!remote_wakeup) + if (flags & DWC2_RESTORE_DCFG) + dwc2_writel(hsotg, dr->dcfg, DCFG); + + if (flags & DWC2_RESTORE_DCTL) dwc2_writel(hsotg, dr->dctl, DCTL); dwc2_writel(hsotg, dr->daintmsk, DAINTMSK); @@ -5310,6 +5313,49 @@ void dwc2_gadget_program_ref_clk(struct dwc2_hsotg *hsotg) dev_dbg(hsotg->dev, "GREFCLK=0x%08x\n", dwc2_readl(hsotg, GREFCLK)); } +int dwc2_gadget_backup_critical_registers(struct dwc2_hsotg *hsotg) +{ + int ret; + + /* Backup all registers */ + ret = dwc2_backup_global_registers(hsotg); + if (ret) { + dev_err(hsotg->dev, "%s: failed to backup global registers\n", + __func__); + return ret; + } + + ret = dwc2_backup_device_registers(hsotg); + if (ret) { + dev_err(hsotg->dev, "%s: failed to backup device registers\n", + __func__); + return ret; + } + + return 0; +} + +int dwc2_gadget_restore_critical_registers(struct dwc2_hsotg *hsotg, + unsigned int flags) +{ + int ret; + + ret = dwc2_restore_global_registers(hsotg); + if (ret) { + dev_err(hsotg->dev, "%s: failed to restore registers\n", + __func__); + return ret; + } + ret = dwc2_restore_device_registers(hsotg, flags); + if (ret) { + dev_err(hsotg->dev, "%s: failed to restore device registers\n", + __func__); + return ret; + } + + return 0; +} + /** * dwc2_gadget_enter_hibernation() - Put controller in Hibernation. * @@ -5327,18 +5373,9 @@ int dwc2_gadget_enter_hibernation(struct dwc2_hsotg *hsotg) /* Change to L2(suspend) state */ hsotg->lx_state = DWC2_L2; dev_dbg(hsotg->dev, "Start of hibernation completed\n"); - ret = dwc2_backup_global_registers(hsotg); - if (ret) { - dev_err(hsotg->dev, "%s: failed to backup global registers\n", - __func__); + ret = dwc2_gadget_backup_critical_registers(hsotg); + if (ret) return ret; - } - ret = dwc2_backup_device_registers(hsotg); - if (ret) { - dev_err(hsotg->dev, "%s: failed to backup device registers\n", - __func__); - return ret; - } gpwrdn = GPWRDN_PWRDNRSTN; udelay(10); @@ -5415,6 +5452,7 @@ int dwc2_gadget_exit_hibernation(struct dwc2_hsotg *hsotg, u32 gpwrdn; u32 dctl; int ret = 0; + unsigned int flags = 0; struct dwc2_gregs_backup *gr; struct dwc2_dregs_backup *dr; @@ -5477,6 +5515,7 @@ int dwc2_gadget_exit_hibernation(struct dwc2_hsotg *hsotg, dctl = dwc2_readl(hsotg, DCTL); dctl |= DCTL_PWRONPRGDONE; dwc2_writel(hsotg, dctl, DCTL); + flags |= DWC2_RESTORE_DCTL; } /* Wait for interrupts which must be cleared */ mdelay(2); @@ -5484,20 +5523,9 @@ int dwc2_gadget_exit_hibernation(struct dwc2_hsotg *hsotg, dwc2_writel(hsotg, 0xffffffff, GINTSTS); /* Restore global registers */ - ret = dwc2_restore_global_registers(hsotg); - if (ret) { - dev_err(hsotg->dev, "%s: failed to restore registers\n", - __func__); + ret = dwc2_gadget_restore_critical_registers(hsotg, flags); + if (ret) return ret; - } - - /* Restore device registers */ - ret = dwc2_restore_device_registers(hsotg, rem_wakeup); - if (ret) { - dev_err(hsotg->dev, "%s: failed to restore device registers\n", - __func__); - return ret; - } if (rem_wakeup) { mdelay(10); @@ -5531,19 +5559,9 @@ int dwc2_gadget_enter_partial_power_down(struct dwc2_hsotg *hsotg) dev_dbg(hsotg->dev, "Entering device partial power down started.\n"); /* Backup all registers */ - ret = dwc2_backup_global_registers(hsotg); - if (ret) { - dev_err(hsotg->dev, "%s: failed to backup global registers\n", - __func__); + ret = dwc2_gadget_backup_critical_registers(hsotg); + if (ret) return ret; - } - - ret = dwc2_backup_device_registers(hsotg); - if (ret) { - dev_err(hsotg->dev, "%s: failed to backup device registers\n", - __func__); - return ret; - } /* * Clear any pending interrupts since dwc2 will not be able to @@ -5590,11 +5608,8 @@ int dwc2_gadget_exit_partial_power_down(struct dwc2_hsotg *hsotg, { u32 pcgcctl; u32 dctl; - struct dwc2_dregs_backup *dr; int ret = 0; - dr = &hsotg->dr_backup; - dev_dbg(hsotg->dev, "Exiting device partial Power Down started.\n"); pcgcctl = dwc2_readl(hsotg, PCGCTL); @@ -5611,21 +5626,10 @@ int dwc2_gadget_exit_partial_power_down(struct dwc2_hsotg *hsotg, udelay(100); if (restore) { - ret = dwc2_restore_global_registers(hsotg); - if (ret) { - dev_err(hsotg->dev, "%s: failed to restore registers\n", - __func__); + ret = dwc2_gadget_restore_critical_registers(hsotg, DWC2_RESTORE_DCTL | + DWC2_RESTORE_DCFG); + if (ret) return ret; - } - /* Restore DCFG */ - dwc2_writel(hsotg, dr->dcfg, DCFG); - - ret = dwc2_restore_device_registers(hsotg, 0); - if (ret) { - dev_err(hsotg->dev, "%s: failed to restore device registers\n", - __func__); - return ret; - } } /* Set the Power-On Programming done bit */
diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c index 8c3941e..60ef80922 100644 --- a/drivers/usb/dwc2/hcd.c +++ b/drivers/usb/dwc2/hcd.c
@@ -5081,7 +5081,7 @@ static void dwc2_hcd_free(struct dwc2_hsotg *hsotg) cancel_work_sync(&hsotg->phy_reset_work); - del_timer(&hsotg->wkp_timer); + timer_delete(&hsotg->wkp_timer); } static void dwc2_hcd_release(struct dwc2_hsotg *hsotg) @@ -5474,6 +5474,49 @@ int dwc2_restore_host_registers(struct dwc2_hsotg *hsotg) return 0; } +int dwc2_host_backup_critical_registers(struct dwc2_hsotg *hsotg) +{ + int ret; + + /* Backup all registers */ + ret = dwc2_backup_global_registers(hsotg); + if (ret) { + dev_err(hsotg->dev, "%s: failed to backup global registers\n", + __func__); + return ret; + } + + ret = dwc2_backup_host_registers(hsotg); + if (ret) { + dev_err(hsotg->dev, "%s: failed to backup host registers\n", + __func__); + return ret; + } + + return 0; +} + +int dwc2_host_restore_critical_registers(struct dwc2_hsotg *hsotg) +{ + int ret; + + ret = dwc2_restore_global_registers(hsotg); + if (ret) { + dev_err(hsotg->dev, "%s: failed to restore registers\n", + __func__); + return ret; + } + + ret = dwc2_restore_host_registers(hsotg); + if (ret) { + dev_err(hsotg->dev, "%s: failed to restore host registers\n", + __func__); + return ret; + } + + return 0; +} + /** * dwc2_host_enter_hibernation() - Put controller in Hibernation. * @@ -5489,18 +5532,9 @@ int dwc2_host_enter_hibernation(struct dwc2_hsotg *hsotg) u32 gpwrdn; dev_dbg(hsotg->dev, "Preparing host for hibernation\n"); - ret = dwc2_backup_global_registers(hsotg); - if (ret) { - dev_err(hsotg->dev, "%s: failed to backup global registers\n", - __func__); + ret = dwc2_host_backup_critical_registers(hsotg); + if (ret) return ret; - } - ret = dwc2_backup_host_registers(hsotg); - if (ret) { - dev_err(hsotg->dev, "%s: failed to backup host registers\n", - __func__); - return ret; - } /* Enter USB Suspend Mode */ hprt0 = dwc2_readl(hsotg, HPRT0); @@ -5694,20 +5728,9 @@ int dwc2_host_exit_hibernation(struct dwc2_hsotg *hsotg, int rem_wakeup, dwc2_writel(hsotg, 0xffffffff, GINTSTS); /* Restore global registers */ - ret = dwc2_restore_global_registers(hsotg); - if (ret) { - dev_err(hsotg->dev, "%s: failed to restore registers\n", - __func__); + ret = dwc2_host_restore_critical_registers(hsotg); + if (ret) return ret; - } - - /* Restore host registers */ - ret = dwc2_restore_host_registers(hsotg); - if (ret) { - dev_err(hsotg->dev, "%s: failed to restore host registers\n", - __func__); - return ret; - } if (rem_wakeup) { dwc2_hcd_rem_wakeup(hsotg); @@ -5774,19 +5797,9 @@ int dwc2_host_enter_partial_power_down(struct dwc2_hsotg *hsotg) dev_warn(hsotg->dev, "Suspend wasn't generated\n"); /* Backup all registers */ - ret = dwc2_backup_global_registers(hsotg); - if (ret) { - dev_err(hsotg->dev, "%s: failed to backup global registers\n", - __func__); + ret = dwc2_host_backup_critical_registers(hsotg); + if (ret) return ret; - } - - ret = dwc2_backup_host_registers(hsotg); - if (ret) { - dev_err(hsotg->dev, "%s: failed to backup host registers\n", - __func__); - return ret; - } /* * Clear any pending interrupts since dwc2 will not be able to @@ -5855,19 +5868,9 @@ int dwc2_host_exit_partial_power_down(struct dwc2_hsotg *hsotg, udelay(100); if (restore) { - ret = dwc2_restore_global_registers(hsotg); - if (ret) { - dev_err(hsotg->dev, "%s: failed to restore registers\n", - __func__); + ret = dwc2_host_restore_critical_registers(hsotg); + if (ret) return ret; - } - - ret = dwc2_restore_host_registers(hsotg); - if (ret) { - dev_err(hsotg->dev, "%s: failed to restore host registers\n", - __func__); - return ret; - } } /* Drive resume signaling and exit suspend mode on the port. */
diff --git a/drivers/usb/dwc2/hcd_queue.c b/drivers/usb/dwc2/hcd_queue.c index 2a542a9..b009879 100644 --- a/drivers/usb/dwc2/hcd_queue.c +++ b/drivers/usb/dwc2/hcd_queue.c
@@ -1302,7 +1302,7 @@ static int dwc2_schedule_periodic(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh) } /* Cancel pending unreserve; if canceled OK, unreserve was pending */ - if (del_timer(&qh->unreserve_timer)) + if (timer_delete(&qh->unreserve_timer)) WARN_ON(!qh->unreserve_pending); /* @@ -1614,7 +1614,7 @@ struct dwc2_qh *dwc2_hcd_qh_create(struct dwc2_hsotg *hsotg, void dwc2_hcd_qh_free(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh) { /* Make sure any unreserve work is finished. */ - if (del_timer_sync(&qh->unreserve_timer)) { + if (timer_delete_sync(&qh->unreserve_timer)) { unsigned long flags; spin_lock_irqsave(&hsotg->lock, flags);
diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c index 91c80a9..12b4dc0 100644 --- a/drivers/usb/dwc2/platform.c +++ b/drivers/usb/dwc2/platform.c
@@ -685,6 +685,14 @@ static int __maybe_unused dwc2_suspend(struct device *dev) regulator_disable(dwc2->usb33d); } + if (is_device_mode) + ret = dwc2_gadget_backup_critical_registers(dwc2); + else + ret = dwc2_host_backup_critical_registers(dwc2); + + if (ret) + return ret; + if (dwc2->ll_hw_enabled && (is_device_mode || dwc2_host_can_poweroff_phy(dwc2))) { ret = __dwc2_lowlevel_hw_disable(dwc2); @@ -694,6 +702,24 @@ static int __maybe_unused dwc2_suspend(struct device *dev) return ret; } +static int dwc2_restore_critical_registers(struct dwc2_hsotg *hsotg) +{ + struct dwc2_gregs_backup *gr; + + gr = &hsotg->gr_backup; + + if (!gr->valid) { + dev_err(hsotg->dev, "No valid register backup, failed to restore\n"); + return -EINVAL; + } + + if (gr->gintsts & GINTSTS_CURMODE_HOST) + return dwc2_host_restore_critical_registers(hsotg); + + return dwc2_gadget_restore_critical_registers(hsotg, DWC2_RESTORE_DCTL | + DWC2_RESTORE_DCFG); +} + static int __maybe_unused dwc2_resume(struct device *dev) { struct dwc2_hsotg *dwc2 = dev_get_drvdata(dev); @@ -706,6 +732,18 @@ static int __maybe_unused dwc2_resume(struct device *dev) } dwc2->phy_off_for_suspend = false; + /* + * During suspend it's possible that the power domain for the + * DWC2 controller is disabled and all register values get lost. + * In case the GUSBCFG register is not initialized, it's clear the + * registers must be restored. + */ + if (!(dwc2_readl(dwc2, GUSBCFG) & GUSBCFG_TOUTCAL_MASK)) { + ret = dwc2_restore_critical_registers(dwc2); + if (ret) + return ret; + } + if (dwc2->params.activate_stm_id_vb_detection) { unsigned long flags; u32 ggpio, gotgctl;
diff --git a/drivers/usb/dwc3/dwc3-am62.c b/drivers/usb/dwc3/dwc3-am62.c index c158364..9db8f3c 100644 --- a/drivers/usb/dwc3/dwc3-am62.c +++ b/drivers/usb/dwc3/dwc3-am62.c
@@ -153,11 +153,11 @@ static int phy_syscon_pll_refclk(struct dwc3_am62 *am62) { struct device *dev = am62->dev; struct device_node *node = dev->of_node; - struct of_phandle_args args; struct regmap *syscon; int ret; - syscon = syscon_regmap_lookup_by_phandle(node, "ti,syscon-phy-pll-refclk"); + syscon = syscon_regmap_lookup_by_phandle_args(node, "ti,syscon-phy-pll-refclk", + 1, &am62->offset); if (IS_ERR(syscon)) { dev_err(dev, "unable to get ti,syscon-phy-pll-refclk regmap\n"); return PTR_ERR(syscon); @@ -165,14 +165,6 @@ static int phy_syscon_pll_refclk(struct dwc3_am62 *am62) am62->syscon = syscon; - ret = of_parse_phandle_with_fixed_args(node, "ti,syscon-phy-pll-refclk", 1, - 0, &args); - if (ret) - return ret; - - of_node_put(args.np); - am62->offset = args.args[0]; - /* Core voltage. PHY_CORE_VOLTAGE bit Recommended to be 0 always */ ret = regmap_update_bits(am62->syscon, am62->offset, PHY_CORE_VOLTAGE_MASK, 0); if (ret) {
diff --git a/drivers/usb/dwc3/dwc3-exynos.c b/drivers/usb/dwc3/dwc3-exynos.c index f5d963f..de686b9 100644 --- a/drivers/usb/dwc3/dwc3-exynos.c +++ b/drivers/usb/dwc3/dwc3-exynos.c
@@ -163,6 +163,12 @@ static const struct dwc3_exynos_driverdata exynos7_drvdata = { .suspend_clk_idx = 1, }; +static const struct dwc3_exynos_driverdata exynos7870_drvdata = { + .clk_names = { "bus_early", "ref", "ctrl" }, + .num_clks = 3, + .suspend_clk_idx = -1, +}; + static const struct dwc3_exynos_driverdata exynos850_drvdata = { .clk_names = { "bus_early", "ref" }, .num_clks = 2, @@ -186,6 +192,9 @@ static const struct of_device_id exynos_dwc3_match[] = { .compatible = "samsung,exynos7-dwusb3", .data = &exynos7_drvdata, }, { + .compatible = "samsung,exynos7870-dwusb3", + .data = &exynos7870_drvdata, + }, { .compatible = "samsung,exynos850-dwusb3", .data = &exynos850_drvdata, }, {
diff --git a/drivers/usb/dwc3/dwc3-pci.c b/drivers/usb/dwc3/dwc3-pci.c index 052852f..54a4ee2 100644 --- a/drivers/usb/dwc3/dwc3-pci.c +++ b/drivers/usb/dwc3/dwc3-pci.c
@@ -148,11 +148,21 @@ static const struct property_entry dwc3_pci_intel_byt_properties[] = { {} }; +/* + * Intel Merrifield SoC uses these endpoints for tracing and they cannot + * be re-allocated if being used because the side band flow control signals + * are hard wired to certain endpoints: + * - 1 High BW Bulk IN (IN#1) (RTIT) + * - 1 1KB BW Bulk IN (IN#8) + 1 1KB BW Bulk OUT (Run Control) (OUT#8) + */ +static const u8 dwc3_pci_mrfld_reserved_endpoints[] = { 3, 16, 17 }; + static const struct property_entry dwc3_pci_mrfld_properties[] = { PROPERTY_ENTRY_STRING("dr_mode", "otg"), PROPERTY_ENTRY_STRING("linux,extcon-name", "mrfld_bcove_pwrsrc"), PROPERTY_ENTRY_BOOL("snps,dis_u3_susphy_quirk"), PROPERTY_ENTRY_BOOL("snps,dis_u2_susphy_quirk"), + PROPERTY_ENTRY_U8_ARRAY("snps,reserved-endpoints", dwc3_pci_mrfld_reserved_endpoints), PROPERTY_ENTRY_BOOL("snps,usb2-gadget-lpm-disable"), PROPERTY_ENTRY_BOOL("linux,sysdev_is_parent"), {}
diff --git a/drivers/usb/dwc3/dwc3-st.c b/drivers/usb/dwc3/dwc3-st.c index ef7c430..5d513de 100644 --- a/drivers/usb/dwc3/dwc3-st.c +++ b/drivers/usb/dwc3/dwc3-st.c
@@ -225,7 +225,7 @@ static int st_dwc3_probe(struct platform_device *pdev) dwc3_data->syscfg_reg_off = res->start; - dev_vdbg(dev, "glue-logic addr 0x%pK, syscfg-reg offset 0x%x\n", + dev_vdbg(dev, "glue-logic addr 0x%p, syscfg-reg offset 0x%x\n", dwc3_data->glue_base, dwc3_data->syscfg_reg_off); struct device_node *child __free(device_node) = of_get_compatible_child(node,
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 89a4dc8..47e73c4 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c
@@ -547,6 +547,7 @@ static int dwc3_gadget_set_xfer_resource(struct dwc3_ep *dep) int dwc3_gadget_start_config(struct dwc3 *dwc, unsigned int resource_index) { struct dwc3_gadget_ep_cmd_params params; + struct dwc3_ep *dep; u32 cmd; int i; int ret; @@ -563,8 +564,13 @@ int dwc3_gadget_start_config(struct dwc3 *dwc, unsigned int resource_index) return ret; /* Reset resource allocation flags */ - for (i = resource_index; i < dwc->num_eps && dwc->eps[i]; i++) - dwc->eps[i]->flags &= ~DWC3_EP_RESOURCE_ALLOCATED; + for (i = resource_index; i < dwc->num_eps; i++) { + dep = dwc->eps[i]; + if (!dep) + continue; + + dep->flags &= ~DWC3_EP_RESOURCE_ALLOCATED; + } return 0; } @@ -751,9 +757,11 @@ void dwc3_gadget_clear_tx_fifos(struct dwc3 *dwc) dwc->last_fifo_depth = fifo_depth; /* Clear existing TXFIFO for all IN eps except ep0 */ - for (num = 3; num < min_t(int, dwc->num_eps, DWC3_ENDPOINTS_NUM); - num += 2) { + for (num = 3; num < min_t(int, dwc->num_eps, DWC3_ENDPOINTS_NUM); num += 2) { dep = dwc->eps[num]; + if (!dep) + continue; + /* Don't change TXFRAMNUM on usb31 version */ size = DWC3_IP_IS(DWC3) ? 0 : dwc3_readl(dwc->regs, DWC3_GTXFIFOSIZ(num >> 1)) & @@ -1971,12 +1979,12 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req) return -ESHUTDOWN; } - if (WARN(req->dep != dep, "request %pK belongs to '%s'\n", + if (WARN(req->dep != dep, "request %p belongs to '%s'\n", &req->request, req->dep->name)) return -EINVAL; if (WARN(req->status < DWC3_REQUEST_STATUS_COMPLETED, - "%s: request %pK already in flight\n", + "%s: request %p already in flight\n", dep->name, &req->request)) return -EINVAL; @@ -2165,7 +2173,7 @@ static int dwc3_gadget_ep_dequeue(struct usb_ep *ep, } } - dev_err(dwc->dev, "request %pK was not queued to %s\n", + dev_err(dwc->dev, "request %p was not queued to %s\n", request, ep->name); ret = -EINVAL; out: @@ -3429,14 +3437,53 @@ static int dwc3_gadget_init_endpoint(struct dwc3 *dwc, u8 epnum) return 0; } +static int dwc3_gadget_get_reserved_endpoints(struct dwc3 *dwc, const char *propname, + u8 *eps, u8 num) +{ + u8 count; + int ret; + + if (!device_property_present(dwc->dev, propname)) + return 0; + + ret = device_property_count_u8(dwc->dev, propname); + if (ret < 0) + return ret; + count = ret; + + ret = device_property_read_u8_array(dwc->dev, propname, eps, min(num, count)); + if (ret) + return ret; + + return count; +} + static int dwc3_gadget_init_endpoints(struct dwc3 *dwc, u8 total) { + const char *propname = "snps,reserved-endpoints"; u8 epnum; + u8 reserved_eps[DWC3_ENDPOINTS_NUM]; + u8 count; + u8 num; + int ret; INIT_LIST_HEAD(&dwc->gadget->ep_list); + ret = dwc3_gadget_get_reserved_endpoints(dwc, propname, + reserved_eps, ARRAY_SIZE(reserved_eps)); + if (ret < 0) { + dev_err(dwc->dev, "failed to read %s\n", propname); + return ret; + } + count = ret; + for (epnum = 0; epnum < total; epnum++) { - int ret; + for (num = 0; num < count; num++) { + if (epnum == reserved_eps[num]) + break; + } + if (num < count) + continue; ret = dwc3_gadget_init_endpoint(dwc, epnum); if (ret) @@ -3703,6 +3750,8 @@ static bool dwc3_gadget_endpoint_trbs_complete(struct dwc3_ep *dep, for (i = 0; i < DWC3_ENDPOINTS_NUM; i++) { dep = dwc->eps[i]; + if (!dep) + continue; if (!(dep->flags & DWC3_EP_ENABLED)) continue; @@ -3852,6 +3901,10 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc, u8 epnum = event->endpoint_number; dep = dwc->eps[epnum]; + if (!dep) { + dev_warn(dwc->dev, "spurious event, endpoint %u is not allocated\n", epnum); + return; + } if (!(dep->flags & DWC3_EP_ENABLED)) { if ((epnum > 1) && !(dep->flags & DWC3_EP_TRANSFER_STARTED))
diff --git a/drivers/usb/gadget/function/uvc_queue.c b/drivers/usb/gadget/function/uvc_queue.c index 5eaeae3..9a1bbd7 100644 --- a/drivers/usb/gadget/function/uvc_queue.c +++ b/drivers/usb/gadget/function/uvc_queue.c
@@ -122,8 +122,6 @@ static const struct vb2_ops uvc_queue_qops = { .queue_setup = uvc_queue_setup, .buf_prepare = uvc_buffer_prepare, .buf_queue = uvc_buffer_queue, - .wait_prepare = vb2_ops_wait_prepare, - .wait_finish = vb2_ops_wait_finish, }; int uvcg_queue_init(struct uvc_video_queue *queue, struct device *dev, enum v4l2_buf_type type,
diff --git a/drivers/usb/gadget/legacy/zero.c b/drivers/usb/gadget/legacy/zero.c index e25e0d8..a05785b 100644 --- a/drivers/usb/gadget/legacy/zero.c +++ b/drivers/usb/gadget/legacy/zero.c
@@ -194,7 +194,7 @@ static void zero_suspend(struct usb_composite_dev *cdev) static void zero_resume(struct usb_composite_dev *cdev) { DBG(cdev, "%s\n", __func__); - del_timer(&autoresume_timer); + timer_delete(&autoresume_timer); } /*-------------------------------------------------------------------------*/ @@ -398,7 +398,7 @@ static int zero_bind(struct usb_composite_dev *cdev) static int zero_unbind(struct usb_composite_dev *cdev) { - del_timer_sync(&autoresume_timer); + timer_delete_sync(&autoresume_timer); if (!IS_ERR_OR_NULL(func_ss)) usb_put_function(func_ss); usb_put_function_instance(func_inst_ss);
diff --git a/drivers/usb/gadget/udc/aspeed-vhub/dev.c b/drivers/usb/gadget/udc/aspeed-vhub/dev.c index 573109c..a09f727 100644 --- a/drivers/usb/gadget/udc/aspeed-vhub/dev.c +++ b/drivers/usb/gadget/udc/aspeed-vhub/dev.c
@@ -548,6 +548,9 @@ int ast_vhub_init_dev(struct ast_vhub *vhub, unsigned int idx) d->vhub = vhub; d->index = idx; d->name = devm_kasprintf(parent, GFP_KERNEL, "port%d", idx+1); + if (!d->name) + return -ENOMEM; + d->regs = vhub->regs + 0x100 + 0x10 * idx; ast_vhub_init_ep0(vhub, &d->ep0, d);
diff --git a/drivers/usb/gadget/udc/omap_udc.c b/drivers/usb/gadget/udc/omap_udc.c index 8902abe..c93ea21 100644 --- a/drivers/usb/gadget/udc/omap_udc.c +++ b/drivers/usb/gadget/udc/omap_udc.c
@@ -252,7 +252,7 @@ static int omap_ep_disable(struct usb_ep *_ep) ep->has_dma = 0; omap_writew(UDC_SET_HALT, UDC_CTRL); list_del_init(&ep->iso); - del_timer(&ep->timer); + timer_delete(&ep->timer); spin_unlock_irqrestore(&ep->udc->lock, flags);
diff --git a/drivers/usb/gadget/udc/pxa25x_udc.c b/drivers/usb/gadget/udc/pxa25x_udc.c index 1e99980..24eb1ae 100644 --- a/drivers/usb/gadget/udc/pxa25x_udc.c +++ b/drivers/usb/gadget/udc/pxa25x_udc.c
@@ -1503,7 +1503,7 @@ reset_gadget(struct pxa25x_udc *dev, struct usb_gadget_driver *driver) ep->stopped = 1; nuke(ep, -ESHUTDOWN); } - del_timer_sync(&dev->timer); + timer_delete_sync(&dev->timer); /* report reset; the driver is already quiesced */ if (driver) @@ -1530,7 +1530,7 @@ stop_activity(struct pxa25x_udc *dev, struct usb_gadget_driver *driver) ep->stopped = 1; nuke(ep, -ESHUTDOWN); } - del_timer_sync(&dev->timer); + timer_delete_sync(&dev->timer); /* report disconnect; the driver is already quiesced */ if (driver) @@ -1607,14 +1607,14 @@ static void handle_ep0 (struct pxa25x_udc *dev) if (udccs0 & UDCCS0_SST) { nuke(ep, -EPIPE); udc_ep0_set_UDCCS(dev, UDCCS0_SST); - del_timer(&dev->timer); + timer_delete(&dev->timer); ep0_idle(dev); } /* previous request unfinished? non-error iff back-to-back ... */ if ((udccs0 & UDCCS0_SA) != 0 && dev->ep0state != EP0_IDLE) { nuke(ep, 0); - del_timer(&dev->timer); + timer_delete(&dev->timer); ep0_idle(dev); }
diff --git a/drivers/usb/gadget/udc/r8a66597-udc.c b/drivers/usb/gadget/udc/r8a66597-udc.c index ff6f846..6c1d15b 100644 --- a/drivers/usb/gadget/udc/r8a66597-udc.c +++ b/drivers/usb/gadget/udc/r8a66597-udc.c
@@ -1810,7 +1810,7 @@ static void r8a66597_remove(struct platform_device *pdev) struct r8a66597 *r8a66597 = platform_get_drvdata(pdev); usb_del_gadget_udc(&r8a66597->gadget); - del_timer_sync(&r8a66597->timer); + timer_delete_sync(&r8a66597->timer); r8a66597_free_request(&r8a66597->ep[0].ep, r8a66597->ep0_req); if (r8a66597->pdata->on_chip) {
diff --git a/drivers/usb/gadget/udc/snps_udc_core.c b/drivers/usb/gadget/udc/snps_udc_core.c index 1f8a99d..373942c 100644 --- a/drivers/usb/gadget/udc/snps_udc_core.c +++ b/drivers/usb/gadget/udc/snps_udc_core.c
@@ -3035,12 +3035,12 @@ void udc_remove(struct udc *dev) stop_timer++; if (timer_pending(&udc_timer)) wait_for_completion(&on_exit); - del_timer_sync(&udc_timer); + timer_delete_sync(&udc_timer); /* remove pollstall timer */ stop_pollstall_timer++; if (timer_pending(&udc_pollstall_timer)) wait_for_completion(&on_pollstall_exit); - del_timer_sync(&udc_pollstall_timer); + timer_delete_sync(&udc_pollstall_timer); udc = NULL; } EXPORT_SYMBOL_GPL(udc_remove);
diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c index cdf4188..150d254 100644 --- a/drivers/usb/host/ehci-platform.c +++ b/drivers/usb/host/ehci-platform.c
@@ -224,7 +224,7 @@ static void quirk_poll_init(struct ehci_platform_priv *priv) static void quirk_poll_end(struct ehci_platform_priv *priv) { - del_timer_sync(&priv->poll_timer); + timer_delete_sync(&priv->poll_timer); cancel_delayed_work(&priv->poll_work); }
diff --git a/drivers/usb/host/isp1362-hcd.c b/drivers/usb/host/isp1362-hcd.c index 2d3a082..954fc5a 100644 --- a/drivers/usb/host/isp1362-hcd.c +++ b/drivers/usb/host/isp1362-hcd.c
@@ -2357,7 +2357,7 @@ static void isp1362_hc_stop(struct usb_hcd *hcd) pr_debug("%s:\n", __func__); - del_timer_sync(&hcd->rh_timer); + timer_delete_sync(&hcd->rh_timer); spin_lock_irqsave(&isp1362_hcd->lock, flags);
diff --git a/drivers/usb/host/max3421-hcd.c b/drivers/usb/host/max3421-hcd.c index 0881fdd..dcf31a5 100644 --- a/drivers/usb/host/max3421-hcd.c +++ b/drivers/usb/host/max3421-hcd.c
@@ -1946,6 +1946,12 @@ max3421_remove(struct spi_device *spi) usb_put_hcd(hcd); } +static const struct spi_device_id max3421_spi_ids[] = { + { "max3421" }, + { }, +}; +MODULE_DEVICE_TABLE(spi, max3421_spi_ids); + static const struct of_device_id max3421_of_match_table[] = { { .compatible = "maxim,max3421", }, {}, @@ -1955,6 +1961,7 @@ MODULE_DEVICE_TABLE(of, max3421_of_match_table); static struct spi_driver max3421_driver = { .probe = max3421_probe, .remove = max3421_remove, + .id_table = max3421_spi_ids, .driver = { .name = "max3421-hcd", .of_match_table = max3421_of_match_table,
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 9b24181..c7784bf 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c
@@ -1003,7 +1003,7 @@ static void ohci_stop (struct usb_hcd *hcd) if (quirk_nec(ohci)) flush_work(&ohci->nec_work); - del_timer_sync(&ohci->io_watchdog); + timer_delete_sync(&ohci->io_watchdog); ohci->prev_frame_no = IO_WATCHDOG_OFF; ohci_writel (ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable);
diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c index 90cee19..b3d734a 100644 --- a/drivers/usb/host/ohci-hub.c +++ b/drivers/usb/host/ohci-hub.c
@@ -315,7 +315,7 @@ static int ohci_bus_suspend (struct usb_hcd *hcd) spin_unlock_irq (&ohci->lock); if (rc == 0) { - del_timer_sync(&ohci->io_watchdog); + timer_delete_sync(&ohci->io_watchdog); ohci->prev_frame_no = IO_WATCHDOG_OFF; } return rc;
diff --git a/drivers/usb/host/oxu210hp-hcd.c b/drivers/usb/host/oxu210hp-hcd.c index fce800b..d75b1b9 100644 --- a/drivers/usb/host/oxu210hp-hcd.c +++ b/drivers/usb/host/oxu210hp-hcd.c
@@ -1127,7 +1127,7 @@ static void ehci_mem_cleanup(struct oxu_hcd *oxu) qh_put(oxu->async); oxu->async = NULL; - del_timer(&oxu->urb_timer); + timer_delete(&oxu->urb_timer); oxu->periodic = NULL; @@ -3154,7 +3154,7 @@ static void oxu_stop(struct usb_hcd *hcd) ehci_port_power(oxu, 0); /* no more interrupts ... */ - del_timer_sync(&oxu->watchdog); + timer_delete_sync(&oxu->watchdog); spin_lock_irq(&oxu->lock); if (HC_IS_RUNNING(hcd->state)) @@ -3887,7 +3887,7 @@ static int oxu_bus_suspend(struct usb_hcd *hcd) spin_unlock_irq(&oxu->lock); /* turn off now-idle HC */ - del_timer_sync(&oxu->watchdog); + timer_delete_sync(&oxu->watchdog); spin_lock_irq(&oxu->lock); ehci_halt(oxu); hcd->state = HC_STATE_SUSPENDED;
diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c index a44992e..67e4721 100644 --- a/drivers/usb/host/r8a66597-hcd.c +++ b/drivers/usb/host/r8a66597-hcd.c
@@ -2384,7 +2384,7 @@ static void r8a66597_remove(struct platform_device *pdev) struct r8a66597 *r8a66597 = platform_get_drvdata(pdev); struct usb_hcd *hcd = r8a66597_to_hcd(r8a66597); - del_timer_sync(&r8a66597->rh_timer); + timer_delete_sync(&r8a66597->rh_timer); usb_remove_hcd(hcd); iounmap(r8a66597->reg); if (r8a66597->pdata->on_chip)
diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c index fa2e4ba..718b1b7 100644 --- a/drivers/usb/host/sl811-hcd.c +++ b/drivers/usb/host/sl811-hcd.c
@@ -1515,7 +1515,7 @@ sl811h_stop(struct usb_hcd *hcd) struct sl811 *sl811 = hcd_to_sl811(hcd); unsigned long flags; - del_timer_sync(&hcd->rh_timer); + timer_delete_sync(&hcd->rh_timer); spin_lock_irqsave(&sl811->lock, flags); port_power(sl811, 0);
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index fd2408b..14e6dfe 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c
@@ -716,7 +716,7 @@ static void uhci_stop(struct usb_hcd *hcd) spin_unlock_irq(&uhci->lock); synchronize_irq(hcd->irq); - del_timer_sync(&uhci->fsbr_timer); + timer_delete_sync(&uhci->fsbr_timer); release_uhci(uhci); }
diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c index 35fcb82..45a8256 100644 --- a/drivers/usb/host/uhci-q.c +++ b/drivers/usb/host/uhci-q.c
@@ -84,7 +84,7 @@ static void uhci_urbp_wants_fsbr(struct uhci_hcd *uhci, struct urb_priv *urbp) uhci_fsbr_on(uhci); else if (uhci->fsbr_expiring) { uhci->fsbr_expiring = 0; - del_timer(&uhci->fsbr_timer); + timer_delete(&uhci->fsbr_timer); } } }
diff --git a/drivers/usb/host/xen-hcd.c b/drivers/usb/host/xen-hcd.c index 46fdab9..05943f2 100644 --- a/drivers/usb/host/xen-hcd.c +++ b/drivers/usb/host/xen-hcd.c
@@ -327,7 +327,7 @@ static int xenhcd_bus_suspend(struct usb_hcd *hcd) } spin_unlock_irq(&info->lock); - del_timer_sync(&info->watchdog); + timer_delete_sync(&info->watchdog); return ret; } @@ -1307,7 +1307,7 @@ static void xenhcd_stop(struct usb_hcd *hcd) { struct xenhcd_info *info = xenhcd_hcd_to_info(hcd); - del_timer_sync(&info->watchdog); + timer_delete_sync(&info->watchdog); spin_lock_irq(&info->lock); /* cancel all urbs */ hcd->state = HC_STATE_HALT;
diff --git a/drivers/usb/host/xhci-histb.c b/drivers/usb/host/xhci-histb.c index 8a7d46d..02396c8 100644 --- a/drivers/usb/host/xhci-histb.c +++ b/drivers/usb/host/xhci-histb.c
@@ -355,7 +355,7 @@ static int __maybe_unused xhci_histb_resume(struct device *dev) if (!device_may_wakeup(dev)) xhci_histb_host_enable(histb); - return xhci_resume(xhci, PMSG_RESUME); + return xhci_resume(xhci, false, false); } static const struct dev_pm_ops xhci_histb_pm_ops = {
diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index 69c278b..c0f2265 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c
@@ -926,7 +926,7 @@ static void xhci_del_comp_mod_timer(struct xhci_hcd *xhci, u32 status, if ((xhci->port_status_u0 != all_ports_seen_u0) && port_in_u0) { xhci->port_status_u0 |= 1 << wIndex; if (xhci->port_status_u0 == all_ports_seen_u0) { - del_timer_sync(&xhci->comp_mode_recovery_timer); + timer_delete_sync(&xhci->comp_mode_recovery_timer); xhci_dbg_trace(xhci, trace_xhci_dbg_quirks, "All USB3 ports have entered U0 already!"); xhci_dbg_trace(xhci, trace_xhci_dbg_quirks,
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index fdf0c10..d698095 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c
@@ -1953,7 +1953,6 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci) xhci->interrupters = NULL; xhci->page_size = 0; - xhci->page_shift = 0; xhci->usb2_rhub.bus_state.bus_suspended = 0; xhci->usb3_rhub.bus_state.bus_suspended = 0; } @@ -2372,6 +2371,22 @@ xhci_create_secondary_interrupter(struct usb_hcd *hcd, unsigned int segs, } EXPORT_SYMBOL_GPL(xhci_create_secondary_interrupter); +static void xhci_hcd_page_size(struct xhci_hcd *xhci) +{ + u32 page_size; + + page_size = readl(&xhci->op_regs->page_size) & XHCI_PAGE_SIZE_MASK; + if (!is_power_of_2(page_size)) { + xhci_warn(xhci, "Invalid page size register = 0x%x\n", page_size); + /* Fallback to 4K page size, since that's common */ + page_size = 1; + } + + xhci->page_size = page_size << 12; + xhci_dbg_trace(xhci, trace_xhci_dbg_init, "HCD page size set to %iK", + xhci->page_size >> 10); +} + int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) { struct xhci_interrupter *ir; @@ -2379,7 +2394,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) dma_addr_t dma; unsigned int val, val2; u64 val_64; - u32 page_size, temp; + u32 temp; int i; INIT_LIST_HEAD(&xhci->cmd_list); @@ -2388,20 +2403,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) INIT_DELAYED_WORK(&xhci->cmd_timer, xhci_handle_command_timeout); init_completion(&xhci->cmd_ring_stop_completion); - page_size = readl(&xhci->op_regs->page_size); - xhci_dbg_trace(xhci, trace_xhci_dbg_init, - "Supported page size register = 0x%x", page_size); - i = ffs(page_size); - if (i < 16) - xhci_dbg_trace(xhci, trace_xhci_dbg_init, - "Supported page size of %iK", (1 << (i+12)) / 1024); - else - xhci_warn(xhci, "WARN: no supported page size\n"); - /* Use 4K pages, since that's common and the minimum the HC supports */ - xhci->page_shift = 12; - xhci->page_size = 1 << xhci->page_shift; - xhci_dbg_trace(xhci, trace_xhci_dbg_init, - "HCD page size set to %iK", xhci->page_size / 1024); + xhci_hcd_page_size(xhci); /* * Program the Number of Device Slots Enabled field in the CONFIG
diff --git a/drivers/usb/host/xhci-mtk.c b/drivers/usb/host/xhci-mtk.c index 9048313..208558c 100644 --- a/drivers/usb/host/xhci-mtk.c +++ b/drivers/usb/host/xhci-mtk.c
@@ -746,10 +746,10 @@ static int __maybe_unused xhci_mtk_suspend(struct device *dev) xhci_dbg(xhci, "%s: stop port polling\n", __func__); clear_bit(HCD_FLAG_POLL_RH, &hcd->flags); - del_timer_sync(&hcd->rh_timer); + timer_delete_sync(&hcd->rh_timer); if (shared_hcd) { clear_bit(HCD_FLAG_POLL_RH, &shared_hcd->flags); - del_timer_sync(&shared_hcd->rh_timer); + timer_delete_sync(&shared_hcd->rh_timer); } ret = xhci_mtk_host_disable(mtk);
diff --git a/drivers/usb/host/xhci-mvebu.c b/drivers/usb/host/xhci-mvebu.c index 87f1597..257e4d7 100644 --- a/drivers/usb/host/xhci-mvebu.c +++ b/drivers/usb/host/xhci-mvebu.c
@@ -73,13 +73,3 @@ int xhci_mvebu_mbus_init_quirk(struct usb_hcd *hcd) return 0; } - -int xhci_mvebu_a3700_init_quirk(struct usb_hcd *hcd) -{ - struct xhci_hcd *xhci = hcd_to_xhci(hcd); - - /* Without reset on resume, the HC won't work at all */ - xhci->quirks |= XHCI_RESET_ON_RESUME; - - return 0; -}
diff --git a/drivers/usb/host/xhci-mvebu.h b/drivers/usb/host/xhci-mvebu.h index 3be0217..9d26e22 100644 --- a/drivers/usb/host/xhci-mvebu.h +++ b/drivers/usb/host/xhci-mvebu.h
@@ -12,16 +12,10 @@ struct usb_hcd; #if IS_ENABLED(CONFIG_USB_XHCI_MVEBU) int xhci_mvebu_mbus_init_quirk(struct usb_hcd *hcd); -int xhci_mvebu_a3700_init_quirk(struct usb_hcd *hcd); #else static inline int xhci_mvebu_mbus_init_quirk(struct usb_hcd *hcd) { return 0; } - -static inline int xhci_mvebu_a3700_init_quirk(struct usb_hcd *hcd) -{ - return 0; -} #endif #endif /* __LINUX_XHCI_MVEBU_H */
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index 54460d1..0c481cb 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c
@@ -807,8 +807,10 @@ static int xhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup) static int xhci_pci_resume(struct usb_hcd *hcd, pm_message_t msg) { - struct xhci_hcd *xhci = hcd_to_xhci(hcd); - struct pci_dev *pdev = to_pci_dev(hcd->self.controller); + struct xhci_hcd *xhci = hcd_to_xhci(hcd); + struct pci_dev *pdev = to_pci_dev(hcd->self.controller); + bool power_lost = msg.event == PM_EVENT_RESTORE; + bool is_auto_resume = msg.event == PM_EVENT_AUTO_RESUME; reset_control_reset(xhci->reset); @@ -839,7 +841,7 @@ static int xhci_pci_resume(struct usb_hcd *hcd, pm_message_t msg) if (xhci->quirks & XHCI_PME_STUCK_QUIRK) xhci_pme_quirk(hcd); - return xhci_resume(xhci, msg); + return xhci_resume(xhci, power_lost, is_auto_resume); } static int xhci_pci_poweroff_late(struct usb_hcd *hcd, bool do_wakeup)
diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c index d85ffa9..3155e3a 100644 --- a/drivers/usb/host/xhci-plat.c +++ b/drivers/usb/host/xhci-plat.c
@@ -106,7 +106,7 @@ static const struct xhci_plat_priv xhci_plat_marvell_armada = { }; static const struct xhci_plat_priv xhci_plat_marvell_armada3700 = { - .init_quirk = xhci_mvebu_a3700_init_quirk, + .quirks = XHCI_RESET_ON_RESUME, }; static const struct xhci_plat_priv xhci_plat_brcm = { @@ -479,9 +479,10 @@ static int xhci_plat_suspend(struct device *dev) return 0; } -static int xhci_plat_resume_common(struct device *dev, struct pm_message pmsg) +static int xhci_plat_resume_common(struct device *dev, bool power_lost) { struct usb_hcd *hcd = dev_get_drvdata(dev); + struct xhci_plat_priv *priv = hcd_to_xhci_priv(hcd); struct xhci_hcd *xhci = hcd_to_xhci(hcd); int ret; @@ -501,7 +502,7 @@ static int xhci_plat_resume_common(struct device *dev, struct pm_message pmsg) if (ret) goto disable_clks; - ret = xhci_resume(xhci, pmsg); + ret = xhci_resume(xhci, power_lost || priv->power_lost, false); if (ret) goto disable_clks; @@ -522,12 +523,12 @@ static int xhci_plat_resume_common(struct device *dev, struct pm_message pmsg) static int xhci_plat_resume(struct device *dev) { - return xhci_plat_resume_common(dev, PMSG_RESUME); + return xhci_plat_resume_common(dev, false); } static int xhci_plat_restore(struct device *dev) { - return xhci_plat_resume_common(dev, PMSG_RESTORE); + return xhci_plat_resume_common(dev, true); } static int __maybe_unused xhci_plat_runtime_suspend(struct device *dev) @@ -548,7 +549,7 @@ static int __maybe_unused xhci_plat_runtime_resume(struct device *dev) struct usb_hcd *hcd = dev_get_drvdata(dev); struct xhci_hcd *xhci = hcd_to_xhci(hcd); - return xhci_resume(xhci, PMSG_AUTO_RESUME); + return xhci_resume(xhci, false, true); } const struct dev_pm_ops xhci_plat_pm_ops = {
diff --git a/drivers/usb/host/xhci-plat.h b/drivers/usb/host/xhci-plat.h index 6475130..fe4f95e 100644 --- a/drivers/usb/host/xhci-plat.h +++ b/drivers/usb/host/xhci-plat.h
@@ -15,6 +15,7 @@ struct usb_hcd; struct xhci_plat_priv { const char *firmware_name; unsigned long long quirks; + bool power_lost; void (*plat_start)(struct usb_hcd *); int (*init_quirk)(struct usb_hcd *); int (*suspend_quirk)(struct usb_hcd *);
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 965bffc..5d64c29 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c
@@ -204,6 +204,50 @@ void inc_deq(struct xhci_hcd *xhci, struct xhci_ring *ring) } /* + * If enqueue points at a link TRB, follow links until an ordinary TRB is reached. + * Toggle the cycle bit of passed link TRBs and optionally chain them. + */ +static void inc_enq_past_link(struct xhci_hcd *xhci, struct xhci_ring *ring, u32 chain) +{ + unsigned int link_trb_count = 0; + + while (trb_is_link(ring->enqueue)) { + + /* + * Section 6.4.4.1 of the 0.95 spec says link TRBs cannot have the chain bit + * set, but other sections talk about dealing with the chain bit set. This was + * fixed in the 0.96 specification errata, but we have to assume that all 0.95 + * xHCI hardware can't handle the chain bit being cleared on a link TRB. + * + * On 0.95 and some 0.96 HCs the chain bit is set once at segment initalization + * and never changed here. On all others, modify it as requested by the caller. + */ + if (!xhci_link_chain_quirk(xhci, ring->type)) { + ring->enqueue->link.control &= cpu_to_le32(~TRB_CHAIN); + ring->enqueue->link.control |= cpu_to_le32(chain); + } + + /* Give this link TRB to the hardware */ + wmb(); + ring->enqueue->link.control ^= cpu_to_le32(TRB_CYCLE); + + /* Toggle the cycle bit after the last ring segment. */ + if (link_trb_toggles_cycle(ring->enqueue)) + ring->cycle_state ^= 1; + + ring->enq_seg = ring->enq_seg->next; + ring->enqueue = ring->enq_seg->trbs; + + trace_xhci_inc_enq(ring); + + if (link_trb_count++ > ring->num_segs) { + xhci_warn(xhci, "Link TRB loop at enqueue\n"); + break; + } + } +} + +/* * See Cycle bit rules. SW is the consumer for the event ring only. * * If we've just enqueued a TRB that is in the middle of a TD (meaning the @@ -211,11 +255,6 @@ void inc_deq(struct xhci_hcd *xhci, struct xhci_ring *ring) * If we've enqueued the last TRB in a TD, make sure the following link TRBs * have their chain bit cleared (so that each Link TRB is a separate TD). * - * Section 6.4.4.1 of the 0.95 spec says link TRBs cannot have the chain bit - * set, but other sections talk about dealing with the chain bit set. This was - * fixed in the 0.96 specification errata, but we have to assume that all 0.95 - * xHCI hardware can't handle the chain bit being cleared on a link TRB. - * * @more_trbs_coming: Will you enqueue more TRBs before calling * prepare_transfer()? */ @@ -223,8 +262,6 @@ static void inc_enq(struct xhci_hcd *xhci, struct xhci_ring *ring, bool more_trbs_coming) { u32 chain; - union xhci_trb *next; - unsigned int link_trb_count = 0; chain = le32_to_cpu(ring->enqueue->generic.field[3]) & TRB_CHAIN; @@ -233,48 +270,67 @@ static void inc_enq(struct xhci_hcd *xhci, struct xhci_ring *ring, return; } - next = ++(ring->enqueue); + ring->enqueue++; - /* Update the dequeue pointer further if that was a link TRB */ - while (trb_is_link(next)) { + /* + * If we are in the middle of a TD or the caller plans to enqueue more + * TDs as one transfer (eg. control), traverse any link TRBs right now. + * Otherwise, enqueue can stay on a link until the next prepare_ring(). + * This avoids enqueue entering deq_seg and simplifies ring expansion. + */ + if (trb_is_link(ring->enqueue) && (chain || more_trbs_coming)) + inc_enq_past_link(xhci, ring, chain); +} - /* - * If the caller doesn't plan on enqueueing more TDs before - * ringing the doorbell, then we don't want to give the link TRB - * to the hardware just yet. We'll give the link TRB back in - * prepare_ring() just before we enqueue the TD at the top of - * the ring. - */ - if (!chain && !more_trbs_coming) - break; +/* + * If the suspect DMA address is a TRB in this TD, this function returns that + * TRB's segment. Otherwise it returns 0. + */ +static struct xhci_segment *trb_in_td(struct xhci_td *td, dma_addr_t suspect_dma) +{ + dma_addr_t start_dma; + dma_addr_t end_seg_dma; + dma_addr_t end_trb_dma; + struct xhci_segment *cur_seg; - /* If we're not dealing with 0.95 hardware or isoc rings on - * AMD 0.96 host, carry over the chain bit of the previous TRB - * (which may mean the chain bit is cleared). - */ - if (!xhci_link_chain_quirk(xhci, ring->type)) { - next->link.control &= cpu_to_le32(~TRB_CHAIN); - next->link.control |= cpu_to_le32(chain); + start_dma = xhci_trb_virt_to_dma(td->start_seg, td->start_trb); + cur_seg = td->start_seg; + + do { + if (start_dma == 0) + return NULL; + /* We may get an event for a Link TRB in the middle of a TD */ + end_seg_dma = xhci_trb_virt_to_dma(cur_seg, + &cur_seg->trbs[TRBS_PER_SEGMENT - 1]); + /* If the end TRB isn't in this segment, this is set to 0 */ + end_trb_dma = xhci_trb_virt_to_dma(cur_seg, td->end_trb); + + if (end_trb_dma > 0) { + /* The end TRB is in this segment, so suspect should be here */ + if (start_dma <= end_trb_dma) { + if (suspect_dma >= start_dma && suspect_dma <= end_trb_dma) + return cur_seg; + } else { + /* Case for one segment with + * a TD wrapped around to the top + */ + if ((suspect_dma >= start_dma && + suspect_dma <= end_seg_dma) || + (suspect_dma >= cur_seg->dma && + suspect_dma <= end_trb_dma)) + return cur_seg; + } + return NULL; } - /* Give this link TRB to the hardware */ - wmb(); - next->link.control ^= cpu_to_le32(TRB_CYCLE); + /* Might still be somewhere in this segment */ + if (suspect_dma >= start_dma && suspect_dma <= end_seg_dma) + return cur_seg; - /* Toggle the cycle bit after the last ring segment. */ - if (link_trb_toggles_cycle(next)) - ring->cycle_state ^= 1; + cur_seg = cur_seg->next; + start_dma = xhci_trb_virt_to_dma(cur_seg, &cur_seg->trbs[0]); + } while (cur_seg != td->start_seg); - ring->enq_seg = ring->enq_seg->next; - ring->enqueue = ring->enq_seg->trbs; - next = ring->enqueue; - - trace_xhci_inc_enq(ring); - - if (link_trb_count++ > ring->num_segs) { - xhci_warn(xhci, "%s: Ring link TRB loop\n", __func__); - break; - } - } + return NULL; } /* @@ -505,8 +561,8 @@ void xhci_ring_ep_doorbell(struct xhci_hcd *xhci, * pointer command pending because the device can choose to start any * stream once the endpoint is on the HW schedule. */ - if ((ep_state & EP_STOP_CMD_PENDING) || (ep_state & SET_DEQ_PENDING) || - (ep_state & EP_HALTED) || (ep_state & EP_CLEARING_TT)) + if (ep_state & (EP_STOP_CMD_PENDING | SET_DEQ_PENDING | EP_HALTED | + EP_CLEARING_TT | EP_STALLED)) return; trace_xhci_ring_ep_doorbell(slot_id, DB_VALUE(ep_index, stream_id)); @@ -1014,7 +1070,7 @@ static int xhci_invalidate_cancelled_tds(struct xhci_virt_ep *ep) td->urb->stream_id); hw_deq &= ~0xf; - if (td->cancel_status == TD_HALTED || trb_in_td(xhci, td, hw_deq, false)) { + if (td->cancel_status == TD_HALTED || trb_in_td(td, hw_deq)) { switch (td->cancel_status) { case TD_CLEARED: /* TD is already no-op */ case TD_CLEARING_CACHE: /* set TR deq command already queued */ @@ -1104,7 +1160,7 @@ static struct xhci_td *find_halted_td(struct xhci_virt_ep *ep) hw_deq = xhci_get_hw_deq(ep->xhci, ep->vdev, ep->ep_index, 0); hw_deq &= ~0xf; td = list_first_entry(&ep->ring->td_list, struct xhci_td, td_list); - if (trb_in_td(ep->xhci, td, hw_deq, false)) + if (trb_in_td(td, hw_deq)) return td; } return NULL; @@ -1164,7 +1220,14 @@ static void xhci_handle_cmd_stop_ep(struct xhci_hcd *xhci, int slot_id, */ switch (GET_EP_CTX_STATE(ep_ctx)) { case EP_STATE_HALTED: - xhci_dbg(xhci, "Stop ep completion raced with stall, reset ep\n"); + xhci_dbg(xhci, "Stop ep completion raced with stall\n"); + /* + * If the halt happened before Stop Endpoint failed, its transfer event + * should have already been handled and Reset Endpoint should be pending. + */ + if (ep->ep_state & EP_HALTED) + goto reset_done; + if (ep->ep_state & EP_HAS_STREAMS) { reset_type = EP_SOFT_RESET; } else { @@ -1175,8 +1238,11 @@ static void xhci_handle_cmd_stop_ep(struct xhci_hcd *xhci, int slot_id, } /* reset ep, reset handler cleans up cancelled tds */ err = xhci_handle_halted_endpoint(xhci, ep, td, reset_type); + xhci_dbg(xhci, "Stop ep completion resetting ep, status %d\n", err); if (err) break; +reset_done: + /* Reset EP handler will clean up cancelled TDs */ ep->ep_state &= ~EP_STOP_CMD_PENDING; return; case EP_STATE_STOPPED: @@ -1198,16 +1264,19 @@ static void xhci_handle_cmd_stop_ep(struct xhci_hcd *xhci, int slot_id, * Stopped state, but it will soon change to Running. * * Assume this bug on unexpected Stop Endpoint failures. - * Keep retrying until the EP starts and stops again, on - * chips where this is known to help. Wait for 100ms. + * Keep retrying until the EP starts and stops again. */ - if (time_is_before_jiffies(ep->stop_time + msecs_to_jiffies(100))) - break; fallthrough; case EP_STATE_RUNNING: /* Race, HW handled stop ep cmd before ep was running */ xhci_dbg(xhci, "Stop ep completion ctx error, ctx_state %d\n", GET_EP_CTX_STATE(ep_ctx)); + /* + * Don't retry forever if we guessed wrong or a defective HC never starts + * the EP or says 'Running' but fails the command. We must give back TDs. + */ + if (time_is_before_jiffies(ep->stop_time + msecs_to_jiffies(100))) + break; command = xhci_alloc_command(xhci, false, GFP_ATOMIC); if (!command) { @@ -1332,43 +1401,6 @@ void xhci_hc_died(struct xhci_hcd *xhci) usb_hc_died(xhci_to_hcd(xhci)); } -static void update_ring_for_set_deq_completion(struct xhci_hcd *xhci, - struct xhci_virt_device *dev, - struct xhci_ring *ep_ring, - unsigned int ep_index) -{ - union xhci_trb *dequeue_temp; - - dequeue_temp = ep_ring->dequeue; - - /* If we get two back-to-back stalls, and the first stalled transfer - * ends just before a link TRB, the dequeue pointer will be left on - * the link TRB by the code in the while loop. So we have to update - * the dequeue pointer one segment further, or we'll jump off - * the segment into la-la-land. - */ - if (trb_is_link(ep_ring->dequeue)) { - ep_ring->deq_seg = ep_ring->deq_seg->next; - ep_ring->dequeue = ep_ring->deq_seg->trbs; - } - - while (ep_ring->dequeue != dev->eps[ep_index].queued_deq_ptr) { - /* We have more usable TRBs */ - ep_ring->dequeue++; - if (trb_is_link(ep_ring->dequeue)) { - if (ep_ring->dequeue == - dev->eps[ep_index].queued_deq_ptr) - break; - ep_ring->deq_seg = ep_ring->deq_seg->next; - ep_ring->dequeue = ep_ring->deq_seg->trbs; - } - if (ep_ring->dequeue == dequeue_temp) { - xhci_dbg(xhci, "Unable to find new dequeue pointer\n"); - break; - } - } -} - /* * When we get a completion for a Set Transfer Ring Dequeue Pointer command, * we need to clear the set deq pending flag in the endpoint ring state, so that @@ -1473,8 +1505,8 @@ static void xhci_handle_cmd_set_deq(struct xhci_hcd *xhci, int slot_id, /* Update the ring's dequeue segment and dequeue pointer * to reflect the new position. */ - update_ring_for_set_deq_completion(xhci, ep->vdev, - ep_ring, ep_index); + ep_ring->deq_seg = ep->queued_deq_seg; + ep_ring->dequeue = ep->queued_deq_ptr; } else { xhci_warn(xhci, "Mismatch between completed Set TR Deq Ptr command & xHCI internal state.\n"); xhci_warn(xhci, "ep deq seg = %p, deq ptr = %p\n", @@ -2116,67 +2148,6 @@ static void handle_port_status(struct xhci_hcd *xhci, union xhci_trb *event) spin_lock(&xhci->lock); } -/* - * If the suspect DMA address is a TRB in this TD, this function returns that - * TRB's segment. Otherwise it returns 0. - */ -struct xhci_segment *trb_in_td(struct xhci_hcd *xhci, struct xhci_td *td, dma_addr_t suspect_dma, - bool debug) -{ - dma_addr_t start_dma; - dma_addr_t end_seg_dma; - dma_addr_t end_trb_dma; - struct xhci_segment *cur_seg; - - start_dma = xhci_trb_virt_to_dma(td->start_seg, td->start_trb); - cur_seg = td->start_seg; - - do { - if (start_dma == 0) - return NULL; - /* We may get an event for a Link TRB in the middle of a TD */ - end_seg_dma = xhci_trb_virt_to_dma(cur_seg, - &cur_seg->trbs[TRBS_PER_SEGMENT - 1]); - /* If the end TRB isn't in this segment, this is set to 0 */ - end_trb_dma = xhci_trb_virt_to_dma(cur_seg, td->end_trb); - - if (debug) - xhci_warn(xhci, - "Looking for event-dma %016llx trb-start %016llx trb-end %016llx seg-start %016llx seg-end %016llx\n", - (unsigned long long)suspect_dma, - (unsigned long long)start_dma, - (unsigned long long)end_trb_dma, - (unsigned long long)cur_seg->dma, - (unsigned long long)end_seg_dma); - - if (end_trb_dma > 0) { - /* The end TRB is in this segment, so suspect should be here */ - if (start_dma <= end_trb_dma) { - if (suspect_dma >= start_dma && suspect_dma <= end_trb_dma) - return cur_seg; - } else { - /* Case for one segment with - * a TD wrapped around to the top - */ - if ((suspect_dma >= start_dma && - suspect_dma <= end_seg_dma) || - (suspect_dma >= cur_seg->dma && - suspect_dma <= end_trb_dma)) - return cur_seg; - } - return NULL; - } else { - /* Might still be somewhere in this segment */ - if (suspect_dma >= start_dma && suspect_dma <= end_seg_dma) - return cur_seg; - } - cur_seg = cur_seg->next; - start_dma = xhci_trb_virt_to_dma(cur_seg, &cur_seg->trbs[0]); - } while (cur_seg != td->start_seg); - - return NULL; -} - static void xhci_clear_hub_tt_buffer(struct xhci_hcd *xhci, struct xhci_td *td, struct xhci_virt_ep *ep) { @@ -2476,6 +2447,12 @@ static void process_isoc_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep, if (ep_trb != td->end_trb) td->error_mid_td = true; break; + case COMP_MISSED_SERVICE_ERROR: + frame->status = -EXDEV; + sum_trbs_for_length = true; + if (ep_trb != td->end_trb) + td->error_mid_td = true; + break; case COMP_INCOMPATIBLE_DEVICE_ERROR: case COMP_STALL_ERROR: frame->status = -EPROTO; @@ -2596,6 +2573,9 @@ static void process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep, xhci_handle_halted_endpoint(xhci, ep, td, EP_SOFT_RESET); return; + case COMP_STALL_ERROR: + ep->ep_state |= EP_STALLED; + break; default: /* do nothing */ break; @@ -2644,6 +2624,22 @@ static int handle_transferless_tx_event(struct xhci_hcd *xhci, struct xhci_virt_ return 0; } +static bool xhci_spurious_success_tx_event(struct xhci_hcd *xhci, + struct xhci_ring *ring) +{ + switch (ring->old_trb_comp_code) { + case COMP_SHORT_PACKET: + return xhci->quirks & XHCI_SPURIOUS_SUCCESS; + case COMP_USB_TRANSACTION_ERROR: + case COMP_BABBLE_DETECTED_ERROR: + case COMP_ISOCH_BUFFER_OVERRUN: + return xhci->quirks & XHCI_ETRON_HOST && + ring->type == TYPE_ISOC; + default: + return false; + } +} + /* * If this function returns an error condition, it means it got a Transfer * event with a corrupted Slot ID, Endpoint ID, or TRB DMA address. @@ -2664,6 +2660,7 @@ static int handle_tx_event(struct xhci_hcd *xhci, int status = -EINPROGRESS; struct xhci_ep_ctx *ep_ctx; u32 trb_comp_code; + bool ring_xrun_event = false; slot_id = TRB_TO_SLOT_ID(le32_to_cpu(event->flags)); ep_index = TRB_TO_EP_ID(le32_to_cpu(event->flags)) - 1; @@ -2697,8 +2694,8 @@ static int handle_tx_event(struct xhci_hcd *xhci, case COMP_SUCCESS: if (EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) { trb_comp_code = COMP_SHORT_PACKET; - xhci_dbg(xhci, "Successful completion on short TX for slot %u ep %u with last td short %d\n", - slot_id, ep_index, ep_ring->last_td_was_short); + xhci_dbg(xhci, "Successful completion on short TX for slot %u ep %u with last td comp code %d\n", + slot_id, ep_index, ep_ring->old_trb_comp_code); } break; case COMP_SHORT_PACKET: @@ -2770,14 +2767,12 @@ static int handle_tx_event(struct xhci_hcd *xhci, * Underrun Event for OUT Isoch endpoint. */ xhci_dbg(xhci, "Underrun event on slot %u ep %u\n", slot_id, ep_index); - if (ep->skip) - break; - return 0; + ring_xrun_event = true; + break; case COMP_RING_OVERRUN: xhci_dbg(xhci, "Overrun event on slot %u ep %u\n", slot_id, ep_index); - if (ep->skip) - break; - return 0; + ring_xrun_event = true; + break; case COMP_MISSED_SERVICE_ERROR: /* * When encounter missed service error, one or more isoc tds @@ -2787,9 +2782,9 @@ static int handle_tx_event(struct xhci_hcd *xhci, */ ep->skip = true; xhci_dbg(xhci, - "Miss service interval error for slot %u ep %u, set skip flag\n", - slot_id, ep_index); - return 0; + "Miss service interval error for slot %u ep %u, set skip flag%s\n", + slot_id, ep_index, ep_trb_dma ? ", skip now" : ""); + break; case COMP_NO_PING_RESPONSE_ERROR: ep->skip = true; xhci_dbg(xhci, @@ -2832,11 +2827,15 @@ static int handle_tx_event(struct xhci_hcd *xhci, */ td = list_first_entry_or_null(&ep_ring->td_list, struct xhci_td, td_list); - if (td && td->error_mid_td && !trb_in_td(xhci, td, ep_trb_dma, false)) { + if (td && td->error_mid_td && !trb_in_td(td, ep_trb_dma)) { xhci_dbg(xhci, "Missing TD completion event after mid TD error\n"); xhci_dequeue_td(xhci, td, ep_ring, td->status); } + /* If the TRB pointer is NULL, missed TDs will be skipped on the next event */ + if (trb_comp_code == COMP_MISSED_SERVICE_ERROR && !ep_trb_dma) + return 0; + if (list_empty(&ep_ring->td_list)) { /* * Don't print wanings if ring is empty due to a stopped endpoint generating an @@ -2846,7 +2845,8 @@ static int handle_tx_event(struct xhci_hcd *xhci, */ if (trb_comp_code != COMP_STOPPED && trb_comp_code != COMP_STOPPED_LENGTH_INVALID && - !ep_ring->last_td_was_short) { + !ring_xrun_event && + !xhci_spurious_success_tx_event(xhci, ep_ring)) { xhci_warn(xhci, "Event TRB for slot %u ep %u with no TDs queued\n", slot_id, ep_index); } @@ -2860,14 +2860,31 @@ static int handle_tx_event(struct xhci_hcd *xhci, td_list); /* Is this a TRB in the currently executing TD? */ - ep_seg = trb_in_td(xhci, td, ep_trb_dma, false); + ep_seg = trb_in_td(td, ep_trb_dma); if (!ep_seg) { if (ep->skip && usb_endpoint_xfer_isoc(&td->urb->ep->desc)) { + /* this event is unlikely to match any TD, don't skip them all */ + if (trb_comp_code == COMP_STOPPED_LENGTH_INVALID) + return 0; + skip_isoc_td(xhci, td, ep, status); - if (!list_empty(&ep_ring->td_list)) + + if (!list_empty(&ep_ring->td_list)) { + if (ring_xrun_event) { + /* + * If we are here, we are on xHCI 1.0 host with no + * idea how many TDs were missed or where the xrun + * occurred. New TDs may have been added after the + * xrun, so skip only one TD to be safe. + */ + xhci_dbg(xhci, "Skipped one TD for slot %u ep %u", + slot_id, ep_index); + return 0; + } continue; + } xhci_dbg(xhci, "All TDs skipped for slot %u ep %u. Clear skip flag.\n", slot_id, ep_index); @@ -2876,6 +2893,10 @@ static int handle_tx_event(struct xhci_hcd *xhci, goto check_endpoint_halted; } + /* TD was queued after xrun, maybe xrun was on a link, don't panic yet */ + if (ring_xrun_event) + return 0; + /* * Skip the Force Stopped Event. The 'ep_trb' of FSE is not in the current * TD pointed by 'ep_ring->dequeue' because that the hardware dequeue @@ -2890,21 +2911,17 @@ static int handle_tx_event(struct xhci_hcd *xhci, /* * Some hosts give a spurious success event after a short - * transfer. Ignore it. + * transfer or error on last TRB. Ignore it. */ - if ((xhci->quirks & XHCI_SPURIOUS_SUCCESS) && - ep_ring->last_td_was_short) { - ep_ring->last_td_was_short = false; + if (xhci_spurious_success_tx_event(xhci, ep_ring)) { + xhci_dbg(xhci, "Spurious event dma %pad, comp_code %u after %u\n", + &ep_trb_dma, trb_comp_code, ep_ring->old_trb_comp_code); + ep_ring->old_trb_comp_code = trb_comp_code; return 0; } /* HC is busted, give up! */ - xhci_err(xhci, - "ERROR Transfer event TRB DMA ptr not part of current TD ep_index %d comp_code %u\n", - ep_index, trb_comp_code); - trb_in_td(xhci, td, ep_trb_dma, true); - - return -ESHUTDOWN; + goto debug_finding_td; } if (ep->skip) { @@ -2922,10 +2939,11 @@ static int handle_tx_event(struct xhci_hcd *xhci, */ } while (ep->skip); - if (trb_comp_code == COMP_SHORT_PACKET) - ep_ring->last_td_was_short = true; - else - ep_ring->last_td_was_short = false; + ep_ring->old_trb_comp_code = trb_comp_code; + + /* Get out if a TD was queued at enqueue after the xrun occurred */ + if (ring_xrun_event) + return 0; ep_trb = &ep_seg->trbs[(ep_trb_dma - ep_seg->dma) / sizeof(*ep_trb)]; trace_xhci_handle_transfer(ep_ring, (struct xhci_generic_trb *) ep_trb, ep_trb_dma); @@ -2957,6 +2975,17 @@ static int handle_tx_event(struct xhci_hcd *xhci, return 0; +debug_finding_td: + xhci_err(xhci, "Event dma %pad for ep %d status %d not part of TD at %016llx - %016llx\n", + &ep_trb_dma, ep_index, trb_comp_code, + (unsigned long long)xhci_trb_virt_to_dma(td->start_seg, td->start_trb), + (unsigned long long)xhci_trb_virt_to_dma(td->end_seg, td->end_trb)); + + xhci_for_each_ring_seg(ep_ring->first_seg, ep_seg) + xhci_warn(xhci, "Ring seg %u dma %pad\n", ep_seg->num, &ep_seg->dma); + + return -ESHUTDOWN; + err_out: xhci_err(xhci, "@%016llx %08x %08x %08x %08x\n", (unsigned long long) xhci_trb_virt_to_dma( @@ -3216,7 +3245,6 @@ static void queue_trb(struct xhci_hcd *xhci, struct xhci_ring *ring, static int prepare_ring(struct xhci_hcd *xhci, struct xhci_ring *ep_ring, u32 ep_state, unsigned int num_trbs, gfp_t mem_flags) { - unsigned int link_trb_count = 0; unsigned int new_segs = 0; /* Make sure the endpoint has been added to xHC schedule */ @@ -3264,33 +3292,9 @@ static int prepare_ring(struct xhci_hcd *xhci, struct xhci_ring *ep_ring, } } - while (trb_is_link(ep_ring->enqueue)) { - /* If we're not dealing with 0.95 hardware or isoc rings - * on AMD 0.96 host, clear the chain bit. - */ - if (!xhci_link_chain_quirk(xhci, ep_ring->type)) - ep_ring->enqueue->link.control &= - cpu_to_le32(~TRB_CHAIN); - else - ep_ring->enqueue->link.control |= - cpu_to_le32(TRB_CHAIN); - - wmb(); - ep_ring->enqueue->link.control ^= cpu_to_le32(TRB_CYCLE); - - /* Toggle the cycle bit after the last ring segment. */ - if (link_trb_toggles_cycle(ep_ring->enqueue)) - ep_ring->cycle_state ^= 1; - - ep_ring->enq_seg = ep_ring->enq_seg->next; - ep_ring->enqueue = ep_ring->enq_seg->trbs; - - /* prevent infinite loop if all first trbs are link trbs */ - if (link_trb_count++ > ep_ring->num_segs) { - xhci_warn(xhci, "Ring is an endless link TRB loop\n"); - return -EINVAL; - } - } + /* Ensure that new TRBs won't overwrite a link */ + if (trb_is_link(ep_ring->enqueue)) + inc_enq_past_link(xhci, ep_ring, 0); if (last_trb_on_seg(ep_ring->enq_seg, ep_ring->enqueue)) { xhci_warn(xhci, "Missing link TRB at end of ring segment\n");
diff --git a/drivers/usb/host/xhci-tegra.c b/drivers/usb/host/xhci-tegra.c index 22dc86f..b5c362c 100644 --- a/drivers/usb/host/xhci-tegra.c +++ b/drivers/usb/host/xhci-tegra.c
@@ -2162,11 +2162,11 @@ static void tegra_xhci_program_utmi_power_lp0_exit(struct tegra_xusb *tegra) } } -static int tegra_xusb_enter_elpg(struct tegra_xusb *tegra, bool runtime) +static int tegra_xusb_enter_elpg(struct tegra_xusb *tegra, bool is_auto_resume) { struct xhci_hcd *xhci = hcd_to_xhci(tegra->hcd); struct device *dev = tegra->dev; - bool wakeup = runtime ? true : device_may_wakeup(dev); + bool wakeup = is_auto_resume ? true : device_may_wakeup(dev); unsigned int i; int err; u32 usbcmd; @@ -2232,11 +2232,11 @@ static int tegra_xusb_enter_elpg(struct tegra_xusb *tegra, bool runtime) return err; } -static int tegra_xusb_exit_elpg(struct tegra_xusb *tegra, bool runtime) +static int tegra_xusb_exit_elpg(struct tegra_xusb *tegra, bool is_auto_resume) { struct xhci_hcd *xhci = hcd_to_xhci(tegra->hcd); struct device *dev = tegra->dev; - bool wakeup = runtime ? true : device_may_wakeup(dev); + bool wakeup = is_auto_resume ? true : device_may_wakeup(dev); unsigned int i; u32 usbcmd; int err; @@ -2287,7 +2287,7 @@ static int tegra_xusb_exit_elpg(struct tegra_xusb *tegra, bool runtime) if (wakeup) tegra_xhci_disable_phy_sleepwalk(tegra); - err = xhci_resume(xhci, runtime ? PMSG_AUTO_RESUME : PMSG_RESUME); + err = xhci_resume(xhci, false, is_auto_resume); if (err < 0) { dev_err(tegra->dev, "failed to resume XHCI: %d\n", err); goto disable_phy;
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 1a90ebc..0452b8d 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c
@@ -627,7 +627,7 @@ void xhci_stop(struct usb_hcd *hcd) /* Deleting Compliance Mode Recovery Timer */ if ((xhci->quirks & XHCI_COMP_MODE_QUIRK) && (!(xhci_all_ports_seen_u0(xhci)))) { - del_timer_sync(&xhci->comp_mode_recovery_timer); + timer_delete_sync(&xhci->comp_mode_recovery_timer); xhci_dbg_trace(xhci, trace_xhci_dbg_quirks, "%s: compliance mode recovery timer deleted", __func__); @@ -672,11 +672,11 @@ void xhci_shutdown(struct usb_hcd *hcd) xhci_dbg(xhci, "%s: stopping usb%d port polling.\n", __func__, hcd->self.busnum); clear_bit(HCD_FLAG_POLL_RH, &hcd->flags); - del_timer_sync(&hcd->rh_timer); + timer_delete_sync(&hcd->rh_timer); if (xhci->shared_hcd) { clear_bit(HCD_FLAG_POLL_RH, &xhci->shared_hcd->flags); - del_timer_sync(&xhci->shared_hcd->rh_timer); + timer_delete_sync(&xhci->shared_hcd->rh_timer); } spin_lock_irq(&xhci->lock); @@ -908,10 +908,10 @@ int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup) xhci_dbg(xhci, "%s: stopping usb%d port polling.\n", __func__, hcd->self.busnum); clear_bit(HCD_FLAG_POLL_RH, &hcd->flags); - del_timer_sync(&hcd->rh_timer); + timer_delete_sync(&hcd->rh_timer); if (xhci->shared_hcd) { clear_bit(HCD_FLAG_POLL_RH, &xhci->shared_hcd->flags); - del_timer_sync(&xhci->shared_hcd->rh_timer); + timer_delete_sync(&xhci->shared_hcd->rh_timer); } if (xhci->quirks & XHCI_SUSPEND_DELAY) @@ -978,7 +978,7 @@ int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup) */ if ((xhci->quirks & XHCI_COMP_MODE_QUIRK) && (!(xhci_all_ports_seen_u0(xhci)))) { - del_timer_sync(&xhci->comp_mode_recovery_timer); + timer_delete_sync(&xhci->comp_mode_recovery_timer); xhci_dbg_trace(xhci, trace_xhci_dbg_quirks, "%s: compliance mode recovery timer deleted", __func__); @@ -994,16 +994,14 @@ EXPORT_SYMBOL_GPL(xhci_suspend); * This is called when the machine transition from S3/S4 mode. * */ -int xhci_resume(struct xhci_hcd *xhci, pm_message_t msg) +int xhci_resume(struct xhci_hcd *xhci, bool power_lost, bool is_auto_resume) { - bool hibernated = (msg.event == PM_EVENT_RESTORE); u32 command, temp = 0; struct usb_hcd *hcd = xhci_to_hcd(xhci); int retval = 0; bool comp_timer_running = false; bool pending_portevent = false; bool suspended_usb3_devs = false; - bool reinit_xhc = false; if (!hcd->state) return 0; @@ -1022,10 +1020,10 @@ int xhci_resume(struct xhci_hcd *xhci, pm_message_t msg) spin_lock_irq(&xhci->lock); - if (hibernated || xhci->quirks & XHCI_RESET_ON_RESUME || xhci->broken_suspend) - reinit_xhc = true; + if (xhci->quirks & XHCI_RESET_ON_RESUME || xhci->broken_suspend) + power_lost = true; - if (!reinit_xhc) { + if (!power_lost) { /* * Some controllers might lose power during suspend, so wait * for controller not ready bit to clear, just as in xHC init. @@ -1065,15 +1063,15 @@ int xhci_resume(struct xhci_hcd *xhci, pm_message_t msg) /* re-initialize the HC on Restore Error, or Host Controller Error */ if ((temp & (STS_SRE | STS_HCE)) && !(xhci->xhc_state & XHCI_STATE_REMOVING)) { - reinit_xhc = true; - if (!xhci->broken_suspend) + if (!power_lost) xhci_warn(xhci, "xHC error in resume, USBSTS 0x%x, Reinit\n", temp); + power_lost = true; } - if (reinit_xhc) { + if (power_lost) { if ((xhci->quirks & XHCI_COMP_MODE_QUIRK) && !(xhci_all_ports_seen_u0(xhci))) { - del_timer_sync(&xhci->comp_mode_recovery_timer); + timer_delete_sync(&xhci->comp_mode_recovery_timer); xhci_dbg_trace(xhci, trace_xhci_dbg_quirks, "Compliance Mode Recovery Timer deleted!"); } @@ -1168,8 +1166,7 @@ int xhci_resume(struct xhci_hcd *xhci, pm_message_t msg) pending_portevent = xhci_pending_portevent(xhci); - if (suspended_usb3_devs && !pending_portevent && - msg.event == PM_EVENT_AUTO_RESUME) { + if (suspended_usb3_devs && !pending_portevent && is_auto_resume) { msleep(120); pending_portevent = xhci_pending_portevent(xhci); } @@ -1608,6 +1605,11 @@ static int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flag goto free_priv; } + /* Class driver might not be aware ep halted due to async URB giveback */ + if (*ep_state & EP_STALLED) + dev_dbg(&urb->dev->dev, "URB %p queued before clearing halt\n", + urb); + switch (usb_endpoint_type(&urb->ep->desc)) { case USB_ENDPOINT_XFER_CONTROL: @@ -1768,8 +1770,8 @@ static int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) goto done; } - /* In this case no commands are pending but the endpoint is stopped */ - if (ep->ep_state & EP_CLEARING_TT) { + /* In these cases no commands are pending but the endpoint is stopped */ + if (ep->ep_state & (EP_CLEARING_TT | EP_STALLED)) { /* and cancelled TDs can be given back right away */ xhci_dbg(xhci, "Invalidating TDs instantly on slot %d ep %d in state 0x%x\n", urb->dev->slot_id, ep_index, ep->ep_state); @@ -3207,8 +3209,11 @@ static void xhci_endpoint_reset(struct usb_hcd *hcd, ep = &vdev->eps[ep_index]; - /* Bail out if toggle is already being cleared by a endpoint reset */ spin_lock_irqsave(&xhci->lock, flags); + + ep->ep_state &= ~EP_STALLED; + + /* Bail out if toggle is already being cleared by a endpoint reset */ if (ep->ep_state & EP_HARD_CLEAR_TOGGLE) { ep->ep_state &= ~EP_HARD_CLEAR_TOGGLE; spin_unlock_irqrestore(&xhci->lock, flags); @@ -4759,8 +4764,8 @@ static u16 xhci_calculate_u1_timeout(struct xhci_hcd *xhci, */ if (timeout_ns <= USB3_LPM_U1_MAX_TIMEOUT) return timeout_ns; - dev_dbg(&udev->dev, "Hub-initiated U1 disabled " - "due to long timeout %llu ms\n", timeout_ns); + dev_dbg(&udev->dev, "Hub-initiated U1 disabled due to long timeout %lluus\n", + timeout_ns); return xhci_get_timeout_no_hub_lpm(udev, USB3_LPM_U1); } @@ -4817,8 +4822,8 @@ static u16 xhci_calculate_u2_timeout(struct xhci_hcd *xhci, */ if (timeout_ns <= USB3_LPM_U2_MAX_TIMEOUT) return timeout_ns; - dev_dbg(&udev->dev, "Hub-initiated U2 disabled " - "due to long timeout %llu ms\n", timeout_ns); + dev_dbg(&udev->dev, "Hub-initiated U2 disabled due to long timeout %lluus\n", + timeout_ns * 256); return xhci_get_timeout_no_hub_lpm(udev, USB3_LPM_U2); }
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 779b01d..37860f1 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h
@@ -211,6 +211,9 @@ struct xhci_op_regs { #define CONFIG_CIE (1 << 9) /* bits 10:31 - reserved and should be preserved */ +/* bits 15:0 - HCD page shift bit */ +#define XHCI_PAGE_SIZE_MASK 0xffff + /** * struct xhci_intr_reg - Interrupt Register Set * @irq_pending: IMAN - Interrupt Management Register. Used to enable @@ -661,7 +664,7 @@ struct xhci_virt_ep { unsigned int err_count; unsigned int ep_state; #define SET_DEQ_PENDING (1 << 0) -#define EP_HALTED (1 << 1) /* For stall handling */ +#define EP_HALTED (1 << 1) /* Halted host ep handling */ #define EP_STOP_CMD_PENDING (1 << 2) /* For URB cancellation */ /* Transitioning the endpoint to using streams, don't enqueue URBs */ #define EP_GETTING_STREAMS (1 << 3) @@ -672,6 +675,7 @@ struct xhci_virt_ep { #define EP_SOFT_CLEAR_TOGGLE (1 << 7) /* usb_hub_clear_tt_buffer is in progress */ #define EP_CLEARING_TT (1 << 8) +#define EP_STALLED (1 << 9) /* For stall handling */ /* ---- Related to URB cancellation ---- */ struct list_head cancelled_td_list; struct xhci_hcd *xhci; @@ -1371,7 +1375,7 @@ struct xhci_ring { unsigned int num_trbs_free; /* used only by xhci DbC */ unsigned int bounce_buf_len; enum xhci_ring_type type; - bool last_td_was_short; + u32 old_trb_comp_code; struct radix_tree_root *trb_address_map; }; @@ -1514,10 +1518,7 @@ struct xhci_hcd { u16 max_interrupters; /* imod_interval in ns (I * 250ns) */ u32 imod_interval; - /* 4KB min, 128MB max */ - int page_size; - /* Valid values are 12 to 20, inclusive */ - int page_shift; + u32 page_size; /* MSI-X/MSI vectors */ int nvecs; /* optional clocks */ @@ -1759,11 +1760,20 @@ static inline void xhci_write_64(struct xhci_hcd *xhci, } -/* Link TRB chain should always be set on 0.95 hosts, and AMD 0.96 ISOC rings */ +/* + * Reportedly, some chapters of v0.95 spec said that Link TRB always has its chain bit set. + * Other chapters and later specs say that it should only be set if the link is inside a TD + * which continues from the end of one segment to the next segment. + * + * Some 0.95 hardware was found to misbehave if any link TRB doesn't have the chain bit set. + * + * 0.96 hardware from AMD and NEC was found to ignore unchained isochronous link TRBs when + * "resynchronizing the pipe" after a Missed Service Error. + */ static inline bool xhci_link_chain_quirk(struct xhci_hcd *xhci, enum xhci_ring_type type) { return (xhci->quirks & XHCI_LINK_TRB_QUIRK) || - (type == TYPE_ISOC && (xhci->quirks & XHCI_AMD_0x96_HOST)); + (type == TYPE_ISOC && (xhci->quirks & (XHCI_AMD_0x96_HOST | XHCI_NEC_HOST))); } /* xHCI debugging */ @@ -1870,7 +1880,7 @@ int xhci_disable_slot(struct xhci_hcd *xhci, u32 slot_id); int xhci_ext_cap_init(struct xhci_hcd *xhci); int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup); -int xhci_resume(struct xhci_hcd *xhci, pm_message_t msg); +int xhci_resume(struct xhci_hcd *xhci, bool power_lost, bool is_auto_resume); irqreturn_t xhci_irq(struct usb_hcd *hcd); irqreturn_t xhci_msi_irq(int irq, void *hcd); @@ -1884,8 +1894,6 @@ int xhci_set_interrupter_moderation(struct xhci_interrupter *ir, /* xHCI ring, segment, TRB, and TD functions */ dma_addr_t xhci_trb_virt_to_dma(struct xhci_segment *seg, union xhci_trb *trb); -struct xhci_segment *trb_in_td(struct xhci_hcd *xhci, struct xhci_td *td, - dma_addr_t suspect_dma, bool debug); int xhci_is_vendor_info_code(struct xhci_hcd *xhci, unsigned int trb_comp_code); void xhci_ring_cmd_db(struct xhci_hcd *xhci); int xhci_queue_slot_control(struct xhci_hcd *xhci, struct xhci_command *cmd,
diff --git a/drivers/usb/isp1760/isp1760-hcd.c b/drivers/usb/isp1760/isp1760-hcd.c index add2d2e..8dcd9cc 100644 --- a/drivers/usb/isp1760/isp1760-hcd.c +++ b/drivers/usb/isp1760/isp1760-hcd.c
@@ -2458,7 +2458,7 @@ static void isp1760_stop(struct usb_hcd *hcd) { struct isp1760_hcd *priv = hcd_to_priv(hcd); - del_timer(&errata2_timer); + timer_delete(&errata2_timer); isp1760_hub_control(hcd, ClearPortFeature, USB_PORT_FEAT_POWER, 1, NULL, 0);
diff --git a/drivers/usb/isp1760/isp1760-udc.c b/drivers/usb/isp1760/isp1760-udc.c index 5cafd23..2af89ee 100644 --- a/drivers/usb/isp1760/isp1760-udc.c +++ b/drivers/usb/isp1760/isp1760-udc.c
@@ -1145,7 +1145,7 @@ static void isp1760_udc_disconnect(struct isp1760_udc *udc) if (udc->driver->disconnect) udc->driver->disconnect(&udc->gadget); - del_timer(&udc->vbus_timer); + timer_delete(&udc->vbus_timer); /* TODO Reset all endpoints ? */ } @@ -1314,7 +1314,7 @@ static int isp1760_udc_stop(struct usb_gadget *gadget) dev_dbg(udc->isp->dev, "%s\n", __func__); - del_timer_sync(&udc->vbus_timer); + timer_delete_sync(&udc->vbus_timer); isp1760_reg_write(udc->regs, mode_reg, 0);
diff --git a/drivers/usb/misc/onboard_usb_dev.h b/drivers/usb/misc/onboard_usb_dev.h index 317b3eb..933797a7 100644 --- a/drivers/usb/misc/onboard_usb_dev.h +++ b/drivers/usb/misc/onboard_usb_dev.h
@@ -23,6 +23,13 @@ static const struct onboard_dev_pdata microchip_usb424_data = { .is_hub = true, }; +static const struct onboard_dev_pdata microchip_usb2514_data = { + .reset_us = 1, + .num_supplies = 2, + .supply_names = { "vdd", "vdda" }, + .is_hub = true, +}; + static const struct onboard_dev_pdata microchip_usb5744_data = { .reset_us = 0, .power_on_delay_us = 10000, @@ -96,7 +103,7 @@ static const struct onboard_dev_pdata xmos_xvf3500_data = { static const struct of_device_id onboard_dev_match[] = { { .compatible = "usb424,2412", .data = µchip_usb424_data, }, - { .compatible = "usb424,2514", .data = µchip_usb424_data, }, + { .compatible = "usb424,2514", .data = µchip_usb2514_data, }, { .compatible = "usb424,2517", .data = µchip_usb424_data, }, { .compatible = "usb424,2744", .data = µchip_usb5744_data, }, { .compatible = "usb424,5744", .data = µchip_usb5744_data, },
diff --git a/drivers/usb/misc/usb251xb.c b/drivers/usb/misc/usb251xb.c index e24cdb6..4fb453c 100644 --- a/drivers/usb/misc/usb251xb.c +++ b/drivers/usb/misc/usb251xb.c
@@ -636,10 +636,8 @@ static int usb251xb_probe(struct usb251xb *hub) if (np && usb_data) { err = usb251xb_get_ofdata(hub, usb_data); - if (err) { - dev_err(dev, "failed to get ofdata: %d\n", err); - return err; - } + if (err) + return dev_err_probe(dev, err, "failed to get ofdata\n"); } /*
diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c index 8d379ae..853a5f0 100644 --- a/drivers/usb/misc/usbtest.c +++ b/drivers/usb/misc/usbtest.c
@@ -626,7 +626,7 @@ static int perform_sglist( mod_timer(&timeout.timer, jiffies + msecs_to_jiffies(SIMPLE_IO_TIMEOUT)); usb_sg_wait(req); - if (!del_timer_sync(&timeout.timer)) + if (!timer_delete_sync(&timeout.timer)) retval = -ETIMEDOUT; else retval = req->status;
diff --git a/drivers/usb/musb/da8xx.c b/drivers/usb/musb/da8xx.c index 26fd71a..eebb24a 100644 --- a/drivers/usb/musb/da8xx.c +++ b/drivers/usb/musb/da8xx.c
@@ -204,7 +204,7 @@ static void __maybe_unused da8xx_musb_try_idle(struct musb *musb, unsigned long musb->xceiv->otg->state == OTG_STATE_A_WAIT_BCON)) { dev_dbg(musb->controller, "%s active, deleting timer\n", usb_otg_state_string(musb->xceiv->otg->state)); - del_timer(&musb->dev_timer); + timer_delete(&musb->dev_timer); last_timer = jiffies; return; } @@ -290,7 +290,7 @@ static irqreturn_t da8xx_musb_interrupt(int irq, void *hci) MUSB_HST_MODE(musb); musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE; portstate(musb->port1_status |= USB_PORT_STAT_POWER); - del_timer(&musb->dev_timer); + timer_delete(&musb->dev_timer); } else if (!(musb->int_usb & MUSB_INTR_BABBLE)) { /* * When babble condition happens, drvvbus interrupt @@ -419,7 +419,7 @@ static int da8xx_musb_exit(struct musb *musb) { struct da8xx_glue *glue = dev_get_drvdata(musb->controller->parent); - del_timer_sync(&musb->dev_timer); + timer_delete_sync(&musb->dev_timer); phy_power_off(glue->phy); phy_exit(glue->phy);
diff --git a/drivers/usb/musb/jz4740.c b/drivers/usb/musb/jz4740.c index acdeb11..df56c97 100644 --- a/drivers/usb/musb/jz4740.c +++ b/drivers/usb/musb/jz4740.c
@@ -59,7 +59,7 @@ static irqreturn_t jz4740_musb_interrupt(int irq, void *__hci) return IRQ_NONE; } -static struct musb_fifo_cfg jz4740_musb_fifo_cfg[] = { +static const struct musb_fifo_cfg jz4740_musb_fifo_cfg[] = { { .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, }, { .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, }, { .hw_ep_num = 2, .style = FIFO_TX, .maxpacket = 64, }, @@ -205,7 +205,7 @@ static const struct musb_hdrc_platform_data jz4740_musb_pdata = { .platform_ops = &jz4740_musb_ops, }; -static struct musb_fifo_cfg jz4770_musb_fifo_cfg[] = { +static const struct musb_fifo_cfg jz4770_musb_fifo_cfg[] = { { .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, }, { .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, }, { .hw_ep_num = 2, .style = FIFO_TX, .maxpacket = 512, },
diff --git a/drivers/usb/musb/mediatek.c b/drivers/usb/musb/mediatek.c index aa988d7..c6cbe71 100644 --- a/drivers/usb/musb/mediatek.c +++ b/drivers/usb/musb/mediatek.c
@@ -365,7 +365,7 @@ static const struct musb_platform_ops mtk_musb_ops = { #define MTK_MUSB_MAX_EP_NUM 8 #define MTK_MUSB_RAM_BITS 11 -static struct musb_fifo_cfg mtk_musb_mode_cfg[] = { +static const struct musb_fifo_cfg mtk_musb_mode_cfg[] = { { .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, }, { .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, }, { .hw_ep_num = 2, .style = FIFO_TX, .maxpacket = 512, },
diff --git a/drivers/usb/musb/mpfs.c b/drivers/usb/musb/mpfs.c index 7edc842..020348a 100644 --- a/drivers/usb/musb/mpfs.c +++ b/drivers/usb/musb/mpfs.c
@@ -29,7 +29,7 @@ struct mpfs_glue { struct clk *clk; }; -static struct musb_fifo_cfg mpfs_musb_mode_cfg[] = { +static const struct musb_fifo_cfg mpfs_musb_mode_cfg[] = { { .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, }, { .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, }, { .hw_ep_num = 2, .style = FIFO_TX, .maxpacket = 512, }, @@ -165,7 +165,7 @@ static void __maybe_unused mpfs_musb_try_idle(struct musb *musb, unsigned long t musb->xceiv->otg->state == OTG_STATE_A_WAIT_BCON)) { dev_dbg(musb->controller, "%s active, deleting timer\n", usb_otg_state_string(musb->xceiv->otg->state)); - del_timer(&musb->dev_timer); + timer_delete(&musb->dev_timer); last_timer = jiffies; return; } @@ -232,7 +232,7 @@ static int mpfs_musb_init(struct musb *musb) static int mpfs_musb_exit(struct musb *musb) { - del_timer_sync(&musb->dev_timer); + timer_delete_sync(&musb->dev_timer); return 0; }
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 7f349f5..cbbb271 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c
@@ -921,7 +921,7 @@ static void musb_handle_intr_connect(struct musb *musb, u8 devctl, u8 int_usb) musb_set_state(musb, OTG_STATE_B_HOST); if (musb->hcd) musb->hcd->self.is_b_host = 1; - del_timer(&musb->otg_timer); + timer_delete(&musb->otg_timer); break; default: if ((devctl & MUSB_DEVCTL_VBUS) @@ -1015,7 +1015,7 @@ static void musb_handle_intr_reset(struct musb *musb) + msecs_to_jiffies(TA_WAIT_BCON(musb))); break; case OTG_STATE_A_PERIPHERAL: - del_timer(&musb->otg_timer); + timer_delete(&musb->otg_timer); musb_g_reset(musb); break; case OTG_STATE_B_WAIT_ACON: @@ -1271,7 +1271,7 @@ MODULE_PARM_DESC(fifo_mode, "initial endpoint configuration"); */ /* mode 0 - fits in 2KB */ -static struct musb_fifo_cfg mode_0_cfg[] = { +static const struct musb_fifo_cfg mode_0_cfg[] = { { .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, }, { .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, }, { .hw_ep_num = 2, .style = FIFO_RXTX, .maxpacket = 512, }, @@ -1280,7 +1280,7 @@ static struct musb_fifo_cfg mode_0_cfg[] = { }; /* mode 1 - fits in 4KB */ -static struct musb_fifo_cfg mode_1_cfg[] = { +static const struct musb_fifo_cfg mode_1_cfg[] = { { .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, .mode = BUF_DOUBLE, }, { .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, .mode = BUF_DOUBLE, }, { .hw_ep_num = 2, .style = FIFO_RXTX, .maxpacket = 512, .mode = BUF_DOUBLE, }, @@ -1289,7 +1289,7 @@ static struct musb_fifo_cfg mode_1_cfg[] = { }; /* mode 2 - fits in 4KB */ -static struct musb_fifo_cfg mode_2_cfg[] = { +static const struct musb_fifo_cfg mode_2_cfg[] = { { .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, }, { .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, }, { .hw_ep_num = 2, .style = FIFO_TX, .maxpacket = 512, }, @@ -1299,7 +1299,7 @@ static struct musb_fifo_cfg mode_2_cfg[] = { }; /* mode 3 - fits in 4KB */ -static struct musb_fifo_cfg mode_3_cfg[] = { +static const struct musb_fifo_cfg mode_3_cfg[] = { { .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, .mode = BUF_DOUBLE, }, { .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, .mode = BUF_DOUBLE, }, { .hw_ep_num = 2, .style = FIFO_TX, .maxpacket = 512, }, @@ -1309,7 +1309,7 @@ static struct musb_fifo_cfg mode_3_cfg[] = { }; /* mode 4 - fits in 16KB */ -static struct musb_fifo_cfg mode_4_cfg[] = { +static const struct musb_fifo_cfg mode_4_cfg[] = { { .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, }, { .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, }, { .hw_ep_num = 2, .style = FIFO_TX, .maxpacket = 512, }, @@ -1340,7 +1340,7 @@ static struct musb_fifo_cfg mode_4_cfg[] = { }; /* mode 5 - fits in 8KB */ -static struct musb_fifo_cfg mode_5_cfg[] = { +static const struct musb_fifo_cfg mode_5_cfg[] = { { .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, }, { .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, }, { .hw_ep_num = 2, .style = FIFO_TX, .maxpacket = 512, }, @@ -1447,7 +1447,7 @@ fifo_setup(struct musb *musb, struct musb_hw_ep *hw_ep, return offset + (maxpacket << ((c_size & MUSB_FIFOSZ_DPB) ? 1 : 0)); } -static struct musb_fifo_cfg ep0_cfg = { +static const struct musb_fifo_cfg ep0_cfg = { .style = FIFO_RXTX, .maxpacket = 64, };
diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index f877faf..e5e813f 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c
@@ -201,7 +201,7 @@ static void dsps_musb_disable(struct musb *musb) musb_writel(reg_base, wrp->coreintr_clear, wrp->usb_bitmap); musb_writel(reg_base, wrp->epintr_clear, wrp->txep_bitmap | wrp->rxep_bitmap); - del_timer_sync(&musb->dev_timer); + timer_delete_sync(&musb->dev_timer); } /* Caller must take musb->lock */ @@ -215,7 +215,7 @@ static int dsps_check_status(struct musb *musb, void *unused) int skip_session = 0; if (glue->vbus_irq) - del_timer(&musb->dev_timer); + timer_delete(&musb->dev_timer); /* * We poll because DSPS IP's won't expose several OTG-critical @@ -499,7 +499,7 @@ static int dsps_musb_exit(struct musb *musb) struct device *dev = musb->controller; struct dsps_glue *glue = dev_get_drvdata(dev->parent); - del_timer_sync(&musb->dev_timer); + timer_delete_sync(&musb->dev_timer); phy_power_off(musb->phy); phy_exit(musb->phy); debugfs_remove_recursive(glue->dbgfs_root); @@ -983,7 +983,7 @@ static int dsps_suspend(struct device *dev) return ret; } - del_timer_sync(&musb->dev_timer); + timer_delete_sync(&musb->dev_timer); mbase = musb->ctrl_base; glue->context.control = musb_readl(mbase, wrp->control);
diff --git a/drivers/usb/musb/sunxi.c b/drivers/usb/musb/sunxi.c index eac1cde..a6bd3e9 100644 --- a/drivers/usb/musb/sunxi.c +++ b/drivers/usb/musb/sunxi.c
@@ -629,7 +629,7 @@ static const struct musb_platform_ops sunxi_musb_ops = { #define SUNXI_MUSB_RAM_BITS 11 /* Allwinner OTG supports up to 5 endpoints */ -static struct musb_fifo_cfg sunxi_musb_mode_cfg_5eps[] = { +static const struct musb_fifo_cfg sunxi_musb_mode_cfg_5eps[] = { MUSB_EP_FIFO_SINGLE(1, FIFO_TX, 512), MUSB_EP_FIFO_SINGLE(1, FIFO_RX, 512), MUSB_EP_FIFO_SINGLE(2, FIFO_TX, 512), @@ -643,7 +643,7 @@ static struct musb_fifo_cfg sunxi_musb_mode_cfg_5eps[] = { }; /* H3/V3s OTG supports only 4 endpoints */ -static struct musb_fifo_cfg sunxi_musb_mode_cfg_4eps[] = { +static const struct musb_fifo_cfg sunxi_musb_mode_cfg_4eps[] = { MUSB_EP_FIFO_SINGLE(1, FIFO_TX, 512), MUSB_EP_FIFO_SINGLE(1, FIFO_RX, 512), MUSB_EP_FIFO_SINGLE(2, FIFO_TX, 512),
diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c index 90b760a..abd2472 100644 --- a/drivers/usb/musb/tusb6010.c +++ b/drivers/usb/musb/tusb6010.c
@@ -525,7 +525,7 @@ static void tusb_musb_try_idle(struct musb *musb, unsigned long timeout) && (musb->xceiv->otg->state == OTG_STATE_A_WAIT_BCON))) { dev_dbg(musb->controller, "%s active, deleting timer\n", usb_otg_state_string(musb->xceiv->otg->state)); - del_timer(&musb->dev_timer); + timer_delete(&musb->dev_timer); last_timer = jiffies; return; } @@ -875,7 +875,7 @@ static irqreturn_t tusb_musb_interrupt(int irq, void *__hci) } if (int_src & TUSB_INT_SRC_USB_IP_CONN) - del_timer(&musb->dev_timer); + timer_delete(&musb->dev_timer); /* OTG state change reports (annoyingly) not issued by Mentor core */ if (int_src & (TUSB_INT_SRC_VBUS_SENSE_CHNG @@ -984,7 +984,7 @@ static void tusb_musb_disable(struct musb *musb) musb_writel(tbase, TUSB_DMA_INT_MASK, 0x7fffffff); musb_writel(tbase, TUSB_GPIO_INT_MASK, 0x1ff); - del_timer(&musb->dev_timer); + timer_delete(&musb->dev_timer); if (is_dma_capable() && !dma_off) { printk(KERN_WARNING "%s %s: dma still active\n", @@ -1174,7 +1174,7 @@ static int tusb_musb_exit(struct musb *musb) { struct tusb6010_glue *glue = dev_get_drvdata(musb->controller->parent); - del_timer_sync(&musb->dev_timer); + timer_delete_sync(&musb->dev_timer); the_musb = NULL; gpiod_set_value(glue->enable, 0);
diff --git a/drivers/usb/phy/phy-mv-usb.c b/drivers/usb/phy/phy-mv-usb.c index 30d6c88..638fba5 100644 --- a/drivers/usb/phy/phy-mv-usb.c +++ b/drivers/usb/phy/phy-mv-usb.c
@@ -110,7 +110,7 @@ static int mv_otg_cancel_timer(struct mv_otg *mvotg, unsigned int id) timer = &mvotg->otg_ctrl.timer[id]; if (timer_pending(timer)) - del_timer(timer); + timer_delete(timer); return 0; }
diff --git a/drivers/usb/phy/phy-mxs-usb.c b/drivers/usb/phy/phy-mxs-usb.c index 7490f17..7069dd3 100644 --- a/drivers/usb/phy/phy-mxs-usb.c +++ b/drivers/usb/phy/phy-mxs-usb.c
@@ -769,11 +769,9 @@ static int mxs_phy_probe(struct platform_device *pdev) return PTR_ERR(base); clk = devm_clk_get(&pdev->dev, NULL); - if (IS_ERR(clk)) { - dev_err(&pdev->dev, - "can't get the clock, err=%ld", PTR_ERR(clk)); - return PTR_ERR(clk); - } + if (IS_ERR(clk)) + return dev_err_probe(&pdev->dev, PTR_ERR(clk), + "can't get the clock\n"); mxs_phy = devm_kzalloc(&pdev->dev, sizeof(*mxs_phy), GFP_KERNEL); if (!mxs_phy)
diff --git a/drivers/usb/phy/phy-ulpi.c b/drivers/usb/phy/phy-ulpi.c index e683a37..4df63e6 100644 --- a/drivers/usb/phy/phy-ulpi.c +++ b/drivers/usb/phy/phy-ulpi.c
@@ -256,29 +256,6 @@ static void otg_ulpi_init(struct usb_phy *phy, struct usb_otg *otg, } struct usb_phy * -otg_ulpi_create(struct usb_phy_io_ops *ops, - unsigned int flags) -{ - struct usb_phy *phy; - struct usb_otg *otg; - - phy = kzalloc(sizeof(*phy), GFP_KERNEL); - if (!phy) - return NULL; - - otg = kzalloc(sizeof(*otg), GFP_KERNEL); - if (!otg) { - kfree(phy); - return NULL; - } - - otg_ulpi_init(phy, otg, ops, flags); - - return phy; -} -EXPORT_SYMBOL_GPL(otg_ulpi_create); - -struct usb_phy * devm_otg_ulpi_create(struct device *dev, struct usb_phy_io_ops *ops, unsigned int flags)
diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index ca3da79..93710b7 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c
@@ -66,29 +66,16 @@ #define MOS_WDR_TIMEOUT 5000 /* default urb timeout */ -#define MOS_PORT1 0x0200 -#define MOS_PORT2 0x0300 -#define MOS_VENREG 0x0000 -#define MOS_MAX_PORT 0x02 -#define MOS_WRITE 0x0E -#define MOS_READ 0x0D - /* Requests */ #define MCS_RD_RTYPE 0xC0 #define MCS_WR_RTYPE 0x40 #define MCS_RDREQ 0x0D #define MCS_WRREQ 0x0E -#define MCS_CTRL_TIMEOUT 500 #define VENDOR_READ_LENGTH (0x01) -#define MAX_NAME_LEN 64 - #define ZLP_REG1 0x3A /* Zero_Flag_Reg1 58 */ #define ZLP_REG5 0x3E /* Zero_Flag_Reg5 62 */ -/* For higher baud Rates use TIOCEXBAUD */ -#define TIOCEXBAUD 0x5462 - /* * Vendor id and device id defines *
diff --git a/drivers/usb/storage/alauda.c b/drivers/usb/storage/alauda.c index 6263c4e..e01f3a4 100644 --- a/drivers/usb/storage/alauda.c +++ b/drivers/usb/storage/alauda.c
@@ -174,7 +174,7 @@ struct alauda_card_info { unsigned char zoneshift; /* 1<<zs blocks per zone */ }; -static struct alauda_card_info alauda_card_ids[] = { +static const struct alauda_card_info alauda_card_ids[] = { /* NAND flash */ { 0x6e, 20, 8, 4, 8}, /* 1 MB */ { 0xe8, 20, 8, 4, 8}, /* 1 MB */ @@ -200,7 +200,7 @@ static struct alauda_card_info alauda_card_ids[] = { { 0,} }; -static struct alauda_card_info *alauda_card_find_id(unsigned char id) +static const struct alauda_card_info *alauda_card_find_id(unsigned char id) { int i; @@ -383,7 +383,7 @@ static int alauda_init_media(struct us_data *us) { unsigned char *data = us->iobuf; int ready = 0; - struct alauda_card_info *media_info; + const struct alauda_card_info *media_info; unsigned int num_zones; while (ready == 0) { @@ -1132,7 +1132,7 @@ static int alauda_transport(struct scsi_cmnd *srb, struct us_data *us) int rc; struct alauda_info *info = (struct alauda_info *) us->extra; unsigned char *ptr = us->iobuf; - static unsigned char inquiry_response[36] = { + static const unsigned char inquiry_response[36] = { 0x00, 0x80, 0x00, 0x01, 0x1F, 0x00, 0x00, 0x00 };
diff --git a/drivers/usb/storage/datafab.c b/drivers/usb/storage/datafab.c index bbfa239..9ba3694 100644 --- a/drivers/usb/storage/datafab.c +++ b/drivers/usb/storage/datafab.c
@@ -319,7 +319,7 @@ static int datafab_determine_lun(struct us_data *us, // // There might be a better way of doing this? - static unsigned char scommand[8] = { 0, 1, 0, 0, 0, 0xa0, 0xec, 1 }; + static const unsigned char scommand[8] = { 0, 1, 0, 0, 0, 0xa0, 0xec, 1 }; unsigned char *command = us->iobuf; unsigned char *buf; int count = 0, rc; @@ -384,7 +384,7 @@ static int datafab_id_device(struct us_data *us, // to the ATA spec, 'Sector Count' isn't used but the Windows driver // sets this bit so we do too... // - static unsigned char scommand[8] = { 0, 1, 0, 0, 0, 0xa0, 0xec, 1 }; + static const unsigned char scommand[8] = { 0, 1, 0, 0, 0, 0xa0, 0xec, 1 }; unsigned char *command = us->iobuf; unsigned char *reply; int rc; @@ -437,16 +437,16 @@ static int datafab_handle_mode_sense(struct us_data *us, struct scsi_cmnd * srb, int sense_6) { - static unsigned char rw_err_page[12] = { + static const unsigned char rw_err_page[12] = { 0x1, 0xA, 0x21, 1, 0, 0, 0, 0, 1, 0, 0, 0 }; - static unsigned char cache_page[12] = { + static const unsigned char cache_page[12] = { 0x8, 0xA, 0x1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - static unsigned char rbac_page[12] = { + static const unsigned char rbac_page[12] = { 0x1B, 0xA, 0, 0x81, 0, 0, 0, 0, 0, 0, 0, 0 }; - static unsigned char timer_page[8] = { + static const unsigned char timer_page[8] = { 0x1C, 0x6, 0, 0, 0, 0 }; unsigned char pc, page_code; @@ -550,7 +550,7 @@ static int datafab_transport(struct scsi_cmnd *srb, struct us_data *us) int rc; unsigned long block, blocks; unsigned char *ptr = us->iobuf; - static unsigned char inquiry_reply[8] = { + static const unsigned char inquiry_reply[8] = { 0x00, 0x80, 0x00, 0x01, 0x1F, 0x00, 0x00, 0x00 };
diff --git a/drivers/usb/storage/initializers.c b/drivers/usb/storage/initializers.c index f8f9ce8..b243bd5 100644 --- a/drivers/usb/storage/initializers.c +++ b/drivers/usb/storage/initializers.c
@@ -54,7 +54,7 @@ int usb_stor_ucr61s2b_init(struct us_data *us) struct bulk_cs_wrap *bcs = (struct bulk_cs_wrap*) us->iobuf; int res; unsigned int partial; - static char init_string[] = "\xec\x0a\x06\x00$PCCHIPS"; + static const char init_string[] = "\xec\x0a\x06\x00$PCCHIPS"; usb_stor_dbg(us, "Sending UCR-61S2B initialization packet...\n");
diff --git a/drivers/usb/storage/jumpshot.c b/drivers/usb/storage/jumpshot.c index 39ca84d..089c6f8 100644 --- a/drivers/usb/storage/jumpshot.c +++ b/drivers/usb/storage/jumpshot.c
@@ -367,16 +367,16 @@ static int jumpshot_handle_mode_sense(struct us_data *us, struct scsi_cmnd * srb, int sense_6) { - static unsigned char rw_err_page[12] = { + static const unsigned char rw_err_page[12] = { 0x1, 0xA, 0x21, 1, 0, 0, 0, 0, 1, 0, 0, 0 }; - static unsigned char cache_page[12] = { + static const unsigned char cache_page[12] = { 0x8, 0xA, 0x1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - static unsigned char rbac_page[12] = { + static const unsigned char rbac_page[12] = { 0x1B, 0xA, 0, 0x81, 0, 0, 0, 0, 0, 0, 0, 0 }; - static unsigned char timer_page[8] = { + static const unsigned char timer_page[8] = { 0x1C, 0x6, 0, 0, 0, 0 }; unsigned char pc, page_code; @@ -477,7 +477,7 @@ static int jumpshot_transport(struct scsi_cmnd *srb, struct us_data *us) int rc; unsigned long block, blocks; unsigned char *ptr = us->iobuf; - static unsigned char inquiry_response[8] = { + static const unsigned char inquiry_response[8] = { 0x00, 0x80, 0x00, 0x01, 0x1F, 0x00, 0x00, 0x00 };
diff --git a/drivers/usb/storage/realtek_cr.c b/drivers/usb/storage/realtek_cr.c index 2a82ed7..b387863 100644 --- a/drivers/usb/storage/realtek_cr.c +++ b/drivers/usb/storage/realtek_cr.c
@@ -191,7 +191,7 @@ MODULE_DEVICE_TABLE(usb, realtek_cr_ids); .initFunction = init_function, \ } -static struct us_unusual_dev realtek_cr_unusual_dev_list[] = { +static const struct us_unusual_dev realtek_cr_unusual_dev_list[] = { # include "unusual_realtek.h" {} /* Terminating entry */ }; @@ -797,10 +797,10 @@ static void rts51x_invoke_transport(struct scsi_cmnd *srb, struct us_data *us) { struct rts51x_chip *chip = (struct rts51x_chip *)(us->extra); static int card_first_show = 1; - static u8 media_not_present[] = { 0x70, 0, 0x02, 0, 0, 0, 0, + static const u8 media_not_present[] = { 0x70, 0, 0x02, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0x3A, 0, 0, 0, 0, 0 }; - static u8 invalid_cmd_field[] = { 0x70, 0, 0x05, 0, 0, 0, 0, + static const u8 invalid_cmd_field[] = { 0x70, 0, 0x05, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0x24, 0, 0, 0, 0, 0 }; int ret; @@ -934,7 +934,7 @@ static void realtek_cr_destructor(void *extra) #ifdef CONFIG_REALTEK_AUTOPM if (ss_en) { - del_timer(&chip->rts51x_suspend_timer); + timer_delete(&chip->rts51x_suspend_timer); chip->timer_expires = 0; } #endif
diff --git a/drivers/usb/storage/sddr09.c b/drivers/usb/storage/sddr09.c index d21ce34..e66b920 100644 --- a/drivers/usb/storage/sddr09.c +++ b/drivers/usb/storage/sddr09.c
@@ -144,7 +144,7 @@ static inline char *nand_flash_manufacturer(int manuf_id) { * 256 MB NAND flash has a 5-byte ID with 2nd byte 0xaa, 0xba, 0xca or 0xda. */ -static struct nand_flash_dev nand_flash_ids[] = { +static const struct nand_flash_dev nand_flash_ids[] = { /* NAND flash */ { 0x6e, 20, 8, 4, 8, 2}, /* 1 MB */ { 0xe8, 20, 8, 4, 8, 2}, /* 1 MB */ @@ -169,7 +169,7 @@ static struct nand_flash_dev nand_flash_ids[] = { { 0,} }; -static struct nand_flash_dev * +static const struct nand_flash_dev * nand_find_id(unsigned char id) { int i; @@ -1133,9 +1133,9 @@ sddr09_reset(struct us_data *us) { } #endif -static struct nand_flash_dev * +static const struct nand_flash_dev * sddr09_get_cardinfo(struct us_data *us, unsigned char flags) { - struct nand_flash_dev *cardinfo; + const struct nand_flash_dev *cardinfo; unsigned char deviceID[4]; char blurbtxt[256]; int result; @@ -1545,12 +1545,12 @@ static int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us) struct sddr09_card_info *info; - static unsigned char inquiry_response[8] = { + static const unsigned char inquiry_response[8] = { 0x00, 0x80, 0x00, 0x02, 0x1F, 0x00, 0x00, 0x00 }; /* note: no block descriptor support */ - static unsigned char mode_page_01[19] = { + static const unsigned char mode_page_01[19] = { 0x00, 0x0F, 0x00, 0x0, 0x0, 0x0, 0x00, 0x01, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 @@ -1584,7 +1584,7 @@ static int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us) } if (srb->cmnd[0] == READ_CAPACITY) { - struct nand_flash_dev *cardinfo; + const struct nand_flash_dev *cardinfo; sddr09_get_wp(us, info); /* read WP bit */
diff --git a/drivers/usb/storage/sddr55.c b/drivers/usb/storage/sddr55.c index d5cdff3..b323f0a 100644 --- a/drivers/usb/storage/sddr55.c +++ b/drivers/usb/storage/sddr55.c
@@ -775,11 +775,11 @@ static void sddr55_card_info_destructor(void *extra) { static int sddr55_transport(struct scsi_cmnd *srb, struct us_data *us) { int result; - static unsigned char inquiry_response[8] = { + static const unsigned char inquiry_response[8] = { 0x00, 0x80, 0x00, 0x02, 0x1F, 0x00, 0x00, 0x00 }; // write-protected for now, no block descriptor support - static unsigned char mode_page_01[20] = { + static const unsigned char mode_page_01[20] = { 0x0, 0x12, 0x00, 0x80, 0x0, 0x0, 0x0, 0x0, 0x01, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
diff --git a/drivers/usb/storage/shuttle_usbat.c b/drivers/usb/storage/shuttle_usbat.c index c33cbf1..27faa0e 100644 --- a/drivers/usb/storage/shuttle_usbat.c +++ b/drivers/usb/storage/shuttle_usbat.c
@@ -1683,7 +1683,7 @@ static int usbat_flash_transport(struct scsi_cmnd * srb, struct us_data *us) struct usbat_info *info = (struct usbat_info *) (us->extra); unsigned long block, blocks; unsigned char *ptr = us->iobuf; - static unsigned char inquiry_response[36] = { + static const unsigned char inquiry_response[36] = { 0x00, 0x80, 0x00, 0x01, 0x1F, 0x00, 0x00, 0x00 };
diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c index e6bc8ec..1aa1bd2 100644 --- a/drivers/usb/storage/transport.c +++ b/drivers/usb/storage/transport.c
@@ -528,7 +528,7 @@ static void last_sector_hacks(struct us_data *us, struct scsi_cmnd *srb) u32 sector; /* To Report "Medium Error: Record Not Found */ - static unsigned char record_not_found[18] = { + static const unsigned char record_not_found[18] = { [0] = 0x70, /* current error */ [2] = MEDIUM_ERROR, /* = 0x03 */ [7] = 0x0a, /* additional length */
diff --git a/drivers/usb/typec/altmodes/thunderbolt.c b/drivers/usb/typec/altmodes/thunderbolt.c index 1b475b1..6eadf78 100644 --- a/drivers/usb/typec/altmodes/thunderbolt.c +++ b/drivers/usb/typec/altmodes/thunderbolt.c
@@ -112,7 +112,7 @@ static void tbt_altmode_work(struct work_struct *work) return; disable_plugs: - for (int i = TYPEC_PLUG_SOP_PP; i > 0; --i) { + for (int i = TYPEC_PLUG_SOP_PP; i >= 0; --i) { if (tbt->plug[i]) typec_altmode_put_plug(tbt->plug[i]); @@ -143,7 +143,7 @@ static int tbt_enter_modes_ordered(struct typec_altmode *alt) if (tbt->plug[TYPEC_PLUG_SOP_P]) { ret = typec_cable_altmode_enter(alt, TYPEC_PLUG_SOP_P, NULL); if (ret < 0) { - for (int i = TYPEC_PLUG_SOP_PP; i > 0; --i) { + for (int i = TYPEC_PLUG_SOP_PP; i >= 0; --i) { if (tbt->plug[i]) typec_altmode_put_plug(tbt->plug[i]); @@ -324,7 +324,7 @@ static void tbt_altmode_remove(struct typec_altmode *alt) { struct tbt_altmode *tbt = typec_altmode_get_drvdata(alt); - for (int i = TYPEC_PLUG_SOP_PP; i > 0; --i) { + for (int i = TYPEC_PLUG_SOP_PP; i >= 0; --i) { if (tbt->plug[i]) typec_altmode_put_plug(tbt->plug[i]); } @@ -351,10 +351,10 @@ static bool tbt_ready(struct typec_altmode *alt) */ for (int i = 0; i < TYPEC_PLUG_SOP_PP + 1; i++) { plug = typec_altmode_get_plug(tbt->alt, i); - if (IS_ERR(plug)) + if (!plug) continue; - if (!plug || plug->svid != USB_TYPEC_TBT_SID) + if (plug->svid != USB_TYPEC_TBT_SID) break; plug->desc = "Thunderbolt3";
diff --git a/drivers/usb/typec/mux/Kconfig b/drivers/usb/typec/mux/Kconfig index 67381b4..6dd8f96 100644 --- a/drivers/usb/typec/mux/Kconfig +++ b/drivers/usb/typec/mux/Kconfig
@@ -56,6 +56,16 @@ Say Y or M if your system has a On Semiconductor NB7VPQ904M Type-C redriver chip found on some devices with a Type-C port. +config TYPEC_MUX_PS883X + tristate "Parade PS883x Type-C retimer driver" + depends on I2C + depends on DRM || DRM=n + select DRM_AUX_BRIDGE if DRM_BRIDGE && OF + select REGMAP_I2C + help + Say Y or M if your system has a Parade PS883x Type-C retimer chip + found on some devices with a Type-C port. + config TYPEC_MUX_PTN36502 tristate "NXP PTN36502 Type-C redriver driver" depends on I2C
diff --git a/drivers/usb/typec/mux/Makefile b/drivers/usb/typec/mux/Makefile index 6087944..b4f599e 100644 --- a/drivers/usb/typec/mux/Makefile +++ b/drivers/usb/typec/mux/Makefile
@@ -6,6 +6,7 @@ obj-$(CONFIG_TYPEC_MUX_INTEL_PMC) += intel_pmc_mux.o obj-$(CONFIG_TYPEC_MUX_IT5205) += it5205.o obj-$(CONFIG_TYPEC_MUX_NB7VPQ904M) += nb7vpq904m.o +obj-$(CONFIG_TYPEC_MUX_PS883X) += ps883x.o obj-$(CONFIG_TYPEC_MUX_PTN36502) += ptn36502.o obj-$(CONFIG_TYPEC_MUX_TUSB1046) += tusb1046.o obj-$(CONFIG_TYPEC_MUX_WCD939X_USBSS) += wcd939x-usbss.o
diff --git a/drivers/usb/typec/mux/ps883x.c b/drivers/usb/typec/mux/ps883x.c new file mode 100644 index 0000000..ad59bab --- /dev/null +++ b/drivers/usb/typec/mux/ps883x.c
@@ -0,0 +1,466 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Parade ps883x usb retimer driver + * + * Copyright (C) 2024 Linaro Ltd. + */ + +#include <drm/bridge/aux-bridge.h> +#include <linux/clk.h> +#include <linux/gpio/consumer.h> +#include <linux/i2c.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/mutex.h> +#include <linux/regmap.h> +#include <linux/regulator/consumer.h> +#include <linux/usb/typec_altmode.h> +#include <linux/usb/typec_dp.h> +#include <linux/usb/typec_mux.h> +#include <linux/usb/typec_retimer.h> + +#define REG_USB_PORT_CONN_STATUS_0 0x00 + +#define CONN_STATUS_0_CONNECTION_PRESENT BIT(0) +#define CONN_STATUS_0_ORIENTATION_REVERSED BIT(1) +#define CONN_STATUS_0_USB_3_1_CONNECTED BIT(5) + +#define REG_USB_PORT_CONN_STATUS_1 0x01 + +#define CONN_STATUS_1_DP_CONNECTED BIT(0) +#define CONN_STATUS_1_DP_SINK_REQUESTED BIT(1) +#define CONN_STATUS_1_DP_PIN_ASSIGNMENT_C_D BIT(2) +#define CONN_STATUS_1_DP_HPD_LEVEL BIT(7) + +#define REG_USB_PORT_CONN_STATUS_2 0x02 + +struct ps883x_retimer { + struct i2c_client *client; + struct gpio_desc *reset_gpio; + struct regmap *regmap; + struct typec_switch_dev *sw; + struct typec_retimer *retimer; + struct clk *xo_clk; + struct regulator *vdd_supply; + struct regulator *vdd33_supply; + struct regulator *vdd33_cap_supply; + struct regulator *vddat_supply; + struct regulator *vddar_supply; + struct regulator *vddio_supply; + + struct typec_switch *typec_switch; + struct typec_mux *typec_mux; + + struct mutex lock; /* protect non-concurrent retimer & switch */ + + enum typec_orientation orientation; + unsigned long mode; + unsigned int svid; +}; + +static int ps883x_configure(struct ps883x_retimer *retimer, int cfg0, + int cfg1, int cfg2) +{ + struct device *dev = &retimer->client->dev; + int ret; + + ret = regmap_write(retimer->regmap, REG_USB_PORT_CONN_STATUS_0, cfg0); + if (ret) { + dev_err(dev, "failed to write conn_status_0: %d\n", ret); + return ret; + } + + ret = regmap_write(retimer->regmap, REG_USB_PORT_CONN_STATUS_1, cfg1); + if (ret) { + dev_err(dev, "failed to write conn_status_1: %d\n", ret); + return ret; + } + + ret = regmap_write(retimer->regmap, REG_USB_PORT_CONN_STATUS_2, cfg2); + if (ret) { + dev_err(dev, "failed to write conn_status_2: %d\n", ret); + return ret; + } + + return 0; +} + +static int ps883x_set(struct ps883x_retimer *retimer) +{ + int cfg0 = CONN_STATUS_0_CONNECTION_PRESENT; + int cfg1 = 0x00; + int cfg2 = 0x00; + + if (retimer->orientation == TYPEC_ORIENTATION_NONE || + retimer->mode == TYPEC_STATE_SAFE) { + return ps883x_configure(retimer, cfg0, cfg1, cfg2); + } + + if (retimer->mode != TYPEC_STATE_USB && retimer->svid != USB_TYPEC_DP_SID) + return -EINVAL; + + if (retimer->orientation == TYPEC_ORIENTATION_REVERSE) + cfg0 |= CONN_STATUS_0_ORIENTATION_REVERSED; + + switch (retimer->mode) { + case TYPEC_STATE_USB: + cfg0 |= CONN_STATUS_0_USB_3_1_CONNECTED; + break; + + case TYPEC_DP_STATE_C: + cfg1 = CONN_STATUS_1_DP_CONNECTED | + CONN_STATUS_1_DP_SINK_REQUESTED | + CONN_STATUS_1_DP_PIN_ASSIGNMENT_C_D | + CONN_STATUS_1_DP_HPD_LEVEL; + break; + + case TYPEC_DP_STATE_D: + cfg0 |= CONN_STATUS_0_USB_3_1_CONNECTED; + cfg1 = CONN_STATUS_1_DP_CONNECTED | + CONN_STATUS_1_DP_SINK_REQUESTED | + CONN_STATUS_1_DP_PIN_ASSIGNMENT_C_D | + CONN_STATUS_1_DP_HPD_LEVEL; + break; + + case TYPEC_DP_STATE_E: + cfg1 = CONN_STATUS_1_DP_CONNECTED | + CONN_STATUS_1_DP_HPD_LEVEL; + break; + + default: + return -EOPNOTSUPP; + } + + return ps883x_configure(retimer, cfg0, cfg1, cfg2); +} + +static int ps883x_sw_set(struct typec_switch_dev *sw, + enum typec_orientation orientation) +{ + struct ps883x_retimer *retimer = typec_switch_get_drvdata(sw); + int ret = 0; + + ret = typec_switch_set(retimer->typec_switch, orientation); + if (ret) + return ret; + + mutex_lock(&retimer->lock); + + if (retimer->orientation != orientation) { + retimer->orientation = orientation; + + ret = ps883x_set(retimer); + } + + mutex_unlock(&retimer->lock); + + return ret; +} + +static int ps883x_retimer_set(struct typec_retimer *rtmr, + struct typec_retimer_state *state) +{ + struct ps883x_retimer *retimer = typec_retimer_get_drvdata(rtmr); + struct typec_mux_state mux_state; + int ret = 0; + + mutex_lock(&retimer->lock); + + if (state->mode != retimer->mode) { + retimer->mode = state->mode; + + if (state->alt) + retimer->svid = state->alt->svid; + else + retimer->svid = 0; + + ret = ps883x_set(retimer); + } + + mutex_unlock(&retimer->lock); + + if (ret) + return ret; + + mux_state.alt = state->alt; + mux_state.data = state->data; + mux_state.mode = state->mode; + + return typec_mux_set(retimer->typec_mux, &mux_state); +} + +static int ps883x_enable_vregs(struct ps883x_retimer *retimer) +{ + struct device *dev = &retimer->client->dev; + int ret; + + ret = regulator_enable(retimer->vdd33_supply); + if (ret) { + dev_err(dev, "cannot enable VDD 3.3V regulator: %d\n", ret); + return ret; + } + + ret = regulator_enable(retimer->vdd33_cap_supply); + if (ret) { + dev_err(dev, "cannot enable VDD 3.3V CAP regulator: %d\n", ret); + goto err_vdd33_disable; + } + + usleep_range(4000, 10000); + + ret = regulator_enable(retimer->vdd_supply); + if (ret) { + dev_err(dev, "cannot enable VDD regulator: %d\n", ret); + goto err_vdd33_cap_disable; + } + + ret = regulator_enable(retimer->vddar_supply); + if (ret) { + dev_err(dev, "cannot enable VDD AR regulator: %d\n", ret); + goto err_vdd_disable; + } + + ret = regulator_enable(retimer->vddat_supply); + if (ret) { + dev_err(dev, "cannot enable VDD AT regulator: %d\n", ret); + goto err_vddar_disable; + } + + ret = regulator_enable(retimer->vddio_supply); + if (ret) { + dev_err(dev, "cannot enable VDD IO regulator: %d\n", ret); + goto err_vddat_disable; + } + + return 0; + +err_vddat_disable: + regulator_disable(retimer->vddat_supply); +err_vddar_disable: + regulator_disable(retimer->vddar_supply); +err_vdd_disable: + regulator_disable(retimer->vdd_supply); +err_vdd33_cap_disable: + regulator_disable(retimer->vdd33_cap_supply); +err_vdd33_disable: + regulator_disable(retimer->vdd33_supply); + + return ret; +} + +static void ps883x_disable_vregs(struct ps883x_retimer *retimer) +{ + regulator_disable(retimer->vddio_supply); + regulator_disable(retimer->vddat_supply); + regulator_disable(retimer->vddar_supply); + regulator_disable(retimer->vdd_supply); + regulator_disable(retimer->vdd33_cap_supply); + regulator_disable(retimer->vdd33_supply); +} + +static int ps883x_get_vregs(struct ps883x_retimer *retimer) +{ + struct device *dev = &retimer->client->dev; + + retimer->vdd_supply = devm_regulator_get(dev, "vdd"); + if (IS_ERR(retimer->vdd_supply)) + return dev_err_probe(dev, PTR_ERR(retimer->vdd_supply), + "failed to get VDD\n"); + + retimer->vdd33_supply = devm_regulator_get(dev, "vdd33"); + if (IS_ERR(retimer->vdd33_supply)) + return dev_err_probe(dev, PTR_ERR(retimer->vdd33_supply), + "failed to get VDD 3.3V\n"); + + retimer->vdd33_cap_supply = devm_regulator_get(dev, "vdd33-cap"); + if (IS_ERR(retimer->vdd33_cap_supply)) + return dev_err_probe(dev, PTR_ERR(retimer->vdd33_cap_supply), + "failed to get VDD CAP 3.3V\n"); + + retimer->vddat_supply = devm_regulator_get(dev, "vddat"); + if (IS_ERR(retimer->vddat_supply)) + return dev_err_probe(dev, PTR_ERR(retimer->vddat_supply), + "failed to get VDD AT\n"); + + retimer->vddar_supply = devm_regulator_get(dev, "vddar"); + if (IS_ERR(retimer->vddar_supply)) + return dev_err_probe(dev, PTR_ERR(retimer->vddar_supply), + "failed to get VDD AR\n"); + + retimer->vddio_supply = devm_regulator_get(dev, "vddio"); + if (IS_ERR(retimer->vddio_supply)) + return dev_err_probe(dev, PTR_ERR(retimer->vddio_supply), + "failed to get VDD IO\n"); + + return 0; +} + +static const struct regmap_config ps883x_retimer_regmap = { + .max_register = 0x1f, + .reg_bits = 8, + .val_bits = 8, +}; + +static int ps883x_retimer_probe(struct i2c_client *client) +{ + struct device *dev = &client->dev; + struct typec_switch_desc sw_desc = { }; + struct typec_retimer_desc rtmr_desc = { }; + struct ps883x_retimer *retimer; + unsigned int val; + int ret; + + retimer = devm_kzalloc(dev, sizeof(*retimer), GFP_KERNEL); + if (!retimer) + return -ENOMEM; + + retimer->client = client; + + mutex_init(&retimer->lock); + + retimer->regmap = devm_regmap_init_i2c(client, &ps883x_retimer_regmap); + if (IS_ERR(retimer->regmap)) + return dev_err_probe(dev, PTR_ERR(retimer->regmap), + "failed to allocate register map\n"); + + ret = ps883x_get_vregs(retimer); + if (ret) + return ret; + + retimer->xo_clk = devm_clk_get(dev, NULL); + if (IS_ERR(retimer->xo_clk)) + return dev_err_probe(dev, PTR_ERR(retimer->xo_clk), + "failed to get xo clock\n"); + + retimer->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_ASIS); + if (IS_ERR(retimer->reset_gpio)) + return dev_err_probe(dev, PTR_ERR(retimer->reset_gpio), + "failed to get reset gpio\n"); + + retimer->typec_switch = typec_switch_get(dev); + if (IS_ERR(retimer->typec_switch)) + return dev_err_probe(dev, PTR_ERR(retimer->typec_switch), + "failed to acquire orientation-switch\n"); + + retimer->typec_mux = typec_mux_get(dev); + if (IS_ERR(retimer->typec_mux)) { + ret = dev_err_probe(dev, PTR_ERR(retimer->typec_mux), + "failed to acquire mode-mux\n"); + goto err_switch_put; + } + + ret = drm_aux_bridge_register(dev); + if (ret) + goto err_mux_put; + + ret = ps883x_enable_vregs(retimer); + if (ret) + goto err_mux_put; + + ret = clk_prepare_enable(retimer->xo_clk); + if (ret) { + dev_err(dev, "failed to enable XO: %d\n", ret); + goto err_vregs_disable; + } + + /* skip resetting if already configured */ + if (regmap_test_bits(retimer->regmap, REG_USB_PORT_CONN_STATUS_0, + CONN_STATUS_0_CONNECTION_PRESENT) == 1) { + gpiod_direction_output(retimer->reset_gpio, 0); + } else { + gpiod_direction_output(retimer->reset_gpio, 1); + + /* VDD IO supply enable to reset release delay */ + usleep_range(4000, 14000); + + gpiod_set_value(retimer->reset_gpio, 0); + + /* firmware initialization delay */ + msleep(60); + + /* make sure device is accessible */ + ret = regmap_read(retimer->regmap, REG_USB_PORT_CONN_STATUS_0, + &val); + if (ret) { + dev_err(dev, "failed to read conn_status_0: %d\n", ret); + if (ret == -ENXIO) + ret = -EIO; + goto err_clk_disable; + } + } + + sw_desc.drvdata = retimer; + sw_desc.fwnode = dev_fwnode(dev); + sw_desc.set = ps883x_sw_set; + + retimer->sw = typec_switch_register(dev, &sw_desc); + if (IS_ERR(retimer->sw)) { + ret = PTR_ERR(retimer->sw); + dev_err(dev, "failed to register typec switch: %d\n", ret); + goto err_clk_disable; + } + + rtmr_desc.drvdata = retimer; + rtmr_desc.fwnode = dev_fwnode(dev); + rtmr_desc.set = ps883x_retimer_set; + + retimer->retimer = typec_retimer_register(dev, &rtmr_desc); + if (IS_ERR(retimer->retimer)) { + ret = PTR_ERR(retimer->retimer); + dev_err(dev, "failed to register typec retimer: %d\n", ret); + goto err_switch_unregister; + } + + return 0; + +err_switch_unregister: + typec_switch_unregister(retimer->sw); +err_clk_disable: + clk_disable_unprepare(retimer->xo_clk); +err_vregs_disable: + gpiod_set_value(retimer->reset_gpio, 1); + ps883x_disable_vregs(retimer); +err_mux_put: + typec_mux_put(retimer->typec_mux); +err_switch_put: + typec_switch_put(retimer->typec_switch); + + return ret; +} + +static void ps883x_retimer_remove(struct i2c_client *client) +{ + struct ps883x_retimer *retimer = i2c_get_clientdata(client); + + typec_retimer_unregister(retimer->retimer); + typec_switch_unregister(retimer->sw); + + gpiod_set_value(retimer->reset_gpio, 1); + + clk_disable_unprepare(retimer->xo_clk); + + ps883x_disable_vregs(retimer); + + typec_mux_put(retimer->typec_mux); + typec_switch_put(retimer->typec_switch); +} + +static const struct of_device_id ps883x_retimer_of_table[] = { + { .compatible = "parade,ps8830" }, + { } +}; +MODULE_DEVICE_TABLE(of, ps883x_retimer_of_table); + +static struct i2c_driver ps883x_retimer_driver = { + .driver = { + .name = "ps883x_retimer", + .of_match_table = ps883x_retimer_of_table, + }, + .probe = ps883x_retimer_probe, + .remove = ps883x_retimer_remove, +}; + +module_i2c_driver(ps883x_retimer_driver); + +MODULE_DESCRIPTION("Parade ps883x Type-C Retimer driver"); +MODULE_LICENSE("GPL");
diff --git a/drivers/usb/typec/ucsi/cros_ec_ucsi.c b/drivers/usb/typec/ucsi/cros_ec_ucsi.c index c605c86..4ec1c6d 100644 --- a/drivers/usb/typec/ucsi/cros_ec_ucsi.c +++ b/drivers/usb/typec/ucsi/cros_ec_ucsi.c
@@ -105,12 +105,13 @@ static int cros_ucsi_async_control(struct ucsi *ucsi, u64 cmd) return 0; } -static int cros_ucsi_sync_control(struct ucsi *ucsi, u64 cmd) +static int cros_ucsi_sync_control(struct ucsi *ucsi, u64 cmd, u32 *cci, + void *data, size_t size) { struct cros_ucsi_data *udata = ucsi_get_drvdata(ucsi); int ret; - ret = ucsi_sync_control_common(ucsi, cmd); + ret = ucsi_sync_control_common(ucsi, cmd, cci, data, size); switch (ret) { case -EBUSY: /* EC may return -EBUSY if CCI.busy is set. @@ -205,12 +206,19 @@ static int cros_ucsi_event(struct notifier_block *nb, { struct cros_ucsi_data *udata = container_of(nb, struct cros_ucsi_data, nb); - if (!(host_event & PD_EVENT_PPM)) - return NOTIFY_OK; + if (host_event & PD_EVENT_INIT) { + /* Late init event received from ChromeOS EC. Treat this as a + * system resume to re-enable communication with the PPM. + */ + dev_dbg(udata->dev, "Late PD init received\n"); + ucsi_resume(udata->ucsi); + } - dev_dbg(udata->dev, "UCSI notification received\n"); - flush_work(&udata->work); - schedule_work(&udata->work); + if (host_event & PD_EVENT_PPM) { + dev_dbg(udata->dev, "UCSI notification received\n"); + flush_work(&udata->work); + schedule_work(&udata->work); + } return NOTIFY_OK; }
diff --git a/drivers/usb/typec/ucsi/debugfs.c b/drivers/usb/typec/ucsi/debugfs.c index 83ff230..eae2b18a 100644 --- a/drivers/usb/typec/ucsi/debugfs.c +++ b/drivers/usb/typec/ucsi/debugfs.c
@@ -28,11 +28,12 @@ static int ucsi_cmd(void *data, u64 val) ucsi->debugfs->status = 0; switch (UCSI_COMMAND(val)) { - case UCSI_SET_UOM: + case UCSI_SET_CCOM: case UCSI_SET_UOR: case UCSI_SET_PDR: case UCSI_CONNECTOR_RESET: case UCSI_SET_SINK_PATH: + case UCSI_SET_NEW_CAM: ret = ucsi_send_command(ucsi, val, NULL, 0); break; case UCSI_GET_CAPABILITY: @@ -42,6 +43,9 @@ static int ucsi_cmd(void *data, u64 val) case UCSI_GET_PDOS: case UCSI_GET_CABLE_PROPERTY: case UCSI_GET_CONNECTOR_STATUS: + case UCSI_GET_ERROR_STATUS: + case UCSI_GET_CAM_CS: + case UCSI_GET_LPM_PPM_INFO: ret = ucsi_send_command(ucsi, val, &ucsi->debugfs->response, sizeof(ucsi->debugfs->response));
diff --git a/drivers/usb/typec/ucsi/trace.c b/drivers/usb/typec/ucsi/trace.c index cb62ad8..596a954 100644 --- a/drivers/usb/typec/ucsi/trace.c +++ b/drivers/usb/typec/ucsi/trace.c
@@ -12,7 +12,7 @@ static const char * const ucsi_cmd_strs[] = { [UCSI_SET_NOTIFICATION_ENABLE] = "SET_NOTIFICATION_ENABLE", [UCSI_GET_CAPABILITY] = "GET_CAPABILITY", [UCSI_GET_CONNECTOR_CAPABILITY] = "GET_CONNECTOR_CAPABILITY", - [UCSI_SET_UOM] = "SET_UOM", + [UCSI_SET_CCOM] = "SET_CCOM", [UCSI_SET_UOR] = "SET_UOR", [UCSI_SET_PDM] = "SET_PDM", [UCSI_SET_PDR] = "SET_PDR",
diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c index 2a2915b..e8c7e9d 100644 --- a/drivers/usb/typec/ucsi/ucsi.c +++ b/drivers/usb/typec/ucsi/ucsi.c
@@ -55,7 +55,8 @@ void ucsi_notify_common(struct ucsi *ucsi, u32 cci) } EXPORT_SYMBOL_GPL(ucsi_notify_common); -int ucsi_sync_control_common(struct ucsi *ucsi, u64 command) +int ucsi_sync_control_common(struct ucsi *ucsi, u64 command, u32 *cci, + void *data, size_t size) { bool ack = UCSI_COMMAND(command) == UCSI_ACK_CC_CI; int ret; @@ -80,6 +81,13 @@ int ucsi_sync_control_common(struct ucsi *ucsi, u64 command) else clear_bit(COMMAND_PENDING, &ucsi->flags); + if (!ret && cci) + ret = ucsi->ops->read_cci(ucsi, cci); + + if (!ret && data && + (*cci & UCSI_CCI_COMMAND_COMPLETE)) + ret = ucsi->ops->read_message_in(ucsi, data, size); + return ret; } EXPORT_SYMBOL_GPL(ucsi_sync_control_common); @@ -95,7 +103,7 @@ static int ucsi_acknowledge(struct ucsi *ucsi, bool conn_ack) ctrl |= UCSI_ACK_CONNECTOR_CHANGE; } - return ucsi->ops->sync_control(ucsi, ctrl); + return ucsi->ops->sync_control(ucsi, ctrl, NULL, NULL, 0); } static int ucsi_run_command(struct ucsi *ucsi, u64 command, u32 *cci, @@ -108,9 +116,7 @@ static int ucsi_run_command(struct ucsi *ucsi, u64 command, u32 *cci, if (size > UCSI_MAX_DATA_LENGTH(ucsi)) return -EINVAL; - ret = ucsi->ops->sync_control(ucsi, command); - if (ucsi->ops->read_cci(ucsi, cci)) - return -EIO; + ret = ucsi->ops->sync_control(ucsi, command, cci, data, size); if (*cci & UCSI_CCI_BUSY) return ucsi_run_command(ucsi, UCSI_CANCEL, cci, NULL, 0, false) ?: -EBUSY; @@ -127,9 +133,6 @@ static int ucsi_run_command(struct ucsi *ucsi, u64 command, u32 *cci, else err = 0; - if (!err && data && UCSI_CCI_LENGTH(*cci)) - err = ucsi->ops->read_message_in(ucsi, data, size); - /* * Don't ACK connection change if there was an error. */
diff --git a/drivers/usb/typec/ucsi/ucsi.h b/drivers/usb/typec/ucsi/ucsi.h index 28780ac..3a2c176 100644 --- a/drivers/usb/typec/ucsi/ucsi.h +++ b/drivers/usb/typec/ucsi/ucsi.h
@@ -79,7 +79,8 @@ struct ucsi_operations { int (*read_cci)(struct ucsi *ucsi, u32 *cci); int (*poll_cci)(struct ucsi *ucsi, u32 *cci); int (*read_message_in)(struct ucsi *ucsi, void *val, size_t val_len); - int (*sync_control)(struct ucsi *ucsi, u64 command); + int (*sync_control)(struct ucsi *ucsi, u64 command, u32 *cci, + void *data, size_t size); int (*async_control)(struct ucsi *ucsi, u64 command); bool (*update_altmodes)(struct ucsi *ucsi, struct ucsi_altmode *orig, struct ucsi_altmode *updated); @@ -108,7 +109,7 @@ void ucsi_connector_change(struct ucsi *ucsi, u8 num); #define UCSI_GET_CAPABILITY_SIZE 128 #define UCSI_GET_CONNECTOR_CAPABILITY 0x07 #define UCSI_GET_CONNECTOR_CAPABILITY_SIZE 32 -#define UCSI_SET_UOM 0x08 +#define UCSI_SET_CCOM 0x08 #define UCSI_SET_UOR 0x09 #define UCSI_SET_PDM 0x0a #define UCSI_SET_PDR 0x0b @@ -123,7 +124,9 @@ void ucsi_connector_change(struct ucsi *ucsi, u8 num); #define UCSI_GET_CONNECTOR_STATUS_SIZE 152 #define UCSI_GET_ERROR_STATUS 0x13 #define UCSI_GET_PD_MESSAGE 0x15 +#define UCSI_GET_CAM_CS 0x18 #define UCSI_SET_SINK_PATH 0x1c +#define UCSI_GET_LPM_PPM_INFO 0x22 #define UCSI_CONNECTOR_NUMBER(_num_) ((u64)(_num_) << 16) #define UCSI_COMMAND(_cmd_) ((_cmd_) & 0xff) @@ -531,7 +534,8 @@ void ucsi_altmode_update_active(struct ucsi_connector *con); int ucsi_resume(struct ucsi *ucsi); void ucsi_notify_common(struct ucsi *ucsi, u32 cci); -int ucsi_sync_control_common(struct ucsi *ucsi, u64 command); +int ucsi_sync_control_common(struct ucsi *ucsi, u64 command, u32 *cci, + void *data, size_t size); #if IS_ENABLED(CONFIG_POWER_SUPPLY) int ucsi_register_port_psy(struct ucsi_connector *con);
diff --git a/drivers/usb/typec/ucsi/ucsi_acpi.c b/drivers/usb/typec/ucsi/ucsi_acpi.c index ac1ebb5..6b92f29 100644 --- a/drivers/usb/typec/ucsi/ucsi_acpi.c +++ b/drivers/usb/typec/ucsi/ucsi_acpi.c
@@ -105,17 +105,23 @@ static const struct ucsi_operations ucsi_acpi_ops = { .async_control = ucsi_acpi_async_control }; -static int ucsi_gram_read_message_in(struct ucsi *ucsi, void *val, size_t val_len) +static int ucsi_gram_sync_control(struct ucsi *ucsi, u64 command, u32 *cci, + void *val, size_t len) { u16 bogus_change = UCSI_CONSTAT_POWER_LEVEL_CHANGE | UCSI_CONSTAT_PDOS_CHANGE; struct ucsi_acpi *ua = ucsi_get_drvdata(ucsi); int ret; - ret = ucsi_acpi_read_message_in(ucsi, val, val_len); + ret = ucsi_sync_control_common(ucsi, command, cci, val, len); if (ret < 0) return ret; + if (UCSI_COMMAND(ua->cmd) == UCSI_GET_PDOS && + ua->cmd & UCSI_GET_PDOS_PARTNER_PDO(1) && + ua->cmd & UCSI_GET_PDOS_SRC_PDOS) + ua->check_bogus_event = true; + if (UCSI_COMMAND(ua->cmd) == UCSI_GET_CONNECTOR_STATUS && ua->check_bogus_event) { /* Clear the bogus change */ @@ -128,28 +134,11 @@ static int ucsi_gram_read_message_in(struct ucsi *ucsi, void *val, size_t val_le return ret; } -static int ucsi_gram_sync_control(struct ucsi *ucsi, u64 command) -{ - struct ucsi_acpi *ua = ucsi_get_drvdata(ucsi); - int ret; - - ret = ucsi_sync_control_common(ucsi, command); - if (ret < 0) - return ret; - - if (UCSI_COMMAND(ua->cmd) == UCSI_GET_PDOS && - ua->cmd & UCSI_GET_PDOS_PARTNER_PDO(1) && - ua->cmd & UCSI_GET_PDOS_SRC_PDOS) - ua->check_bogus_event = true; - - return ret; -} - static const struct ucsi_operations ucsi_gram_ops = { .read_version = ucsi_acpi_read_version, .read_cci = ucsi_acpi_read_cci, .poll_cci = ucsi_acpi_poll_cci, - .read_message_in = ucsi_gram_read_message_in, + .read_message_in = ucsi_acpi_read_message_in, .sync_control = ucsi_gram_sync_control, .async_control = ucsi_acpi_async_control };
diff --git a/drivers/usb/typec/ucsi/ucsi_ccg.c b/drivers/usb/typec/ucsi/ucsi_ccg.c index 4b16687..f01e4ef6 100644 --- a/drivers/usb/typec/ucsi/ucsi_ccg.c +++ b/drivers/usb/typec/ucsi/ucsi_ccg.c
@@ -222,7 +222,6 @@ struct ucsi_ccg { u16 fw_build; struct work_struct pm_work; - u64 last_cmd_sent; bool has_multiple_dp; struct ucsi_ccg_altmode orig[UCSI_MAX_ALTMODES]; struct ucsi_ccg_altmode updated[UCSI_MAX_ALTMODES]; @@ -538,9 +537,10 @@ static void ucsi_ccg_update_set_new_cam_cmd(struct ucsi_ccg *uc, * first and then vdo=0x3 */ static void ucsi_ccg_nvidia_altmode(struct ucsi_ccg *uc, - struct ucsi_altmode *alt) + struct ucsi_altmode *alt, + u64 command) { - switch (UCSI_ALTMODE_OFFSET(uc->last_cmd_sent)) { + switch (UCSI_ALTMODE_OFFSET(command)) { case NVIDIA_FTB_DP_OFFSET: if (alt[0].mid == USB_TYPEC_NVIDIA_VLINK_DBG_VDO) alt[0].mid = USB_TYPEC_NVIDIA_VLINK_DP_VDO | @@ -578,37 +578,11 @@ static int ucsi_ccg_read_cci(struct ucsi *ucsi, u32 *cci) static int ucsi_ccg_read_message_in(struct ucsi *ucsi, void *val, size_t val_len) { struct ucsi_ccg *uc = ucsi_get_drvdata(ucsi); - struct ucsi_capability *cap; - struct ucsi_altmode *alt; spin_lock(&uc->op_lock); memcpy(val, uc->op_data.message_in, val_len); spin_unlock(&uc->op_lock); - switch (UCSI_COMMAND(uc->last_cmd_sent)) { - case UCSI_GET_CURRENT_CAM: - if (uc->has_multiple_dp) - ucsi_ccg_update_get_current_cam_cmd(uc, (u8 *)val); - break; - case UCSI_GET_ALTERNATE_MODES: - if (UCSI_ALTMODE_RECIPIENT(uc->last_cmd_sent) == - UCSI_RECIPIENT_SOP) { - alt = val; - if (alt[0].svid == USB_TYPEC_NVIDIA_VLINK_SID) - ucsi_ccg_nvidia_altmode(uc, alt); - } - break; - case UCSI_GET_CAPABILITY: - if (uc->fw_build == CCG_FW_BUILD_NVIDIA_TEGRA) { - cap = val; - cap->features &= ~UCSI_CAP_ALT_MODE_DETAILS; - } - break; - default: - break; - } - uc->last_cmd_sent = 0; - return 0; } @@ -628,7 +602,8 @@ static int ucsi_ccg_async_control(struct ucsi *ucsi, u64 command) return ccg_write(uc, reg, (u8 *)&command, sizeof(command)); } -static int ucsi_ccg_sync_control(struct ucsi *ucsi, u64 command) +static int ucsi_ccg_sync_control(struct ucsi *ucsi, u64 command, u32 *cci, + void *data, size_t size) { struct ucsi_ccg *uc = ucsi_get_drvdata(ucsi); struct ucsi_connector *con; @@ -638,11 +613,9 @@ static int ucsi_ccg_sync_control(struct ucsi *ucsi, u64 command) mutex_lock(&uc->lock); pm_runtime_get_sync(uc->dev); - uc->last_cmd_sent = command; - - if (UCSI_COMMAND(uc->last_cmd_sent) == UCSI_SET_NEW_CAM && + if (UCSI_COMMAND(command) == UCSI_SET_NEW_CAM && uc->has_multiple_dp) { - con_index = (uc->last_cmd_sent >> 16) & + con_index = (command >> 16) & UCSI_CMD_CONNECTOR_MASK; if (con_index == 0) { ret = -EINVAL; @@ -652,7 +625,31 @@ static int ucsi_ccg_sync_control(struct ucsi *ucsi, u64 command) ucsi_ccg_update_set_new_cam_cmd(uc, con, &command); } - ret = ucsi_sync_control_common(ucsi, command); + ret = ucsi_sync_control_common(ucsi, command, cci, data, size); + + switch (UCSI_COMMAND(command)) { + case UCSI_GET_CURRENT_CAM: + if (uc->has_multiple_dp) + ucsi_ccg_update_get_current_cam_cmd(uc, (u8 *)data); + break; + case UCSI_GET_ALTERNATE_MODES: + if (UCSI_ALTMODE_RECIPIENT(command) == UCSI_RECIPIENT_SOP) { + struct ucsi_altmode *alt = data; + + if (alt[0].svid == USB_TYPEC_NVIDIA_VLINK_SID) + ucsi_ccg_nvidia_altmode(uc, alt, command); + } + break; + case UCSI_GET_CAPABILITY: + if (uc->fw_build == CCG_FW_BUILD_NVIDIA_TEGRA) { + struct ucsi_capability *cap = data; + + cap->features &= ~UCSI_CAP_ALT_MODE_DETAILS; + } + break; + default: + break; + } err_put: pm_runtime_put_sync(uc->dev); @@ -1391,22 +1388,35 @@ static ssize_t do_flash_store(struct device *dev, if (!flash) return n; - if (uc->fw_build == 0x0) { - dev_err(dev, "fail to flash FW due to missing FW build info\n"); - return -EINVAL; - } - schedule_work(&uc->work); return n; } +static umode_t ucsi_ccg_attrs_is_visible(struct kobject *kobj, struct attribute *attr, int idx) +{ + struct device *dev = kobj_to_dev(kobj); + struct ucsi_ccg *uc = i2c_get_clientdata(to_i2c_client(dev)); + + if (!uc->fw_build) + return 0; + + return attr->mode; +} + static DEVICE_ATTR_WO(do_flash); static struct attribute *ucsi_ccg_attrs[] = { &dev_attr_do_flash.attr, NULL, }; -ATTRIBUTE_GROUPS(ucsi_ccg); +static struct attribute_group ucsi_ccg_attr_group = { + .attrs = ucsi_ccg_attrs, + .is_visible = ucsi_ccg_attrs_is_visible, +}; +static const struct attribute_group *ucsi_ccg_groups[] = { + &ucsi_ccg_attr_group, + NULL, +}; static int ucsi_ccg_probe(struct i2c_client *client) { @@ -1433,11 +1443,10 @@ static int ucsi_ccg_probe(struct i2c_client *client) uc->fw_build = CCG_FW_BUILD_NVIDIA_TEGRA; else if (!strcmp(fw_name, "nvidia,gpu")) uc->fw_build = CCG_FW_BUILD_NVIDIA; + if (!uc->fw_build) + dev_err(uc->dev, "failed to get FW build information\n"); } - if (!uc->fw_build) - dev_err(uc->dev, "failed to get FW build information\n"); - /* reset ccg device and initialize ucsi */ status = ucsi_ccg_init(uc); if (status < 0) {
diff --git a/drivers/vdpa/mlx5/core/mr.c b/drivers/vdpa/mlx5/core/mr.c index 8455f08..6142434 100644 --- a/drivers/vdpa/mlx5/core/mr.c +++ b/drivers/vdpa/mlx5/core/mr.c
@@ -190,9 +190,12 @@ static void fill_indir(struct mlx5_vdpa_dev *mvdev, struct mlx5_vdpa_mr *mkey, v klm->bcount = cpu_to_be32(klm_bcount(dmr->end - dmr->start)); preve = dmr->end; } else { + u64 bcount = min_t(u64, dmr->start - preve, MAX_KLM_SIZE); + klm->key = cpu_to_be32(mvdev->res.null_mkey); - klm->bcount = cpu_to_be32(klm_bcount(dmr->start - preve)); - preve = dmr->start; + klm->bcount = cpu_to_be32(klm_bcount(bcount)); + preve += bcount; + goto again; } }
diff --git a/drivers/vdpa/mlx5/net/mlx5_vnet.c b/drivers/vdpa/mlx5/net/mlx5_vnet.c index 3609904..cccc49a 100644 --- a/drivers/vdpa/mlx5/net/mlx5_vnet.c +++ b/drivers/vdpa/mlx5/net/mlx5_vnet.c
@@ -3884,6 +3884,9 @@ static int mlx5_vdpa_dev_add(struct vdpa_mgmt_dev *v_mdev, const char *name, ndev->mvdev.max_vqs = max_vqs; mvdev = &ndev->mvdev; mvdev->mdev = mdev; + /* cpu_to_mlx5vdpa16() below depends on this flag */ + mvdev->actual_features = + (device_features & BIT_ULL(VIRTIO_F_VERSION_1)); ndev->vqs = kcalloc(max_vqs, sizeof(*ndev->vqs), GFP_KERNEL); ndev->event_cbs = kcalloc(max_vqs + 1, sizeof(*ndev->event_cbs), GFP_KERNEL);
diff --git a/drivers/vdpa/vdpa_user/vduse_dev.c b/drivers/vdpa/vdpa_user/vduse_dev.c index 7ae9969..6a9a373 100644 --- a/drivers/vdpa/vdpa_user/vduse_dev.c +++ b/drivers/vdpa/vdpa_user/vduse_dev.c
@@ -144,6 +144,7 @@ static struct workqueue_struct *vduse_irq_bound_wq; static u32 allowed_device_id[] = { VIRTIO_ID_BLOCK, VIRTIO_ID_NET, + VIRTIO_ID_FS, }; static inline struct vduse_dev *vdpa_to_vduse(struct vdpa_device *vdpa)
diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c index 6f7ae7e..5ba39f7 100644 --- a/drivers/vfio/pci/vfio_pci.c +++ b/drivers/vfio/pci/vfio_pci.c
@@ -111,9 +111,7 @@ static int vfio_pci_open_device(struct vfio_device *core_vdev) if (ret) return ret; - if (vfio_pci_is_vga(pdev) && - pdev->vendor == PCI_VENDOR_ID_INTEL && - IS_ENABLED(CONFIG_VFIO_PCI_IGD)) { + if (vfio_pci_is_intel_display(pdev)) { ret = vfio_pci_igd_init(vdev); if (ret && ret != -ENODEV) { pci_warn(pdev, "Failed to setup Intel IGD regions\n");
diff --git a/drivers/vfio/pci/vfio_pci_config.c b/drivers/vfio/pci/vfio_pci_config.c index 9414258..1443739 100644 --- a/drivers/vfio/pci/vfio_pci_config.c +++ b/drivers/vfio/pci/vfio_pci_config.c
@@ -1814,7 +1814,8 @@ int vfio_config_init(struct vfio_pci_core_device *vdev) cpu_to_le16(PCI_COMMAND_MEMORY); } - if (!IS_ENABLED(CONFIG_VFIO_PCI_INTX) || vdev->nointx) + if (!IS_ENABLED(CONFIG_VFIO_PCI_INTX) || vdev->nointx || + vdev->pdev->irq == IRQ_NOTCONNECTED) vconfig[PCI_INTERRUPT_PIN] = 0; ret = vfio_cap_init(vdev);
diff --git a/drivers/vfio/pci/vfio_pci_core.c b/drivers/vfio/pci/vfio_pci_core.c index c8586d4..35f9046 100644 --- a/drivers/vfio/pci/vfio_pci_core.c +++ b/drivers/vfio/pci/vfio_pci_core.c
@@ -727,15 +727,7 @@ EXPORT_SYMBOL_GPL(vfio_pci_core_finish_enable); static int vfio_pci_get_irq_count(struct vfio_pci_core_device *vdev, int irq_type) { if (irq_type == VFIO_PCI_INTX_IRQ_INDEX) { - u8 pin; - - if (!IS_ENABLED(CONFIG_VFIO_PCI_INTX) || - vdev->nointx || vdev->pdev->is_virtfn) - return 0; - - pci_read_config_byte(vdev->pdev, PCI_INTERRUPT_PIN, &pin); - - return pin ? 1 : 0; + return vdev->vconfig[PCI_INTERRUPT_PIN] ? 1 : 0; } else if (irq_type == VFIO_PCI_MSI_IRQ_INDEX) { u8 pos; u16 flags;
diff --git a/drivers/vfio/pci/vfio_pci_igd.c b/drivers/vfio/pci/vfio_pci_igd.c index dd70e24..ef490a4 100644 --- a/drivers/vfio/pci/vfio_pci_igd.c +++ b/drivers/vfio/pci/vfio_pci_igd.c
@@ -435,6 +435,12 @@ static int vfio_pci_igd_cfg_init(struct vfio_pci_core_device *vdev) return 0; } +bool vfio_pci_is_intel_display(struct pci_dev *pdev) +{ + return (pdev->vendor == PCI_VENDOR_ID_INTEL) && + ((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY); +} + int vfio_pci_igd_init(struct vfio_pci_core_device *vdev) { int ret;
diff --git a/drivers/vfio/pci/vfio_pci_intrs.c b/drivers/vfio/pci/vfio_pci_intrs.c index 8382c58..56596635 100644 --- a/drivers/vfio/pci/vfio_pci_intrs.c +++ b/drivers/vfio/pci/vfio_pci_intrs.c
@@ -259,7 +259,7 @@ static int vfio_intx_enable(struct vfio_pci_core_device *vdev, if (!is_irq_none(vdev)) return -EINVAL; - if (!pdev->irq) + if (!pdev->irq || pdev->irq == IRQ_NOTCONNECTED) return -ENODEV; name = kasprintf(GFP_KERNEL_ACCOUNT, "vfio-intx(%s)", pci_name(pdev));
diff --git a/drivers/vfio/pci/vfio_pci_priv.h b/drivers/vfio/pci/vfio_pci_priv.h index 5e4fa69..a9972ea 100644 --- a/drivers/vfio/pci/vfio_pci_priv.h +++ b/drivers/vfio/pci/vfio_pci_priv.h
@@ -67,8 +67,14 @@ void vfio_pci_memory_unlock_and_restore(struct vfio_pci_core_device *vdev, u16 cmd); #ifdef CONFIG_VFIO_PCI_IGD +bool vfio_pci_is_intel_display(struct pci_dev *pdev); int vfio_pci_igd_init(struct vfio_pci_core_device *vdev); #else +static inline bool vfio_pci_is_intel_display(struct pci_dev *pdev) +{ + return false; +} + static inline int vfio_pci_igd_init(struct vfio_pci_core_device *vdev) { return -ENODEV;
diff --git a/drivers/vfio/pci/virtio/Kconfig b/drivers/vfio/pci/virtio/Kconfig index 2770f7e..33e04e6 100644 --- a/drivers/vfio/pci/virtio/Kconfig +++ b/drivers/vfio/pci/virtio/Kconfig
@@ -1,11 +1,11 @@ # SPDX-License-Identifier: GPL-2.0-only config VIRTIO_VFIO_PCI - tristate "VFIO support for VIRTIO NET PCI VF devices" + tristate "VFIO support for VIRTIO PCI VF devices" depends on VIRTIO_PCI select VFIO_PCI_CORE help - This provides migration support for VIRTIO NET PCI VF devices - using the VFIO framework. Migration support requires the + This provides migration support for VIRTIO NET and BLOCK PCI VF + devices using the VFIO framework. Migration support requires the SR-IOV PF device to support specific VIRTIO extensions, otherwise this driver provides no additional functionality beyond vfio-pci.
diff --git a/drivers/vfio/pci/virtio/legacy_io.c b/drivers/vfio/pci/virtio/legacy_io.c index 20382ee..832af5b 100644 --- a/drivers/vfio/pci/virtio/legacy_io.c +++ b/drivers/vfio/pci/virtio/legacy_io.c
@@ -382,7 +382,9 @@ static bool virtiovf_bar0_exists(struct pci_dev *pdev) bool virtiovf_support_legacy_io(struct pci_dev *pdev) { - return virtio_pci_admin_has_legacy_io(pdev) && !virtiovf_bar0_exists(pdev); + /* For now, the legacy IO functionality is supported only for virtio-net */ + return pdev->device == 0x1041 && virtio_pci_admin_has_legacy_io(pdev) && + !virtiovf_bar0_exists(pdev); } int virtiovf_init_legacy_io(struct virtiovf_pci_core_device *virtvdev)
diff --git a/drivers/vfio/pci/virtio/main.c b/drivers/vfio/pci/virtio/main.c index d534d48..515fe1b 100644 --- a/drivers/vfio/pci/virtio/main.c +++ b/drivers/vfio/pci/virtio/main.c
@@ -187,8 +187,9 @@ static void virtiovf_pci_remove(struct pci_dev *pdev) } static const struct pci_device_id virtiovf_pci_table[] = { - /* Only virtio-net is supported/tested so far */ + /* Only virtio-net and virtio-block are supported/tested so far */ { PCI_DRIVER_OVERRIDE_DEVICE_VFIO(PCI_VENDOR_ID_REDHAT_QUMRANET, 0x1041) }, + { PCI_DRIVER_OVERRIDE_DEVICE_VFIO(PCI_VENDOR_ID_REDHAT_QUMRANET, 0x1042) }, {} }; @@ -221,4 +222,4 @@ module_pci_driver(virtiovf_pci_driver); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Yishai Hadas <yishaih@nvidia.com>"); MODULE_DESCRIPTION( - "VIRTIO VFIO PCI - User Level meta-driver for VIRTIO NET devices"); + "VIRTIO VFIO PCI - User Level meta-driver for VIRTIO NET and BLOCK devices");
diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c index 50ebc95..0ac5607 100644 --- a/drivers/vfio/vfio_iommu_type1.c +++ b/drivers/vfio/vfio_iommu_type1.c
@@ -103,9 +103,9 @@ struct vfio_dma { struct vfio_batch { struct page **pages; /* for pin_user_pages_remote */ struct page *fallback_page; /* if pages alloc fails */ - int capacity; /* length of pages array */ - int size; /* of batch currently */ - int offset; /* of next entry in pages */ + unsigned int capacity; /* length of pages array */ + unsigned int size; /* of batch currently */ + unsigned int offset; /* of next entry in pages */ }; struct vfio_iommu_group { @@ -471,12 +471,12 @@ static int put_pfn(unsigned long pfn, int prot) #define VFIO_BATCH_MAX_CAPACITY (PAGE_SIZE / sizeof(struct page *)) -static void vfio_batch_init(struct vfio_batch *batch) +static void __vfio_batch_init(struct vfio_batch *batch, bool single) { batch->size = 0; batch->offset = 0; - if (unlikely(disable_hugepages)) + if (single || unlikely(disable_hugepages)) goto fallback; batch->pages = (struct page **) __get_free_page(GFP_KERNEL); @@ -491,6 +491,16 @@ static void vfio_batch_init(struct vfio_batch *batch) batch->capacity = 1; } +static void vfio_batch_init(struct vfio_batch *batch) +{ + __vfio_batch_init(batch, false); +} + +static void vfio_batch_init_single(struct vfio_batch *batch) +{ + __vfio_batch_init(batch, true); +} + static void vfio_batch_unpin(struct vfio_batch *batch, struct vfio_dma *dma) { while (batch->size) { @@ -510,7 +520,7 @@ static void vfio_batch_fini(struct vfio_batch *batch) static int follow_fault_pfn(struct vm_area_struct *vma, struct mm_struct *mm, unsigned long vaddr, unsigned long *pfn, - bool write_fault) + unsigned long *addr_mask, bool write_fault) { struct follow_pfnmap_args args = { .vma = vma, .address = vaddr }; int ret; @@ -534,10 +544,12 @@ static int follow_fault_pfn(struct vm_area_struct *vma, struct mm_struct *mm, return ret; } - if (write_fault && !args.writable) + if (write_fault && !args.writable) { ret = -EFAULT; - else + } else { *pfn = args.pfn; + *addr_mask = args.addr_mask; + } follow_pfnmap_end(&args); return ret; @@ -545,25 +557,33 @@ static int follow_fault_pfn(struct vm_area_struct *vma, struct mm_struct *mm, /* * Returns the positive number of pfns successfully obtained or a negative - * error code. + * error code. The initial pfn is stored in the pfn arg. For page-backed + * pfns, the provided batch is also updated to indicate the filled pages and + * initial offset. For VM_PFNMAP pfns, only the returned number of pfns and + * returned initial pfn are provided; subsequent pfns are contiguous. */ -static int vaddr_get_pfns(struct mm_struct *mm, unsigned long vaddr, - long npages, int prot, unsigned long *pfn, - struct page **pages) +static long vaddr_get_pfns(struct mm_struct *mm, unsigned long vaddr, + unsigned long npages, int prot, unsigned long *pfn, + struct vfio_batch *batch) { + unsigned long pin_pages = min_t(unsigned long, npages, batch->capacity); struct vm_area_struct *vma; unsigned int flags = 0; - int ret; + long ret; if (prot & IOMMU_WRITE) flags |= FOLL_WRITE; mmap_read_lock(mm); - ret = pin_user_pages_remote(mm, vaddr, npages, flags | FOLL_LONGTERM, - pages, NULL); + ret = pin_user_pages_remote(mm, vaddr, pin_pages, flags | FOLL_LONGTERM, + batch->pages, NULL); if (ret > 0) { - *pfn = page_to_pfn(pages[0]); + *pfn = page_to_pfn(batch->pages[0]); + batch->size = ret; + batch->offset = 0; goto done; + } else if (!ret) { + ret = -EFAULT; } vaddr = untagged_addr_remote(mm, vaddr); @@ -572,15 +592,22 @@ static int vaddr_get_pfns(struct mm_struct *mm, unsigned long vaddr, vma = vma_lookup(mm, vaddr); if (vma && vma->vm_flags & VM_PFNMAP) { - ret = follow_fault_pfn(vma, mm, vaddr, pfn, prot & IOMMU_WRITE); + unsigned long addr_mask; + + ret = follow_fault_pfn(vma, mm, vaddr, pfn, &addr_mask, + prot & IOMMU_WRITE); if (ret == -EAGAIN) goto retry; if (!ret) { - if (is_invalid_reserved_pfn(*pfn)) - ret = 1; - else + if (is_invalid_reserved_pfn(*pfn)) { + unsigned long epfn; + + epfn = (*pfn | (~addr_mask >> PAGE_SHIFT)) + 1; + ret = min_t(long, npages, epfn - *pfn); + } else { ret = -EFAULT; + } } } done: @@ -594,7 +621,7 @@ static int vaddr_get_pfns(struct mm_struct *mm, unsigned long vaddr, * first page and all consecutive pages with the same locking. */ static long vfio_pin_pages_remote(struct vfio_dma *dma, unsigned long vaddr, - long npage, unsigned long *pfn_base, + unsigned long npage, unsigned long *pfn_base, unsigned long limit, struct vfio_batch *batch) { unsigned long pfn; @@ -616,32 +643,42 @@ static long vfio_pin_pages_remote(struct vfio_dma *dma, unsigned long vaddr, *pfn_base = 0; } + if (unlikely(disable_hugepages)) + npage = 1; + while (npage) { if (!batch->size) { /* Empty batch, so refill it. */ - long req_pages = min_t(long, npage, batch->capacity); - - ret = vaddr_get_pfns(mm, vaddr, req_pages, dma->prot, - &pfn, batch->pages); + ret = vaddr_get_pfns(mm, vaddr, npage, dma->prot, + &pfn, batch); if (ret < 0) goto unpin_out; - batch->size = ret; - batch->offset = 0; - if (!*pfn_base) { *pfn_base = pfn; rsvd = is_invalid_reserved_pfn(*pfn_base); } + + /* Handle pfnmap */ + if (!batch->size) { + if (pfn != *pfn_base + pinned || !rsvd) + goto out; + + pinned += ret; + npage -= ret; + vaddr += (PAGE_SIZE * ret); + iova += (PAGE_SIZE * ret); + continue; + } } /* - * pfn is preset for the first iteration of this inner loop and - * updated at the end to handle a VM_PFNMAP pfn. In that case, - * batch->pages isn't valid (there's no struct page), so allow - * batch->pages to be touched only when there's more than one - * pfn to check, which guarantees the pfns are from a - * !VM_PFNMAP vma. + * pfn is preset for the first iteration of this inner loop + * due to the fact that vaddr_get_pfns() needs to provide the + * initial pfn for pfnmaps. Therefore to reduce redundancy, + * the next pfn is fetched at the end of the loop. + * A PageReserved() page could still qualify as page backed + * and rsvd here, and therefore continues to use the batch. */ while (true) { if (pfn != *pfn_base + pinned || @@ -676,21 +713,12 @@ static long vfio_pin_pages_remote(struct vfio_dma *dma, unsigned long vaddr, pfn = page_to_pfn(batch->pages[batch->offset]); } - - if (unlikely(disable_hugepages)) - break; } out: ret = vfio_lock_acct(dma, lock_acct, false); unpin_out: - if (batch->size == 1 && !batch->offset) { - /* May be a VM_PFNMAP pfn, which the batch can't remember. */ - put_pfn(pfn, dma->prot); - batch->size = 0; - } - if (ret < 0) { if (pinned && !rsvd) { for (pfn = *pfn_base ; pinned ; pfn++, pinned--) @@ -705,7 +733,7 @@ static long vfio_pin_pages_remote(struct vfio_dma *dma, unsigned long vaddr, } static long vfio_unpin_pages_remote(struct vfio_dma *dma, dma_addr_t iova, - unsigned long pfn, long npage, + unsigned long pfn, unsigned long npage, bool do_accounting) { long unlocked = 0, locked = 0; @@ -728,7 +756,7 @@ static long vfio_unpin_pages_remote(struct vfio_dma *dma, dma_addr_t iova, static int vfio_pin_page_external(struct vfio_dma *dma, unsigned long vaddr, unsigned long *pfn_base, bool do_accounting) { - struct page *pages[1]; + struct vfio_batch batch; struct mm_struct *mm; int ret; @@ -736,7 +764,9 @@ static int vfio_pin_page_external(struct vfio_dma *dma, unsigned long vaddr, if (!mmget_not_zero(mm)) return -ENODEV; - ret = vaddr_get_pfns(mm, vaddr, 1, dma->prot, pfn_base, pages); + vfio_batch_init_single(&batch); + + ret = vaddr_get_pfns(mm, vaddr, 1, dma->prot, pfn_base, &batch); if (ret != 1) goto out; @@ -755,6 +785,7 @@ static int vfio_pin_page_external(struct vfio_dma *dma, unsigned long vaddr, } out: + vfio_batch_fini(&batch); mmput(mm); return ret; }
diff --git a/drivers/vhost/Kconfig b/drivers/vhost/Kconfig index b455d9a..020d4fb 100644 --- a/drivers/vhost/Kconfig +++ b/drivers/vhost/Kconfig
@@ -47,6 +47,7 @@ tristate "VHOST_SCSI TCM fabric driver" depends on TARGET_CORE && EVENTFD select VHOST + select SG_POOL default n help Say M here to enable the vhost_scsi TCM fabric module
diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c index 718fa4e..f6f5a7a 100644 --- a/drivers/vhost/scsi.c +++ b/drivers/vhost/scsi.c
@@ -45,6 +45,55 @@ #define VHOST_SCSI_PREALLOC_SGLS 2048 #define VHOST_SCSI_PREALLOC_UPAGES 2048 #define VHOST_SCSI_PREALLOC_PROT_SGLS 2048 +/* + * For the legacy descriptor case we allocate an iov per byte in the + * virtio_scsi_cmd_resp struct. + */ +#define VHOST_SCSI_MAX_RESP_IOVS sizeof(struct virtio_scsi_cmd_resp) + +static unsigned int vhost_scsi_inline_sg_cnt = VHOST_SCSI_PREALLOC_SGLS; + +#ifdef CONFIG_ARCH_NO_SG_CHAIN +static int vhost_scsi_set_inline_sg_cnt(const char *buf, + const struct kernel_param *kp) +{ + pr_err("Setting inline_sg_cnt is not supported.\n"); + return -EOPNOTSUPP; +} +#else +static int vhost_scsi_set_inline_sg_cnt(const char *buf, + const struct kernel_param *kp) +{ + unsigned int cnt; + int ret; + + ret = kstrtouint(buf, 10, &cnt); + if (ret) + return ret; + + if (ret > VHOST_SCSI_PREALLOC_SGLS) { + pr_err("Max inline_sg_cnt is %u\n", VHOST_SCSI_PREALLOC_SGLS); + return -EINVAL; + } + + vhost_scsi_inline_sg_cnt = cnt; + return 0; +} +#endif + +static int vhost_scsi_get_inline_sg_cnt(char *buf, + const struct kernel_param *kp) +{ + return sprintf(buf, "%u\n", vhost_scsi_inline_sg_cnt); +} + +static const struct kernel_param_ops vhost_scsi_inline_sg_cnt_op = { + .get = vhost_scsi_get_inline_sg_cnt, + .set = vhost_scsi_set_inline_sg_cnt, +}; + +module_param_cb(inline_sg_cnt, &vhost_scsi_inline_sg_cnt_op, NULL, 0644); +MODULE_PARM_DESC(inline_sg_cnt, "Set the number of scatterlist entries to pre-allocate. The default is 2048."); /* Max number of requests before requeueing the job. * Using this limit prevents one virtqueue from starving others with @@ -62,40 +111,26 @@ struct vhost_scsi_inflight { struct vhost_scsi_cmd { /* Descriptor from vhost_get_vq_desc() for virt_queue segment */ int tvc_vq_desc; - /* virtio-scsi initiator task attribute */ - int tvc_task_attr; - /* virtio-scsi response incoming iovecs */ - int tvc_in_iovs; - /* virtio-scsi initiator data direction */ - enum dma_data_direction tvc_data_direction; - /* Expected data transfer length from virtio-scsi header */ - u32 tvc_exp_data_len; - /* The Tag from include/linux/virtio_scsi.h:struct virtio_scsi_cmd_req */ - u64 tvc_tag; /* The number of scatterlists associated with this cmd */ u32 tvc_sgl_count; u32 tvc_prot_sgl_count; - /* Saved unpacked SCSI LUN for vhost_scsi_target_queue_cmd() */ - u32 tvc_lun; u32 copied_iov:1; - const void *saved_iter_addr; - struct iov_iter saved_iter; - /* Pointer to the SGL formatted memory from virtio-scsi */ - struct scatterlist *tvc_sgl; - struct scatterlist *tvc_prot_sgl; - struct page **tvc_upages; - /* Pointer to response header iovec */ - struct iovec *tvc_resp_iov; - /* Pointer to vhost_scsi for our device */ - struct vhost_scsi *tvc_vhost; + const void *read_iov; + struct iov_iter *read_iter; + struct scatterlist *sgl; + struct sg_table table; + struct scatterlist *prot_sgl; + struct sg_table prot_table; + /* Fast path response header iovec used when only one vec is needed */ + struct iovec tvc_resp_iov; + /* Number of iovs for response */ + unsigned int tvc_resp_iovs_cnt; + /* Pointer to response header iovecs if more than one is needed */ + struct iovec *tvc_resp_iovs; /* Pointer to vhost_virtqueue for the cmd */ struct vhost_virtqueue *tvc_vq; - /* Pointer to vhost nexus memory */ - struct vhost_scsi_nexus *tvc_nexus; /* The TCM I/O descriptor that is accessed via container_of() */ struct se_cmd tvc_se_cmd; - /* Copy of the incoming SCSI command descriptor block (CDB) */ - unsigned char tvc_cdb[VHOST_SCSI_MAX_CDB_SIZE]; /* Sense buffer that will be mapped into outgoing status */ unsigned char tvc_sense_buf[TRANSPORT_SENSE_BUFFER]; /* Completed commands list, serviced from vhost worker thread */ @@ -187,6 +222,7 @@ struct vhost_scsi_virtqueue { struct vhost_scsi_cmd *scsi_cmds; struct sbitmap scsi_tags; int max_cmds; + struct page **upages; struct vhost_work completion_work; struct llist_head completion_list; @@ -206,6 +242,8 @@ struct vhost_scsi { bool vs_events_missed; /* any missed events, protected by vq->mutex */ int vs_events_nr; /* num of pending events, protected by vq->mutex */ + + unsigned int inline_sg_cnt; }; struct vhost_scsi_tmf { @@ -330,23 +368,38 @@ static void vhost_scsi_release_cmd_res(struct se_cmd *se_cmd) struct vhost_scsi_cmd, tvc_se_cmd); struct vhost_scsi_virtqueue *svq = container_of(tv_cmd->tvc_vq, struct vhost_scsi_virtqueue, vq); + struct vhost_scsi *vs = svq->vs; struct vhost_scsi_inflight *inflight = tv_cmd->inflight; + struct scatterlist *sg; + struct page *page; int i; if (tv_cmd->tvc_sgl_count) { - for (i = 0; i < tv_cmd->tvc_sgl_count; i++) { + for_each_sgtable_sg(&tv_cmd->table, sg, i) { + page = sg_page(sg); + if (!page) + continue; + if (tv_cmd->copied_iov) - __free_page(sg_page(&tv_cmd->tvc_sgl[i])); + __free_page(page); else - put_page(sg_page(&tv_cmd->tvc_sgl[i])); + put_page(page); } - kfree(tv_cmd->saved_iter_addr); + kfree(tv_cmd->read_iter); + kfree(tv_cmd->read_iov); + sg_free_table_chained(&tv_cmd->table, vs->inline_sg_cnt); } if (tv_cmd->tvc_prot_sgl_count) { - for (i = 0; i < tv_cmd->tvc_prot_sgl_count; i++) - put_page(sg_page(&tv_cmd->tvc_prot_sgl[i])); + for_each_sgtable_sg(&tv_cmd->prot_table, sg, i) { + page = sg_page(sg); + if (page) + put_page(page); + } + sg_free_table_chained(&tv_cmd->prot_table, vs->inline_sg_cnt); } + if (tv_cmd->tvc_resp_iovs != &tv_cmd->tvc_resp_iov) + kfree(tv_cmd->tvc_resp_iovs); sbitmap_clear_bit(&svq->scsi_tags, se_cmd->map_tag); vhost_scsi_put_inflight(inflight); } @@ -533,15 +586,18 @@ static void vhost_scsi_evt_work(struct vhost_work *work) static int vhost_scsi_copy_sgl_to_iov(struct vhost_scsi_cmd *cmd) { - struct iov_iter *iter = &cmd->saved_iter; - struct scatterlist *sg = cmd->tvc_sgl; + struct iov_iter *iter = cmd->read_iter; + struct scatterlist *sg; struct page *page; size_t len; int i; - for (i = 0; i < cmd->tvc_sgl_count; i++) { - page = sg_page(&sg[i]); - len = sg[i].length; + for_each_sgtable_sg(&cmd->table, sg, i) { + page = sg_page(sg); + if (!page) + continue; + + len = sg->length; if (copy_page_to_iter(page, 0, len, iter) != len) { pr_err("Could not copy data while handling misaligned cmd. Error %zu\n", @@ -578,7 +634,7 @@ static void vhost_scsi_complete_cmd_work(struct vhost_work *work) cmd, se_cmd->residual_count, se_cmd->scsi_status); memset(&v_rsp, 0, sizeof(v_rsp)); - if (cmd->saved_iter_addr && vhost_scsi_copy_sgl_to_iov(cmd)) { + if (cmd->read_iter && vhost_scsi_copy_sgl_to_iov(cmd)) { v_rsp.response = VIRTIO_SCSI_S_BAD_TARGET; } else { v_rsp.resid = cpu_to_vhost32(cmd->tvc_vq, @@ -591,8 +647,8 @@ static void vhost_scsi_complete_cmd_work(struct vhost_work *work) se_cmd->scsi_sense_length); } - iov_iter_init(&iov_iter, ITER_DEST, cmd->tvc_resp_iov, - cmd->tvc_in_iovs, sizeof(v_rsp)); + iov_iter_init(&iov_iter, ITER_DEST, cmd->tvc_resp_iovs, + cmd->tvc_resp_iovs_cnt, sizeof(v_rsp)); ret = copy_to_iter(&v_rsp, sizeof(v_rsp), &iov_iter); if (likely(ret == sizeof(v_rsp))) { signal = true; @@ -609,55 +665,53 @@ static void vhost_scsi_complete_cmd_work(struct vhost_work *work) } static struct vhost_scsi_cmd * -vhost_scsi_get_cmd(struct vhost_virtqueue *vq, struct vhost_scsi_tpg *tpg, - unsigned char *cdb, u64 scsi_tag, u16 lun, u8 task_attr, - u32 exp_data_len, int data_direction) +vhost_scsi_get_cmd(struct vhost_virtqueue *vq, u64 scsi_tag) { struct vhost_scsi_virtqueue *svq = container_of(vq, struct vhost_scsi_virtqueue, vq); struct vhost_scsi_cmd *cmd; - struct vhost_scsi_nexus *tv_nexus; - struct scatterlist *sg, *prot_sg; - struct iovec *tvc_resp_iov; - struct page **pages; + struct scatterlist *sgl, *prot_sgl; int tag; - tv_nexus = tpg->tpg_nexus; - if (!tv_nexus) { - pr_err("Unable to locate active struct vhost_scsi_nexus\n"); - return ERR_PTR(-EIO); - } - tag = sbitmap_get(&svq->scsi_tags); if (tag < 0) { - pr_err("Unable to obtain tag for vhost_scsi_cmd\n"); + pr_warn_once("Guest sent too many cmds. Returning TASK_SET_FULL.\n"); return ERR_PTR(-ENOMEM); } cmd = &svq->scsi_cmds[tag]; - sg = cmd->tvc_sgl; - prot_sg = cmd->tvc_prot_sgl; - pages = cmd->tvc_upages; - tvc_resp_iov = cmd->tvc_resp_iov; + sgl = cmd->sgl; + prot_sgl = cmd->prot_sgl; memset(cmd, 0, sizeof(*cmd)); - cmd->tvc_sgl = sg; - cmd->tvc_prot_sgl = prot_sg; - cmd->tvc_upages = pages; + cmd->sgl = sgl; + cmd->prot_sgl = prot_sgl; cmd->tvc_se_cmd.map_tag = tag; - cmd->tvc_tag = scsi_tag; - cmd->tvc_lun = lun; - cmd->tvc_task_attr = task_attr; - cmd->tvc_exp_data_len = exp_data_len; - cmd->tvc_data_direction = data_direction; - cmd->tvc_nexus = tv_nexus; cmd->inflight = vhost_scsi_get_inflight(vq); - cmd->tvc_resp_iov = tvc_resp_iov; - - memcpy(cmd->tvc_cdb, cdb, VHOST_SCSI_MAX_CDB_SIZE); return cmd; } +static void vhost_scsi_revert_map_iov_to_sgl(struct iov_iter *iter, + struct scatterlist *curr, + struct scatterlist *end) +{ + size_t revert_bytes = 0; + struct page *page; + + while (curr != end) { + page = sg_page(curr); + + if (page) { + put_page(page); + revert_bytes += curr->length; + } + /* Clear so we can re-use it for the copy path */ + sg_set_page(curr, NULL, 0, 0); + curr = sg_next(curr); + } + iov_iter_revert(iter, revert_bytes); +} + /* * Map a user memory range into a scatterlist * @@ -666,14 +720,17 @@ vhost_scsi_get_cmd(struct vhost_virtqueue *vq, struct vhost_scsi_tpg *tpg, static int vhost_scsi_map_to_sgl(struct vhost_scsi_cmd *cmd, struct iov_iter *iter, - struct scatterlist *sgl, + struct sg_table *sg_table, + struct scatterlist **sgl, bool is_prot) { - struct page **pages = cmd->tvc_upages; - struct scatterlist *sg = sgl; - ssize_t bytes, mapped_bytes; - size_t offset, mapped_offset; - unsigned int npages = 0; + struct vhost_scsi_virtqueue *svq = container_of(cmd->tvc_vq, + struct vhost_scsi_virtqueue, vq); + struct page **pages = svq->upages; + struct scatterlist *sg = *sgl; + ssize_t bytes; + size_t offset; + unsigned int n, npages = 0; bytes = iov_iter_get_pages2(iter, pages, LONG_MAX, VHOST_SCSI_PREALLOC_UPAGES, &offset); @@ -681,11 +738,8 @@ vhost_scsi_map_to_sgl(struct vhost_scsi_cmd *cmd, if (bytes <= 0) return bytes < 0 ? bytes : -EFAULT; - mapped_bytes = bytes; - mapped_offset = offset; - while (bytes) { - unsigned n = min_t(unsigned, PAGE_SIZE - offset, bytes); + n = min_t(unsigned int, PAGE_SIZE - offset, bytes); /* * The block layer requires bios/requests to be a multiple of * 512 bytes, but Windows can send us vecs that are misaligned. @@ -706,25 +760,24 @@ vhost_scsi_map_to_sgl(struct vhost_scsi_cmd *cmd, goto revert_iter_get_pages; } - sg_set_page(sg++, pages[npages++], n, offset); + sg_set_page(sg, pages[npages++], n, offset); + sg = sg_next(sg); bytes -= n; offset = 0; } + *sgl = sg; return npages; revert_iter_get_pages: - iov_iter_revert(iter, mapped_bytes); + vhost_scsi_revert_map_iov_to_sgl(iter, *sgl, sg); - npages = 0; - while (mapped_bytes) { - unsigned int n = min_t(unsigned int, PAGE_SIZE - mapped_offset, - mapped_bytes); + iov_iter_revert(iter, bytes); + while (bytes) { + n = min_t(unsigned int, PAGE_SIZE, bytes); put_page(pages[npages++]); - - mapped_bytes -= n; - mapped_offset = 0; + bytes -= n; } return -EINVAL; @@ -752,33 +805,42 @@ vhost_scsi_calc_sgls(struct iov_iter *iter, size_t bytes, int max_sgls) static int vhost_scsi_copy_iov_to_sgl(struct vhost_scsi_cmd *cmd, struct iov_iter *iter, - struct scatterlist *sg, int sg_count) + struct sg_table *sg_table, int sg_count, + int data_dir) { size_t len = iov_iter_count(iter); unsigned int nbytes = 0; + struct scatterlist *sg; struct page *page; - int i; + int i, ret; - if (cmd->tvc_data_direction == DMA_FROM_DEVICE) { - cmd->saved_iter_addr = dup_iter(&cmd->saved_iter, iter, - GFP_KERNEL); - if (!cmd->saved_iter_addr) + if (data_dir == DMA_FROM_DEVICE) { + cmd->read_iter = kzalloc(sizeof(*cmd->read_iter), GFP_KERNEL); + if (!cmd->read_iter) return -ENOMEM; + + cmd->read_iov = dup_iter(cmd->read_iter, iter, GFP_KERNEL); + if (!cmd->read_iov) { + ret = -ENOMEM; + goto free_iter; + } } - for (i = 0; i < sg_count; i++) { + for_each_sgtable_sg(sg_table, sg, i) { page = alloc_page(GFP_KERNEL); if (!page) { - i--; + ret = -ENOMEM; goto err; } nbytes = min_t(unsigned int, PAGE_SIZE, len); - sg_set_page(&sg[i], page, nbytes, 0); + sg_set_page(sg, page, nbytes, 0); - if (cmd->tvc_data_direction == DMA_TO_DEVICE && - copy_page_from_iter(page, 0, nbytes, iter) != nbytes) + if (data_dir == DMA_TO_DEVICE && + copy_page_from_iter(page, 0, nbytes, iter) != nbytes) { + ret = -EFAULT; goto err; + } len -= nbytes; } @@ -790,66 +852,63 @@ vhost_scsi_copy_iov_to_sgl(struct vhost_scsi_cmd *cmd, struct iov_iter *iter, pr_err("Could not read %u bytes while handling misaligned cmd\n", nbytes); - for (; i >= 0; i--) - __free_page(sg_page(&sg[i])); - kfree(cmd->saved_iter_addr); - return -ENOMEM; + for_each_sgtable_sg(sg_table, sg, i) { + page = sg_page(sg); + if (page) + __free_page(page); + } + kfree(cmd->read_iov); +free_iter: + kfree(cmd->read_iter); + return ret; } static int vhost_scsi_map_iov_to_sgl(struct vhost_scsi_cmd *cmd, struct iov_iter *iter, - struct scatterlist *sg, int sg_count, bool is_prot) + struct sg_table *sg_table, int sg_count, bool is_prot) { - struct scatterlist *p = sg; - size_t revert_bytes; + struct scatterlist *sg = sg_table->sgl; int ret; while (iov_iter_count(iter)) { - ret = vhost_scsi_map_to_sgl(cmd, iter, sg, is_prot); + ret = vhost_scsi_map_to_sgl(cmd, iter, sg_table, &sg, is_prot); if (ret < 0) { - revert_bytes = 0; - - while (p < sg) { - struct page *page = sg_page(p); - - if (page) { - put_page(page); - revert_bytes += p->length; - } - p++; - } - - iov_iter_revert(iter, revert_bytes); + vhost_scsi_revert_map_iov_to_sgl(iter, sg_table->sgl, + sg); return ret; } - sg += ret; } return 0; } static int -vhost_scsi_mapal(struct vhost_scsi_cmd *cmd, +vhost_scsi_mapal(struct vhost_scsi *vs, struct vhost_scsi_cmd *cmd, size_t prot_bytes, struct iov_iter *prot_iter, - size_t data_bytes, struct iov_iter *data_iter) + size_t data_bytes, struct iov_iter *data_iter, int data_dir) { int sgl_count, ret; if (prot_bytes) { sgl_count = vhost_scsi_calc_sgls(prot_iter, prot_bytes, VHOST_SCSI_PREALLOC_PROT_SGLS); - if (sgl_count < 0) - return sgl_count; + cmd->prot_table.sgl = cmd->prot_sgl; + ret = sg_alloc_table_chained(&cmd->prot_table, sgl_count, + cmd->prot_table.sgl, + vs->inline_sg_cnt); + if (ret) + return ret; - sg_init_table(cmd->tvc_prot_sgl, sgl_count); cmd->tvc_prot_sgl_count = sgl_count; pr_debug("%s prot_sg %p prot_sgl_count %u\n", __func__, - cmd->tvc_prot_sgl, cmd->tvc_prot_sgl_count); + cmd->prot_table.sgl, cmd->tvc_prot_sgl_count); ret = vhost_scsi_map_iov_to_sgl(cmd, prot_iter, - cmd->tvc_prot_sgl, + &cmd->prot_table, cmd->tvc_prot_sgl_count, true); if (ret < 0) { + sg_free_table_chained(&cmd->prot_table, + vs->inline_sg_cnt); cmd->tvc_prot_sgl_count = 0; return ret; } @@ -859,20 +918,23 @@ vhost_scsi_mapal(struct vhost_scsi_cmd *cmd, if (sgl_count < 0) return sgl_count; - sg_init_table(cmd->tvc_sgl, sgl_count); + cmd->table.sgl = cmd->sgl; + ret = sg_alloc_table_chained(&cmd->table, sgl_count, cmd->table.sgl, + vs->inline_sg_cnt); + if (ret) + return ret; + cmd->tvc_sgl_count = sgl_count; pr_debug("%s data_sg %p data_sgl_count %u\n", __func__, - cmd->tvc_sgl, cmd->tvc_sgl_count); + cmd->table.sgl, cmd->tvc_sgl_count); - ret = vhost_scsi_map_iov_to_sgl(cmd, data_iter, cmd->tvc_sgl, + ret = vhost_scsi_map_iov_to_sgl(cmd, data_iter, &cmd->table, cmd->tvc_sgl_count, false); - if (ret == -EINVAL) { - sg_init_table(cmd->tvc_sgl, cmd->tvc_sgl_count); - ret = vhost_scsi_copy_iov_to_sgl(cmd, data_iter, cmd->tvc_sgl, - cmd->tvc_sgl_count); - } - + if (ret == -EINVAL) + ret = vhost_scsi_copy_iov_to_sgl(cmd, data_iter, &cmd->table, + cmd->tvc_sgl_count, data_dir); if (ret < 0) { + sg_free_table_chained(&cmd->table, vs->inline_sg_cnt); cmd->tvc_sgl_count = 0; return ret; } @@ -896,32 +958,33 @@ static int vhost_scsi_to_tcm_attr(int attr) return TCM_SIMPLE_TAG; } -static void vhost_scsi_target_queue_cmd(struct vhost_scsi_cmd *cmd) +static void vhost_scsi_target_queue_cmd(struct vhost_scsi_nexus *nexus, + struct vhost_scsi_cmd *cmd, + unsigned char *cdb, u16 lun, + int task_attr, int data_dir, + u32 exp_data_len) { struct se_cmd *se_cmd = &cmd->tvc_se_cmd; - struct vhost_scsi_nexus *tv_nexus; struct scatterlist *sg_ptr, *sg_prot_ptr = NULL; /* FIXME: BIDI operation */ if (cmd->tvc_sgl_count) { - sg_ptr = cmd->tvc_sgl; + sg_ptr = cmd->table.sgl; if (cmd->tvc_prot_sgl_count) - sg_prot_ptr = cmd->tvc_prot_sgl; + sg_prot_ptr = cmd->prot_table.sgl; else se_cmd->prot_pto = true; } else { sg_ptr = NULL; } - tv_nexus = cmd->tvc_nexus; se_cmd->tag = 0; - target_init_cmd(se_cmd, tv_nexus->tvn_se_sess, &cmd->tvc_sense_buf[0], - cmd->tvc_lun, cmd->tvc_exp_data_len, - vhost_scsi_to_tcm_attr(cmd->tvc_task_attr), - cmd->tvc_data_direction, TARGET_SCF_ACK_KREF); + target_init_cmd(se_cmd, nexus->tvn_se_sess, &cmd->tvc_sense_buf[0], + lun, exp_data_len, vhost_scsi_to_tcm_attr(task_attr), + data_dir, TARGET_SCF_ACK_KREF); - if (target_submit_prep(se_cmd, cmd->tvc_cdb, sg_ptr, + if (target_submit_prep(se_cmd, cdb, sg_ptr, cmd->tvc_sgl_count, NULL, 0, sg_prot_ptr, cmd->tvc_prot_sgl_count, GFP_KERNEL)) return; @@ -930,6 +993,24 @@ static void vhost_scsi_target_queue_cmd(struct vhost_scsi_cmd *cmd) } static void +vhost_scsi_send_status(struct vhost_scsi *vs, struct vhost_virtqueue *vq, + int head, unsigned int out, u8 status) +{ + struct virtio_scsi_cmd_resp __user *resp; + struct virtio_scsi_cmd_resp rsp; + int ret; + + memset(&rsp, 0, sizeof(rsp)); + rsp.status = status; + resp = vq->iov[out].iov_base; + ret = __copy_to_user(resp, &rsp, sizeof(rsp)); + if (!ret) + vhost_add_used_and_signal(&vs->dev, vq, head, 0); + else + pr_err("Faulted on virtio_scsi_cmd_resp\n"); +} + +static void vhost_scsi_send_bad_target(struct vhost_scsi *vs, struct vhost_virtqueue *vq, int head, unsigned out) @@ -1049,6 +1130,43 @@ vhost_scsi_get_req(struct vhost_virtqueue *vq, struct vhost_scsi_ctx *vc, return ret; } +static int +vhost_scsi_setup_resp_iovs(struct vhost_scsi_cmd *cmd, struct iovec *in_iovs, + unsigned int in_iovs_cnt) +{ + int i, cnt; + + if (!in_iovs_cnt) + return 0; + /* + * Initiator's normally just put the virtio_scsi_cmd_resp in the first + * iov, but just in case they wedged in some data with it we check for + * greater than or equal to the response struct. + */ + if (in_iovs[0].iov_len >= sizeof(struct virtio_scsi_cmd_resp)) { + cmd->tvc_resp_iovs = &cmd->tvc_resp_iov; + cmd->tvc_resp_iovs_cnt = 1; + } else { + /* + * Legacy descriptor layouts didn't specify that we must put + * the entire response in one iov. Worst case we have a + * iov per byte. + */ + cnt = min(VHOST_SCSI_MAX_RESP_IOVS, in_iovs_cnt); + cmd->tvc_resp_iovs = kcalloc(cnt, sizeof(struct iovec), + GFP_KERNEL); + if (!cmd->tvc_resp_iovs) + return -ENOMEM; + + cmd->tvc_resp_iovs_cnt = cnt; + } + + for (i = 0; i < cmd->tvc_resp_iovs_cnt; i++) + cmd->tvc_resp_iovs[i] = in_iovs[i]; + + return 0; +} + static u16 vhost_buf_to_lun(u8 *lun_buf) { return ((lun_buf[2] << 8) | lun_buf[3]) & 0x3FFF; @@ -1060,16 +1178,17 @@ vhost_scsi_handle_vq(struct vhost_scsi *vs, struct vhost_virtqueue *vq) struct vhost_scsi_tpg **vs_tpg, *tpg; struct virtio_scsi_cmd_req v_req; struct virtio_scsi_cmd_req_pi v_req_pi; + struct vhost_scsi_nexus *nexus; struct vhost_scsi_ctx vc; struct vhost_scsi_cmd *cmd; struct iov_iter in_iter, prot_iter, data_iter; u64 tag; u32 exp_data_len, data_direction; - int ret, prot_bytes, i, c = 0; + int ret, prot_bytes, c = 0; u16 lun; u8 task_attr; bool t10_pi = vhost_has_feature(vq, VIRTIO_SCSI_F_T10_PI); - void *cdb; + u8 *cdb; mutex_lock(&vq->mutex); /* @@ -1212,29 +1331,39 @@ vhost_scsi_handle_vq(struct vhost_scsi *vs, struct vhost_virtqueue *vq) scsi_command_size(cdb), VHOST_SCSI_MAX_CDB_SIZE); goto err; } - cmd = vhost_scsi_get_cmd(vq, tpg, cdb, tag, lun, task_attr, - exp_data_len + prot_bytes, - data_direction); - if (IS_ERR(cmd)) { - vq_err(vq, "vhost_scsi_get_cmd failed %ld\n", - PTR_ERR(cmd)); + + nexus = tpg->tpg_nexus; + if (!nexus) { + vq_err(vq, "Unable to locate active struct vhost_scsi_nexus\n"); + ret = -EIO; goto err; } - cmd->tvc_vhost = vs; + + cmd = vhost_scsi_get_cmd(vq, tag); + if (IS_ERR(cmd)) { + ret = PTR_ERR(cmd); + vq_err(vq, "vhost_scsi_get_tag failed %dd\n", ret); + goto err; + } cmd->tvc_vq = vq; - for (i = 0; i < vc.in ; i++) - cmd->tvc_resp_iov[i] = vq->iov[vc.out + i]; - cmd->tvc_in_iovs = vc.in; + + ret = vhost_scsi_setup_resp_iovs(cmd, &vq->iov[vc.out], vc.in); + if (ret) { + vq_err(vq, "Failed to alloc recv iovs\n"); + vhost_scsi_release_cmd_res(&cmd->tvc_se_cmd); + goto err; + } pr_debug("vhost_scsi got command opcode: %#02x, lun: %d\n", - cmd->tvc_cdb[0], cmd->tvc_lun); + cdb[0], lun); pr_debug("cmd: %p exp_data_len: %d, prot_bytes: %d data_direction:" " %d\n", cmd, exp_data_len, prot_bytes, data_direction); if (data_direction != DMA_NONE) { - if (unlikely(vhost_scsi_mapal(cmd, prot_bytes, - &prot_iter, exp_data_len, - &data_iter))) { + ret = vhost_scsi_mapal(vs, cmd, prot_bytes, &prot_iter, + exp_data_len, &data_iter, + data_direction); + if (unlikely(ret)) { vq_err(vq, "Failed to map iov to sgl\n"); vhost_scsi_release_cmd_res(&cmd->tvc_se_cmd); goto err; @@ -1246,7 +1375,9 @@ vhost_scsi_handle_vq(struct vhost_scsi *vs, struct vhost_virtqueue *vq) * vhost_scsi_queue_data_in() and vhost_scsi_queue_status() */ cmd->tvc_vq_desc = vc.head; - vhost_scsi_target_queue_cmd(cmd); + vhost_scsi_target_queue_cmd(nexus, cmd, cdb, lun, task_attr, + data_direction, + exp_data_len + prot_bytes); ret = 0; err: /* @@ -1254,11 +1385,15 @@ vhost_scsi_handle_vq(struct vhost_scsi *vs, struct vhost_virtqueue *vq) * EINVAL: Invalid response buffer, drop the request * EIO: Respond with bad target * EAGAIN: Pending request + * ENOMEM: Could not allocate resources for request */ if (ret == -ENXIO) break; else if (ret == -EIO) vhost_scsi_send_bad_target(vs, vq, vc.head, vc.out); + else if (ret == -ENOMEM) + vhost_scsi_send_status(vs, vq, vc.head, vc.out, + SAM_STAT_TASK_SET_FULL); } while (likely(!vhost_exceeds_weight(vq, ++c, 0))); out: mutex_unlock(&vq->mutex); @@ -1596,13 +1731,12 @@ static void vhost_scsi_destroy_vq_cmds(struct vhost_virtqueue *vq) for (i = 0; i < svq->max_cmds; i++) { tv_cmd = &svq->scsi_cmds[i]; - kfree(tv_cmd->tvc_sgl); - kfree(tv_cmd->tvc_prot_sgl); - kfree(tv_cmd->tvc_upages); - kfree(tv_cmd->tvc_resp_iov); + kfree(tv_cmd->sgl); + kfree(tv_cmd->prot_sgl); } sbitmap_free(&svq->scsi_tags); + kfree(svq->upages); kfree(svq->scsi_cmds); svq->scsi_cmds = NULL; } @@ -1611,6 +1745,7 @@ static int vhost_scsi_setup_vq_cmds(struct vhost_virtqueue *vq, int max_cmds) { struct vhost_scsi_virtqueue *svq = container_of(vq, struct vhost_scsi_virtqueue, vq); + struct vhost_scsi *vs = svq->vs; struct vhost_scsi_cmd *tv_cmd; unsigned int i; @@ -1628,39 +1763,33 @@ static int vhost_scsi_setup_vq_cmds(struct vhost_virtqueue *vq, int max_cmds) return -ENOMEM; } + svq->upages = kcalloc(VHOST_SCSI_PREALLOC_UPAGES, sizeof(struct page *), + GFP_KERNEL); + if (!svq->upages) + goto out; + for (i = 0; i < max_cmds; i++) { tv_cmd = &svq->scsi_cmds[i]; - tv_cmd->tvc_sgl = kcalloc(VHOST_SCSI_PREALLOC_SGLS, - sizeof(struct scatterlist), - GFP_KERNEL); - if (!tv_cmd->tvc_sgl) { - pr_err("Unable to allocate tv_cmd->tvc_sgl\n"); - goto out; + if (vs->inline_sg_cnt) { + tv_cmd->sgl = kcalloc(vs->inline_sg_cnt, + sizeof(struct scatterlist), + GFP_KERNEL); + if (!tv_cmd->sgl) { + pr_err("Unable to allocate tv_cmd->sgl\n"); + goto out; + } } - tv_cmd->tvc_upages = kcalloc(VHOST_SCSI_PREALLOC_UPAGES, - sizeof(struct page *), - GFP_KERNEL); - if (!tv_cmd->tvc_upages) { - pr_err("Unable to allocate tv_cmd->tvc_upages\n"); - goto out; - } - - tv_cmd->tvc_resp_iov = kcalloc(UIO_MAXIOV, - sizeof(struct iovec), - GFP_KERNEL); - if (!tv_cmd->tvc_resp_iov) { - pr_err("Unable to allocate tv_cmd->tvc_resp_iov\n"); - goto out; - } - - tv_cmd->tvc_prot_sgl = kcalloc(VHOST_SCSI_PREALLOC_PROT_SGLS, - sizeof(struct scatterlist), - GFP_KERNEL); - if (!tv_cmd->tvc_prot_sgl) { - pr_err("Unable to allocate tv_cmd->tvc_prot_sgl\n"); - goto out; + if (vhost_has_feature(vq, VIRTIO_SCSI_F_T10_PI) && + vs->inline_sg_cnt) { + tv_cmd->prot_sgl = kcalloc(vs->inline_sg_cnt, + sizeof(struct scatterlist), + GFP_KERNEL); + if (!tv_cmd->prot_sgl) { + pr_err("Unable to allocate tv_cmd->prot_sgl\n"); + goto out; + } } } return 0; @@ -1699,14 +1828,19 @@ vhost_scsi_set_endpoint(struct vhost_scsi *vs, } } + if (vs->vs_tpg) { + pr_err("vhost-scsi endpoint already set for %s.\n", + vs->vs_vhost_wwpn); + ret = -EEXIST; + goto out; + } + len = sizeof(vs_tpg[0]) * VHOST_SCSI_MAX_TARGET; vs_tpg = kzalloc(len, GFP_KERNEL); if (!vs_tpg) { ret = -ENOMEM; goto out; } - if (vs->vs_tpg) - memcpy(vs_tpg, vs->vs_tpg, len); mutex_lock(&vhost_scsi_mutex); list_for_each_entry(tpg, &vhost_scsi_list, tv_tpg_list) { @@ -1722,12 +1856,6 @@ vhost_scsi_set_endpoint(struct vhost_scsi *vs, tv_tport = tpg->tport; if (!strcmp(tv_tport->tport_name, t->vhost_wwpn)) { - if (vs->vs_tpg && vs->vs_tpg[tpg->tport_tpgt]) { - mutex_unlock(&tpg->tv_tpg_mutex); - mutex_unlock(&vhost_scsi_mutex); - ret = -EEXIST; - goto undepend; - } /* * In order to ensure individual vhost-scsi configfs * groups cannot be removed while in use by vhost ioctl, @@ -1774,15 +1902,15 @@ vhost_scsi_set_endpoint(struct vhost_scsi *vs, } ret = 0; } else { - ret = -EEXIST; + ret = -ENODEV; + goto free_tpg; } /* - * Act as synchronize_rcu to make sure access to - * old vs->vs_tpg is finished. + * Act as synchronize_rcu to make sure requests after this point + * see a fully setup device. */ vhost_scsi_flush(vs); - kfree(vs->vs_tpg); vs->vs_tpg = vs_tpg; goto out; @@ -1802,6 +1930,7 @@ vhost_scsi_set_endpoint(struct vhost_scsi *vs, target_undepend_item(&tpg->se_tpg.tpg_group.cg_item); } } +free_tpg: kfree(vs_tpg); out: mutex_unlock(&vs->dev.mutex); @@ -1904,6 +2033,7 @@ vhost_scsi_clear_endpoint(struct vhost_scsi *vs, vhost_scsi_flush(vs); kfree(vs->vs_tpg); vs->vs_tpg = NULL; + memset(vs->vs_vhost_wwpn, 0, sizeof(vs->vs_vhost_wwpn)); WARN_ON(vs->vs_events_nr); mutex_unlock(&vs->dev.mutex); return 0; @@ -1948,6 +2078,7 @@ static int vhost_scsi_open(struct inode *inode, struct file *f) vs = kvzalloc(sizeof(*vs), GFP_KERNEL); if (!vs) goto err_vs; + vs->inline_sg_cnt = vhost_scsi_inline_sg_cnt; if (nvqs > VHOST_SCSI_MAX_IO_VQ) { pr_err("Invalid max_io_vqs of %d. Using %d.\n", nvqs,
diff --git a/drivers/video/fbdev/aty/radeon_backlight.c b/drivers/video/fbdev/aty/radeon_backlight.c index 9e41d2a..bf764c9 100644 --- a/drivers/video/fbdev/aty/radeon_backlight.c +++ b/drivers/video/fbdev/aty/radeon_backlight.c
@@ -59,7 +59,7 @@ static int radeon_bl_update_status(struct backlight_device *bd) */ level = backlight_get_brightness(bd); - del_timer_sync(&rinfo->lvds_timer); + timer_delete_sync(&rinfo->lvds_timer); radeon_engine_idle(); lvds_gen_cntl = INREG(LVDS_GEN_CNTL);
diff --git a/drivers/video/fbdev/aty/radeon_base.c b/drivers/video/fbdev/aty/radeon_base.c index d866608..c6c4753 100644 --- a/drivers/video/fbdev/aty/radeon_base.c +++ b/drivers/video/fbdev/aty/radeon_base.c
@@ -1082,7 +1082,7 @@ int radeon_screen_blank(struct radeonfb_info *rinfo, int blank, int mode_switch) } break; case MT_LCD: - del_timer_sync(&rinfo->lvds_timer); + timer_delete_sync(&rinfo->lvds_timer); val = INREG(LVDS_GEN_CNTL); if (unblank) { u32 target_val = (val & ~LVDS_DISPLAY_DIS) | LVDS_BLON | LVDS_ON @@ -2516,7 +2516,7 @@ static void radeonfb_pci_unregister(struct pci_dev *pdev) if (rinfo->mon2_EDID) sysfs_remove_bin_file(&rinfo->pdev->dev.kobj, &edid2_attr); - del_timer_sync(&rinfo->lvds_timer); + timer_delete_sync(&rinfo->lvds_timer); arch_phys_wc_del(rinfo->wc_cookie); radeonfb_bl_exit(rinfo); unregister_framebuffer(info);
diff --git a/drivers/video/fbdev/aty/radeon_pm.c b/drivers/video/fbdev/aty/radeon_pm.c index 97a5972..5ff4a96 100644 --- a/drivers/video/fbdev/aty/radeon_pm.c +++ b/drivers/video/fbdev/aty/radeon_pm.c
@@ -2650,7 +2650,7 @@ static int radeonfb_pci_suspend_late(struct device *dev, pm_message_t mesg) /* Sleep */ rinfo->asleep = 1; rinfo->lock_blank = 1; - del_timer_sync(&rinfo->lvds_timer); + timer_delete_sync(&rinfo->lvds_timer); #ifdef CONFIG_PPC_PMAC /* On powermac, we have hooks to properly suspend/resume AGP now,
diff --git a/drivers/video/fbdev/omap/hwa742.c b/drivers/video/fbdev/omap/hwa742.c index 161fc65..64e76e1f 100644 --- a/drivers/video/fbdev/omap/hwa742.c +++ b/drivers/video/fbdev/omap/hwa742.c
@@ -597,7 +597,7 @@ static int hwa742_set_update_mode(enum omapfb_update_mode mode) break; case OMAPFB_AUTO_UPDATE: hwa742.stop_auto_update = 1; - del_timer_sync(&hwa742.auto_update_timer); + timer_delete_sync(&hwa742.auto_update_timer); break; case OMAPFB_UPDATE_DISABLED: break;
diff --git a/drivers/video/fbdev/omap2/omapfb/dss/dsi.c b/drivers/video/fbdev/omap2/omapfb/dss/dsi.c index 1f3434c..370e862 100644 --- a/drivers/video/fbdev/omap2/omapfb/dss/dsi.c +++ b/drivers/video/fbdev/omap2/omapfb/dss/dsi.c
@@ -835,7 +835,7 @@ static irqreturn_t omap_dsi_irq_handler(int irq, void *arg) #ifdef DSI_CATCH_MISSING_TE if (irqstatus & DSI_IRQ_TE_TRIGGER) - del_timer(&dsi->te_timer); + timer_delete(&dsi->te_timer); #endif /* make a copy and unlock, so that isrs can unregister
diff --git a/drivers/virt/vboxguest/vboxguest_core.c b/drivers/virt/vboxguest/vboxguest_core.c index c6e9855..f1674f3 100644 --- a/drivers/virt/vboxguest/vboxguest_core.c +++ b/drivers/virt/vboxguest/vboxguest_core.c
@@ -495,7 +495,7 @@ static int vbg_heartbeat_init(struct vbg_dev *gdev) */ static void vbg_heartbeat_exit(struct vbg_dev *gdev) { - del_timer_sync(&gdev->heartbeat_timer); + timer_delete_sync(&gdev->heartbeat_timer); vbg_heartbeat_host_config(gdev, false); vbg_req_free(gdev->guest_heartbeat_req, sizeof(*gdev->guest_heartbeat_req));
diff --git a/drivers/virtio/virtio.c b/drivers/virtio/virtio.c index ba37665..150753c 100644 --- a/drivers/virtio/virtio.c +++ b/drivers/virtio/virtio.c
@@ -395,6 +395,34 @@ static const struct cpumask *virtio_irq_get_affinity(struct device *_d, return dev->config->get_vq_affinity(dev, irq_vec); } +static void virtio_dev_shutdown(struct device *_d) +{ + struct virtio_device *dev = dev_to_virtio(_d); + struct virtio_driver *drv = drv_to_virtio(dev->dev.driver); + + /* + * Stop accesses to or from the device. + * We only need to do it if there's a driver - no accesses otherwise. + */ + if (!drv) + return; + + /* + * Some devices get wedged if you kick them after they are + * reset. Mark all vqs as broken to make sure we don't. + */ + virtio_break_device(dev); + /* + * Guarantee that any callback will see vq->broken as true. + */ + virtio_synchronize_cbs(dev); + /* + * As IOMMUs are reset on shutdown, this will block device access to memory. + * Some devices get wedged if this happens, so reset to make sure it does not. + */ + dev->config->reset(dev); +} + static const struct bus_type virtio_bus = { .name = "virtio", .match = virtio_dev_match, @@ -403,6 +431,7 @@ static const struct bus_type virtio_bus = { .probe = virtio_dev_probe, .remove = virtio_dev_remove, .irq_get_affinity = virtio_irq_get_affinity, + .shutdown = virtio_dev_shutdown, }; int __register_virtio_driver(struct virtio_driver *driver, struct module *owner)
diff --git a/drivers/watchdog/alim7101_wdt.c b/drivers/watchdog/alim7101_wdt.c index 9c7cf93..03a559b 100644 --- a/drivers/watchdog/alim7101_wdt.c +++ b/drivers/watchdog/alim7101_wdt.c
@@ -166,7 +166,7 @@ static void wdt_startup(void) static void wdt_turnoff(void) { /* Stop the timer */ - del_timer_sync(&timer); + timer_delete_sync(&timer); wdt_change(WDT_DISABLE); pr_info("Watchdog timer is now disabled...\n"); } @@ -223,7 +223,7 @@ static int fop_close(struct inode *inode, struct file *file) if (wdt_expect_close == 42) wdt_turnoff(); else { - /* wim: shouldn't there be a: del_timer(&timer); */ + /* wim: shouldn't there be a: timer_delete(&timer); */ pr_crit("device file closed unexpectedly. Will not stop the WDT!\n"); } clear_bit(0, &wdt_is_open);
diff --git a/drivers/watchdog/at91sam9_wdt.c b/drivers/watchdog/at91sam9_wdt.c index 7be70b9..1b47a2f 100644 --- a/drivers/watchdog/at91sam9_wdt.c +++ b/drivers/watchdog/at91sam9_wdt.c
@@ -242,7 +242,7 @@ static int at91_wdt_init(struct platform_device *pdev, struct at91wdt *wdt) return 0; out_stop_timer: - del_timer(&wdt->timer); + timer_delete(&wdt->timer); return err; } @@ -378,7 +378,7 @@ static void at91wdt_remove(struct platform_device *pdev) watchdog_unregister_device(&wdt->wdd); pr_warn("I quit now, hardware will probably reboot!\n"); - del_timer(&wdt->timer); + timer_delete(&wdt->timer); } #if defined(CONFIG_OF)
diff --git a/drivers/watchdog/bcm47xx_wdt.c b/drivers/watchdog/bcm47xx_wdt.c index 06a54c7..4c09513 100644 --- a/drivers/watchdog/bcm47xx_wdt.c +++ b/drivers/watchdog/bcm47xx_wdt.c
@@ -139,7 +139,7 @@ static int bcm47xx_wdt_soft_stop(struct watchdog_device *wdd) { struct bcm47xx_wdt *wdt = bcm47xx_wdt_get(wdd); - del_timer_sync(&wdt->soft_timer); + timer_delete_sync(&wdt->soft_timer); wdt->timer_set(wdt, 0); return 0; @@ -213,7 +213,7 @@ static int bcm47xx_wdt_probe(struct platform_device *pdev) err_timer: if (soft) - del_timer_sync(&wdt->soft_timer); + timer_delete_sync(&wdt->soft_timer); return ret; }
diff --git a/drivers/watchdog/cpwd.c b/drivers/watchdog/cpwd.c index 4fb92c9..13a4d47e 100644 --- a/drivers/watchdog/cpwd.c +++ b/drivers/watchdog/cpwd.c
@@ -240,7 +240,7 @@ static void cpwd_brokentimer(struct timer_list *unused) * were called directly instead of by kernel timer */ if (timer_pending(&cpwd_timer)) - del_timer(&cpwd_timer); + timer_delete(&cpwd_timer); for (id = 0; id < WD_NUMDEVS; id++) { if (p->devs[id].runstatus & WD_STAT_BSTOP) { @@ -629,7 +629,7 @@ static void cpwd_remove(struct platform_device *op) } if (p->broken) - del_timer_sync(&cpwd_timer); + timer_delete_sync(&cpwd_timer); if (p->initialized) free_irq(p->irq, p);
diff --git a/drivers/watchdog/lpc18xx_wdt.c b/drivers/watchdog/lpc18xx_wdt.c index f19580e..28e3fc0 100644 --- a/drivers/watchdog/lpc18xx_wdt.c +++ b/drivers/watchdog/lpc18xx_wdt.c
@@ -135,7 +135,7 @@ static int lpc18xx_wdt_start(struct watchdog_device *wdt_dev) unsigned int val; if (timer_pending(&lpc18xx_wdt->timer)) - del_timer(&lpc18xx_wdt->timer); + timer_delete(&lpc18xx_wdt->timer); val = readl(lpc18xx_wdt->base + LPC18XX_WDT_MOD); val |= LPC18XX_WDT_MOD_WDEN; @@ -266,7 +266,7 @@ static void lpc18xx_wdt_remove(struct platform_device *pdev) struct lpc18xx_wdt_dev *lpc18xx_wdt = platform_get_drvdata(pdev); dev_warn(&pdev->dev, "I quit now, hardware will probably reboot!\n"); - del_timer_sync(&lpc18xx_wdt->timer); + timer_delete_sync(&lpc18xx_wdt->timer); } static const struct of_device_id lpc18xx_wdt_match[] = {
diff --git a/drivers/watchdog/machzwd.c b/drivers/watchdog/machzwd.c index 73d6414..0ae8e5b 100644 --- a/drivers/watchdog/machzwd.c +++ b/drivers/watchdog/machzwd.c
@@ -189,7 +189,7 @@ static void zf_timer_off(void) unsigned long flags; /* stop internal ping */ - del_timer_sync(&zf_timer); + timer_delete_sync(&zf_timer); spin_lock_irqsave(&zf_port_lock, flags); /* stop watchdog timer */ @@ -337,7 +337,7 @@ static int zf_close(struct inode *inode, struct file *file) if (zf_expect_close == 42) zf_timer_off(); else { - del_timer(&zf_timer); + timer_delete(&zf_timer); pr_err("device file closed unexpectedly. Will not stop the WDT!\n"); } clear_bit(0, &zf_is_open);
diff --git a/drivers/watchdog/mixcomwd.c b/drivers/watchdog/mixcomwd.c index 70d9cf8..1ecd5c4 100644 --- a/drivers/watchdog/mixcomwd.c +++ b/drivers/watchdog/mixcomwd.c
@@ -141,7 +141,7 @@ static int mixcomwd_open(struct inode *inode, struct file *file) __module_get(THIS_MODULE); else { if (mixcomwd_timer_alive) { - del_timer(&mixcomwd_timer); + timer_delete(&mixcomwd_timer); mixcomwd_timer_alive = 0; } } @@ -295,7 +295,7 @@ static void __exit mixcomwd_exit(void) if (!nowayout) { if (mixcomwd_timer_alive) { pr_warn("I quit now, hardware will probably reboot!\n"); - del_timer_sync(&mixcomwd_timer); + timer_delete_sync(&mixcomwd_timer); mixcomwd_timer_alive = 0; } }
diff --git a/drivers/watchdog/pcwd.c b/drivers/watchdog/pcwd.c index 31d3dcb..d4ea7d6 100644 --- a/drivers/watchdog/pcwd.c +++ b/drivers/watchdog/pcwd.c
@@ -432,7 +432,7 @@ static int pcwd_stop(void) int stat_reg; /* Stop the timer */ - del_timer(&pcwd_private.timer); + timer_delete(&pcwd_private.timer); /* Disable the board */ if (pcwd_private.revision == PCWD_REVISION_C) {
diff --git a/drivers/watchdog/pika_wdt.c b/drivers/watchdog/pika_wdt.c index 393aa4b..87b8988 100644 --- a/drivers/watchdog/pika_wdt.c +++ b/drivers/watchdog/pika_wdt.c
@@ -129,7 +129,7 @@ static int pikawdt_release(struct inode *inode, struct file *file) { /* stop internal ping */ if (!pikawdt_private.expect_close) - del_timer(&pikawdt_private.timer); + timer_delete(&pikawdt_private.timer); clear_bit(0, &pikawdt_private.open); pikawdt_private.expect_close = 0;
diff --git a/drivers/watchdog/sbc60xxwdt.c b/drivers/watchdog/sbc60xxwdt.c index e9bf129..03eaf48 100644 --- a/drivers/watchdog/sbc60xxwdt.c +++ b/drivers/watchdog/sbc60xxwdt.c
@@ -146,7 +146,7 @@ static void wdt_startup(void) static void wdt_turnoff(void) { /* Stop the timer */ - del_timer_sync(&timer); + timer_delete_sync(&timer); inb_p(wdt_stop); pr_info("Watchdog timer is now disabled...\n"); } @@ -210,7 +210,7 @@ static int fop_close(struct inode *inode, struct file *file) if (wdt_expect_close == 42) wdt_turnoff(); else { - del_timer(&timer); + timer_delete(&timer); pr_crit("device file closed unexpectedly. Will not stop the WDT!\n"); } clear_bit(0, &wdt_is_open);
diff --git a/drivers/watchdog/sc520_wdt.c b/drivers/watchdog/sc520_wdt.c index e849e1a..005f62e 100644 --- a/drivers/watchdog/sc520_wdt.c +++ b/drivers/watchdog/sc520_wdt.c
@@ -186,7 +186,7 @@ static int wdt_startup(void) static int wdt_turnoff(void) { /* Stop the timer */ - del_timer_sync(&timer); + timer_delete_sync(&timer); /* Stop the watchdog */ wdt_config(0);
diff --git a/drivers/watchdog/shwdt.c b/drivers/watchdog/shwdt.c index 7f0150c..95af9ad 100644 --- a/drivers/watchdog/shwdt.c +++ b/drivers/watchdog/shwdt.c
@@ -129,7 +129,7 @@ static int sh_wdt_stop(struct watchdog_device *wdt_dev) spin_lock_irqsave(&wdt->lock, flags); - del_timer(&wdt->timer); + timer_delete(&wdt->timer); csr = sh_wdt_read_csr(); csr &= ~WTCSR_TME;
diff --git a/drivers/watchdog/via_wdt.c b/drivers/watchdog/via_wdt.c index eeb39f9..d647923 100644 --- a/drivers/watchdog/via_wdt.c +++ b/drivers/watchdog/via_wdt.c
@@ -233,7 +233,7 @@ static int wdt_probe(struct pci_dev *pdev, static void wdt_remove(struct pci_dev *pdev) { watchdog_unregister_device(&wdt_dev); - del_timer_sync(&timer); + timer_delete_sync(&timer); iounmap(wdt_mem); release_mem_region(mmio, VIA_WDT_MMIO_LEN); release_resource(&wdt_res);
diff --git a/drivers/watchdog/w83877f_wdt.c b/drivers/watchdog/w83877f_wdt.c index 1937084..53db59e 100644 --- a/drivers/watchdog/w83877f_wdt.c +++ b/drivers/watchdog/w83877f_wdt.c
@@ -166,7 +166,7 @@ static void wdt_startup(void) static void wdt_turnoff(void) { /* Stop the timer */ - del_timer_sync(&timer); + timer_delete_sync(&timer); wdt_change(WDT_DISABLE); @@ -228,7 +228,7 @@ static int fop_close(struct inode *inode, struct file *file) if (wdt_expect_close == 42) wdt_turnoff(); else { - del_timer(&timer); + timer_delete(&timer); pr_crit("device file closed unexpectedly. Will not stop the WDT!\n"); } clear_bit(0, &wdt_is_open);
diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c index cc2007b..5b5fda6 100644 --- a/fs/9p/vfs_inode_dotl.c +++ b/fs/9p/vfs_inode_dotl.c
@@ -407,8 +407,8 @@ static struct dentry *v9fs_vfs_mkdir_dotl(struct mnt_idmap *idmap, err); goto error; } - v9fs_fid_add(dentry, &fid); v9fs_set_create_acl(inode, fid, dacl, pacl); + v9fs_fid_add(dentry, &fid); d_instantiate(dentry, inode); err = 0; inc_nlink(dir);
diff --git a/fs/afs/fs_probe.c b/fs/afs/fs_probe.c index 07a8bfb..e0030ac 100644 --- a/fs/afs/fs_probe.c +++ b/fs/afs/fs_probe.c
@@ -534,6 +534,6 @@ int afs_wait_for_one_fs_probe(struct afs_server *server, struct afs_endpoint_sta */ void afs_fs_probe_cleanup(struct afs_net *net) { - if (del_timer_sync(&net->fs_probe_timer)) + if (timer_delete_sync(&net->fs_probe_timer)) afs_dec_servers_outstanding(net); }
diff --git a/fs/afs/server.c b/fs/afs/server.c index c530d1c..8755f27 100644 --- a/fs/afs/server.c +++ b/fs/afs/server.c
@@ -318,7 +318,7 @@ struct afs_server *afs_use_server(struct afs_server *server, bool activate, a = atomic_inc_return(&server->active); if (a == 1 && activate && !test_bit(AFS_SERVER_FL_EXPIRED, &server->flags)) - del_timer(&server->timer); + timer_delete(&server->timer); trace_afs_server(server->debug_id, r + 1, a, reason); return server;
diff --git a/fs/bcachefs/Kconfig b/fs/bcachefs/Kconfig index c979875..adcf425 100644 --- a/fs/bcachefs/Kconfig +++ b/fs/bcachefs/Kconfig
@@ -4,7 +4,7 @@ depends on BLOCK select EXPORTFS select CLOSURES - select LIBCRC32C + select CRC32 select CRC64 select FS_POSIX_ACL select LZ4_COMPRESS @@ -26,6 +26,7 @@ select SRCU select SYMBOLIC_ERRNAME select MIN_HEAP + select XARRAY_MULTI help The bcachefs filesystem - a modern, copy on write filesystem, with support for multiple devices, compression, checksumming, etc.
diff --git a/fs/bcachefs/acl.c b/fs/bcachefs/acl.c index 9948772..d03adc36 100644 --- a/fs/bcachefs/acl.c +++ b/fs/bcachefs/acl.c
@@ -273,7 +273,7 @@ struct posix_acl *bch2_get_acl(struct inode *vinode, int type, bool rcu) struct bch_fs *c = inode->v.i_sb->s_fs_info; struct bch_hash_info hash = bch2_hash_info_init(c, &inode->ei_inode); struct xattr_search_key search = X_SEARCH(acl_to_xattr_type(type), "", 0); - struct btree_iter iter = { NULL }; + struct btree_iter iter = {}; struct posix_acl *acl = NULL; if (rcu) @@ -344,7 +344,7 @@ int bch2_set_acl(struct mnt_idmap *idmap, { struct bch_inode_info *inode = to_bch_ei(dentry->d_inode); struct bch_fs *c = inode->v.i_sb->s_fs_info; - struct btree_iter inode_iter = { NULL }; + struct btree_iter inode_iter = {}; struct bch_inode_unpacked inode_u; struct posix_acl *acl; umode_t mode;
diff --git a/fs/bcachefs/alloc_background.c b/fs/bcachefs/alloc_background.c index c12ca75..94ea9e4 100644 --- a/fs/bcachefs/alloc_background.c +++ b/fs/bcachefs/alloc_background.c
@@ -610,7 +610,7 @@ int bch2_alloc_read(struct bch_fs *c) * bch2_check_alloc_key() which runs later: */ if (!ca) { - bch2_btree_iter_set_pos(&iter, POS(k.k->p.inode + 1, 0)); + bch2_btree_iter_set_pos(trans, &iter, POS(k.k->p.inode + 1, 0)); continue; } @@ -631,17 +631,17 @@ int bch2_alloc_read(struct bch_fs *c) * bch2_check_alloc_key() which runs later: */ if (!ca) { - bch2_btree_iter_set_pos(&iter, POS(k.k->p.inode + 1, 0)); + bch2_btree_iter_set_pos(trans, &iter, POS(k.k->p.inode + 1, 0)); continue; } if (k.k->p.offset < ca->mi.first_bucket) { - bch2_btree_iter_set_pos(&iter, POS(k.k->p.inode, ca->mi.first_bucket)); + bch2_btree_iter_set_pos(trans, &iter, POS(k.k->p.inode, ca->mi.first_bucket)); continue; } if (k.k->p.offset >= ca->mi.nbuckets) { - bch2_btree_iter_set_pos(&iter, POS(k.k->p.inode + 1, 0)); + bch2_btree_iter_set_pos(trans, &iter, POS(k.k->p.inode + 1, 0)); continue; } @@ -1039,9 +1039,10 @@ int bch2_trigger_alloc(struct btree_trans *trans, * This synthesizes deleted extents for holes, similar to BTREE_ITER_slots for * extents style btrees, but works on non-extents btrees: */ -static struct bkey_s_c bch2_get_key_or_hole(struct btree_iter *iter, struct bpos end, struct bkey *hole) +static struct bkey_s_c bch2_get_key_or_hole(struct btree_trans *trans, struct btree_iter *iter, + struct bpos end, struct bkey *hole) { - struct bkey_s_c k = bch2_btree_iter_peek_slot(iter); + struct bkey_s_c k = bch2_btree_iter_peek_slot(trans, iter); if (bkey_err(k)) return k; @@ -1052,9 +1053,9 @@ static struct bkey_s_c bch2_get_key_or_hole(struct btree_iter *iter, struct bpos struct btree_iter iter2; struct bpos next; - bch2_trans_copy_iter(&iter2, iter); + bch2_trans_copy_iter(trans, &iter2, iter); - struct btree_path *path = btree_iter_path(iter->trans, iter); + struct btree_path *path = btree_iter_path(trans, iter); if (!bpos_eq(path->l[0].b->key.k.p, SPOS_MAX)) end = bkey_min(end, bpos_nosnap_successor(path->l[0].b->key.k.p)); @@ -1064,9 +1065,9 @@ static struct bkey_s_c bch2_get_key_or_hole(struct btree_iter *iter, struct bpos * btree node min/max is a closed interval, upto takes a half * open interval: */ - k = bch2_btree_iter_peek_max(&iter2, end); + k = bch2_btree_iter_peek_max(trans, &iter2, end); next = iter2.pos; - bch2_trans_iter_exit(iter->trans, &iter2); + bch2_trans_iter_exit(trans, &iter2); BUG_ON(next.offset >= iter->pos.offset + U32_MAX); @@ -1107,13 +1108,14 @@ static bool next_bucket(struct bch_fs *c, struct bch_dev **ca, struct bpos *buck return *ca != NULL; } -static struct bkey_s_c bch2_get_key_or_real_bucket_hole(struct btree_iter *iter, - struct bch_dev **ca, struct bkey *hole) +static struct bkey_s_c bch2_get_key_or_real_bucket_hole(struct btree_trans *trans, + struct btree_iter *iter, + struct bch_dev **ca, struct bkey *hole) { - struct bch_fs *c = iter->trans->c; + struct bch_fs *c = trans->c; struct bkey_s_c k; again: - k = bch2_get_key_or_hole(iter, POS_MAX, hole); + k = bch2_get_key_or_hole(trans, iter, POS_MAX, hole); if (bkey_err(k)) return k; @@ -1126,7 +1128,7 @@ static struct bkey_s_c bch2_get_key_or_real_bucket_hole(struct btree_iter *iter, if (!next_bucket(c, ca, &hole_start)) return bkey_s_c_null; - bch2_btree_iter_set_pos(iter, hole_start); + bch2_btree_iter_set_pos(trans, iter, hole_start); goto again; } @@ -1167,8 +1169,8 @@ int bch2_check_alloc_key(struct btree_trans *trans, a = bch2_alloc_to_v4(alloc_k, &a_convert); - bch2_btree_iter_set_pos(discard_iter, alloc_k.k->p); - k = bch2_btree_iter_peek_slot(discard_iter); + bch2_btree_iter_set_pos(trans, discard_iter, alloc_k.k->p); + k = bch2_btree_iter_peek_slot(trans, discard_iter); ret = bkey_err(k); if (ret) goto err; @@ -1181,8 +1183,8 @@ int bch2_check_alloc_key(struct btree_trans *trans, goto err; } - bch2_btree_iter_set_pos(freespace_iter, alloc_freespace_pos(alloc_k.k->p, *a)); - k = bch2_btree_iter_peek_slot(freespace_iter); + bch2_btree_iter_set_pos(trans, freespace_iter, alloc_freespace_pos(alloc_k.k->p, *a)); + k = bch2_btree_iter_peek_slot(trans, freespace_iter); ret = bkey_err(k); if (ret) goto err; @@ -1195,8 +1197,8 @@ int bch2_check_alloc_key(struct btree_trans *trans, goto err; } - bch2_btree_iter_set_pos(bucket_gens_iter, alloc_gens_pos(alloc_k.k->p, &gens_offset)); - k = bch2_btree_iter_peek_slot(bucket_gens_iter); + bch2_btree_iter_set_pos(trans, bucket_gens_iter, alloc_gens_pos(alloc_k.k->p, &gens_offset)); + k = bch2_btree_iter_peek_slot(trans, bucket_gens_iter); ret = bkey_err(k); if (ret) goto err; @@ -1249,9 +1251,9 @@ int bch2_check_alloc_hole_freespace(struct btree_trans *trans, if (!ca->mi.freespace_initialized) return 0; - bch2_btree_iter_set_pos(freespace_iter, start); + bch2_btree_iter_set_pos(trans, freespace_iter, start); - k = bch2_btree_iter_peek_slot(freespace_iter); + k = bch2_btree_iter_peek_slot(trans, freespace_iter); ret = bkey_err(k); if (ret) goto err; @@ -1300,9 +1302,9 @@ int bch2_check_alloc_hole_bucket_gens(struct btree_trans *trans, unsigned i, gens_offset, gens_end_offset; int ret; - bch2_btree_iter_set_pos(bucket_gens_iter, alloc_gens_pos(start, &gens_offset)); + bch2_btree_iter_set_pos(trans, bucket_gens_iter, alloc_gens_pos(start, &gens_offset)); - k = bch2_btree_iter_peek_slot(bucket_gens_iter); + k = bch2_btree_iter_peek_slot(trans, bucket_gens_iter); ret = bkey_err(k); if (ret) goto err; @@ -1435,7 +1437,7 @@ int bch2_check_discard_freespace_key(struct btree_trans *trans, struct btree_ite *gen = a->gen; out: fsck_err: - bch2_set_btree_iter_dontneed(&alloc_iter); + bch2_set_btree_iter_dontneed(trans, &alloc_iter); bch2_trans_iter_exit(trans, &alloc_iter); printbuf_exit(&buf); return ret; @@ -1572,7 +1574,7 @@ int bch2_check_alloc_info(struct bch_fs *c) bch2_trans_begin(trans); - k = bch2_get_key_or_real_bucket_hole(&iter, &ca, &hole); + k = bch2_get_key_or_real_bucket_hole(trans, &iter, &ca, &hole); ret = bkey_err(k); if (ret) goto bkey_err; @@ -1610,7 +1612,7 @@ int bch2_check_alloc_info(struct bch_fs *c) if (ret) goto bkey_err; - bch2_btree_iter_set_pos(&iter, next); + bch2_btree_iter_set_pos(trans, &iter, next); bkey_err: if (bch2_err_matches(ret, BCH_ERR_transaction_restart)) continue; @@ -1638,7 +1640,7 @@ int bch2_check_alloc_info(struct bch_fs *c) BTREE_ITER_prefetch); while (1) { bch2_trans_begin(trans); - k = bch2_btree_iter_peek(&iter); + k = bch2_btree_iter_peek(trans, &iter); if (!k.k) break; @@ -1657,7 +1659,7 @@ int bch2_check_alloc_info(struct bch_fs *c) break; } - bch2_btree_iter_set_pos(&iter, bpos_nosnap_successor(iter.pos)); + bch2_btree_iter_set_pos(trans, &iter, bpos_nosnap_successor(iter.pos)); } bch2_trans_iter_exit(trans, &iter); if (ret) @@ -1685,7 +1687,7 @@ static int bch2_check_alloc_to_lru_ref(struct btree_trans *trans, struct printbuf buf = PRINTBUF; int ret; - alloc_k = bch2_btree_iter_peek(alloc_iter); + alloc_k = bch2_btree_iter_peek(trans, alloc_iter); if (!alloc_k.k) return 0; @@ -1826,7 +1828,7 @@ static int bch2_discard_one_bucket(struct btree_trans *trans, { struct bch_fs *c = trans->c; struct bpos pos = need_discard_iter->pos; - struct btree_iter iter = { NULL }; + struct btree_iter iter = {}; struct bkey_s_c k; struct bkey_i_alloc_v4 *a; struct printbuf buf = PRINTBUF; @@ -1950,7 +1952,7 @@ static void bch2_do_discards_work(struct work_struct *work) trace_discard_buckets(c, s.seen, s.open, s.need_journal_commit, s.discarded, bch2_err_str(ret)); - percpu_ref_put(&ca->io_ref); + percpu_ref_put(&ca->io_ref[WRITE]); bch2_write_ref_put(c, BCH_WRITE_REF_discard); } @@ -1967,7 +1969,7 @@ void bch2_dev_do_discards(struct bch_dev *ca) if (queue_work(c->write_ref_wq, &ca->discard_work)) return; - percpu_ref_put(&ca->io_ref); + percpu_ref_put(&ca->io_ref[WRITE]); put_write_ref: bch2_write_ref_put(c, BCH_WRITE_REF_discard); } @@ -2045,7 +2047,7 @@ static void bch2_do_discards_fast_work(struct work_struct *work) trace_discard_buckets_fast(c, s.seen, s.open, s.need_journal_commit, s.discarded, bch2_err_str(ret)); bch2_trans_put(trans); - percpu_ref_put(&ca->io_ref); + percpu_ref_put(&ca->io_ref[WRITE]); bch2_write_ref_put(c, BCH_WRITE_REF_discard_fast); } @@ -2065,7 +2067,7 @@ static void bch2_discard_one_bucket_fast(struct bch_dev *ca, u64 bucket) if (queue_work(c->write_ref_wq, &ca->discard_fast_work)) return; - percpu_ref_put(&ca->io_ref); + percpu_ref_put(&ca->io_ref[WRITE]); put_ref: bch2_write_ref_put(c, BCH_WRITE_REF_discard_fast); } @@ -2082,6 +2084,9 @@ static int invalidate_one_bp(struct btree_trans *trans, if (ret) return ret; + if (!extent_k.k) + return 0; + struct bkey_i *n = bch2_bkey_make_mut(trans, &extent_iter, &extent_k, BTREE_UPDATE_internal_snapshot_node); @@ -2199,9 +2204,9 @@ static struct bkey_s_c next_lru_key(struct btree_trans *trans, struct btree_iter { struct bkey_s_c k; again: - k = bch2_btree_iter_peek_max(iter, lru_pos(ca->dev_idx, U64_MAX, LRU_TIME_MAX)); + k = bch2_btree_iter_peek_max(trans, iter, lru_pos(ca->dev_idx, U64_MAX, LRU_TIME_MAX)); if (!k.k && !*wrapped) { - bch2_btree_iter_set_pos(iter, lru_pos(ca->dev_idx, 0, 0)); + bch2_btree_iter_set_pos(trans, iter, lru_pos(ca->dev_idx, 0, 0)); *wrapped = true; goto again; } @@ -2251,12 +2256,12 @@ static void bch2_do_invalidates_work(struct work_struct *work) if (ret) break; - bch2_btree_iter_advance(&iter); + bch2_btree_iter_advance(trans, &iter); } bch2_trans_iter_exit(trans, &iter); err: bch2_trans_put(trans); - percpu_ref_put(&ca->io_ref); + percpu_ref_put(&ca->io_ref[WRITE]); bch2_bkey_buf_exit(&last_flushed, c); bch2_write_ref_put(c, BCH_WRITE_REF_invalidate); } @@ -2274,7 +2279,7 @@ void bch2_dev_do_invalidates(struct bch_dev *ca) if (queue_work(c->write_ref_wq, &ca->invalidate_work)) return; - percpu_ref_put(&ca->io_ref); + percpu_ref_put(&ca->io_ref[WRITE]); put_ref: bch2_write_ref_put(c, BCH_WRITE_REF_invalidate); } @@ -2321,7 +2326,7 @@ int bch2_dev_freespace_init(struct bch_fs *c, struct bch_dev *ca, break; } - k = bch2_get_key_or_hole(&iter, end, &hole); + k = bch2_get_key_or_hole(trans, &iter, end, &hole); ret = bkey_err(k); if (ret) goto bkey_err; @@ -2340,7 +2345,7 @@ int bch2_dev_freespace_init(struct bch_fs *c, struct bch_dev *ca, if (ret) goto bkey_err; - bch2_btree_iter_advance(&iter); + bch2_btree_iter_advance(trans, &iter); } else { struct bkey_i *freespace; @@ -2360,7 +2365,7 @@ int bch2_dev_freespace_init(struct bch_fs *c, struct bch_dev *ca, if (ret) goto bkey_err; - bch2_btree_iter_set_pos(&iter, k.k->p); + bch2_btree_iter_set_pos(trans, &iter, k.k->p); } bkey_err: if (bch2_err_matches(ret, BCH_ERR_transaction_restart)) @@ -2506,7 +2511,7 @@ void bch2_recalc_capacity(struct bch_fs *c) bch2_set_ra_pages(c, ra_pages); - for_each_rw_member(c, ca) { + __for_each_online_member(c, ca, BIT(BCH_MEMBER_STATE_rw), READ) { u64 dev_reserve = 0; /*
diff --git a/fs/bcachefs/alloc_background.h b/fs/bcachefs/alloc_background.h index c556cca..34b3d6a 100644 --- a/fs/bcachefs/alloc_background.h +++ b/fs/bcachefs/alloc_background.h
@@ -321,11 +321,11 @@ static inline u64 should_invalidate_buckets(struct bch_dev *ca, { u64 want_free = ca->mi.nbuckets >> 7; u64 free = max_t(s64, 0, - u.d[BCH_DATA_free].buckets - + u.d[BCH_DATA_need_discard].buckets + u.buckets[BCH_DATA_free] + + u.buckets[BCH_DATA_need_discard] - bch2_dev_buckets_reserved(ca, BCH_WATERMARK_stripe)); - return clamp_t(s64, want_free - free, 0, u.d[BCH_DATA_cached].buckets); + return clamp_t(s64, want_free - free, 0, u.buckets[BCH_DATA_cached]); } void bch2_dev_do_invalidates(struct bch_dev *);
diff --git a/fs/bcachefs/alloc_foreground.c b/fs/bcachefs/alloc_foreground.c index da0d729..7c930ef 100644 --- a/fs/bcachefs/alloc_foreground.c +++ b/fs/bcachefs/alloc_foreground.c
@@ -327,7 +327,7 @@ bch2_bucket_alloc_early(struct btree_trans *trans, bucket = sector_to_bucket(ca, round_up(bucket_to_sector(ca, bucket) + 1, 1ULL << ca->mi.btree_bitmap_shift)); - bch2_btree_iter_set_pos(&iter, POS(ca->dev_idx, bucket)); + bch2_btree_iter_set_pos(trans, &iter, POS(ca->dev_idx, bucket)); s->buckets_seen++; s->skipped_mi_btree_bitmap++; continue; @@ -355,7 +355,7 @@ bch2_bucket_alloc_early(struct btree_trans *trans, watermark, s, cl) : NULL; next: - bch2_set_btree_iter_dontneed(&citer); + bch2_set_btree_iter_dontneed(trans, &citer); bch2_trans_iter_exit(trans, &citer); if (ob) break; @@ -417,7 +417,7 @@ static struct open_bucket *bch2_bucket_alloc_freelist(struct btree_trans *trans, 1ULL << ca->mi.btree_bitmap_shift)); alloc_cursor = bucket|(iter.pos.offset & (~0ULL << 56)); - bch2_btree_iter_set_pos(&iter, POS(ca->dev_idx, alloc_cursor)); + bch2_btree_iter_set_pos(trans, &iter, POS(ca->dev_idx, alloc_cursor)); s->skipped_mi_btree_bitmap++; goto next; } @@ -426,7 +426,7 @@ static struct open_bucket *bch2_bucket_alloc_freelist(struct btree_trans *trans, if (ob) { if (!IS_ERR(ob)) *dev_alloc_cursor = iter.pos.offset; - bch2_set_btree_iter_dontneed(&iter); + bch2_set_btree_iter_dontneed(trans, &iter); break; } @@ -469,7 +469,7 @@ static noinline void trace_bucket_alloc2(struct bch_fs *c, struct bch_dev *ca, prt_printf(&buf, "watermark\t%s\n", bch2_watermarks[watermark]); prt_printf(&buf, "data type\t%s\n", __bch2_data_types[data_type]); prt_printf(&buf, "blocking\t%u\n", cl != NULL); - prt_printf(&buf, "free\t%llu\n", usage->d[BCH_DATA_free].buckets); + prt_printf(&buf, "free\t%llu\n", usage->buckets[BCH_DATA_free]); prt_printf(&buf, "avail\t%llu\n", dev_buckets_free(ca, *usage, watermark)); prt_printf(&buf, "copygc_wait\t%lu/%lli\n", bch2_copygc_wait_amount(c), @@ -524,10 +524,10 @@ static struct open_bucket *bch2_bucket_alloc_trans(struct btree_trans *trans, bch2_dev_usage_read_fast(ca, usage); avail = dev_buckets_free(ca, *usage, watermark); - if (usage->d[BCH_DATA_need_discard].buckets > avail) + if (usage->buckets[BCH_DATA_need_discard] > avail) bch2_dev_do_discards(ca); - if (usage->d[BCH_DATA_need_gc_gens].buckets > avail) + if (usage->buckets[BCH_DATA_need_gc_gens] > avail) bch2_gc_gens_async(c); if (should_invalidate_buckets(ca, *usage)) @@ -606,8 +606,7 @@ struct open_bucket *bch2_bucket_alloc(struct bch_fs *c, struct bch_dev *ca, static int __dev_stripe_cmp(struct dev_stripe_state *stripe, unsigned l, unsigned r) { - return ((stripe->next_alloc[l] > stripe->next_alloc[r]) - - (stripe->next_alloc[l] < stripe->next_alloc[r])); + return cmp_int(stripe->next_alloc[l], stripe->next_alloc[r]); } #define dev_stripe_cmp(l, r) __dev_stripe_cmp(stripe, l, r) @@ -626,25 +625,62 @@ struct dev_alloc_list bch2_dev_alloc_list(struct bch_fs *c, return ret; } +static const u64 stripe_clock_hand_rescale = 1ULL << 62; /* trigger rescale at */ +static const u64 stripe_clock_hand_max = 1ULL << 56; /* max after rescale */ +static const u64 stripe_clock_hand_inv = 1ULL << 52; /* max increment, if a device is empty */ + +static noinline void bch2_stripe_state_rescale(struct dev_stripe_state *stripe) +{ + /* + * Avoid underflowing clock hands if at all possible, if clock hands go + * to 0 then we lose information - clock hands can be in a wide range if + * we have devices we rarely try to allocate from, if we generally + * allocate from a specified target but only sometimes have to fall back + * to the whole filesystem. + */ + u64 scale_max = U64_MAX; /* maximum we can subtract without underflow */ + u64 scale_min = 0; /* minumum we must subtract to avoid overflow */ + + for (u64 *v = stripe->next_alloc; + v < stripe->next_alloc + ARRAY_SIZE(stripe->next_alloc); v++) { + if (*v) + scale_max = min(scale_max, *v); + if (*v > stripe_clock_hand_max) + scale_min = max(scale_min, *v - stripe_clock_hand_max); + } + + u64 scale = max(scale_min, scale_max); + + for (u64 *v = stripe->next_alloc; + v < stripe->next_alloc + ARRAY_SIZE(stripe->next_alloc); v++) + *v = *v < scale ? 0 : *v - scale; +} + static inline void bch2_dev_stripe_increment_inlined(struct bch_dev *ca, struct dev_stripe_state *stripe, struct bch_dev_usage *usage) { + /* + * Stripe state has a per device clock hand: we allocate from the device + * with the smallest clock hand. + * + * When we allocate, we don't do a simple increment; we add the inverse + * of the device's free space. This results in round robin behavior that + * biases in favor of the device(s) with more free space. + */ + u64 *v = stripe->next_alloc + ca->dev_idx; u64 free_space = __dev_buckets_available(ca, *usage, BCH_WATERMARK_normal); u64 free_space_inv = free_space - ? div64_u64(1ULL << 48, free_space) - : 1ULL << 48; - u64 scale = *v / 4; + ? div64_u64(stripe_clock_hand_inv, free_space) + : stripe_clock_hand_inv; - if (*v + free_space_inv >= *v) - *v += free_space_inv; - else - *v = U64_MAX; + /* Saturating add, avoid overflow: */ + u64 sum = *v + free_space_inv; + *v = sum >= *v ? sum : U64_MAX; - for (v = stripe->next_alloc; - v < stripe->next_alloc + ARRAY_SIZE(stripe->next_alloc); v++) - *v = *v < scale ? 0 : *v - scale; + if (unlikely(*v > stripe_clock_hand_rescale)) + bch2_stripe_state_rescale(stripe); } void bch2_dev_stripe_increment(struct bch_dev *ca, @@ -1633,7 +1669,7 @@ void bch2_fs_alloc_debug_to_text(struct printbuf *out, struct bch_fs *c) void bch2_dev_alloc_debug_to_text(struct printbuf *out, struct bch_dev *ca) { struct bch_fs *c = ca->fs; - struct bch_dev_usage stats = bch2_dev_usage_read(ca); + struct bch_dev_usage_full stats = bch2_dev_usage_full_read(ca); unsigned nr[BCH_DATA_NR]; memset(nr, 0, sizeof(nr)); @@ -1656,7 +1692,8 @@ void bch2_dev_alloc_debug_to_text(struct printbuf *out, struct bch_dev *ca) printbuf_tabstop_push(out, 16); prt_printf(out, "open buckets\t%i\r\n", ca->nr_open_buckets); - prt_printf(out, "buckets to invalidate\t%llu\r\n", should_invalidate_buckets(ca, stats)); + prt_printf(out, "buckets to invalidate\t%llu\r\n", + should_invalidate_buckets(ca, bch2_dev_usage_read(ca))); } static noinline void bch2_print_allocator_stuck(struct bch_fs *c)
diff --git a/fs/bcachefs/backpointers.c b/fs/bcachefs/backpointers.c index 21d1d86..ff26bb5 100644 --- a/fs/bcachefs/backpointers.c +++ b/fs/bcachefs/backpointers.c
@@ -252,12 +252,24 @@ struct bkey_s_c bch2_backpointer_get_key(struct btree_trans *trans, 0, bp.v->level, iter_flags); - struct bkey_s_c k = bch2_btree_iter_peek_slot(iter); + struct bkey_s_c k = bch2_btree_iter_peek_slot(trans, iter); if (bkey_err(k)) { bch2_trans_iter_exit(trans, iter); return k; } + /* + * peek_slot() doesn't normally return NULL - except when we ask for a + * key at a btree level that doesn't exist. + * + * We may want to revisit this and change peek_slot(): + */ + if (!k.k) { + bkey_init(&iter->k); + iter->k.p = bp.v->pos; + k.k = &iter->k; + } + if (k.k && extent_matches_bp(c, bp.v->btree_id, bp.v->level, k, bp)) return k; @@ -293,7 +305,7 @@ struct btree *bch2_backpointer_get_node(struct btree_trans *trans, 0, bp.v->level - 1, 0); - struct btree *b = bch2_btree_iter_peek_node(iter); + struct btree *b = bch2_btree_iter_peek_node(trans, iter); if (IS_ERR_OR_NULL(b)) goto err; @@ -321,7 +333,7 @@ static int bch2_check_backpointer_has_valid_bucket(struct btree_trans *trans, st return 0; struct bch_fs *c = trans->c; - struct btree_iter alloc_iter = { NULL }; + struct btree_iter alloc_iter = {}; struct bkey_s_c alloc_k; struct printbuf buf = PRINTBUF; int ret = 0; @@ -462,7 +474,7 @@ static int check_extent_checksum(struct btree_trans *trans, if (bio) bio_put(bio); kvfree(data_buf); - percpu_ref_put(&ca->io_ref); + percpu_ref_put(&ca->io_ref[READ]); printbuf_exit(&buf); return ret; } @@ -650,7 +662,7 @@ static int check_btree_root_to_backpointers(struct btree_trans *trans, retry: bch2_trans_node_iter_init(trans, &iter, btree_id, POS_MIN, 0, bch2_btree_id_root(c, btree_id)->b->c.level, 0); - b = bch2_btree_iter_peek_node(&iter); + b = bch2_btree_iter_peek_node(trans, &iter); ret = PTR_ERR_OR_ZERO(b); if (ret) goto err; @@ -934,7 +946,7 @@ static int btree_node_get_and_pin(struct btree_trans *trans, struct bkey_i *k, { struct btree_iter iter; bch2_trans_node_iter_init(trans, &iter, btree, k->k.p, 0, level, 0); - struct btree *b = bch2_btree_iter_peek_node(&iter); + struct btree *b = bch2_btree_iter_peek_node(trans, &iter); int ret = PTR_ERR_OR_ZERO(b); if (ret) goto err;
diff --git a/fs/bcachefs/bcachefs.h b/fs/bcachefs/bcachefs.h index f523110..5d9f208 100644 --- a/fs/bcachefs/bcachefs.h +++ b/fs/bcachefs/bcachefs.h
@@ -524,8 +524,8 @@ struct bch_dev { struct percpu_ref ref; #endif struct completion ref_completion; - struct percpu_ref io_ref; - struct completion io_ref_completion; + struct percpu_ref io_ref[2]; + struct completion io_ref_completion[2]; struct bch_fs *fs; @@ -562,7 +562,8 @@ struct bch_dev { unsigned long *bucket_backpointer_mismatches; unsigned long *bucket_backpointer_empty; - struct bch_dev_usage __percpu *usage; + struct bch_dev_usage_full __percpu + *usage; /* Allocator: */ u64 alloc_cursor[3];
diff --git a/fs/bcachefs/btree_gc.c b/fs/bcachefs/btree_gc.c index 2025d40..7b98ba2 100644 --- a/fs/bcachefs/btree_gc.c +++ b/fs/bcachefs/btree_gc.c
@@ -691,7 +691,7 @@ static int bch2_gc_btree(struct btree_trans *trans, struct btree_iter iter; bch2_trans_node_iter_init(trans, &iter, btree, POS_MIN, 0, bch2_btree_id_root(c, btree)->b->c.level, 0); - struct btree *b = bch2_btree_iter_peek_node(&iter); + struct btree *b = bch2_btree_iter_peek_node(trans, &iter); ret = PTR_ERR_OR_ZERO(b); if (ret) goto err_root; @@ -1199,7 +1199,7 @@ int bch2_gc_gens(struct bch_fs *c) BCH_TRANS_COMMIT_no_enospc, ({ ca = bch2_dev_iterate(c, ca, k.k->p.inode); if (!ca) { - bch2_btree_iter_set_pos(&iter, POS(k.k->p.inode + 1, 0)); + bch2_btree_iter_set_pos(trans, &iter, POS(k.k->p.inode + 1, 0)); continue; } bch2_alloc_write_oldest_gen(trans, ca, &iter, k);
diff --git a/fs/bcachefs/btree_io.c b/fs/bcachefs/btree_io.c index 1d94a2b..5fd4a58 100644 --- a/fs/bcachefs/btree_io.c +++ b/fs/bcachefs/btree_io.c
@@ -1353,7 +1353,7 @@ static void btree_node_read_work(struct work_struct *work) "btree read error %s for %s", bch2_blk_status_to_str(bio->bi_status), buf.buf); if (rb->have_ioref) - percpu_ref_put(&ca->io_ref); + percpu_ref_put(&ca->io_ref[READ]); rb->have_ioref = false; bch2_mark_io_failure(&failed, &rb->pick, false); @@ -1609,6 +1609,7 @@ static void btree_node_read_all_replicas_endio(struct bio *bio) struct bch_dev *ca = bch2_dev_have_ref(c, rb->pick.ptr.dev); bch2_latency_acct(ca, rb->start_time, READ); + percpu_ref_put(&ca->io_ref[READ]); } ra->err[rb->idx] = bio->bi_status; @@ -1908,7 +1909,8 @@ static void btree_node_scrub_work(struct work_struct *work) scrub->key.k->k.p, 0, scrub->level - 1, 0); struct btree *b; - int ret = lockrestart_do(trans, PTR_ERR_OR_ZERO(b = bch2_btree_iter_peek_node(&iter))); + int ret = lockrestart_do(trans, + PTR_ERR_OR_ZERO(b = bch2_btree_iter_peek_node(trans, &iter))); if (ret) goto err; @@ -1927,7 +1929,7 @@ static void btree_node_scrub_work(struct work_struct *work) printbuf_exit(&err); bch2_bkey_buf_exit(&scrub->key, c);; btree_bounce_free(c, c->opts.btree_node_size, scrub->used_mempool, scrub->buf); - percpu_ref_put(&scrub->ca->io_ref); + percpu_ref_put(&scrub->ca->io_ref[READ]); kfree(scrub); bch2_write_ref_put(c, BCH_WRITE_REF_btree_node_scrub); } @@ -1996,7 +1998,7 @@ int bch2_btree_node_scrub(struct btree_trans *trans, return 0; err_free: btree_bounce_free(c, c->opts.btree_node_size, used_mempool, buf); - percpu_ref_put(&ca->io_ref); + percpu_ref_put(&ca->io_ref[READ]); err: bch2_write_ref_put(c, BCH_WRITE_REF_btree_node_scrub); return ret; @@ -2144,6 +2146,7 @@ static void btree_node_write_endio(struct bio *bio) if (ca && bio->bi_status) { struct printbuf buf = PRINTBUF; + buf.atomic++; prt_printf(&buf, "btree write error: %s\n ", bch2_blk_status_to_str(bio->bi_status)); bch2_btree_pos_to_text(&buf, c, b); @@ -2158,8 +2161,12 @@ static void btree_node_write_endio(struct bio *bio) spin_unlock_irqrestore(&c->btree_write_error_lock, flags); } + /* + * XXX: we should be using io_ref[WRITE], but we aren't retrying failed + * btree writes yet (due to device removal/ro): + */ if (wbio->have_ioref) - percpu_ref_put(&ca->io_ref); + percpu_ref_put(&ca->io_ref[READ]); if (parent) { bio_put(bio);
diff --git a/fs/bcachefs/btree_iter.c b/fs/bcachefs/btree_iter.c index a9c110b..e34e959 100644 --- a/fs/bcachefs/btree_iter.c +++ b/fs/bcachefs/btree_iter.c
@@ -244,10 +244,8 @@ void bch2_trans_verify_paths(struct btree_trans *trans) bch2_btree_path_verify(trans, path); } -static void bch2_btree_iter_verify(struct btree_iter *iter) +static void bch2_btree_iter_verify(struct btree_trans *trans, struct btree_iter *iter) { - struct btree_trans *trans = iter->trans; - BUG_ON(!!(iter->flags & BTREE_ITER_cached) != btree_iter_path(trans, iter)->cached); BUG_ON((iter->flags & BTREE_ITER_is_extents) && @@ -276,9 +274,9 @@ static void bch2_btree_iter_verify_entry_exit(struct btree_iter *iter) bkey_gt(iter->pos, iter->k.p))); } -static int bch2_btree_iter_verify_ret(struct btree_iter *iter, struct bkey_s_c k) +static int bch2_btree_iter_verify_ret(struct btree_trans *trans, + struct btree_iter *iter, struct bkey_s_c k) { - struct btree_trans *trans = iter->trans; struct btree_iter copy; struct bkey_s_c prev; int ret = 0; @@ -299,7 +297,7 @@ static int bch2_btree_iter_verify_ret(struct btree_iter *iter, struct bkey_s_c k bch2_trans_iter_init(trans, ©, iter->btree_id, iter->pos, BTREE_ITER_nopreserve| BTREE_ITER_all_snapshots); - prev = bch2_btree_iter_prev(©); + prev = bch2_btree_iter_prev(trans, ©); if (!prev.k) goto out; @@ -365,9 +363,11 @@ static inline void bch2_btree_path_verify_level(struct btree_trans *trans, struct btree_path *path, unsigned l) {} static inline void bch2_btree_path_verify(struct btree_trans *trans, struct btree_path *path) {} -static inline void bch2_btree_iter_verify(struct btree_iter *iter) {} +static inline void bch2_btree_iter_verify(struct btree_trans *trans, + struct btree_iter *iter) {} static inline void bch2_btree_iter_verify_entry_exit(struct btree_iter *iter) {} -static inline int bch2_btree_iter_verify_ret(struct btree_iter *iter, struct bkey_s_c k) { return 0; } +static inline int bch2_btree_iter_verify_ret(struct btree_trans *trans, struct btree_iter *iter, + struct bkey_s_c k) { return 0; } #endif @@ -1855,10 +1855,8 @@ struct bkey_s_c bch2_btree_path_peek_slot(struct btree_path *path, struct bkey * return (struct bkey_s_c) { u, NULL }; } -void bch2_set_btree_iter_dontneed(struct btree_iter *iter) +void bch2_set_btree_iter_dontneed(struct btree_trans *trans, struct btree_iter *iter) { - struct btree_trans *trans = iter->trans; - if (!iter->path || trans->restarted) return; @@ -1870,17 +1868,14 @@ void bch2_set_btree_iter_dontneed(struct btree_iter *iter) /* Btree iterators: */ int __must_check -__bch2_btree_iter_traverse(struct btree_iter *iter) +__bch2_btree_iter_traverse(struct btree_trans *trans, struct btree_iter *iter) { - return bch2_btree_path_traverse(iter->trans, iter->path, iter->flags); + return bch2_btree_path_traverse(trans, iter->path, iter->flags); } int __must_check -bch2_btree_iter_traverse(struct btree_iter *iter) +bch2_btree_iter_traverse(struct btree_trans *trans, struct btree_iter *iter) { - struct btree_trans *trans = iter->trans; - int ret; - bch2_trans_verify_not_unlocked_or_in_restart(trans); iter->path = bch2_btree_path_set_pos(trans, iter->path, @@ -1888,7 +1883,7 @@ bch2_btree_iter_traverse(struct btree_iter *iter) iter->flags & BTREE_ITER_intent, btree_iter_ip_allocated(iter)); - ret = bch2_btree_path_traverse(iter->trans, iter->path, iter->flags); + int ret = bch2_btree_path_traverse(trans, iter->path, iter->flags); if (ret) return ret; @@ -1900,14 +1895,14 @@ bch2_btree_iter_traverse(struct btree_iter *iter) /* Iterate across nodes (leaf and interior nodes) */ -struct btree *bch2_btree_iter_peek_node(struct btree_iter *iter) +struct btree *bch2_btree_iter_peek_node(struct btree_trans *trans, + struct btree_iter *iter) { - struct btree_trans *trans = iter->trans; struct btree *b = NULL; int ret; EBUG_ON(trans->paths[iter->path].cached); - bch2_btree_iter_verify(iter); + bch2_btree_iter_verify(trans, iter); ret = bch2_btree_path_traverse(trans, iter->path, iter->flags); if (ret) @@ -1929,7 +1924,7 @@ struct btree *bch2_btree_iter_peek_node(struct btree_iter *iter) btree_path_set_should_be_locked(trans, btree_iter_path(trans, iter)); out: bch2_btree_iter_verify_entry_exit(iter); - bch2_btree_iter_verify(iter); + bch2_btree_iter_verify(trans, iter); return b; err: @@ -1938,26 +1933,26 @@ struct btree *bch2_btree_iter_peek_node(struct btree_iter *iter) } /* Only kept for -tools */ -struct btree *bch2_btree_iter_peek_node_and_restart(struct btree_iter *iter) +struct btree *bch2_btree_iter_peek_node_and_restart(struct btree_trans *trans, + struct btree_iter *iter) { struct btree *b; - while (b = bch2_btree_iter_peek_node(iter), + while (b = bch2_btree_iter_peek_node(trans, iter), bch2_err_matches(PTR_ERR_OR_ZERO(b), BCH_ERR_transaction_restart)) - bch2_trans_begin(iter->trans); + bch2_trans_begin(trans); return b; } -struct btree *bch2_btree_iter_next_node(struct btree_iter *iter) +struct btree *bch2_btree_iter_next_node(struct btree_trans *trans, struct btree_iter *iter) { - struct btree_trans *trans = iter->trans; struct btree *b = NULL; int ret; EBUG_ON(trans->paths[iter->path].cached); bch2_trans_verify_not_unlocked_or_in_restart(trans); - bch2_btree_iter_verify(iter); + bch2_btree_iter_verify(trans, iter); ret = bch2_btree_path_traverse(trans, iter->path, iter->flags); if (ret) @@ -2024,7 +2019,7 @@ struct btree *bch2_btree_iter_next_node(struct btree_iter *iter) EBUG_ON(btree_iter_path(trans, iter)->uptodate); out: bch2_btree_iter_verify_entry_exit(iter); - bch2_btree_iter_verify(iter); + bch2_btree_iter_verify(trans, iter); return b; err: @@ -2034,7 +2029,7 @@ struct btree *bch2_btree_iter_next_node(struct btree_iter *iter) /* Iterate across keys (in leaf nodes only) */ -inline bool bch2_btree_iter_advance(struct btree_iter *iter) +inline bool bch2_btree_iter_advance(struct btree_trans *trans, struct btree_iter *iter) { struct bpos pos = iter->k.p; bool ret = !(iter->flags & BTREE_ITER_all_snapshots @@ -2043,11 +2038,11 @@ inline bool bch2_btree_iter_advance(struct btree_iter *iter) if (ret && !(iter->flags & BTREE_ITER_is_extents)) pos = bkey_successor(iter, pos); - bch2_btree_iter_set_pos(iter, pos); + bch2_btree_iter_set_pos(trans, iter, pos); return ret; } -inline bool bch2_btree_iter_rewind(struct btree_iter *iter) +inline bool bch2_btree_iter_rewind(struct btree_trans *trans, struct btree_iter *iter) { struct bpos pos = bkey_start_pos(&iter->k); bool ret = !(iter->flags & BTREE_ITER_all_snapshots @@ -2056,7 +2051,7 @@ inline bool bch2_btree_iter_rewind(struct btree_iter *iter) if (ret && !(iter->flags & BTREE_ITER_is_extents)) pos = bkey_predecessor(iter, pos); - bch2_btree_iter_set_pos(iter, pos); + bch2_btree_iter_set_pos(trans, iter, pos); return ret; } @@ -2183,9 +2178,9 @@ void btree_trans_peek_prev_journal(struct btree_trans *trans, * bkey_s_c_null: */ static noinline -struct bkey_s_c btree_trans_peek_key_cache(struct btree_iter *iter, struct bpos pos) +struct bkey_s_c btree_trans_peek_key_cache(struct btree_trans *trans, struct btree_iter *iter, + struct bpos pos) { - struct btree_trans *trans = iter->trans; struct bch_fs *c = trans->c; struct bkey u; struct bkey_s_c k; @@ -2231,14 +2226,14 @@ struct bkey_s_c btree_trans_peek_key_cache(struct btree_iter *iter, struct bpos return k; } -static struct bkey_s_c __bch2_btree_iter_peek(struct btree_iter *iter, struct bpos search_key) +static struct bkey_s_c __bch2_btree_iter_peek(struct btree_trans *trans, struct btree_iter *iter, + struct bpos search_key) { - struct btree_trans *trans = iter->trans; struct bkey_s_c k, k2; int ret; EBUG_ON(btree_iter_path(trans, iter)->cached); - bch2_btree_iter_verify(iter); + bch2_btree_iter_verify(trans, iter); while (1) { iter->path = bch2_btree_path_set_pos(trans, iter->path, search_key, @@ -2248,7 +2243,7 @@ static struct bkey_s_c __bch2_btree_iter_peek(struct btree_iter *iter, struct bp ret = bch2_btree_path_traverse(trans, iter->path, iter->flags); if (unlikely(ret)) { /* ensure that iter->k is consistent with iter->pos: */ - bch2_btree_iter_set_pos(iter, iter->pos); + bch2_btree_iter_set_pos(trans, iter, iter->pos); k = bkey_s_c_err(ret); break; } @@ -2258,7 +2253,7 @@ static struct bkey_s_c __bch2_btree_iter_peek(struct btree_iter *iter, struct bp if (unlikely(!l->b)) { /* No btree nodes at requested level: */ - bch2_btree_iter_set_pos(iter, SPOS_MAX); + bch2_btree_iter_set_pos(trans, iter, SPOS_MAX); k = bkey_s_c_null; break; } @@ -2269,10 +2264,10 @@ static struct bkey_s_c __bch2_btree_iter_peek(struct btree_iter *iter, struct bp if (unlikely(iter->flags & BTREE_ITER_with_key_cache) && k.k && - (k2 = btree_trans_peek_key_cache(iter, k.k->p)).k) { + (k2 = btree_trans_peek_key_cache(trans, iter, k.k->p)).k) { k = k2; if (bkey_err(k)) { - bch2_btree_iter_set_pos(iter, iter->pos); + bch2_btree_iter_set_pos(trans, iter, iter->pos); break; } } @@ -2305,27 +2300,28 @@ static struct bkey_s_c __bch2_btree_iter_peek(struct btree_iter *iter, struct bp search_key = bpos_successor(l->b->key.k.p); } else { /* End of btree: */ - bch2_btree_iter_set_pos(iter, SPOS_MAX); + bch2_btree_iter_set_pos(trans, iter, SPOS_MAX); k = bkey_s_c_null; break; } } - bch2_btree_iter_verify(iter); + bch2_btree_iter_verify(trans, iter); return k; } /** * bch2_btree_iter_peek_max() - returns first key greater than or equal to * iterator's current position + * @trans: btree transaction object * @iter: iterator to peek from * @end: search limit: returns keys less than or equal to @end * * Returns: key if found, or an error extractable with bkey_err(). */ -struct bkey_s_c bch2_btree_iter_peek_max(struct btree_iter *iter, struct bpos end) +struct bkey_s_c bch2_btree_iter_peek_max(struct btree_trans *trans, struct btree_iter *iter, + struct bpos end) { - struct btree_trans *trans = iter->trans; struct bpos search_key = btree_iter_search_key(iter); struct bkey_s_c k; struct bpos iter_pos = iter->pos; @@ -2348,7 +2344,7 @@ struct bkey_s_c bch2_btree_iter_peek_max(struct btree_iter *iter, struct bpos en } while (1) { - k = __bch2_btree_iter_peek(iter, search_key); + k = __bch2_btree_iter_peek(trans, iter, search_key); if (unlikely(!k.k)) goto end; if (unlikely(bkey_err(k))) @@ -2462,9 +2458,9 @@ struct bkey_s_c bch2_btree_iter_peek_max(struct btree_iter *iter, struct bpos en if (!(iter->flags & BTREE_ITER_all_snapshots)) iter->pos.snapshot = iter->snapshot; - ret = bch2_btree_iter_verify_ret(iter, k); + ret = bch2_btree_iter_verify_ret(trans, iter, k); if (unlikely(ret)) { - bch2_btree_iter_set_pos(iter, iter->pos); + bch2_btree_iter_set_pos(trans, iter, iter->pos); k = bkey_s_c_err(ret); } @@ -2472,7 +2468,7 @@ struct bkey_s_c bch2_btree_iter_peek_max(struct btree_iter *iter, struct bpos en return k; end: - bch2_btree_iter_set_pos(iter, end); + bch2_btree_iter_set_pos(trans, iter, end); k = bkey_s_c_null; goto out_no_locked; } @@ -2480,24 +2476,25 @@ struct bkey_s_c bch2_btree_iter_peek_max(struct btree_iter *iter, struct bpos en /** * bch2_btree_iter_next() - returns first key greater than iterator's current * position + * @trans: btree transaction object * @iter: iterator to peek from * * Returns: key if found, or an error extractable with bkey_err(). */ -struct bkey_s_c bch2_btree_iter_next(struct btree_iter *iter) +struct bkey_s_c bch2_btree_iter_next(struct btree_trans *trans, struct btree_iter *iter) { - if (!bch2_btree_iter_advance(iter)) + if (!bch2_btree_iter_advance(trans, iter)) return bkey_s_c_null; - return bch2_btree_iter_peek(iter); + return bch2_btree_iter_peek(trans, iter); } -static struct bkey_s_c __bch2_btree_iter_peek_prev(struct btree_iter *iter, struct bpos search_key) +static struct bkey_s_c __bch2_btree_iter_peek_prev(struct btree_trans *trans, struct btree_iter *iter, + struct bpos search_key) { - struct btree_trans *trans = iter->trans; struct bkey_s_c k, k2; - bch2_btree_iter_verify(iter); + bch2_btree_iter_verify(trans, iter); while (1) { iter->path = bch2_btree_path_set_pos(trans, iter->path, search_key, @@ -2507,7 +2504,7 @@ static struct bkey_s_c __bch2_btree_iter_peek_prev(struct btree_iter *iter, stru int ret = bch2_btree_path_traverse(trans, iter->path, iter->flags); if (unlikely(ret)) { /* ensure that iter->k is consistent with iter->pos: */ - bch2_btree_iter_set_pos(iter, iter->pos); + bch2_btree_iter_set_pos(trans, iter, iter->pos); k = bkey_s_c_err(ret); break; } @@ -2517,7 +2514,7 @@ static struct bkey_s_c __bch2_btree_iter_peek_prev(struct btree_iter *iter, stru if (unlikely(!l->b)) { /* No btree nodes at requested level: */ - bch2_btree_iter_set_pos(iter, SPOS_MAX); + bch2_btree_iter_set_pos(trans, iter, SPOS_MAX); k = bkey_s_c_null; break; } @@ -2533,10 +2530,10 @@ static struct bkey_s_c __bch2_btree_iter_peek_prev(struct btree_iter *iter, stru if (unlikely(iter->flags & BTREE_ITER_with_key_cache) && k.k && - (k2 = btree_trans_peek_key_cache(iter, k.k->p)).k) { + (k2 = btree_trans_peek_key_cache(trans, iter, k.k->p)).k) { k = k2; if (bkey_err(k2)) { - bch2_btree_iter_set_pos(iter, iter->pos); + bch2_btree_iter_set_pos(trans, iter, iter->pos); break; } } @@ -2557,25 +2554,27 @@ static struct bkey_s_c __bch2_btree_iter_peek_prev(struct btree_iter *iter, stru search_key = bpos_predecessor(path->l[0].b->data->min_key); } else { /* Start of btree: */ - bch2_btree_iter_set_pos(iter, POS_MIN); + bch2_btree_iter_set_pos(trans, iter, POS_MIN); k = bkey_s_c_null; break; } } - bch2_btree_iter_verify(iter); + bch2_btree_iter_verify(trans, iter); return k; } /** * bch2_btree_iter_peek_prev_min() - returns first key less than or equal to * iterator's current position + * @trans: btree transaction object * @iter: iterator to peek from * @end: search limit: returns keys greater than or equal to @end * * Returns: key if found, or an error extractable with bkey_err(). */ -struct bkey_s_c bch2_btree_iter_peek_prev_min(struct btree_iter *iter, struct bpos end) +struct bkey_s_c bch2_btree_iter_peek_prev_min(struct btree_trans *trans, struct btree_iter *iter, + struct bpos end) { if ((iter->flags & (BTREE_ITER_is_extents|BTREE_ITER_filter_snapshots)) && !bkey_eq(iter->pos, POS_MAX)) { @@ -2587,7 +2586,7 @@ struct bkey_s_c bch2_btree_iter_peek_prev_min(struct btree_iter *iter, struct bp * real visible extents - easiest to just use peek_slot() (which * internally uses peek() for extents) */ - struct bkey_s_c k = bch2_btree_iter_peek_slot(iter); + struct bkey_s_c k = bch2_btree_iter_peek_slot(trans, iter); if (bkey_err(k)) return k; @@ -2597,7 +2596,6 @@ struct bkey_s_c bch2_btree_iter_peek_prev_min(struct btree_iter *iter, struct bp return k; } - struct btree_trans *trans = iter->trans; struct bpos search_key = iter->pos; struct bkey_s_c k; btree_path_idx_t saved_path = 0; @@ -2613,7 +2611,7 @@ struct bkey_s_c bch2_btree_iter_peek_prev_min(struct btree_iter *iter, struct bp } while (1) { - k = __bch2_btree_iter_peek_prev(iter, search_key); + k = __bch2_btree_iter_peek_prev(trans, iter, search_key); if (unlikely(!k.k)) goto end; if (unlikely(bkey_err(k))) @@ -2704,10 +2702,10 @@ struct bkey_s_c bch2_btree_iter_peek_prev_min(struct btree_iter *iter, struct bp bch2_path_put_nokeep(trans, saved_path, iter->flags & BTREE_ITER_intent); bch2_btree_iter_verify_entry_exit(iter); - bch2_btree_iter_verify(iter); + bch2_btree_iter_verify(trans, iter); return k; end: - bch2_btree_iter_set_pos(iter, end); + bch2_btree_iter_set_pos(trans, iter, end); k = bkey_s_c_null; goto out_no_locked; } @@ -2715,27 +2713,27 @@ struct bkey_s_c bch2_btree_iter_peek_prev_min(struct btree_iter *iter, struct bp /** * bch2_btree_iter_prev() - returns first key less than iterator's current * position + * @trans: btree transaction object * @iter: iterator to peek from * * Returns: key if found, or an error extractable with bkey_err(). */ -struct bkey_s_c bch2_btree_iter_prev(struct btree_iter *iter) +struct bkey_s_c bch2_btree_iter_prev(struct btree_trans *trans, struct btree_iter *iter) { - if (!bch2_btree_iter_rewind(iter)) + if (!bch2_btree_iter_rewind(trans, iter)) return bkey_s_c_null; - return bch2_btree_iter_peek_prev(iter); + return bch2_btree_iter_peek_prev(trans, iter); } -struct bkey_s_c bch2_btree_iter_peek_slot(struct btree_iter *iter) +struct bkey_s_c bch2_btree_iter_peek_slot(struct btree_trans *trans, struct btree_iter *iter) { - struct btree_trans *trans = iter->trans; struct bpos search_key; struct bkey_s_c k; int ret; bch2_trans_verify_not_unlocked_or_in_restart(trans); - bch2_btree_iter_verify(iter); + bch2_btree_iter_verify(trans, iter); bch2_btree_iter_verify_entry_exit(iter); EBUG_ON(btree_iter_path(trans, iter)->level && (iter->flags & BTREE_ITER_with_key_cache)); @@ -2751,7 +2749,7 @@ struct bkey_s_c bch2_btree_iter_peek_slot(struct btree_iter *iter) if (iter->pos.inode == KEY_INODE_MAX) return bkey_s_c_null; - bch2_btree_iter_set_pos(iter, bpos_nosnap_successor(iter->pos)); + bch2_btree_iter_set_pos(trans, iter, bpos_nosnap_successor(iter->pos)); } search_key = btree_iter_search_key(iter); @@ -2785,7 +2783,7 @@ struct bkey_s_c bch2_btree_iter_peek_slot(struct btree_iter *iter) goto out; if (unlikely(iter->flags & BTREE_ITER_with_key_cache) && - (k = btree_trans_peek_key_cache(iter, iter->pos)).k) { + (k = btree_trans_peek_key_cache(trans, iter, iter->pos)).k) { if (!bkey_err(k)) iter->k = *k.k; /* We're not returning a key from iter->path: */ @@ -2812,8 +2810,8 @@ struct bkey_s_c bch2_btree_iter_peek_slot(struct btree_iter *iter) if (iter->flags & BTREE_ITER_intent) { struct btree_iter iter2; - bch2_trans_copy_iter(&iter2, iter); - k = bch2_btree_iter_peek_max(&iter2, end); + bch2_trans_copy_iter(trans, &iter2, iter); + k = bch2_btree_iter_peek_max(trans, &iter2, end); if (k.k && !bkey_err(k)) { swap(iter->key_cache_path, iter2.key_cache_path); @@ -2824,9 +2822,9 @@ struct bkey_s_c bch2_btree_iter_peek_slot(struct btree_iter *iter) } else { struct bpos pos = iter->pos; - k = bch2_btree_iter_peek_max(iter, end); + k = bch2_btree_iter_peek_max(trans, iter, end); if (unlikely(bkey_err(k))) - bch2_btree_iter_set_pos(iter, pos); + bch2_btree_iter_set_pos(trans, iter, pos); else iter->pos = pos; } @@ -2857,39 +2855,39 @@ struct bkey_s_c bch2_btree_iter_peek_slot(struct btree_iter *iter) btree_path_set_should_be_locked(trans, btree_iter_path(trans, iter)); out_no_locked: bch2_btree_iter_verify_entry_exit(iter); - bch2_btree_iter_verify(iter); - ret = bch2_btree_iter_verify_ret(iter, k); + bch2_btree_iter_verify(trans, iter); + ret = bch2_btree_iter_verify_ret(trans, iter, k); if (unlikely(ret)) return bkey_s_c_err(ret); return k; } -struct bkey_s_c bch2_btree_iter_next_slot(struct btree_iter *iter) +struct bkey_s_c bch2_btree_iter_next_slot(struct btree_trans *trans, struct btree_iter *iter) { - if (!bch2_btree_iter_advance(iter)) + if (!bch2_btree_iter_advance(trans, iter)) return bkey_s_c_null; - return bch2_btree_iter_peek_slot(iter); + return bch2_btree_iter_peek_slot(trans, iter); } -struct bkey_s_c bch2_btree_iter_prev_slot(struct btree_iter *iter) +struct bkey_s_c bch2_btree_iter_prev_slot(struct btree_trans *trans, struct btree_iter *iter) { - if (!bch2_btree_iter_rewind(iter)) + if (!bch2_btree_iter_rewind(trans, iter)) return bkey_s_c_null; - return bch2_btree_iter_peek_slot(iter); + return bch2_btree_iter_peek_slot(trans, iter); } /* Obsolete, but still used by rust wrapper in -tools */ -struct bkey_s_c bch2_btree_iter_peek_and_restart_outlined(struct btree_iter *iter) +struct bkey_s_c bch2_btree_iter_peek_and_restart_outlined(struct btree_trans *trans, struct btree_iter *iter) { struct bkey_s_c k; - while (btree_trans_too_many_iters(iter->trans) || - (k = bch2_btree_iter_peek_type(iter, iter->flags), + while (btree_trans_too_many_iters(trans) || + (k = bch2_btree_iter_peek_type(trans, iter, iter->flags), bch2_err_matches(bkey_err(k), BCH_ERR_transaction_restart))) - bch2_trans_begin(iter->trans); + bch2_trans_begin(trans); return k; } @@ -3035,7 +3033,6 @@ void bch2_trans_iter_exit(struct btree_trans *trans, struct btree_iter *iter) iter->path = 0; iter->update_path = 0; iter->key_cache_path = 0; - iter->trans = NULL; } void bch2_trans_iter_init_outlined(struct btree_trans *trans, @@ -3075,10 +3072,9 @@ void bch2_trans_node_iter_init(struct btree_trans *trans, BUG_ON(iter->min_depth != depth); } -void bch2_trans_copy_iter(struct btree_iter *dst, struct btree_iter *src) +void bch2_trans_copy_iter(struct btree_trans *trans, + struct btree_iter *dst, struct btree_iter *src) { - struct btree_trans *trans = src->trans; - *dst = *src; #ifdef TRACK_PATH_ALLOCATED dst->ip_allocated = _RET_IP_;
diff --git a/fs/bcachefs/btree_iter.h b/fs/bcachefs/btree_iter.h index e6f51a3..9d2cccf 100644 --- a/fs/bcachefs/btree_iter.h +++ b/fs/bcachefs/btree_iter.h
@@ -393,36 +393,37 @@ void bch2_trans_node_add(struct btree_trans *trans, struct btree_path *, struct void bch2_trans_node_drop(struct btree_trans *trans, struct btree *); void bch2_trans_node_reinit_iter(struct btree_trans *, struct btree *); -int __must_check __bch2_btree_iter_traverse(struct btree_iter *iter); -int __must_check bch2_btree_iter_traverse(struct btree_iter *); +int __must_check __bch2_btree_iter_traverse(struct btree_trans *, struct btree_iter *); +int __must_check bch2_btree_iter_traverse(struct btree_trans *, struct btree_iter *); -struct btree *bch2_btree_iter_peek_node(struct btree_iter *); -struct btree *bch2_btree_iter_peek_node_and_restart(struct btree_iter *); -struct btree *bch2_btree_iter_next_node(struct btree_iter *); +struct btree *bch2_btree_iter_peek_node(struct btree_trans *, struct btree_iter *); +struct btree *bch2_btree_iter_peek_node_and_restart(struct btree_trans *, struct btree_iter *); +struct btree *bch2_btree_iter_next_node(struct btree_trans *, struct btree_iter *); -struct bkey_s_c bch2_btree_iter_peek_max(struct btree_iter *, struct bpos); -struct bkey_s_c bch2_btree_iter_next(struct btree_iter *); +struct bkey_s_c bch2_btree_iter_peek_max(struct btree_trans *, struct btree_iter *, struct bpos); +struct bkey_s_c bch2_btree_iter_next(struct btree_trans *, struct btree_iter *); -static inline struct bkey_s_c bch2_btree_iter_peek(struct btree_iter *iter) +static inline struct bkey_s_c bch2_btree_iter_peek(struct btree_trans *trans, + struct btree_iter *iter) { - return bch2_btree_iter_peek_max(iter, SPOS_MAX); + return bch2_btree_iter_peek_max(trans, iter, SPOS_MAX); } -struct bkey_s_c bch2_btree_iter_peek_prev_min(struct btree_iter *, struct bpos); +struct bkey_s_c bch2_btree_iter_peek_prev_min(struct btree_trans *, struct btree_iter *, struct bpos); -static inline struct bkey_s_c bch2_btree_iter_peek_prev(struct btree_iter *iter) +static inline struct bkey_s_c bch2_btree_iter_peek_prev(struct btree_trans *trans, struct btree_iter *iter) { - return bch2_btree_iter_peek_prev_min(iter, POS_MIN); + return bch2_btree_iter_peek_prev_min(trans, iter, POS_MIN); } -struct bkey_s_c bch2_btree_iter_prev(struct btree_iter *); +struct bkey_s_c bch2_btree_iter_prev(struct btree_trans *, struct btree_iter *); -struct bkey_s_c bch2_btree_iter_peek_slot(struct btree_iter *); -struct bkey_s_c bch2_btree_iter_next_slot(struct btree_iter *); -struct bkey_s_c bch2_btree_iter_prev_slot(struct btree_iter *); +struct bkey_s_c bch2_btree_iter_peek_slot(struct btree_trans *, struct btree_iter *); +struct bkey_s_c bch2_btree_iter_next_slot(struct btree_trans *, struct btree_iter *); +struct bkey_s_c bch2_btree_iter_prev_slot(struct btree_trans *, struct btree_iter *); -bool bch2_btree_iter_advance(struct btree_iter *); -bool bch2_btree_iter_rewind(struct btree_iter *); +bool bch2_btree_iter_advance(struct btree_trans *, struct btree_iter *); +bool bch2_btree_iter_rewind(struct btree_trans *, struct btree_iter *); static inline void __bch2_btree_iter_set_pos(struct btree_iter *iter, struct bpos new_pos) { @@ -433,10 +434,9 @@ static inline void __bch2_btree_iter_set_pos(struct btree_iter *iter, struct bpo iter->k.size = 0; } -static inline void bch2_btree_iter_set_pos(struct btree_iter *iter, struct bpos new_pos) +static inline void bch2_btree_iter_set_pos(struct btree_trans *trans, + struct btree_iter *iter, struct bpos new_pos) { - struct btree_trans *trans = iter->trans; - if (unlikely(iter->update_path)) bch2_path_put(trans, iter->update_path, iter->flags & BTREE_ITER_intent); @@ -454,13 +454,14 @@ static inline void bch2_btree_iter_set_pos_to_extent_start(struct btree_iter *it iter->pos = bkey_start_pos(&iter->k); } -static inline void bch2_btree_iter_set_snapshot(struct btree_iter *iter, u32 snapshot) +static inline void bch2_btree_iter_set_snapshot(struct btree_trans *trans, + struct btree_iter *iter, u32 snapshot) { struct bpos pos = iter->pos; iter->snapshot = snapshot; pos.snapshot = snapshot; - bch2_btree_iter_set_pos(iter, pos); + bch2_btree_iter_set_pos(trans, iter, pos); } void bch2_trans_iter_exit(struct btree_trans *, struct btree_iter *); @@ -502,7 +503,6 @@ static inline void bch2_trans_iter_init_common(struct btree_trans *trans, unsigned flags, unsigned long ip) { - iter->trans = trans; iter->update_path = 0; iter->key_cache_path = 0; iter->btree_id = btree_id; @@ -539,9 +539,9 @@ static inline void bch2_trans_iter_init(struct btree_trans *trans, void bch2_trans_node_iter_init(struct btree_trans *, struct btree_iter *, enum btree_id, struct bpos, unsigned, unsigned, unsigned); -void bch2_trans_copy_iter(struct btree_iter *, struct btree_iter *); +void bch2_trans_copy_iter(struct btree_trans *, struct btree_iter *, struct btree_iter *); -void bch2_set_btree_iter_dontneed(struct btree_iter *); +void bch2_set_btree_iter_dontneed(struct btree_trans *, struct btree_iter *); void *__bch2_trans_kmalloc(struct btree_trans *, size_t); @@ -588,7 +588,7 @@ static inline struct bkey_s_c __bch2_bkey_get_iter(struct btree_trans *trans, struct bkey_s_c k; bch2_trans_iter_init(trans, iter, btree_id, pos, flags); - k = bch2_btree_iter_peek_slot(iter); + k = bch2_btree_iter_peek_slot(trans, iter); if (!bkey_err(k) && type && k.k->type != type) k = bkey_s_c_err(-BCH_ERR_ENOENT_bkey_type_mismatch); @@ -658,14 +658,14 @@ u32 bch2_trans_begin(struct btree_trans *); int _ret3 = 0; \ do { \ _ret3 = lockrestart_do((_trans), ({ \ - struct btree *_b = bch2_btree_iter_peek_node(&_iter); \ + struct btree *_b = bch2_btree_iter_peek_node(_trans, &_iter);\ if (!_b) \ break; \ \ PTR_ERR_OR_ZERO(_b) ?: (_do); \ })) ?: \ lockrestart_do((_trans), \ - PTR_ERR_OR_ZERO(bch2_btree_iter_next_node(&_iter))); \ + PTR_ERR_OR_ZERO(bch2_btree_iter_next_node(_trans, &_iter)));\ } while (!_ret3); \ \ bch2_trans_iter_exit((_trans), &(_iter)); \ @@ -677,31 +677,34 @@ u32 bch2_trans_begin(struct btree_trans *); __for_each_btree_node(_trans, _iter, _btree_id, _start, \ 0, 0, _flags, _b, _do) -static inline struct bkey_s_c bch2_btree_iter_peek_prev_type(struct btree_iter *iter, +static inline struct bkey_s_c bch2_btree_iter_peek_prev_type(struct btree_trans *trans, + struct btree_iter *iter, unsigned flags) { - return flags & BTREE_ITER_slots ? bch2_btree_iter_peek_slot(iter) : - bch2_btree_iter_peek_prev(iter); + return flags & BTREE_ITER_slots ? bch2_btree_iter_peek_slot(trans, iter) : + bch2_btree_iter_peek_prev(trans, iter); } -static inline struct bkey_s_c bch2_btree_iter_peek_type(struct btree_iter *iter, +static inline struct bkey_s_c bch2_btree_iter_peek_type(struct btree_trans *trans, + struct btree_iter *iter, unsigned flags) { - return flags & BTREE_ITER_slots ? bch2_btree_iter_peek_slot(iter) : - bch2_btree_iter_peek(iter); + return flags & BTREE_ITER_slots ? bch2_btree_iter_peek_slot(trans, iter) : + bch2_btree_iter_peek(trans, iter); } -static inline struct bkey_s_c bch2_btree_iter_peek_max_type(struct btree_iter *iter, - struct bpos end, - unsigned flags) +static inline struct bkey_s_c bch2_btree_iter_peek_max_type(struct btree_trans *trans, + struct btree_iter *iter, + struct bpos end, + unsigned flags) { if (!(flags & BTREE_ITER_slots)) - return bch2_btree_iter_peek_max(iter, end); + return bch2_btree_iter_peek_max(trans, iter, end); if (bkey_gt(iter->pos, end)) return bkey_s_c_null; - return bch2_btree_iter_peek_slot(iter); + return bch2_btree_iter_peek_slot(trans, iter); } int __bch2_btree_trans_too_many_iters(struct btree_trans *); @@ -768,14 +771,14 @@ transaction_restart: \ \ do { \ _ret3 = lockrestart_do(_trans, ({ \ - (_k) = bch2_btree_iter_peek_max_type(&(_iter), \ + (_k) = bch2_btree_iter_peek_max_type(_trans, &(_iter), \ _end, (_flags)); \ if (!(_k).k) \ break; \ \ bkey_err(_k) ?: (_do); \ })); \ - } while (!_ret3 && bch2_btree_iter_advance(&(_iter))); \ + } while (!_ret3 && bch2_btree_iter_advance(_trans, &(_iter))); \ \ bch2_trans_iter_exit((_trans), &(_iter)); \ _ret3; \ @@ -813,14 +816,14 @@ transaction_restart: \ \ do { \ _ret3 = lockrestart_do(_trans, ({ \ - (_k) = bch2_btree_iter_peek_prev_type(&(_iter), \ + (_k) = bch2_btree_iter_peek_prev_type(_trans, &(_iter), \ (_flags)); \ if (!(_k).k) \ break; \ \ bkey_err(_k) ?: (_do); \ })); \ - } while (!_ret3 && bch2_btree_iter_rewind(&(_iter))); \ + } while (!_ret3 && bch2_btree_iter_rewind(_trans, &(_iter))); \ \ bch2_trans_iter_exit((_trans), &(_iter)); \ _ret3; \ @@ -850,37 +853,38 @@ transaction_restart: \ (_do) ?: bch2_trans_commit(_trans, (_disk_res),\ (_journal_seq), (_commit_flags))) -struct bkey_s_c bch2_btree_iter_peek_and_restart_outlined(struct btree_iter *); +struct bkey_s_c bch2_btree_iter_peek_and_restart_outlined(struct btree_trans *, + struct btree_iter *); #define for_each_btree_key_max_norestart(_trans, _iter, _btree_id, \ _start, _end, _flags, _k, _ret) \ for (bch2_trans_iter_init((_trans), &(_iter), (_btree_id), \ (_start), (_flags)); \ - (_k) = bch2_btree_iter_peek_max_type(&(_iter), _end, _flags),\ + (_k) = bch2_btree_iter_peek_max_type(_trans, &(_iter), _end, _flags),\ !((_ret) = bkey_err(_k)) && (_k).k; \ - bch2_btree_iter_advance(&(_iter))) + bch2_btree_iter_advance(_trans, &(_iter))) -#define for_each_btree_key_max_continue_norestart(_iter, _end, _flags, _k, _ret)\ +#define for_each_btree_key_max_continue_norestart(_trans, _iter, _end, _flags, _k, _ret)\ for (; \ - (_k) = bch2_btree_iter_peek_max_type(&(_iter), _end, _flags), \ + (_k) = bch2_btree_iter_peek_max_type(_trans, &(_iter), _end, _flags), \ !((_ret) = bkey_err(_k)) && (_k).k; \ - bch2_btree_iter_advance(&(_iter))) + bch2_btree_iter_advance(_trans, &(_iter))) #define for_each_btree_key_norestart(_trans, _iter, _btree_id, \ _start, _flags, _k, _ret) \ for_each_btree_key_max_norestart(_trans, _iter, _btree_id, _start,\ SPOS_MAX, _flags, _k, _ret) -#define for_each_btree_key_reverse_norestart(_trans, _iter, _btree_id, \ - _start, _flags, _k, _ret) \ - for (bch2_trans_iter_init((_trans), &(_iter), (_btree_id), \ - (_start), (_flags)); \ - (_k) = bch2_btree_iter_peek_prev_type(&(_iter), _flags), \ - !((_ret) = bkey_err(_k)) && (_k).k; \ - bch2_btree_iter_rewind(&(_iter))) +#define for_each_btree_key_reverse_norestart(_trans, _iter, _btree_id, \ + _start, _flags, _k, _ret) \ + for (bch2_trans_iter_init((_trans), &(_iter), (_btree_id), \ + (_start), (_flags)); \ + (_k) = bch2_btree_iter_peek_prev_type(_trans, &(_iter), _flags), \ + !((_ret) = bkey_err(_k)) && (_k).k; \ + bch2_btree_iter_rewind(_trans, &(_iter))) -#define for_each_btree_key_continue_norestart(_iter, _flags, _k, _ret) \ - for_each_btree_key_max_continue_norestart(_iter, SPOS_MAX, _flags, _k, _ret) +#define for_each_btree_key_continue_norestart(_trans, _iter, _flags, _k, _ret) \ + for_each_btree_key_max_continue_norestart(_trans, _iter, SPOS_MAX, _flags, _k, _ret) /* * This should not be used in a fastpath, without first trying _do in
diff --git a/fs/bcachefs/btree_key_cache.c b/fs/bcachefs/btree_key_cache.c index edce594..2b18658 100644 --- a/fs/bcachefs/btree_key_cache.c +++ b/fs/bcachefs/btree_key_cache.c
@@ -287,6 +287,19 @@ static int btree_key_cache_create(struct btree_trans *trans, return ret; } +static noinline_for_stack void do_trace_key_cache_fill(struct btree_trans *trans, + struct btree_path *ck_path, + struct bkey_s_c k) +{ + struct printbuf buf = PRINTBUF; + + bch2_bpos_to_text(&buf, ck_path->pos); + prt_char(&buf, ' '); + bch2_bkey_val_to_text(&buf, trans->c, k); + trace_key_cache_fill(trans, buf.buf); + printbuf_exit(&buf); +} + static noinline int btree_key_cache_fill(struct btree_trans *trans, struct btree_path *ck_path, unsigned flags) @@ -306,7 +319,7 @@ static noinline int btree_key_cache_fill(struct btree_trans *trans, BTREE_ITER_key_cache_fill| BTREE_ITER_cached_nofill); iter.flags &= ~BTREE_ITER_with_journal; - k = bch2_btree_iter_peek_slot(&iter); + k = bch2_btree_iter_peek_slot(trans, &iter); ret = bkey_err(k); if (ret) goto err; @@ -320,18 +333,11 @@ static noinline int btree_key_cache_fill(struct btree_trans *trans, if (ret) goto err; - if (trace_key_cache_fill_enabled()) { - struct printbuf buf = PRINTBUF; - - bch2_bpos_to_text(&buf, ck_path->pos); - prt_char(&buf, ' '); - bch2_bkey_val_to_text(&buf, trans->c, k); - trace_key_cache_fill(trans, buf.buf); - printbuf_exit(&buf); - } + if (trace_key_cache_fill_enabled()) + do_trace_key_cache_fill(trans, ck_path, k); out: /* We're not likely to need this iterator again: */ - bch2_set_btree_iter_dontneed(&iter); + bch2_set_btree_iter_dontneed(trans, &iter); err: bch2_trans_iter_exit(trans, &iter); return ret; @@ -412,7 +418,7 @@ static int btree_key_cache_flush_pos(struct btree_trans *trans, BTREE_ITER_intent); b_iter.flags &= ~BTREE_ITER_with_key_cache; - ret = bch2_btree_iter_traverse(&c_iter); + ret = bch2_btree_iter_traverse(trans, &c_iter); if (ret) goto out; @@ -444,7 +450,7 @@ static int btree_key_cache_flush_pos(struct btree_trans *trans, !test_bit(JOURNAL_space_low, &c->journal.flags)) commit_flags |= BCH_TRANS_COMMIT_no_journal_res; - struct bkey_s_c btree_k = bch2_btree_iter_peek_slot(&b_iter); + struct bkey_s_c btree_k = bch2_btree_iter_peek_slot(trans, &b_iter); ret = bkey_err(btree_k); if (ret) goto err;
diff --git a/fs/bcachefs/btree_node_scan.c b/fs/bcachefs/btree_node_scan.c index 25d54b7..8c9fdb7 100644 --- a/fs/bcachefs/btree_node_scan.c +++ b/fs/bcachefs/btree_node_scan.c
@@ -271,7 +271,7 @@ static int read_btree_nodes_worker(void *p) err: bio_put(bio); free_page((unsigned long) buf); - percpu_ref_put(&ca->io_ref); + percpu_ref_put(&ca->io_ref[READ]); closure_put(w->cl); kfree(w); return 0; @@ -291,7 +291,7 @@ static int read_btree_nodes(struct find_btree_nodes *f) struct find_btree_nodes_worker *w = kmalloc(sizeof(*w), GFP_KERNEL); if (!w) { - percpu_ref_put(&ca->io_ref); + percpu_ref_put(&ca->io_ref[READ]); ret = -ENOMEM; goto err; } @@ -303,14 +303,14 @@ static int read_btree_nodes(struct find_btree_nodes *f) struct task_struct *t = kthread_create(read_btree_nodes_worker, w, "read_btree_nodes/%s", ca->name); ret = PTR_ERR_OR_ZERO(t); if (ret) { - percpu_ref_put(&ca->io_ref); + percpu_ref_put(&ca->io_ref[READ]); kfree(w); bch_err_msg(c, ret, "starting kthread"); break; } closure_get(&cl); - percpu_ref_get(&ca->io_ref); + percpu_ref_get(&ca->io_ref[READ]); wake_up_process(t); } err:
diff --git a/fs/bcachefs/btree_types.h b/fs/bcachefs/btree_types.h index 77578da..023c472 100644 --- a/fs/bcachefs/btree_types.h +++ b/fs/bcachefs/btree_types.h
@@ -367,7 +367,6 @@ static inline unsigned long btree_path_ip_allocated(struct btree_path *path) * @nodes_intent_locked - bitmask indicating which locks are intent locks */ struct btree_iter { - struct btree_trans *trans; btree_path_idx_t path; btree_path_idx_t update_path; btree_path_idx_t key_cache_path;
diff --git a/fs/bcachefs/btree_update.c b/fs/bcachefs/btree_update.c index c05394f..1e6b783 100644 --- a/fs/bcachefs/btree_update.c +++ b/fs/bcachefs/btree_update.c
@@ -126,7 +126,7 @@ int __bch2_insert_snapshot_whiteouts(struct btree_trans *trans, struct bpos new_pos) { struct bch_fs *c = trans->c; - struct btree_iter old_iter, new_iter = { NULL }; + struct btree_iter old_iter, new_iter = {}; struct bkey_s_c old_k, new_k; snapshot_id_list s; struct bkey_i *update; @@ -140,7 +140,7 @@ int __bch2_insert_snapshot_whiteouts(struct btree_trans *trans, bch2_trans_iter_init(trans, &old_iter, id, old_pos, BTREE_ITER_not_extents| BTREE_ITER_all_snapshots); - while ((old_k = bch2_btree_iter_prev(&old_iter)).k && + while ((old_k = bch2_btree_iter_prev(trans, &old_iter)).k && !(ret = bkey_err(old_k)) && bkey_eq(old_pos, old_k.k->p)) { struct bpos whiteout_pos = @@ -296,7 +296,7 @@ static int bch2_trans_update_extent(struct btree_trans *trans, BTREE_ITER_intent| BTREE_ITER_with_updates| BTREE_ITER_not_extents); - k = bch2_btree_iter_peek_max(&iter, POS(insert->k.p.inode, U64_MAX)); + k = bch2_btree_iter_peek_max(trans, &iter, POS(insert->k.p.inode, U64_MAX)); if ((ret = bkey_err(k))) goto err; if (!k.k) @@ -322,8 +322,8 @@ static int bch2_trans_update_extent(struct btree_trans *trans, if (done) goto out; next: - bch2_btree_iter_advance(&iter); - k = bch2_btree_iter_peek_max(&iter, POS(insert->k.p.inode, U64_MAX)); + bch2_btree_iter_advance(trans, &iter); + k = bch2_btree_iter_peek_max(trans, &iter, POS(insert->k.p.inode, U64_MAX)); if ((ret = bkey_err(k))) goto err; if (!k.k) @@ -592,13 +592,13 @@ int bch2_bkey_get_empty_slot(struct btree_trans *trans, struct btree_iter *iter, enum btree_id btree, struct bpos end) { bch2_trans_iter_init(trans, iter, btree, end, BTREE_ITER_intent); - struct bkey_s_c k = bch2_btree_iter_peek_prev(iter); + struct bkey_s_c k = bch2_btree_iter_peek_prev(trans, iter); int ret = bkey_err(k); if (ret) goto err; - bch2_btree_iter_advance(iter); - k = bch2_btree_iter_peek_slot(iter); + bch2_btree_iter_advance(trans, iter); + k = bch2_btree_iter_peek_slot(trans, iter); ret = bkey_err(k); if (ret) goto err; @@ -634,7 +634,7 @@ int bch2_btree_insert_nonextent(struct btree_trans *trans, BTREE_ITER_cached| BTREE_ITER_not_extents| BTREE_ITER_intent); - ret = bch2_btree_iter_traverse(&iter) ?: + ret = bch2_btree_iter_traverse(trans, &iter) ?: bch2_trans_update(trans, &iter, k, flags); bch2_trans_iter_exit(trans, &iter); return ret; @@ -646,7 +646,7 @@ int bch2_btree_insert_trans(struct btree_trans *trans, enum btree_id id, struct btree_iter iter; bch2_trans_iter_init(trans, &iter, id, bkey_start_pos(&k->k), BTREE_ITER_intent|flags); - int ret = bch2_btree_iter_traverse(&iter) ?: + int ret = bch2_btree_iter_traverse(trans, &iter) ?: bch2_trans_update(trans, &iter, k, flags); bch2_trans_iter_exit(trans, &iter); return ret; @@ -695,7 +695,7 @@ int bch2_btree_delete(struct btree_trans *trans, bch2_trans_iter_init(trans, &iter, btree, pos, BTREE_ITER_cached| BTREE_ITER_intent); - ret = bch2_btree_iter_traverse(&iter) ?: + ret = bch2_btree_iter_traverse(trans, &iter) ?: bch2_btree_delete_at(trans, &iter, update_flags); bch2_trans_iter_exit(trans, &iter); @@ -713,7 +713,7 @@ int bch2_btree_delete_range_trans(struct btree_trans *trans, enum btree_id id, int ret = 0; bch2_trans_iter_init(trans, &iter, id, start, BTREE_ITER_intent); - while ((k = bch2_btree_iter_peek_max(&iter, end)).k) { + while ((k = bch2_btree_iter_peek_max(trans, &iter, end)).k) { struct disk_reservation disk_res = bch2_disk_reservation_init(trans->c, 0); struct bkey_i delete; @@ -808,7 +808,7 @@ int bch2_btree_bit_mod(struct btree_trans *trans, enum btree_id btree, struct btree_iter iter; bch2_trans_iter_init(trans, &iter, btree, pos, BTREE_ITER_intent); - int ret = bch2_btree_iter_traverse(&iter) ?: + int ret = bch2_btree_iter_traverse(trans, &iter) ?: bch2_btree_bit_mod_iter(trans, &iter, set); bch2_trans_iter_exit(trans, &iter); return ret;
diff --git a/fs/bcachefs/btree_update_interior.c b/fs/bcachefs/btree_update_interior.c index bf7e1da..55fbeeb 100644 --- a/fs/bcachefs/btree_update_interior.c +++ b/fs/bcachefs/btree_update_interior.c
@@ -2147,7 +2147,7 @@ static int get_iter_to_node(struct btree_trans *trans, struct btree_iter *iter, bch2_trans_node_iter_init(trans, iter, b->c.btree_id, b->key.k.p, BTREE_MAX_DEPTH, b->c.level, BTREE_ITER_intent); - int ret = bch2_btree_iter_traverse(iter); + int ret = bch2_btree_iter_traverse(trans, iter); if (ret) goto err; @@ -2239,7 +2239,7 @@ static int bch2_btree_node_rewrite_key(struct btree_trans *trans, bch2_trans_node_iter_init(trans, &iter, btree, k->k.p, BTREE_MAX_DEPTH, level, 0); - struct btree *b = bch2_btree_iter_peek_node(&iter); + struct btree *b = bch2_btree_iter_peek_node(trans, &iter); int ret = PTR_ERR_OR_ZERO(b); if (ret) goto out; @@ -2262,7 +2262,7 @@ int bch2_btree_node_rewrite_pos(struct btree_trans *trans, /* Traverse one depth lower to get a pointer to the node itself: */ struct btree_iter iter; bch2_trans_node_iter_init(trans, &iter, btree, pos, 0, level - 1, 0); - struct btree *b = bch2_btree_iter_peek_node(&iter); + struct btree *b = bch2_btree_iter_peek_node(trans, &iter); int ret = PTR_ERR_OR_ZERO(b); if (ret) goto err; @@ -2406,7 +2406,7 @@ static int __bch2_btree_node_update_key(struct btree_trans *trans, bool skip_triggers) { struct bch_fs *c = trans->c; - struct btree_iter iter2 = { NULL }; + struct btree_iter iter2 = {}; struct btree *parent; int ret; @@ -2430,7 +2430,7 @@ static int __bch2_btree_node_update_key(struct btree_trans *trans, parent = btree_node_parent(btree_iter_path(trans, iter), b); if (parent) { - bch2_trans_copy_iter(&iter2, iter); + bch2_trans_copy_iter(trans, &iter2, iter); iter2.path = bch2_btree_path_make_mut(trans, iter2.path, iter2.flags & BTREE_ITER_intent, @@ -2444,7 +2444,7 @@ static int __bch2_btree_node_update_key(struct btree_trans *trans, trans->paths_sorted = false; - ret = bch2_btree_iter_traverse(&iter2) ?: + ret = bch2_btree_iter_traverse(trans, &iter2) ?: bch2_trans_update(trans, &iter2, new_key, BTREE_TRIGGER_norun); if (ret) goto err;
diff --git a/fs/bcachefs/btree_write_buffer.c b/fs/bcachefs/btree_write_buffer.c index 2c09d19..adbe576 100644 --- a/fs/bcachefs/btree_write_buffer.c +++ b/fs/bcachefs/btree_write_buffer.c
@@ -144,7 +144,7 @@ static inline int wb_flush_one(struct btree_trans *trans, struct btree_iter *ite EBUG_ON(!trans->c->btree_write_buffer.flushing.pin.seq); EBUG_ON(trans->c->btree_write_buffer.flushing.pin.seq > wb->journal_seq); - ret = bch2_btree_iter_traverse(iter); + ret = bch2_btree_iter_traverse(trans, iter); if (ret) return ret; @@ -208,7 +208,7 @@ btree_write_buffered_insert(struct btree_trans *trans, trans->journal_res.seq = wb->journal_seq; - ret = bch2_btree_iter_traverse(&iter) ?: + ret = bch2_btree_iter_traverse(trans, &iter) ?: bch2_trans_update(trans, &iter, &wb->k, BTREE_UPDATE_internal_snapshot_node); bch2_trans_iter_exit(trans, &iter); @@ -285,7 +285,7 @@ static int bch2_btree_write_buffer_flush_locked(struct btree_trans *trans) struct bch_fs *c = trans->c; struct journal *j = &c->journal; struct btree_write_buffer *wb = &c->btree_write_buffer; - struct btree_iter iter = { NULL }; + struct btree_iter iter = {}; size_t overwritten = 0, fast = 0, slowpath = 0, could_not_insert = 0; bool write_locked = false; bool accounting_replay_done = test_bit(BCH_FS_accounting_replay_done, &c->flags); @@ -368,7 +368,7 @@ static int bch2_btree_write_buffer_flush_locked(struct btree_trans *trans) write_locked = false; ret = lockrestart_do(trans, - bch2_btree_iter_traverse(&iter) ?: + bch2_btree_iter_traverse(trans, &iter) ?: bch2_foreground_maybe_merge(trans, iter.path, 0, BCH_WATERMARK_reclaim| BCH_TRANS_COMMIT_journal_reclaim| @@ -385,7 +385,7 @@ static int bch2_btree_write_buffer_flush_locked(struct btree_trans *trans) BTREE_ITER_intent|BTREE_ITER_all_snapshots); } - bch2_btree_iter_set_pos(&iter, k->k.k.p); + bch2_btree_iter_set_pos(trans, &iter, k->k.k.p); btree_iter_path(trans, &iter)->preserve = false; bool accounting_accumulated = false;
diff --git a/fs/bcachefs/buckets.c b/fs/bcachefs/buckets.c index 0903311..fea61e6 100644 --- a/fs/bcachefs/buckets.c +++ b/fs/bcachefs/buckets.c
@@ -30,6 +30,12 @@ void bch2_dev_usage_read_fast(struct bch_dev *ca, struct bch_dev_usage *usage) { + for (unsigned i = 0; i < BCH_DATA_NR; i++) + usage->buckets[i] = percpu_u64_get(&ca->usage->d[i].buckets); +} + +void bch2_dev_usage_full_read_fast(struct bch_dev *ca, struct bch_dev_usage_full *usage) +{ memset(usage, 0, sizeof(*usage)); acc_u64s_percpu((u64 *) usage, (u64 __percpu *) ca->usage, dev_usage_u64s()); } @@ -75,7 +81,7 @@ bch2_fs_usage_read_short(struct bch_fs *c) void bch2_dev_usage_to_text(struct printbuf *out, struct bch_dev *ca, - struct bch_dev_usage *usage) + struct bch_dev_usage_full *usage) { if (out->nr_tabstops < 5) { printbuf_tabstops_reset(out); @@ -365,7 +371,7 @@ int bch2_check_fix_ptrs(struct btree_trans *trans, struct btree_iter iter; bch2_trans_node_iter_init(trans, &iter, btree, new->k.p, 0, level, BTREE_ITER_intent|BTREE_ITER_all_snapshots); - ret = bch2_btree_iter_traverse(&iter) ?: + ret = bch2_btree_iter_traverse(trans, &iter) ?: bch2_trans_update(trans, &iter, new, BTREE_UPDATE_internal_snapshot_node| BTREE_TRIGGER_norun); @@ -707,7 +713,7 @@ static int bch2_trigger_stripe_ptr(struct btree_trans *trans, struct disk_accounting_pos acc; memset(&acc, 0, sizeof(acc)); acc.type = BCH_DISK_ACCOUNTING_replicas; - memcpy(&acc.replicas, &m->r.e, replicas_entry_bytes(&m->r.e)); + unsafe_memcpy(&acc.replicas, &m->r.e, replicas_entry_bytes(&m->r.e), "VLA"); gc_stripe_unlock(m); acc.replicas.data_type = data_type; @@ -1132,7 +1138,7 @@ int bch2_trans_mark_dev_sbs_flags(struct bch_fs *c, for_each_online_member(c, ca) { int ret = bch2_trans_mark_dev_sb(c, ca, flags); if (ret) { - percpu_ref_put(&ca->io_ref); + percpu_ref_put(&ca->io_ref[READ]); return ret; } } @@ -1331,7 +1337,7 @@ void bch2_dev_buckets_free(struct bch_dev *ca) int bch2_dev_buckets_alloc(struct bch_fs *c, struct bch_dev *ca) { - ca->usage = alloc_percpu(struct bch_dev_usage); + ca->usage = alloc_percpu(struct bch_dev_usage_full); if (!ca->usage) return -BCH_ERR_ENOMEM_usage_init;
diff --git a/fs/bcachefs/buckets.h b/fs/bcachefs/buckets.h index c536325..1c38b16 100644 --- a/fs/bcachefs/buckets.h +++ b/fs/bcachefs/buckets.h
@@ -172,7 +172,16 @@ static inline struct bch_dev_usage bch2_dev_usage_read(struct bch_dev *ca) return ret; } -void bch2_dev_usage_to_text(struct printbuf *, struct bch_dev *, struct bch_dev_usage *); +void bch2_dev_usage_full_read_fast(struct bch_dev *, struct bch_dev_usage_full *); +static inline struct bch_dev_usage_full bch2_dev_usage_full_read(struct bch_dev *ca) +{ + struct bch_dev_usage_full ret; + + bch2_dev_usage_full_read_fast(ca, &ret); + return ret; +} + +void bch2_dev_usage_to_text(struct printbuf *, struct bch_dev *, struct bch_dev_usage_full *); static inline u64 bch2_dev_buckets_reserved(struct bch_dev *ca, enum bch_watermark watermark) { @@ -207,7 +216,7 @@ static inline u64 dev_buckets_free(struct bch_dev *ca, enum bch_watermark watermark) { return max_t(s64, 0, - usage.d[BCH_DATA_free].buckets - + usage.buckets[BCH_DATA_free]- ca->nr_open_buckets - bch2_dev_buckets_reserved(ca, watermark)); } @@ -217,10 +226,10 @@ static inline u64 __dev_buckets_available(struct bch_dev *ca, enum bch_watermark watermark) { return max_t(s64, 0, - usage.d[BCH_DATA_free].buckets - + usage.d[BCH_DATA_cached].buckets - + usage.d[BCH_DATA_need_gc_gens].buckets - + usage.d[BCH_DATA_need_discard].buckets + usage.buckets[BCH_DATA_free] + + usage.buckets[BCH_DATA_cached] + + usage.buckets[BCH_DATA_need_gc_gens] + + usage.buckets[BCH_DATA_need_discard] - ca->nr_open_buckets - bch2_dev_buckets_reserved(ca, watermark)); }
diff --git a/fs/bcachefs/buckets_types.h b/fs/bcachefs/buckets_types.h index 900b868..0aed250 100644 --- a/fs/bcachefs/buckets_types.h +++ b/fs/bcachefs/buckets_types.h
@@ -54,7 +54,12 @@ struct bucket_gens { u8 b[] __counted_by(nbuckets); }; +/* Only info on bucket countns: */ struct bch_dev_usage { + u64 buckets[BCH_DATA_NR]; +}; + +struct bch_dev_usage_full { struct bch_dev_usage_type { u64 buckets; u64 sectors; /* _compressed_ sectors: */
diff --git a/fs/bcachefs/chardev.c b/fs/bcachefs/chardev.c index 584f4a3..5891b3a 100644 --- a/fs/bcachefs/chardev.c +++ b/fs/bcachefs/chardev.c
@@ -350,8 +350,8 @@ static ssize_t bch2_data_job_read(struct file *file, char __user *buf, if (ctx->arg.op == BCH_DATA_OP_scrub) { struct bch_dev *ca = bch2_dev_tryget(c, ctx->arg.scrub.dev); if (ca) { - struct bch_dev_usage u; - bch2_dev_usage_read_fast(ca, &u); + struct bch_dev_usage_full u; + bch2_dev_usage_full_read_fast(ca, &u); for (unsigned i = BCH_DATA_btree; i < ARRAY_SIZE(u.d); i++) if (ctx->arg.scrub.data_types & BIT(i)) e.p.sectors_total += u.d[i].sectors; @@ -473,7 +473,7 @@ static long bch2_ioctl_dev_usage(struct bch_fs *c, struct bch_ioctl_dev_usage __user *user_arg) { struct bch_ioctl_dev_usage arg; - struct bch_dev_usage src; + struct bch_dev_usage_full src; struct bch_dev *ca; unsigned i; @@ -493,7 +493,7 @@ static long bch2_ioctl_dev_usage(struct bch_fs *c, if (IS_ERR(ca)) return PTR_ERR(ca); - src = bch2_dev_usage_read(ca); + src = bch2_dev_usage_full_read(ca); arg.state = ca->mi.state; arg.bucket_size = ca->mi.bucket_size; @@ -514,7 +514,7 @@ static long bch2_ioctl_dev_usage_v2(struct bch_fs *c, struct bch_ioctl_dev_usage_v2 __user *user_arg) { struct bch_ioctl_dev_usage_v2 arg; - struct bch_dev_usage src; + struct bch_dev_usage_full src; struct bch_dev *ca; int ret = 0; @@ -534,7 +534,7 @@ static long bch2_ioctl_dev_usage_v2(struct bch_fs *c, if (IS_ERR(ca)) return PTR_ERR(ca); - src = bch2_dev_usage_read(ca); + src = bch2_dev_usage_full_read(ca); arg.state = ca->mi.state; arg.bucket_size = ca->mi.bucket_size; @@ -615,7 +615,7 @@ static long bch2_ioctl_disk_get_idx(struct bch_fs *c, for_each_online_member(c, ca) if (ca->dev == dev) { - percpu_ref_put(&ca->io_ref); + percpu_ref_put(&ca->io_ref[READ]); return ca->dev_idx; }
diff --git a/fs/bcachefs/clock.c b/fs/bcachefs/clock.c index 1f8e035..d6dd12d 100644 --- a/fs/bcachefs/clock.c +++ b/fs/bcachefs/clock.c
@@ -121,7 +121,7 @@ void bch2_kthread_io_clock_wait(struct io_clock *clock, } while (0); __set_current_state(TASK_RUNNING); - del_timer_sync(&wait.cpu_timer); + timer_delete_sync(&wait.cpu_timer); destroy_timer_on_stack(&wait.cpu_timer); bch2_io_timer_del(clock, &wait.io_timer); }
diff --git a/fs/bcachefs/compress.c b/fs/bcachefs/compress.c index 85fc903..28ed324 100644 --- a/fs/bcachefs/compress.c +++ b/fs/bcachefs/compress.c
@@ -371,13 +371,14 @@ static int attempt_compress(struct bch_fs *c, }; zlib_set_workspace(&strm, workspace); - zlib_deflateInit2(&strm, + if (zlib_deflateInit2(&strm, compression.level ? clamp_t(unsigned, compression.level, Z_BEST_SPEED, Z_BEST_COMPRESSION) : Z_DEFAULT_COMPRESSION, Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, - Z_DEFAULT_STRATEGY); + Z_DEFAULT_STRATEGY) != Z_OK) + return 0; if (zlib_deflate(&strm, Z_FINISH) != Z_STREAM_END) return 0;
diff --git a/fs/bcachefs/data_update.c b/fs/bcachefs/data_update.c index fe400df..de02ebf 100644 --- a/fs/bcachefs/data_update.c +++ b/fs/bcachefs/data_update.c
@@ -216,7 +216,7 @@ static int __bch2_data_update_index_update(struct btree_trans *trans, bch2_trans_begin(trans); - k = bch2_btree_iter_peek_slot(&iter); + k = bch2_btree_iter_peek_slot(trans, &iter); ret = bkey_err(k); if (ret) goto err; @@ -398,7 +398,7 @@ static int __bch2_data_update_index_update(struct btree_trans *trans, BCH_TRANS_COMMIT_no_enospc| m->data_opts.btree_insert_flags); if (!ret) { - bch2_btree_iter_set_pos(&iter, next_pos); + bch2_btree_iter_set_pos(trans, &iter, next_pos); this_cpu_add(c->counters[BCH_COUNTER_io_move_finish], new->k.size); if (trace_io_move_finish_enabled()) @@ -426,7 +426,7 @@ static int __bch2_data_update_index_update(struct btree_trans *trans, count_event(c, io_move_fail); - bch2_btree_iter_advance(&iter); + bch2_btree_iter_advance(trans, &iter); goto next; } out: @@ -497,7 +497,7 @@ static int bch2_update_unwritten_extent(struct btree_trans *trans, bch2_trans_iter_init(trans, &iter, update->btree_id, update->op.pos, BTREE_ITER_slots); ret = lockrestart_do(trans, ({ - k = bch2_btree_iter_peek_slot(&iter); + k = bch2_btree_iter_peek_slot(trans, &iter); bkey_err(k); })); bch2_trans_iter_exit(trans, &iter);
diff --git a/fs/bcachefs/debug.c b/fs/bcachefs/debug.c index 788af88..5a8bc70 100644 --- a/fs/bcachefs/debug.c +++ b/fs/bcachefs/debug.c
@@ -57,7 +57,7 @@ static bool bch2_btree_verify_replica(struct bch_fs *c, struct btree *b, submit_bio_wait(bio); bio_put(bio); - percpu_ref_put(&ca->io_ref); + percpu_ref_put(&ca->io_ref[READ]); memcpy(n_ondisk, n_sorted, btree_buf_bytes(b)); @@ -297,7 +297,7 @@ void bch2_btree_node_ondisk_to_text(struct printbuf *out, struct bch_fs *c, if (bio) bio_put(bio); kvfree(n_ondisk); - percpu_ref_put(&ca->io_ref); + percpu_ref_put(&ca->io_ref[READ]); } #ifdef CONFIG_DEBUG_FS
diff --git a/fs/bcachefs/dirent.c b/fs/bcachefs/dirent.c index d7f9f79..bf53a02 100644 --- a/fs/bcachefs/dirent.c +++ b/fs/bcachefs/dirent.c
@@ -417,8 +417,8 @@ int bch2_dirent_rename(struct btree_trans *trans, enum bch_rename_mode mode) { struct qstr src_name_lookup, dst_name_lookup; - struct btree_iter src_iter = { NULL }; - struct btree_iter dst_iter = { NULL }; + struct btree_iter src_iter = {}; + struct btree_iter dst_iter = {}; struct bkey_s_c old_src, old_dst = bkey_s_c_null; struct bkey_i_dirent *new_src = NULL, *new_dst = NULL; struct bpos dst_pos = @@ -586,16 +586,16 @@ int bch2_dirent_rename(struct btree_trans *trans, } if (delete_src) { - bch2_btree_iter_set_snapshot(&src_iter, old_src.k->p.snapshot); - ret = bch2_btree_iter_traverse(&src_iter) ?: + bch2_btree_iter_set_snapshot(trans, &src_iter, old_src.k->p.snapshot); + ret = bch2_btree_iter_traverse(trans, &src_iter) ?: bch2_btree_delete_at(trans, &src_iter, BTREE_UPDATE_internal_snapshot_node); if (ret) goto out; } if (delete_dst) { - bch2_btree_iter_set_snapshot(&dst_iter, old_dst.k->p.snapshot); - ret = bch2_btree_iter_traverse(&dst_iter) ?: + bch2_btree_iter_set_snapshot(trans, &dst_iter, old_dst.k->p.snapshot); + ret = bch2_btree_iter_traverse(trans, &dst_iter) ?: bch2_btree_delete_at(trans, &dst_iter, BTREE_UPDATE_internal_snapshot_node); if (ret) goto out; @@ -642,7 +642,7 @@ u64 bch2_dirent_lookup(struct bch_fs *c, subvol_inum dir, const struct qstr *name, subvol_inum *inum) { struct btree_trans *trans = bch2_trans_get(c); - struct btree_iter iter = { NULL }; + struct btree_iter iter = {}; int ret = lockrestart_do(trans, bch2_dirent_lookup_trans(trans, &iter, dir, hash_info, name, inum, 0)); @@ -771,7 +771,7 @@ int bch2_fsck_remove_dirent(struct btree_trans *trans, struct bpos pos) bch2_trans_iter_init(trans, &iter, BTREE_ID_dirents, pos, BTREE_ITER_intent); - ret = bch2_btree_iter_traverse(&iter) ?: + ret = bch2_btree_iter_traverse(trans, &iter) ?: bch2_hash_delete_at(trans, bch2_dirent_hash_desc, &dir_hash_info, &iter, BTREE_UPDATE_internal_snapshot_node);
diff --git a/fs/bcachefs/disk_accounting.c b/fs/bcachefs/disk_accounting.c index a59f6c1..b007319 100644 --- a/fs/bcachefs/disk_accounting.c +++ b/fs/bcachefs/disk_accounting.c
@@ -739,7 +739,7 @@ int bch2_accounting_read(struct bch_fs *c) struct disk_accounting_pos next; memset(&next, 0, sizeof(next)); next.type = acc_k.type + 1; - bch2_btree_iter_set_pos(&iter, disk_accounting_pos_to_bpos(&next)); + bch2_btree_iter_set_pos(trans, &iter, disk_accounting_pos_to_bpos(&next)); continue; } @@ -930,7 +930,7 @@ void bch2_verify_accounting_clean(struct bch_fs *c) struct disk_accounting_pos next; memset(&next, 0, sizeof(next)); next.type = acc_k.type + 1; - bch2_btree_iter_set_pos(&iter, disk_accounting_pos_to_bpos(&next)); + bch2_btree_iter_set_pos(trans, &iter, disk_accounting_pos_to_bpos(&next)); continue; }
diff --git a/fs/bcachefs/disk_groups.c b/fs/bcachefs/disk_groups.c index 5df8de0..1186280 100644 --- a/fs/bcachefs/disk_groups.c +++ b/fs/bcachefs/disk_groups.c
@@ -555,9 +555,9 @@ void bch2_target_to_text(struct printbuf *out, struct bch_fs *c, unsigned v) ? rcu_dereference(c->devs[t.dev]) : NULL; - if (ca && percpu_ref_tryget(&ca->io_ref)) { + if (ca && percpu_ref_tryget(&ca->io_ref[READ])) { prt_printf(out, "/dev/%s", ca->name); - percpu_ref_put(&ca->io_ref); + percpu_ref_put(&ca->io_ref[READ]); } else if (ca) { prt_printf(out, "offline device %u", t.dev); } else {
diff --git a/fs/bcachefs/ec.c b/fs/bcachefs/ec.c index 6faeda7..a396865 100644 --- a/fs/bcachefs/ec.c +++ b/fs/bcachefs/ec.c
@@ -105,6 +105,7 @@ struct ec_bio { struct bch_dev *ca; struct ec_stripe_buf *buf; size_t idx; + int rw; u64 submit_time; struct bio bio; }; @@ -462,7 +463,8 @@ int bch2_trigger_stripe(struct btree_trans *trans, return ret; if (gc) - memcpy(&gc->r.e, &acc.replicas, replicas_entry_bytes(&acc.replicas)); + unsafe_memcpy(&gc->r.e, &acc.replicas, + replicas_entry_bytes(&acc.replicas), "VLA"); } if (old_s) { @@ -703,6 +705,7 @@ static void ec_block_endio(struct bio *bio) struct bch_extent_ptr *ptr = &v->ptrs[ec_bio->idx]; struct bch_dev *ca = ec_bio->ca; struct closure *cl = bio->bi_private; + int rw = ec_bio->rw; bch2_account_io_completion(ca, bio_data_dir(bio), ec_bio->submit_time, !bio->bi_status); @@ -724,7 +727,7 @@ static void ec_block_endio(struct bio *bio) } bio_put(&ec_bio->bio); - percpu_ref_put(&ca->io_ref); + percpu_ref_put(&ca->io_ref[rw]); closure_put(cl); } @@ -775,6 +778,7 @@ static void ec_block_io(struct bch_fs *c, struct ec_stripe_buf *buf, ec_bio->ca = ca; ec_bio->buf = buf; ec_bio->idx = idx; + ec_bio->rw = rw; ec_bio->submit_time = local_clock(); ec_bio->bio.bi_iter.bi_sector = ptr->offset + buf->offset + (offset >> 9); @@ -784,14 +788,14 @@ static void ec_block_io(struct bch_fs *c, struct ec_stripe_buf *buf, bch2_bio_map(&ec_bio->bio, buf->data[idx] + offset, b); closure_get(cl); - percpu_ref_get(&ca->io_ref); + percpu_ref_get(&ca->io_ref[rw]); submit_bio(&ec_bio->bio); offset += b; } - percpu_ref_put(&ca->io_ref); + percpu_ref_put(&ca->io_ref[rw]); } static int get_stripe_key_trans(struct btree_trans *trans, u64 idx, @@ -1264,7 +1268,7 @@ static void zero_out_rest_of_ec_bucket(struct bch_fs *c, ob->sectors_free, GFP_KERNEL, 0); - percpu_ref_put(&ca->io_ref); + percpu_ref_put(&ca->io_ref[WRITE]); if (ret) s->err = ret; @@ -1836,7 +1840,7 @@ static int __get_existing_stripe(struct btree_trans *trans, ret = 1; } out: - bch2_set_btree_iter_dontneed(&iter); + bch2_set_btree_iter_dontneed(trans, &iter); err: bch2_trans_iter_exit(trans, &iter); return ret; @@ -1949,7 +1953,7 @@ static int __bch2_ec_stripe_head_reserve(struct btree_trans *trans, struct ec_st if (bkey_gt(k.k->p, POS(0, U32_MAX))) { if (start_pos.offset) { start_pos = min_pos; - bch2_btree_iter_set_pos(&iter, start_pos); + bch2_btree_iter_set_pos(trans, &iter, start_pos); continue; }
diff --git a/fs/bcachefs/error.c b/fs/bcachefs/error.c index d4dfd13..baf5dfb 100644 --- a/fs/bcachefs/error.c +++ b/fs/bcachefs/error.c
@@ -34,7 +34,7 @@ bool __bch2_inconsistent_error(struct bch_fs *c, struct printbuf *out) journal_cur_seq(&c->journal)); return true; case BCH_ON_ERROR_panic: - bch2_print_string_as_lines(KERN_ERR, out->buf); + bch2_print_string_as_lines_nonblocking(KERN_ERR, out->buf); panic(bch2_fmt(c, "panic after error")); return true; default: @@ -45,6 +45,8 @@ bool __bch2_inconsistent_error(struct bch_fs *c, struct printbuf *out) bool bch2_inconsistent_error(struct bch_fs *c) { struct printbuf buf = PRINTBUF; + buf.atomic++; + printbuf_indent_add_nextline(&buf, 2); bool ret = __bch2_inconsistent_error(c, &buf); @@ -59,6 +61,7 @@ static bool bch2_fs_trans_inconsistent(struct bch_fs *c, struct btree_trans *tra const char *fmt, va_list args) { struct printbuf buf = PRINTBUF; + buf.atomic++; bch2_log_msg_start(c, &buf); @@ -68,7 +71,7 @@ static bool bch2_fs_trans_inconsistent(struct bch_fs *c, struct btree_trans *tra if (trans) bch2_trans_updates_to_text(&buf, trans); bool ret = __bch2_inconsistent_error(c, &buf); - bch2_print_string_as_lines(KERN_ERR, buf.buf); + bch2_print_string_as_lines_nonblocking(KERN_ERR, buf.buf); printbuf_exit(&buf); return ret;
diff --git a/fs/bcachefs/extent_update.c b/fs/bcachefs/extent_update.c index 6aac579..6bb4298 100644 --- a/fs/bcachefs/extent_update.c +++ b/fs/bcachefs/extent_update.c
@@ -112,7 +112,7 @@ int bch2_extent_atomic_end(struct btree_trans *trans, unsigned nr_iters = 0; int ret; - ret = bch2_btree_iter_traverse(iter); + ret = bch2_btree_iter_traverse(trans, iter); if (ret) return ret; @@ -126,9 +126,9 @@ int bch2_extent_atomic_end(struct btree_trans *trans, if (ret < 0) return ret; - bch2_trans_copy_iter(©, iter); + bch2_trans_copy_iter(trans, ©, iter); - for_each_btree_key_max_continue_norestart(copy, insert->k.p, 0, k, ret) { + for_each_btree_key_max_continue_norestart(trans, copy, insert->k.p, 0, k, ret) { unsigned offset = 0; if (bkey_gt(bkey_start_pos(&insert->k), bkey_start_pos(k.k)))
diff --git a/fs/bcachefs/fs-io-buffered.c b/fs/bcachefs/fs-io-buffered.c index a03e2c7..19d4599 100644 --- a/fs/bcachefs/fs-io-buffered.c +++ b/fs/bcachefs/fs-io-buffered.c
@@ -183,12 +183,12 @@ static void bchfs_read(struct btree_trans *trans, if (ret) goto err; - bch2_btree_iter_set_snapshot(&iter, snapshot); + bch2_btree_iter_set_snapshot(trans, &iter, snapshot); - bch2_btree_iter_set_pos(&iter, + bch2_btree_iter_set_pos(trans, &iter, POS(inum.inum, rbio->bio.bi_iter.bi_sector)); - k = bch2_btree_iter_peek_slot(&iter); + k = bch2_btree_iter_peek_slot(trans, &iter); ret = bkey_err(k); if (ret) goto err;
diff --git a/fs/bcachefs/fs-io.c b/fs/bcachefs/fs-io.c index c80ed3a..65c2c33 100644 --- a/fs/bcachefs/fs-io.c +++ b/fs/bcachefs/fs-io.c
@@ -48,7 +48,7 @@ static void nocow_flush_endio(struct bio *_bio) struct nocow_flush *bio = container_of(_bio, struct nocow_flush, bio); closure_put(bio->cl); - percpu_ref_put(&bio->ca->io_ref); + percpu_ref_put(&bio->ca->io_ref[WRITE]); bio_put(&bio->bio); } @@ -71,7 +71,7 @@ void bch2_inode_flush_nocow_writes_async(struct bch_fs *c, for_each_set_bit(dev, devs.d, BCH_SB_MEMBERS_MAX) { rcu_read_lock(); ca = rcu_dereference(c->devs[dev]); - if (ca && !percpu_ref_tryget(&ca->io_ref)) + if (ca && !percpu_ref_tryget(&ca->io_ref[WRITE])) ca = NULL; rcu_read_unlock(); @@ -636,9 +636,9 @@ static noinline int __bchfs_fallocate(struct bch_inode_info *inode, int mode, if (ret) goto bkey_err; - bch2_btree_iter_set_snapshot(&iter, snapshot); + bch2_btree_iter_set_snapshot(trans, &iter, snapshot); - k = bch2_btree_iter_peek_slot(&iter); + k = bch2_btree_iter_peek_slot(trans, &iter); if ((ret = bkey_err(k))) goto bkey_err; @@ -649,13 +649,13 @@ static noinline int __bchfs_fallocate(struct bch_inode_info *inode, int mode, /* already reserved */ if (bkey_extent_is_reservation(k) && bch2_bkey_nr_ptrs_fully_allocated(k) >= opts.data_replicas) { - bch2_btree_iter_advance(&iter); + bch2_btree_iter_advance(trans, &iter); continue; } if (bkey_extent_is_data(k.k) && !(mode & FALLOC_FL_ZERO_RANGE)) { - bch2_btree_iter_advance(&iter); + bch2_btree_iter_advance(trans, &iter); continue; } @@ -676,7 +676,7 @@ static noinline int __bchfs_fallocate(struct bch_inode_info *inode, int mode, if (ret) goto bkey_err; } - bch2_btree_iter_set_pos(&iter, POS(iter.pos.inode, hole_start)); + bch2_btree_iter_set_pos(trans, &iter, POS(iter.pos.inode, hole_start)); if (ret) goto bkey_err;
diff --git a/fs/bcachefs/fs.c b/fs/bcachefs/fs.c index fc834bd..5a41b1a 100644 --- a/fs/bcachefs/fs.c +++ b/fs/bcachefs/fs.c
@@ -88,7 +88,7 @@ int __must_check bch2_write_inode(struct bch_fs *c, void *p, unsigned fields) { struct btree_trans *trans = bch2_trans_get(c); - struct btree_iter iter = { NULL }; + struct btree_iter iter = {}; struct bch_inode_unpacked inode_u; int ret; retry: @@ -1075,7 +1075,7 @@ int bch2_setattr_nonsize(struct mnt_idmap *idmap, struct bch_fs *c = inode->v.i_sb->s_fs_info; struct bch_qid qid; struct btree_trans *trans; - struct btree_iter inode_iter = { NULL }; + struct btree_iter inode_iter = {}; struct bch_inode_unpacked inode_u; struct posix_acl *acl = NULL; kuid_t kuid; @@ -1330,9 +1330,9 @@ static int bch2_fiemap(struct inode *vinode, struct fiemap_extent_info *info, if (ret) continue; - bch2_btree_iter_set_snapshot(&iter, snapshot); + bch2_btree_iter_set_snapshot(trans, &iter, snapshot); - k = bch2_btree_iter_peek_max(&iter, end); + k = bch2_btree_iter_peek_max(trans, &iter, end); ret = bkey_err(k); if (ret) continue; @@ -1342,7 +1342,7 @@ static int bch2_fiemap(struct inode *vinode, struct fiemap_extent_info *info, if (!bkey_extent_is_data(k.k) && k.k->type != KEY_TYPE_reservation) { - bch2_btree_iter_advance(&iter); + bch2_btree_iter_advance(trans, &iter); continue; } @@ -1380,7 +1380,7 @@ static int bch2_fiemap(struct inode *vinode, struct fiemap_extent_info *info, bkey_copy(prev.k, cur.k); have_extent = true; - bch2_btree_iter_set_pos(&iter, + bch2_btree_iter_set_pos(trans, &iter, POS(iter.pos.inode, iter.pos.offset + sectors)); } bch2_trans_iter_exit(trans, &iter); @@ -1697,17 +1697,17 @@ static int bch2_get_name(struct dentry *parent, char *name, struct dentry *child if (ret) goto err; - bch2_btree_iter_set_snapshot(&iter1, snapshot); - bch2_btree_iter_set_snapshot(&iter2, snapshot); + bch2_btree_iter_set_snapshot(trans, &iter1, snapshot); + bch2_btree_iter_set_snapshot(trans, &iter2, snapshot); ret = bch2_inode_find_by_inum_trans(trans, inode_inum(inode), &inode_u); if (ret) goto err; if (inode_u.bi_dir == dir->ei_inode.bi_inum) { - bch2_btree_iter_set_pos(&iter1, POS(inode_u.bi_dir, inode_u.bi_dir_offset)); + bch2_btree_iter_set_pos(trans, &iter1, POS(inode_u.bi_dir, inode_u.bi_dir_offset)); - k = bch2_btree_iter_peek_slot(&iter1); + k = bch2_btree_iter_peek_slot(trans, &iter1); ret = bkey_err(k); if (ret) goto err; @@ -1731,7 +1731,7 @@ static int bch2_get_name(struct dentry *parent, char *name, struct dentry *child * File with multiple hardlinks and our backref is to the wrong * directory - linear search: */ - for_each_btree_key_continue_norestart(iter2, 0, k, ret) { + for_each_btree_key_continue_norestart(trans, iter2, 0, k, ret) { if (k.k->p.inode > dir->ei_inode.bi_inum) break; @@ -2237,7 +2237,7 @@ static int bch2_fs_get_tree(struct fs_context *fc) /* XXX: create an anonymous device for multi device filesystems */ sb->s_bdev = bdev; sb->s_dev = bdev->bd_dev; - percpu_ref_put(&ca->io_ref); + percpu_ref_put(&ca->io_ref[READ]); break; }
diff --git a/fs/bcachefs/fsck.c b/fs/bcachefs/fsck.c index 5232029..18308f3 100644 --- a/fs/bcachefs/fsck.c +++ b/fs/bcachefs/fsck.c
@@ -186,7 +186,7 @@ static int lookup_lostfound(struct btree_trans *trans, u32 snapshot, { struct bch_fs *c = trans->c; struct qstr lostfound_str = QSTR("lost+found"); - struct btree_iter lostfound_iter = { NULL }; + struct btree_iter lostfound_iter = {}; u64 inum = 0; unsigned d_type = 0; int ret; @@ -295,8 +295,8 @@ static int lookup_lostfound(struct btree_trans *trans, u32 snapshot, if (ret) goto err; - bch2_btree_iter_set_snapshot(&lostfound_iter, snapshot); - ret = bch2_btree_iter_traverse(&lostfound_iter); + bch2_btree_iter_set_snapshot(trans, &lostfound_iter, snapshot); + ret = bch2_btree_iter_traverse(trans, &lostfound_iter); if (ret) goto err; @@ -544,7 +544,7 @@ static int reconstruct_subvol(struct btree_trans *trans, u32 snapshotid, u32 sub new_inode.bi_subvol = subvolid; int ret = bch2_inode_create(trans, &inode_iter, &new_inode, snapshotid, cpu) ?: - bch2_btree_iter_traverse(&inode_iter) ?: + bch2_btree_iter_traverse(trans, &inode_iter) ?: bch2_inode_write(trans, &inode_iter, &new_inode); bch2_trans_iter_exit(trans, &inode_iter); if (ret) @@ -609,7 +609,7 @@ static int reconstruct_inode(struct btree_trans *trans, enum btree_id btree, u32 struct btree_iter iter = {}; bch2_trans_iter_init(trans, &iter, BTREE_ID_extents, SPOS(inum, U64_MAX, snapshot), 0); - struct bkey_s_c k = bch2_btree_iter_peek_prev_min(&iter, POS(inum, 0)); + struct bkey_s_c k = bch2_btree_iter_peek_prev_min(trans, &iter, POS(inum, 0)); bch2_trans_iter_exit(trans, &iter); int ret = bkey_err(k); if (ret) @@ -1557,7 +1557,7 @@ static int overlapping_extents_found(struct btree_trans *trans, { struct bch_fs *c = trans->c; struct printbuf buf = PRINTBUF; - struct btree_iter iter1, iter2 = { NULL }; + struct btree_iter iter1, iter2 = {}; struct bkey_s_c k1, k2; int ret; @@ -1566,7 +1566,7 @@ static int overlapping_extents_found(struct btree_trans *trans, bch2_trans_iter_init(trans, &iter1, btree, pos1, BTREE_ITER_all_snapshots| BTREE_ITER_not_extents); - k1 = bch2_btree_iter_peek_max(&iter1, POS(pos1.inode, U64_MAX)); + k1 = bch2_btree_iter_peek_max(trans, &iter1, POS(pos1.inode, U64_MAX)); ret = bkey_err(k1); if (ret) goto err; @@ -1586,12 +1586,12 @@ static int overlapping_extents_found(struct btree_trans *trans, goto err; } - bch2_trans_copy_iter(&iter2, &iter1); + bch2_trans_copy_iter(trans, &iter2, &iter1); while (1) { - bch2_btree_iter_advance(&iter2); + bch2_btree_iter_advance(trans, &iter2); - k2 = bch2_btree_iter_peek_max(&iter2, POS(pos1.inode, U64_MAX)); + k2 = bch2_btree_iter_peek_max(trans, &iter2, POS(pos1.inode, U64_MAX)); ret = bkey_err(k2); if (ret) goto err; @@ -1791,9 +1791,9 @@ static int check_extent(struct btree_trans *trans, struct btree_iter *iter, (bch2_bkey_val_to_text(&buf, c, k), buf.buf))) { struct btree_iter iter2; - bch2_trans_copy_iter(&iter2, iter); - bch2_btree_iter_set_snapshot(&iter2, i->snapshot); - ret = bch2_btree_iter_traverse(&iter2) ?: + bch2_trans_copy_iter(trans, &iter2, iter); + bch2_btree_iter_set_snapshot(trans, &iter2, i->snapshot); + ret = bch2_btree_iter_traverse(trans, &iter2) ?: bch2_btree_delete_at(trans, &iter2, BTREE_UPDATE_internal_snapshot_node); bch2_trans_iter_exit(trans, &iter2); @@ -2185,7 +2185,7 @@ static int check_dirent(struct btree_trans *trans, struct btree_iter *iter, BTREE_ID_dirents, SPOS(k.k->p.inode, k.k->p.offset, *i), BTREE_ITER_intent); - ret = bch2_btree_iter_traverse(&delete_iter) ?: + ret = bch2_btree_iter_traverse(trans, &delete_iter) ?: bch2_hash_delete_at(trans, bch2_dirent_hash_desc, hash_info, &delete_iter, @@ -2412,7 +2412,7 @@ static int check_subvol_path(struct btree_trans *trans, struct btree_iter *iter, bch2_trans_iter_exit(trans, &parent_iter); bch2_trans_iter_init(trans, &parent_iter, BTREE_ID_subvolumes, POS(0, parent), 0); - k = bch2_btree_iter_peek_slot(&parent_iter); + k = bch2_btree_iter_peek_slot(trans, &parent_iter); ret = bkey_err(k); if (ret) goto err;
diff --git a/fs/bcachefs/inode.c b/fs/bcachefs/inode.c index 8005107..b51d98c 100644 --- a/fs/bcachefs/inode.c +++ b/fs/bcachefs/inode.c
@@ -940,7 +940,7 @@ int bch2_inode_create(struct btree_trans *trans, BTREE_ITER_intent); struct bkey_s_c k; again: - while ((k = bch2_btree_iter_peek(iter)).k && + while ((k = bch2_btree_iter_peek(trans, iter)).k && !(ret = bkey_err(k)) && bkey_lt(k.k->p, POS(0, max))) { if (pos < iter->pos.offset) @@ -951,7 +951,7 @@ int bch2_inode_create(struct btree_trans *trans, * we've found just one: */ pos = iter->pos.offset + 1; - bch2_btree_iter_set_pos(iter, POS(0, pos)); + bch2_btree_iter_set_pos(trans, iter, POS(0, pos)); } if (!ret && pos < max) @@ -967,12 +967,12 @@ int bch2_inode_create(struct btree_trans *trans, /* Retry from start */ pos = start = min; - bch2_btree_iter_set_pos(iter, POS(0, pos)); + bch2_btree_iter_set_pos(trans, iter, POS(0, pos)); le32_add_cpu(&cursor->v.gen, 1); goto again; found_slot: - bch2_btree_iter_set_pos(iter, SPOS(0, pos, snapshot)); - k = bch2_btree_iter_peek_slot(iter); + bch2_btree_iter_set_pos(trans, iter, SPOS(0, pos, snapshot)); + k = bch2_btree_iter_peek_slot(trans, iter); ret = bkey_err(k); if (ret) { bch2_trans_iter_exit(trans, iter); @@ -1009,9 +1009,9 @@ static int bch2_inode_delete_keys(struct btree_trans *trans, if (ret) goto err; - bch2_btree_iter_set_snapshot(&iter, snapshot); + bch2_btree_iter_set_snapshot(trans, &iter, snapshot); - k = bch2_btree_iter_peek_max(&iter, end); + k = bch2_btree_iter_peek_max(trans, &iter, end); ret = bkey_err(k); if (ret) goto err; @@ -1042,7 +1042,7 @@ static int bch2_inode_delete_keys(struct btree_trans *trans, int bch2_inode_rm(struct bch_fs *c, subvol_inum inum) { struct btree_trans *trans = bch2_trans_get(c); - struct btree_iter iter = { NULL }; + struct btree_iter iter = {}; struct bkey_s_c k; u32 snapshot; int ret; @@ -1207,7 +1207,7 @@ int bch2_inum_opts_get(struct btree_trans *trans, subvol_inum inum, struct bch_i static noinline int __bch2_inode_rm_snapshot(struct btree_trans *trans, u64 inum, u32 snapshot) { struct bch_fs *c = trans->c; - struct btree_iter iter = { NULL }; + struct btree_iter iter = {}; struct bkey_i_inode_generation delete; struct bch_inode_unpacked inode_u; struct bkey_s_c k;
diff --git a/fs/bcachefs/io_misc.c b/fs/bcachefs/io_misc.c index 6b842c8..cc07729 100644 --- a/fs/bcachefs/io_misc.c +++ b/fs/bcachefs/io_misc.c
@@ -43,7 +43,7 @@ int bch2_extent_fallocate(struct btree_trans *trans, bch2_bkey_buf_init(&new); closure_init_stack(&cl); - k = bch2_btree_iter_peek_slot(iter); + k = bch2_btree_iter_peek_slot(trans, iter); ret = bkey_err(k); if (ret) return ret; @@ -164,12 +164,12 @@ int bch2_fpunch_at(struct btree_trans *trans, struct btree_iter *iter, if (ret) continue; - bch2_btree_iter_set_snapshot(iter, snapshot); + bch2_btree_iter_set_snapshot(trans, iter, snapshot); /* * peek_max() doesn't have ideal semantics for extents: */ - k = bch2_btree_iter_peek_max(iter, end_pos); + k = bch2_btree_iter_peek_max(trans, iter, end_pos); if (!k.k) break; @@ -230,7 +230,7 @@ static int truncate_set_isize(struct btree_trans *trans, u64 new_i_size, bool warn) { - struct btree_iter iter = { NULL }; + struct btree_iter iter = {}; struct bch_inode_unpacked inode_u; int ret; @@ -399,7 +399,7 @@ case LOGGED_OP_FINSERT_start: if (ret) goto err; } else { - bch2_btree_iter_set_pos(&iter, POS(inum.inum, src_offset)); + bch2_btree_iter_set_pos(trans, &iter, POS(inum.inum, src_offset)); ret = bch2_fpunch_at(trans, &iter, inum, src_offset + len, i_sectors_delta); if (ret && !bch2_err_matches(ret, BCH_ERR_transaction_restart)) @@ -425,12 +425,12 @@ case LOGGED_OP_FINSERT_shift_extents: if (ret) goto btree_err; - bch2_btree_iter_set_snapshot(&iter, snapshot); - bch2_btree_iter_set_pos(&iter, SPOS(inum.inum, pos, snapshot)); + bch2_btree_iter_set_snapshot(trans, &iter, snapshot); + bch2_btree_iter_set_pos(trans, &iter, SPOS(inum.inum, pos, snapshot)); k = insert - ? bch2_btree_iter_peek_prev_min(&iter, POS(inum.inum, 0)) - : bch2_btree_iter_peek_max(&iter, POS(inum.inum, U64_MAX)); + ? bch2_btree_iter_peek_prev_min(trans, &iter, POS(inum.inum, 0)) + : bch2_btree_iter_peek_max(trans, &iter, POS(inum.inum, U64_MAX)); if ((ret = bkey_err(k))) goto btree_err;
diff --git a/fs/bcachefs/io_read.c b/fs/bcachefs/io_read.c index fd01e67..417bb0c 100644 --- a/fs/bcachefs/io_read.c +++ b/fs/bcachefs/io_read.c
@@ -394,7 +394,7 @@ static inline struct bch_read_bio *bch2_rbio_free(struct bch_read_bio *rbio) if (rbio->have_ioref) { struct bch_dev *ca = bch2_dev_have_ref(rbio->c, rbio->pick.ptr.dev); - percpu_ref_put(&ca->io_ref); + percpu_ref_put(&ca->io_ref[READ]); } if (rbio->split) { @@ -909,7 +909,7 @@ static noinline void read_from_stale_dirty_pointer(struct btree_trans *trans, prt_printf(&buf, "memory gen: %u", gen); - ret = lockrestart_do(trans, bkey_err(k = bch2_btree_iter_peek_slot(&iter))); + ret = lockrestart_do(trans, bkey_err(k = bch2_btree_iter_peek_slot(trans, &iter))); if (!ret) { prt_newline(&buf); bch2_bkey_val_to_text(&buf, c, k); @@ -1003,7 +1003,7 @@ int __bch2_read_extent(struct btree_trans *trans, struct bch_read_bio *orig, unlikely(dev_ptr_stale(ca, &pick.ptr))) { read_from_stale_dirty_pointer(trans, ca, k, pick.ptr); bch2_mark_io_failure(failed, &pick, false); - percpu_ref_put(&ca->io_ref); + percpu_ref_put(&ca->io_ref[READ]); goto retry_pick; } @@ -1036,7 +1036,7 @@ int __bch2_read_extent(struct btree_trans *trans, struct bch_read_bio *orig, */ if (pick.crc.compressed_size > u->op.wbio.bio.bi_iter.bi_size) { if (ca) - percpu_ref_put(&ca->io_ref); + percpu_ref_put(&ca->io_ref[READ]); rbio->ret = -BCH_ERR_data_read_buffer_too_small; goto out_read_done; } @@ -1285,12 +1285,12 @@ int __bch2_read(struct btree_trans *trans, struct bch_read_bio *rbio, if (ret) goto err; - bch2_btree_iter_set_snapshot(&iter, snapshot); + bch2_btree_iter_set_snapshot(trans, &iter, snapshot); - bch2_btree_iter_set_pos(&iter, + bch2_btree_iter_set_pos(trans, &iter, POS(inum.inum, bvec_iter.bi_sector)); - k = bch2_btree_iter_peek_slot(&iter); + k = bch2_btree_iter_peek_slot(trans, &iter); ret = bkey_err(k); if (ret) goto err;
diff --git a/fs/bcachefs/io_write.c b/fs/bcachefs/io_write.c index 07b5583..a418fa62 100644 --- a/fs/bcachefs/io_write.c +++ b/fs/bcachefs/io_write.c
@@ -168,9 +168,9 @@ int bch2_sum_sector_overwrites(struct btree_trans *trans, *i_sectors_delta = 0; *disk_sectors_delta = 0; - bch2_trans_copy_iter(&iter, extent_iter); + bch2_trans_copy_iter(trans, &iter, extent_iter); - for_each_btree_key_max_continue_norestart(iter, + for_each_btree_key_max_continue_norestart(trans, iter, new->k.p, BTREE_ITER_slots, old, ret) { s64 sectors = min(new->k.p.offset, old.k->p.offset) - max(bkey_start_offset(&new->k), @@ -292,7 +292,7 @@ int bch2_extent_update(struct btree_trans *trans, * path already traversed at iter->pos because * bch2_trans_extent_update() will use it to attempt extent merging */ - ret = __bch2_btree_iter_traverse(iter); + ret = __bch2_btree_iter_traverse(trans, iter); if (ret) return ret; @@ -337,7 +337,7 @@ int bch2_extent_update(struct btree_trans *trans, if (i_sectors_delta_total) *i_sectors_delta_total += i_sectors_delta; - bch2_btree_iter_set_pos(iter, next_pos); + bch2_btree_iter_set_pos(trans, iter, next_pos); return 0; } @@ -445,6 +445,11 @@ void bch2_submit_wbio_replicas(struct bch_write_bio *wbio, struct bch_fs *c, BUG_ON(c->opts.nochanges); bkey_for_each_ptr(ptrs, ptr) { + /* + * XXX: btree writes should be using io_ref[WRITE], but we + * aren't retrying failed btree writes yet (due to device + * removal/ro): + */ struct bch_dev *ca = nocow ? bch2_dev_have_ref(c, ptr->dev) : bch2_dev_get_ioref(c, ptr->dev, type == BCH_DATA_btree ? READ : WRITE); @@ -697,12 +702,19 @@ static void bch2_write_endio(struct bio *bio) bch2_account_io_completion(ca, BCH_MEMBER_ERROR_write, wbio->submit_time, !bio->bi_status); - if (bio->bi_status) { - bch_err_inum_offset_ratelimited(ca, - op->pos.inode, - wbio->inode_offset << 9, - "data write error: %s", - bch2_blk_status_to_str(bio->bi_status)); + if (unlikely(bio->bi_status)) { + if (ca) + bch_err_inum_offset_ratelimited(ca, + op->pos.inode, + wbio->inode_offset << 9, + "data write error: %s", + bch2_blk_status_to_str(bio->bi_status)); + else + bch_err_inum_offset_ratelimited(c, + op->pos.inode, + wbio->inode_offset << 9, + "data write error: %s", + bch2_blk_status_to_str(bio->bi_status)); set_bit(wbio->dev, op->failed.d); op->flags |= BCH_WRITE_io_error; } @@ -715,7 +727,7 @@ static void bch2_write_endio(struct bio *bio) } if (wbio->have_ioref) - percpu_ref_put(&ca->io_ref); + percpu_ref_put(&ca->io_ref[WRITE]); if (wbio->bounce) bch2_bio_free_pages_pool(c, bio); @@ -1293,7 +1305,7 @@ static void bch2_nocow_write(struct bch_write_op *op) if (ret) break; - k = bch2_btree_iter_peek_slot(&iter); + k = bch2_btree_iter_peek_slot(trans, &iter); ret = bkey_err(k); if (ret) break; @@ -1377,7 +1389,7 @@ static void bch2_nocow_write(struct bch_write_op *op) bch2_keylist_push(&op->insert_keys); if (op->flags & BCH_WRITE_submitted) break; - bch2_btree_iter_advance(&iter); + bch2_btree_iter_advance(trans, &iter); } out: bch2_trans_iter_exit(trans, &iter); @@ -1414,7 +1426,7 @@ static void bch2_nocow_write(struct bch_write_op *op) return; err_get_ioref: darray_for_each(buckets, i) - percpu_ref_put(&bch2_dev_have_ref(c, i->b.inode)->io_ref); + percpu_ref_put(&bch2_dev_have_ref(c, i->b.inode)->io_ref[WRITE]); /* Fall back to COW path: */ goto out;
diff --git a/fs/bcachefs/journal.c b/fs/bcachefs/journal.c index 8a36d55..d8f74b6 100644 --- a/fs/bcachefs/journal.c +++ b/fs/bcachefs/journal.c
@@ -1315,7 +1315,7 @@ int bch2_fs_journal_alloc(struct bch_fs *c) int ret = bch2_dev_journal_alloc(ca, true); if (ret) { - percpu_ref_put(&ca->io_ref); + percpu_ref_put(&ca->io_ref[READ]); return ret; } } @@ -1404,6 +1404,14 @@ int bch2_fs_journal_start(struct journal *j, u64 cur_seq) nr = cur_seq - last_seq; + /* + * Extra fudge factor, in case we crashed when the journal pin fifo was + * nearly or completely full. We'll need to be able to open additional + * journal entries (at least a few) in order for journal replay to get + * going: + */ + nr += nr / 4; + if (nr + 1 > j->pin.size) { free_fifo(&j->pin); init_fifo(&j->pin, roundup_pow_of_two(nr + 1), GFP_KERNEL); @@ -1461,11 +1469,9 @@ int bch2_fs_journal_start(struct journal *j, u64 cur_seq) j->reservations.idx = journal_cur_seq(j); c->last_bucket_seq_cleanup = journal_cur_seq(j); - - bch2_journal_space_available(j); spin_unlock(&j->lock); - return bch2_journal_reclaim_start(j); + return 0; } /* init/exit: */
diff --git a/fs/bcachefs/journal_io.c b/fs/bcachefs/journal_io.c index 2debc21..1b7961f 100644 --- a/fs/bcachefs/journal_io.c +++ b/fs/bcachefs/journal_io.c
@@ -1218,7 +1218,7 @@ static CLOSURE_CALLBACK(bch2_journal_read_device) out: bch_verbose(c, "journal read done on device %s, ret %i", ca->name, ret); kvfree(buf.data); - percpu_ref_put(&ca->io_ref); + percpu_ref_put(&ca->io_ref[READ]); closure_return(cl); return; err: @@ -1253,7 +1253,7 @@ int bch2_journal_read(struct bch_fs *c, if ((ca->mi.state == BCH_MEMBER_STATE_rw || ca->mi.state == BCH_MEMBER_STATE_ro) && - percpu_ref_tryget(&ca->io_ref)) + percpu_ref_tryget(&ca->io_ref[READ])) closure_call(&ca->journal.read, bch2_journal_read_device, system_unbound_wq, @@ -1768,7 +1768,7 @@ static void journal_write_endio(struct bio *bio) } closure_put(&w->io); - percpu_ref_put(&ca->io_ref); + percpu_ref_put(&ca->io_ref[WRITE]); } static CLOSURE_CALLBACK(journal_write_submit) @@ -1843,7 +1843,7 @@ static CLOSURE_CALLBACK(journal_write_preflush) if (w->separate_flush) { for_each_rw_member(c, ca) { - percpu_ref_get(&ca->io_ref); + percpu_ref_get(&ca->io_ref[WRITE]); struct journal_device *ja = &ca->journal; struct bio *bio = &ja->bio[w->idx]->bio;
diff --git a/fs/bcachefs/migrate.c b/fs/bcachefs/migrate.c index 57ad662..90dcf80 100644 --- a/fs/bcachefs/migrate.c +++ b/fs/bcachefs/migrate.c
@@ -130,7 +130,7 @@ static int bch2_dev_metadata_drop(struct bch_fs *c, retry: ret = 0; while (bch2_trans_begin(trans), - (b = bch2_btree_iter_peek_node(&iter)) && + (b = bch2_btree_iter_peek_node(trans, &iter)) && !(ret = PTR_ERR_OR_ZERO(b))) { bch2_progress_update_iter(trans, progress, &iter, "dropping metadata"); @@ -154,7 +154,7 @@ static int bch2_dev_metadata_drop(struct bch_fs *c, if (ret) break; next: - bch2_btree_iter_next_node(&iter); + bch2_btree_iter_next_node(trans, &iter); } if (bch2_err_matches(ret, BCH_ERR_transaction_restart)) goto retry;
diff --git a/fs/bcachefs/move.c b/fs/bcachefs/move.c index 5d41260..fc396b9 100644 --- a/fs/bcachefs/move.c +++ b/fs/bcachefs/move.c
@@ -545,7 +545,7 @@ static struct bkey_s_c bch2_lookup_indirect_extent_for_move(struct btree_trans * BTREE_ID_reflink, reflink_pos, BTREE_ITER_not_extents); - struct bkey_s_c k = bch2_btree_iter_peek(iter); + struct bkey_s_c k = bch2_btree_iter_peek(trans, iter); if (!k.k || bkey_err(k)) { bch2_trans_iter_exit(trans, iter); return k; @@ -603,7 +603,7 @@ static int bch2_move_data_btree(struct moving_context *ctxt, bch2_trans_begin(trans); - k = bch2_btree_iter_peek(&iter); + k = bch2_btree_iter_peek(trans, &iter); if (!k.k) break; @@ -681,7 +681,7 @@ static int bch2_move_data_btree(struct moving_context *ctxt, if (ctxt->stats) atomic64_add(k.k->size, &ctxt->stats->sectors_seen); next_nondata: - bch2_btree_iter_advance(&iter); + bch2_btree_iter_advance(trans, &iter); } bch2_trans_iter_exit(trans, &reflink_iter); @@ -794,7 +794,7 @@ static int __bch2_move_data_phys(struct moving_context *ctxt, bch2_trans_begin(trans); - k = bch2_btree_iter_peek(&bp_iter); + k = bch2_btree_iter_peek(trans, &bp_iter); ret = bkey_err(k); if (bch2_err_matches(ret, BCH_ERR_transaction_restart)) continue; @@ -876,7 +876,7 @@ static int __bch2_move_data_phys(struct moving_context *ctxt, if (ctxt->stats) atomic64_add(sectors, &ctxt->stats->sectors_seen); next: - bch2_btree_iter_advance(&bp_iter); + bch2_btree_iter_advance(trans, &bp_iter); } err: bch2_trans_iter_exit(trans, &bp_iter); @@ -991,7 +991,7 @@ static int bch2_move_btree(struct bch_fs *c, retry: ret = 0; while (bch2_trans_begin(trans), - (b = bch2_btree_iter_peek_node(&iter)) && + (b = bch2_btree_iter_peek_node(trans, &iter)) && !(ret = PTR_ERR_OR_ZERO(b))) { if (kthread && kthread_should_stop()) break; @@ -1011,7 +1011,7 @@ static int bch2_move_btree(struct bch_fs *c, if (ret) break; next: - bch2_btree_iter_next_node(&iter); + bch2_btree_iter_next_node(trans, &iter); } if (bch2_err_matches(ret, BCH_ERR_transaction_restart)) goto retry;
diff --git a/fs/bcachefs/movinggc.c b/fs/bcachefs/movinggc.c index 5126c87..159410c 100644 --- a/fs/bcachefs/movinggc.c +++ b/fs/bcachefs/movinggc.c
@@ -280,7 +280,11 @@ unsigned long bch2_copygc_wait_amount(struct bch_fs *c) s64 wait = S64_MAX, fragmented_allowed, fragmented; for_each_rw_member(c, ca) { - struct bch_dev_usage usage = bch2_dev_usage_read(ca); + struct bch_dev_usage_full usage_full = bch2_dev_usage_full_read(ca); + struct bch_dev_usage usage; + + for (unsigned i = 0; i < BCH_DATA_NR; i++) + usage.buckets[i] = usage_full.d[i].buckets; fragmented_allowed = ((__dev_buckets_available(ca, usage, BCH_WATERMARK_stripe) * ca->mi.bucket_size) >> 1); @@ -288,7 +292,7 @@ unsigned long bch2_copygc_wait_amount(struct bch_fs *c) for (unsigned i = 0; i < BCH_DATA_NR; i++) if (data_type_movable(i)) - fragmented += usage.d[i].fragmented; + fragmented += usage_full.d[i].fragmented; wait = min(wait, max(0LL, fragmented_allowed - fragmented)); }
diff --git a/fs/bcachefs/namei.c b/fs/bcachefs/namei.c index ee72517..0d65ea9 100644 --- a/fs/bcachefs/namei.c +++ b/fs/bcachefs/namei.c
@@ -28,8 +28,8 @@ int bch2_create_trans(struct btree_trans *trans, unsigned flags) { struct bch_fs *c = trans->c; - struct btree_iter dir_iter = { NULL }; - struct btree_iter inode_iter = { NULL }; + struct btree_iter dir_iter = {}; + struct btree_iter inode_iter = {}; subvol_inum new_inum = dir; u64 now = bch2_current_time(c); u64 cpu = raw_smp_processor_id(); @@ -127,8 +127,8 @@ int bch2_create_trans(struct btree_trans *trans, if (ret) goto err; - bch2_btree_iter_set_snapshot(&dir_iter, dir_snapshot); - ret = bch2_btree_iter_traverse(&dir_iter); + bch2_btree_iter_set_snapshot(trans, &dir_iter, dir_snapshot); + ret = bch2_btree_iter_traverse(trans, &dir_iter); if (ret) goto err; } @@ -177,9 +177,9 @@ int bch2_create_trans(struct btree_trans *trans, new_inode->bi_depth = dir_u->bi_depth + 1; inode_iter.flags &= ~BTREE_ITER_all_snapshots; - bch2_btree_iter_set_snapshot(&inode_iter, snapshot); + bch2_btree_iter_set_snapshot(trans, &inode_iter, snapshot); - ret = bch2_btree_iter_traverse(&inode_iter) ?: + ret = bch2_btree_iter_traverse(trans, &inode_iter) ?: bch2_inode_write(trans, &inode_iter, new_inode); err: bch2_trans_iter_exit(trans, &inode_iter); @@ -193,8 +193,8 @@ int bch2_link_trans(struct btree_trans *trans, const struct qstr *name) { struct bch_fs *c = trans->c; - struct btree_iter dir_iter = { NULL }; - struct btree_iter inode_iter = { NULL }; + struct btree_iter dir_iter = {}; + struct btree_iter inode_iter = {}; struct bch_hash_info dir_hash; u64 now = bch2_current_time(c); u64 dir_offset = 0; @@ -253,9 +253,9 @@ int bch2_unlink_trans(struct btree_trans *trans, bool deleting_subvol) { struct bch_fs *c = trans->c; - struct btree_iter dir_iter = { NULL }; - struct btree_iter dirent_iter = { NULL }; - struct btree_iter inode_iter = { NULL }; + struct btree_iter dir_iter = {}; + struct btree_iter dirent_iter = {}; + struct btree_iter inode_iter = {}; struct bch_hash_info dir_hash; subvol_inum inum; u64 now = bch2_current_time(c); @@ -301,7 +301,7 @@ int bch2_unlink_trans(struct btree_trans *trans, if (ret) goto err; - k = bch2_btree_iter_peek_slot(&dirent_iter); + k = bch2_btree_iter_peek_slot(trans, &dirent_iter); ret = bkey_err(k); if (ret) goto err; @@ -310,8 +310,8 @@ int bch2_unlink_trans(struct btree_trans *trans, * If we're deleting a subvolume, we need to really delete the * dirent, not just emit a whiteout in the current snapshot: */ - bch2_btree_iter_set_snapshot(&dirent_iter, k.k->p.snapshot); - ret = bch2_btree_iter_traverse(&dirent_iter); + bch2_btree_iter_set_snapshot(trans, &dirent_iter, k.k->p.snapshot); + ret = bch2_btree_iter_traverse(trans, &dirent_iter); if (ret) goto err; } else { @@ -390,10 +390,10 @@ int bch2_rename_trans(struct btree_trans *trans, enum bch_rename_mode mode) { struct bch_fs *c = trans->c; - struct btree_iter src_dir_iter = { NULL }; - struct btree_iter dst_dir_iter = { NULL }; - struct btree_iter src_inode_iter = { NULL }; - struct btree_iter dst_inode_iter = { NULL }; + struct btree_iter src_dir_iter = {}; + struct btree_iter dst_dir_iter = {}; + struct btree_iter src_inode_iter = {}; + struct btree_iter dst_inode_iter = {}; struct bch_hash_info src_hash, dst_hash; subvol_inum src_inum, dst_inum; u64 src_offset, dst_offset; @@ -666,7 +666,7 @@ static int bch2_check_dirent_inode_dirent(struct btree_trans *trans, { struct bch_fs *c = trans->c; struct printbuf buf = PRINTBUF; - struct btree_iter bp_iter = { NULL }; + struct btree_iter bp_iter = {}; int ret = 0; if (inode_points_to_dirent(target, d))
diff --git a/fs/bcachefs/quota.c b/fs/bcachefs/quota.c index 8b857fc..3d4755d 100644 --- a/fs/bcachefs/quota.c +++ b/fs/bcachefs/quota.c
@@ -516,7 +516,7 @@ static int bch2_fs_quota_read_inode(struct btree_trans *trans, bch2_quota_acct(c, bch_qid(&u), Q_INO, 1, KEY_TYPE_QUOTA_NOCHECK); advance: - bch2_btree_iter_set_pos(iter, bpos_nosnap_successor(iter->pos)); + bch2_btree_iter_set_pos(trans, iter, bpos_nosnap_successor(iter->pos)); return 0; }
diff --git a/fs/bcachefs/rebalance.c b/fs/bcachefs/rebalance.c index b9bde04..c63fa53 100644 --- a/fs/bcachefs/rebalance.c +++ b/fs/bcachefs/rebalance.c
@@ -233,7 +233,7 @@ int bch2_set_rebalance_needs_scan_trans(struct btree_trans *trans, u64 inum) bch2_trans_iter_init(trans, &iter, BTREE_ID_rebalance_work, SPOS(inum, REBALANCE_WORK_SCAN_OFFSET, U32_MAX), BTREE_ITER_intent); - k = bch2_btree_iter_peek_slot(&iter); + k = bch2_btree_iter_peek_slot(trans, &iter); ret = bkey_err(k); if (ret) goto err; @@ -281,7 +281,7 @@ static int bch2_clear_rebalance_needs_scan(struct btree_trans *trans, u64 inum, bch2_trans_iter_init(trans, &iter, BTREE_ID_rebalance_work, SPOS(inum, REBALANCE_WORK_SCAN_OFFSET, U32_MAX), BTREE_ITER_intent); - k = bch2_btree_iter_peek_slot(&iter); + k = bch2_btree_iter_peek_slot(trans, &iter); ret = bkey_err(k); if (ret) goto err; @@ -301,7 +301,7 @@ static struct bkey_s_c next_rebalance_entry(struct btree_trans *trans, struct btree_iter *work_iter) { return !kthread_should_stop() - ? bch2_btree_iter_peek(work_iter) + ? bch2_btree_iter_peek(trans, work_iter) : bkey_s_c_null; } @@ -335,7 +335,7 @@ static struct bkey_s_c next_rebalance_extent(struct btree_trans *trans, work_pos.inode ? BTREE_ID_extents : BTREE_ID_reflink, work_pos, BTREE_ITER_all_snapshots); - struct bkey_s_c k = bch2_btree_iter_peek_slot(extent_iter); + struct bkey_s_c k = bch2_btree_iter_peek_slot(trans, extent_iter); if (bkey_err(k)) return k; @@ -511,7 +511,7 @@ static int do_rebalance(struct moving_context *ctxt) struct btree_trans *trans = ctxt->trans; struct bch_fs *c = trans->c; struct bch_fs_rebalance *r = &c->rebalance; - struct btree_iter rebalance_work_iter, extent_iter = { NULL }; + struct btree_iter rebalance_work_iter, extent_iter = {}; struct bkey_s_c k; int ret = 0; @@ -552,7 +552,7 @@ static int do_rebalance(struct moving_context *ctxt) if (ret) break; - bch2_btree_iter_advance(&rebalance_work_iter); + bch2_btree_iter_advance(trans, &rebalance_work_iter); } bch2_trans_iter_exit(trans, &extent_iter);
diff --git a/fs/bcachefs/recovery.c b/fs/bcachefs/recovery.c index 266c577..79fd18a 100644 --- a/fs/bcachefs/recovery.c +++ b/fs/bcachefs/recovery.c
@@ -198,7 +198,7 @@ static int bch2_journal_replay_accounting_key(struct btree_trans *trans, bch2_trans_node_iter_init(trans, &iter, k->btree_id, k->k->k.p, BTREE_MAX_DEPTH, k->level, BTREE_ITER_intent); - int ret = bch2_btree_iter_traverse(&iter); + int ret = bch2_btree_iter_traverse(trans, &iter); if (ret) goto out; @@ -261,7 +261,7 @@ static int bch2_journal_replay_key(struct btree_trans *trans, bch2_trans_node_iter_init(trans, &iter, k->btree_id, k->k->k.p, BTREE_MAX_DEPTH, k->level, iter_flags); - ret = bch2_btree_iter_traverse(&iter); + ret = bch2_btree_iter_traverse(trans, &iter); if (ret) goto out; @@ -270,7 +270,7 @@ static int bch2_journal_replay_key(struct btree_trans *trans, bch2_trans_iter_exit(trans, &iter); bch2_trans_node_iter_init(trans, &iter, k->btree_id, k->k->k.p, BTREE_MAX_DEPTH, 0, iter_flags); - ret = bch2_btree_iter_traverse(&iter) ?: + ret = bch2_btree_iter_traverse(trans, &iter) ?: bch2_btree_increase_depth(trans, iter.path, 0) ?: -BCH_ERR_transaction_restart_nested; goto out;
diff --git a/fs/bcachefs/reflink.c b/fs/bcachefs/reflink.c index ee23f1f..710178e 100644 --- a/fs/bcachefs/reflink.c +++ b/fs/bcachefs/reflink.c
@@ -495,7 +495,7 @@ static int bch2_make_extent_indirect(struct btree_trans *trans, bool reflink_p_may_update_opts_field) { struct bch_fs *c = trans->c; - struct btree_iter reflink_iter = { NULL }; + struct btree_iter reflink_iter = {}; struct bkey_s_c k; struct bkey_i *r_v; struct bkey_i_reflink_p *r_p; @@ -507,7 +507,7 @@ static int bch2_make_extent_indirect(struct btree_trans *trans, bch2_trans_iter_init(trans, &reflink_iter, BTREE_ID_reflink, POS_MAX, BTREE_ITER_intent); - k = bch2_btree_iter_peek_prev(&reflink_iter); + k = bch2_btree_iter_peek_prev(trans, &reflink_iter); ret = bkey_err(k); if (ret) goto err; @@ -569,12 +569,13 @@ static int bch2_make_extent_indirect(struct btree_trans *trans, return ret; } -static struct bkey_s_c get_next_src(struct btree_iter *iter, struct bpos end) +static struct bkey_s_c get_next_src(struct btree_trans *trans, + struct btree_iter *iter, struct bpos end) { struct bkey_s_c k; int ret; - for_each_btree_key_max_continue_norestart(*iter, end, 0, k, ret) { + for_each_btree_key_max_continue_norestart(trans, *iter, end, 0, k, ret) { if (bkey_extent_is_unwritten(k)) continue; @@ -583,7 +584,7 @@ static struct bkey_s_c get_next_src(struct btree_iter *iter, struct bpos end) } if (bkey_ge(iter->pos, end)) - bch2_btree_iter_set_pos(iter, end); + bch2_btree_iter_set_pos(trans, iter, end); return ret ? bkey_s_c_err(ret) : bkey_s_c_null; } @@ -647,27 +648,27 @@ s64 bch2_remap_range(struct bch_fs *c, if (ret) continue; - bch2_btree_iter_set_snapshot(&src_iter, src_snapshot); + bch2_btree_iter_set_snapshot(trans, &src_iter, src_snapshot); ret = bch2_subvolume_get_snapshot(trans, dst_inum.subvol, &dst_snapshot); if (ret) continue; - bch2_btree_iter_set_snapshot(&dst_iter, dst_snapshot); + bch2_btree_iter_set_snapshot(trans, &dst_iter, dst_snapshot); if (dst_inum.inum < src_inum.inum) { /* Avoid some lock cycle transaction restarts */ - ret = bch2_btree_iter_traverse(&dst_iter); + ret = bch2_btree_iter_traverse(trans, &dst_iter); if (ret) continue; } dst_done = dst_iter.pos.offset - dst_start.offset; src_want = POS(src_start.inode, src_start.offset + dst_done); - bch2_btree_iter_set_pos(&src_iter, src_want); + bch2_btree_iter_set_pos(trans, &src_iter, src_want); - src_k = get_next_src(&src_iter, src_end); + src_k = get_next_src(trans, &src_iter, src_end); ret = bkey_err(src_k); if (ret) continue; @@ -738,7 +739,7 @@ s64 bch2_remap_range(struct bch_fs *c, do { struct bch_inode_unpacked inode_u; - struct btree_iter inode_iter = { NULL }; + struct btree_iter inode_iter = {}; bch2_trans_begin(trans);
diff --git a/fs/bcachefs/sb-members.h b/fs/bcachefs/sb-members.h index 3826163..06bb41a 100644 --- a/fs/bcachefs/sb-members.h +++ b/fs/bcachefs/sb-members.h
@@ -20,7 +20,7 @@ struct bch_member bch2_sb_member_get(struct bch_sb *sb, int i); static inline bool bch2_dev_is_online(struct bch_dev *ca) { - return !percpu_ref_is_zero(&ca->io_ref); + return !percpu_ref_is_zero(&ca->io_ref[READ]); } static inline struct bch_dev *bch2_dev_rcu(struct bch_fs *, unsigned); @@ -156,33 +156,34 @@ static inline struct bch_dev *bch2_get_next_dev(struct bch_fs *c, struct bch_dev static inline struct bch_dev *bch2_get_next_online_dev(struct bch_fs *c, struct bch_dev *ca, - unsigned state_mask) + unsigned state_mask, + int rw) { rcu_read_lock(); if (ca) - percpu_ref_put(&ca->io_ref); + percpu_ref_put(&ca->io_ref[rw]); while ((ca = __bch2_next_dev(c, ca, NULL)) && (!((1 << ca->mi.state) & state_mask) || - !percpu_ref_tryget(&ca->io_ref))) + !percpu_ref_tryget(&ca->io_ref[rw]))) ; rcu_read_unlock(); return ca; } -#define __for_each_online_member(_c, _ca, state_mask) \ +#define __for_each_online_member(_c, _ca, state_mask, rw) \ for (struct bch_dev *_ca = NULL; \ - (_ca = bch2_get_next_online_dev(_c, _ca, state_mask));) + (_ca = bch2_get_next_online_dev(_c, _ca, state_mask, rw));) #define for_each_online_member(c, ca) \ - __for_each_online_member(c, ca, ~0) + __for_each_online_member(c, ca, ~0, READ) #define for_each_rw_member(c, ca) \ - __for_each_online_member(c, ca, BIT(BCH_MEMBER_STATE_rw)) + __for_each_online_member(c, ca, BIT(BCH_MEMBER_STATE_rw), WRITE) #define for_each_readable_member(c, ca) \ - __for_each_online_member(c, ca, BIT( BCH_MEMBER_STATE_rw)|BIT(BCH_MEMBER_STATE_ro)) + __for_each_online_member(c, ca, BIT( BCH_MEMBER_STATE_rw)|BIT(BCH_MEMBER_STATE_ro), READ) static inline bool bch2_dev_exists(const struct bch_fs *c, unsigned dev) { @@ -287,7 +288,7 @@ static inline struct bch_dev *bch2_dev_get_ioref(struct bch_fs *c, unsigned dev, rcu_read_lock(); struct bch_dev *ca = bch2_dev_rcu(c, dev); - if (ca && !percpu_ref_tryget(&ca->io_ref)) + if (ca && !percpu_ref_tryget(&ca->io_ref[rw])) ca = NULL; rcu_read_unlock(); @@ -297,7 +298,7 @@ static inline struct bch_dev *bch2_dev_get_ioref(struct bch_fs *c, unsigned dev, return ca; if (ca) - percpu_ref_put(&ca->io_ref); + percpu_ref_put(&ca->io_ref[rw]); return NULL; }
diff --git a/fs/bcachefs/snapshot.c b/fs/bcachefs/snapshot.c index 0c65065..b7de29a 100644 --- a/fs/bcachefs/snapshot.c +++ b/fs/bcachefs/snapshot.c
@@ -843,9 +843,6 @@ static int check_snapshot_exists(struct btree_trans *trans, u32 id) { struct bch_fs *c = trans->c; - if (bch2_snapshot_exists(c, id)) - return 0; - /* Do we need to reconstruct the snapshot_tree entry as well? */ struct btree_iter iter; struct bkey_s_c k; @@ -1074,9 +1071,9 @@ static inline void normalize_snapshot_child_pointers(struct bch_snapshot *s) static int bch2_snapshot_node_delete(struct btree_trans *trans, u32 id) { struct bch_fs *c = trans->c; - struct btree_iter iter, p_iter = (struct btree_iter) { NULL }; - struct btree_iter c_iter = (struct btree_iter) { NULL }; - struct btree_iter tree_iter = (struct btree_iter) { NULL }; + struct btree_iter iter, p_iter = {}; + struct btree_iter c_iter = {}; + struct btree_iter tree_iter = {}; struct bkey_s_c_snapshot s; u32 parent_id, child_id; unsigned i; @@ -1193,13 +1190,13 @@ static int create_snapids(struct btree_trans *trans, u32 parent, u32 tree, bch2_trans_iter_init(trans, &iter, BTREE_ID_snapshots, POS_MIN, BTREE_ITER_intent); - k = bch2_btree_iter_peek(&iter); + k = bch2_btree_iter_peek(trans, &iter); ret = bkey_err(k); if (ret) goto err; for (i = 0; i < nr_snapids; i++) { - k = bch2_btree_iter_prev_slot(&iter); + k = bch2_btree_iter_prev_slot(trans, &iter); ret = bkey_err(k); if (ret) goto err;
diff --git a/fs/bcachefs/str_hash.c b/fs/bcachefs/str_hash.c index 602afca..a90bf7b 100644 --- a/fs/bcachefs/str_hash.c +++ b/fs/bcachefs/str_hash.c
@@ -195,7 +195,7 @@ int __bch2_str_hash_check_key(struct btree_trans *trans, struct btree_iter *k_iter, struct bkey_s_c hash_k) { struct bch_fs *c = trans->c; - struct btree_iter iter = { NULL }; + struct btree_iter iter = {}; struct printbuf buf = PRINTBUF; struct bkey_s_c k; int ret = 0;
diff --git a/fs/bcachefs/str_hash.h b/fs/bcachefs/str_hash.h index 575ad1e..09a354a 100644 --- a/fs/bcachefs/str_hash.h +++ b/fs/bcachefs/str_hash.h
@@ -231,11 +231,11 @@ int bch2_hash_needs_whiteout(struct btree_trans *trans, struct bkey_s_c k; int ret; - bch2_trans_copy_iter(&iter, start); + bch2_trans_copy_iter(trans, &iter, start); - bch2_btree_iter_advance(&iter); + bch2_btree_iter_advance(trans, &iter); - for_each_btree_key_continue_norestart(iter, BTREE_ITER_slots, k, ret) { + for_each_btree_key_continue_norestart(trans, iter, BTREE_ITER_slots, k, ret) { if (k.k->type != desc.key_type && k.k->type != KEY_TYPE_hash_whiteout) break; @@ -280,7 +280,7 @@ struct bkey_s_c bch2_hash_set_or_get_in_snapshot(struct btree_trans *trans, } if (!slot.path && !(flags & STR_HASH_must_replace)) - bch2_trans_copy_iter(&slot, iter); + bch2_trans_copy_iter(trans, &slot, iter); if (k.k->type != KEY_TYPE_hash_whiteout) goto not_found;
diff --git a/fs/bcachefs/subvolume.c b/fs/bcachefs/subvolume.c index cd0d8e5..5537283 100644 --- a/fs/bcachefs/subvolume.c +++ b/fs/bcachefs/subvolume.c
@@ -275,7 +275,7 @@ int bch2_subvol_has_children(struct btree_trans *trans, u32 subvol) struct btree_iter iter; bch2_trans_iter_init(trans, &iter, BTREE_ID_subvolume_children, POS(subvol, 0), 0); - struct bkey_s_c k = bch2_btree_iter_peek(&iter); + struct bkey_s_c k = bch2_btree_iter_peek(trans, &iter); bch2_trans_iter_exit(trans, &iter); return bkey_err(k) ?: k.k && k.k->p.inode == subvol @@ -574,7 +574,7 @@ int bch2_subvolume_create(struct btree_trans *trans, u64 inode, bool ro) { struct bch_fs *c = trans->c; - struct btree_iter dst_iter, src_iter = (struct btree_iter) { NULL }; + struct btree_iter dst_iter, src_iter = {}; struct bkey_i_subvolume *new_subvol = NULL; struct bkey_i_subvolume *src_subvol = NULL; u32 parent = 0, new_nodes[2], snapshot_subvols[2];
diff --git a/fs/bcachefs/subvolume.h b/fs/bcachefs/subvolume.h index 910f6196..f640c1e 100644 --- a/fs/bcachefs/subvolume.h +++ b/fs/bcachefs/subvolume.h
@@ -33,16 +33,16 @@ int bch2_subvol_is_ro_trans(struct btree_trans *, u32); int bch2_subvol_is_ro(struct bch_fs *, u32); static inline struct bkey_s_c -bch2_btree_iter_peek_in_subvolume_max_type(struct btree_iter *iter, struct bpos end, - u32 subvolid, unsigned flags) +bch2_btree_iter_peek_in_subvolume_max_type(struct btree_trans *trans, struct btree_iter *iter, + struct bpos end, u32 subvolid, unsigned flags) { u32 snapshot; - int ret = bch2_subvolume_get_snapshot(iter->trans, subvolid, &snapshot); + int ret = bch2_subvolume_get_snapshot(trans, subvolid, &snapshot); if (ret) return bkey_s_c_err(ret); - bch2_btree_iter_set_snapshot(iter, snapshot); - return bch2_btree_iter_peek_max_type(iter, end, flags); + bch2_btree_iter_set_snapshot(trans, iter, snapshot); + return bch2_btree_iter_peek_max_type(trans, iter, end, flags); } #define for_each_btree_key_in_subvolume_max_continue(_trans, _iter, \ @@ -53,14 +53,14 @@ bch2_btree_iter_peek_in_subvolume_max_type(struct btree_iter *iter, struct bpos \ do { \ _ret3 = lockrestart_do(_trans, ({ \ - (_k) = bch2_btree_iter_peek_in_subvolume_max_type(&(_iter), \ + (_k) = bch2_btree_iter_peek_in_subvolume_max_type(trans, &(_iter),\ _end, _subvolid, (_flags)); \ if (!(_k).k) \ break; \ \ bkey_err(_k) ?: (_do); \ })); \ - } while (!_ret3 && bch2_btree_iter_advance(&(_iter))); \ + } while (!_ret3 && bch2_btree_iter_advance(_trans, &(_iter))); \ \ bch2_trans_iter_exit((_trans), &(_iter)); \ _ret3; \
diff --git a/fs/bcachefs/super-io.c b/fs/bcachefs/super-io.c index 572b06b..e27422b 100644 --- a/fs/bcachefs/super-io.c +++ b/fs/bcachefs/super-io.c
@@ -248,7 +248,7 @@ struct bch_sb_field *bch2_sb_field_resize_id(struct bch_sb_handle *sb, struct bch_sb_handle *dev_sb = &ca->disk_sb; if (bch2_sb_realloc(dev_sb, le32_to_cpu(dev_sb->sb->u64s) + d)) { - percpu_ref_put(&ca->io_ref); + percpu_ref_put(&ca->io_ref[READ]); return NULL; } } @@ -945,7 +945,7 @@ static void write_super_endio(struct bio *bio) } closure_put(&ca->fs->sb_write); - percpu_ref_put(&ca->io_ref); + percpu_ref_put(&ca->io_ref[READ]); } static void read_back_super(struct bch_fs *c, struct bch_dev *ca) @@ -963,7 +963,7 @@ static void read_back_super(struct bch_fs *c, struct bch_dev *ca) this_cpu_add(ca->io_done->sectors[READ][BCH_DATA_sb], bio_sectors(bio)); - percpu_ref_get(&ca->io_ref); + percpu_ref_get(&ca->io_ref[READ]); closure_bio_submit(bio, &c->sb_write); } @@ -989,7 +989,7 @@ static void write_one_super(struct bch_fs *c, struct bch_dev *ca, unsigned idx) this_cpu_add(ca->io_done->sectors[WRITE][BCH_DATA_sb], bio_sectors(bio)); - percpu_ref_get(&ca->io_ref); + percpu_ref_get(&ca->io_ref[READ]); closure_bio_submit(bio, &c->sb_write); } @@ -1014,13 +1014,20 @@ int bch2_write_super(struct bch_fs *c) closure_init_stack(cl); memset(&sb_written, 0, sizeof(sb_written)); + /* + * Note: we do writes to RO devices here, and we might want to change + * that in the future. + * + * For now, we expect to be able to call write_super() when we're not + * yet RW: + */ for_each_online_member(c, ca) { ret = darray_push(&online_devices, ca); if (bch2_fs_fatal_err_on(ret, c, "%s: error allocating online devices", __func__)) { - percpu_ref_put(&ca->io_ref); + percpu_ref_put(&ca->io_ref[READ]); goto out; } - percpu_ref_get(&ca->io_ref); + percpu_ref_get(&ca->io_ref[READ]); } /* Make sure we're using the new magic numbers: */ @@ -1186,7 +1193,7 @@ int bch2_write_super(struct bch_fs *c) /* Make new options visible after they're persistent: */ bch2_sb_update(c); darray_for_each(online_devices, ca) - percpu_ref_put(&(*ca)->io_ref); + percpu_ref_put(&(*ca)->io_ref[READ]); darray_exit(&online_devices); printbuf_exit(&err); return ret;
diff --git a/fs/bcachefs/super.c b/fs/bcachefs/super.c index 20208f3..a58edde43 100644 --- a/fs/bcachefs/super.c +++ b/fs/bcachefs/super.c
@@ -185,6 +185,7 @@ static void bch2_dev_unlink(struct bch_dev *); static void bch2_dev_free(struct bch_dev *); static int bch2_dev_alloc(struct bch_fs *, unsigned); static int bch2_dev_sysfs_online(struct bch_fs *, struct bch_dev *); +static void bch2_dev_io_ref_stop(struct bch_dev *, int); static void __bch2_dev_read_only(struct bch_fs *, struct bch_dev *); struct bch_fs *bch2_dev_to_fs(dev_t dev) @@ -294,8 +295,10 @@ static void __bch2_fs_read_only(struct bch_fs *c) /* * After stopping journal: */ - for_each_member_device(c, ca) + for_each_member_device(c, ca) { + bch2_dev_io_ref_stop(ca, WRITE); bch2_dev_allocator_remove(c, ca); + } } #ifndef BCH_WRITE_REF_DEBUG @@ -465,10 +468,6 @@ static int __bch2_fs_read_write(struct bch_fs *c, bool early) if (ret) goto err; - ret = bch2_fs_mark_dirty(c); - if (ret) - goto err; - clear_bit(BCH_FS_clean_shutdown, &c->flags); /* @@ -480,10 +479,24 @@ static int __bch2_fs_read_write(struct bch_fs *c, bool early) set_bit(JOURNAL_need_flush_write, &c->journal.flags); set_bit(JOURNAL_running, &c->journal.flags); - for_each_rw_member(c, ca) + __for_each_online_member(c, ca, BIT(BCH_MEMBER_STATE_rw), READ) { bch2_dev_allocator_add(c, ca); + percpu_ref_reinit(&ca->io_ref[WRITE]); + } bch2_recalc_capacity(c); + ret = bch2_fs_mark_dirty(c); + if (ret) + goto err; + + spin_lock(&c->journal.lock); + bch2_journal_space_available(&c->journal); + spin_unlock(&c->journal.lock); + + ret = bch2_journal_reclaim_start(&c->journal); + if (ret) + goto err; + set_bit(BCH_FS_rw, &c->flags); set_bit(BCH_FS_was_rw, &c->flags); @@ -495,11 +508,6 @@ static int __bch2_fs_read_write(struct bch_fs *c, bool early) atomic_long_inc(&c->writes[i]); } #endif - - ret = bch2_journal_reclaim_start(&c->journal); - if (ret) - goto err; - if (!early) { ret = bch2_fs_read_write_late(c); if (ret) @@ -675,6 +683,7 @@ void bch2_fs_free(struct bch_fs *c) if (ca) { EBUG_ON(atomic_long_read(&ca->ref) != 1); + bch2_dev_io_ref_stop(ca, READ); bch2_free_super(&ca->disk_sb); bch2_dev_free(ca); } @@ -1199,6 +1208,15 @@ static int bch2_dev_in_fs(struct bch_sb_handle *fs, /* Device startup/shutdown: */ +static void bch2_dev_io_ref_stop(struct bch_dev *ca, int rw) +{ + if (!percpu_ref_is_zero(&ca->io_ref[rw])) { + reinit_completion(&ca->io_ref_completion[rw]); + percpu_ref_kill(&ca->io_ref[rw]); + wait_for_completion(&ca->io_ref_completion[rw]); + } +} + static void bch2_dev_release(struct kobject *kobj) { struct bch_dev *ca = container_of(kobj, struct bch_dev, kobj); @@ -1208,6 +1226,9 @@ static void bch2_dev_release(struct kobject *kobj) static void bch2_dev_free(struct bch_dev *ca) { + WARN_ON(!percpu_ref_is_zero(&ca->io_ref[WRITE])); + WARN_ON(!percpu_ref_is_zero(&ca->io_ref[READ])); + cancel_work_sync(&ca->io_error_work); bch2_dev_unlink(ca); @@ -1226,7 +1247,8 @@ static void bch2_dev_free(struct bch_dev *ca) bch2_time_stats_quantiles_exit(&ca->io_latency[WRITE]); bch2_time_stats_quantiles_exit(&ca->io_latency[READ]); - percpu_ref_exit(&ca->io_ref); + percpu_ref_exit(&ca->io_ref[WRITE]); + percpu_ref_exit(&ca->io_ref[READ]); #ifndef CONFIG_BCACHEFS_DEBUG percpu_ref_exit(&ca->ref); #endif @@ -1238,14 +1260,12 @@ static void __bch2_dev_offline(struct bch_fs *c, struct bch_dev *ca) lockdep_assert_held(&c->state_lock); - if (percpu_ref_is_zero(&ca->io_ref)) + if (percpu_ref_is_zero(&ca->io_ref[READ])) return; __bch2_dev_read_only(c, ca); - reinit_completion(&ca->io_ref_completion); - percpu_ref_kill(&ca->io_ref); - wait_for_completion(&ca->io_ref_completion); + bch2_dev_io_ref_stop(ca, READ); bch2_dev_unlink(ca); @@ -1262,11 +1282,18 @@ static void bch2_dev_ref_complete(struct percpu_ref *ref) } #endif -static void bch2_dev_io_ref_complete(struct percpu_ref *ref) +static void bch2_dev_io_ref_read_complete(struct percpu_ref *ref) { - struct bch_dev *ca = container_of(ref, struct bch_dev, io_ref); + struct bch_dev *ca = container_of(ref, struct bch_dev, io_ref[READ]); - complete(&ca->io_ref_completion); + complete(&ca->io_ref_completion[READ]); +} + +static void bch2_dev_io_ref_write_complete(struct percpu_ref *ref) +{ + struct bch_dev *ca = container_of(ref, struct bch_dev, io_ref[WRITE]); + + complete(&ca->io_ref_completion[WRITE]); } static void bch2_dev_unlink(struct bch_dev *ca) @@ -1330,7 +1357,8 @@ static struct bch_dev *__bch2_dev_alloc(struct bch_fs *c, kobject_init(&ca->kobj, &bch2_dev_ktype); init_completion(&ca->ref_completion); - init_completion(&ca->io_ref_completion); + init_completion(&ca->io_ref_completion[READ]); + init_completion(&ca->io_ref_completion[WRITE]); INIT_WORK(&ca->io_error_work, bch2_io_error_work); @@ -1356,7 +1384,9 @@ static struct bch_dev *__bch2_dev_alloc(struct bch_fs *c, bch2_dev_allocator_background_init(ca); - if (percpu_ref_init(&ca->io_ref, bch2_dev_io_ref_complete, + if (percpu_ref_init(&ca->io_ref[READ], bch2_dev_io_ref_read_complete, + PERCPU_REF_INIT_DEAD, GFP_KERNEL) || + percpu_ref_init(&ca->io_ref[WRITE], bch2_dev_io_ref_write_complete, PERCPU_REF_INIT_DEAD, GFP_KERNEL) || !(ca->sb_read_scratch = kmalloc(BCH_SB_READ_SCRATCH_BUF_SIZE, GFP_KERNEL)) || bch2_dev_buckets_alloc(c, ca) || @@ -1419,7 +1449,8 @@ static int __bch2_dev_attach_bdev(struct bch_dev *ca, struct bch_sb_handle *sb) return -BCH_ERR_device_size_too_small; } - BUG_ON(!percpu_ref_is_zero(&ca->io_ref)); + BUG_ON(!percpu_ref_is_zero(&ca->io_ref[READ])); + BUG_ON(!percpu_ref_is_zero(&ca->io_ref[WRITE])); ret = bch2_dev_journal_init(ca, sb->sb); if (ret) @@ -1438,7 +1469,7 @@ static int __bch2_dev_attach_bdev(struct bch_dev *ca, struct bch_sb_handle *sb) ca->dev = ca->disk_sb.bdev->bd_dev; - percpu_ref_reinit(&ca->io_ref); + percpu_ref_reinit(&ca->io_ref[READ]); return 0; } @@ -1568,6 +1599,8 @@ static bool bch2_fs_may_start(struct bch_fs *c) static void __bch2_dev_read_only(struct bch_fs *c, struct bch_dev *ca) { + bch2_dev_io_ref_stop(ca, WRITE); + /* * The allocator thread itself allocates btree nodes, so stop it first: */ @@ -1584,6 +1617,10 @@ static void __bch2_dev_read_write(struct bch_fs *c, struct bch_dev *ca) bch2_dev_allocator_add(c, ca); bch2_recalc_capacity(c); + + if (percpu_ref_is_zero(&ca->io_ref[WRITE])) + percpu_ref_reinit(&ca->io_ref[WRITE]); + bch2_dev_do_discards(ca); } @@ -1731,7 +1768,7 @@ int bch2_dev_remove(struct bch_fs *c, struct bch_dev *ca, int flags) return 0; err: if (ca->mi.state == BCH_MEMBER_STATE_rw && - !percpu_ref_is_zero(&ca->io_ref)) + !percpu_ref_is_zero(&ca->io_ref[READ])) __bch2_dev_read_write(c, ca); up_write(&c->state_lock); return ret;
diff --git a/fs/bcachefs/tests.c b/fs/bcachefs/tests.c index 6c64698..c265b10 100644 --- a/fs/bcachefs/tests.c +++ b/fs/bcachefs/tests.c
@@ -43,7 +43,7 @@ static int test_delete(struct bch_fs *c, u64 nr) BTREE_ITER_intent); ret = commit_do(trans, NULL, NULL, 0, - bch2_btree_iter_traverse(&iter) ?: + bch2_btree_iter_traverse(trans, &iter) ?: bch2_trans_update(trans, &iter, &k.k_i, 0)); bch_err_msg(c, ret, "update error"); if (ret) @@ -51,7 +51,7 @@ static int test_delete(struct bch_fs *c, u64 nr) pr_info("deleting once"); ret = commit_do(trans, NULL, NULL, 0, - bch2_btree_iter_traverse(&iter) ?: + bch2_btree_iter_traverse(trans, &iter) ?: bch2_btree_delete_at(trans, &iter, 0)); bch_err_msg(c, ret, "delete error (first)"); if (ret) @@ -59,7 +59,7 @@ static int test_delete(struct bch_fs *c, u64 nr) pr_info("deleting twice"); ret = commit_do(trans, NULL, NULL, 0, - bch2_btree_iter_traverse(&iter) ?: + bch2_btree_iter_traverse(trans, &iter) ?: bch2_btree_delete_at(trans, &iter, 0)); bch_err_msg(c, ret, "delete error (second)"); if (ret) @@ -84,7 +84,7 @@ static int test_delete_written(struct bch_fs *c, u64 nr) BTREE_ITER_intent); ret = commit_do(trans, NULL, NULL, 0, - bch2_btree_iter_traverse(&iter) ?: + bch2_btree_iter_traverse(trans, &iter) ?: bch2_trans_update(trans, &iter, &k.k_i, 0)); bch_err_msg(c, ret, "update error"); if (ret) @@ -94,7 +94,7 @@ static int test_delete_written(struct bch_fs *c, u64 nr) bch2_journal_flush_all_pins(&c->journal); ret = commit_do(trans, NULL, NULL, 0, - bch2_btree_iter_traverse(&iter) ?: + bch2_btree_iter_traverse(trans, &iter) ?: bch2_btree_delete_at(trans, &iter, 0)); bch_err_msg(c, ret, "delete error"); if (ret) @@ -349,10 +349,10 @@ static int test_peek_end(struct bch_fs *c, u64 nr) bch2_trans_iter_init(trans, &iter, BTREE_ID_xattrs, SPOS(0, 0, U32_MAX), 0); - lockrestart_do(trans, bkey_err(k = bch2_btree_iter_peek_max(&iter, POS(0, U64_MAX)))); + lockrestart_do(trans, bkey_err(k = bch2_btree_iter_peek_max(trans, &iter, POS(0, U64_MAX)))); BUG_ON(k.k); - lockrestart_do(trans, bkey_err(k = bch2_btree_iter_peek_max(&iter, POS(0, U64_MAX)))); + lockrestart_do(trans, bkey_err(k = bch2_btree_iter_peek_max(trans, &iter, POS(0, U64_MAX)))); BUG_ON(k.k); bch2_trans_iter_exit(trans, &iter); @@ -369,10 +369,10 @@ static int test_peek_end_extents(struct bch_fs *c, u64 nr) bch2_trans_iter_init(trans, &iter, BTREE_ID_extents, SPOS(0, 0, U32_MAX), 0); - lockrestart_do(trans, bkey_err(k = bch2_btree_iter_peek_max(&iter, POS(0, U64_MAX)))); + lockrestart_do(trans, bkey_err(k = bch2_btree_iter_peek_max(trans, &iter, POS(0, U64_MAX)))); BUG_ON(k.k); - lockrestart_do(trans, bkey_err(k = bch2_btree_iter_peek_max(&iter, POS(0, U64_MAX)))); + lockrestart_do(trans, bkey_err(k = bch2_btree_iter_peek_max(trans, &iter, POS(0, U64_MAX)))); BUG_ON(k.k); bch2_trans_iter_exit(trans, &iter); @@ -488,7 +488,7 @@ static int test_snapshot_filter(struct bch_fs *c, u32 snapid_lo, u32 snapid_hi) trans = bch2_trans_get(c); bch2_trans_iter_init(trans, &iter, BTREE_ID_xattrs, SPOS(0, 0, snapid_lo), 0); - lockrestart_do(trans, bkey_err(k = bch2_btree_iter_peek_max(&iter, POS(0, U64_MAX)))); + lockrestart_do(trans, bkey_err(k = bch2_btree_iter_peek_max(trans, &iter, POS(0, U64_MAX)))); BUG_ON(k.k->p.snapshot != U32_MAX); @@ -602,9 +602,9 @@ static int rand_lookup(struct bch_fs *c, u64 nr) SPOS(0, 0, U32_MAX), 0); for (i = 0; i < nr; i++) { - bch2_btree_iter_set_pos(&iter, SPOS(0, test_rand(), U32_MAX)); + bch2_btree_iter_set_pos(trans, &iter, SPOS(0, test_rand(), U32_MAX)); - lockrestart_do(trans, bkey_err(k = bch2_btree_iter_peek(&iter))); + lockrestart_do(trans, bkey_err(k = bch2_btree_iter_peek(trans, &iter))); ret = bkey_err(k); if (ret) break; @@ -623,9 +623,9 @@ static int rand_mixed_trans(struct btree_trans *trans, struct bkey_s_c k; int ret; - bch2_btree_iter_set_pos(iter, SPOS(0, pos, U32_MAX)); + bch2_btree_iter_set_pos(trans, iter, SPOS(0, pos, U32_MAX)); - k = bch2_btree_iter_peek(iter); + k = bch2_btree_iter_peek(trans, iter); ret = bkey_err(k); bch_err_msg(trans->c, ret, "lookup error"); if (ret) @@ -672,7 +672,7 @@ static int __do_delete(struct btree_trans *trans, struct bpos pos) bch2_trans_iter_init(trans, &iter, BTREE_ID_xattrs, pos, BTREE_ITER_intent); - k = bch2_btree_iter_peek_max(&iter, POS(0, U64_MAX)); + k = bch2_btree_iter_peek_max(trans, &iter, POS(0, U64_MAX)); ret = bkey_err(k); if (ret) goto err;
diff --git a/fs/bcachefs/xattr.c b/fs/bcachefs/xattr.c index f9667b9..651da52 100644 --- a/fs/bcachefs/xattr.c +++ b/fs/bcachefs/xattr.c
@@ -168,7 +168,7 @@ int bch2_xattr_set(struct btree_trans *trans, subvol_inum inum, int type, int flags) { struct bch_fs *c = trans->c; - struct btree_iter inode_iter = { NULL }; + struct btree_iter inode_iter = {}; int ret; ret = bch2_subvol_is_ro_trans(trans, inum.subvol) ?:
diff --git a/fs/btrfs/Kconfig b/fs/btrfs/Kconfig index fa85155..73a2dfb 100644 --- a/fs/btrfs/Kconfig +++ b/fs/btrfs/Kconfig
@@ -3,9 +3,9 @@ config BTRFS_FS tristate "Btrfs filesystem support" select BLK_CGROUP_PUNT_BIO + select CRC32 select CRYPTO select CRYPTO_CRC32C - select LIBCRC32C select CRYPTO_XXHASH select CRYPTO_SHA256 select CRYPTO_BLAKE2B
diff --git a/fs/btrfs/zstd.c b/fs/btrfs/zstd.c index cd5f38d..3541efa 100644 --- a/fs/btrfs/zstd.c +++ b/fs/btrfs/zstd.c
@@ -225,7 +225,7 @@ void zstd_cleanup_workspace_manager(void) } spin_unlock_bh(&wsm.lock); - del_timer_sync(&wsm.timer); + timer_delete_sync(&wsm.timer); } /*
diff --git a/fs/cachefiles/namei.c b/fs/cachefiles/namei.c index 83a6012..14d0cc8 100644 --- a/fs/cachefiles/namei.c +++ b/fs/cachefiles/namei.c
@@ -128,10 +128,11 @@ struct dentry *cachefiles_get_directory(struct cachefiles_cache *cache, ret = security_path_mkdir(&path, subdir, 0700); if (ret < 0) goto mkdir_error; - subdir = ERR_PTR(cachefiles_inject_write_error()); - if (!IS_ERR(subdir)) + ret = cachefiles_inject_write_error(); + if (ret == 0) subdir = vfs_mkdir(&nop_mnt_idmap, d_inode(dir), subdir, 0700); - ret = PTR_ERR(subdir); + else + subdir = ERR_PTR(ret); if (IS_ERR(subdir)) { trace_cachefiles_vfs_error(NULL, d_inode(dir), ret, cachefiles_trace_mkdir_error);
diff --git a/fs/ceph/Kconfig b/fs/ceph/Kconfig index 7249d70..3e7def3 100644 --- a/fs/ceph/Kconfig +++ b/fs/ceph/Kconfig
@@ -3,7 +3,7 @@ tristate "Ceph distributed file system" depends on INET select CEPH_LIB - select LIBCRC32C + select CRC32 select CRYPTO_AES select CRYPTO select NETFS_SUPPORT
diff --git a/fs/erofs/Kconfig b/fs/erofs/Kconfig index 331e49c..8f68ec4 100644 --- a/fs/erofs/Kconfig +++ b/fs/erofs/Kconfig
@@ -3,8 +3,8 @@ config EROFS_FS tristate "EROFS filesystem support" depends on BLOCK + select CRC32 select FS_IOMAP - select LIBCRC32C help EROFS (Enhanced Read-Only File System) is a lightweight read-only file system with modern designs (e.g. no buffer heads, inline
diff --git a/fs/exec.c b/fs/exec.c index f45859a..8e4ea5f 100644 --- a/fs/exec.c +++ b/fs/exec.c
@@ -1227,13 +1227,12 @@ int begin_new_exec(struct linux_binprm * bprm) */ bprm->point_of_no_return = true; - /* - * Make this the only thread in the thread group. - */ + /* Make this the only thread in the thread group */ retval = de_thread(me); if (retval) goto out; - + /* see the comment in check_unsafe_exec() */ + current->fs->in_exec = 0; /* * Cancel any io_uring activity across execve */ @@ -1495,6 +1494,8 @@ static void free_bprm(struct linux_binprm *bprm) } free_arg_pages(bprm); if (bprm->cred) { + /* in case exec fails before de_thread() succeeds */ + current->fs->in_exec = 0; mutex_unlock(¤t->signal->cred_guard_mutex); abort_creds(bprm->cred); } @@ -1616,6 +1617,10 @@ static void check_unsafe_exec(struct linux_binprm *bprm) * suid exec because the differently privileged task * will be able to manipulate the current directory, etc. * It would be nice to force an unshare instead... + * + * Otherwise we set fs->in_exec = 1 to deny clone(CLONE_FS) + * from another sub-thread until de_thread() succeeds, this + * state is protected by cred_guard_mutex we hold. */ n_fs = 1; spin_lock(&p->fs->lock); @@ -1859,10 +1864,9 @@ static int bprm_execve(struct linux_binprm *bprm) goto out; sched_mm_cid_after_execve(current); - /* execve succeeded */ - current->fs->in_exec = 0; - current->in_execve = 0; rseq_execve(current); + /* execve succeeded */ + current->in_execve = 0; user_events_execve(current); acct_update_integrals(current); task_numa_free(current, false); @@ -1879,7 +1883,7 @@ static int bprm_execve(struct linux_binprm *bprm) force_fatal_sig(SIGSEGV); sched_mm_cid_after_execve(current); - current->fs->in_exec = 0; + rseq_set_notify_resume(current); current->in_execve = 0; return retval;
diff --git a/fs/exportfs/expfs.c b/fs/exportfs/expfs.c index b5845c4..128dd09 100644 --- a/fs/exportfs/expfs.c +++ b/fs/exportfs/expfs.c
@@ -608,4 +608,5 @@ struct dentry *exportfs_decode_fh(struct vfsmount *mnt, struct fid *fid, } EXPORT_SYMBOL_GPL(exportfs_decode_fh); +MODULE_DESCRIPTION("Code mapping from inodes to file handles"); MODULE_LICENSE("GPL");
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 8122d4f..1819344 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c
@@ -5680,7 +5680,7 @@ failed_mount8: __maybe_unused /* flush s_sb_upd_work before sbi destroy */ flush_work(&sbi->s_sb_upd_work); ext4_stop_mmpd(sbi); - del_timer_sync(&sbi->s_err_report); + timer_delete_sync(&sbi->s_err_report); ext4_group_desc_free(sbi); failed_mount: #if IS_ENABLED(CONFIG_UNICODE)
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index 51e31df..6dcbaa2 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c
@@ -32,6 +32,100 @@ MODULE_ALIAS("devname:fuse"); static struct kmem_cache *fuse_req_cachep; +const unsigned long fuse_timeout_timer_freq = + secs_to_jiffies(FUSE_TIMEOUT_TIMER_FREQ); + +bool fuse_request_expired(struct fuse_conn *fc, struct list_head *list) +{ + struct fuse_req *req; + + req = list_first_entry_or_null(list, struct fuse_req, list); + if (!req) + return false; + return time_is_before_jiffies(req->create_time + fc->timeout.req_timeout); +} + +bool fuse_fpq_processing_expired(struct fuse_conn *fc, struct list_head *processing) +{ + int i; + + for (i = 0; i < FUSE_PQ_HASH_SIZE; i++) + if (fuse_request_expired(fc, &processing[i])) + return true; + + return false; +} + +/* + * Check if any requests aren't being completed by the time the request timeout + * elapses. To do so, we: + * - check the fiq pending list + * - check the bg queue + * - check the fpq io and processing lists + * + * To make this fast, we only check against the head request on each list since + * these are generally queued in order of creation time (eg newer requests get + * queued to the tail). We might miss a few edge cases (eg requests transitioning + * between lists, re-sent requests at the head of the pending list having a + * later creation time than other requests on that list, etc.) but that is fine + * since if the request never gets fulfilled, it will eventually be caught. + */ +void fuse_check_timeout(struct work_struct *work) +{ + struct delayed_work *dwork = to_delayed_work(work); + struct fuse_conn *fc = container_of(dwork, struct fuse_conn, + timeout.work); + struct fuse_iqueue *fiq = &fc->iq; + struct fuse_dev *fud; + struct fuse_pqueue *fpq; + bool expired = false; + + if (!atomic_read(&fc->num_waiting)) + goto out; + + spin_lock(&fiq->lock); + expired = fuse_request_expired(fc, &fiq->pending); + spin_unlock(&fiq->lock); + if (expired) + goto abort_conn; + + spin_lock(&fc->bg_lock); + expired = fuse_request_expired(fc, &fc->bg_queue); + spin_unlock(&fc->bg_lock); + if (expired) + goto abort_conn; + + spin_lock(&fc->lock); + if (!fc->connected) { + spin_unlock(&fc->lock); + return; + } + list_for_each_entry(fud, &fc->devices, entry) { + fpq = &fud->pq; + spin_lock(&fpq->lock); + if (fuse_request_expired(fc, &fpq->io) || + fuse_fpq_processing_expired(fc, fpq->processing)) { + spin_unlock(&fpq->lock); + spin_unlock(&fc->lock); + goto abort_conn; + } + + spin_unlock(&fpq->lock); + } + spin_unlock(&fc->lock); + + if (fuse_uring_request_expired(fc)) + goto abort_conn; + +out: + queue_delayed_work(system_wq, &fc->timeout.work, + fuse_timeout_timer_freq); + return; + +abort_conn: + fuse_abort_conn(fc); +} + static void fuse_request_init(struct fuse_mount *fm, struct fuse_req *req) { INIT_LIST_HEAD(&req->list); @@ -40,6 +134,7 @@ static void fuse_request_init(struct fuse_mount *fm, struct fuse_req *req) refcount_set(&req->count, 1); __set_bit(FR_PENDING, &req->flags); req->fm = fm; + req->create_time = jiffies; } static struct fuse_req *fuse_request_alloc(struct fuse_mount *fm, gfp_t flags) @@ -407,6 +502,24 @@ static int queue_interrupt(struct fuse_req *req) return 0; } +bool fuse_remove_pending_req(struct fuse_req *req, spinlock_t *lock) +{ + spin_lock(lock); + if (test_bit(FR_PENDING, &req->flags)) { + /* + * FR_PENDING does not get cleared as the request will end + * up in destruction anyway. + */ + list_del(&req->list); + spin_unlock(lock); + __fuse_put_request(req); + req->out.h.error = -EINTR; + return true; + } + spin_unlock(lock); + return false; +} + static void request_wait_answer(struct fuse_req *req) { struct fuse_conn *fc = req->fm->fc; @@ -428,22 +541,20 @@ static void request_wait_answer(struct fuse_req *req) } if (!test_bit(FR_FORCE, &req->flags)) { + bool removed; + /* Only fatal signals may interrupt this */ err = wait_event_killable(req->waitq, test_bit(FR_FINISHED, &req->flags)); if (!err) return; - spin_lock(&fiq->lock); - /* Request is not yet in userspace, bail out */ - if (test_bit(FR_PENDING, &req->flags)) { - list_del(&req->list); - spin_unlock(&fiq->lock); - __fuse_put_request(req); - req->out.h.error = -EINTR; + if (test_bit(FR_URING, &req->flags)) + removed = fuse_uring_remove_pending_req(req); + else + removed = fuse_remove_pending_req(req, &fiq->lock); + if (removed) return; - } - spin_unlock(&fiq->lock); } /* @@ -1533,14 +1644,10 @@ static int fuse_notify_inval_entry(struct fuse_conn *fc, unsigned int size, struct fuse_copy_state *cs) { struct fuse_notify_inval_entry_out outarg; - int err = -ENOMEM; - char *buf; + int err; + char *buf = NULL; struct qstr name; - buf = kzalloc(FUSE_NAME_MAX + 1, GFP_KERNEL); - if (!buf) - goto err; - err = -EINVAL; if (size < sizeof(outarg)) goto err; @@ -1550,13 +1657,18 @@ static int fuse_notify_inval_entry(struct fuse_conn *fc, unsigned int size, goto err; err = -ENAMETOOLONG; - if (outarg.namelen > FUSE_NAME_MAX) + if (outarg.namelen > fc->name_max) goto err; err = -EINVAL; if (size != sizeof(outarg) + outarg.namelen + 1) goto err; + err = -ENOMEM; + buf = kzalloc(outarg.namelen + 1, GFP_KERNEL); + if (!buf) + goto err; + name.name = buf; name.len = outarg.namelen; err = fuse_copy_one(cs, buf, outarg.namelen + 1); @@ -1581,14 +1693,10 @@ static int fuse_notify_delete(struct fuse_conn *fc, unsigned int size, struct fuse_copy_state *cs) { struct fuse_notify_delete_out outarg; - int err = -ENOMEM; - char *buf; + int err; + char *buf = NULL; struct qstr name; - buf = kzalloc(FUSE_NAME_MAX + 1, GFP_KERNEL); - if (!buf) - goto err; - err = -EINVAL; if (size < sizeof(outarg)) goto err; @@ -1598,13 +1706,18 @@ static int fuse_notify_delete(struct fuse_conn *fc, unsigned int size, goto err; err = -ENAMETOOLONG; - if (outarg.namelen > FUSE_NAME_MAX) + if (outarg.namelen > fc->name_max) goto err; err = -EINVAL; if (size != sizeof(outarg) + outarg.namelen + 1) goto err; + err = -ENOMEM; + buf = kzalloc(outarg.namelen + 1, GFP_KERNEL); + if (!buf) + goto err; + name.name = buf; name.len = outarg.namelen; err = fuse_copy_one(cs, buf, outarg.namelen + 1); @@ -2275,6 +2388,9 @@ void fuse_abort_conn(struct fuse_conn *fc) LIST_HEAD(to_end); unsigned int i; + if (fc->timeout.req_timeout) + cancel_delayed_work(&fc->timeout.work); + /* Background queuing checks fc->connected under bg_lock */ spin_lock(&fc->bg_lock); fc->connected = 0;
diff --git a/fs/fuse/dev_uring.c b/fs/fuse/dev_uring.c index 82bf458..accdce2 100644 --- a/fs/fuse/dev_uring.c +++ b/fs/fuse/dev_uring.c
@@ -140,6 +140,33 @@ void fuse_uring_abort_end_requests(struct fuse_ring *ring) } } +bool fuse_uring_request_expired(struct fuse_conn *fc) +{ + struct fuse_ring *ring = fc->ring; + struct fuse_ring_queue *queue; + int qid; + + if (!ring) + return false; + + for (qid = 0; qid < ring->nr_queues; qid++) { + queue = READ_ONCE(ring->queues[qid]); + if (!queue) + continue; + + spin_lock(&queue->lock); + if (fuse_request_expired(fc, &queue->fuse_req_queue) || + fuse_request_expired(fc, &queue->fuse_req_bg_queue) || + fuse_fpq_processing_expired(fc, queue->fpq.processing)) { + spin_unlock(&queue->lock); + return true; + } + spin_unlock(&queue->lock); + } + + return false; +} + void fuse_uring_destruct(struct fuse_conn *fc) { struct fuse_ring *ring = fc->ring; @@ -211,7 +238,6 @@ static struct fuse_ring *fuse_uring_create(struct fuse_conn *fc) ring->nr_queues = nr_queues; ring->fc = fc; ring->max_payload_sz = max_payload_size; - atomic_set(&ring->queue_refs, 0); smp_store_release(&fc->ring, ring); spin_unlock(&fc->lock); @@ -726,8 +752,6 @@ static void fuse_uring_add_req_to_ring_ent(struct fuse_ring_ent *ent, struct fuse_req *req) { struct fuse_ring_queue *queue = ent->queue; - struct fuse_conn *fc = req->fm->fc; - struct fuse_iqueue *fiq = &fc->iq; lockdep_assert_held(&queue->lock); @@ -737,9 +761,7 @@ static void fuse_uring_add_req_to_ring_ent(struct fuse_ring_ent *ent, ent->state); } - spin_lock(&fiq->lock); clear_bit(FR_PENDING, &req->flags); - spin_unlock(&fiq->lock); ent->fuse_req = req; ent->state = FRRS_FUSE_REQ; list_move(&ent->list, &queue->ent_w_req_queue); @@ -1238,6 +1260,8 @@ void fuse_uring_queue_fuse_req(struct fuse_iqueue *fiq, struct fuse_req *req) if (unlikely(queue->stopped)) goto err_unlock; + set_bit(FR_URING, &req->flags); + req->ring_queue = queue; ent = list_first_entry_or_null(&queue->ent_avail_queue, struct fuse_ring_ent, list); if (ent) @@ -1276,6 +1300,8 @@ bool fuse_uring_queue_bq_req(struct fuse_req *req) return false; } + set_bit(FR_URING, &req->flags); + req->ring_queue = queue; list_add_tail(&req->list, &queue->fuse_req_bg_queue); ent = list_first_entry_or_null(&queue->ent_avail_queue, @@ -1306,6 +1332,13 @@ bool fuse_uring_queue_bq_req(struct fuse_req *req) return true; } +bool fuse_uring_remove_pending_req(struct fuse_req *req) +{ + struct fuse_ring_queue *queue = req->ring_queue; + + return fuse_remove_pending_req(req, &queue->lock); +} + static const struct fuse_iqueue_ops fuse_io_uring_ops = { /* should be send over io-uring as enhancement */ .send_forget = fuse_dev_queue_forget,
diff --git a/fs/fuse/dev_uring_i.h b/fs/fuse/dev_uring_i.h index 2102b3d..51a5639 100644 --- a/fs/fuse/dev_uring_i.h +++ b/fs/fuse/dev_uring_i.h
@@ -142,6 +142,8 @@ void fuse_uring_abort_end_requests(struct fuse_ring *ring); int fuse_uring_cmd(struct io_uring_cmd *cmd, unsigned int issue_flags); void fuse_uring_queue_fuse_req(struct fuse_iqueue *fiq, struct fuse_req *req); bool fuse_uring_queue_bq_req(struct fuse_req *req); +bool fuse_uring_remove_pending_req(struct fuse_req *req); +bool fuse_uring_request_expired(struct fuse_conn *fc); static inline void fuse_uring_abort(struct fuse_conn *fc) { @@ -172,12 +174,6 @@ static inline bool fuse_uring_ready(struct fuse_conn *fc) #else /* CONFIG_FUSE_IO_URING */ -struct fuse_ring; - -static inline void fuse_uring_create(struct fuse_conn *fc) -{ -} - static inline void fuse_uring_destruct(struct fuse_conn *fc) { } @@ -200,6 +196,16 @@ static inline bool fuse_uring_ready(struct fuse_conn *fc) return false; } +static inline bool fuse_uring_remove_pending_req(struct fuse_req *req) +{ + return false; +} + +static inline bool fuse_uring_request_expired(struct fuse_conn *fc) +{ + return false; +} + #endif /* CONFIG_FUSE_IO_URING */ #endif /* _FS_FUSE_DEV_URING_I_H */
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 85e4f89..83ac192 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c
@@ -370,7 +370,7 @@ int fuse_lookup_name(struct super_block *sb, u64 nodeid, const struct qstr *name *inode = NULL; err = -ENAMETOOLONG; - if (name->len > FUSE_NAME_MAX) + if (name->len > fm->fc->name_max) goto out; @@ -1137,6 +1137,9 @@ static int fuse_link(struct dentry *entry, struct inode *newdir, struct fuse_mount *fm = get_fuse_mount(inode); FUSE_ARGS(args); + if (fm->fc->no_link) + goto out; + memset(&inarg, 0, sizeof(inarg)); inarg.oldnodeid = get_node_id(inode); args.opcode = FUSE_LINK; @@ -1151,6 +1154,12 @@ static int fuse_link(struct dentry *entry, struct inode *newdir, else if (err == -EINTR) fuse_invalidate_attr(inode); + if (err == -ENOSYS) + fm->fc->no_link = 1; +out: + if (fm->fc->no_link) + return -EPERM; + return err; }
diff --git a/fs/fuse/fuse_dev_i.h b/fs/fuse/fuse_dev_i.h index 3b2bfe1..b3c2e32 100644 --- a/fs/fuse/fuse_dev_i.h +++ b/fs/fuse/fuse_dev_i.h
@@ -61,6 +61,10 @@ int fuse_copy_out_args(struct fuse_copy_state *cs, struct fuse_args *args, void fuse_dev_queue_forget(struct fuse_iqueue *fiq, struct fuse_forget_link *forget); void fuse_dev_queue_interrupt(struct fuse_iqueue *fiq, struct fuse_req *req); +bool fuse_remove_pending_req(struct fuse_req *req, spinlock_t *lock); + +bool fuse_request_expired(struct fuse_conn *fc, struct list_head *list); +bool fuse_fpq_processing_expired(struct fuse_conn *fc, struct list_head *processing); #endif
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index fee96fe..d56d4fd 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h
@@ -38,14 +38,34 @@ /** Bias for fi->writectr, meaning new writepages must not be sent */ #define FUSE_NOWRITE INT_MIN -/** It could be as large as PATH_MAX, but would that have any uses? */ -#define FUSE_NAME_MAX 1024 +/** Maximum length of a filename, not including terminating null */ + +/* maximum, small enough for FUSE_MIN_READ_BUFFER*/ +#define FUSE_NAME_LOW_MAX 1024 +/* maximum, but needs a request buffer > FUSE_MIN_READ_BUFFER */ +#define FUSE_NAME_MAX (PATH_MAX - 1) /** Number of dentries for each connection in the control filesystem */ #define FUSE_CTL_NUM_DENTRIES 5 +/* Frequency (in seconds) of request timeout checks, if opted into */ +#define FUSE_TIMEOUT_TIMER_FREQ 15 + +/** Frequency (in jiffies) of request timeout checks, if opted into */ +extern const unsigned long fuse_timeout_timer_freq; + /** Maximum of max_pages received in init_out */ extern unsigned int fuse_max_pages_limit; +/* + * Default timeout (in seconds) for the server to reply to a request + * before the connection is aborted, if no timeout was specified on mount. + */ +extern unsigned int fuse_default_req_timeout; +/* + * Max timeout (in seconds) for the server to reply to a request before + * the connection is aborted. + */ +extern unsigned int fuse_max_req_timeout; /** List of active connections */ extern struct list_head fuse_conn_list; @@ -378,6 +398,7 @@ struct fuse_io_priv { * FR_FINISHED: request is finished * FR_PRIVATE: request is on private list * FR_ASYNC: request is asynchronous + * FR_URING: request is handled through fuse-io-uring */ enum fuse_req_flag { FR_ISREPLY, @@ -392,6 +413,7 @@ enum fuse_req_flag { FR_FINISHED, FR_PRIVATE, FR_ASYNC, + FR_URING, }; /** @@ -441,7 +463,10 @@ struct fuse_req { #ifdef CONFIG_FUSE_IO_URING void *ring_entry; + void *ring_queue; #endif + /** When (in jiffies) the request was created */ + unsigned long create_time; }; struct fuse_iqueue; @@ -867,6 +892,9 @@ struct fuse_conn { /* Use pages instead of pointer for kernel I/O */ unsigned int use_pages_for_kvec_io:1; + /* Is link not implemented by fs? */ + unsigned int no_link:1; + /* Use io_uring for communication */ unsigned int io_uring; @@ -900,6 +928,9 @@ struct fuse_conn { /** Version counter for evict inode */ atomic64_t evict_ctr; + /* maximum file name length */ + u32 name_max; + /** Called on final put */ void (*release)(struct fuse_conn *); @@ -935,6 +966,15 @@ struct fuse_conn { /** uring connection information*/ struct fuse_ring *ring; #endif + + /** Only used if the connection opts into request timeouts */ + struct { + /* Worker for checking if any requests have timed out */ + struct delayed_work work; + + /* Request timeout (in jiffies). 0 = no timeout */ + unsigned int req_timeout; + } timeout; }; /* @@ -1216,6 +1256,9 @@ void fuse_request_end(struct fuse_req *req); void fuse_abort_conn(struct fuse_conn *fc); void fuse_wait_aborted(struct fuse_conn *fc); +/* Check if any requests timed out */ +void fuse_check_timeout(struct work_struct *work); + /** * Invalidate inode attributes */
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index e9db2cb..fd48e8d 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c
@@ -37,6 +37,9 @@ DEFINE_MUTEX(fuse_mutex); static int set_global_limit(const char *val, const struct kernel_param *kp); unsigned int fuse_max_pages_limit = 256; +/* default is no timeout */ +unsigned int fuse_default_req_timeout; +unsigned int fuse_max_req_timeout; unsigned max_user_bgreq; module_param_call(max_user_bgreq, set_global_limit, param_get_uint, @@ -979,6 +982,8 @@ void fuse_conn_init(struct fuse_conn *fc, struct fuse_mount *fm, fc->user_ns = get_user_ns(user_ns); fc->max_pages = FUSE_DEFAULT_MAX_PAGES_PER_REQ; fc->max_pages_limit = fuse_max_pages_limit; + fc->name_max = FUSE_NAME_LOW_MAX; + fc->timeout.req_timeout = 0; if (IS_ENABLED(CONFIG_FUSE_PASSTHROUGH)) fuse_backing_files_init(fc); @@ -1007,6 +1012,8 @@ void fuse_conn_put(struct fuse_conn *fc) if (IS_ENABLED(CONFIG_FUSE_DAX)) fuse_dax_conn_free(fc); + if (fc->timeout.req_timeout) + cancel_delayed_work_sync(&fc->timeout.work); if (fiq->ops->release) fiq->ops->release(fiq); put_pid_ns(fc->pid_ns); @@ -1257,6 +1264,34 @@ static void process_init_limits(struct fuse_conn *fc, struct fuse_init_out *arg) spin_unlock(&fc->bg_lock); } +static void set_request_timeout(struct fuse_conn *fc, unsigned int timeout) +{ + fc->timeout.req_timeout = secs_to_jiffies(timeout); + INIT_DELAYED_WORK(&fc->timeout.work, fuse_check_timeout); + queue_delayed_work(system_wq, &fc->timeout.work, + fuse_timeout_timer_freq); +} + +static void init_server_timeout(struct fuse_conn *fc, unsigned int timeout) +{ + if (!timeout && !fuse_max_req_timeout && !fuse_default_req_timeout) + return; + + if (!timeout) + timeout = fuse_default_req_timeout; + + if (fuse_max_req_timeout) { + if (timeout) + timeout = min(fuse_max_req_timeout, timeout); + else + timeout = fuse_max_req_timeout; + } + + timeout = max(FUSE_TIMEOUT_TIMER_FREQ, timeout); + + set_request_timeout(fc, timeout); +} + struct fuse_init_args { struct fuse_args args; struct fuse_init_in in; @@ -1275,6 +1310,7 @@ static void process_init_reply(struct fuse_mount *fm, struct fuse_args *args, ok = false; else { unsigned long ra_pages; + unsigned int timeout = 0; process_init_limits(fc, arg); @@ -1338,6 +1374,13 @@ static void process_init_reply(struct fuse_mount *fm, struct fuse_args *args, fc->max_pages = min_t(unsigned int, fc->max_pages_limit, max_t(unsigned int, arg->max_pages, 1)); + + /* + * PATH_MAX file names might need two pages for + * ops like rename + */ + if (fc->max_pages > 1) + fc->name_max = FUSE_NAME_MAX; } if (IS_ENABLED(CONFIG_FUSE_DAX)) { if (flags & FUSE_MAP_ALIGNMENT && @@ -1392,12 +1435,17 @@ static void process_init_reply(struct fuse_mount *fm, struct fuse_args *args, } if (flags & FUSE_OVER_IO_URING && fuse_uring_enabled()) fc->io_uring = 1; + + if (flags & FUSE_REQUEST_TIMEOUT) + timeout = arg->request_timeout; } else { ra_pages = fc->max_read / PAGE_SIZE; fc->no_lock = 1; fc->no_flock = 1; } + init_server_timeout(fc, timeout); + fm->sb->s_bdi->ra_pages = min(fm->sb->s_bdi->ra_pages, ra_pages); fc->minor = arg->minor; @@ -1439,7 +1487,8 @@ void fuse_send_init(struct fuse_mount *fm) FUSE_HANDLE_KILLPRIV_V2 | FUSE_SETXATTR_EXT | FUSE_INIT_EXT | FUSE_SECURITY_CTX | FUSE_CREATE_SUPP_GROUP | FUSE_HAS_EXPIRE_ONLY | FUSE_DIRECT_IO_ALLOW_MMAP | - FUSE_NO_EXPORT_SUPPORT | FUSE_HAS_RESEND | FUSE_ALLOW_IDMAP; + FUSE_NO_EXPORT_SUPPORT | FUSE_HAS_RESEND | FUSE_ALLOW_IDMAP | + FUSE_REQUEST_TIMEOUT; #ifdef CONFIG_FUSE_DAX if (fm->fc->dax) flags |= FUSE_MAP_ALIGNMENT;
diff --git a/fs/fuse/sysctl.c b/fs/fuse/sysctl.c index 63fb1e5..e2d921a 100644 --- a/fs/fuse/sysctl.c +++ b/fs/fuse/sysctl.c
@@ -13,6 +13,12 @@ static struct ctl_table_header *fuse_table_header; /* Bound by fuse_init_out max_pages, which is a u16 */ static unsigned int sysctl_fuse_max_pages_limit = 65535; +/* + * fuse_init_out request timeouts are u16. + * This goes up to ~18 hours, which is plenty for a timeout. + */ +static unsigned int sysctl_fuse_req_timeout_limit = 65535; + static const struct ctl_table fuse_sysctl_table[] = { { .procname = "max_pages_limit", @@ -23,6 +29,24 @@ static const struct ctl_table fuse_sysctl_table[] = { .extra1 = SYSCTL_ONE, .extra2 = &sysctl_fuse_max_pages_limit, }, + { + .procname = "default_request_timeout", + .data = &fuse_default_req_timeout, + .maxlen = sizeof(fuse_default_req_timeout), + .mode = 0644, + .proc_handler = proc_douintvec_minmax, + .extra1 = SYSCTL_ZERO, + .extra2 = &sysctl_fuse_req_timeout_limit, + }, + { + .procname = "max_request_timeout", + .data = &fuse_max_req_timeout, + .maxlen = sizeof(fuse_max_req_timeout), + .mode = 0644, + .proc_handler = proc_douintvec_minmax, + .extra1 = SYSCTL_ZERO, + .extra2 = &sysctl_fuse_req_timeout_limit, + }, }; int fuse_sysctl_register(void)
diff --git a/fs/gfs2/Kconfig b/fs/gfs2/Kconfig index be7f87a..7bd231d1 100644 --- a/fs/gfs2/Kconfig +++ b/fs/gfs2/Kconfig
@@ -4,7 +4,6 @@ select BUFFER_HEAD select FS_POSIX_ACL select CRC32 - select LIBCRC32C select QUOTACTL select FS_IOMAP help
diff --git a/fs/hostfs/hostfs.h b/fs/hostfs/hostfs.h index 8b39c15..15b2f09 100644 --- a/fs/hostfs/hostfs.h +++ b/fs/hostfs/hostfs.h
@@ -60,7 +60,7 @@ struct hostfs_stat { unsigned int uid; unsigned int gid; unsigned long long size; - struct hostfs_timespec atime, mtime, ctime; + struct hostfs_timespec atime, mtime, ctime, btime; unsigned int blksize; unsigned long long blocks; struct {
diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c index a2c6b90..702c413 100644 --- a/fs/hostfs/hostfs_kern.c +++ b/fs/hostfs/hostfs_kern.c
@@ -33,6 +33,7 @@ struct hostfs_inode_info { struct inode vfs_inode; struct mutex open_mutex; dev_t dev; + struct hostfs_timespec btime; }; static inline struct hostfs_inode_info *HOSTFS_I(struct inode *inode) @@ -547,6 +548,7 @@ static int hostfs_inode_set(struct inode *ino, void *data) } HOSTFS_I(ino)->dev = dev; + HOSTFS_I(ino)->btime = st->btime; ino->i_ino = st->ino; ino->i_mode = st->mode; return hostfs_inode_update(ino, st); @@ -557,7 +559,10 @@ static int hostfs_inode_test(struct inode *inode, void *data) const struct hostfs_stat *st = data; dev_t dev = MKDEV(st->dev.maj, st->dev.min); - return inode->i_ino == st->ino && HOSTFS_I(inode)->dev == dev; + return inode->i_ino == st->ino && HOSTFS_I(inode)->dev == dev && + (inode->i_mode & S_IFMT) == (st->mode & S_IFMT) && + HOSTFS_I(inode)->btime.tv_sec == st->btime.tv_sec && + HOSTFS_I(inode)->btime.tv_nsec == st->btime.tv_nsec; } static struct inode *hostfs_iget(struct super_block *sb, char *name)
diff --git a/fs/hostfs/hostfs_user.c b/fs/hostfs/hostfs_user.c index 97e9c40..3bcd9f3 100644 --- a/fs/hostfs/hostfs_user.c +++ b/fs/hostfs/hostfs_user.c
@@ -18,39 +18,48 @@ #include "hostfs.h" #include <utime.h> -static void stat64_to_hostfs(const struct stat64 *buf, struct hostfs_stat *p) +static void statx_to_hostfs(const struct statx *buf, struct hostfs_stat *p) { - p->ino = buf->st_ino; - p->mode = buf->st_mode; - p->nlink = buf->st_nlink; - p->uid = buf->st_uid; - p->gid = buf->st_gid; - p->size = buf->st_size; - p->atime.tv_sec = buf->st_atime; - p->atime.tv_nsec = 0; - p->ctime.tv_sec = buf->st_ctime; - p->ctime.tv_nsec = 0; - p->mtime.tv_sec = buf->st_mtime; - p->mtime.tv_nsec = 0; - p->blksize = buf->st_blksize; - p->blocks = buf->st_blocks; - p->rdev.maj = os_major(buf->st_rdev); - p->rdev.min = os_minor(buf->st_rdev); - p->dev.maj = os_major(buf->st_dev); - p->dev.min = os_minor(buf->st_dev); + p->ino = buf->stx_ino; + p->mode = buf->stx_mode; + p->nlink = buf->stx_nlink; + p->uid = buf->stx_uid; + p->gid = buf->stx_gid; + p->size = buf->stx_size; + p->atime.tv_sec = buf->stx_atime.tv_sec; + p->atime.tv_nsec = buf->stx_atime.tv_nsec; + p->ctime.tv_sec = buf->stx_ctime.tv_sec; + p->ctime.tv_nsec = buf->stx_ctime.tv_nsec; + p->mtime.tv_sec = buf->stx_mtime.tv_sec; + p->mtime.tv_nsec = buf->stx_mtime.tv_nsec; + if (buf->stx_mask & STATX_BTIME) { + p->btime.tv_sec = buf->stx_btime.tv_sec; + p->btime.tv_nsec = buf->stx_btime.tv_nsec; + } else { + memset(&p->btime, 0, sizeof(p->btime)); + } + p->blksize = buf->stx_blksize; + p->blocks = buf->stx_blocks; + p->rdev.maj = buf->stx_rdev_major; + p->rdev.min = buf->stx_rdev_minor; + p->dev.maj = buf->stx_dev_major; + p->dev.min = buf->stx_dev_minor; } int stat_file(const char *path, struct hostfs_stat *p, int fd) { - struct stat64 buf; + struct statx buf; + int flags = AT_SYMLINK_NOFOLLOW; if (fd >= 0) { - if (fstat64(fd, &buf) < 0) - return -errno; - } else if (lstat64(path, &buf) < 0) { - return -errno; + flags |= AT_EMPTY_PATH; + path = ""; } - stat64_to_hostfs(&buf, p); + + if ((statx(fd, path, flags, STATX_BASIC_STATS | STATX_BTIME, &buf)) < 0) + return -errno; + + statx_to_hostfs(&buf, p); return 0; }
diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c index a5ccba2..743a1d7 100644 --- a/fs/jbd2/journal.c +++ b/fs/jbd2/journal.c
@@ -197,7 +197,7 @@ static int kjournald2(void *arg) if (journal->j_commit_sequence != journal->j_commit_request) { jbd2_debug(1, "OK, requests differ\n"); write_unlock(&journal->j_state_lock); - del_timer_sync(&journal->j_commit_timer); + timer_delete_sync(&journal->j_commit_timer); jbd2_journal_commit_transaction(journal); write_lock(&journal->j_state_lock); goto loop; @@ -246,7 +246,7 @@ static int kjournald2(void *arg) goto loop; end_loop: - del_timer_sync(&journal->j_commit_timer); + timer_delete_sync(&journal->j_commit_timer); journal->j_task = NULL; wake_up(&journal->j_wait_done_commit); jbd2_debug(1, "Journal thread exiting.\n");
diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c index 4061e0b..bb815a0 100644 --- a/fs/jffs2/wbuf.c +++ b/fs/jffs2/wbuf.c
@@ -584,7 +584,7 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad) size_t retlen; /* Nothing to do if not write-buffering the flash. In particular, we shouldn't - del_timer() the timer we never initialised. */ + call timer_delete() on the timer we never initialised. */ if (!jffs2_is_writebuffered(c)) return 0;
diff --git a/fs/namespace.c b/fs/namespace.c index 6100e5b..14935a0 100644 --- a/fs/namespace.c +++ b/fs/namespace.c
@@ -2478,7 +2478,8 @@ struct vfsmount *clone_private_mount(const struct path *path) struct mount *old_mnt = real_mount(path->mnt); struct mount *new_mnt; - scoped_guard(rwsem_read, &namespace_sem) + guard(rwsem_read)(&namespace_sem); + if (IS_MNT_UNBINDABLE(old_mnt)) return ERR_PTR(-EINVAL); @@ -5326,8 +5327,10 @@ struct kstatmount { struct mnt_idmap *idmap; u64 mask; struct path root; - struct statmount sm; struct seq_file seq; + + /* Must be last --ends in a flexible-array member. */ + struct statmount sm; }; static u64 mnt_to_attr_flags(struct vfsmount *mnt)
diff --git a/fs/nfs/client.c b/fs/nfs/client.c index 3b0918a..02c916a 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c
@@ -546,6 +546,8 @@ int nfs_create_rpc_client(struct nfs_client *clp, args.flags |= RPC_CLNT_CREATE_NOPING; if (test_bit(NFS_CS_REUSEPORT, &clp->cl_flags)) args.flags |= RPC_CLNT_CREATE_REUSEPORT; + if (test_bit(NFS_CS_NETUNREACH_FATAL, &clp->cl_flags)) + args.flags |= RPC_CLNT_CREATE_NETUNREACH_FATAL; if (!IS_ERR(clp->cl_rpcclient)) return 0; @@ -709,6 +711,9 @@ static int nfs_init_server(struct nfs_server *server, if (ctx->flags & NFS_MOUNT_NORESVPORT) set_bit(NFS_CS_NORESVPORT, &cl_init.init_flags); + if (ctx->flags & NFS_MOUNT_NETUNREACH_FATAL) + __set_bit(NFS_CS_NETUNREACH_FATAL, &cl_init.init_flags); + /* Allocate or find a client reference we can use */ clp = nfs_get_client(&cl_init); if (IS_ERR(clp))
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c index 4db912f..8bdbc4d 100644 --- a/fs/nfs/delegation.c +++ b/fs/nfs/delegation.c
@@ -79,6 +79,7 @@ static void nfs_mark_return_delegation(struct nfs_server *server, struct nfs_delegation *delegation) { set_bit(NFS_DELEGATION_RETURN, &delegation->flags); + set_bit(NFS4SERV_DELEGRETURN, &server->delegation_flags); set_bit(NFS4CLNT_DELEGRETURN, &server->nfs_client->cl_state); } @@ -306,7 +307,8 @@ nfs_start_delegation_return_locked(struct nfs_inode *nfsi) if (delegation == NULL) goto out; spin_lock(&delegation->lock); - if (!test_and_set_bit(NFS_DELEGATION_RETURNING, &delegation->flags)) { + if (delegation->inode && + !test_and_set_bit(NFS_DELEGATION_RETURNING, &delegation->flags)) { clear_bit(NFS_DELEGATION_RETURN_DELAYED, &delegation->flags); /* Refcount matched in nfs_end_delegation_return() */ ret = nfs_get_delegation(delegation); @@ -330,14 +332,16 @@ nfs_start_delegation_return(struct nfs_inode *nfsi) } static void nfs_abort_delegation_return(struct nfs_delegation *delegation, - struct nfs_client *clp, int err) + struct nfs_server *server, int err) { - spin_lock(&delegation->lock); clear_bit(NFS_DELEGATION_RETURNING, &delegation->flags); if (err == -EAGAIN) { set_bit(NFS_DELEGATION_RETURN_DELAYED, &delegation->flags); - set_bit(NFS4CLNT_DELEGRETURN_DELAYED, &clp->cl_state); + set_bit(NFS4SERV_DELEGRETURN_DELAYED, + &server->delegation_flags); + set_bit(NFS4CLNT_DELEGRETURN_DELAYED, + &server->nfs_client->cl_state); } spin_unlock(&delegation->lock); } @@ -547,7 +551,7 @@ int nfs_inode_set_delegation(struct inode *inode, const struct cred *cred, */ static int nfs_end_delegation_return(struct inode *inode, struct nfs_delegation *delegation, int issync) { - struct nfs_client *clp = NFS_SERVER(inode)->nfs_client; + struct nfs_server *server = NFS_SERVER(inode); unsigned int mode = O_WRONLY | O_RDWR; int err = 0; @@ -569,11 +573,11 @@ static int nfs_end_delegation_return(struct inode *inode, struct nfs_delegation /* * Guard against state recovery */ - err = nfs4_wait_clnt_recover(clp); + err = nfs4_wait_clnt_recover(server->nfs_client); } if (err) { - nfs_abort_delegation_return(delegation, clp, err); + nfs_abort_delegation_return(delegation, server, err); goto out; } @@ -590,17 +594,6 @@ static bool nfs_delegation_need_return(struct nfs_delegation *delegation) if (test_and_clear_bit(NFS_DELEGATION_RETURN, &delegation->flags)) ret = true; - else if (test_bit(NFS_DELEGATION_RETURN_IF_CLOSED, &delegation->flags)) { - struct inode *inode; - - spin_lock(&delegation->lock); - inode = delegation->inode; - if (inode && list_empty(&NFS_I(inode)->open_files)) - ret = true; - spin_unlock(&delegation->lock); - } - if (ret) - clear_bit(NFS_DELEGATION_RETURN_IF_CLOSED, &delegation->flags); if (test_bit(NFS_DELEGATION_RETURNING, &delegation->flags) || test_bit(NFS_DELEGATION_RETURN_DELAYED, &delegation->flags) || test_bit(NFS_DELEGATION_REVOKED, &delegation->flags)) @@ -619,6 +612,9 @@ static int nfs_server_return_marked_delegations(struct nfs_server *server, struct nfs_delegation *place_holder_deleg = NULL; int err = 0; + if (!test_and_clear_bit(NFS4SERV_DELEGRETURN, + &server->delegation_flags)) + return 0; restart: /* * To avoid quadratic looping we hold a reference @@ -670,6 +666,7 @@ static int nfs_server_return_marked_delegations(struct nfs_server *server, cond_resched(); if (!err) goto restart; + set_bit(NFS4SERV_DELEGRETURN, &server->delegation_flags); set_bit(NFS4CLNT_DELEGRETURN, &server->nfs_client->cl_state); goto out; } @@ -684,6 +681,9 @@ static bool nfs_server_clear_delayed_delegations(struct nfs_server *server) struct nfs_delegation *d; bool ret = false; + if (!test_and_clear_bit(NFS4SERV_DELEGRETURN_DELAYED, + &server->delegation_flags)) + goto out; list_for_each_entry_rcu (d, &server->delegations, super_list) { if (!test_bit(NFS_DELEGATION_RETURN_DELAYED, &d->flags)) continue; @@ -691,6 +691,7 @@ static bool nfs_server_clear_delayed_delegations(struct nfs_server *server) clear_bit(NFS_DELEGATION_RETURN_DELAYED, &d->flags); ret = true; } +out: return ret; } @@ -878,11 +879,25 @@ int nfs4_inode_make_writeable(struct inode *inode) return nfs4_inode_return_delegation(inode); } -static void nfs_mark_return_if_closed_delegation(struct nfs_server *server, - struct nfs_delegation *delegation) +static void +nfs_mark_return_if_closed_delegation(struct nfs_server *server, + struct nfs_delegation *delegation) { - set_bit(NFS_DELEGATION_RETURN_IF_CLOSED, &delegation->flags); - set_bit(NFS4CLNT_DELEGRETURN, &server->nfs_client->cl_state); + struct inode *inode; + + if (test_bit(NFS_DELEGATION_RETURN, &delegation->flags) || + test_bit(NFS_DELEGATION_RETURN_IF_CLOSED, &delegation->flags)) + return; + spin_lock(&delegation->lock); + inode = delegation->inode; + if (!inode) + goto out; + if (list_empty(&NFS_I(inode)->open_files)) + nfs_mark_return_delegation(server, delegation); + else + set_bit(NFS_DELEGATION_RETURN_IF_CLOSED, &delegation->flags); +out: + spin_unlock(&delegation->lock); } static bool nfs_server_mark_return_all_delegations(struct nfs_server *server) @@ -1276,6 +1291,7 @@ static void nfs_mark_test_expired_delegation(struct nfs_server *server, return; clear_bit(NFS_DELEGATION_NEED_RECLAIM, &delegation->flags); set_bit(NFS_DELEGATION_TEST_EXPIRED, &delegation->flags); + set_bit(NFS4SERV_DELEGATION_EXPIRED, &server->delegation_flags); set_bit(NFS4CLNT_DELEGATION_EXPIRED, &server->nfs_client->cl_state); } @@ -1354,6 +1370,9 @@ static int nfs_server_reap_expired_delegations(struct nfs_server *server, nfs4_stateid stateid; unsigned long gen = ++server->delegation_gen; + if (!test_and_clear_bit(NFS4SERV_DELEGATION_EXPIRED, + &server->delegation_flags)) + return 0; restart: rcu_read_lock(); list_for_each_entry_rcu(delegation, &server->delegations, super_list) { @@ -1383,6 +1402,9 @@ static int nfs_server_reap_expired_delegations(struct nfs_server *server, goto restart; } nfs_inode_mark_test_expired_delegation(server,inode); + set_bit(NFS4SERV_DELEGATION_EXPIRED, &server->delegation_flags); + set_bit(NFS4CLNT_DELEGATION_EXPIRED, + &server->nfs_client->cl_state); iput(inode); return -EAGAIN; }
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index bc95748..bd23fc7 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c
@@ -666,6 +666,8 @@ static bool nfs_use_readdirplus(struct inode *dir, struct dir_context *ctx, { if (!nfs_server_capable(dir, NFS_CAP_READDIRPLUS)) return false; + if (NFS_SERVER(dir)->flags & NFS_MOUNT_FORCE_RDIRPLUS) + return true; if (ctx->pos == 0 || cache_hits + cache_misses > NFS_READDIR_CACHE_USAGE_THRESHOLD) return true;
diff --git a/fs/nfs/flexfilelayout/flexfilelayout.c b/fs/nfs/flexfilelayout/flexfilelayout.c index 98b45b6..61ad269 100644 --- a/fs/nfs/flexfilelayout/flexfilelayout.c +++ b/fs/nfs/flexfilelayout/flexfilelayout.c
@@ -1154,10 +1154,14 @@ static int ff_layout_async_handle_error_v4(struct rpc_task *task, rpc_wake_up(&tbl->slot_tbl_waitq); goto reset; /* RPC connection errors */ + case -ENETDOWN: + case -ENETUNREACH: + if (test_bit(NFS_CS_NETUNREACH_FATAL, &clp->cl_flags)) + return -NFS4ERR_FATAL_IOERROR; + fallthrough; case -ECONNREFUSED: case -EHOSTDOWN: case -EHOSTUNREACH: - case -ENETUNREACH: case -EIO: case -ETIMEDOUT: case -EPIPE: @@ -1183,6 +1187,7 @@ static int ff_layout_async_handle_error_v4(struct rpc_task *task, /* Retry all errors through either pNFS or MDS except for -EJUKEBOX */ static int ff_layout_async_handle_error_v3(struct rpc_task *task, + struct nfs_client *clp, struct pnfs_layout_segment *lseg, u32 idx) { @@ -1200,6 +1205,11 @@ static int ff_layout_async_handle_error_v3(struct rpc_task *task, case -EJUKEBOX: nfs_inc_stats(lseg->pls_layout->plh_inode, NFSIOS_DELAY); goto out_retry; + case -ENETDOWN: + case -ENETUNREACH: + if (test_bit(NFS_CS_NETUNREACH_FATAL, &clp->cl_flags)) + return -NFS4ERR_FATAL_IOERROR; + fallthrough; default: dprintk("%s DS connection error %d\n", __func__, task->tk_status); @@ -1234,7 +1244,7 @@ static int ff_layout_async_handle_error(struct rpc_task *task, switch (vers) { case 3: - return ff_layout_async_handle_error_v3(task, lseg, idx); + return ff_layout_async_handle_error_v3(task, clp, lseg, idx); case 4: return ff_layout_async_handle_error_v4(task, state, clp, lseg, idx); @@ -1264,6 +1274,7 @@ static void ff_layout_io_track_ds_error(struct pnfs_layout_segment *lseg, case -ECONNRESET: case -EHOSTDOWN: case -EHOSTUNREACH: + case -ENETDOWN: case -ENETUNREACH: case -EADDRINUSE: case -ENOBUFS: @@ -1337,6 +1348,9 @@ static int ff_layout_read_done_cb(struct rpc_task *task, return task->tk_status; case -EAGAIN: goto out_eagain; + case -NFS4ERR_FATAL_IOERROR: + task->tk_status = -EIO; + return 0; } return 0; @@ -1507,6 +1521,9 @@ static int ff_layout_write_done_cb(struct rpc_task *task, return task->tk_status; case -EAGAIN: return -EAGAIN; + case -NFS4ERR_FATAL_IOERROR: + task->tk_status = -EIO; + return 0; } if (hdr->res.verf->committed == NFS_FILE_SYNC || @@ -1551,6 +1568,9 @@ static int ff_layout_commit_done_cb(struct rpc_task *task, case -EAGAIN: rpc_restart_call_prepare(task); return -EAGAIN; + case -NFS4ERR_FATAL_IOERROR: + task->tk_status = -EIO; + return 0; } ff_layout_set_layoutcommit(data->inode, data->lseg, data->lwb);
diff --git a/fs/nfs/fs_context.c b/fs/nfs/fs_context.c index b069385..13f71ca 100644 --- a/fs/nfs/fs_context.c +++ b/fs/nfs/fs_context.c
@@ -50,6 +50,7 @@ enum nfs_param { Opt_clientaddr, Opt_cto, Opt_alignwrite, + Opt_fatal_neterrors, Opt_fg, Opt_fscache, Opt_fscache_flag, @@ -72,6 +73,8 @@ enum nfs_param { Opt_posix, Opt_proto, Opt_rdirplus, + Opt_rdirplus_none, + Opt_rdirplus_force, Opt_rdma, Opt_resvport, Opt_retrans, @@ -96,6 +99,20 @@ enum nfs_param { }; enum { + Opt_fatal_neterrors_default, + Opt_fatal_neterrors_enetunreach, + Opt_fatal_neterrors_none, +}; + +static const struct constant_table nfs_param_enums_fatal_neterrors[] = { + { "default", Opt_fatal_neterrors_default }, + { "ENETDOWN:ENETUNREACH", Opt_fatal_neterrors_enetunreach }, + { "ENETUNREACH:ENETDOWN", Opt_fatal_neterrors_enetunreach }, + { "none", Opt_fatal_neterrors_none }, + {} +}; + +enum { Opt_local_lock_all, Opt_local_lock_flock, Opt_local_lock_none, @@ -151,6 +168,8 @@ static const struct fs_parameter_spec nfs_fs_parameters[] = { fsparam_string("clientaddr", Opt_clientaddr), fsparam_flag_no("cto", Opt_cto), fsparam_flag_no("alignwrite", Opt_alignwrite), + fsparam_enum("fatal_neterrors", Opt_fatal_neterrors, + nfs_param_enums_fatal_neterrors), fsparam_flag ("fg", Opt_fg), fsparam_flag_no("fsc", Opt_fscache_flag), fsparam_string("fsc", Opt_fscache), @@ -174,7 +193,8 @@ static const struct fs_parameter_spec nfs_fs_parameters[] = { fsparam_u32 ("port", Opt_port), fsparam_flag_no("posix", Opt_posix), fsparam_string("proto", Opt_proto), - fsparam_flag_no("rdirplus", Opt_rdirplus), + fsparam_flag_no("rdirplus", Opt_rdirplus), // rdirplus|nordirplus + fsparam_string("rdirplus", Opt_rdirplus), // rdirplus=... fsparam_flag ("rdma", Opt_rdma), fsparam_flag_no("resvport", Opt_resvport), fsparam_u32 ("retrans", Opt_retrans), @@ -288,6 +308,12 @@ static const struct constant_table nfs_xprtsec_policies[] = { {} }; +static const struct constant_table nfs_rdirplus_tokens[] = { + { "none", Opt_rdirplus_none }, + { "force", Opt_rdirplus_force }, + {} +}; + /* * Sanity-check a server address provided by the mount command. * @@ -636,10 +662,25 @@ static int nfs_fs_context_parse_param(struct fs_context *fc, ctx->flags &= ~NFS_MOUNT_NOACL; break; case Opt_rdirplus: - if (result.negated) + if (result.negated) { + ctx->flags &= ~NFS_MOUNT_FORCE_RDIRPLUS; ctx->flags |= NFS_MOUNT_NORDIRPLUS; - else - ctx->flags &= ~NFS_MOUNT_NORDIRPLUS; + } else if (!param->string) { + ctx->flags &= ~(NFS_MOUNT_NORDIRPLUS | NFS_MOUNT_FORCE_RDIRPLUS); + } else { + switch (lookup_constant(nfs_rdirplus_tokens, param->string, -1)) { + case Opt_rdirplus_none: + ctx->flags &= ~NFS_MOUNT_FORCE_RDIRPLUS; + ctx->flags |= NFS_MOUNT_NORDIRPLUS; + break; + case Opt_rdirplus_force: + ctx->flags &= ~NFS_MOUNT_NORDIRPLUS; + ctx->flags |= NFS_MOUNT_FORCE_RDIRPLUS; + break; + default: + goto out_invalid_value; + } + } break; case Opt_sharecache: if (result.negated) @@ -872,6 +913,25 @@ static int nfs_fs_context_parse_param(struct fs_context *fc, goto out_of_bounds; ctx->nfs_server.max_connect = result.uint_32; break; + case Opt_fatal_neterrors: + trace_nfs_mount_assign(param->key, param->string); + switch (result.uint_32) { + case Opt_fatal_neterrors_default: + if (fc->net_ns != &init_net) + ctx->flags |= NFS_MOUNT_NETUNREACH_FATAL; + else + ctx->flags &= ~NFS_MOUNT_NETUNREACH_FATAL; + break; + case Opt_fatal_neterrors_enetunreach: + ctx->flags |= NFS_MOUNT_NETUNREACH_FATAL; + break; + case Opt_fatal_neterrors_none: + ctx->flags &= ~NFS_MOUNT_NETUNREACH_FATAL; + break; + default: + goto out_invalid_value; + } + break; case Opt_lookupcache: trace_nfs_mount_assign(param->key, param->string); switch (result.uint_32) { @@ -1651,6 +1711,9 @@ static int nfs_init_fs_context(struct fs_context *fc) ctx->xprtsec.cert_serial = TLS_NO_CERT; ctx->xprtsec.privkey_serial = TLS_NO_PRIVKEY; + if (fc->net_ns != &init_net) + ctx->flags |= NFS_MOUNT_NETUNREACH_FATAL; + fc->s_iflags |= SB_I_STABLE_WRITES; } fc->fs_private = ctx;
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 1aa67fc..119e447 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c
@@ -74,6 +74,8 @@ nfs_fattr_to_ino_t(struct nfs_fattr *fattr) int nfs_wait_bit_killable(struct wait_bit_key *key, int mode) { + if (unlikely(nfs_current_task_exiting())) + return -EINTR; schedule(); if (signal_pending_state(mode, current)) return -ERESTARTSYS;
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index 1ac1d3e..ec8d32d 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h
@@ -912,6 +912,11 @@ static inline u32 nfs_stateid_hash(nfs4_stateid *stateid) } #endif +static inline bool nfs_current_task_exiting(void) +{ + return (current->flags & PF_EXITING) != 0; +} + static inline bool nfs_error_is_fatal(int err) { switch (err) {
diff --git a/fs/nfs/nfs3client.c b/fs/nfs/nfs3client.c index b0c8a39..0d7310c 100644 --- a/fs/nfs/nfs3client.c +++ b/fs/nfs/nfs3client.c
@@ -120,6 +120,8 @@ struct nfs_client *nfs3_set_ds_client(struct nfs_server *mds_srv, if (mds_srv->flags & NFS_MOUNT_NORESVPORT) __set_bit(NFS_CS_NORESVPORT, &cl_init.init_flags); + if (test_bit(NFS_CS_NETUNREACH_FATAL, &mds_clp->cl_flags)) + __set_bit(NFS_CS_NETUNREACH_FATAL, &cl_init.init_flags); __set_bit(NFS_CS_DS, &cl_init.init_flags);
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c index 755ed3c..a4cb675 100644 --- a/fs/nfs/nfs3proc.c +++ b/fs/nfs/nfs3proc.c
@@ -39,7 +39,7 @@ nfs3_rpc_wrapper(struct rpc_clnt *clnt, struct rpc_message *msg, int flags) __set_current_state(TASK_KILLABLE|TASK_FREEZABLE_UNSAFE); schedule_timeout(NFS_JUKEBOX_RETRY_TIME); res = -ERESTARTSYS; - } while (!fatal_signal_pending(current)); + } while (!fatal_signal_pending(current) && !nfs_current_task_exiting()); return res; }
diff --git a/fs/nfs/nfs42proc.c b/fs/nfs/nfs42proc.c index 1924c4a..5cf52ec 100644 --- a/fs/nfs/nfs42proc.c +++ b/fs/nfs/nfs42proc.c
@@ -21,6 +21,8 @@ #define NFSDBG_FACILITY NFSDBG_PROC static int nfs42_do_offload_cancel_async(struct file *dst, nfs4_stateid *std); +static int nfs42_proc_offload_status(struct file *file, nfs4_stateid *stateid, + u64 *copied); static void nfs42_set_netaddr(struct file *filep, struct nfs42_netaddr *naddr) { @@ -173,6 +175,20 @@ int nfs42_proc_deallocate(struct file *filep, loff_t offset, loff_t len) return err; } +static void nfs4_copy_dequeue_callback(struct nfs_server *dst_server, + struct nfs_server *src_server, + struct nfs4_copy_state *copy) +{ + spin_lock(&dst_server->nfs_client->cl_lock); + list_del_init(©->copies); + spin_unlock(&dst_server->nfs_client->cl_lock); + if (dst_server != src_server) { + spin_lock(&src_server->nfs_client->cl_lock); + list_del_init(©->src_copies); + spin_unlock(&src_server->nfs_client->cl_lock); + } +} + static int handle_async_copy(struct nfs42_copy_res *res, struct nfs_server *dst_server, struct nfs_server *src_server, @@ -182,9 +198,12 @@ static int handle_async_copy(struct nfs42_copy_res *res, bool *restart) { struct nfs4_copy_state *copy, *tmp_copy = NULL, *iter; - int status = NFS4_OK; struct nfs_open_context *dst_ctx = nfs_file_open_context(dst); struct nfs_open_context *src_ctx = nfs_file_open_context(src); + struct nfs_client *clp = dst_server->nfs_client; + unsigned long timeout = 3 * HZ; + int status = NFS4_OK; + u64 copied; copy = kzalloc(sizeof(struct nfs4_copy_state), GFP_KERNEL); if (!copy) @@ -222,15 +241,12 @@ static int handle_async_copy(struct nfs42_copy_res *res, spin_unlock(&src_server->nfs_client->cl_lock); } - status = wait_for_completion_interruptible(©->completion); - spin_lock(&dst_server->nfs_client->cl_lock); - list_del_init(©->copies); - spin_unlock(&dst_server->nfs_client->cl_lock); - if (dst_server != src_server) { - spin_lock(&src_server->nfs_client->cl_lock); - list_del_init(©->src_copies); - spin_unlock(&src_server->nfs_client->cl_lock); - } +wait: + status = wait_for_completion_interruptible_timeout(©->completion, + timeout); + if (!status) + goto timeout; + nfs4_copy_dequeue_callback(dst_server, src_server, copy); if (status == -ERESTARTSYS) { goto out_cancel; } else if (copy->flags || copy->error == NFS4ERR_PARTNER_NO_AUTH) { @@ -240,6 +256,7 @@ static int handle_async_copy(struct nfs42_copy_res *res, } out: res->write_res.count = copy->count; + /* Copy out the updated write verifier provided by CB_OFFLOAD. */ memcpy(&res->write_res.verifier, ©->verf, sizeof(copy->verf)); status = -copy->error; @@ -251,6 +268,39 @@ static int handle_async_copy(struct nfs42_copy_res *res, if (!nfs42_files_from_same_server(src, dst)) nfs42_do_offload_cancel_async(src, src_stateid); goto out_free; +timeout: + timeout <<= 1; + if (timeout > (clp->cl_lease_time >> 1)) + timeout = clp->cl_lease_time >> 1; + status = nfs42_proc_offload_status(dst, ©->stateid, &copied); + if (status == -EINPROGRESS) + goto wait; + nfs4_copy_dequeue_callback(dst_server, src_server, copy); + switch (status) { + case 0: + /* The server recognized the copy stateid, so it hasn't + * rebooted. Don't overwrite the verifier returned in the + * COPY result. */ + res->write_res.count = copied; + goto out_free; + case -EREMOTEIO: + /* COPY operation failed on the server. */ + status = -EOPNOTSUPP; + res->write_res.count = copied; + goto out_free; + case -EBADF: + /* Server did not recognize the copy stateid. It has + * probably restarted and lost the plot. */ + res->write_res.count = 0; + status = -EOPNOTSUPP; + break; + case -EOPNOTSUPP: + /* RFC 7862 REQUIREs server to support OFFLOAD_STATUS when + * it has signed up for an async COPY, so server is not + * spec-compliant. */ + res->write_res.count = 0; + } + goto out_free; } static int process_copy_commit(struct file *dst, loff_t pos_dst, @@ -582,6 +632,108 @@ static int nfs42_do_offload_cancel_async(struct file *dst, return status; } +static int +_nfs42_proc_offload_status(struct nfs_server *server, struct file *file, + struct nfs42_offload_data *data) +{ + struct nfs_open_context *ctx = nfs_file_open_context(file); + struct rpc_message msg = { + .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OFFLOAD_STATUS], + .rpc_argp = &data->args, + .rpc_resp = &data->res, + .rpc_cred = ctx->cred, + }; + int status; + + status = nfs4_call_sync(server->client, server, &msg, + &data->args.osa_seq_args, + &data->res.osr_seq_res, 1); + trace_nfs4_offload_status(&data->args, status); + switch (status) { + case 0: + break; + + case -NFS4ERR_ADMIN_REVOKED: + case -NFS4ERR_BAD_STATEID: + case -NFS4ERR_OLD_STATEID: + /* + * Server does not recognize the COPY stateid. CB_OFFLOAD + * could have purged it, or server might have rebooted. + * Since COPY stateids don't have an associated inode, + * avoid triggering state recovery. + */ + status = -EBADF; + break; + case -NFS4ERR_NOTSUPP: + case -ENOTSUPP: + case -EOPNOTSUPP: + server->caps &= ~NFS_CAP_OFFLOAD_STATUS; + status = -EOPNOTSUPP; + break; + } + + return status; +} + +/** + * nfs42_proc_offload_status - Poll completion status of an async copy operation + * @dst: handle of file being copied into + * @stateid: copy stateid (from async COPY result) + * @copied: OUT: number of bytes copied so far + * + * Return values: + * %0: Server returned an NFS4_OK completion status + * %-EINPROGRESS: Server returned no completion status + * %-EREMOTEIO: Server returned an error completion status + * %-EBADF: Server did not recognize the copy stateid + * %-EOPNOTSUPP: Server does not support OFFLOAD_STATUS + * %-ERESTARTSYS: Wait interrupted by signal + * + * Other negative errnos indicate the client could not complete the + * request. + */ +static int +nfs42_proc_offload_status(struct file *dst, nfs4_stateid *stateid, u64 *copied) +{ + struct inode *inode = file_inode(dst); + struct nfs_server *server = NFS_SERVER(inode); + struct nfs4_exception exception = { + .inode = inode, + }; + struct nfs42_offload_data *data; + int status; + + if (!(server->caps & NFS_CAP_OFFLOAD_STATUS)) + return -EOPNOTSUPP; + + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + data->seq_server = server; + data->args.osa_src_fh = NFS_FH(inode); + memcpy(&data->args.osa_stateid, stateid, + sizeof(data->args.osa_stateid)); + exception.stateid = &data->args.osa_stateid; + do { + status = _nfs42_proc_offload_status(server, dst, data); + if (status == -EOPNOTSUPP) + goto out; + status = nfs4_handle_exception(server, status, &exception); + } while (exception.retry); + if (status) + goto out; + + *copied = data->res.osr_count; + if (!data->res.complete_count) + status = -EINPROGRESS; + else if (data->res.osr_complete != NFS_OK) + status = -EREMOTEIO; + +out: + kfree(data); + return status; +} + static int _nfs42_proc_copy_notify(struct file *src, struct file *dst, struct nfs42_copy_notify_args *args, struct nfs42_copy_notify_res *res)
diff --git a/fs/nfs/nfs42xdr.c b/fs/nfs/nfs42xdr.c index 5072d7e..b1b6634 100644 --- a/fs/nfs/nfs42xdr.c +++ b/fs/nfs/nfs42xdr.c
@@ -35,6 +35,11 @@ #define encode_offload_cancel_maxsz (op_encode_hdr_maxsz + \ XDR_QUADLEN(NFS4_STATEID_SIZE)) #define decode_offload_cancel_maxsz (op_decode_hdr_maxsz) +#define encode_offload_status_maxsz (op_encode_hdr_maxsz + \ + XDR_QUADLEN(NFS4_STATEID_SIZE)) +#define decode_offload_status_maxsz (op_decode_hdr_maxsz + \ + 2 /* osr_count */ + \ + 2 /* osr_complete */) #define encode_copy_notify_maxsz (op_encode_hdr_maxsz + \ XDR_QUADLEN(NFS4_STATEID_SIZE) + \ 1 + /* nl4_type */ \ @@ -143,6 +148,14 @@ decode_sequence_maxsz + \ decode_putfh_maxsz + \ decode_offload_cancel_maxsz) +#define NFS4_enc_offload_status_sz (compound_encode_hdr_maxsz + \ + encode_sequence_maxsz + \ + encode_putfh_maxsz + \ + encode_offload_status_maxsz) +#define NFS4_dec_offload_status_sz (compound_decode_hdr_maxsz + \ + decode_sequence_maxsz + \ + decode_putfh_maxsz + \ + decode_offload_status_maxsz) #define NFS4_enc_copy_notify_sz (compound_encode_hdr_maxsz + \ encode_sequence_maxsz + \ encode_putfh_maxsz + \ @@ -345,6 +358,14 @@ static void encode_offload_cancel(struct xdr_stream *xdr, encode_nfs4_stateid(xdr, &args->osa_stateid); } +static void encode_offload_status(struct xdr_stream *xdr, + const struct nfs42_offload_status_args *args, + struct compound_hdr *hdr) +{ + encode_op_hdr(xdr, OP_OFFLOAD_STATUS, decode_offload_status_maxsz, hdr); + encode_nfs4_stateid(xdr, &args->osa_stateid); +} + static void encode_copy_notify(struct xdr_stream *xdr, const struct nfs42_copy_notify_args *args, struct compound_hdr *hdr) @@ -570,6 +591,25 @@ static void nfs4_xdr_enc_offload_cancel(struct rpc_rqst *req, } /* + * Encode OFFLOAD_STATUS request + */ +static void nfs4_xdr_enc_offload_status(struct rpc_rqst *req, + struct xdr_stream *xdr, + const void *data) +{ + const struct nfs42_offload_status_args *args = data; + struct compound_hdr hdr = { + .minorversion = nfs4_xdr_minorversion(&args->osa_seq_args), + }; + + encode_compound_hdr(xdr, req, &hdr); + encode_sequence(xdr, &args->osa_seq_args, &hdr); + encode_putfh(xdr, args->osa_src_fh, &hdr); + encode_offload_status(xdr, args, &hdr); + encode_nops(&hdr); +} + +/* * Encode COPY_NOTIFY request */ static void nfs4_xdr_enc_copy_notify(struct rpc_rqst *req, @@ -921,6 +961,26 @@ static int decode_offload_cancel(struct xdr_stream *xdr, return decode_op_hdr(xdr, OP_OFFLOAD_CANCEL); } +static int decode_offload_status(struct xdr_stream *xdr, + struct nfs42_offload_status_res *res) +{ + ssize_t result; + int status; + + status = decode_op_hdr(xdr, OP_OFFLOAD_STATUS); + if (status) + return status; + /* osr_count */ + if (xdr_stream_decode_u64(xdr, &res->osr_count) < 0) + return -EIO; + /* osr_complete<1> */ + result = xdr_stream_decode_uint32_array(xdr, &res->osr_complete, 1); + if (result < 0) + return -EIO; + res->complete_count = result; + return 0; +} + static int decode_copy_notify(struct xdr_stream *xdr, struct nfs42_copy_notify_res *res) { @@ -1371,6 +1431,32 @@ static int nfs4_xdr_dec_offload_cancel(struct rpc_rqst *rqstp, } /* + * Decode OFFLOAD_STATUS response + */ +static int nfs4_xdr_dec_offload_status(struct rpc_rqst *rqstp, + struct xdr_stream *xdr, + void *data) +{ + struct nfs42_offload_status_res *res = data; + struct compound_hdr hdr; + int status; + + status = decode_compound_hdr(xdr, &hdr); + if (status) + goto out; + status = decode_sequence(xdr, &res->osr_seq_res, rqstp); + if (status) + goto out; + status = decode_putfh(xdr); + if (status) + goto out; + status = decode_offload_status(xdr, res); + +out: + return status; +} + +/* * Decode COPY_NOTIFY response */ static int nfs4_xdr_dec_copy_notify(struct rpc_rqst *rqstp,
diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c index 83378f6..162c85a 100644 --- a/fs/nfs/nfs4client.c +++ b/fs/nfs/nfs4client.c
@@ -233,6 +233,8 @@ struct nfs_client *nfs4_alloc_client(const struct nfs_client_initdata *cl_init) __set_bit(NFS_CS_NO_RETRANS_TIMEOUT, &clp->cl_flags); if (test_bit(NFS_CS_PNFS, &cl_init->init_flags)) __set_bit(NFS_CS_PNFS, &clp->cl_flags); + if (test_bit(NFS_CS_NETUNREACH_FATAL, &cl_init->init_flags)) + __set_bit(NFS_CS_NETUNREACH_FATAL, &clp->cl_flags); /* * Set up the connection to the server before we add add to the * global list. @@ -937,6 +939,9 @@ static int nfs4_set_client(struct nfs_server *server, __set_bit(NFS_CS_TSM_POSSIBLE, &cl_init.init_flags); server->port = rpc_get_port((struct sockaddr *)addr); + if (server->flags & NFS_MOUNT_NETUNREACH_FATAL) + __set_bit(NFS_CS_NETUNREACH_FATAL, &cl_init.init_flags); + /* Allocate or find a client reference we can use */ clp = nfs_get_client(&cl_init); if (IS_ERR(clp)) @@ -1011,6 +1016,8 @@ struct nfs_client *nfs4_set_ds_client(struct nfs_server *mds_srv, if (mds_srv->flags & NFS_MOUNT_NORESVPORT) __set_bit(NFS_CS_NORESVPORT, &cl_init.init_flags); + if (test_bit(NFS_CS_NETUNREACH_FATAL, &mds_clp->cl_flags)) + __set_bit(NFS_CS_NETUNREACH_FATAL, &cl_init.init_flags); __set_bit(NFS_CS_PNFS, &cl_init.init_flags); cl_init.max_connect = NFS_MAX_TRANSPORTS;
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 70c8ea9..970f28d 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c
@@ -195,6 +195,9 @@ static int nfs4_map_errors(int err) return -EBUSY; case -NFS4ERR_NOT_SAME: return -ENOTSYNC; + case -ENETDOWN: + case -ENETUNREACH: + break; default: dprintk("%s could not handle NFSv4 error %d\n", __func__, -err); @@ -443,6 +446,8 @@ static int nfs4_delay_killable(long *timeout) { might_sleep(); + if (unlikely(nfs_current_task_exiting())) + return -EINTR; __set_current_state(TASK_KILLABLE|TASK_FREEZABLE_UNSAFE); schedule_timeout(nfs4_update_delay(timeout)); if (!__fatal_signal_pending(current)) @@ -454,6 +459,8 @@ static int nfs4_delay_interruptible(long *timeout) { might_sleep(); + if (unlikely(nfs_current_task_exiting())) + return -EINTR; __set_current_state(TASK_INTERRUPTIBLE|TASK_FREEZABLE_UNSAFE); schedule_timeout(nfs4_update_delay(timeout)); if (!signal_pending(current)) @@ -1774,7 +1781,8 @@ static void nfs_set_open_stateid_locked(struct nfs4_state *state, rcu_read_unlock(); trace_nfs4_open_stateid_update_wait(state->inode, stateid, 0); - if (!fatal_signal_pending(current)) { + if (!fatal_signal_pending(current) && + !nfs_current_task_exiting()) { if (schedule_timeout(5*HZ) == 0) status = -EAGAIN; else @@ -3576,7 +3584,7 @@ static bool nfs4_refresh_open_old_stateid(nfs4_stateid *dst, write_sequnlock(&state->seqlock); trace_nfs4_close_stateid_update_wait(state->inode, dst, 0); - if (fatal_signal_pending(current)) + if (fatal_signal_pending(current) || nfs_current_task_exiting()) status = -EINTR; else if (schedule_timeout(5*HZ) != 0) @@ -9594,7 +9602,7 @@ static void nfs41_sequence_call_done(struct rpc_task *task, void *data) return; trace_nfs4_sequence(clp, task->tk_status); - if (task->tk_status < 0 && !task->tk_client->cl_shutdown) { + if (task->tk_status < 0 && clp->cl_cons_state >= 0) { dprintk("%s ERROR %d\n", __func__, task->tk_status); if (refcount_read(&clp->cl_count) == 1) return; @@ -10798,7 +10806,8 @@ static const struct nfs4_minor_version_ops nfs_v4_2_minor_ops = { | NFS_CAP_CLONE | NFS_CAP_LAYOUTERROR | NFS_CAP_READ_PLUS - | NFS_CAP_MOVEABLE, + | NFS_CAP_MOVEABLE + | NFS_CAP_OFFLOAD_STATUS, .init_client = nfs41_init_client, .shutdown_client = nfs41_shutdown_client, .match_stateid = nfs41_match_stateid,
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index 542cdf7..7612e97 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c
@@ -1198,7 +1198,7 @@ void nfs4_schedule_state_manager(struct nfs_client *clp) struct rpc_clnt *clnt = clp->cl_rpcclient; bool swapon = false; - if (clnt->cl_shutdown) + if (clp->cl_cons_state < 0) return; set_bit(NFS4CLNT_RUN_MANAGER, &clp->cl_state); @@ -1403,7 +1403,7 @@ int nfs4_schedule_stateid_recovery(const struct nfs_server *server, struct nfs4_ dprintk("%s: scheduling stateid recovery for server %s\n", __func__, clp->cl_hostname); nfs4_schedule_state_manager(clp); - return 0; + return clp->cl_cons_state < 0 ? clp->cl_cons_state : 0; } EXPORT_SYMBOL_GPL(nfs4_schedule_stateid_recovery); @@ -2739,7 +2739,15 @@ static void nfs4_state_manager(struct nfs_client *clp) pr_warn_ratelimited("NFS: state manager%s%s failed on NFSv4 server %s" " with error %d\n", section_sep, section, clp->cl_hostname, -status); - ssleep(1); + switch (status) { + case -ENETDOWN: + case -ENETUNREACH: + nfs_mark_client_ready(clp, -EIO); + break; + default: + ssleep(1); + break; + } out_drain: memalloc_nofs_restore(memflags); nfs4_end_drain_session(clp);
diff --git a/fs/nfs/nfs4trace.h b/fs/nfs/nfs4trace.h index 22c9733..bc67fe6 100644 --- a/fs/nfs/nfs4trace.h +++ b/fs/nfs/nfs4trace.h
@@ -2608,7 +2608,7 @@ TRACE_EVENT(nfs4_copy_notify, ) ); -TRACE_EVENT(nfs4_offload_cancel, +DECLARE_EVENT_CLASS(nfs4_offload_class, TP_PROTO( const struct nfs42_offload_status_args *args, int error @@ -2640,6 +2640,15 @@ TRACE_EVENT(nfs4_offload_cancel, __entry->stateid_seq, __entry->stateid_hash ) ); +#define DEFINE_NFS4_OFFLOAD_EVENT(name) \ + DEFINE_EVENT(nfs4_offload_class, name, \ + TP_PROTO( \ + const struct nfs42_offload_status_args *args, \ + int error \ + ), \ + TP_ARGS(args, error)) +DEFINE_NFS4_OFFLOAD_EVENT(nfs4_offload_cancel); +DEFINE_NFS4_OFFLOAD_EVENT(nfs4_offload_status); DECLARE_EVENT_CLASS(nfs4_xattr_event, TP_PROTO(
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index e8ac3f6..55bef5f 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c
@@ -82,9 +82,8 @@ static int decode_layoutget(struct xdr_stream *xdr, struct rpc_rqst *req, * we currently use size 2 (u64) out of (NFS4_OPAQUE_LIMIT >> 2) */ #define pagepad_maxsz (1) -#define open_owner_id_maxsz (1 + 2 + 1 + 1 + 2) -#define lock_owner_id_maxsz (1 + 1 + 4) -#define decode_lockowner_maxsz (1 + XDR_QUADLEN(IDMAP_NAMESZ)) +#define open_owner_id_maxsz (2 + 1 + 2 + 2) +#define lock_owner_id_maxsz (2 + 1 + 2) #define compound_encode_hdr_maxsz (3 + (NFS4_MAXTAGLEN >> 2)) #define compound_decode_hdr_maxsz (3 + (NFS4_MAXTAGLEN >> 2)) #define op_encode_hdr_maxsz (1) @@ -185,7 +184,7 @@ static int decode_layoutget(struct xdr_stream *xdr, struct rpc_rqst *req, #define encode_claim_null_maxsz (1 + nfs4_name_maxsz) #define encode_open_maxsz (op_encode_hdr_maxsz + \ 2 + encode_share_access_maxsz + 2 + \ - open_owner_id_maxsz + \ + 1 + open_owner_id_maxsz + \ encode_opentype_maxsz + \ encode_claim_null_maxsz) #define decode_space_limit_maxsz (3) @@ -255,13 +254,14 @@ static int decode_layoutget(struct xdr_stream *xdr, struct rpc_rqst *req, #define encode_link_maxsz (op_encode_hdr_maxsz + \ nfs4_name_maxsz) #define decode_link_maxsz (op_decode_hdr_maxsz + decode_change_info_maxsz) -#define encode_lockowner_maxsz (7) +#define encode_lockowner_maxsz (2 + 1 + lock_owner_id_maxsz) + #define encode_lock_maxsz (op_encode_hdr_maxsz + \ 7 + \ 1 + encode_stateid_maxsz + 1 + \ encode_lockowner_maxsz) #define decode_lock_denied_maxsz \ - (8 + decode_lockowner_maxsz) + (2 + 2 + 1 + 2 + 1 + lock_owner_id_maxsz) #define decode_lock_maxsz (op_decode_hdr_maxsz + \ decode_lock_denied_maxsz) #define encode_lockt_maxsz (op_encode_hdr_maxsz + 5 + \ @@ -617,7 +617,7 @@ static int decode_layoutget(struct xdr_stream *xdr, struct rpc_rqst *req, encode_lockowner_maxsz) #define NFS4_dec_release_lockowner_sz \ (compound_decode_hdr_maxsz + \ - decode_lockowner_maxsz) + decode_release_lockowner_maxsz) #define NFS4_enc_access_sz (compound_encode_hdr_maxsz + \ encode_sequence_maxsz + \ encode_putfh_maxsz + \ @@ -1412,7 +1412,7 @@ static inline void encode_openhdr(struct xdr_stream *xdr, const struct nfs_opena __be32 *p; /* * opcode 4, seqid 4, share_access 4, share_deny 4, clientid 8, ownerlen 4, - * owner 4 = 32 + * owner 28 */ encode_nfs4_seqid(xdr, arg->seqid); encode_share_access(xdr, arg->share_access); @@ -5077,7 +5077,7 @@ static int decode_link(struct xdr_stream *xdr, struct nfs4_change_info *cinfo) /* * We create the owner, so we know a proper owner.id length is 4. */ -static int decode_lock_denied (struct xdr_stream *xdr, struct file_lock *fl) +static int decode_lock_denied(struct xdr_stream *xdr, struct file_lock *fl) { uint64_t offset, length, clientid; __be32 *p; @@ -7702,6 +7702,7 @@ const struct rpc_procinfo nfs4_procedures[] = { PROC42(CLONE, enc_clone, dec_clone), PROC42(COPY, enc_copy, dec_copy), PROC42(OFFLOAD_CANCEL, enc_offload_cancel, dec_offload_cancel), + PROC42(OFFLOAD_STATUS, enc_offload_status, dec_offload_status), PROC42(COPY_NOTIFY, enc_copy_notify, dec_copy_notify), PROC(LOOKUPP, enc_lookupp, dec_lookupp), PROC42(LAYOUTERROR, enc_layouterror, dec_layouterror),
diff --git a/fs/nfs/super.c b/fs/nfs/super.c index aeb715b..9eea9e6 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c
@@ -454,8 +454,12 @@ static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss, { NFS_MOUNT_NONLM, ",nolock", "" }, { NFS_MOUNT_NOACL, ",noacl", "" }, { NFS_MOUNT_NORDIRPLUS, ",nordirplus", "" }, + { NFS_MOUNT_FORCE_RDIRPLUS, ",rdirplus=force", "" }, { NFS_MOUNT_UNSHARED, ",nosharecache", "" }, { NFS_MOUNT_NORESVPORT, ",noresvport", "" }, + { NFS_MOUNT_NETUNREACH_FATAL, + ",fatal_neterrors=ENETDOWN:ENETUNREACH", + ",fatal_neterrors=none" }, { 0, NULL, NULL } }; const struct proc_nfs_info *nfs_infop;
diff --git a/fs/nfs/sysfs.c b/fs/nfs/sysfs.c index 7b59a40..37cb2b7 100644 --- a/fs/nfs/sysfs.c +++ b/fs/nfs/sysfs.c
@@ -14,6 +14,7 @@ #include <linux/rcupdate.h> #include <linux/lockd/lockd.h> +#include "internal.h" #include "nfs4_fs.h" #include "netns.h" #include "sysfs.h" @@ -228,6 +229,25 @@ static void shutdown_client(struct rpc_clnt *clnt) rpc_cancel_tasks(clnt, -EIO, shutdown_match_client, NULL); } +/* + * Shut down the nfs_client only once all the superblocks + * have been shut down. + */ +static void shutdown_nfs_client(struct nfs_client *clp) +{ + struct nfs_server *server; + rcu_read_lock(); + list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) { + if (!(server->flags & NFS_MOUNT_SHUTDOWN)) { + rcu_read_unlock(); + return; + } + } + rcu_read_unlock(); + nfs_mark_client_ready(clp, -EIO); + shutdown_client(clp->cl_rpcclient); +} + static ssize_t shutdown_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) @@ -259,7 +279,6 @@ shutdown_store(struct kobject *kobj, struct kobj_attribute *attr, server->flags |= NFS_MOUNT_SHUTDOWN; shutdown_client(server->client); - shutdown_client(server->nfs_client->cl_rpcclient); if (!IS_ERR(server->client_acl)) shutdown_client(server->client_acl); @@ -267,11 +286,44 @@ shutdown_store(struct kobject *kobj, struct kobj_attribute *attr, if (server->nlm_host) shutdown_client(server->nlm_host->h_rpcclnt); out: + shutdown_nfs_client(server->nfs_client); return count; } static struct kobj_attribute nfs_sysfs_attr_shutdown = __ATTR_RW(shutdown); +#if IS_ENABLED(CONFIG_NFS_V4_1) +static ssize_t +implid_domain_show(struct kobject *kobj, struct kobj_attribute *attr, + char *buf) +{ + struct nfs_server *server = container_of(kobj, struct nfs_server, kobj); + struct nfs41_impl_id *impl_id = server->nfs_client->cl_implid; + + if (!impl_id || strlen(impl_id->domain) == 0) + return 0; //sysfs_emit(buf, ""); + return sysfs_emit(buf, "%s\n", impl_id->domain); +} + +static struct kobj_attribute nfs_sysfs_attr_implid_domain = __ATTR_RO(implid_domain); + + +static ssize_t +implid_name_show(struct kobject *kobj, struct kobj_attribute *attr, + char *buf) +{ + struct nfs_server *server = container_of(kobj, struct nfs_server, kobj); + struct nfs41_impl_id *impl_id = server->nfs_client->cl_implid; + + if (!impl_id || strlen(impl_id->name) == 0) + return 0; //sysfs_emit(buf, ""); + return sysfs_emit(buf, "%s\n", impl_id->name); +} + +static struct kobj_attribute nfs_sysfs_attr_implid_name = __ATTR_RO(implid_name); + +#endif /* IS_ENABLED(CONFIG_NFS_V4_1) */ + #define RPC_CLIENT_NAME_SIZE 64 void nfs_sysfs_link_rpc_client(struct nfs_server *server, @@ -309,6 +361,32 @@ static struct kobj_type nfs_sb_ktype = { .child_ns_type = nfs_netns_object_child_ns_type, }; +#if IS_ENABLED(CONFIG_NFS_V4_1) +static void nfs_sysfs_add_nfsv41_server(struct nfs_server *server) +{ + int ret; + + if (!server->nfs_client->cl_implid) + return; + + ret = sysfs_create_file_ns(&server->kobj, &nfs_sysfs_attr_implid_domain.attr, + nfs_netns_server_namespace(&server->kobj)); + if (ret < 0) + pr_warn("NFS: sysfs_create_file_ns for server-%d failed (%d)\n", + server->s_sysfs_id, ret); + + ret = sysfs_create_file_ns(&server->kobj, &nfs_sysfs_attr_implid_name.attr, + nfs_netns_server_namespace(&server->kobj)); + if (ret < 0) + pr_warn("NFS: sysfs_create_file_ns for server-%d failed (%d)\n", + server->s_sysfs_id, ret); +} +#else /* CONFIG_NFS_V4_1 */ +static inline void nfs_sysfs_add_nfsv41_server(struct nfs_server *server) +{ +} +#endif /* CONFIG_NFS_V4_1 */ + void nfs_sysfs_add_server(struct nfs_server *server) { int ret; @@ -325,6 +403,8 @@ void nfs_sysfs_add_server(struct nfs_server *server) if (ret < 0) pr_warn("NFS: sysfs_create_file_ns for server-%d failed (%d)\n", server->s_sysfs_id, ret); + + nfs_sysfs_add_nfsv41_server(server); } EXPORT_SYMBOL_GPL(nfs_sysfs_add_server);
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index aa3d8be..23df8b2 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c
@@ -579,8 +579,10 @@ static struct nfs_page *nfs_lock_and_join_requests(struct folio *folio) while (!nfs_lock_request(head)) { ret = nfs_wait_on_request(head); - if (ret < 0) + if (ret < 0) { + nfs_release_request(head); return ERR_PTR(ret); + } } /* Ensure that nobody removed the request before we locked it */
diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c index 3a202e5..83970d97 100644 --- a/fs/nilfs2/segment.c +++ b/fs/nilfs2/segment.c
@@ -2424,7 +2424,7 @@ static void nilfs_segctor_accept(struct nilfs_sc_info *sci) * the area protected by sc_state_lock. */ if (thread_is_alive) - del_timer_sync(&sci->sc_timer); + timer_delete_sync(&sci->sc_timer); } /**
diff --git a/fs/ntfs3/attrib.c b/fs/ntfs3/attrib.c index af94e37..e946f75 100644 --- a/fs/ntfs3/attrib.c +++ b/fs/ntfs3/attrib.c
@@ -2664,8 +2664,9 @@ int attr_set_compress(struct ntfs_inode *ni, bool compr) attr->nres.run_off = cpu_to_le16(run_off); } - /* Update data attribute flags. */ + /* Update attribute flags. */ if (compr) { + attr->flags &= ~ATTR_FLAG_SPARSED; attr->flags |= ATTR_FLAG_COMPRESSED; attr->nres.c_unit = NTFS_LZNT_CUNIT; } else {
diff --git a/fs/ntfs3/file.c b/fs/ntfs3/file.c index 3f96a11..9b6a3f8 100644 --- a/fs/ntfs3/file.c +++ b/fs/ntfs3/file.c
@@ -101,8 +101,26 @@ int ntfs_fileattr_set(struct mnt_idmap *idmap, struct dentry *dentry, /* Allowed to change compression for empty files and for directories only. */ if (!is_dedup(ni) && !is_encrypted(ni) && (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode))) { - /* Change compress state. */ - int err = ni_set_compress(inode, flags & FS_COMPR_FL); + int err = 0; + struct address_space *mapping = inode->i_mapping; + + /* write out all data and wait. */ + filemap_invalidate_lock(mapping); + err = filemap_write_and_wait(mapping); + + if (err >= 0) { + /* Change compress state. */ + bool compr = flags & FS_COMPR_FL; + err = ni_set_compress(inode, compr); + + /* For files change a_ops too. */ + if (!err) + mapping->a_ops = compr ? &ntfs_aops_cmpr : + &ntfs_aops; + } + + filemap_invalidate_unlock(mapping); + if (err) return err; } @@ -412,6 +430,7 @@ static int ntfs_extend(struct inode *inode, loff_t pos, size_t count, } if (extend_init && !is_compressed(ni)) { + WARN_ON(ni->i_valid >= pos); err = ntfs_extend_initialized_size(file, ni, ni->i_valid, pos); if (err) goto out; @@ -1228,21 +1247,22 @@ static ssize_t ntfs_file_write_iter(struct kiocb *iocb, struct iov_iter *from) ssize_t ret; int err; - err = check_write_restriction(inode); - if (err) - return err; - - if (is_compressed(ni) && (iocb->ki_flags & IOCB_DIRECT)) { - ntfs_inode_warn(inode, "direct i/o + compressed not supported"); - return -EOPNOTSUPP; - } - if (!inode_trylock(inode)) { if (iocb->ki_flags & IOCB_NOWAIT) return -EAGAIN; inode_lock(inode); } + ret = check_write_restriction(inode); + if (ret) + goto out; + + if (is_compressed(ni) && (iocb->ki_flags & IOCB_DIRECT)) { + ntfs_inode_warn(inode, "direct i/o + compressed not supported"); + ret = -EOPNOTSUPP; + goto out; + } + ret = generic_write_checks(iocb, from); if (ret <= 0) goto out;
diff --git a/fs/ntfs3/frecord.c b/fs/ntfs3/frecord.c index 5df6a0b..b7a8320 100644 --- a/fs/ntfs3/frecord.c +++ b/fs/ntfs3/frecord.c
@@ -281,63 +281,6 @@ struct ATTRIB *ni_enum_attr_ex(struct ntfs_inode *ni, struct ATTRIB *attr, } /* - * ni_load_attr - Load attribute that contains given VCN. - */ -struct ATTRIB *ni_load_attr(struct ntfs_inode *ni, enum ATTR_TYPE type, - const __le16 *name, u8 name_len, CLST vcn, - struct mft_inode **pmi) -{ - struct ATTR_LIST_ENTRY *le; - struct ATTRIB *attr; - struct mft_inode *mi; - struct ATTR_LIST_ENTRY *next; - - if (!ni->attr_list.size) { - if (pmi) - *pmi = &ni->mi; - return mi_find_attr(ni, &ni->mi, NULL, type, name, name_len, - NULL); - } - - le = al_find_ex(ni, NULL, type, name, name_len, NULL); - if (!le) - return NULL; - - /* - * Unfortunately ATTR_LIST_ENTRY contains only start VCN. - * So to find the ATTRIB segment that contains 'vcn' we should - * enumerate some entries. - */ - if (vcn) { - for (;; le = next) { - next = al_find_ex(ni, le, type, name, name_len, NULL); - if (!next || le64_to_cpu(next->vcn) > vcn) - break; - } - } - - if (ni_load_mi(ni, le, &mi)) - return NULL; - - if (pmi) - *pmi = mi; - - attr = mi_find_attr(ni, mi, NULL, type, name, name_len, &le->id); - if (!attr) - return NULL; - - if (!attr->non_res) - return attr; - - if (le64_to_cpu(attr->nres.svcn) <= vcn && - vcn <= le64_to_cpu(attr->nres.evcn)) - return attr; - - _ntfs_bad_inode(&ni->vfs_inode); - return NULL; -} - -/* * ni_load_all_mi - Load all subrecords. */ int ni_load_all_mi(struct ntfs_inode *ni) @@ -3434,10 +3377,12 @@ int ni_set_compress(struct inode *inode, bool compr) } ni->std_fa = std->fa; - if (compr) + if (compr) { + std->fa &= ~FILE_ATTRIBUTE_SPARSE_FILE; std->fa |= FILE_ATTRIBUTE_COMPRESSED; - else + } else { std->fa &= ~FILE_ATTRIBUTE_COMPRESSED; + } if (ni->std_fa != std->fa) { ni->std_fa = std->fa;
diff --git a/fs/ntfs3/fsntfs.c b/fs/ntfs3/fsntfs.c index 938d351..df81f1f 100644 --- a/fs/ntfs3/fsntfs.c +++ b/fs/ntfs3/fsntfs.c
@@ -1035,34 +1035,6 @@ struct buffer_head *ntfs_bread(struct super_block *sb, sector_t block) return NULL; } -int ntfs_sb_read(struct super_block *sb, u64 lbo, size_t bytes, void *buffer) -{ - struct block_device *bdev = sb->s_bdev; - u32 blocksize = sb->s_blocksize; - u64 block = lbo >> sb->s_blocksize_bits; - u32 off = lbo & (blocksize - 1); - u32 op = blocksize - off; - - for (; bytes; block += 1, off = 0, op = blocksize) { - struct buffer_head *bh = __bread(bdev, block, blocksize); - - if (!bh) - return -EIO; - - if (op > bytes) - op = bytes; - - memcpy(buffer, bh->b_data + off, op); - - put_bh(bh); - - bytes -= op; - buffer = Add2Ptr(buffer, op); - } - - return 0; -} - int ntfs_sb_write(struct super_block *sb, u64 lbo, size_t bytes, const void *buf, int wait) {
diff --git a/fs/ntfs3/index.c b/fs/ntfs3/index.c index 7eb9fae..78d20e4 100644 --- a/fs/ntfs3/index.c +++ b/fs/ntfs3/index.c
@@ -618,7 +618,7 @@ static bool index_hdr_check(const struct INDEX_HDR *hdr, u32 bytes) u32 off = le32_to_cpu(hdr->de_off); if (!IS_ALIGNED(off, 8) || tot > bytes || end > tot || - off + sizeof(struct NTFS_DE) > end) { + size_add(off, sizeof(struct NTFS_DE)) > end) { /* incorrect index buffer. */ return false; } @@ -736,7 +736,7 @@ static struct NTFS_DE *hdr_find_e(const struct ntfs_index *indx, if (end > total) return NULL; - if (off + sizeof(struct NTFS_DE) > end) + if (size_add(off, sizeof(struct NTFS_DE)) > end) return NULL; e = Add2Ptr(hdr, off);
diff --git a/fs/ntfs3/inode.c b/fs/ntfs3/inode.c index a1e1122..3e2957a 100644 --- a/fs/ntfs3/inode.c +++ b/fs/ntfs3/inode.c
@@ -1025,46 +1025,6 @@ int ntfs_sync_inode(struct inode *inode) } /* - * writeback_inode - Helper function for ntfs_flush_inodes(). - * - * This writes both the inode and the file data blocks, waiting - * for in flight data blocks before the start of the call. It - * does not wait for any io started during the call. - */ -static int writeback_inode(struct inode *inode) -{ - int ret = sync_inode_metadata(inode, 0); - - if (!ret) - ret = filemap_fdatawrite(inode->i_mapping); - return ret; -} - -/* - * ntfs_flush_inodes - * - * Write data and metadata corresponding to i1 and i2. The io is - * started but we do not wait for any of it to finish. - * - * filemap_flush() is used for the block device, so if there is a dirty - * page for a block already in flight, we will not wait and start the - * io over again. - */ -int ntfs_flush_inodes(struct super_block *sb, struct inode *i1, - struct inode *i2) -{ - int ret = 0; - - if (i1) - ret = writeback_inode(i1); - if (!ret && i2) - ret = writeback_inode(i2); - if (!ret) - ret = filemap_flush(sb->s_bdev_file->f_mapping); - return ret; -} - -/* * Helper function to read file. */ int inode_read_data(struct inode *inode, void *data, size_t bytes)
diff --git a/fs/ntfs3/ntfs.h b/fs/ntfs3/ntfs.h index 241f2ff..1ff13b6 100644 --- a/fs/ntfs3/ntfs.h +++ b/fs/ntfs3/ntfs.h
@@ -717,7 +717,7 @@ static inline struct NTFS_DE *hdr_first_de(const struct INDEX_HDR *hdr) struct NTFS_DE *e; u16 esize; - if (de_off >= used || de_off + sizeof(struct NTFS_DE) > used ) + if (de_off >= used || size_add(de_off, sizeof(struct NTFS_DE)) > used) return NULL; e = Add2Ptr(hdr, de_off);
diff --git a/fs/ntfs3/ntfs_fs.h b/fs/ntfs3/ntfs_fs.h index 3828204..d628977 100644 --- a/fs/ntfs3/ntfs_fs.h +++ b/fs/ntfs3/ntfs_fs.h
@@ -530,9 +530,6 @@ struct ATTRIB *ni_find_attr(struct ntfs_inode *ni, struct ATTRIB *attr, struct ATTRIB *ni_enum_attr_ex(struct ntfs_inode *ni, struct ATTRIB *attr, struct ATTR_LIST_ENTRY **le, struct mft_inode **mi); -struct ATTRIB *ni_load_attr(struct ntfs_inode *ni, enum ATTR_TYPE type, - const __le16 *name, u8 name_len, CLST vcn, - struct mft_inode **pmi); int ni_load_all_mi(struct ntfs_inode *ni); bool ni_add_subrecord(struct ntfs_inode *ni, CLST rno, struct mft_inode **mi); int ni_remove_attr(struct ntfs_inode *ni, enum ATTR_TYPE type, @@ -619,7 +616,6 @@ enum NTFS_DIRTY_FLAGS { NTFS_DIRTY_ERROR = 2, }; int ntfs_set_state(struct ntfs_sb_info *sbi, enum NTFS_DIRTY_FLAGS dirty); -int ntfs_sb_read(struct super_block *sb, u64 lbo, size_t bytes, void *buffer); int ntfs_sb_write(struct super_block *sb, u64 lbo, size_t bytes, const void *buffer, int wait); int ntfs_sb_write_run(struct ntfs_sb_info *sbi, const struct runs_tree *run, @@ -717,8 +713,6 @@ int ntfs_write_end(struct file *file, struct address_space *mapping, loff_t pos, u32 len, u32 copied, struct folio *folio, void *fsdata); int ntfs3_write_inode(struct inode *inode, struct writeback_control *wbc); int ntfs_sync_inode(struct inode *inode); -int ntfs_flush_inodes(struct super_block *sb, struct inode *i1, - struct inode *i2); int inode_read_data(struct inode *inode, void *data, size_t bytes); int ntfs_create_inode(struct mnt_idmap *idmap, struct inode *dir, struct dentry *dentry, const struct cpu_str *uni,
diff --git a/fs/ntfs3/super.c b/fs/ntfs3/super.c index 6a0f6b0..920a1ab 100644 --- a/fs/ntfs3/super.c +++ b/fs/ntfs3/super.c
@@ -555,6 +555,55 @@ static const struct proc_ops ntfs3_label_fops = { .proc_write = ntfs3_label_write, }; +static void ntfs_create_procdir(struct super_block *sb) +{ + struct proc_dir_entry *e; + + if (!proc_info_root) + return; + + e = proc_mkdir(sb->s_id, proc_info_root); + if (e) { + struct ntfs_sb_info *sbi = sb->s_fs_info; + + proc_create_data("volinfo", 0444, e, + &ntfs3_volinfo_fops, sb); + proc_create_data("label", 0644, e, + &ntfs3_label_fops, sb); + sbi->procdir = e; + } +} + +static void ntfs_remove_procdir(struct super_block *sb) +{ + struct ntfs_sb_info *sbi = sb->s_fs_info; + + if (!sbi->procdir) + return; + + remove_proc_entry("label", sbi->procdir); + remove_proc_entry("volinfo", sbi->procdir); + remove_proc_entry(sb->s_id, proc_info_root); + sbi->procdir = NULL; +} + +static void ntfs_create_proc_root(void) +{ + proc_info_root = proc_mkdir("fs/ntfs3", NULL); +} + +static void ntfs_remove_proc_root(void) +{ + if (proc_info_root) { + remove_proc_entry("fs/ntfs3", NULL); + proc_info_root = NULL; + } +} +#else +static void ntfs_create_procdir(struct super_block *sb) {} +static void ntfs_remove_procdir(struct super_block *sb) {} +static void ntfs_create_proc_root(void) {} +static void ntfs_remove_proc_root(void) {} #endif static struct kmem_cache *ntfs_inode_cachep; @@ -644,15 +693,7 @@ static void ntfs_put_super(struct super_block *sb) { struct ntfs_sb_info *sbi = sb->s_fs_info; -#ifdef CONFIG_PROC_FS - // Remove /proc/fs/ntfs3/.. - if (sbi->procdir) { - remove_proc_entry("label", sbi->procdir); - remove_proc_entry("volinfo", sbi->procdir); - remove_proc_entry(sb->s_id, proc_info_root); - sbi->procdir = NULL; - } -#endif + ntfs_remove_procdir(sb); /* Mark rw ntfs as clear, if possible. */ ntfs_set_state(sbi, NTFS_DIRTY_CLEAR); @@ -1590,20 +1631,7 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc) kfree(boot2); } -#ifdef CONFIG_PROC_FS - /* Create /proc/fs/ntfs3/.. */ - if (proc_info_root) { - struct proc_dir_entry *e = proc_mkdir(sb->s_id, proc_info_root); - static_assert((S_IRUGO | S_IWUSR) == 0644); - if (e) { - proc_create_data("volinfo", S_IRUGO, e, - &ntfs3_volinfo_fops, sb); - proc_create_data("label", S_IRUGO | S_IWUSR, e, - &ntfs3_label_fops, sb); - sbi->procdir = e; - } - } -#endif + ntfs_create_procdir(sb); if (is_legacy_ntfs(sb)) sb->s_flags |= SB_RDONLY; @@ -1853,14 +1881,11 @@ static int __init init_ntfs_fs(void) if (IS_ENABLED(CONFIG_NTFS3_LZX_XPRESS)) pr_info("ntfs3: Read-only LZX/Xpress compression included\n"); -#ifdef CONFIG_PROC_FS - /* Create "/proc/fs/ntfs3" */ - proc_info_root = proc_mkdir("fs/ntfs3", NULL); -#endif + ntfs_create_proc_root(); err = ntfs3_init_bitmap(); if (err) - return err; + goto out2; ntfs_inode_cachep = kmem_cache_create( "ntfs_inode_cache", sizeof(struct ntfs_inode), 0, @@ -1880,6 +1905,8 @@ static int __init init_ntfs_fs(void) kmem_cache_destroy(ntfs_inode_cachep); out1: ntfs3_exit_bitmap(); +out2: + ntfs_remove_proc_root(); return err; } @@ -1890,11 +1917,7 @@ static void __exit exit_ntfs_fs(void) unregister_filesystem(&ntfs_fs_type); unregister_as_ntfs_legacy(); ntfs3_exit_bitmap(); - -#ifdef CONFIG_PROC_FS - if (proc_info_root) - remove_proc_entry("fs/ntfs3", NULL); -#endif + ntfs_remove_proc_root(); } MODULE_LICENSE("GPL");
diff --git a/fs/ocfs2/cluster/tcp.c b/fs/ocfs2/cluster/tcp.c index 0f46b22..fce9beb 100644 --- a/fs/ocfs2/cluster/tcp.c +++ b/fs/ocfs2/cluster/tcp.c
@@ -724,7 +724,7 @@ static void o2net_shutdown_sc(struct work_struct *work) if (o2net_unregister_callbacks(sc->sc_sock->sk, sc)) { /* we shouldn't flush as we're in the thread, the * races with pending sc work structs are harmless */ - del_timer_sync(&sc->sc_idle_timeout); + timer_delete_sync(&sc->sc_idle_timeout); o2net_sc_cancel_delayed_work(sc, &sc->sc_keepalive_work); sc_put(sc); kernel_sock_shutdown(sc->sc_sock, SHUT_RDWR);
diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c index 557cf9d..f8b9c9c 100644 --- a/fs/pstore/platform.c +++ b/fs/pstore/platform.c
@@ -563,7 +563,7 @@ void pstore_unregister(struct pstore_info *psi) pstore_unregister_kmsg(); /* Stop timer and make sure all work has finished. */ - del_timer_sync(&pstore_timer); + timer_delete_sync(&pstore_timer); flush_work(&pstore_work); /* Remove all backend records from filesystem tree. */
diff --git a/fs/smb/client/cifs_fs_sb.h b/fs/smb/client/cifs_fs_sb.h index 6517591..5e8d163 100644 --- a/fs/smb/client/cifs_fs_sb.h +++ b/fs/smb/client/cifs_fs_sb.h
@@ -49,6 +49,7 @@ struct cifs_sb_info { struct rb_root tlink_tree; + struct list_head tcon_sb_link; spinlock_t tlink_tree_lock; struct tcon_link *master_tlink; struct nls_table *local_nls;
diff --git a/fs/smb/client/cifsfs.h b/fs/smb/client/cifsfs.h index 8dea0cf..ca435a3 100644 --- a/fs/smb/client/cifsfs.h +++ b/fs/smb/client/cifsfs.h
@@ -135,7 +135,6 @@ extern ssize_t cifs_file_copychunk_range(unsigned int xid, extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg); extern void cifs_setsize(struct inode *inode, loff_t offset); -extern int cifs_truncate_page(struct address_space *mapping, loff_t from); struct smb3_fs_context; extern struct dentry *cifs_smb3_do_mount(struct file_system_type *fs_type, @@ -146,6 +145,6 @@ extern const struct export_operations cifs_export_ops; #endif /* CONFIG_CIFS_NFSD_EXPORT */ /* when changing internal version - update following two lines at same time */ -#define SMB3_PRODUCT_BUILD 53 -#define CIFS_VERSION "2.53" +#define SMB3_PRODUCT_BUILD 54 +#define CIFS_VERSION "2.54" #endif /* _CIFSFS_H */
diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h index 6ae170a..07c4688 100644 --- a/fs/smb/client/cifsglob.h +++ b/fs/smb/client/cifsglob.h
@@ -714,6 +714,8 @@ struct TCP_Server_Info { spinlock_t srv_lock; /* protect anything here that is not protected */ __u64 conn_id; /* connection identifier (useful for debugging) */ int srv_count; /* reference counter */ + int rfc1001_sessinit; /* whether to estasblish netbios session */ + bool with_rfc1001; /* if netbios session is used */ /* 15 character server name + 0x20 16th byte indicating type = srv */ char server_RFC1001_name[RFC1001_NAME_LEN_WITH_NULL]; struct smb_version_operations *ops; @@ -1321,7 +1323,8 @@ struct cifs_tcon { #endif struct list_head pending_opens; /* list of incomplete opens */ struct cached_fids *cfids; - /* BB add field for back pointer to sb struct(s)? */ + struct list_head cifs_sb_list; + spinlock_t sb_list_lock; #ifdef CONFIG_CIFS_DFS_UPCALL struct delayed_work dfs_cache_work; struct list_head dfs_ses_list; @@ -1718,6 +1721,7 @@ struct mid_q_entry { void *resp_buf; /* pointer to received SMB header */ unsigned int resp_buf_size; int mid_state; /* wish this were enum but can not pass to wait_event */ + int mid_rc; /* rc for MID_RC */ unsigned int mid_flags; __le16 command; /* smb command code */ unsigned int optype; /* operation type */ @@ -1880,6 +1884,7 @@ static inline bool is_replayable_error(int error) #define MID_RESPONSE_MALFORMED 0x10 #define MID_SHUTDOWN 0x20 #define MID_RESPONSE_READY 0x40 /* ready for other process handle the rsp */ +#define MID_RC 0x80 /* mid_rc contains custom rc */ /* Flags */ #define MID_WAIT_CANCELLED 1 /* Cancelled while waiting for response */
diff --git a/fs/smb/client/cifssmb.c b/fs/smb/client/cifssmb.c index 29dcb88..60cb264 100644 --- a/fs/smb/client/cifssmb.c +++ b/fs/smb/client/cifssmb.c
@@ -1041,15 +1041,31 @@ static __u16 convert_disposition(int disposition) static int access_flags_to_smbopen_mode(const int access_flags) { - int masked_flags = access_flags & (GENERIC_READ | GENERIC_WRITE); + /* + * SYSTEM_SECURITY grants both read and write access to SACL, treat is as read/write. + * MAXIMUM_ALLOWED grants as many access as possible, so treat it as read/write too. + * SYNCHRONIZE as is does not grant any specific access, so do not check its mask. + * If only SYNCHRONIZE bit is specified then fallback to read access. + */ + bool with_write_flags = access_flags & (FILE_WRITE_DATA | FILE_APPEND_DATA | FILE_WRITE_EA | + FILE_DELETE_CHILD | FILE_WRITE_ATTRIBUTES | DELETE | + WRITE_DAC | WRITE_OWNER | SYSTEM_SECURITY | + MAXIMUM_ALLOWED | GENERIC_WRITE | GENERIC_ALL); + bool with_read_flags = access_flags & (FILE_READ_DATA | FILE_READ_EA | FILE_EXECUTE | + FILE_READ_ATTRIBUTES | READ_CONTROL | + SYSTEM_SECURITY | MAXIMUM_ALLOWED | GENERIC_ALL | + GENERIC_EXECUTE | GENERIC_READ); + bool with_execute_flags = access_flags & (FILE_EXECUTE | MAXIMUM_ALLOWED | GENERIC_ALL | + GENERIC_EXECUTE); - if (masked_flags == GENERIC_READ) - return SMBOPEN_READ; - else if (masked_flags == GENERIC_WRITE) + if (with_write_flags && with_read_flags) + return SMBOPEN_READWRITE; + else if (with_write_flags) return SMBOPEN_WRITE; - - /* just go for read/write */ - return SMBOPEN_READWRITE; + else if (with_execute_flags) + return SMBOPEN_EXECUTE; + else + return SMBOPEN_READ; } int
diff --git a/fs/smb/client/connect.c b/fs/smb/client/connect.c index d7bad2c..f298e86 100644 --- a/fs/smb/client/connect.c +++ b/fs/smb/client/connect.c
@@ -371,7 +371,7 @@ static bool cifs_tcp_ses_needs_reconnect(struct TCP_Server_Info *server, int num * */ static int __cifs_reconnect(struct TCP_Server_Info *server, - bool mark_smb_session) + bool mark_smb_session, bool once) { int rc = 0; @@ -399,6 +399,9 @@ static int __cifs_reconnect(struct TCP_Server_Info *server, if (rc) { cifs_server_unlock(server); cifs_dbg(FYI, "%s: reconnect error %d\n", __func__, rc); + /* If was asked to reconnect only once, do not try it more times */ + if (once) + break; msleep(3000); } else { atomic_inc(&tcpSesReconnectCount); @@ -564,19 +567,33 @@ static int reconnect_dfs_server(struct TCP_Server_Info *server) return rc; } -int cifs_reconnect(struct TCP_Server_Info *server, bool mark_smb_session) +static int +_cifs_reconnect(struct TCP_Server_Info *server, bool mark_smb_session, bool once) { if (!server->leaf_fullpath) - return __cifs_reconnect(server, mark_smb_session); + return __cifs_reconnect(server, mark_smb_session, once); return reconnect_dfs_server(server); } #else -int cifs_reconnect(struct TCP_Server_Info *server, bool mark_smb_session) +static int +_cifs_reconnect(struct TCP_Server_Info *server, bool mark_smb_session, bool once) { - return __cifs_reconnect(server, mark_smb_session); + return __cifs_reconnect(server, mark_smb_session, once); } #endif +int +cifs_reconnect(struct TCP_Server_Info *server, bool mark_smb_session) +{ + return _cifs_reconnect(server, mark_smb_session, false); +} + +static int +cifs_reconnect_once(struct TCP_Server_Info *server) +{ + return _cifs_reconnect(server, true, true); +} + static void cifs_echo_request(struct work_struct *work) { @@ -803,26 +820,110 @@ is_smb_response(struct TCP_Server_Info *server, unsigned char type) /* Regular SMB response */ return true; case RFC1002_SESSION_KEEP_ALIVE: + /* + * RFC 1002 session keep alive can sent by the server only when + * we established a RFC 1002 session. But Samba servers send + * RFC 1002 session keep alive also over port 445 on which + * RFC 1002 session is not established. + */ cifs_dbg(FYI, "RFC 1002 session keep alive\n"); break; case RFC1002_POSITIVE_SESSION_RESPONSE: - cifs_dbg(FYI, "RFC 1002 positive session response\n"); + /* + * RFC 1002 positive session response cannot be returned + * for SMB request. RFC 1002 session response is handled + * exclusively in ip_rfc1001_connect() function. + */ + cifs_server_dbg(VFS, "RFC 1002 positive session response (unexpected)\n"); + cifs_reconnect(server, true); break; case RFC1002_NEGATIVE_SESSION_RESPONSE: /* * We get this from Windows 98 instead of an error on - * SMB negprot response. + * SMB negprot response, when we have not established + * RFC 1002 session (which means ip_rfc1001_connect() + * was skipped). Note that same still happens with + * Windows Server 2022 when connecting via port 139. + * So for this case when mount option -o nonbsessinit + * was not specified, try to reconnect with establishing + * RFC 1002 session. If new socket establishment with + * RFC 1002 session was successful then return to the + * mid's caller -EAGAIN, so it can retry the request. */ - cifs_dbg(FYI, "RFC 1002 negative session response\n"); - /* give server a second to clean up */ - msleep(1000); - /* - * Always try 445 first on reconnect since we get NACK - * on some if we ever connected to port 139 (the NACK - * is since we do not begin with RFC1001 session - * initialize frame). - */ - cifs_set_port((struct sockaddr *)&server->dstaddr, CIFS_PORT); + if (!cifs_rdma_enabled(server) && + server->tcpStatus == CifsInNegotiate && + !server->with_rfc1001 && + server->rfc1001_sessinit != 0) { + int rc, mid_rc; + struct mid_q_entry *mid, *nmid; + LIST_HEAD(dispose_list); + + cifs_dbg(FYI, "RFC 1002 negative session response during SMB Negotiate, retrying with NetBIOS session\n"); + + /* + * Before reconnect, delete all pending mids for this + * server, so reconnect would not signal connection + * aborted error to mid's callbacks. Note that for this + * server there should be exactly one pending mid + * corresponding to SMB1/SMB2 Negotiate packet. + */ + spin_lock(&server->mid_lock); + list_for_each_entry_safe(mid, nmid, &server->pending_mid_q, qhead) { + kref_get(&mid->refcount); + list_move(&mid->qhead, &dispose_list); + mid->mid_flags |= MID_DELETED; + } + spin_unlock(&server->mid_lock); + + /* Now try to reconnect once with NetBIOS session. */ + server->with_rfc1001 = true; + rc = cifs_reconnect_once(server); + + /* + * If reconnect was successful then indicate -EAGAIN + * to mid's caller. If reconnect failed with -EAGAIN + * then mask it as -EHOSTDOWN, so mid's caller would + * know that it failed. + */ + if (rc == 0) + mid_rc = -EAGAIN; + else if (rc == -EAGAIN) + mid_rc = -EHOSTDOWN; + else + mid_rc = rc; + + /* + * After reconnect (either successful or unsuccessful) + * deliver reconnect status to mid's caller via mid's + * callback. Use MID_RC state which indicates that the + * return code should be read from mid_rc member. + */ + list_for_each_entry_safe(mid, nmid, &dispose_list, qhead) { + list_del_init(&mid->qhead); + mid->mid_rc = mid_rc; + mid->mid_state = MID_RC; + mid->callback(mid); + release_mid(mid); + } + + /* + * If reconnect failed then wait two seconds. In most + * cases we were been called from the mount context and + * delivered failure to mid's callback will stop this + * receiver task thread and fails the mount process. + * So wait two seconds to prevent another reconnect + * in this task thread, which would be useless as the + * mount context will fail at all. + */ + if (rc != 0) + msleep(2000); + } else { + cifs_server_dbg(VFS, "RFC 1002 negative session response (unexpected)\n"); + cifs_reconnect(server, true); + } + break; + case RFC1002_RETARGET_SESSION_RESPONSE: + cifs_server_dbg(VFS, "RFC 1002 retarget session response (unexpected)\n"); cifs_reconnect(server, true); break; default: @@ -1701,6 +1802,8 @@ cifs_get_tcp_session(struct smb3_fs_context *ctx, ctx->source_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL); memcpy(tcp_ses->server_RFC1001_name, ctx->target_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL); + tcp_ses->rfc1001_sessinit = ctx->rfc1001_sessinit; + tcp_ses->with_rfc1001 = false; tcp_ses->session_estab = false; tcp_ses->sequence_number = 0; tcp_ses->channel_sequence_num = 0; /* only tracked for primary channel */ @@ -1731,12 +1834,8 @@ cifs_get_tcp_session(struct smb3_fs_context *ctx, */ tcp_ses->tcpStatus = CifsNew; ++tcp_ses->srv_count; + tcp_ses->echo_interval = ctx->echo_interval * HZ; - if (ctx->echo_interval >= SMB_ECHO_INTERVAL_MIN && - ctx->echo_interval <= SMB_ECHO_INTERVAL_MAX) - tcp_ses->echo_interval = ctx->echo_interval * HZ; - else - tcp_ses->echo_interval = SMB_ECHO_INTERVAL_DEFAULT * HZ; if (tcp_ses->rdma) { #ifndef CONFIG_CIFS_SMB_DIRECT cifs_dbg(VFS, "CONFIG_CIFS_SMB_DIRECT is not enabled\n"); @@ -3221,6 +3320,7 @@ ip_rfc1001_connect(struct TCP_Server_Info *server) return -EIO; } + server->with_rfc1001 = true; return 0; } @@ -3332,7 +3432,16 @@ generic_ip_connect(struct TCP_Server_Info *server) return rc; } trace_smb3_connect_done(server->hostname, server->conn_id, &server->dstaddr); - if (sport == htons(RFC1001_PORT)) + + /* + * Establish RFC1001 NetBIOS session when it was explicitly requested + * by mount option -o nbsessinit, or when connecting to default RFC1001 + * server port (139) and it was not explicitly disabled by mount option + * -o nonbsessinit. + */ + if (server->with_rfc1001 || + server->rfc1001_sessinit == 1 || + (server->rfc1001_sessinit == -1 && sport == htons(RFC1001_PORT))) rc = ip_rfc1001_connect(server); return rc; @@ -3481,6 +3590,7 @@ int cifs_setup_cifs_sb(struct cifs_sb_info *cifs_sb) struct smb3_fs_context *ctx = cifs_sb->ctx; INIT_DELAYED_WORK(&cifs_sb->prune_tlinks, cifs_prune_tlinks); + INIT_LIST_HEAD(&cifs_sb->tcon_sb_link); spin_lock_init(&cifs_sb->tlink_tree_lock); cifs_sb->tlink_tree = RB_ROOT; @@ -3713,6 +3823,10 @@ static int mount_setup_tlink(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses, tlink_rb_insert(&cifs_sb->tlink_tree, tlink); spin_unlock(&cifs_sb->tlink_tree_lock); + spin_lock(&tcon->sb_list_lock); + list_add(&cifs_sb->tcon_sb_link, &tcon->cifs_sb_list); + spin_unlock(&tcon->sb_list_lock); + queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks, TLINK_IDLE_EXPIRE); return 0; @@ -4054,9 +4168,19 @@ cifs_umount(struct cifs_sb_info *cifs_sb) struct rb_root *root = &cifs_sb->tlink_tree; struct rb_node *node; struct tcon_link *tlink; + struct cifs_tcon *tcon = NULL; cancel_delayed_work_sync(&cifs_sb->prune_tlinks); + if (cifs_sb->master_tlink) { + tcon = cifs_sb->master_tlink->tl_tcon; + if (tcon) { + spin_lock(&tcon->sb_list_lock); + list_del_init(&cifs_sb->tcon_sb_link); + spin_unlock(&tcon->sb_list_lock); + } + } + spin_lock(&cifs_sb->tlink_tree_lock); while ((node = rb_first(root))) { tlink = rb_entry(node, struct tcon_link, tl_rbnode); @@ -4078,11 +4202,13 @@ int cifs_negotiate_protocol(const unsigned int xid, struct cifs_ses *ses, struct TCP_Server_Info *server) { + bool in_retry = false; int rc = 0; if (!server->ops->need_neg || !server->ops->negotiate) return -ENOSYS; +retry: /* only send once per connect */ spin_lock(&server->srv_lock); if (server->tcpStatus != CifsGood && @@ -4102,6 +4228,14 @@ cifs_negotiate_protocol(const unsigned int xid, struct cifs_ses *ses, spin_unlock(&server->srv_lock); rc = server->ops->negotiate(xid, ses, server); + if (rc == -EAGAIN) { + /* Allow one retry attempt */ + if (!in_retry) { + in_retry = true; + goto retry; + } + rc = -EHOSTDOWN; + } if (rc == 0) { spin_lock(&server->srv_lock); if (server->tcpStatus == CifsInNegotiate)
diff --git a/fs/smb/client/fs_context.c b/fs/smb/client/fs_context.c index bdb762d..2980941 100644 --- a/fs/smb/client/fs_context.c +++ b/fs/smb/client/fs_context.c
@@ -135,6 +135,7 @@ const struct fs_parameter_spec smb3_fs_parameters[] = { fsparam_flag("witness", Opt_witness), fsparam_flag_no("nativesocket", Opt_nativesocket), fsparam_flag_no("unicode", Opt_unicode), + fsparam_flag_no("nbsessinit", Opt_nbsessinit), /* Mount options which take uid or gid */ fsparam_uid("backupuid", Opt_backupuid), @@ -968,6 +969,10 @@ static int smb3_verify_reconfigure_ctx(struct fs_context *fc, cifs_errorf(fc, "can not change unicode during remount\n"); return -EINVAL; } + if (new_ctx->rfc1001_sessinit != old_ctx->rfc1001_sessinit) { + cifs_errorf(fc, "can not change nbsessinit during remount\n"); + return -EINVAL; + } return 0; } @@ -1333,6 +1338,7 @@ static int smb3_fs_context_parse_param(struct fs_context *fc, case Opt_rsize: ctx->rsize = result.uint_32; ctx->got_rsize = true; + ctx->vol_rsize = ctx->rsize; break; case Opt_wsize: ctx->wsize = result.uint_32; @@ -1348,6 +1354,7 @@ static int smb3_fs_context_parse_param(struct fs_context *fc, ctx->wsize, PAGE_SIZE); } } + ctx->vol_wsize = ctx->wsize; break; case Opt_acregmax: if (result.uint_32 > CIFS_MAX_ACTIMEO / HZ) { @@ -1383,6 +1390,11 @@ static int smb3_fs_context_parse_param(struct fs_context *fc, ctx->closetimeo = HZ * result.uint_32; break; case Opt_echo_interval: + if (result.uint_32 < SMB_ECHO_INTERVAL_MIN || + result.uint_32 > SMB_ECHO_INTERVAL_MAX) { + cifs_errorf(fc, "echo interval is out of bounds\n"); + goto cifs_parse_mount_err; + } ctx->echo_interval = result.uint_32; break; case Opt_snapshot: @@ -1602,6 +1614,10 @@ static int smb3_fs_context_parse_param(struct fs_context *fc, if (i == RFC1001_NAME_LEN && param->string[i] != 0) pr_warn("server netbiosname longer than 15 truncated\n"); break; + case Opt_nbsessinit: + ctx->rfc1001_sessinit = !result.negated; + cifs_dbg(FYI, "rfc1001_sessinit set to %d\n", ctx->rfc1001_sessinit); + break; case Opt_ver: /* version of mount userspace tools, not dialect */ /* If interface changes in mount.cifs bump to new ver */ @@ -1889,13 +1905,16 @@ int smb3_init_fs_context(struct fs_context *fc) memset(ctx->source_rfc1001_name, 0x20, RFC1001_NAME_LEN); for (i = 0; i < strnlen(nodename, RFC1001_NAME_LEN); i++) ctx->source_rfc1001_name[i] = toupper(nodename[i]); - ctx->source_rfc1001_name[RFC1001_NAME_LEN] = 0; + /* * null target name indicates to use *SMBSERVR default called name * if we end up sending RFC1001 session initialize */ ctx->target_rfc1001_name[0] = 0; + + ctx->rfc1001_sessinit = -1; /* autodetect based on port number */ + ctx->cred_uid = current_uid(); ctx->linux_uid = current_uid(); ctx->linux_gid = current_gid();
diff --git a/fs/smb/client/fs_context.h b/fs/smb/client/fs_context.h index 42c6b66..d1d2924 100644 --- a/fs/smb/client/fs_context.h +++ b/fs/smb/client/fs_context.h
@@ -174,6 +174,7 @@ enum cifs_param { Opt_iocharset, Opt_netbiosname, Opt_servern, + Opt_nbsessinit, Opt_ver, Opt_vers, Opt_sec, @@ -216,6 +217,7 @@ struct smb3_fs_context { char *iocharset; /* local code page for mapping to and from Unicode */ char source_rfc1001_name[RFC1001_NAME_LEN_WITH_NULL]; /* clnt nb name */ char target_rfc1001_name[RFC1001_NAME_LEN_WITH_NULL]; /* srvr nb name */ + int rfc1001_sessinit; kuid_t cred_uid; kuid_t linux_uid; kgid_t linux_gid; @@ -280,6 +282,9 @@ struct smb3_fs_context { bool use_client_guid:1; /* reuse existing guid for multichannel */ u8 client_guid[SMB2_CLIENT_GUID_SIZE]; + /* User-specified original r/wsize value */ + unsigned int vol_rsize; + unsigned int vol_wsize; unsigned int bsize; unsigned int rasize; unsigned int rsize;
diff --git a/fs/smb/client/inode.c b/fs/smb/client/inode.c index 3bb21aa..a00a9d9 100644 --- a/fs/smb/client/inode.c +++ b/fs/smb/client/inode.c
@@ -2901,23 +2901,6 @@ int cifs_fiemap(struct inode *inode, struct fiemap_extent_info *fei, u64 start, return -EOPNOTSUPP; } -int cifs_truncate_page(struct address_space *mapping, loff_t from) -{ - pgoff_t index = from >> PAGE_SHIFT; - unsigned offset = from & (PAGE_SIZE - 1); - struct page *page; - int rc = 0; - - page = grab_cache_page(mapping, index); - if (!page) - return -ENOMEM; - - zero_user_segment(page, offset, PAGE_SIZE); - unlock_page(page); - put_page(page); - return rc; -} - void cifs_setsize(struct inode *inode, loff_t offset) { struct cifsInodeInfo *cifs_i = CIFS_I(inode); @@ -3012,8 +2995,6 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs, */ attrs->ia_ctime = attrs->ia_mtime = current_time(inode); attrs->ia_valid |= ATTR_CTIME | ATTR_MTIME; - - cifs_truncate_page(inode->i_mapping, inode->i_size); } return rc;
diff --git a/fs/smb/client/link.c b/fs/smb/client/link.c index a882536..769752a 100644 --- a/fs/smb/client/link.c +++ b/fs/smb/client/link.c
@@ -258,7 +258,7 @@ cifs_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, struct cifs_open_parms oparms; struct cifs_io_parms io_parms = {0}; int buf_type = CIFS_NO_BUFFER; - FILE_ALL_INFO file_info; + struct cifs_open_info_data query_data; oparms = (struct cifs_open_parms) { .tcon = tcon, @@ -270,11 +270,11 @@ cifs_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, .fid = &fid, }; - rc = CIFS_open(xid, &oparms, &oplock, &file_info); + rc = tcon->ses->server->ops->open(xid, &oparms, &oplock, &query_data); if (rc) return rc; - if (file_info.EndOfFile != cpu_to_le64(CIFS_MF_SYMLINK_FILE_SIZE)) { + if (query_data.fi.EndOfFile != cpu_to_le64(CIFS_MF_SYMLINK_FILE_SIZE)) { rc = -ENOENT; /* it's not a symlink */ goto out; @@ -313,7 +313,7 @@ cifs_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, .fid = &fid, }; - rc = CIFS_open(xid, &oparms, &oplock, NULL); + rc = tcon->ses->server->ops->open(xid, &oparms, &oplock, NULL); if (rc) return rc;
diff --git a/fs/smb/client/misc.c b/fs/smb/client/misc.c index b328dc5..7b6ed9b 100644 --- a/fs/smb/client/misc.c +++ b/fs/smb/client/misc.c
@@ -137,8 +137,10 @@ tcon_info_alloc(bool dir_leases_enabled, enum smb3_tcon_ref_trace trace) spin_lock_init(&ret_buf->tc_lock); INIT_LIST_HEAD(&ret_buf->openFileList); INIT_LIST_HEAD(&ret_buf->tcon_list); + INIT_LIST_HEAD(&ret_buf->cifs_sb_list); spin_lock_init(&ret_buf->open_file_lock); spin_lock_init(&ret_buf->stat_lock); + spin_lock_init(&ret_buf->sb_list_lock); atomic_set(&ret_buf->num_local_opens, 0); atomic_set(&ret_buf->num_remote_opens, 0); ret_buf->stats_from_time = ktime_get_real_seconds();
diff --git a/fs/smb/client/smb1ops.c b/fs/smb/client/smb1ops.c index 8701484..26df807 100644 --- a/fs/smb/client/smb1ops.c +++ b/fs/smb/client/smb1ops.c
@@ -14,6 +14,8 @@ #include "cifspdu.h" #include "cifs_unicode.h" #include "fs_context.h" +#include "nterr.h" +#include "smberr.h" /* * An NT cancel request header looks just like the original request except: @@ -426,13 +428,6 @@ cifs_negotiate(const unsigned int xid, { int rc; rc = CIFSSMBNegotiate(xid, ses, server); - if (rc == -EAGAIN) { - /* retry only once on 1st time connection */ - set_credits(server, 1); - rc = CIFSSMBNegotiate(xid, ses, server); - if (rc == -EAGAIN) - rc = -EHOSTDOWN; - } return rc; } @@ -444,8 +439,8 @@ cifs_negotiate_wsize(struct cifs_tcon *tcon, struct smb3_fs_context *ctx) unsigned int wsize; /* start with specified wsize, or default */ - if (ctx->wsize) - wsize = ctx->wsize; + if (ctx->got_wsize) + wsize = ctx->vol_wsize; else if (tcon->unix_ext && (unix_cap & CIFS_UNIX_LARGE_WRITE_CAP)) wsize = CIFS_DEFAULT_IOSIZE; else @@ -497,7 +492,7 @@ cifs_negotiate_rsize(struct cifs_tcon *tcon, struct smb3_fs_context *ctx) else defsize = server->maxBuf - sizeof(READ_RSP); - rsize = ctx->rsize ? ctx->rsize : defsize; + rsize = ctx->got_rsize ? ctx->vol_rsize : defsize; /* * no CAP_LARGE_READ_X? Then MS-CIFS states that we must limit this to @@ -1069,6 +1064,47 @@ cifs_make_node(unsigned int xid, struct inode *inode, full_path, mode, dev); } +static bool +cifs_is_network_name_deleted(char *buf, struct TCP_Server_Info *server) +{ + struct smb_hdr *shdr = (struct smb_hdr *)buf; + struct TCP_Server_Info *pserver; + struct cifs_ses *ses; + struct cifs_tcon *tcon; + + if (shdr->Flags2 & SMBFLG2_ERR_STATUS) { + if (shdr->Status.CifsError != cpu_to_le32(NT_STATUS_NETWORK_NAME_DELETED)) + return false; + } else { + if (shdr->Status.DosError.ErrorClass != ERRSRV || + shdr->Status.DosError.Error != cpu_to_le16(ERRinvtid)) + return false; + } + + /* If server is a channel, select the primary channel */ + pserver = SERVER_IS_CHAN(server) ? server->primary_server : server; + + spin_lock(&cifs_tcp_ses_lock); + list_for_each_entry(ses, &pserver->smb_ses_list, smb_ses_list) { + if (cifs_ses_exiting(ses)) + continue; + list_for_each_entry(tcon, &ses->tcon_list, tcon_list) { + if (tcon->tid == shdr->Tid) { + spin_lock(&tcon->tc_lock); + tcon->need_reconnect = true; + spin_unlock(&tcon->tc_lock); + spin_unlock(&cifs_tcp_ses_lock); + pr_warn_once("Server share %s deleted.\n", + tcon->tree_name); + return true; + } + } + } + spin_unlock(&cifs_tcp_ses_lock); + + return false; +} + struct smb_version_operations smb1_operations = { .send_cancel = send_nt_cancel, .compare_fids = cifs_compare_fids, @@ -1153,6 +1189,7 @@ struct smb_version_operations smb1_operations = { .get_acl_by_fid = get_cifs_acl_by_fid, .set_acl = set_cifs_acl, .make_node = cifs_make_node, + .is_network_name_deleted = cifs_is_network_name_deleted, }; struct smb_version_values smb1_values = {
diff --git a/fs/smb/client/smb2file.c b/fs/smb/client/smb2file.c index d609a20..a7f6292 100644 --- a/fs/smb/client/smb2file.c +++ b/fs/smb/client/smb2file.c
@@ -152,16 +152,35 @@ int smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms, __u32 int err_buftype = CIFS_NO_BUFFER; struct cifs_fid *fid = oparms->fid; struct network_resiliency_req nr_ioctl_req; + bool retry_without_read_attributes = false; smb2_path = cifs_convert_path_to_utf16(oparms->path, oparms->cifs_sb); if (smb2_path == NULL) return -ENOMEM; - oparms->desired_access |= FILE_READ_ATTRIBUTES; + /* + * GENERIC_READ, GENERIC_EXECUTE, GENERIC_ALL and MAXIMUM_ALLOWED + * contains also FILE_READ_ATTRIBUTES access right. So do not append + * FILE_READ_ATTRIBUTES when not needed and prevent calling code path + * for retry_without_read_attributes. + */ + if (!(oparms->desired_access & FILE_READ_ATTRIBUTES) && + !(oparms->desired_access & GENERIC_READ) && + !(oparms->desired_access & GENERIC_EXECUTE) && + !(oparms->desired_access & GENERIC_ALL) && + !(oparms->desired_access & MAXIMUM_ALLOWED)) { + oparms->desired_access |= FILE_READ_ATTRIBUTES; + retry_without_read_attributes = true; + } smb2_oplock = SMB2_OPLOCK_LEVEL_BATCH; rc = SMB2_open(xid, oparms, smb2_path, &smb2_oplock, smb2_data, NULL, &err_iov, &err_buftype); + if (rc == -EACCES && retry_without_read_attributes) { + oparms->desired_access &= ~FILE_READ_ATTRIBUTES; + rc = SMB2_open(xid, oparms, smb2_path, &smb2_oplock, smb2_data, NULL, &err_iov, + &err_buftype); + } if (rc && data) { struct smb2_hdr *hdr = err_iov.iov_base;
diff --git a/fs/smb/client/smb2glob.h b/fs/smb/client/smb2glob.h index 2466e61..22449532 100644 --- a/fs/smb/client/smb2glob.h +++ b/fs/smb/client/smb2glob.h
@@ -38,6 +38,7 @@ enum smb2_compound_ops { SMB2_OP_SET_REPARSE, SMB2_OP_GET_REPARSE, SMB2_OP_QUERY_WSL_EA, + SMB2_OP_OPEN_QUERY, }; /* Used when constructing chained read requests. */
diff --git a/fs/smb/client/smb2inode.c b/fs/smb/client/smb2inode.c index e9fd3e2..57d9bfba 100644 --- a/fs/smb/client/smb2inode.c +++ b/fs/smb/client/smb2inode.c
@@ -176,6 +176,7 @@ static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, struct kvec *out_iov, int *out_buftype, struct dentry *dentry) { + struct smb2_create_rsp *create_rsp = NULL; struct smb2_query_info_rsp *qi_rsp = NULL; struct smb2_compound_vars *vars = NULL; __u8 oplock = SMB2_OPLOCK_LEVEL_NONE; @@ -265,7 +266,13 @@ static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, num_rqst++; rc = 0; - for (i = 0; i < num_cmds; i++) { + i = 0; + + /* Skip the leading explicit OPEN operation */ + if (num_cmds > 0 && cmds[0] == SMB2_OP_OPEN_QUERY) + i++; + + for (; i < num_cmds; i++) { /* Operation */ switch (cmds[i]) { case SMB2_OP_QUERY_INFO: @@ -640,6 +647,27 @@ static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, } tmp_rc = rc; + + if (rc == 0 && num_cmds > 0 && cmds[0] == SMB2_OP_OPEN_QUERY) { + create_rsp = rsp_iov[0].iov_base; + idata = in_iov[0].iov_base; + idata->fi.CreationTime = create_rsp->CreationTime; + idata->fi.LastAccessTime = create_rsp->LastAccessTime; + idata->fi.LastWriteTime = create_rsp->LastWriteTime; + idata->fi.ChangeTime = create_rsp->ChangeTime; + idata->fi.Attributes = create_rsp->FileAttributes; + idata->fi.AllocationSize = create_rsp->AllocationSize; + idata->fi.EndOfFile = create_rsp->EndofFile; + if (le32_to_cpu(idata->fi.NumberOfLinks) == 0) + idata->fi.NumberOfLinks = cpu_to_le32(1); /* dummy value */ + idata->fi.DeletePending = 0; + idata->fi.Directory = !!(le32_to_cpu(create_rsp->FileAttributes) & ATTR_DIRECTORY); + + /* smb2_parse_contexts() fills idata->fi.IndexNumber */ + rc = smb2_parse_contexts(server, &rsp_iov[0], &oparms->fid->epoch, + oparms->fid->lease_key, &oplock, &idata->fi, NULL); + } + for (i = 0; i < num_cmds; i++) { char *buf = rsp_iov[i + i].iov_base; @@ -978,6 +1006,43 @@ int smb2_query_path_info(const unsigned int xid, case 0: rc = parse_create_response(data, cifs_sb, full_path, &out_iov[0]); break; + case -EACCES: + /* + * If SMB2_OP_QUERY_INFO (called when POSIX extensions are not used) failed with + * STATUS_ACCESS_DENIED then it means that caller does not have permission to + * open the path with FILE_READ_ATTRIBUTES access and therefore cannot issue + * SMB2_OP_QUERY_INFO command. + * + * There is an alternative way how to query limited information about path but still + * suitable for stat() syscall. SMB2 OPEN/CREATE operation returns in its successful + * response subset of query information. + * + * So try to open the path without FILE_READ_ATTRIBUTES but with MAXIMUM_ALLOWED + * access which will grant the maximum possible access to the file and the response + * will contain required query information for stat() syscall. + */ + + if (tcon->posix_extensions) + break; + + num_cmds = 1; + cmds[0] = SMB2_OP_OPEN_QUERY; + in_iov[0].iov_base = data; + in_iov[0].iov_len = sizeof(*data); + oparms = CIFS_OPARMS(cifs_sb, tcon, full_path, MAXIMUM_ALLOWED, + FILE_OPEN, create_options, ACL_NO_MODE); + free_rsp_iov(out_iov, out_buftype, ARRAY_SIZE(out_iov)); + rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, + &oparms, in_iov, cmds, num_cmds, + cfile, out_iov, out_buftype, NULL); + + hdr = out_iov[0].iov_base; + if (!hdr || out_buftype[0] == CIFS_NO_BUFFER) + goto out; + + if (!rc) + rc = parse_create_response(data, cifs_sb, full_path, &out_iov[0]); + break; case -EOPNOTSUPP: /* * BB TODO: When support for special files added to Samba
diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c index a700e59..41d8cd2 100644 --- a/fs/smb/client/smb2ops.c +++ b/fs/smb/client/smb2ops.c
@@ -464,12 +464,20 @@ smb2_negotiate(const unsigned int xid, server->CurrentMid = 0; spin_unlock(&server->mid_lock); rc = SMB2_negotiate(xid, ses, server); - /* BB we probably don't need to retry with modern servers */ - if (rc == -EAGAIN) - rc = -EHOSTDOWN; return rc; } +static inline unsigned int +prevent_zero_iosize(unsigned int size, const char *type) +{ + if (size == 0) { + cifs_dbg(VFS, "SMB: Zero %ssize calculated, using minimum value %u\n", + type, CIFS_MIN_DEFAULT_IOSIZE); + return CIFS_MIN_DEFAULT_IOSIZE; + } + return size; +} + static unsigned int smb2_negotiate_wsize(struct cifs_tcon *tcon, struct smb3_fs_context *ctx) { @@ -477,12 +485,12 @@ smb2_negotiate_wsize(struct cifs_tcon *tcon, struct smb3_fs_context *ctx) unsigned int wsize; /* start with specified wsize, or default */ - wsize = ctx->wsize ? ctx->wsize : CIFS_DEFAULT_IOSIZE; + wsize = ctx->got_wsize ? ctx->vol_wsize : CIFS_DEFAULT_IOSIZE; wsize = min_t(unsigned int, wsize, server->max_write); if (!(server->capabilities & SMB2_GLOBAL_CAP_LARGE_MTU)) wsize = min_t(unsigned int, wsize, SMB2_MAX_BUFFER_SIZE); - return wsize; + return prevent_zero_iosize(wsize, "w"); } static unsigned int @@ -492,7 +500,7 @@ smb3_negotiate_wsize(struct cifs_tcon *tcon, struct smb3_fs_context *ctx) unsigned int wsize; /* start with specified wsize, or default */ - wsize = ctx->wsize ? ctx->wsize : SMB3_DEFAULT_IOSIZE; + wsize = ctx->got_wsize ? ctx->vol_wsize : SMB3_DEFAULT_IOSIZE; wsize = min_t(unsigned int, wsize, server->max_write); #ifdef CONFIG_CIFS_SMB_DIRECT if (server->rdma) { @@ -514,7 +522,7 @@ smb3_negotiate_wsize(struct cifs_tcon *tcon, struct smb3_fs_context *ctx) if (!(server->capabilities & SMB2_GLOBAL_CAP_LARGE_MTU)) wsize = min_t(unsigned int, wsize, SMB2_MAX_BUFFER_SIZE); - return wsize; + return prevent_zero_iosize(wsize, "w"); } static unsigned int @@ -524,13 +532,13 @@ smb2_negotiate_rsize(struct cifs_tcon *tcon, struct smb3_fs_context *ctx) unsigned int rsize; /* start with specified rsize, or default */ - rsize = ctx->rsize ? ctx->rsize : CIFS_DEFAULT_IOSIZE; + rsize = ctx->got_rsize ? ctx->vol_rsize : CIFS_DEFAULT_IOSIZE; rsize = min_t(unsigned int, rsize, server->max_read); if (!(server->capabilities & SMB2_GLOBAL_CAP_LARGE_MTU)) rsize = min_t(unsigned int, rsize, SMB2_MAX_BUFFER_SIZE); - return rsize; + return prevent_zero_iosize(rsize, "r"); } static unsigned int @@ -540,7 +548,7 @@ smb3_negotiate_rsize(struct cifs_tcon *tcon, struct smb3_fs_context *ctx) unsigned int rsize; /* start with specified rsize, or default */ - rsize = ctx->rsize ? ctx->rsize : SMB3_DEFAULT_IOSIZE; + rsize = ctx->got_rsize ? ctx->vol_rsize : SMB3_DEFAULT_IOSIZE; rsize = min_t(unsigned int, rsize, server->max_read); #ifdef CONFIG_CIFS_SMB_DIRECT if (server->rdma) { @@ -563,7 +571,7 @@ smb3_negotiate_rsize(struct cifs_tcon *tcon, struct smb3_fs_context *ctx) if (!(server->capabilities & SMB2_GLOBAL_CAP_LARGE_MTU)) rsize = min_t(unsigned int, rsize, SMB2_MAX_BUFFER_SIZE); - return rsize; + return prevent_zero_iosize(rsize, "r"); } /* @@ -3526,8 +3534,6 @@ static long smb3_simple_falloc(struct file *file, struct cifs_tcon *tcon, if (rc == 0) { netfs_resize_file(&cifsi->netfs, new_eof, true); cifs_setsize(inode, new_eof); - cifs_truncate_page(inode->i_mapping, inode->i_size); - truncate_setsize(inode, new_eof); } goto out; }
diff --git a/fs/smb/client/smb2pdu.c b/fs/smb/client/smb2pdu.c index 4f69a18..81e05db 100644 --- a/fs/smb/client/smb2pdu.c +++ b/fs/smb/client/smb2pdu.c
@@ -43,6 +43,7 @@ #endif #include "cached_dir.h" #include "compress.h" +#include "fs_context.h" /* * The following table defines the expected "StructureSize" of SMB2 requests @@ -4089,6 +4090,24 @@ smb2_echo_callback(struct mid_q_entry *mid) add_credits(server, &credits, CIFS_ECHO_OP); } +static void cifs_renegotiate_iosize(struct TCP_Server_Info *server, + struct cifs_tcon *tcon) +{ + struct cifs_sb_info *cifs_sb; + + if (server == NULL || tcon == NULL) + return; + + spin_lock(&tcon->sb_list_lock); + list_for_each_entry(cifs_sb, &tcon->cifs_sb_list, tcon_sb_link) { + cifs_sb->ctx->rsize = + server->ops->negotiate_rsize(tcon, cifs_sb->ctx); + cifs_sb->ctx->wsize = + server->ops->negotiate_wsize(tcon, cifs_sb->ctx); + } + spin_unlock(&tcon->sb_list_lock); +} + void smb2_reconnect_server(struct work_struct *work) { struct TCP_Server_Info *server = container_of(work, @@ -4174,9 +4193,10 @@ void smb2_reconnect_server(struct work_struct *work) list_for_each_entry_safe(tcon, tcon2, &tmp_list, rlist) { rc = smb2_reconnect(SMB2_INTERNAL_CMD, tcon, server, true); - if (!rc) + if (!rc) { + cifs_renegotiate_iosize(server, tcon); cifs_reopen_persistent_handles(tcon); - else + } else resched = true; list_del_init(&tcon->rlist); if (tcon->ipc)
diff --git a/fs/smb/client/transport.c b/fs/smb/client/transport.c index 03434db..266af17 100644 --- a/fs/smb/client/transport.c +++ b/fs/smb/client/transport.c
@@ -894,6 +894,9 @@ cifs_sync_mid_result(struct mid_q_entry *mid, struct TCP_Server_Info *server) case MID_SHUTDOWN: rc = -EHOSTDOWN; break; + case MID_RC: + rc = mid->mid_rc; + break; default: if (!(mid->mid_flags & MID_DELETED)) { list_del_init(&mid->qhead);
diff --git a/fs/smb/client/xattr.c b/fs/smb/client/xattr.c index 7d49f38..b88fa04 100644 --- a/fs/smb/client/xattr.c +++ b/fs/smb/client/xattr.c
@@ -31,6 +31,8 @@ * secure, replaced by SMB2 (then even more highly secure SMB3) many years ago */ #define SMB3_XATTR_CIFS_ACL "system.smb3_acl" /* DACL only */ +#define SMB3_XATTR_CIFS_NTSD_SACL "system.smb3_ntsd_sacl" /* SACL only */ +#define SMB3_XATTR_CIFS_NTSD_OWNER "system.smb3_ntsd_owner" /* owner only */ #define SMB3_XATTR_CIFS_NTSD "system.smb3_ntsd" /* owner plus DACL */ #define SMB3_XATTR_CIFS_NTSD_FULL "system.smb3_ntsd_full" /* owner/DACL/SACL */ #define SMB3_XATTR_ATTRIB "smb3.dosattrib" /* full name: user.smb3.dosattrib */ @@ -38,6 +40,7 @@ /* BB need to add server (Samba e.g) support for security and trusted prefix */ enum { XATTR_USER, XATTR_CIFS_ACL, XATTR_ACL_ACCESS, XATTR_ACL_DEFAULT, + XATTR_CIFS_NTSD_SACL, XATTR_CIFS_NTSD_OWNER, XATTR_CIFS_NTSD, XATTR_CIFS_NTSD_FULL }; static int cifs_attrib_set(unsigned int xid, struct cifs_tcon *pTcon, @@ -160,6 +163,8 @@ static int cifs_xattr_set(const struct xattr_handler *handler, break; case XATTR_CIFS_ACL: + case XATTR_CIFS_NTSD_SACL: + case XATTR_CIFS_NTSD_OWNER: case XATTR_CIFS_NTSD: case XATTR_CIFS_NTSD_FULL: { struct smb_ntsd *pacl; @@ -187,6 +192,13 @@ static int cifs_xattr_set(const struct xattr_handler *handler, CIFS_ACL_GROUP | CIFS_ACL_DACL); break; + case XATTR_CIFS_NTSD_OWNER: + aclflags = (CIFS_ACL_OWNER | + CIFS_ACL_GROUP); + break; + case XATTR_CIFS_NTSD_SACL: + aclflags = CIFS_ACL_SACL; + break; case XATTR_CIFS_ACL: default: aclflags = CIFS_ACL_DACL; @@ -308,6 +320,8 @@ static int cifs_xattr_get(const struct xattr_handler *handler, break; case XATTR_CIFS_ACL: + case XATTR_CIFS_NTSD_SACL: + case XATTR_CIFS_NTSD_OWNER: case XATTR_CIFS_NTSD: case XATTR_CIFS_NTSD_FULL: { /* @@ -327,6 +341,12 @@ static int cifs_xattr_get(const struct xattr_handler *handler, case XATTR_CIFS_NTSD: extra_info = OWNER_SECINFO | GROUP_SECINFO | DACL_SECINFO; break; + case XATTR_CIFS_NTSD_OWNER: + extra_info = OWNER_SECINFO | GROUP_SECINFO; + break; + case XATTR_CIFS_NTSD_SACL: + extra_info = SACL_SECINFO; + break; case XATTR_CIFS_ACL: default: extra_info = DACL_SECINFO; @@ -448,6 +468,20 @@ static const struct xattr_handler smb3_acl_xattr_handler = { .set = cifs_xattr_set, }; +static const struct xattr_handler smb3_ntsd_sacl_xattr_handler = { + .name = SMB3_XATTR_CIFS_NTSD_SACL, + .flags = XATTR_CIFS_NTSD_SACL, + .get = cifs_xattr_get, + .set = cifs_xattr_set, +}; + +static const struct xattr_handler smb3_ntsd_owner_xattr_handler = { + .name = SMB3_XATTR_CIFS_NTSD_OWNER, + .flags = XATTR_CIFS_NTSD_OWNER, + .get = cifs_xattr_get, + .set = cifs_xattr_set, +}; + static const struct xattr_handler cifs_cifs_ntsd_xattr_handler = { .name = CIFS_XATTR_CIFS_NTSD, .flags = XATTR_CIFS_NTSD, @@ -493,6 +527,8 @@ const struct xattr_handler * const cifs_xattr_handlers[] = { &cifs_os2_xattr_handler, &cifs_cifs_acl_xattr_handler, &smb3_acl_xattr_handler, /* alias for above since avoiding "cifs" */ + &smb3_ntsd_sacl_xattr_handler, + &smb3_ntsd_owner_xattr_handler, &cifs_cifs_ntsd_xattr_handler, &smb3_ntsd_xattr_handler, /* alias for above since avoiding "cifs" */ &cifs_cifs_ntsd_full_xattr_handler,
diff --git a/fs/smb/common/smb2pdu.h b/fs/smb/common/smb2pdu.h index c7a0efd..764dca8 100644 --- a/fs/smb/common/smb2pdu.h +++ b/fs/smb/common/smb2pdu.h
@@ -95,6 +95,9 @@ */ #define SMB3_DEFAULT_IOSIZE (4 * 1024 * 1024) +/* According to MS-SMB2 specification The minimum recommended value is 65536.*/ +#define CIFS_MIN_DEFAULT_IOSIZE (65536) + /* * SMB2 Header Definition *
diff --git a/fs/smb/server/auth.c b/fs/smb/server/auth.c index 00b31cf..83caa38 100644 --- a/fs/smb/server/auth.c +++ b/fs/smb/server/auth.c
@@ -1016,9 +1016,9 @@ static int ksmbd_get_encryption_key(struct ksmbd_work *work, __u64 ses_id, ses_enc_key = enc ? sess->smb3encryptionkey : sess->smb3decryptionkey; - if (enc) - ksmbd_user_session_get(sess); memcpy(key, ses_enc_key, SMB3_ENC_DEC_KEY_SIZE); + if (!enc) + ksmbd_user_session_put(sess); return 0; }
diff --git a/fs/smb/server/connection.h b/fs/smb/server/connection.h index 91c2318..14620e1 100644 --- a/fs/smb/server/connection.h +++ b/fs/smb/server/connection.h
@@ -27,6 +27,7 @@ enum { KSMBD_SESS_EXITING, KSMBD_SESS_NEED_RECONNECT, KSMBD_SESS_NEED_NEGOTIATE, + KSMBD_SESS_NEED_SETUP, KSMBD_SESS_RELEASING }; @@ -187,6 +188,11 @@ static inline bool ksmbd_conn_need_negotiate(struct ksmbd_conn *conn) return READ_ONCE(conn->status) == KSMBD_SESS_NEED_NEGOTIATE; } +static inline bool ksmbd_conn_need_setup(struct ksmbd_conn *conn) +{ + return READ_ONCE(conn->status) == KSMBD_SESS_NEED_SETUP; +} + static inline bool ksmbd_conn_need_reconnect(struct ksmbd_conn *conn) { return READ_ONCE(conn->status) == KSMBD_SESS_NEED_RECONNECT; @@ -217,6 +223,11 @@ static inline void ksmbd_conn_set_need_negotiate(struct ksmbd_conn *conn) WRITE_ONCE(conn->status, KSMBD_SESS_NEED_NEGOTIATE); } +static inline void ksmbd_conn_set_need_setup(struct ksmbd_conn *conn) +{ + WRITE_ONCE(conn->status, KSMBD_SESS_NEED_SETUP); +} + static inline void ksmbd_conn_set_need_reconnect(struct ksmbd_conn *conn) { WRITE_ONCE(conn->status, KSMBD_SESS_NEED_RECONNECT);
diff --git a/fs/smb/server/mgmt/user_session.c b/fs/smb/server/mgmt/user_session.c index 53d308f..3f45f28 100644 --- a/fs/smb/server/mgmt/user_session.c +++ b/fs/smb/server/mgmt/user_session.c
@@ -181,7 +181,7 @@ static void ksmbd_expire_session(struct ksmbd_conn *conn) down_write(&sessions_table_lock); down_write(&conn->session_lock); xa_for_each(&conn->sessions, id, sess) { - if (atomic_read(&sess->refcnt) == 0 && + if (atomic_read(&sess->refcnt) <= 1 && (sess->state != SMB2_SESSION_VALID || time_after(jiffies, sess->last_active + SMB2_SESSION_TIMEOUT))) { @@ -233,7 +233,8 @@ void ksmbd_sessions_deregister(struct ksmbd_conn *conn) down_write(&conn->session_lock); xa_erase(&conn->sessions, sess->id); up_write(&conn->session_lock); - ksmbd_session_destroy(sess); + if (atomic_dec_and_test(&sess->refcnt)) + ksmbd_session_destroy(sess); } } } @@ -252,7 +253,8 @@ void ksmbd_sessions_deregister(struct ksmbd_conn *conn) if (xa_empty(&sess->ksmbd_chann_list)) { xa_erase(&conn->sessions, sess->id); hash_del(&sess->hlist); - ksmbd_session_destroy(sess); + if (atomic_dec_and_test(&sess->refcnt)) + ksmbd_session_destroy(sess); } } up_write(&conn->session_lock); @@ -328,8 +330,8 @@ void ksmbd_user_session_put(struct ksmbd_session *sess) if (atomic_read(&sess->refcnt) <= 0) WARN_ON(1); - else - atomic_dec(&sess->refcnt); + else if (atomic_dec_and_test(&sess->refcnt)) + ksmbd_session_destroy(sess); } struct preauth_session *ksmbd_preauth_session_alloc(struct ksmbd_conn *conn, @@ -372,13 +374,13 @@ void destroy_previous_session(struct ksmbd_conn *conn, ksmbd_all_conn_set_status(id, KSMBD_SESS_NEED_RECONNECT); err = ksmbd_conn_wait_idle_sess_id(conn, id); if (err) { - ksmbd_all_conn_set_status(id, KSMBD_SESS_NEED_NEGOTIATE); + ksmbd_all_conn_set_status(id, KSMBD_SESS_NEED_SETUP); goto out; } ksmbd_destroy_file_table(&prev_sess->file_table); prev_sess->state = SMB2_SESSION_EXPIRED; - ksmbd_all_conn_set_status(id, KSMBD_SESS_NEED_NEGOTIATE); + ksmbd_all_conn_set_status(id, KSMBD_SESS_NEED_SETUP); ksmbd_launch_ksmbd_durable_scavenger(); out: up_write(&conn->session_lock); @@ -436,7 +438,7 @@ static struct ksmbd_session *__session_create(int protocol) xa_init(&sess->rpc_handle_list); sess->sequence_number = 1; rwlock_init(&sess->tree_conns_lock); - atomic_set(&sess->refcnt, 1); + atomic_set(&sess->refcnt, 2); ret = __init_smb2_session(sess); if (ret)
diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c index 4ddf430..d24d95d 100644 --- a/fs/smb/server/smb2pdu.c +++ b/fs/smb/server/smb2pdu.c
@@ -1249,7 +1249,7 @@ int smb2_handle_negotiate(struct ksmbd_work *work) } conn->srv_sec_mode = le16_to_cpu(rsp->SecurityMode); - ksmbd_conn_set_need_negotiate(conn); + ksmbd_conn_set_need_setup(conn); err_out: ksmbd_conn_unlock(conn); @@ -1271,6 +1271,9 @@ static int alloc_preauth_hash(struct ksmbd_session *sess, if (sess->Preauth_HashValue) return 0; + if (!conn->preauth_info) + return -ENOMEM; + sess->Preauth_HashValue = kmemdup(conn->preauth_info->Preauth_HashValue, PREAUTH_HASHVALUE_SIZE, KSMBD_DEFAULT_GFP); if (!sess->Preauth_HashValue) @@ -1674,6 +1677,11 @@ int smb2_sess_setup(struct ksmbd_work *work) ksmbd_debug(SMB, "Received smb2 session setup request\n"); + if (!ksmbd_conn_need_setup(conn) && !ksmbd_conn_good(conn)) { + work->send_no_response = 1; + return rc; + } + WORK_BUFFERS(work, req, rsp); rsp->StructureSize = cpu_to_le16(9); @@ -1909,7 +1917,7 @@ int smb2_sess_setup(struct ksmbd_work *work) if (try_delay) { ksmbd_conn_set_need_reconnect(conn); ssleep(5); - ksmbd_conn_set_need_negotiate(conn); + ksmbd_conn_set_need_setup(conn); } } smb2_set_err_rsp(work); @@ -2235,14 +2243,15 @@ int smb2_session_logoff(struct ksmbd_work *work) return -ENOENT; } - ksmbd_destroy_file_table(&sess->file_table); down_write(&conn->session_lock); sess->state = SMB2_SESSION_EXPIRED; up_write(&conn->session_lock); - ksmbd_free_user(sess->user); - sess->user = NULL; - ksmbd_all_conn_set_status(sess_id, KSMBD_SESS_NEED_NEGOTIATE); + if (sess->user) { + ksmbd_free_user(sess->user); + sess->user = NULL; + } + ksmbd_all_conn_set_status(sess_id, KSMBD_SESS_NEED_SETUP); rsp->StructureSize = cpu_to_le16(4); err = ksmbd_iov_pin_rsp(work, rsp, sizeof(struct smb2_logoff_rsp));
diff --git a/fs/smb/server/smbacl.c b/fs/smb/server/smbacl.c index 49b1286..5aa7a66 100644 --- a/fs/smb/server/smbacl.c +++ b/fs/smb/server/smbacl.c
@@ -270,6 +270,11 @@ static int sid_to_id(struct mnt_idmap *idmap, return -EIO; } + if (psid->num_subauth == 0) { + pr_err("%s: zero subauthorities!\n", __func__); + return -EIO; + } + if (sidtype == SIDOWNER) { kuid_t uid; uid_t id; @@ -1026,7 +1031,9 @@ int smb_inherit_dacl(struct ksmbd_conn *conn, struct dentry *parent = path->dentry->d_parent; struct mnt_idmap *idmap = mnt_idmap(path->mnt); int inherited_flags = 0, flags = 0, i, nt_size = 0, pdacl_size; - int rc = 0, dacloffset, pntsd_type, pntsd_size, acl_len, aces_size; + int rc = 0, pntsd_type, pntsd_size, acl_len, aces_size; + unsigned int dacloffset; + size_t dacl_struct_end; u16 num_aces, ace_cnt = 0; char *aces_base; bool is_dir = S_ISDIR(d_inode(path->dentry)->i_mode); @@ -1035,8 +1042,11 @@ int smb_inherit_dacl(struct ksmbd_conn *conn, parent, &parent_pntsd); if (pntsd_size <= 0) return -ENOENT; + dacloffset = le32_to_cpu(parent_pntsd->dacloffset); - if (!dacloffset || (dacloffset + sizeof(struct smb_acl) > pntsd_size)) { + if (!dacloffset || + check_add_overflow(dacloffset, sizeof(struct smb_acl), &dacl_struct_end) || + dacl_struct_end > (size_t)pntsd_size) { rc = -EINVAL; goto free_parent_pntsd; } @@ -1240,7 +1250,9 @@ int smb_check_perm_dacl(struct ksmbd_conn *conn, const struct path *path, struct smb_ntsd *pntsd = NULL; struct smb_acl *pdacl; struct posix_acl *posix_acls; - int rc = 0, pntsd_size, acl_size, aces_size, pdacl_size, dacl_offset; + int rc = 0, pntsd_size, acl_size, aces_size, pdacl_size; + unsigned int dacl_offset; + size_t dacl_struct_end; struct smb_sid sid; int granted = le32_to_cpu(*pdaccess & ~FILE_MAXIMAL_ACCESS_LE); struct smb_ace *ace; @@ -1259,7 +1271,8 @@ int smb_check_perm_dacl(struct ksmbd_conn *conn, const struct path *path, dacl_offset = le32_to_cpu(pntsd->dacloffset); if (!dacl_offset || - (dacl_offset + sizeof(struct smb_acl) > pntsd_size)) + check_add_overflow(dacl_offset, sizeof(struct smb_acl), &dacl_struct_end) || + dacl_struct_end > (size_t)pntsd_size) goto err_out; pdacl = (struct smb_acl *)((char *)pntsd + le32_to_cpu(pntsd->dacloffset));
diff --git a/fs/userfaultfd.c b/fs/userfaultfd.c index 97c4d71..d80f943 100644 --- a/fs/userfaultfd.c +++ b/fs/userfaultfd.c
@@ -396,32 +396,6 @@ vm_fault_t handle_userfault(struct vm_fault *vmf, unsigned long reason) goto out; /* - * If it's already released don't get it. This avoids to loop - * in __get_user_pages if userfaultfd_release waits on the - * caller of handle_userfault to release the mmap_lock. - */ - if (unlikely(READ_ONCE(ctx->released))) { - /* - * Don't return VM_FAULT_SIGBUS in this case, so a non - * cooperative manager can close the uffd after the - * last UFFDIO_COPY, without risking to trigger an - * involuntary SIGBUS if the process was starting the - * userfaultfd while the userfaultfd was still armed - * (but after the last UFFDIO_COPY). If the uffd - * wasn't already closed when the userfault reached - * this point, that would normally be solved by - * userfaultfd_must_wait returning 'false'. - * - * If we were to return VM_FAULT_SIGBUS here, the non - * cooperative manager would be instead forced to - * always call UFFDIO_UNREGISTER before it can safely - * close the uffd. - */ - ret = VM_FAULT_NOPAGE; - goto out; - } - - /* * Check that we can return VM_FAULT_RETRY. * * NOTE: it should become possible to return VM_FAULT_RETRY @@ -457,6 +431,31 @@ vm_fault_t handle_userfault(struct vm_fault *vmf, unsigned long reason) if (vmf->flags & FAULT_FLAG_RETRY_NOWAIT) goto out; + if (unlikely(READ_ONCE(ctx->released))) { + /* + * If a concurrent release is detected, do not return + * VM_FAULT_SIGBUS or VM_FAULT_NOPAGE, but instead always + * return VM_FAULT_RETRY with lock released proactively. + * + * If we were to return VM_FAULT_SIGBUS here, the non + * cooperative manager would be instead forced to + * always call UFFDIO_UNREGISTER before it can safely + * close the uffd, to avoid involuntary SIGBUS triggered. + * + * If we were to return VM_FAULT_NOPAGE, it would work for + * the fault path, in which the lock will be released + * later. However for GUP, faultin_page() does nothing + * special on NOPAGE, so GUP would spin retrying without + * releasing the mmap read lock, causing possible livelock. + * + * Here only VM_FAULT_RETRY would make sure the mmap lock + * be released immediately, so that the thread concurrently + * releasing the userfault would always make progress. + */ + release_fault_lock(vmf); + goto out; + } + /* take the reference before dropping the mmap_lock */ userfaultfd_ctx_get(ctx);
diff --git a/fs/xfs/Kconfig b/fs/xfs/Kconfig index fffd6ff..ae0ca68 100644 --- a/fs/xfs/Kconfig +++ b/fs/xfs/Kconfig
@@ -3,7 +3,7 @@ tristate "XFS filesystem support" depends on BLOCK select EXPORTFS - select LIBCRC32C + select CRC32 select FS_IOMAP help XFS is a high performance journaling filesystem which originated
diff --git a/include/asm-generic/module.h b/include/asm-generic/module.h index 98e1541..a862250 100644 --- a/include/asm-generic/module.h +++ b/include/asm-generic/module.h
@@ -19,12 +19,8 @@ struct mod_arch_specific #define Elf_Dyn Elf64_Dyn #define Elf_Ehdr Elf64_Ehdr #define Elf_Addr Elf64_Addr -#ifdef CONFIG_MODULES_USE_ELF_REL #define Elf_Rel Elf64_Rel -#endif -#ifdef CONFIG_MODULES_USE_ELF_RELA #define Elf_Rela Elf64_Rela -#endif #define ELF_R_TYPE(X) ELF64_R_TYPE(X) #define ELF_R_SYM(X) ELF64_R_SYM(X) @@ -36,12 +32,8 @@ struct mod_arch_specific #define Elf_Dyn Elf32_Dyn #define Elf_Ehdr Elf32_Ehdr #define Elf_Addr Elf32_Addr -#ifdef CONFIG_MODULES_USE_ELF_REL #define Elf_Rel Elf32_Rel -#endif -#ifdef CONFIG_MODULES_USE_ELF_RELA #define Elf_Rela Elf32_Rela -#endif #define ELF_R_TYPE(X) ELF32_R_TYPE(X) #define ELF_R_SYM(X) ELF32_R_SYM(X) #endif
diff --git a/include/asm-generic/tlb.h b/include/asm-generic/tlb.h index d1adfba..88a4297 100644 --- a/include/asm-generic/tlb.h +++ b/include/asm-generic/tlb.h
@@ -227,10 +227,10 @@ static inline void tlb_remove_page(struct mmu_gather *tlb, struct page *page); */ static inline void tlb_remove_table(struct mmu_gather *tlb, void *table) { - struct page *page = (struct page *)table; + struct ptdesc *ptdesc = (struct ptdesc *)table; - pagetable_dtor(page_ptdesc(page)); - tlb_remove_page(tlb, page); + pagetable_dtor(ptdesc); + tlb_remove_page(tlb, ptdesc_page(ptdesc)); } #endif /* CONFIG_MMU_GATHER_TABLE_FREE */ @@ -493,17 +493,11 @@ static inline void tlb_remove_page(struct mmu_gather *tlb, struct page *page) return tlb_remove_page_size(tlb, page, PAGE_SIZE); } -static inline void tlb_remove_ptdesc(struct mmu_gather *tlb, void *pt) +static inline void tlb_remove_ptdesc(struct mmu_gather *tlb, struct ptdesc *pt) { tlb_remove_table(tlb, pt); } -/* Like tlb_remove_ptdesc, but for page-like page directories. */ -static inline void tlb_remove_page_ptdesc(struct mmu_gather *tlb, struct ptdesc *pt) -{ - tlb_remove_page(tlb, ptdesc_page(pt)); -} - static inline void tlb_change_page_size(struct mmu_gather *tlb, unsigned int page_size) {
diff --git a/include/cxl/event.h b/include/cxl/event.h index 04edd44..f9ae179 100644 --- a/include/cxl/event.h +++ b/include/cxl/event.h
@@ -164,10 +164,99 @@ struct cxl_cper_work_data { struct cxl_cper_event_rec rec; }; +#define PROT_ERR_VALID_AGENT_TYPE BIT_ULL(0) +#define PROT_ERR_VALID_AGENT_ADDRESS BIT_ULL(1) +#define PROT_ERR_VALID_DEVICE_ID BIT_ULL(2) +#define PROT_ERR_VALID_SERIAL_NUMBER BIT_ULL(3) +#define PROT_ERR_VALID_CAPABILITY BIT_ULL(4) +#define PROT_ERR_VALID_DVSEC BIT_ULL(5) +#define PROT_ERR_VALID_ERROR_LOG BIT_ULL(6) + +/* + * The layout of the enumeration and the values matches CXL Agent Type + * field in the UEFI 2.10 Section N.2.13, + */ +enum { + RCD, /* Restricted CXL Device */ + RCH_DP, /* Restricted CXL Host Downstream Port */ + DEVICE, /* CXL Device */ + LD, /* CXL Logical Device */ + FMLD, /* CXL Fabric Manager managed Logical Device */ + RP, /* CXL Root Port */ + DSP, /* CXL Downstream Switch Port */ + USP, /* CXL Upstream Switch Port */ +}; + +#pragma pack(1) + +/* Compute Express Link Protocol Error Section, UEFI v2.10 sec N.2.13 */ +struct cxl_cper_sec_prot_err { + u64 valid_bits; + u8 agent_type; + u8 reserved[7]; + + /* + * Except for RCH Downstream Port, all the remaining CXL Agent + * types are uniquely identified by the PCIe compatible SBDF number. + */ + union { + u64 rcrb_base_addr; + struct { + u8 function; + u8 device; + u8 bus; + u16 segment; + u8 reserved_1[3]; + }; + } agent_addr; + + struct { + u16 vendor_id; + u16 device_id; + u16 subsystem_vendor_id; + u16 subsystem_id; + u8 class_code[2]; + u16 slot; + u8 reserved_1[4]; + } device_id; + + struct { + u32 lower_dw; + u32 upper_dw; + } dev_serial_num; + + u8 capability[60]; + u16 dvsec_len; + u16 err_len; + u8 reserved_2[4]; +}; + +#pragma pack() + +/* CXL RAS Capability Structure, CXL v3.0 sec 8.2.4.16 */ +struct cxl_ras_capability_regs { + u32 uncor_status; + u32 uncor_mask; + u32 uncor_severity; + u32 cor_status; + u32 cor_mask; + u32 cap_control; + u32 header_log[16]; +}; + +struct cxl_cper_prot_err_work_data { + struct cxl_cper_sec_prot_err prot_err; + struct cxl_ras_capability_regs ras_cap; + int severity; +}; + #ifdef CONFIG_ACPI_APEI_GHES int cxl_cper_register_work(struct work_struct *work); int cxl_cper_unregister_work(struct work_struct *work); int cxl_cper_kfifo_get(struct cxl_cper_work_data *wd); +int cxl_cper_register_prot_err_work(struct work_struct *work); +int cxl_cper_unregister_prot_err_work(struct work_struct *work); +int cxl_cper_prot_err_kfifo_get(struct cxl_cper_prot_err_work_data *wd); #else static inline int cxl_cper_register_work(struct work_struct *work) { @@ -182,6 +271,18 @@ static inline int cxl_cper_kfifo_get(struct cxl_cper_work_data *wd) { return 0; } +static inline int cxl_cper_register_prot_err_work(struct work_struct *work) +{ + return 0; +} +static inline int cxl_cper_unregister_prot_err_work(struct work_struct *work) +{ + return 0; +} +static inline int cxl_cper_prot_err_kfifo_get(struct cxl_cper_prot_err_work_data *wd) +{ + return 0; +} #endif #endif /* _LINUX_CXL_EVENT_H */
diff --git a/include/linux/acpi.h b/include/linux/acpi.h index a70e62d..3f2e93e 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h
@@ -1094,6 +1094,17 @@ static inline acpi_handle acpi_get_processor_handle(int cpu) #endif /* !CONFIG_ACPI */ +#ifdef CONFIG_ACPI_HMAT +int hmat_get_extended_linear_cache_size(struct resource *backing_res, int nid, + resource_size_t *size); +#else +static inline int hmat_get_extended_linear_cache_size(struct resource *backing_res, + int nid, resource_size_t *size) +{ + return -EOPNOTSUPP; +} +#endif + extern void arch_post_acpi_subsys_init(void); #ifdef CONFIG_ACPI_HOTPLUG_IOAPIC
diff --git a/include/linux/bvec.h b/include/linux/bvec.h index ba8f52d..204b22a 100644 --- a/include/linux/bvec.h +++ b/include/linux/bvec.h
@@ -184,6 +184,12 @@ static inline void bvec_iter_advance_single(const struct bio_vec *bv, ((bvl = bvec_iter_bvec((bio_vec), (iter))), 1); \ bvec_iter_advance_single((bio_vec), &(iter), (bvl).bv_len)) +#define for_each_mp_bvec(bvl, bio_vec, iter, start) \ + for (iter = (start); \ + (iter).bi_size && \ + ((bvl = mp_bvec_iter_bvec((bio_vec), (iter))), 1); \ + bvec_iter_advance_single((bio_vec), &(iter), (bvl).bv_len)) + /* for iterating one bio from start to end */ #define BVEC_ITER_ALL_INIT (struct bvec_iter) \ { \
diff --git a/include/linux/cgroup-defs.h b/include/linux/cgroup-defs.h index 485b651..5bc8f55 100644 --- a/include/linux/cgroup-defs.h +++ b/include/linux/cgroup-defs.h
@@ -710,6 +710,7 @@ struct cgroup_subsys { void (*css_released)(struct cgroup_subsys_state *css); void (*css_free)(struct cgroup_subsys_state *css); void (*css_reset)(struct cgroup_subsys_state *css); + void (*css_killed)(struct cgroup_subsys_state *css); void (*css_rstat_flush)(struct cgroup_subsys_state *css, int cpu); int (*css_extra_stat_show)(struct seq_file *seq, struct cgroup_subsys_state *css);
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h index 28e999f..e7da3c3 100644 --- a/include/linux/cgroup.h +++ b/include/linux/cgroup.h
@@ -344,7 +344,7 @@ static inline u64 cgroup_id(const struct cgroup *cgrp) */ static inline bool css_is_dying(struct cgroup_subsys_state *css) { - return !(css->flags & CSS_NO_REF) && percpu_ref_is_dying(&css->refcnt); + return css->flags & CSS_DYING; } static inline void cgroup_get(struct cgroup *cgrp)
diff --git a/include/linux/context_tracking_irq.h b/include/linux/context_tracking_irq.h index c50b567..197916e 100644 --- a/include/linux/context_tracking_irq.h +++ b/include/linux/context_tracking_irq.h
@@ -10,12 +10,12 @@ void ct_irq_exit_irqson(void); void ct_nmi_enter(void); void ct_nmi_exit(void); #else -static inline void ct_irq_enter(void) { } -static inline void ct_irq_exit(void) { } +static __always_inline void ct_irq_enter(void) { } +static __always_inline void ct_irq_exit(void) { } static inline void ct_irq_enter_irqson(void) { } static inline void ct_irq_exit_irqson(void) { } -static inline void ct_nmi_enter(void) { } -static inline void ct_nmi_exit(void) { } +static __always_inline void ct_nmi_enter(void) { } +static __always_inline void ct_nmi_exit(void) { } #endif #endif
diff --git a/include/linux/cper.h b/include/linux/cper.h index 265b0f8..0ed60a9 100644 --- a/include/linux/cper.h +++ b/include/linux/cper.h
@@ -89,6 +89,10 @@ enum { #define CPER_NOTIFY_DMAR \ GUID_INIT(0x667DD791, 0xC6B3, 0x4c27, 0x8A, 0x6B, 0x0F, 0x8E, \ 0x72, 0x2D, 0xEB, 0x41) +/* CXL Protocol Error Section */ +#define CPER_SEC_CXL_PROT_ERR \ + GUID_INIT(0x80B9EFB4, 0x52B5, 0x4DE3, 0xA7, 0x77, 0x68, 0x78, \ + 0x4B, 0x77, 0x10, 0x48) /* CXL Event record UUIDs are formatted as GUIDs and reported in section type */ /* @@ -601,4 +605,8 @@ void cper_estatus_print(const char *pfx, int cper_estatus_check_header(const struct acpi_hest_generic_status *estatus); int cper_estatus_check(const struct acpi_hest_generic_status *estatus); +struct cxl_cper_sec_prot_err; +void cxl_cper_print_prot_err(const char *pfx, + const struct cxl_cper_sec_prot_err *prot_err); + #endif
diff --git a/include/linux/fsl/mc.h b/include/linux/fsl/mc.h index 99f30c7..897d621 100644 --- a/include/linux/fsl/mc.h +++ b/include/linux/fsl/mc.h
@@ -417,8 +417,6 @@ int __must_check fsl_mc_portal_allocate(struct fsl_mc_device *mc_dev, void fsl_mc_portal_free(struct fsl_mc_io *mc_io); -int fsl_mc_portal_reset(struct fsl_mc_io *mc_io); - int __must_check fsl_mc_object_allocate(struct fsl_mc_device *mc_dev, enum fsl_mc_pool_type pool_type, struct fsl_mc_device **new_mc_adev);
diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h index 88e0788..1adcba3 100644 --- a/include/linux/hrtimer.h +++ b/include/linux/hrtimer.h
@@ -231,8 +231,6 @@ static inline enum hrtimer_restart hrtimer_dummy_timeout(struct hrtimer *unused) /* Exported timer functions: */ /* Initialize timers: */ -extern void hrtimer_init(struct hrtimer *timer, clockid_t which_clock, - enum hrtimer_mode mode); extern void hrtimer_setup(struct hrtimer *timer, enum hrtimer_restart (*function)(struct hrtimer *), clockid_t clock_id, enum hrtimer_mode mode); extern void hrtimer_setup_on_stack(struct hrtimer *timer,
diff --git a/include/linux/hrtimer_types.h b/include/linux/hrtimer_types.h index ad66a30..8fbbb6b 100644 --- a/include/linux/hrtimer_types.h +++ b/include/linux/hrtimer_types.h
@@ -34,12 +34,12 @@ enum hrtimer_restart { * @is_hard: Set if hrtimer will be expired in hard interrupt context * even on RT. * - * The hrtimer structure must be initialized by hrtimer_init() + * The hrtimer structure must be initialized by hrtimer_setup() */ struct hrtimer { struct timerqueue_node node; ktime_t _softexpires; - enum hrtimer_restart (*function)(struct hrtimer *); + enum hrtimer_restart (*__private function)(struct hrtimer *); struct hrtimer_clock_base *base; u8 state; u8 is_rel;
diff --git a/include/linux/io_uring/cmd.h b/include/linux/io_uring/cmd.h index e6723fa..0634a3d 100644 --- a/include/linux/io_uring/cmd.h +++ b/include/linux/io_uring/cmd.h
@@ -21,7 +21,6 @@ struct io_uring_cmd { struct io_uring_cmd_data { void *op_data; - struct io_uring_sqe sqes[2]; }; static inline const void *io_uring_sqe_cmd(const struct io_uring_sqe *sqe)
diff --git a/include/linux/iomap.h b/include/linux/iomap.h index 02fe001..68416b1 100644 --- a/include/linux/iomap.h +++ b/include/linux/iomap.h
@@ -79,6 +79,11 @@ struct vm_fault; #define IOMAP_F_ATOMIC_BIO (1U << 8) /* + * Flag reserved for file system specific usage + */ +#define IOMAP_F_PRIVATE (1U << 12) + +/* * Flags set by the core iomap code during operations: * * IOMAP_F_SIZE_CHANGED indicates to the iomap_end method that the file size @@ -88,14 +93,8 @@ struct vm_fault; * range it covers needs to be remapped by the high level before the operation * can proceed. */ -#define IOMAP_F_SIZE_CHANGED (1U << 8) -#define IOMAP_F_STALE (1U << 9) - -/* - * Flags from 0x1000 up are for file system specific usage: - */ -#define IOMAP_F_PRIVATE (1U << 12) - +#define IOMAP_F_SIZE_CHANGED (1U << 14) +#define IOMAP_F_STALE (1U << 15) /* * Magic value for addr:
diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h index 33ff41e..bb71111 100644 --- a/include/linux/irqdomain.h +++ b/include/linux/irqdomain.h
@@ -72,7 +72,7 @@ void of_phandle_args_to_fwspec(struct device_node *np, const u32 *args, /** * struct irq_domain_ops - Methods for irq_domain objects - * @match: Match an interrupt controller device node to a host, returns + * @match: Match an interrupt controller device node to a domain, returns * 1 on a match * @select: Match an interrupt controller fw specification. It is more generic * than @match as it receives a complete struct irq_fwspec. Therefore, @@ -352,8 +352,8 @@ struct irq_domain *irq_domain_create_legacy(struct fwnode_handle *fwnode, void *host_data); struct irq_domain *irq_find_matching_fwspec(struct irq_fwspec *fwspec, enum irq_domain_bus_token bus_token); -void irq_set_default_host(struct irq_domain *host); -struct irq_domain *irq_get_default_host(void); +void irq_set_default_domain(struct irq_domain *domain); +struct irq_domain *irq_get_default_domain(void); int irq_domain_alloc_descs(int virq, unsigned int nr_irqs, irq_hw_number_t hwirq, int node, const struct irq_affinity_desc *affinity); @@ -454,7 +454,7 @@ static inline struct irq_domain *irq_domain_add_nomap(struct device_node *of_nod return IS_ERR(d) ? NULL : d; } -unsigned int irq_create_direct_mapping(struct irq_domain *host); +unsigned int irq_create_direct_mapping(struct irq_domain *domain); #endif static inline struct irq_domain *irq_domain_add_tree(struct device_node *of_node, @@ -507,7 +507,7 @@ static inline struct irq_domain *irq_domain_create_tree(struct fwnode_handle *fw return IS_ERR(d) ? NULL : d; } -void irq_domain_remove(struct irq_domain *host); +void irq_domain_remove(struct irq_domain *domain); int irq_domain_associate(struct irq_domain *domain, unsigned int irq, irq_hw_number_t hwirq); @@ -515,16 +515,16 @@ void irq_domain_associate_many(struct irq_domain *domain, unsigned int irq_base, irq_hw_number_t hwirq_base, int count); -unsigned int irq_create_mapping_affinity(struct irq_domain *host, +unsigned int irq_create_mapping_affinity(struct irq_domain *domain, irq_hw_number_t hwirq, const struct irq_affinity_desc *affinity); unsigned int irq_create_fwspec_mapping(struct irq_fwspec *fwspec); void irq_dispose_mapping(unsigned int virq); -static inline unsigned int irq_create_mapping(struct irq_domain *host, +static inline unsigned int irq_create_mapping(struct irq_domain *domain, irq_hw_number_t hwirq) { - return irq_create_mapping_affinity(host, hwirq, NULL); + return irq_create_mapping_affinity(domain, hwirq, NULL); } struct irq_desc *__irq_resolve_mapping(struct irq_domain *domain,
diff --git a/include/linux/kdb.h b/include/linux/kdb.h index 905a2e2..ecbf819 100644 --- a/include/linux/kdb.h +++ b/include/linux/kdb.h
@@ -104,7 +104,7 @@ extern int kdb_initial_cpu; #define KDB_NOENVVALUE (-6) #define KDB_NOTIMP (-7) #define KDB_ENVFULL (-8) -#define KDB_ENVBUFFULL (-9) +#define KDB_KMALLOCFAILED (-9) #define KDB_TOOMANYBPT (-10) #define KDB_TOOMANYDBREGS (-11) #define KDB_DUPBPT (-12)
diff --git a/include/linux/kgdb.h b/include/linux/kgdb.h index 51ef131..5eebbe7 100644 --- a/include/linux/kgdb.h +++ b/include/linux/kgdb.h
@@ -257,7 +257,6 @@ extern void kgdb_arch_late(void); * hardware breakpoints. * @correct_hw_break: Allow an architecture to specify how to correct the * hardware debug registers. - * @enable_nmi: Manage NMI-triggered entry to KGDB */ struct kgdb_arch { unsigned char gdb_bpt_instr[BREAK_INSTR_SIZE]; @@ -270,8 +269,6 @@ struct kgdb_arch { void (*disable_hw_break)(struct pt_regs *regs); void (*remove_all_hw_break)(void); void (*correct_hw_break)(void); - - void (*enable_nmi)(bool on); }; /** @@ -306,14 +303,6 @@ extern const struct kgdb_arch arch_kgdb_ops; extern unsigned long kgdb_arch_pc(int exception, struct pt_regs *regs); -#ifdef CONFIG_SERIAL_KGDB_NMI -extern int kgdb_register_nmi_console(void); -extern int kgdb_unregister_nmi_console(void); -#else -static inline int kgdb_register_nmi_console(void) { return 0; } -static inline int kgdb_unregister_nmi_console(void) { return 0; } -#endif - extern int kgdb_register_io_module(struct kgdb_io *local_kgdb_io_ops); extern void kgdb_unregister_io_module(struct kgdb_io *local_kgdb_io_ops); extern struct kgdb_io *dbg_io_ops;
diff --git a/include/linux/linkage.h b/include/linux/linkage.h index 5c8865b..b11660b 100644 --- a/include/linux/linkage.h +++ b/include/linux/linkage.h
@@ -134,10 +134,6 @@ .size name, .-name #endif -/* If symbol 'name' is treated as a subroutine (gets called, and returns) - * then please use ENDPROC to mark 'name' as STT_FUNC for the benefit of - * static analysis tools such as stack depth analyzer. - */ #ifndef ENDPROC /* deprecated, use SYM_FUNC_END */ #define ENDPROC(name) \
diff --git a/include/linux/mfd/mt6397/rtc.h b/include/linux/mfd/mt6397/rtc.h index 068ae1c..27883af 100644 --- a/include/linux/mfd/mt6397/rtc.h +++ b/include/linux/mfd/mt6397/rtc.h
@@ -60,11 +60,6 @@ #define RTC_PDN2 0x002e #define RTC_PDN2_PWRON_ALARM BIT(4) -#define RTC_MIN_YEAR 1968 -#define RTC_BASE_YEAR 1900 -#define RTC_NUM_YEARS 128 -#define RTC_MIN_YEAR_OFFSET (RTC_MIN_YEAR - RTC_BASE_YEAR) - #define MTK_RTC_POLL_DELAY_US 10 #define MTK_RTC_POLL_TIMEOUT (jiffies_to_usecs(HZ))
diff --git a/include/linux/mm.h b/include/linux/mm.h index 32ba0e3..b7f13f0 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h
@@ -2495,11 +2495,13 @@ struct follow_pfnmap_args { * Outputs: * * @pfn: the PFN of the address + * @addr_mask: address mask covering pfn * @pgprot: the pgprot_t of the mapping * @writable: whether the mapping is writable * @special: whether the mapping is a special mapping (real PFN maps) */ unsigned long pfn; + unsigned long addr_mask; pgprot_t pgprot; bool writable; bool special; @@ -4236,4 +4238,14 @@ int arch_get_shadow_stack_status(struct task_struct *t, unsigned long __user *st int arch_set_shadow_stack_status(struct task_struct *t, unsigned long status); int arch_lock_shadow_stack_status(struct task_struct *t, unsigned long status); + +/* + * mseal of userspace process's system mappings. + */ +#ifdef CONFIG_MSEAL_SYSTEM_MAPPINGS +#define VM_SEALED_SYSMAP VM_SEALED +#else +#define VM_SEALED_SYSMAP VM_NONE +#endif + #endif /* _LINUX_MM_H */
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index fa79145..cf3b644 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h
@@ -4192,7 +4192,7 @@ int dev_change_flags(struct net_device *dev, unsigned int flags, int netif_set_alias(struct net_device *dev, const char *alias, size_t len); int dev_set_alias(struct net_device *, const char *, size_t); int dev_get_alias(const struct net_device *, char *, size_t); -int netif_change_net_namespace(struct net_device *dev, struct net *net, +int __dev_change_net_namespace(struct net_device *dev, struct net *net, const char *pat, int new_ifindex, struct netlink_ext_ack *extack); int dev_change_net_namespace(struct net_device *dev, struct net *net,
diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h index 9ac83ca..d8cad84 100644 --- a/include/linux/nfs4.h +++ b/include/linux/nfs4.h
@@ -300,6 +300,7 @@ enum nfsstat4 { /* error codes for internal client use */ #define NFS4ERR_RESET_TO_MDS 12001 #define NFS4ERR_RESET_TO_PNFS 12002 +#define NFS4ERR_FATAL_IOERROR 12003 static inline bool seqid_mutating_err(u32 err) { @@ -691,6 +692,7 @@ enum { NFSPROC4_CLNT_LISTXATTRS, NFSPROC4_CLNT_REMOVEXATTR, NFSPROC4_CLNT_READ_PLUS, + NFSPROC4_CLNT_OFFLOAD_STATUS, }; /* nfs41 types */
diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h index f00bfce..7131963 100644 --- a/include/linux/nfs_fs_sb.h +++ b/include/linux/nfs_fs_sb.h
@@ -50,6 +50,7 @@ struct nfs_client { #define NFS_CS_DS 7 /* - Server is a DS */ #define NFS_CS_REUSEPORT 8 /* - reuse src port on reconnect */ #define NFS_CS_PNFS 9 /* - Server used for pnfs */ +#define NFS_CS_NETUNREACH_FATAL 10 /* - ENETUNREACH errors are fatal */ struct sockaddr_storage cl_addr; /* server identifier */ size_t cl_addrlen; char * cl_hostname; /* hostname of server */ @@ -167,6 +168,8 @@ struct nfs_server { #define NFS_MOUNT_TRUNK_DISCOVERY 0x04000000 #define NFS_MOUNT_SHUTDOWN 0x08000000 #define NFS_MOUNT_NO_ALIGNWRITE 0x10000000 +#define NFS_MOUNT_FORCE_RDIRPLUS 0x20000000 +#define NFS_MOUNT_NETUNREACH_FATAL 0x40000000 unsigned int fattr_valid; /* Valid attributes */ unsigned int caps; /* server capabilities */ @@ -250,6 +253,10 @@ struct nfs_server { struct list_head ss_copies; struct list_head ss_src_copies; + unsigned long delegation_flags; +#define NFS4SERV_DELEGRETURN (1) +#define NFS4SERV_DELEGATION_EXPIRED (2) +#define NFS4SERV_DELEGRETURN_DELAYED (3) unsigned long delegation_gen; unsigned long mig_gen; unsigned long mig_status; @@ -289,6 +296,7 @@ struct nfs_server { #define NFS_CAP_CASE_INSENSITIVE (1U << 6) #define NFS_CAP_CASE_PRESERVING (1U << 7) #define NFS_CAP_REBOOT_LAYOUTRETURN (1U << 8) +#define NFS_CAP_OFFLOAD_STATUS (1U << 9) #define NFS_CAP_OPEN_XOR (1U << 12) #define NFS_CAP_DELEGTIME (1U << 13) #define NFS_CAP_POSIX_LOCK (1U << 14)
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index d66c61c..67f6632 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h
@@ -1515,8 +1515,9 @@ struct nfs42_offload_status_args { struct nfs42_offload_status_res { struct nfs4_sequence_res osr_seq_res; - uint64_t osr_count; - int osr_status; + u64 osr_count; + int complete_count; + u32 osr_complete; }; struct nfs42_copy_notify_args {
diff --git a/include/linux/node.h b/include/linux/node.h index 9a881c2..2b75178 100644 --- a/include/linux/node.h +++ b/include/linux/node.h
@@ -57,6 +57,11 @@ enum cache_write_policy { NODE_CACHE_WRITE_OTHER, }; +enum cache_mode { + NODE_CACHE_ADDR_MODE_RESERVED, + NODE_CACHE_ADDR_MODE_EXTENDED_LINEAR, +}; + /** * struct node_cache_attrs - system memory caching attributes * @@ -65,6 +70,7 @@ enum cache_write_policy { * @size: Total size of cache in bytes * @line_size: Number of bytes fetched on a cache miss * @level: The cache hierarchy level + * @address_mode: The address mode */ struct node_cache_attrs { enum cache_indexing indexing; @@ -72,6 +78,7 @@ struct node_cache_attrs { u64 size; u16 line_size; u8 level; + u16 address_mode; }; #ifdef CONFIG_HMEM_REPORTING
diff --git a/include/linux/objtool.h b/include/linux/objtool.h index 3ca965a..366ad00 100644 --- a/include/linux/objtool.h +++ b/include/linux/objtool.h
@@ -69,7 +69,7 @@ * In asm, there are two kinds of code: normal C-type callable functions and * the rest. The normal callable functions can be called by other code, and * don't do anything unusual with the stack. Such normal callable functions - * are annotated with the ENTRY/ENDPROC macros. Most asm code falls in this + * are annotated with SYM_FUNC_{START,END}. Most asm code falls in this * category. In this case, no special debugging annotations are needed because * objtool can automatically generate the ORC data for the ORC unwinder to read * at runtime.
diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h index 5bd9492..e6a21b6 100644 --- a/include/linux/page-flags.h +++ b/include/linux/page-flags.h
@@ -226,11 +226,48 @@ static __always_inline const struct page *page_fixed_fake_head(const struct page } return page; } + +static __always_inline bool page_count_writable(const struct page *page, int u) +{ + if (!static_branch_unlikely(&hugetlb_optimize_vmemmap_key)) + return true; + + /* + * The refcount check is ordered before the fake-head check to prevent + * the following race: + * CPU 1 (HVO) CPU 2 (speculative PFN walker) + * + * page_ref_freeze() + * synchronize_rcu() + * rcu_read_lock() + * page_is_fake_head() is false + * vmemmap_remap_pte() + * XXX: struct page[] becomes r/o + * + * page_ref_unfreeze() + * page_ref_count() is not zero + * + * atomic_add_unless(&page->_refcount) + * XXX: try to modify r/o struct page[] + * + * The refcount check also prevents modification attempts to other (r/o) + * tail pages that are not fake heads. + */ + if (atomic_read_acquire(&page->_refcount) == u) + return false; + + return page_fixed_fake_head(page) == page; +} #else static inline const struct page *page_fixed_fake_head(const struct page *page) { return page; } + +static inline bool page_count_writable(const struct page *page, int u) +{ + return true; +} #endif static __always_inline int page_is_fake_head(const struct page *page)
diff --git a/include/linux/page_ref.h b/include/linux/page_ref.h index 8c236c6..544150d 100644 --- a/include/linux/page_ref.h +++ b/include/linux/page_ref.h
@@ -234,7 +234,7 @@ static inline bool page_ref_add_unless(struct page *page, int nr, int u) rcu_read_lock(); /* avoid writing to the vmemmap area being remapped */ - if (!page_is_fake_head(page) && page_ref_count(page) != u) + if (page_count_writable(page, u)) ret = atomic_add_unless(&page->_refcount, nr, u); rcu_read_unlock();
diff --git a/include/linux/platform_data/cros_ec_commands.h b/include/linux/platform_data/cros_ec_commands.h index ecf290a..1f4e4f2 100644 --- a/include/linux/platform_data/cros_ec_commands.h +++ b/include/linux/platform_data/cros_ec_commands.h
@@ -5046,6 +5046,7 @@ struct ec_response_pd_status { #define PD_EVENT_DATA_SWAP BIT(3) #define PD_EVENT_TYPEC BIT(4) #define PD_EVENT_PPM BIT(5) +#define PD_EVENT_INIT BIT(6) struct ec_response_host_event_status { uint32_t status; /* PD MCU host event status */
diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h index f8159f8..120536f 100644 --- a/include/linux/rcupdate.h +++ b/include/linux/rcupdate.h
@@ -132,7 +132,7 @@ static inline void rcu_sysrq_end(void) { } #if defined(CONFIG_NO_HZ_FULL) && (!defined(CONFIG_GENERIC_ENTRY) || !defined(CONFIG_KVM_XFER_TO_GUEST_WORK)) void rcu_irq_work_resched(void); #else -static inline void rcu_irq_work_resched(void) { } +static __always_inline void rcu_irq_work_resched(void) { } #endif #ifdef CONFIG_RCU_NOCB_CPU
diff --git a/include/linux/rtc.h b/include/linux/rtc.h index 3f4d315..95da051f 100644 --- a/include/linux/rtc.h +++ b/include/linux/rtc.h
@@ -170,6 +170,7 @@ struct rtc_device { /* useful timestamps */ #define RTC_TIMESTAMP_BEGIN_0000 -62167219200ULL /* 0000-01-01 00:00:00 */ #define RTC_TIMESTAMP_BEGIN_1900 -2208988800LL /* 1900-01-01 00:00:00 */ +#define RTC_TIMESTAMP_EPOCH_GPS 315964800LL /* 1980-01-06 00:00:00 */ #define RTC_TIMESTAMP_BEGIN_2000 946684800LL /* 2000-01-01 00:00:00 */ #define RTC_TIMESTAMP_END_2063 2966371199LL /* 2063-12-31 23:59:59 */ #define RTC_TIMESTAMP_END_2079 3471292799LL /* 2079-12-31 23:59:59 */
diff --git a/include/linux/sched/smt.h b/include/linux/sched/smt.h index fb1e295..166b19a 100644 --- a/include/linux/sched/smt.h +++ b/include/linux/sched/smt.h
@@ -12,7 +12,7 @@ static __always_inline bool sched_smt_active(void) return static_branch_likely(&sched_smt_present); } #else -static inline bool sched_smt_active(void) { return false; } +static __always_inline bool sched_smt_active(void) { return false; } #endif void arch_smt_update(void);
diff --git a/include/linux/seq_buf.h b/include/linux/seq_buf.h index fe41da0..52791e0 100644 --- a/include/linux/seq_buf.h +++ b/include/linux/seq_buf.h
@@ -167,8 +167,8 @@ extern int seq_buf_hex_dump(struct seq_buf *s, const char *prefix_str, const void *buf, size_t len, bool ascii); #ifdef CONFIG_BINARY_PRINTF -extern int -seq_buf_bprintf(struct seq_buf *s, const char *fmt, const u32 *binary); +__printf(2, 0) +int seq_buf_bprintf(struct seq_buf *s, const char *fmt, const u32 *binary); #endif void seq_buf_do_printk(struct seq_buf *s, const char *lvl);
diff --git a/include/linux/seq_file.h b/include/linux/seq_file.h index 2fb266e..d6ebf05 100644 --- a/include/linux/seq_file.h +++ b/include/linux/seq_file.h
@@ -181,6 +181,7 @@ int seq_open_private(struct file *, const struct seq_operations *, int); int seq_release_private(struct inode *, struct file *); #ifdef CONFIG_BINARY_PRINTF +__printf(2, 0) void seq_bprintf(struct seq_file *m, const char *f, const u32 *binary); #endif
diff --git a/include/linux/serdev.h b/include/linux/serdev.h index ff78efc..34562eb 100644 --- a/include/linux/serdev.h +++ b/include/linux/serdev.h
@@ -84,7 +84,6 @@ enum serdev_parity { struct serdev_controller_ops { ssize_t (*write_buf)(struct serdev_controller *, const u8 *, size_t); void (*write_flush)(struct serdev_controller *); - int (*write_room)(struct serdev_controller *); int (*open)(struct serdev_controller *); void (*close)(struct serdev_controller *); void (*set_flow_control)(struct serdev_controller *, bool); @@ -212,7 +211,6 @@ int serdev_device_break_ctl(struct serdev_device *serdev, int break_state); void serdev_device_write_wakeup(struct serdev_device *); ssize_t serdev_device_write(struct serdev_device *, const u8 *, size_t, long); void serdev_device_write_flush(struct serdev_device *); -int serdev_device_write_room(struct serdev_device *); /* * serdev device driver functions @@ -273,10 +271,6 @@ static inline ssize_t serdev_device_write(struct serdev_device *sdev, return -ENODEV; } static inline void serdev_device_write_flush(struct serdev_device *sdev) {} -static inline int serdev_device_write_room(struct serdev_device *sdev) -{ - return 0; -} #define serdev_device_driver_register(x) #define serdev_device_driver_unregister(x)
diff --git a/include/linux/sort.h b/include/linux/sort.h index e163287..8e5603b 100644 --- a/include/linux/sort.h +++ b/include/linux/sort.h
@@ -13,4 +13,15 @@ void sort(void *base, size_t num, size_t size, cmp_func_t cmp_func, swap_func_t swap_func); +/* Versions that periodically call cond_resched(): */ + +void sort_r_nonatomic(void *base, size_t num, size_t size, + cmp_r_func_t cmp_func, + swap_r_func_t swap_func, + const void *priv); + +void sort_nonatomic(void *base, size_t num, size_t size, + cmp_func_t cmp_func, + swap_func_t swap_func); + #endif
diff --git a/include/linux/string.h b/include/linux/string.h index 0403a4c..01621ad 100644 --- a/include/linux/string.h +++ b/include/linux/string.h
@@ -336,8 +336,8 @@ int __sysfs_match_string(const char * const *array, size_t n, const char *s); #define sysfs_match_string(_a, _s) __sysfs_match_string(_a, ARRAY_SIZE(_a), _s) #ifdef CONFIG_BINARY_PRINTF -int vbin_printf(u32 *bin_buf, size_t size, const char *fmt, va_list args); -int bstr_printf(char *buf, size_t size, const char *fmt, const u32 *bin_buf); +__printf(3, 0) int vbin_printf(u32 *bin_buf, size_t size, const char *fmt, va_list args); +__printf(3, 0) int bstr_printf(char *buf, size_t size, const char *fmt, const u32 *bin_buf); #endif extern ssize_t memory_read_from_buffer(void *to, size_t count, loff_t *ppos,
diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h index fec976e..f8b406b 100644 --- a/include/linux/sunrpc/clnt.h +++ b/include/linux/sunrpc/clnt.h
@@ -64,7 +64,9 @@ struct rpc_clnt { cl_noretranstimeo: 1,/* No retransmit timeouts */ cl_autobind : 1,/* use getport() */ cl_chatty : 1,/* be verbose */ - cl_shutdown : 1;/* rpc immediate -EIO */ + cl_shutdown : 1,/* rpc immediate -EIO */ + cl_netunreach_fatal : 1; + /* Treat ENETUNREACH errors as fatal */ struct xprtsec_parms cl_xprtsec; /* transport security policy */ struct rpc_rtt * cl_rtt; /* RTO estimator data */ @@ -175,6 +177,7 @@ struct rpc_add_xprt_test { #define RPC_CLNT_CREATE_SOFTERR (1UL << 10) #define RPC_CLNT_CREATE_REUSEPORT (1UL << 11) #define RPC_CLNT_CREATE_CONNECTED (1UL << 12) +#define RPC_CLNT_CREATE_NETUNREACH_FATAL (1UL << 13) struct rpc_clnt *rpc_create(struct rpc_create_args *args); struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *,
diff --git a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h index eac57914..ccba79e 100644 --- a/include/linux/sunrpc/sched.h +++ b/include/linux/sunrpc/sched.h
@@ -134,6 +134,7 @@ struct rpc_task_setup { #define RPC_TASK_MOVEABLE 0x0004 /* nfs4.1+ rpc tasks */ #define RPC_TASK_NULLCREDS 0x0010 /* Use AUTH_NULL credential */ #define RPC_CALL_MAJORSEEN 0x0020 /* major timeout seen */ +#define RPC_TASK_NETUNREACH_FATAL 0x0040 /* ENETUNREACH is fatal */ #define RPC_TASK_DYNAMIC 0x0080 /* task was kmalloc'ed */ #define RPC_TASK_NO_ROUND_ROBIN 0x0100 /* send requests on "main" xprt */ #define RPC_TASK_SOFT 0x0200 /* Use soft timeouts */
diff --git a/include/linux/sunrpc/xprtmultipath.h b/include/linux/sunrpc/xprtmultipath.h index e411368c..e4db502 100644 --- a/include/linux/sunrpc/xprtmultipath.h +++ b/include/linux/sunrpc/xprtmultipath.h
@@ -56,6 +56,7 @@ extern void rpc_xprt_switch_add_xprt(struct rpc_xprt_switch *xps, struct rpc_xprt *xprt); extern void rpc_xprt_switch_remove_xprt(struct rpc_xprt_switch *xps, struct rpc_xprt *xprt, bool offline); +extern struct rpc_xprt *rpc_xprt_switch_get_main_xprt(struct rpc_xprt_switch *xps); extern void xprt_iter_init(struct rpc_xprt_iter *xpi, struct rpc_xprt_switch *xps);
diff --git a/include/linux/timer.h b/include/linux/timer.h index e67ecd1c..10596d7 100644 --- a/include/linux/timer.h +++ b/include/linux/timer.h
@@ -30,7 +30,7 @@ * * @TIMER_IRQSAFE: An irqsafe timer is executed with IRQ disabled and * it's safe to wait for the completion of the running instance from - * IRQ handlers, for example, by calling del_timer_sync(). + * IRQ handlers, for example, by calling timer_delete_sync(). * * Note: The irq disabled callback execution is a special case for * workqueue locking issues. It's not meant for executing random crap @@ -168,40 +168,6 @@ extern int timer_delete(struct timer_list *timer); extern int timer_shutdown_sync(struct timer_list *timer); extern int timer_shutdown(struct timer_list *timer); -/** - * del_timer_sync - Delete a pending timer and wait for a running callback - * @timer: The timer to be deleted - * - * See timer_delete_sync() for detailed explanation. - * - * Do not use in new code. Use timer_delete_sync() instead. - * - * Returns: - * * %0 - The timer was not pending - * * %1 - The timer was pending and deactivated - */ -static inline int del_timer_sync(struct timer_list *timer) -{ - return timer_delete_sync(timer); -} - -/** - * del_timer - Delete a pending timer - * @timer: The timer to be deleted - * - * See timer_delete() for detailed explanation. - * - * Do not use in new code. Use timer_delete() instead. - * - * Returns: - * * %0 - The timer was not pending - * * %1 - The timer was pending and deactivated - */ -static inline int del_timer(struct timer_list *timer) -{ - return timer_delete(timer); -} - extern void init_timers(void); struct hrtimer; extern enum hrtimer_restart it_real_fn(struct hrtimer *);
diff --git a/include/linux/trace.h b/include/linux/trace.h index fdcd76b..7eaad85 100644 --- a/include/linux/trace.h +++ b/include/linux/trace.h
@@ -72,8 +72,8 @@ static inline int unregister_ftrace_export(struct trace_export *export) static inline void trace_printk_init_buffers(void) { } -static inline int trace_array_printk(struct trace_array *tr, unsigned long ip, - const char *fmt, ...) +static inline __printf(3, 4) +int trace_array_printk(struct trace_array *tr, unsigned long ip, const char *fmt, ...) { return 0; }
diff --git a/include/linux/trace_seq.h b/include/linux/trace_seq.h index 1ef95c0..a93ed5a 100644 --- a/include/linux/trace_seq.h +++ b/include/linux/trace_seq.h
@@ -88,8 +88,8 @@ extern __printf(2, 3) void trace_seq_printf(struct trace_seq *s, const char *fmt, ...); extern __printf(2, 0) void trace_seq_vprintf(struct trace_seq *s, const char *fmt, va_list args); -extern void -trace_seq_bprintf(struct trace_seq *s, const char *fmt, const u32 *binary); +extern __printf(2, 0) +void trace_seq_bprintf(struct trace_seq *s, const char *fmt, const u32 *binary); extern int trace_print_seq(struct seq_file *m, struct trace_seq *s); extern int trace_seq_to_user(struct trace_seq *s, char __user *ubuf, int cnt); @@ -113,8 +113,8 @@ static inline __printf(2, 3) void trace_seq_printf(struct trace_seq *s, const char *fmt, ...) { } -static inline void -trace_seq_bprintf(struct trace_seq *s, const char *fmt, const u32 *binary) +static inline __printf(2, 0) +void trace_seq_bprintf(struct trace_seq *s, const char *fmt, const u32 *binary) { }
diff --git a/include/linux/tty.h b/include/linux/tty.h index 2372f93..0a46e40 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h
@@ -239,7 +239,6 @@ struct tty_struct { struct list_head tty_files; -#define N_TTY_BUF_SIZE 4096 struct work_struct SAK_work; } __randomize_layout; @@ -251,7 +250,7 @@ struct tty_file_private { }; /** - * DOC: TTY Struct Flags + * enum tty_struct_flags - TTY Struct Flags * * These bits are used in the :c:member:`tty_struct.flags` field. * @@ -260,62 +259,64 @@ struct tty_file_private { * tty->write. Thus, you must use the inline functions set_bit() and * clear_bit() to make things atomic. * - * TTY_THROTTLED + * @TTY_THROTTLED: * Driver input is throttled. The ldisc should call * :c:member:`tty_driver.unthrottle()` in order to resume reception when * it is ready to process more data (at threshold min). * - * TTY_IO_ERROR + * @TTY_IO_ERROR: * If set, causes all subsequent userspace read/write calls on the tty to * fail, returning -%EIO. (May be no ldisc too.) * - * TTY_OTHER_CLOSED + * @TTY_OTHER_CLOSED: * Device is a pty and the other side has closed. * - * TTY_EXCLUSIVE + * @TTY_EXCLUSIVE: * Exclusive open mode (a single opener). * - * TTY_DO_WRITE_WAKEUP + * @TTY_DO_WRITE_WAKEUP: * If set, causes the driver to call the * :c:member:`tty_ldisc_ops.write_wakeup()` method in order to resume * transmission when it can accept more data to transmit. * - * TTY_LDISC_OPEN + * @TTY_LDISC_OPEN: * Indicates that a line discipline is open. For debugging purposes only. * - * TTY_PTY_LOCK + * @TTY_PTY_LOCK: * A flag private to pty code to implement %TIOCSPTLCK/%TIOCGPTLCK logic. * - * TTY_NO_WRITE_SPLIT + * @TTY_NO_WRITE_SPLIT: * Prevent driver from splitting up writes into smaller chunks (preserve * write boundaries to driver). * - * TTY_HUPPED + * @TTY_HUPPED: * The TTY was hung up. This is set post :c:member:`tty_driver.hangup()`. * - * TTY_HUPPING + * @TTY_HUPPING: * The TTY is in the process of hanging up to abort potential readers. * - * TTY_LDISC_CHANGING + * @TTY_LDISC_CHANGING: * Line discipline for this TTY is being changed. I/O should not block * when this is set. Use tty_io_nonblock() to check. * - * TTY_LDISC_HALTED + * @TTY_LDISC_HALTED: * Line discipline for this TTY was stopped. No work should be queued to * this ldisc. */ -#define TTY_THROTTLED 0 -#define TTY_IO_ERROR 1 -#define TTY_OTHER_CLOSED 2 -#define TTY_EXCLUSIVE 3 -#define TTY_DO_WRITE_WAKEUP 5 -#define TTY_LDISC_OPEN 11 -#define TTY_PTY_LOCK 16 -#define TTY_NO_WRITE_SPLIT 17 -#define TTY_HUPPED 18 -#define TTY_HUPPING 19 -#define TTY_LDISC_CHANGING 20 -#define TTY_LDISC_HALTED 22 +enum tty_struct_flags { + TTY_THROTTLED, + TTY_IO_ERROR, + TTY_OTHER_CLOSED, + TTY_EXCLUSIVE, + TTY_DO_WRITE_WAKEUP, + TTY_LDISC_OPEN, + TTY_PTY_LOCK, + TTY_NO_WRITE_SPLIT, + TTY_HUPPED, + TTY_HUPPING, + TTY_LDISC_CHANGING, + TTY_LDISC_HALTED, +}; static inline bool tty_io_nonblock(struct tty_struct *tty, struct file *file) {
diff --git a/include/linux/tty_driver.h b/include/linux/tty_driver.h index d4cdc08..188ee9b 100644 --- a/include/linux/tty_driver.h +++ b/include/linux/tty_driver.h
@@ -17,6 +17,92 @@ struct serial_icounter_struct; struct serial_struct; /** + * enum tty_driver_flag -- TTY Driver Flags + * + * These are flags passed to tty_alloc_driver(). + * + * @TTY_DRIVER_INSTALLED: + * Whether this driver was succesfully installed. This is a tty internal + * flag. Do not touch. + * + * @TTY_DRIVER_RESET_TERMIOS: + * Requests the tty layer to reset the termios setting when the last + * process has closed the device. Used for PTYs, in particular. + * + * @TTY_DRIVER_REAL_RAW: + * Indicates that the driver will guarantee not to set any special + * character handling flags if this is set for the tty: + * + * ``(IGNBRK || (!BRKINT && !PARMRK)) && (IGNPAR || !INPCK)`` + * + * That is, if there is no reason for the driver to + * send notifications of parity and break characters up to the line + * driver, it won't do so. This allows the line driver to optimize for + * this case if this flag is set. (Note that there is also a promise, if + * the above case is true, not to signal overruns, either.) + * + * @TTY_DRIVER_DYNAMIC_DEV: + * The individual tty devices need to be registered with a call to + * tty_register_device() when the device is found in the system and + * unregistered with a call to tty_unregister_device() so the devices will + * be show up properly in sysfs. If not set, all &tty_driver.num entries + * will be created by the tty core in sysfs when tty_register_driver() is + * called. This is to be used by drivers that have tty devices that can + * appear and disappear while the main tty driver is registered with the + * tty core. + * + * @TTY_DRIVER_DEVPTS_MEM: + * Don't use the standard arrays (&tty_driver.ttys and + * &tty_driver.termios), instead use dynamic memory keyed through the + * devpts filesystem. This is only applicable to the PTY driver. + * + * @TTY_DRIVER_HARDWARE_BREAK: + * Hardware handles break signals. Pass the requested timeout to the + * &tty_operations.break_ctl instead of using a simple on/off interface. + * + * @TTY_DRIVER_DYNAMIC_ALLOC: + * Do not allocate structures which are needed per line for this driver + * (&tty_driver.ports) as it would waste memory. The driver will take + * care. This is only applicable to the PTY driver. + * + * @TTY_DRIVER_UNNUMBERED_NODE: + * Do not create numbered ``/dev`` nodes. For example, create + * ``/dev/ttyprintk`` and not ``/dev/ttyprintk0``. Applicable only when a + * driver for a single tty device is being allocated. + */ +enum tty_driver_flag { + TTY_DRIVER_INSTALLED = BIT(0), + TTY_DRIVER_RESET_TERMIOS = BIT(1), + TTY_DRIVER_REAL_RAW = BIT(2), + TTY_DRIVER_DYNAMIC_DEV = BIT(3), + TTY_DRIVER_DEVPTS_MEM = BIT(4), + TTY_DRIVER_HARDWARE_BREAK = BIT(5), + TTY_DRIVER_DYNAMIC_ALLOC = BIT(6), + TTY_DRIVER_UNNUMBERED_NODE = BIT(7), +}; + +enum tty_driver_type { + TTY_DRIVER_TYPE_SYSTEM, + TTY_DRIVER_TYPE_CONSOLE, + TTY_DRIVER_TYPE_SERIAL, + TTY_DRIVER_TYPE_PTY, + TTY_DRIVER_TYPE_SCC, + TTY_DRIVER_TYPE_SYSCONS, +}; + +enum tty_driver_subtype { + SYSTEM_TYPE_TTY = 1, + SYSTEM_TYPE_CONSOLE, + SYSTEM_TYPE_SYSCONS, + SYSTEM_TYPE_SYSPTMX, + + PTY_TYPE_MASTER = 1, + PTY_TYPE_SLAVE, + + SERIAL_TYPE_NORMAL = 1, +}; + +/** * struct tty_operations -- interface between driver and tty * * @lookup: ``struct tty_struct *()(struct tty_driver *self, struct file *, @@ -414,8 +500,8 @@ struct tty_operations { * @major: major /dev device number (zero for autoassignment) * @minor_start: the first minor /dev device number * @num: number of devices allocated - * @type: type of tty driver (%TTY_DRIVER_TYPE_) - * @subtype: subtype of tty driver (%SYSTEM_TYPE_, %PTY_TYPE_, %SERIAL_TYPE_) + * @type: type of tty driver (enum tty_driver_type) + * @subtype: subtype of tty driver (enum tty_driver_subtype) * @init_termios: termios to set to each tty initially (e.g. %tty_std_termios) * @flags: tty driver flags (%TTY_DRIVER_) * @proc_entry: proc fs entry, used internally @@ -447,8 +533,8 @@ struct tty_driver { int major; int minor_start; unsigned int num; - short type; - short subtype; + enum tty_driver_type type; + enum tty_driver_subtype subtype; struct ktermios init_termios; unsigned long flags; struct proc_dir_entry *proc_entry; @@ -478,7 +564,13 @@ struct tty_driver *tty_find_polling_driver(char *name, int *line); void tty_driver_kref_put(struct tty_driver *driver); -/* Use TTY_DRIVER_* flags below */ +/** + * tty_alloc_driver - allocate tty driver + * @lines: count of lines this driver can handle at most + * @flags: some of enum tty_driver_flag, will be set in driver->flags + * + * Returns: struct tty_driver or a PTR-encoded error (use IS_ERR() and friends). + */ #define tty_alloc_driver(lines, flags) \ __tty_alloc_driver(lines, THIS_MODULE, flags) @@ -494,84 +586,6 @@ static inline void tty_set_operations(struct tty_driver *driver, driver->ops = op; } -/** - * DOC: TTY Driver Flags - * - * TTY_DRIVER_RESET_TERMIOS - * Requests the tty layer to reset the termios setting when the last - * process has closed the device. Used for PTYs, in particular. - * - * TTY_DRIVER_REAL_RAW - * Indicates that the driver will guarantee not to set any special - * character handling flags if this is set for the tty: - * - * ``(IGNBRK || (!BRKINT && !PARMRK)) && (IGNPAR || !INPCK)`` - * - * That is, if there is no reason for the driver to - * send notifications of parity and break characters up to the line - * driver, it won't do so. This allows the line driver to optimize for - * this case if this flag is set. (Note that there is also a promise, if - * the above case is true, not to signal overruns, either.) - * - * TTY_DRIVER_DYNAMIC_DEV - * The individual tty devices need to be registered with a call to - * tty_register_device() when the device is found in the system and - * unregistered with a call to tty_unregister_device() so the devices will - * be show up properly in sysfs. If not set, all &tty_driver.num entries - * will be created by the tty core in sysfs when tty_register_driver() is - * called. This is to be used by drivers that have tty devices that can - * appear and disappear while the main tty driver is registered with the - * tty core. - * - * TTY_DRIVER_DEVPTS_MEM - * Don't use the standard arrays (&tty_driver.ttys and - * &tty_driver.termios), instead use dynamic memory keyed through the - * devpts filesystem. This is only applicable to the PTY driver. - * - * TTY_DRIVER_HARDWARE_BREAK - * Hardware handles break signals. Pass the requested timeout to the - * &tty_operations.break_ctl instead of using a simple on/off interface. - * - * TTY_DRIVER_DYNAMIC_ALLOC - * Do not allocate structures which are needed per line for this driver - * (&tty_driver.ports) as it would waste memory. The driver will take - * care. This is only applicable to the PTY driver. - * - * TTY_DRIVER_UNNUMBERED_NODE - * Do not create numbered ``/dev`` nodes. For example, create - * ``/dev/ttyprintk`` and not ``/dev/ttyprintk0``. Applicable only when a - * driver for a single tty device is being allocated. - */ -#define TTY_DRIVER_INSTALLED 0x0001 -#define TTY_DRIVER_RESET_TERMIOS 0x0002 -#define TTY_DRIVER_REAL_RAW 0x0004 -#define TTY_DRIVER_DYNAMIC_DEV 0x0008 -#define TTY_DRIVER_DEVPTS_MEM 0x0010 -#define TTY_DRIVER_HARDWARE_BREAK 0x0020 -#define TTY_DRIVER_DYNAMIC_ALLOC 0x0040 -#define TTY_DRIVER_UNNUMBERED_NODE 0x0080 - -/* tty driver types */ -#define TTY_DRIVER_TYPE_SYSTEM 0x0001 -#define TTY_DRIVER_TYPE_CONSOLE 0x0002 -#define TTY_DRIVER_TYPE_SERIAL 0x0003 -#define TTY_DRIVER_TYPE_PTY 0x0004 -#define TTY_DRIVER_TYPE_SCC 0x0005 /* scc driver */ -#define TTY_DRIVER_TYPE_SYSCONS 0x0006 - -/* system subtypes (magic, used by tty_io.c) */ -#define SYSTEM_TYPE_TTY 0x0001 -#define SYSTEM_TYPE_CONSOLE 0x0002 -#define SYSTEM_TYPE_SYSCONS 0x0003 -#define SYSTEM_TYPE_SYSPTMX 0x0004 - -/* pty subtypes (magic, used by tty_io.c) */ -#define PTY_TYPE_MASTER 0x0001 -#define PTY_TYPE_SLAVE 0x0002 - -/* serial subtype definitions */ -#define SERIAL_TYPE_NORMAL 1 - int tty_register_driver(struct tty_driver *driver); void tty_unregister_driver(struct tty_driver *driver); struct device *tty_register_device(struct tty_driver *driver, unsigned index,
diff --git a/include/linux/tty_ldisc.h b/include/linux/tty_ldisc.h index af01e89..c5cccc3 100644 --- a/include/linux/tty_ldisc.h +++ b/include/linux/tty_ldisc.h
@@ -39,7 +39,6 @@ do { \ int ldsem_down_read(struct ld_semaphore *sem, long timeout); int ldsem_down_read_trylock(struct ld_semaphore *sem); int ldsem_down_write(struct ld_semaphore *sem, long timeout); -int ldsem_down_write_trylock(struct ld_semaphore *sem); void ldsem_up_read(struct ld_semaphore *sem); void ldsem_up_write(struct ld_semaphore *sem);
diff --git a/include/linux/usb.h b/include/linux/usb.h index cfa8005..b467387 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h
@@ -51,6 +51,7 @@ struct ep_device; * @desc: descriptor for this endpoint, wMaxPacketSize in native byteorder * @ss_ep_comp: SuperSpeed companion descriptor for this endpoint * @ssp_isoc_ep_comp: SuperSpeedPlus isoc companion descriptor for this endpoint + * @eusb2_isoc_ep_comp: eUSB2 isoc companion descriptor for this endpoint * @urb_list: urbs queued to this endpoint; maintained by usbcore * @hcpriv: for use by HCD; typically holds hardware dma queue head (QH) * with one or more transfer descriptors (TDs) per urb @@ -64,9 +65,10 @@ struct ep_device; * descriptor within an active interface in a given USB configuration. */ struct usb_host_endpoint { - struct usb_endpoint_descriptor desc; - struct usb_ss_ep_comp_descriptor ss_ep_comp; - struct usb_ssp_isoc_ep_comp_descriptor ssp_isoc_ep_comp; + struct usb_endpoint_descriptor desc; + struct usb_ss_ep_comp_descriptor ss_ep_comp; + struct usb_ssp_isoc_ep_comp_descriptor ssp_isoc_ep_comp; + struct usb_eusb2_isoc_ep_comp_descriptor eusb2_isoc_ep_comp; struct list_head urb_list; void *hcpriv; struct ep_device *ep_dev; /* For sysfs info */
diff --git a/include/linux/usb/musb.h b/include/linux/usb/musb.h index 3963e55..fbdef950 100644 --- a/include/linux/usb/musb.h +++ b/include/linux/usb/musb.h
@@ -61,7 +61,7 @@ struct musb_hdrc_eps_bits { }; struct musb_hdrc_config { - struct musb_fifo_cfg *fifo_cfg; /* board fifo configuration */ + const struct musb_fifo_cfg *fifo_cfg; /* board fifo configuration */ unsigned fifo_cfg_size; /* size of the fifo configuration */ /* MUSB configuration-specific details */
diff --git a/include/linux/usb/ulpi.h b/include/linux/usb/ulpi.h index 5050f50..4b65106 100644 --- a/include/linux/usb/ulpi.h +++ b/include/linux/usb/ulpi.h
@@ -49,19 +49,10 @@ /*-------------------------------------------------------------------------*/ #if IS_ENABLED(CONFIG_USB_ULPI) -struct usb_phy *otg_ulpi_create(struct usb_phy_io_ops *ops, - unsigned int flags); - struct usb_phy *devm_otg_ulpi_create(struct device *dev, struct usb_phy_io_ops *ops, unsigned int flags); #else -static inline struct usb_phy *otg_ulpi_create(struct usb_phy_io_ops *ops, - unsigned int flags) -{ - return NULL; -} - static inline struct usb_phy *devm_otg_ulpi_create(struct device *dev, struct usb_phy_io_ops *ops, unsigned int flags)
diff --git a/include/misc/cxl-base.h b/include/misc/cxl-base.h deleted file mode 100644 index 2251da7..0000000 --- a/include/misc/cxl-base.h +++ /dev/null
@@ -1,48 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * Copyright 2014 IBM Corp. - */ - -#ifndef _MISC_CXL_BASE_H -#define _MISC_CXL_BASE_H - -#ifdef CONFIG_CXL_BASE - -#define CXL_IRQ_RANGES 4 - -struct cxl_irq_ranges { - irq_hw_number_t offset[CXL_IRQ_RANGES]; - irq_hw_number_t range[CXL_IRQ_RANGES]; -}; - -extern atomic_t cxl_use_count; - -static inline bool cxl_ctx_in_use(void) -{ - return (atomic_read(&cxl_use_count) != 0); -} - -static inline void cxl_ctx_get(void) -{ - atomic_inc(&cxl_use_count); -} - -static inline void cxl_ctx_put(void) -{ - atomic_dec(&cxl_use_count); -} - -struct cxl_afu *cxl_afu_get(struct cxl_afu *afu); -void cxl_afu_put(struct cxl_afu *afu); -void cxl_slbia(struct mm_struct *mm); - -#else /* CONFIG_CXL_BASE */ - -static inline bool cxl_ctx_in_use(void) { return false; } -static inline struct cxl_afu *cxl_afu_get(struct cxl_afu *afu) { return NULL; } -static inline void cxl_afu_put(struct cxl_afu *afu) {} -static inline void cxl_slbia(struct mm_struct *mm) {} - -#endif /* CONFIG_CXL_BASE */ - -#endif
diff --git a/include/misc/cxl.h b/include/misc/cxl.h deleted file mode 100644 index d804429..0000000 --- a/include/misc/cxl.h +++ /dev/null
@@ -1,265 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * Copyright 2015 IBM Corp. - */ - -#ifndef _MISC_CXL_H -#define _MISC_CXL_H - -#include <linux/pci.h> -#include <linux/poll.h> -#include <linux/interrupt.h> -#include <uapi/misc/cxl.h> - -/* - * This documents the in kernel API for driver to use CXL. It allows kernel - * drivers to bind to AFUs using an AFU configuration record exposed as a PCI - * configuration record. - * - * This API enables control over AFU and contexts which can't be part of the - * generic PCI API. This API is agnostic to the actual AFU. - */ - -/* Get the AFU associated with a pci_dev */ -struct cxl_afu *cxl_pci_to_afu(struct pci_dev *dev); - -/* Get the AFU conf record number associated with a pci_dev */ -unsigned int cxl_pci_to_cfg_record(struct pci_dev *dev); - - -/* - * Context lifetime overview: - * - * An AFU context may be inited and then started and stopped multiple times - * before it's released. ie. - * - cxl_dev_context_init() - * - cxl_start_context() - * - cxl_stop_context() - * - cxl_start_context() - * - cxl_stop_context() - * ...repeat... - * - cxl_release_context() - * Once released, a context can't be started again. - * - * One context is inited by the cxl driver for every pci_dev. This is to be - * used as a default kernel context. cxl_get_context() will get this - * context. This context will be released by PCI hot unplug, so doesn't need to - * be released explicitly by drivers. - * - * Additional kernel contexts may be inited using cxl_dev_context_init(). - * These must be released using cxl_context_detach(). - * - * Once a context has been inited, IRQs may be configured. Firstly these IRQs - * must be allocated (cxl_allocate_afu_irqs()), then individually mapped to - * specific handlers (cxl_map_afu_irq()). - * - * These IRQs can be unmapped (cxl_unmap_afu_irq()) and finally released - * (cxl_free_afu_irqs()). - * - * The AFU can be reset (cxl_afu_reset()). This will cause the PSL/AFU - * hardware to lose track of all contexts. It's upto the caller of - * cxl_afu_reset() to restart these contexts. - */ - -/* - * On pci_enabled_device(), the cxl driver will init a single cxl context for - * use by the driver. It doesn't start this context (as that will likely - * generate DMA traffic for most AFUs). - * - * This gets the default context associated with this pci_dev. This context - * doesn't need to be released as this will be done by the PCI subsystem on hot - * unplug. - */ -struct cxl_context *cxl_get_context(struct pci_dev *dev); -/* - * Allocate and initalise a context associated with a AFU PCI device. This - * doesn't start the context in the AFU. - */ -struct cxl_context *cxl_dev_context_init(struct pci_dev *dev); -/* - * Release and free a context. Context should be stopped before calling. - */ -int cxl_release_context(struct cxl_context *ctx); - -/* - * Set and get private data associated with a context. Allows drivers to have a - * back pointer to some useful structure. - */ -int cxl_set_priv(struct cxl_context *ctx, void *priv); -void *cxl_get_priv(struct cxl_context *ctx); - -/* - * Allocate AFU interrupts for this context. num=0 will allocate the default - * for this AFU as given in the AFU descriptor. This number doesn't include the - * interrupt 0 (CAIA defines AFU IRQ 0 for page faults). Each interrupt to be - * used must map a handler with cxl_map_afu_irq. - */ -int cxl_allocate_afu_irqs(struct cxl_context *cxl, int num); -/* Free allocated interrupts */ -void cxl_free_afu_irqs(struct cxl_context *cxl); - -/* - * Map a handler for an AFU interrupt associated with a particular context. AFU - * IRQS numbers start from 1 (CAIA defines AFU IRQ 0 for page faults). cookie - * is private data is that will be provided to the interrupt handler. - */ -int cxl_map_afu_irq(struct cxl_context *cxl, int num, - irq_handler_t handler, void *cookie, char *name); -/* unmap mapped IRQ handlers */ -void cxl_unmap_afu_irq(struct cxl_context *cxl, int num, void *cookie); - -/* - * Start work on the AFU. This starts an cxl context and associates it with a - * task. task == NULL will make it a kernel context. - */ -int cxl_start_context(struct cxl_context *ctx, u64 wed, - struct task_struct *task); -/* - * Stop a context and remove it from the PSL - */ -int cxl_stop_context(struct cxl_context *ctx); - -/* Reset the AFU */ -int cxl_afu_reset(struct cxl_context *ctx); - -/* - * Set a context as a master context. - * This sets the default problem space area mapped as the full space, rather - * than just the per context area (for slaves). - */ -void cxl_set_master(struct cxl_context *ctx); - -/* - * Map and unmap the AFU Problem Space area. The amount and location mapped - * depends on if this context is a master or slave. - */ -void __iomem *cxl_psa_map(struct cxl_context *ctx); -void cxl_psa_unmap(void __iomem *addr); - -/* Get the process element for this context */ -int cxl_process_element(struct cxl_context *ctx); - -/* - * These calls allow drivers to create their own file descriptors and make them - * identical to the cxl file descriptor user API. An example use case: - * - * struct file_operations cxl_my_fops = {}; - * ...... - * // Init the context - * ctx = cxl_dev_context_init(dev); - * if (IS_ERR(ctx)) - * return PTR_ERR(ctx); - * // Create and attach a new file descriptor to my file ops - * file = cxl_get_fd(ctx, &cxl_my_fops, &fd); - * // Start context - * rc = cxl_start_work(ctx, &work.work); - * if (rc) { - * fput(file); - * put_unused_fd(fd); - * return -ENODEV; - * } - * // No error paths after installing the fd - * fd_install(fd, file); - * return fd; - * - * This inits a context, and gets a file descriptor and associates some file - * ops to that file descriptor. If the file ops are blank, the cxl driver will - * fill them in with the default ones that mimic the standard user API. Once - * completed, the file descriptor can be installed. Once the file descriptor is - * installed, it's visible to the user so no errors must occur past this point. - * - * If cxl_fd_release() file op call is installed, the context will be stopped - * and released when the fd is released. Hence the driver won't need to manage - * this itself. - */ - -/* - * Take a context and associate it with my file ops. Returns the associated - * file and file descriptor. Any file ops which are blank are filled in by the - * cxl driver with the default ops to mimic the standard API. - */ -struct file *cxl_get_fd(struct cxl_context *ctx, struct file_operations *fops, - int *fd); -/* Get the context associated with this file */ -struct cxl_context *cxl_fops_get_context(struct file *file); -/* - * Start a context associated a struct cxl_ioctl_start_work used by the - * standard cxl user API. - */ -int cxl_start_work(struct cxl_context *ctx, - struct cxl_ioctl_start_work *work); -/* - * Export all the existing fops so drivers can use them - */ -int cxl_fd_open(struct inode *inode, struct file *file); -int cxl_fd_release(struct inode *inode, struct file *file); -long cxl_fd_ioctl(struct file *file, unsigned int cmd, unsigned long arg); -int cxl_fd_mmap(struct file *file, struct vm_area_struct *vm); -__poll_t cxl_fd_poll(struct file *file, struct poll_table_struct *poll); -ssize_t cxl_fd_read(struct file *file, char __user *buf, size_t count, - loff_t *off); - -/* - * For EEH, a driver may want to assert a PERST will reload the same image - * from flash into the FPGA. - * - * This is a property of the entire adapter, not a single AFU, so drivers - * should set this property with care! - */ -void cxl_perst_reloads_same_image(struct cxl_afu *afu, - bool perst_reloads_same_image); - -/* - * Read the VPD for the card where the AFU resides - */ -ssize_t cxl_read_adapter_vpd(struct pci_dev *dev, void *buf, size_t count); - -/* - * AFU driver ops allow an AFU driver to create their own events to pass to - * userspace through the file descriptor as a simpler alternative to overriding - * the read() and poll() calls that works with the generic cxl events. These - * events are given priority over the generic cxl events, so they will be - * delivered first if multiple types of events are pending. - * - * The AFU driver must call cxl_context_events_pending() to notify the cxl - * driver that new events are ready to be delivered for a specific context. - * cxl_context_events_pending() will adjust the current count of AFU driver - * events for this context, and wake up anyone waiting on the context wait - * queue. - * - * The cxl driver will then call fetch_event() to get a structure defining - * the size and address of the driver specific event data. The cxl driver - * will build a cxl header with type and process_element fields filled in, - * and header.size set to sizeof(struct cxl_event_header) + data_size. - * The total size of the event is limited to CXL_READ_MIN_SIZE (4K). - * - * fetch_event() is called with a spin lock held, so it must not sleep. - * - * The cxl driver will then deliver the event to userspace, and finally - * call event_delivered() to return the status of the operation, identified - * by cxl context and AFU driver event data pointers. - * 0 Success - * -EFAULT copy_to_user() has failed - * -EINVAL Event data pointer is NULL, or event size is greater than - * CXL_READ_MIN_SIZE. - */ -struct cxl_afu_driver_ops { - struct cxl_event_afu_driver_reserved *(*fetch_event) ( - struct cxl_context *ctx); - void (*event_delivered) (struct cxl_context *ctx, - struct cxl_event_afu_driver_reserved *event, - int rc); -}; - -/* - * Associate the above driver ops with a specific context. - * Reset the current count of AFU driver events. - */ -void cxl_set_driver_ops(struct cxl_context *ctx, - struct cxl_afu_driver_ops *ops); - -/* Notify cxl driver that new events are ready to be delivered for context */ -void cxl_context_events_pending(struct cxl_context *ctx, - unsigned int new_events); - -#endif /* _MISC_CXL_H */
diff --git a/include/misc/cxllib.h b/include/misc/cxllib.h deleted file mode 100644 index eacc417..0000000 --- a/include/misc/cxllib.h +++ /dev/null
@@ -1,129 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * Copyright 2017 IBM Corp. - */ - -#ifndef _MISC_CXLLIB_H -#define _MISC_CXLLIB_H - -#include <linux/pci.h> -#include <asm/reg.h> - -/* - * cxl driver exports a in-kernel 'library' API which can be called by - * other drivers to help interacting with an IBM XSL. - */ - -/* - * tells whether capi is supported on the PCIe slot where the - * device is seated - * - * Input: - * dev: device whose slot needs to be checked - * flags: 0 for the time being - */ -bool cxllib_slot_is_supported(struct pci_dev *dev, unsigned long flags); - - -/* - * Returns the configuration parameters to be used by the XSL or device - * - * Input: - * dev: device, used to find PHB - * Output: - * struct cxllib_xsl_config: - * version - * capi BAR address, i.e. 0x2000000000000-0x2FFFFFFFFFFFF - * capi BAR size - * data send control (XSL_DSNCTL) - * dummy read address (XSL_DRA) - */ -#define CXL_XSL_CONFIG_VERSION1 1 -struct cxllib_xsl_config { - u32 version; /* format version for register encoding */ - u32 log_bar_size;/* log size of the capi_window */ - u64 bar_addr; /* address of the start of capi window */ - u64 dsnctl; /* matches definition of XSL_DSNCTL */ - u64 dra; /* real address that can be used for dummy read */ -}; - -int cxllib_get_xsl_config(struct pci_dev *dev, struct cxllib_xsl_config *cfg); - - -/* - * Activate capi for the pci host bridge associated with the device. - * Can be extended to deactivate once we know how to do it. - * Device must be ready to accept messages from the CAPP unit and - * respond accordingly (TLB invalidates, ...) - * - * PHB is switched to capi mode through calls to skiboot. - * CAPP snooping is activated - * - * Input: - * dev: device whose PHB should switch mode - * mode: mode to switch to i.e. CAPI or PCI - * flags: options related to the mode - */ -enum cxllib_mode { - CXL_MODE_CXL, - CXL_MODE_PCI, -}; - -#define CXL_MODE_NO_DMA 0 -#define CXL_MODE_DMA_TVT0 1 -#define CXL_MODE_DMA_TVT1 2 - -int cxllib_switch_phb_mode(struct pci_dev *dev, enum cxllib_mode mode, - unsigned long flags); - - -/* - * Set the device for capi DMA. - * Define its dma_ops and dma offset so that allocations will be using TVT#1 - * - * Input: - * dev: device to set - * flags: options. CXL_MODE_DMA_TVT1 should be used - */ -int cxllib_set_device_dma(struct pci_dev *dev, unsigned long flags); - - -/* - * Get the Process Element structure for the given thread - * - * Input: - * task: task_struct for the context of the translation - * translation_mode: whether addresses should be translated - * Output: - * attr: attributes to fill up the Process Element structure from CAIA - */ -struct cxllib_pe_attributes { - u64 sr; - u32 lpid; - u32 tid; - u32 pid; -}; -#define CXL_TRANSLATED_MODE 0 -#define CXL_REAL_MODE 1 - -int cxllib_get_PE_attributes(struct task_struct *task, - unsigned long translation_mode, struct cxllib_pe_attributes *attr); - - -/* - * Handle memory fault. - * Fault in all the pages of the specified buffer for the permissions - * provided in ‘flags’ - * - * Shouldn't be called from interrupt context - * - * Input: - * mm: struct mm for the thread faulting the pages - * addr: base address of the buffer to page in - * size: size of the buffer to page in - * flags: permission requested (DSISR_ISSTORE...) - */ -int cxllib_handle_fault(struct mm_struct *mm, u64 addr, u64 size, u64 flags); - - -#endif /* _MISC_CXLLIB_H */
diff --git a/include/net/ip.h b/include/net/ip.h index 8a48ade..47ed6d2 100644 --- a/include/net/ip.h +++ b/include/net/ip.h
@@ -667,14 +667,6 @@ static inline void ip_ipgre_mc_map(__be32 naddr, const unsigned char *broadcast, memcpy(buf, &naddr, sizeof(naddr)); } -#if IS_MODULE(CONFIG_IPV6) -#define EXPORT_IPV6_MOD(X) EXPORT_SYMBOL(X) -#define EXPORT_IPV6_MOD_GPL(X) EXPORT_SYMBOL_GPL(X) -#else -#define EXPORT_IPV6_MOD(X) -#define EXPORT_IPV6_MOD_GPL(X) -#endif - #if IS_ENABLED(CONFIG_IPV6) #include <linux/ipv6.h> #endif @@ -694,6 +686,14 @@ static __inline__ void inet_reset_saddr(struct sock *sk) #endif +#if IS_MODULE(CONFIG_IPV6) +#define EXPORT_IPV6_MOD(X) EXPORT_SYMBOL(X) +#define EXPORT_IPV6_MOD_GPL(X) EXPORT_SYMBOL_GPL(X) +#else +#define EXPORT_IPV6_MOD(X) +#define EXPORT_IPV6_MOD_GPL(X) +#endif + static inline unsigned int ipv4_addr_hash(__be32 ip) { return (__force unsigned int) ip;
diff --git a/include/net/netdev_lock.h b/include/net/netdev_lock.h index 1c0c9a9..c316b55 100644 --- a/include/net/netdev_lock.h +++ b/include/net/netdev_lock.h
@@ -98,4 +98,7 @@ static inline int netdev_lock_cmp_fn(const struct lockdep_map *a, &qdisc_xmit_lock_key); \ } +int netdev_debug_event(struct notifier_block *nb, unsigned long event, + void *ptr); + #endif
diff --git a/include/net/page_pool/memory_provider.h b/include/net/page_pool/memory_provider.h index b3e6658..ada4f96 100644 --- a/include/net/page_pool/memory_provider.h +++ b/include/net/page_pool/memory_provider.h
@@ -6,6 +6,7 @@ #include <net/page_pool/types.h> struct netdev_rx_queue; +struct netlink_ext_ack; struct sk_buff; struct memory_provider_ops { @@ -24,8 +25,13 @@ void net_mp_niov_clear_page_pool(struct net_iov *niov); int net_mp_open_rxq(struct net_device *dev, unsigned ifq_idx, struct pp_memory_provider_params *p); +int __net_mp_open_rxq(struct net_device *dev, unsigned int rxq_idx, + const struct pp_memory_provider_params *p, + struct netlink_ext_ack *extack); void net_mp_close_rxq(struct net_device *dev, unsigned ifq_idx, struct pp_memory_provider_params *old_p); +void __net_mp_close_rxq(struct net_device *dev, unsigned int rxq_idx, + const struct pp_memory_provider_params *old_p); /** * net_mp_netmem_place_in_cache() - give a netmem to a page pool
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h index 84e6b9f..d8da764 100644 --- a/include/net/sctp/sctp.h +++ b/include/net/sctp/sctp.h
@@ -636,7 +636,7 @@ static inline void sctp_transport_pl_reset(struct sctp_transport *t) } } else { if (t->pl.state != SCTP_PL_DISABLED) { - if (del_timer(&t->probe_timer)) + if (timer_delete(&t->probe_timer)) sctp_transport_put(t); t->pl.state = SCTP_PL_DISABLED; }
diff --git a/include/net/tcp.h b/include/net/tcp.h index df04dc0..4450c38 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h
@@ -779,7 +779,6 @@ static inline int tcp_bound_to_half_wnd(struct tcp_sock *tp, int pktsize) /* tcp.c */ void tcp_get_info(struct sock *, struct tcp_info *); -void tcp_sock_rfree(struct sk_buff *skb); /* Read 'sendfile()'-style from a TCP socket */ int tcp_read_sock(struct sock *sk, read_descriptor_t *desc, @@ -2899,18 +2898,4 @@ enum skb_drop_reason tcp_inbound_hash(struct sock *sk, const void *saddr, const void *daddr, int family, int dif, int sdif); -/* version of skb_set_owner_r() avoiding one atomic_add() */ -static inline void tcp_skb_set_owner_r(struct sk_buff *skb, struct sock *sk) -{ - skb_orphan(skb); - skb->sk = sk; - skb->destructor = tcp_sock_rfree; - - sock_owned_by_me(sk); - atomic_set(&sk->sk_rmem_alloc, - atomic_read(&sk->sk_rmem_alloc) + skb->truesize); - - sk_forward_alloc_add(sk, -skb->truesize); -} - #endif /* _TCP_H */
diff --git a/include/trace/events/sunrpc.h b/include/trace/events/sunrpc.h index 8518413..5d33138 100644 --- a/include/trace/events/sunrpc.h +++ b/include/trace/events/sunrpc.h
@@ -343,6 +343,7 @@ TRACE_EVENT(rpc_request, { RPC_TASK_MOVEABLE, "MOVEABLE" }, \ { RPC_TASK_NULLCREDS, "NULLCREDS" }, \ { RPC_CALL_MAJORSEEN, "MAJORSEEN" }, \ + { RPC_TASK_NETUNREACH_FATAL, "NETUNREACH_FATAL"}, \ { RPC_TASK_DYNAMIC, "DYNAMIC" }, \ { RPC_TASK_NO_ROUND_ROBIN, "NO_ROUND_ROBIN" }, \ { RPC_TASK_SOFT, "SOFT" }, \
diff --git a/include/trace/events/timer.h b/include/trace/events/timer.h index 1ef58a0..1641ae3 100644 --- a/include/trace/events/timer.h +++ b/include/trace/events/timer.h
@@ -185,12 +185,12 @@ TRACE_EVENT(timer_base_idle, { HRTIMER_MODE_REL_PINNED_HARD, "REL|PINNED|HARD" }) /** - * hrtimer_init - called when the hrtimer is initialized + * hrtimer_setup - called when the hrtimer is initialized * @hrtimer: pointer to struct hrtimer * @clockid: the hrtimers clock * @mode: the hrtimers mode */ -TRACE_EVENT(hrtimer_init, +TRACE_EVENT(hrtimer_setup, TP_PROTO(struct hrtimer *hrtimer, clockid_t clockid, enum hrtimer_mode mode), @@ -235,7 +235,7 @@ TRACE_EVENT(hrtimer_start, TP_fast_assign( __entry->hrtimer = hrtimer; - __entry->function = hrtimer->function; + __entry->function = ACCESS_PRIVATE(hrtimer, function); __entry->expires = hrtimer_get_expires(hrtimer); __entry->softexpires = hrtimer_get_softexpires(hrtimer); __entry->mode = mode; @@ -271,7 +271,7 @@ TRACE_EVENT(hrtimer_expire_entry, TP_fast_assign( __entry->hrtimer = hrtimer; __entry->now = *now; - __entry->function = hrtimer->function; + __entry->function = ACCESS_PRIVATE(hrtimer, function); ), TP_printk("hrtimer=%p function=%ps now=%llu",
diff --git a/include/uapi/linux/fuse.h b/include/uapi/linux/fuse.h index 5e0eb41..5ec43ec 100644 --- a/include/uapi/linux/fuse.h +++ b/include/uapi/linux/fuse.h
@@ -229,6 +229,9 @@ * - FUSE_URING_IN_OUT_HEADER_SZ * - FUSE_URING_OP_IN_OUT_SZ * - enum fuse_uring_cmd + * + * 7.43 + * - add FUSE_REQUEST_TIMEOUT */ #ifndef _LINUX_FUSE_H @@ -264,7 +267,7 @@ #define FUSE_KERNEL_VERSION 7 /** Minor version number of this interface */ -#define FUSE_KERNEL_MINOR_VERSION 42 +#define FUSE_KERNEL_MINOR_VERSION 43 /** The node ID of the root inode */ #define FUSE_ROOT_ID 1 @@ -435,6 +438,8 @@ struct fuse_file_lock { * of the request ID indicates resend requests * FUSE_ALLOW_IDMAP: allow creation of idmapped mounts * FUSE_OVER_IO_URING: Indicate that client supports io-uring + * FUSE_REQUEST_TIMEOUT: kernel supports timing out requests. + * init_out.request_timeout contains the timeout (in secs) */ #define FUSE_ASYNC_READ (1 << 0) #define FUSE_POSIX_LOCKS (1 << 1) @@ -477,11 +482,11 @@ struct fuse_file_lock { #define FUSE_PASSTHROUGH (1ULL << 37) #define FUSE_NO_EXPORT_SUPPORT (1ULL << 38) #define FUSE_HAS_RESEND (1ULL << 39) - /* Obsolete alias for FUSE_DIRECT_IO_ALLOW_MMAP */ #define FUSE_DIRECT_IO_RELAX FUSE_DIRECT_IO_ALLOW_MMAP #define FUSE_ALLOW_IDMAP (1ULL << 40) #define FUSE_OVER_IO_URING (1ULL << 41) +#define FUSE_REQUEST_TIMEOUT (1ULL << 42) /** * CUSE INIT request/reply flags @@ -909,7 +914,8 @@ struct fuse_init_out { uint16_t map_alignment; uint32_t flags2; uint32_t max_stack_depth; - uint32_t unused[6]; + uint16_t request_timeout; + uint16_t unused[11]; }; #define CUSE_INIT_INFO_MAX 4096
diff --git a/include/uapi/linux/ublk_cmd.h b/include/uapi/linux/ublk_cmd.h index 7255b36..583b866 100644 --- a/include/uapi/linux/ublk_cmd.h +++ b/include/uapi/linux/ublk_cmd.h
@@ -410,6 +410,29 @@ struct ublk_param_dma_align { __u8 pad[4]; }; +#define UBLK_MIN_SEGMENT_SIZE 4096 +/* + * If any one of the three segment parameter is set as 0, the behavior is + * undefined. + */ +struct ublk_param_segment { + /* + * seg_boundary_mask + 1 needs to be power_of_2(), and the sum has + * to be >= UBLK_MIN_SEGMENT_SIZE(4096) + */ + __u64 seg_boundary_mask; + + /* + * max_segment_size could be override by virt_boundary_mask, so be + * careful when setting both. + * + * max_segment_size has to be >= UBLK_MIN_SEGMENT_SIZE(4096) + */ + __u32 max_segment_size; + __u16 max_segments; + __u8 pad[2]; +}; + struct ublk_params { /* * Total length of parameters, userspace has to set 'len' for both @@ -423,6 +446,7 @@ struct ublk_params { #define UBLK_PARAM_TYPE_DEVT (1 << 2) #define UBLK_PARAM_TYPE_ZONED (1 << 3) #define UBLK_PARAM_TYPE_DMA_ALIGN (1 << 4) +#define UBLK_PARAM_TYPE_SEGMENT (1 << 5) __u32 types; /* types of parameter included */ struct ublk_param_basic basic; @@ -430,6 +454,7 @@ struct ublk_params { struct ublk_param_devt devt; struct ublk_param_zoned zoned; struct ublk_param_dma_align dma; + struct ublk_param_segment seg; }; #endif
diff --git a/include/uapi/linux/usb/ch9.h b/include/uapi/linux/usb/ch9.h index 0522906..8003243 100644 --- a/include/uapi/linux/usb/ch9.h +++ b/include/uapi/linux/usb/ch9.h
@@ -253,6 +253,9 @@ struct usb_ctrlrequest { #define USB_DT_BOS 0x0f #define USB_DT_DEVICE_CAPABILITY 0x10 #define USB_DT_WIRELESS_ENDPOINT_COMP 0x11 +/* From the eUSB2 spec */ +#define USB_DT_EUSB2_ISOC_ENDPOINT_COMP 0x12 +/* From Wireless USB spec */ #define USB_DT_WIRE_ADAPTER 0x21 /* From USB Device Firmware Upgrade Specification, Revision 1.1 */ #define USB_DT_DFU_FUNCTIONAL 0x21 @@ -676,6 +679,18 @@ static inline int usb_endpoint_interrupt_type( /*-------------------------------------------------------------------------*/ +/* USB_DT_EUSB2_ISOC_ENDPOINT_COMP: eUSB2 Isoch Endpoint Companion descriptor */ +struct usb_eusb2_isoc_ep_comp_descriptor { + __u8 bLength; + __u8 bDescriptorType; + __le16 wMaxPacketSize; + __le32 dwBytesPerInterval; +} __attribute__ ((packed)); + +#define USB_DT_EUSB2_ISOC_EP_COMP_SIZE 8 + +/*-------------------------------------------------------------------------*/ + /* USB_DT_SSP_ISOC_ENDPOINT_COMP: SuperSpeedPlus Isochronous Endpoint Companion * descriptor */
diff --git a/include/uapi/misc/cxl.h b/include/uapi/misc/cxl.h deleted file mode 100644 index 56376d3..0000000 --- a/include/uapi/misc/cxl.h +++ /dev/null
@@ -1,156 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ -/* - * Copyright 2014 IBM Corp. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ - -#ifndef _UAPI_MISC_CXL_H -#define _UAPI_MISC_CXL_H - -#include <linux/types.h> -#include <linux/ioctl.h> - - -struct cxl_ioctl_start_work { - __u64 flags; - __u64 work_element_descriptor; - __u64 amr; - __s16 num_interrupts; - __u16 tid; - __s32 reserved1; - __u64 reserved2; - __u64 reserved3; - __u64 reserved4; - __u64 reserved5; -}; - -#define CXL_START_WORK_AMR 0x0000000000000001ULL -#define CXL_START_WORK_NUM_IRQS 0x0000000000000002ULL -#define CXL_START_WORK_ERR_FF 0x0000000000000004ULL -#define CXL_START_WORK_TID 0x0000000000000008ULL -#define CXL_START_WORK_ALL (CXL_START_WORK_AMR |\ - CXL_START_WORK_NUM_IRQS |\ - CXL_START_WORK_ERR_FF |\ - CXL_START_WORK_TID) - - -/* Possible modes that an afu can be in */ -#define CXL_MODE_DEDICATED 0x1 -#define CXL_MODE_DIRECTED 0x2 - -/* possible flags for the cxl_afu_id flags field */ -#define CXL_AFUID_FLAG_SLAVE 0x1 /* In directed-mode afu is in slave mode */ - -struct cxl_afu_id { - __u64 flags; /* One of CXL_AFUID_FLAG_X */ - __u32 card_id; - __u32 afu_offset; - __u32 afu_mode; /* one of the CXL_MODE_X */ - __u32 reserved1; - __u64 reserved2; - __u64 reserved3; - __u64 reserved4; - __u64 reserved5; - __u64 reserved6; -}; - -/* base adapter image header is included in the image */ -#define CXL_AI_NEED_HEADER 0x0000000000000001ULL -#define CXL_AI_ALL CXL_AI_NEED_HEADER - -#define CXL_AI_HEADER_SIZE 128 -#define CXL_AI_BUFFER_SIZE 4096 -#define CXL_AI_MAX_ENTRIES 256 -#define CXL_AI_MAX_CHUNK_SIZE (CXL_AI_BUFFER_SIZE * CXL_AI_MAX_ENTRIES) - -struct cxl_adapter_image { - __u64 flags; - __u64 data; - __u64 len_data; - __u64 len_image; - __u64 reserved1; - __u64 reserved2; - __u64 reserved3; - __u64 reserved4; -}; - -/* ioctl numbers */ -#define CXL_MAGIC 0xCA -/* AFU devices */ -#define CXL_IOCTL_START_WORK _IOW(CXL_MAGIC, 0x00, struct cxl_ioctl_start_work) -#define CXL_IOCTL_GET_PROCESS_ELEMENT _IOR(CXL_MAGIC, 0x01, __u32) -#define CXL_IOCTL_GET_AFU_ID _IOR(CXL_MAGIC, 0x02, struct cxl_afu_id) -/* adapter devices */ -#define CXL_IOCTL_DOWNLOAD_IMAGE _IOW(CXL_MAGIC, 0x0A, struct cxl_adapter_image) -#define CXL_IOCTL_VALIDATE_IMAGE _IOW(CXL_MAGIC, 0x0B, struct cxl_adapter_image) - -#define CXL_READ_MIN_SIZE 0x1000 /* 4K */ - -/* Events from read() */ -enum cxl_event_type { - CXL_EVENT_RESERVED = 0, - CXL_EVENT_AFU_INTERRUPT = 1, - CXL_EVENT_DATA_STORAGE = 2, - CXL_EVENT_AFU_ERROR = 3, - CXL_EVENT_AFU_DRIVER = 4, -}; - -struct cxl_event_header { - __u16 type; - __u16 size; - __u16 process_element; - __u16 reserved1; -}; - -struct cxl_event_afu_interrupt { - __u16 flags; - __u16 irq; /* Raised AFU interrupt number */ - __u32 reserved1; -}; - -struct cxl_event_data_storage { - __u16 flags; - __u16 reserved1; - __u32 reserved2; - __u64 addr; - __u64 dsisr; - __u64 reserved3; -}; - -struct cxl_event_afu_error { - __u16 flags; - __u16 reserved1; - __u32 reserved2; - __u64 error; -}; - -struct cxl_event_afu_driver_reserved { - /* - * Defines the buffer passed to the cxl driver by the AFU driver. - * - * This is not ABI since the event header.size passed to the user for - * existing events is set in the read call to sizeof(cxl_event_header) - * + sizeof(whatever event is being dispatched) and the user is already - * required to use a 4K buffer on the read call. - * - * Of course the contents will be ABI, but that's up the AFU driver. - */ - __u32 data_size; - __u8 data[]; -}; - -struct cxl_event { - struct cxl_event_header header; - union { - struct cxl_event_afu_interrupt irq; - struct cxl_event_data_storage fault; - struct cxl_event_afu_error afu_error; - struct cxl_event_afu_driver_reserved afu_driver_event; - }; -}; - -#endif /* _UAPI_MISC_CXL_H */
diff --git a/init/Kconfig b/init/Kconfig index 681f38e..dd2ea3b 100644 --- a/init/Kconfig +++ b/init/Kconfig
@@ -132,6 +132,11 @@ config CC_HAS_MULTIDIMENSIONAL_NONSTRING def_bool $(success,echo 'char tag[][4] __attribute__((__nonstring__)) = { };' | $(CC) $(CLANG_FLAGS) -x c - -c -o /dev/null -Werror) +config LD_CAN_USE_KEEP_IN_OVERLAY + # ld.lld prior to 21.0.0 did not support KEEP within an overlay description + # https://github.com/llvm/llvm-project/pull/130661 + def_bool LD_IS_BFD || LLD_VERSION >= 210000 + config RUSTC_HAS_COERCE_POINTEE def_bool RUSTC_VERSION >= 108400 @@ -709,7 +714,7 @@ config CPU_ISOLATION bool "CPU isolation" - depends on SMP || COMPILE_TEST + depends on SMP default y help Make sure that CPUs running critical tasks are not disturbed by @@ -1888,6 +1893,28 @@ config ARCH_HAS_MEMBARRIER_SYNC_CORE bool +config ARCH_SUPPORTS_MSEAL_SYSTEM_MAPPINGS + bool + help + Control MSEAL_SYSTEM_MAPPINGS access based on architecture. + + A 64-bit kernel is required for the memory sealing feature. + No specific hardware features from the CPU are needed. + + To enable this feature, the architecture needs to update their + special mappings calls to include the sealing flag and confirm + that it doesn't unmap/remap system mappings during the life + time of the process. The existence of this flag for an architecture + implies that it does not require the remapping of the system + mappings during process lifetime, so sealing these mappings is safe + from a kernel perspective. + + After the architecture enables this, a distribution can set + CONFIG_MSEAL_SYSTEM_MAPPING to manage access to the feature. + + For complete descriptions of memory sealing, please see + Documentation/userspace-api/mseal.rst + config HAVE_PERF_EVENTS bool help
diff --git a/io_uring/Kconfig b/io_uring/Kconfig index 9e2a4be..4b949c4 100644 --- a/io_uring/Kconfig +++ b/io_uring/Kconfig
@@ -5,6 +5,7 @@ config IO_URING_ZCRX def_bool y + depends on IO_URING depends on PAGE_POOL depends on INET depends on NET_RX_BUSY_POLL
diff --git a/io_uring/io_uring.c b/io_uring/io_uring.c index 3ba49c6..c6209fe 100644 --- a/io_uring/io_uring.c +++ b/io_uring/io_uring.c
@@ -1141,10 +1141,9 @@ void tctx_task_work(struct callback_head *cb) WARN_ON_ONCE(ret); } -static inline void io_req_local_work_add(struct io_kiocb *req, - struct io_ring_ctx *ctx, - unsigned flags) +static void io_req_local_work_add(struct io_kiocb *req, unsigned flags) { + struct io_ring_ctx *ctx = req->ctx; unsigned nr_wait, nr_tw, nr_tw_prev; struct llist_node *head; @@ -1239,17 +1238,16 @@ static void io_req_normal_work_add(struct io_kiocb *req) void __io_req_task_work_add(struct io_kiocb *req, unsigned flags) { if (req->ctx->flags & IORING_SETUP_DEFER_TASKRUN) - io_req_local_work_add(req, req->ctx, flags); + io_req_local_work_add(req, flags); else io_req_normal_work_add(req); } -void io_req_task_work_add_remote(struct io_kiocb *req, struct io_ring_ctx *ctx, - unsigned flags) +void io_req_task_work_add_remote(struct io_kiocb *req, unsigned flags) { - if (WARN_ON_ONCE(!(ctx->flags & IORING_SETUP_DEFER_TASKRUN))) + if (WARN_ON_ONCE(!(req->ctx->flags & IORING_SETUP_DEFER_TASKRUN))) return; - io_req_local_work_add(req, ctx, flags); + __io_req_task_work_add(req, flags); } static void __cold io_move_task_work_from_local(struct io_ring_ctx *ctx) @@ -1645,6 +1643,8 @@ io_req_flags_t io_file_get_flags(struct file *file) { io_req_flags_t res = 0; + BUILD_BUG_ON(REQ_F_ISREG_BIT != REQ_F_SUPPORT_NOWAIT_BIT + 1); + if (S_ISREG(file_inode(file)->i_mode)) res |= REQ_F_ISREG; if ((file->f_flags & O_NONBLOCK) || (file->f_mode & FMODE_NOWAIT)) @@ -1796,7 +1796,7 @@ struct io_wq_work *io_wq_free_work(struct io_wq_work *work) struct io_kiocb *req = container_of(work, struct io_kiocb, work); struct io_kiocb *nxt = NULL; - if (req_ref_put_and_test(req)) { + if (req_ref_put_and_test_atomic(req)) { if (req->flags & IO_REQ_LINK_FLAGS) nxt = io_req_find_next(req); io_free_req(req);
diff --git a/io_uring/io_uring.h b/io_uring/io_uring.h index 87f8831..e4050b2 100644 --- a/io_uring/io_uring.h +++ b/io_uring/io_uring.h
@@ -89,8 +89,7 @@ struct file *io_file_get_fixed(struct io_kiocb *req, int fd, unsigned issue_flags); void __io_req_task_work_add(struct io_kiocb *req, unsigned flags); -void io_req_task_work_add_remote(struct io_kiocb *req, struct io_ring_ctx *ctx, - unsigned flags); +void io_req_task_work_add_remote(struct io_kiocb *req, unsigned flags); void io_req_task_queue(struct io_kiocb *req); void io_req_task_complete(struct io_kiocb *req, io_tw_token_t tw); void io_req_task_queue_fail(struct io_kiocb *req, int ret);
diff --git a/io_uring/msg_ring.c b/io_uring/msg_ring.c index 0bbcbbc..50a958e 100644 --- a/io_uring/msg_ring.c +++ b/io_uring/msg_ring.c
@@ -38,8 +38,8 @@ static void io_double_unlock_ctx(struct io_ring_ctx *octx) mutex_unlock(&octx->uring_lock); } -static int io_double_lock_ctx(struct io_ring_ctx *octx, - unsigned int issue_flags) +static int io_lock_external_ctx(struct io_ring_ctx *octx, + unsigned int issue_flags) { /* * To ensure proper ordering between the two ctxs, we can only @@ -93,13 +93,14 @@ static int io_msg_remote_post(struct io_ring_ctx *ctx, struct io_kiocb *req, kmem_cache_free(req_cachep, req); return -EOWNERDEAD; } + req->opcode = IORING_OP_NOP; req->cqe.user_data = user_data; io_req_set_res(req, res, cflags); percpu_ref_get(&ctx->refs); req->ctx = ctx; req->tctx = NULL; req->io_task_work.func = io_msg_tw_complete; - io_req_task_work_add_remote(req, ctx, IOU_F_TWQ_LAZY_WAKE); + io_req_task_work_add_remote(req, IOU_F_TWQ_LAZY_WAKE); return 0; } @@ -154,7 +155,7 @@ static int __io_msg_ring_data(struct io_ring_ctx *target_ctx, ret = -EOVERFLOW; if (target_ctx->flags & IORING_SETUP_IOPOLL) { - if (unlikely(io_double_lock_ctx(target_ctx, issue_flags))) + if (unlikely(io_lock_external_ctx(target_ctx, issue_flags))) return -EAGAIN; } if (io_post_aux_cqe(target_ctx, msg->user_data, msg->len, flags)) @@ -199,7 +200,7 @@ static int io_msg_install_complete(struct io_kiocb *req, unsigned int issue_flag struct file *src_file = msg->src_file; int ret; - if (unlikely(io_double_lock_ctx(target_ctx, issue_flags))) + if (unlikely(io_lock_external_ctx(target_ctx, issue_flags))) return -EAGAIN; ret = __io_fixed_fd_install(target_ctx, src_file, msg->dst_fd);
diff --git a/io_uring/net.c b/io_uring/net.c index 8944eb67..24040bc 100644 --- a/io_uring/net.c +++ b/io_uring/net.c
@@ -97,6 +97,11 @@ struct io_recvzc { struct io_zcrx_ifq *ifq; }; +static int io_sg_from_iter_iovec(struct sk_buff *skb, + struct iov_iter *from, size_t length); +static int io_sg_from_iter(struct sk_buff *skb, + struct iov_iter *from, size_t length); + int io_shutdown_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) { struct io_shutdown *shutdown = io_kiocb_to_cmd(req, struct io_shutdown); @@ -176,16 +181,6 @@ static struct io_async_msghdr *io_msg_alloc_async(struct io_kiocb *req) return hdr; } -/* assign new iovec to kmsg, if we need to */ -static void io_net_vec_assign(struct io_kiocb *req, struct io_async_msghdr *kmsg, - struct iovec *iov) -{ - if (iov) { - req->flags |= REQ_F_NEED_CLEANUP; - io_vec_reset_iovec(&kmsg->vec, iov, kmsg->msg.msg_iter.nr_segs); - } -} - static inline void io_mshot_prep_retry(struct io_kiocb *req, struct io_async_msghdr *kmsg) { @@ -217,7 +212,11 @@ static int io_net_import_vec(struct io_kiocb *req, struct io_async_msghdr *iomsg &iomsg->msg.msg_iter, io_is_compat(req->ctx)); if (unlikely(ret < 0)) return ret; - io_net_vec_assign(req, iomsg, iov); + + if (iov) { + req->flags |= REQ_F_NEED_CLEANUP; + io_vec_reset_iovec(&iomsg->vec, iov, iomsg->msg.msg_iter.nr_segs); + } return 0; } @@ -325,25 +324,6 @@ static int io_msg_copy_hdr(struct io_kiocb *req, struct io_async_msghdr *iomsg, return 0; } -static int io_sendmsg_copy_hdr(struct io_kiocb *req, - struct io_async_msghdr *iomsg) -{ - struct io_sr_msg *sr = io_kiocb_to_cmd(req, struct io_sr_msg); - struct user_msghdr msg; - int ret; - - ret = io_msg_copy_hdr(req, iomsg, &msg, ITER_SOURCE, NULL); - if (unlikely(ret)) - return ret; - - if (!(req->flags & REQ_F_BUFFER_SELECT)) - ret = io_net_import_vec(req, iomsg, msg.msg_iov, msg.msg_iovlen, - ITER_SOURCE); - /* save msg_control as sys_sendmsg() overwrites it */ - sr->msg_control = iomsg->msg.msg_control_user; - return ret; -} - void io_sendmsg_recvmsg_cleanup(struct io_kiocb *req) { struct io_async_msghdr *io = req->async_data; @@ -379,6 +359,8 @@ static int io_send_setup(struct io_kiocb *req, const struct io_uring_sqe *sqe) kmsg->msg.msg_name = &kmsg->addr; kmsg->msg.msg_namelen = addr_len; } + if (sr->flags & IORING_RECVSEND_FIXED_BUF) + return 0; if (!io_do_buffer_select(req)) { ret = import_ubuf(ITER_SOURCE, sr->buf, sr->len, &kmsg->msg.msg_iter); @@ -392,31 +374,24 @@ static int io_sendmsg_setup(struct io_kiocb *req, const struct io_uring_sqe *sqe { struct io_sr_msg *sr = io_kiocb_to_cmd(req, struct io_sr_msg); struct io_async_msghdr *kmsg = req->async_data; - - sr->umsg = u64_to_user_ptr(READ_ONCE(sqe->addr)); - - return io_sendmsg_copy_hdr(req, kmsg); -} - -static int io_sendmsg_zc_setup(struct io_kiocb *req, const struct io_uring_sqe *sqe) -{ - struct io_sr_msg *sr = io_kiocb_to_cmd(req, struct io_sr_msg); - struct io_async_msghdr *kmsg = req->async_data; struct user_msghdr msg; int ret; - if (!(sr->flags & IORING_RECVSEND_FIXED_BUF)) - return io_sendmsg_setup(req, sqe); - sr->umsg = u64_to_user_ptr(READ_ONCE(sqe->addr)); - ret = io_msg_copy_hdr(req, kmsg, &msg, ITER_SOURCE, NULL); if (unlikely(ret)) return ret; + /* save msg_control as sys_sendmsg() overwrites it */ sr->msg_control = kmsg->msg.msg_control_user; - kmsg->msg.msg_iter.nr_segs = msg.msg_iovlen; - return io_prep_reg_iovec(req, &kmsg->vec, msg.msg_iov, msg.msg_iovlen); + if (sr->flags & IORING_RECVSEND_FIXED_BUF) { + kmsg->msg.msg_iter.nr_segs = msg.msg_iovlen; + return io_prep_reg_iovec(req, &kmsg->vec, msg.msg_iov, + msg.msg_iovlen); + } + if (req->flags & REQ_F_BUFFER_SELECT) + return 0; + return io_net_import_vec(req, kmsg, msg.msg_iov, msg.msg_iovlen, ITER_SOURCE); } #define SENDMSG_FLAGS (IORING_RECVSEND_POLL_FIRST | IORING_RECVSEND_BUNDLE) @@ -427,12 +402,6 @@ int io_sendmsg_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) sr->done_io = 0; sr->retry = false; - - if (req->opcode != IORING_OP_SEND) { - if (sqe->addr2 || sqe->file_index) - return -EINVAL; - } - sr->len = READ_ONCE(sqe->len); sr->flags = READ_ONCE(sqe->ioprio); if (sr->flags & ~SENDMSG_FLAGS) @@ -458,6 +427,8 @@ int io_sendmsg_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) return -ENOMEM; if (req->opcode != IORING_OP_SENDMSG) return io_send_setup(req, sqe); + if (unlikely(sqe->addr2 || sqe->file_index)) + return -EINVAL; return io_sendmsg_setup(req, sqe); } @@ -1302,11 +1273,12 @@ int io_send_zc_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) { struct io_sr_msg *zc = io_kiocb_to_cmd(req, struct io_sr_msg); struct io_ring_ctx *ctx = req->ctx; + struct io_async_msghdr *iomsg; struct io_kiocb *notif; + int ret; zc->done_io = 0; zc->retry = false; - req->flags |= REQ_F_POLL_NO_LAZY; if (unlikely(READ_ONCE(sqe->__pad2[0]) || READ_ONCE(sqe->addr3))) return -EINVAL; @@ -1320,7 +1292,7 @@ int io_send_zc_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) notif->cqe.user_data = req->cqe.user_data; notif->cqe.res = 0; notif->cqe.flags = IORING_CQE_F_NOTIF; - req->flags |= REQ_F_NEED_CLEANUP; + req->flags |= REQ_F_NEED_CLEANUP | REQ_F_POLL_NO_LAZY; zc->flags = READ_ONCE(sqe->ioprio); if (unlikely(zc->flags & ~IO_ZC_FLAGS_COMMON)) { @@ -1335,11 +1307,6 @@ int io_send_zc_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) } } - if (req->opcode != IORING_OP_SEND_ZC) { - if (unlikely(sqe->addr2 || sqe->file_index)) - return -EINVAL; - } - zc->len = READ_ONCE(sqe->len); zc->msg_flags = READ_ONCE(sqe->msg_flags) | MSG_NOSIGNAL | MSG_ZEROCOPY; req->buf_index = READ_ONCE(sqe->buf_index); @@ -1349,13 +1316,28 @@ int io_send_zc_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) if (io_is_compat(req->ctx)) zc->msg_flags |= MSG_CMSG_COMPAT; - if (unlikely(!io_msg_alloc_async(req))) + iomsg = io_msg_alloc_async(req); + if (unlikely(!iomsg)) return -ENOMEM; + if (req->opcode == IORING_OP_SEND_ZC) { - req->flags |= REQ_F_IMPORT_BUFFER; - return io_send_setup(req, sqe); + if (zc->flags & IORING_RECVSEND_FIXED_BUF) + req->flags |= REQ_F_IMPORT_BUFFER; + ret = io_send_setup(req, sqe); + } else { + if (unlikely(sqe->addr2 || sqe->file_index)) + return -EINVAL; + ret = io_sendmsg_setup(req, sqe); } - return io_sendmsg_zc_setup(req, sqe); + if (unlikely(ret)) + return ret; + + if (!(zc->flags & IORING_RECVSEND_FIXED_BUF)) { + iomsg->msg.sg_from_iter = io_sg_from_iter_iovec; + return io_notif_account_mem(zc->notif, iomsg->msg.msg_iter.count); + } + iomsg->msg.sg_from_iter = io_sg_from_iter; + return 0; } static int io_sg_from_iter_iovec(struct sk_buff *skb, @@ -1412,27 +1394,13 @@ static int io_send_zc_import(struct io_kiocb *req, unsigned int issue_flags) { struct io_sr_msg *sr = io_kiocb_to_cmd(req, struct io_sr_msg); struct io_async_msghdr *kmsg = req->async_data; - int ret; - if (sr->flags & IORING_RECVSEND_FIXED_BUF) { - sr->notif->buf_index = req->buf_index; - ret = io_import_reg_buf(sr->notif, &kmsg->msg.msg_iter, - (u64)(uintptr_t)sr->buf, sr->len, - ITER_SOURCE, issue_flags); - if (unlikely(ret)) - return ret; - kmsg->msg.sg_from_iter = io_sg_from_iter; - } else { - ret = import_ubuf(ITER_SOURCE, sr->buf, sr->len, &kmsg->msg.msg_iter); - if (unlikely(ret)) - return ret; - ret = io_notif_account_mem(sr->notif, sr->len); - if (unlikely(ret)) - return ret; - kmsg->msg.sg_from_iter = io_sg_from_iter_iovec; - } + WARN_ON_ONCE(!(sr->flags & IORING_RECVSEND_FIXED_BUF)); - return ret; + sr->notif->buf_index = req->buf_index; + return io_import_reg_buf(sr->notif, &kmsg->msg.msg_iter, + (u64)(uintptr_t)sr->buf, sr->len, + ITER_SOURCE, issue_flags); } int io_send_zc(struct io_kiocb *req, unsigned int issue_flags) @@ -1513,8 +1481,6 @@ int io_sendmsg_zc(struct io_kiocb *req, unsigned int issue_flags) unsigned flags; int ret, min_ret = 0; - kmsg->msg.sg_from_iter = io_sg_from_iter_iovec; - if (req->flags & REQ_F_IMPORT_BUFFER) { unsigned uvec_segs = kmsg->msg.msg_iter.nr_segs; int ret; @@ -1523,7 +1489,6 @@ int io_sendmsg_zc(struct io_kiocb *req, unsigned int issue_flags) &kmsg->vec, uvec_segs, issue_flags); if (unlikely(ret)) return ret; - kmsg->msg.sg_from_iter = io_sg_from_iter; req->flags &= ~REQ_F_IMPORT_BUFFER; }
diff --git a/io_uring/refs.h b/io_uring/refs.h index 63982ea..0d928d8 100644 --- a/io_uring/refs.h +++ b/io_uring/refs.h
@@ -17,6 +17,13 @@ static inline bool req_ref_inc_not_zero(struct io_kiocb *req) return atomic_inc_not_zero(&req->refs); } +static inline bool req_ref_put_and_test_atomic(struct io_kiocb *req) +{ + WARN_ON_ONCE(!(data_race(req->flags) & REQ_F_REFCOUNT)); + WARN_ON_ONCE(req_ref_zero_or_close_to_overflow(req)); + return atomic_dec_and_test(&req->refs); +} + static inline bool req_ref_put_and_test(struct io_kiocb *req) { if (likely(!(req->flags & REQ_F_REFCOUNT)))
diff --git a/io_uring/rsrc.c b/io_uring/rsrc.c index 3f195e2..5e64a8b 100644 --- a/io_uring/rsrc.c +++ b/io_uring/rsrc.c
@@ -1002,20 +1002,33 @@ int io_buffer_unregister_bvec(struct io_uring_cmd *cmd, unsigned int index, } EXPORT_SYMBOL_GPL(io_buffer_unregister_bvec); -static int io_import_fixed(int ddir, struct iov_iter *iter, - struct io_mapped_ubuf *imu, - u64 buf_addr, size_t len) +static int validate_fixed_range(u64 buf_addr, size_t len, + const struct io_mapped_ubuf *imu) { u64 buf_end; - size_t offset; - if (WARN_ON_ONCE(!imu)) - return -EFAULT; if (unlikely(check_add_overflow(buf_addr, (u64)len, &buf_end))) return -EFAULT; /* not inside the mapped region */ if (unlikely(buf_addr < imu->ubuf || buf_end > (imu->ubuf + imu->len))) return -EFAULT; + if (unlikely(len > MAX_RW_COUNT)) + return -EFAULT; + return 0; +} + +static int io_import_fixed(int ddir, struct iov_iter *iter, + struct io_mapped_ubuf *imu, + u64 buf_addr, size_t len) +{ + size_t offset; + int ret; + + if (WARN_ON_ONCE(!imu)) + return -EFAULT; + ret = validate_fixed_range(buf_addr, len, imu); + if (unlikely(ret)) + return ret; if (!(imu->dir & (1 << ddir))) return -EFAULT; @@ -1305,12 +1318,12 @@ static int io_vec_fill_bvec(int ddir, struct iov_iter *iter, u64 buf_addr = (u64)(uintptr_t)iovec[iov_idx].iov_base; struct bio_vec *src_bvec; size_t offset; - u64 buf_end; + int ret; - if (unlikely(check_add_overflow(buf_addr, (u64)iov_len, &buf_end))) - return -EFAULT; - if (unlikely(buf_addr < imu->ubuf || buf_end > (imu->ubuf + imu->len))) - return -EFAULT; + ret = validate_fixed_range(buf_addr, iov_len, imu); + if (unlikely(ret)) + return ret; + if (unlikely(!iov_len)) return -EFAULT; if (unlikely(check_add_overflow(total_len, iov_len, &total_len))) @@ -1349,6 +1362,82 @@ static int io_estimate_bvec_size(struct iovec *iov, unsigned nr_iovs, return max_segs; } +static int io_vec_fill_kern_bvec(int ddir, struct iov_iter *iter, + struct io_mapped_ubuf *imu, + struct iovec *iovec, unsigned nr_iovs, + struct iou_vec *vec) +{ + const struct bio_vec *src_bvec = imu->bvec; + struct bio_vec *res_bvec = vec->bvec; + unsigned res_idx = 0; + size_t total_len = 0; + unsigned iov_idx; + + for (iov_idx = 0; iov_idx < nr_iovs; iov_idx++) { + size_t offset = (size_t)(uintptr_t)iovec[iov_idx].iov_base; + size_t iov_len = iovec[iov_idx].iov_len; + struct bvec_iter bi = { + .bi_size = offset + iov_len, + }; + struct bio_vec bv; + + bvec_iter_advance(src_bvec, &bi, offset); + for_each_mp_bvec(bv, src_bvec, bi, bi) + res_bvec[res_idx++] = bv; + total_len += iov_len; + } + iov_iter_bvec(iter, ddir, res_bvec, res_idx, total_len); + return 0; +} + +static int iov_kern_bvec_size(const struct iovec *iov, + const struct io_mapped_ubuf *imu, + unsigned int *nr_seg) +{ + size_t offset = (size_t)(uintptr_t)iov->iov_base; + const struct bio_vec *bvec = imu->bvec; + int start = 0, i = 0; + size_t off = 0; + int ret; + + ret = validate_fixed_range(offset, iov->iov_len, imu); + if (unlikely(ret)) + return ret; + + for (i = 0; off < offset + iov->iov_len && i < imu->nr_bvecs; + off += bvec[i].bv_len, i++) { + if (offset >= off && offset < off + bvec[i].bv_len) + start = i; + } + *nr_seg = i - start; + return 0; +} + +static int io_kern_bvec_size(struct iovec *iov, unsigned nr_iovs, + struct io_mapped_ubuf *imu, unsigned *nr_segs) +{ + unsigned max_segs = 0; + size_t total_len = 0; + unsigned i; + int ret; + + *nr_segs = 0; + for (i = 0; i < nr_iovs; i++) { + if (unlikely(!iov[i].iov_len)) + return -EFAULT; + if (unlikely(check_add_overflow(total_len, iov[i].iov_len, + &total_len))) + return -EOVERFLOW; + ret = iov_kern_bvec_size(&iov[i], imu, &max_segs); + if (unlikely(ret)) + return ret; + *nr_segs += max_segs; + } + if (total_len > MAX_RW_COUNT) + return -EINVAL; + return 0; +} + int io_import_reg_vec(int ddir, struct iov_iter *iter, struct io_kiocb *req, struct iou_vec *vec, unsigned nr_iovs, unsigned issue_flags) @@ -1363,14 +1452,20 @@ int io_import_reg_vec(int ddir, struct iov_iter *iter, if (!node) return -EFAULT; imu = node->buf; - if (imu->is_kbuf) - return -EOPNOTSUPP; if (!(imu->dir & (1 << ddir))) return -EFAULT; iovec_off = vec->nr - nr_iovs; iov = vec->iovec + iovec_off; - nr_segs = io_estimate_bvec_size(iov, nr_iovs, imu); + + if (imu->is_kbuf) { + int ret = io_kern_bvec_size(iov, nr_iovs, imu, &nr_segs); + + if (unlikely(ret)) + return ret; + } else { + nr_segs = io_estimate_bvec_size(iov, nr_iovs, imu); + } if (sizeof(struct bio_vec) > sizeof(struct iovec)) { size_t bvec_bytes; @@ -1397,6 +1492,9 @@ int io_import_reg_vec(int ddir, struct iov_iter *iter, req->flags |= REQ_F_NEED_CLEANUP; } + if (imu->is_kbuf) + return io_vec_fill_kern_bvec(ddir, iter, imu, iov, nr_iovs, vec); + return io_vec_fill_bvec(ddir, iter, imu, iov, nr_iovs, vec); }
diff --git a/io_uring/uring_cmd.c b/io_uring/uring_cmd.c index f2cfc37..a9ea7d2 100644 --- a/io_uring/uring_cmd.c +++ b/io_uring/uring_cmd.c
@@ -205,8 +205,8 @@ static int io_uring_cmd_prep_setup(struct io_kiocb *req, * that it doesn't read in per-op data, play it safe and ensure that * any SQE data is stable beyond prep. This can later get relaxed. */ - memcpy(ac->data.sqes, sqe, uring_sqe_size(req->ctx)); - ioucmd->sqe = ac->data.sqes; + memcpy(ac->sqes, sqe, uring_sqe_size(req->ctx)); + ioucmd->sqe = ac->sqes; return 0; } @@ -307,17 +307,18 @@ static inline int io_uring_cmd_getsockopt(struct socket *sock, struct io_uring_cmd *cmd, unsigned int issue_flags) { + const struct io_uring_sqe *sqe = cmd->sqe; bool compat = !!(issue_flags & IO_URING_F_COMPAT); int optlen, optname, level, err; void __user *optval; - level = READ_ONCE(cmd->sqe->level); + level = READ_ONCE(sqe->level); if (level != SOL_SOCKET) return -EOPNOTSUPP; - optval = u64_to_user_ptr(READ_ONCE(cmd->sqe->optval)); - optname = READ_ONCE(cmd->sqe->optname); - optlen = READ_ONCE(cmd->sqe->optlen); + optval = u64_to_user_ptr(READ_ONCE(sqe->optval)); + optname = READ_ONCE(sqe->optname); + optlen = READ_ONCE(sqe->optlen); err = do_sock_getsockopt(sock, compat, level, optname, USER_SOCKPTR(optval), @@ -333,15 +334,16 @@ static inline int io_uring_cmd_setsockopt(struct socket *sock, struct io_uring_cmd *cmd, unsigned int issue_flags) { + const struct io_uring_sqe *sqe = cmd->sqe; bool compat = !!(issue_flags & IO_URING_F_COMPAT); int optname, optlen, level; void __user *optval; sockptr_t optval_s; - optval = u64_to_user_ptr(READ_ONCE(cmd->sqe->optval)); - optname = READ_ONCE(cmd->sqe->optname); - optlen = READ_ONCE(cmd->sqe->optlen); - level = READ_ONCE(cmd->sqe->level); + optval = u64_to_user_ptr(READ_ONCE(sqe->optval)); + optname = READ_ONCE(sqe->optname); + optlen = READ_ONCE(sqe->optlen); + level = READ_ONCE(sqe->level); optval_s = USER_SOCKPTR(optval); return do_sock_setsockopt(sock, compat, level, optname, optval_s,
diff --git a/io_uring/uring_cmd.h b/io_uring/uring_cmd.h index 14e5252..b04686b 100644 --- a/io_uring/uring_cmd.h +++ b/io_uring/uring_cmd.h
@@ -6,6 +6,7 @@ struct io_async_cmd { struct io_uring_cmd_data data; struct iou_vec vec; + struct io_uring_sqe sqes[2]; }; int io_uring_cmd(struct io_kiocb *req, unsigned int issue_flags);
diff --git a/io_uring/zcrx.c b/io_uring/zcrx.c index 9c95b5b..80d4a6f 100644 --- a/io_uring/zcrx.c +++ b/io_uring/zcrx.c
@@ -818,6 +818,14 @@ io_zcrx_recv_skb(read_descriptor_t *desc, struct sk_buff *skb, int ret = 0; len = min_t(size_t, len, desc->count); + /* + * __tcp_read_sock() always calls io_zcrx_recv_skb one last time, even + * if desc->count is already 0. This is caused by the if (offset + 1 != + * skb->len) check. Return early in this case to break out of + * __tcp_read_sock(). + */ + if (!len) + return 0; if (unlikely(args->nr_skbs++ > IO_SKBS_PER_CALL_LIMIT)) return -EAGAIN;
diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c index ac2db99..3caf2cd 100644 --- a/kernel/cgroup/cgroup.c +++ b/kernel/cgroup/cgroup.c
@@ -1695,7 +1695,7 @@ static void cgroup_rm_file(struct cgroup *cgrp, const struct cftype *cft) cfile->kn = NULL; spin_unlock_irq(&cgroup_file_kn_lock); - del_timer_sync(&cfile->notify_timer); + timer_delete_sync(&cfile->notify_timer); } kernfs_remove_by_name(cgrp->kn, cgroup_file_name(cgrp, cft, name)); @@ -5923,6 +5923,12 @@ static void kill_css(struct cgroup_subsys_state *css) if (css->flags & CSS_DYING) return; + /* + * Call css_killed(), if defined, before setting the CSS_DYING flag + */ + if (css->ss->css_killed) + css->ss->css_killed(css); + css->flags |= CSS_DYING; /*
diff --git a/kernel/cgroup/cpuset-internal.h b/kernel/cgroup/cpuset-internal.h index 976a8bc..383963e 100644 --- a/kernel/cgroup/cpuset-internal.h +++ b/kernel/cgroup/cpuset-internal.h
@@ -33,6 +33,7 @@ enum prs_errcode { PERR_CPUSEMPTY, PERR_HKEEPING, PERR_ACCESS, + PERR_REMOTE, }; /* bits in struct cpuset flags field */
diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c index 39c1fc6..306b604 100644 --- a/kernel/cgroup/cpuset.c +++ b/kernel/cgroup/cpuset.c
@@ -61,10 +61,17 @@ static const char * const perr_strings[] = { [PERR_CPUSEMPTY] = "cpuset.cpus and cpuset.cpus.exclusive are empty", [PERR_HKEEPING] = "partition config conflicts with housekeeping setup", [PERR_ACCESS] = "Enable partition not permitted", + [PERR_REMOTE] = "Have remote partition underneath", }; /* - * Exclusive CPUs distributed out to sub-partitions of top_cpuset + * For local partitions, update to subpartitions_cpus & isolated_cpus is done + * in update_parent_effective_cpumask(). For remote partitions, it is done in + * the remote_partition_*() and remote_cpus_update() helpers. + */ +/* + * Exclusive CPUs distributed out to local or remote sub-partitions of + * top_cpuset */ static cpumask_var_t subpartitions_cpus; @@ -86,7 +93,6 @@ static struct list_head remote_children; * A flag to force sched domain rebuild at the end of an operation. * It can be set in * - update_partition_sd_lb() - * - remote_partition_check() * - update_cpumasks_hier() * - cpuset_update_flag() * - cpuset_hotplug_update_tasks() @@ -1089,9 +1095,14 @@ void cpuset_reset_sched_domains(void) * * Iterate through each task of @cs updating its cpus_allowed to the * effective cpuset's. As this function is called with cpuset_mutex held, - * cpuset membership stays stable. For top_cpuset, task_cpu_possible_mask() - * is used instead of effective_cpus to make sure all offline CPUs are also - * included as hotplug code won't update cpumasks for tasks in top_cpuset. + * cpuset membership stays stable. + * + * For top_cpuset, task_cpu_possible_mask() is used instead of effective_cpus + * to make sure all offline CPUs are also included as hotplug code won't + * update cpumasks for tasks in top_cpuset. + * + * As task_cpu_possible_mask() can be task dependent in arm64, we have to + * do cpu masking per task instead of doing it once for all. */ void cpuset_update_tasks_cpumask(struct cpuset *cs, struct cpumask *new_cpus) { @@ -1151,7 +1162,7 @@ static void update_sibling_cpumasks(struct cpuset *parent, struct cpuset *cs, * * Return: 0 if successful, an error code otherwise */ -static int update_partition_exclusive(struct cpuset *cs, int new_prs) +static int update_partition_exclusive_flag(struct cpuset *cs, int new_prs) { bool exclusive = (new_prs > PRS_MEMBER); @@ -1234,12 +1245,12 @@ static void reset_partition_data(struct cpuset *cs) } /* - * partition_xcpus_newstate - Exclusive CPUs state change + * isolated_cpus_update - Update the isolated_cpus mask * @old_prs: old partition_root_state * @new_prs: new partition_root_state * @xcpus: exclusive CPUs with state change */ -static void partition_xcpus_newstate(int old_prs, int new_prs, struct cpumask *xcpus) +static void isolated_cpus_update(int old_prs, int new_prs, struct cpumask *xcpus) { WARN_ON_ONCE(old_prs == new_prs); if (new_prs == PRS_ISOLATED) @@ -1273,8 +1284,8 @@ static bool partition_xcpus_add(int new_prs, struct cpuset *parent, isolcpus_updated = (new_prs != parent->partition_root_state); if (isolcpus_updated) - partition_xcpus_newstate(parent->partition_root_state, new_prs, - xcpus); + isolated_cpus_update(parent->partition_root_state, new_prs, + xcpus); cpumask_andnot(parent->effective_cpus, parent->effective_cpus, xcpus); return isolcpus_updated; @@ -1304,8 +1315,8 @@ static bool partition_xcpus_del(int old_prs, struct cpuset *parent, isolcpus_updated = (old_prs != parent->partition_root_state); if (isolcpus_updated) - partition_xcpus_newstate(old_prs, parent->partition_root_state, - xcpus); + isolated_cpus_update(old_prs, parent->partition_root_state, + xcpus); cpumask_and(xcpus, xcpus, cpu_active_mask); cpumask_or(parent->effective_cpus, parent->effective_cpus, xcpus); @@ -1340,20 +1351,57 @@ EXPORT_SYMBOL_GPL(cpuset_cpu_is_isolated); * compute_effective_exclusive_cpumask - compute effective exclusive CPUs * @cs: cpuset * @xcpus: effective exclusive CPUs value to be set - * Return: true if xcpus is not empty, false otherwise. + * @real_cs: the real cpuset (can be NULL) + * Return: 0 if there is no sibling conflict, > 0 otherwise * - * Starting with exclusive_cpus (cpus_allowed if exclusive_cpus is not set), - * it must be a subset of parent's effective_xcpus. + * If exclusive_cpus isn't explicitly set or a real_cs is provided, we have to + * scan the sibling cpusets and exclude their exclusive_cpus or effective_xcpus + * as well. The provision of real_cs means that a cpumask is being changed and + * the given cs is a trial one. */ -static bool compute_effective_exclusive_cpumask(struct cpuset *cs, - struct cpumask *xcpus) +static int compute_effective_exclusive_cpumask(struct cpuset *cs, + struct cpumask *xcpus, + struct cpuset *real_cs) { + struct cgroup_subsys_state *css; struct cpuset *parent = parent_cs(cs); + struct cpuset *sibling; + int retval = 0; if (!xcpus) xcpus = cs->effective_xcpus; - return cpumask_and(xcpus, user_xcpus(cs), parent->effective_xcpus); + cpumask_and(xcpus, user_xcpus(cs), parent->effective_xcpus); + + if (!real_cs) { + if (!cpumask_empty(cs->exclusive_cpus)) + return 0; + } else { + cs = real_cs; + } + + /* + * Exclude exclusive CPUs from siblings + */ + rcu_read_lock(); + cpuset_for_each_child(sibling, css, parent) { + if (sibling == cs) + continue; + + if (!cpumask_empty(sibling->exclusive_cpus) && + cpumask_intersects(xcpus, sibling->exclusive_cpus)) { + cpumask_andnot(xcpus, xcpus, sibling->exclusive_cpus); + retval++; + continue; + } + if (!cpumask_empty(sibling->effective_xcpus) && + cpumask_intersects(xcpus, sibling->effective_xcpus)) { + cpumask_andnot(xcpus, xcpus, sibling->effective_xcpus); + retval++; + } + } + rcu_read_unlock(); + return retval; } static inline bool is_remote_partition(struct cpuset *cs) @@ -1395,7 +1443,7 @@ static int remote_partition_enable(struct cpuset *cs, int new_prs, * remote partition root underneath it, its exclusive_cpus must * have overlapped with subpartitions_cpus. */ - compute_effective_exclusive_cpumask(cs, tmp->new_cpus); + compute_effective_exclusive_cpumask(cs, tmp->new_cpus, NULL); if (cpumask_empty(tmp->new_cpus) || cpumask_intersects(tmp->new_cpus, subpartitions_cpus) || cpumask_subset(top_cpuset.effective_cpus, tmp->new_cpus)) @@ -1404,8 +1452,11 @@ static int remote_partition_enable(struct cpuset *cs, int new_prs, spin_lock_irq(&callback_lock); isolcpus_updated = partition_xcpus_add(new_prs, NULL, tmp->new_cpus); list_add(&cs->remote_sibling, &remote_children); + cpumask_copy(cs->effective_xcpus, tmp->new_cpus); spin_unlock_irq(&callback_lock); update_unbound_workqueue_cpumask(isolcpus_updated); + cpuset_force_rebuild(); + cs->prs_err = 0; /* * Propagate changes in top_cpuset's effective_cpus down the hierarchy. @@ -1428,20 +1479,24 @@ static void remote_partition_disable(struct cpuset *cs, struct tmpmasks *tmp) { bool isolcpus_updated; - compute_effective_exclusive_cpumask(cs, tmp->new_cpus); WARN_ON_ONCE(!is_remote_partition(cs)); - WARN_ON_ONCE(!cpumask_subset(tmp->new_cpus, subpartitions_cpus)); + WARN_ON_ONCE(!cpumask_subset(cs->effective_xcpus, subpartitions_cpus)); spin_lock_irq(&callback_lock); list_del_init(&cs->remote_sibling); isolcpus_updated = partition_xcpus_del(cs->partition_root_state, - NULL, tmp->new_cpus); - cs->partition_root_state = -cs->partition_root_state; - if (!cs->prs_err) - cs->prs_err = PERR_INVCPUS; + NULL, cs->effective_xcpus); + if (cs->prs_err) + cs->partition_root_state = -cs->partition_root_state; + else + cs->partition_root_state = PRS_MEMBER; + + /* effective_xcpus may need to be changed */ + compute_effective_exclusive_cpumask(cs, NULL, NULL); reset_partition_data(cs); spin_unlock_irq(&callback_lock); update_unbound_workqueue_cpumask(isolcpus_updated); + cpuset_force_rebuild(); /* * Propagate changes in top_cpuset's effective_cpus down the hierarchy. @@ -1453,14 +1508,15 @@ static void remote_partition_disable(struct cpuset *cs, struct tmpmasks *tmp) /* * remote_cpus_update - cpus_exclusive change of remote partition * @cs: the cpuset to be updated - * @newmask: the new effective_xcpus mask + * @xcpus: the new exclusive_cpus mask, if non-NULL + * @excpus: the new effective_xcpus mask * @tmp: temporary masks * * top_cpuset and subpartitions_cpus will be updated or partition can be * invalidated. */ -static void remote_cpus_update(struct cpuset *cs, struct cpumask *newmask, - struct tmpmasks *tmp) +static void remote_cpus_update(struct cpuset *cs, struct cpumask *xcpus, + struct cpumask *excpus, struct tmpmasks *tmp) { bool adding, deleting; int prs = cs->partition_root_state; @@ -1471,29 +1527,45 @@ static void remote_cpus_update(struct cpuset *cs, struct cpumask *newmask, WARN_ON_ONCE(!cpumask_subset(cs->effective_xcpus, subpartitions_cpus)); - if (cpumask_empty(newmask)) + if (cpumask_empty(excpus)) { + cs->prs_err = PERR_CPUSEMPTY; goto invalidate; + } - adding = cpumask_andnot(tmp->addmask, newmask, cs->effective_xcpus); - deleting = cpumask_andnot(tmp->delmask, cs->effective_xcpus, newmask); + adding = cpumask_andnot(tmp->addmask, excpus, cs->effective_xcpus); + deleting = cpumask_andnot(tmp->delmask, cs->effective_xcpus, excpus); /* * Additions of remote CPUs is only allowed if those CPUs are * not allocated to other partitions and there are effective_cpus * left in the top cpuset. */ - if (adding && (!capable(CAP_SYS_ADMIN) || - cpumask_intersects(tmp->addmask, subpartitions_cpus) || - cpumask_subset(top_cpuset.effective_cpus, tmp->addmask))) - goto invalidate; + if (adding) { + if (!capable(CAP_SYS_ADMIN)) + cs->prs_err = PERR_ACCESS; + else if (cpumask_intersects(tmp->addmask, subpartitions_cpus) || + cpumask_subset(top_cpuset.effective_cpus, tmp->addmask)) + cs->prs_err = PERR_NOCPUS; + if (cs->prs_err) + goto invalidate; + } spin_lock_irq(&callback_lock); if (adding) isolcpus_updated += partition_xcpus_add(prs, NULL, tmp->addmask); if (deleting) isolcpus_updated += partition_xcpus_del(prs, NULL, tmp->delmask); + /* + * Need to update effective_xcpus and exclusive_cpus now as + * update_sibling_cpumasks() below may iterate back to the same cs. + */ + cpumask_copy(cs->effective_xcpus, excpus); + if (xcpus) + cpumask_copy(cs->exclusive_cpus, xcpus); spin_unlock_irq(&callback_lock); update_unbound_workqueue_cpumask(isolcpus_updated); + if (adding || deleting) + cpuset_force_rebuild(); /* * Propagate changes in top_cpuset's effective_cpus down the hierarchy. @@ -1507,47 +1579,6 @@ static void remote_cpus_update(struct cpuset *cs, struct cpumask *newmask, } /* - * remote_partition_check - check if a child remote partition needs update - * @cs: the cpuset to be updated - * @newmask: the new effective_xcpus mask - * @delmask: temporary mask for deletion (not in tmp) - * @tmp: temporary masks - * - * This should be called before the given cs has updated its cpus_allowed - * and/or effective_xcpus. - */ -static void remote_partition_check(struct cpuset *cs, struct cpumask *newmask, - struct cpumask *delmask, struct tmpmasks *tmp) -{ - struct cpuset *child, *next; - int disable_cnt = 0; - - /* - * Compute the effective exclusive CPUs that will be deleted. - */ - if (!cpumask_andnot(delmask, cs->effective_xcpus, newmask) || - !cpumask_intersects(delmask, subpartitions_cpus)) - return; /* No deletion of exclusive CPUs in partitions */ - - /* - * Searching the remote children list to look for those that will - * be impacted by the deletion of exclusive CPUs. - * - * Since a cpuset must be removed from the remote children list - * before it can go offline and holding cpuset_mutex will prevent - * any change in cpuset status. RCU read lock isn't needed. - */ - lockdep_assert_held(&cpuset_mutex); - list_for_each_entry_safe(child, next, &remote_children, remote_sibling) - if (cpumask_intersects(child->effective_cpus, delmask)) { - remote_partition_disable(child, tmp); - disable_cnt++; - } - if (disable_cnt) - cpuset_force_rebuild(); -} - -/* * prstate_housekeeping_conflict - check for partition & housekeeping conflicts * @prstate: partition root state to be checked * @new_cpus: cpu mask @@ -1601,7 +1632,7 @@ static bool prstate_housekeeping_conflict(int prstate, struct cpumask *new_cpus) * The partcmd_update command is used by update_cpumasks_hier() with newmask * NULL and update_cpumask() with newmask set. The partcmd_invalidate is used * by update_cpumask() with NULL newmask. In both cases, the callers won't - * check for error and so partition_root_state and prs_error will be updated + * check for error and so partition_root_state and prs_err will be updated * directly. */ static int update_parent_effective_cpumask(struct cpuset *cs, int cmd, @@ -1614,11 +1645,12 @@ static int update_parent_effective_cpumask(struct cpuset *cs, int cmd, int old_prs, new_prs; int part_error = PERR_NONE; /* Partition error? */ int subparts_delta = 0; - struct cpumask *xcpus; /* cs effective_xcpus */ int isolcpus_updated = 0; + struct cpumask *xcpus = user_xcpus(cs); bool nocpu; lockdep_assert_held(&cpuset_mutex); + WARN_ON_ONCE(is_remote_partition(cs)); /* * new_prs will only be changed for the partcmd_update and @@ -1626,7 +1658,6 @@ static int update_parent_effective_cpumask(struct cpuset *cs, int cmd, */ adding = deleting = false; old_prs = new_prs = cs->partition_root_state; - xcpus = user_xcpus(cs); if (cmd == partcmd_invalidate) { if (is_prs_invalid(old_prs)) @@ -1661,12 +1692,19 @@ static int update_parent_effective_cpumask(struct cpuset *cs, int cmd, if ((cmd == partcmd_enable) || (cmd == partcmd_enablei)) { /* - * Enabling partition root is not allowed if its - * effective_xcpus is empty or doesn't overlap with - * parent's effective_xcpus. + * Need to call compute_effective_exclusive_cpumask() in case + * exclusive_cpus not set. Sibling conflict should only happen + * if exclusive_cpus isn't set. */ - if (cpumask_empty(xcpus) || - !cpumask_intersects(xcpus, parent->effective_xcpus)) + xcpus = tmp->new_cpus; + if (compute_effective_exclusive_cpumask(cs, xcpus, NULL)) + WARN_ON_ONCE(!cpumask_empty(cs->exclusive_cpus)); + + /* + * Enabling partition root is not allowed if its + * effective_xcpus is empty. + */ + if (cpumask_empty(xcpus)) return PERR_INVCPUS; if (prstate_housekeeping_conflict(new_prs, xcpus)) @@ -1679,19 +1717,22 @@ static int update_parent_effective_cpumask(struct cpuset *cs, int cmd, if (nocpu) return PERR_NOCPUS; - cpumask_copy(tmp->delmask, xcpus); - deleting = true; - subparts_delta++; + deleting = cpumask_and(tmp->delmask, xcpus, parent->effective_xcpus); + if (deleting) + subparts_delta++; new_prs = (cmd == partcmd_enable) ? PRS_ROOT : PRS_ISOLATED; } else if (cmd == partcmd_disable) { /* - * May need to add cpus to parent's effective_cpus for - * valid partition root. + * May need to add cpus back to parent's effective_cpus + * (and maybe removed from subpartitions_cpus/isolated_cpus) + * for valid partition root. xcpus may contain CPUs that + * shouldn't be removed from the two global cpumasks. */ - adding = !is_prs_invalid(old_prs) && - cpumask_and(tmp->addmask, xcpus, parent->effective_xcpus); - if (adding) + if (is_partition_valid(cs)) { + cpumask_copy(tmp->addmask, cs->effective_xcpus); + adding = true; subparts_delta--; + } new_prs = PRS_MEMBER; } else if (newmask) { /* @@ -1701,6 +1742,7 @@ static int update_parent_effective_cpumask(struct cpuset *cs, int cmd, part_error = PERR_CPUSEMPTY; goto write_error; } + /* Check newmask again, whether cpus are available for parent/cs */ nocpu |= tasks_nocpu_error(parent, cs, newmask); @@ -1829,7 +1871,7 @@ static int update_parent_effective_cpumask(struct cpuset *cs, int cmd, * CPU lists in cs haven't been updated yet. So defer it to later. */ if ((old_prs != new_prs) && (cmd != partcmd_update)) { - int err = update_partition_exclusive(cs, new_prs); + int err = update_partition_exclusive_flag(cs, new_prs); if (err) return err; @@ -1867,7 +1909,7 @@ static int update_parent_effective_cpumask(struct cpuset *cs, int cmd, update_unbound_workqueue_cpumask(isolcpus_updated); if ((old_prs != new_prs) && (cmd == partcmd_update)) - update_partition_exclusive(cs, new_prs); + update_partition_exclusive_flag(cs, new_prs); if (adding || deleting) { cpuset_update_tasks_cpumask(parent, tmp->addmask); @@ -1917,7 +1959,7 @@ static void compute_partition_effective_cpumask(struct cpuset *cs, * 2) All the effective_cpus will be used up and cp * has tasks */ - compute_effective_exclusive_cpumask(cs, new_ecpus); + compute_effective_exclusive_cpumask(cs, new_ecpus, NULL); cpumask_and(new_ecpus, new_ecpus, cpu_active_mask); rcu_read_lock(); @@ -1925,6 +1967,11 @@ static void compute_partition_effective_cpumask(struct cpuset *cs, if (!is_partition_valid(child)) continue; + /* + * There shouldn't be a remote partition underneath another + * partition root. + */ + WARN_ON_ONCE(is_remote_partition(child)); child->prs_err = 0; if (!cpumask_subset(child->effective_xcpus, cs->effective_xcpus)) @@ -1980,32 +2027,39 @@ static void update_cpumasks_hier(struct cpuset *cs, struct tmpmasks *tmp, bool remote = is_remote_partition(cp); bool update_parent = false; + old_prs = new_prs = cp->partition_root_state; + /* - * Skip descendent remote partition that acquires CPUs - * directly from top cpuset unless it is cs. + * For child remote partition root (!= cs), we need to call + * remote_cpus_update() if effective_xcpus will be changed. + * Otherwise, we can skip the whole subtree. + * + * remote_cpus_update() will reuse tmp->new_cpus only after + * its value is being processed. */ if (remote && (cp != cs)) { - pos_css = css_rightmost_descendant(pos_css); - continue; + compute_effective_exclusive_cpumask(cp, tmp->new_cpus, NULL); + if (cpumask_equal(cp->effective_xcpus, tmp->new_cpus)) { + pos_css = css_rightmost_descendant(pos_css); + continue; + } + rcu_read_unlock(); + remote_cpus_update(cp, NULL, tmp->new_cpus, tmp); + rcu_read_lock(); + + /* Remote partition may be invalidated */ + new_prs = cp->partition_root_state; + remote = (new_prs == old_prs); } - /* - * Update effective_xcpus if exclusive_cpus set. - * The case when exclusive_cpus isn't set is handled later. - */ - if (!cpumask_empty(cp->exclusive_cpus) && (cp != cs)) { - spin_lock_irq(&callback_lock); - compute_effective_exclusive_cpumask(cp, NULL); - spin_unlock_irq(&callback_lock); - } - - old_prs = new_prs = cp->partition_root_state; - if (remote || (is_partition_valid(parent) && - is_partition_valid(cp))) + if (remote || (is_partition_valid(parent) && is_partition_valid(cp))) compute_partition_effective_cpumask(cp, tmp->new_cpus); else compute_effective_cpumask(tmp->new_cpus, cp, parent); + if (remote) + goto get_css; /* Ready to update cpuset data */ + /* * A partition with no effective_cpus is allowed as long as * there is no task associated with it. Call @@ -2025,9 +2079,6 @@ static void update_cpumasks_hier(struct cpuset *cs, struct tmpmasks *tmp, if (is_in_v2_mode() && !remote && cpumask_empty(tmp->new_cpus)) cpumask_copy(tmp->new_cpus, parent->effective_cpus); - if (remote) - goto get_css; - /* * Skip the whole subtree if * 1) the cpumask remains the same, @@ -2088,6 +2139,9 @@ static void update_cpumasks_hier(struct cpuset *cs, struct tmpmasks *tmp, spin_lock_irq(&callback_lock); cpumask_copy(cp->effective_cpus, tmp->new_cpus); cp->partition_root_state = new_prs; + if (!cpumask_empty(cp->exclusive_cpus) && (cp != cs)) + compute_effective_exclusive_cpumask(cp, NULL, NULL); + /* * Make sure effective_xcpus is properly set for a valid * partition root. @@ -2174,7 +2228,14 @@ static void update_sibling_cpumasks(struct cpuset *parent, struct cpuset *cs, parent); if (cpumask_equal(tmp->new_cpus, sibling->effective_cpus)) continue; + } else if (is_remote_partition(sibling)) { + /* + * Change in a sibling cpuset won't affect a remote + * partition root. + */ + continue; } + if (!css_tryget_online(&sibling->css)) continue; @@ -2231,8 +2292,9 @@ static int update_cpumask(struct cpuset *cs, struct cpuset *trialcs, * trialcs->effective_xcpus is used as a temporary cpumask * for checking validity of the partition root. */ + trialcs->partition_root_state = PRS_MEMBER; if (!cpumask_empty(trialcs->exclusive_cpus) || is_partition_valid(cs)) - compute_effective_exclusive_cpumask(trialcs, NULL); + compute_effective_exclusive_cpumask(trialcs, NULL, cs); } /* Nothing to do if the cpus didn't change */ @@ -2305,19 +2367,13 @@ static int update_cpumask(struct cpuset *cs, struct cpuset *trialcs, * Call remote_cpus_update() to handle valid remote partition */ if (is_remote_partition(cs)) - remote_cpus_update(cs, xcpus, &tmp); + remote_cpus_update(cs, NULL, xcpus, &tmp); else if (invalidate) update_parent_effective_cpumask(cs, partcmd_invalidate, NULL, &tmp); else update_parent_effective_cpumask(cs, partcmd_update, xcpus, &tmp); - } else if (!cpumask_empty(cs->exclusive_cpus)) { - /* - * Use trialcs->effective_cpus as a temp cpumask - */ - remote_partition_check(cs, trialcs->effective_xcpus, - trialcs->effective_cpus, &tmp); } spin_lock_irq(&callback_lock); @@ -2369,8 +2425,15 @@ static int update_exclusive_cpumask(struct cpuset *cs, struct cpuset *trialcs, if (cpumask_equal(cs->exclusive_cpus, trialcs->exclusive_cpus)) return 0; - if (*buf) - compute_effective_exclusive_cpumask(trialcs, NULL); + if (*buf) { + trialcs->partition_root_state = PRS_MEMBER; + /* + * Reject the change if there is exclusive CPUs conflict with + * the siblings. + */ + if (compute_effective_exclusive_cpumask(trialcs, NULL, cs)) + return -EINVAL; + } /* * Check all the descendants in update_cpumasks_hier() if @@ -2401,8 +2464,8 @@ static int update_exclusive_cpumask(struct cpuset *cs, struct cpuset *trialcs, if (invalidate) remote_partition_disable(cs, &tmp); else - remote_cpus_update(cs, trialcs->effective_xcpus, - &tmp); + remote_cpus_update(cs, trialcs->exclusive_cpus, + trialcs->effective_xcpus, &tmp); } else if (invalidate) { update_parent_effective_cpumask(cs, partcmd_invalidate, NULL, &tmp); @@ -2410,12 +2473,6 @@ static int update_exclusive_cpumask(struct cpuset *cs, struct cpuset *trialcs, update_parent_effective_cpumask(cs, partcmd_update, trialcs->effective_xcpus, &tmp); } - } else if (!cpumask_empty(trialcs->exclusive_cpus)) { - /* - * Use trialcs->effective_cpus as a temp cpumask - */ - remote_partition_check(cs, trialcs->effective_xcpus, - trialcs->effective_cpus, &tmp); } spin_lock_irq(&callback_lock); cpumask_copy(cs->exclusive_cpus, trialcs->exclusive_cpus); @@ -2782,7 +2839,7 @@ static int update_prstate(struct cpuset *cs, int new_prs) int err = PERR_NONE, old_prs = cs->partition_root_state; struct cpuset *parent = parent_cs(cs); struct tmpmasks tmpmask; - bool new_xcpus_state = false; + bool isolcpus_updated = false; if (old_prs == new_prs) return 0; @@ -2796,18 +2853,7 @@ static int update_prstate(struct cpuset *cs, int new_prs) if (alloc_cpumasks(NULL, &tmpmask)) return -ENOMEM; - /* - * Setup effective_xcpus if not properly set yet, it will be cleared - * later if partition becomes invalid. - */ - if ((new_prs > 0) && cpumask_empty(cs->exclusive_cpus)) { - spin_lock_irq(&callback_lock); - cpumask_and(cs->effective_xcpus, - cs->cpus_allowed, parent->effective_xcpus); - spin_unlock_irq(&callback_lock); - } - - err = update_partition_exclusive(cs, new_prs); + err = update_partition_exclusive_flag(cs, new_prs); if (err) goto out; @@ -2821,6 +2867,19 @@ static int update_prstate(struct cpuset *cs, int new_prs) } /* + * We don't support the creation of a new local partition with + * a remote partition underneath it. This unsupported + * setting can happen only if parent is the top_cpuset because + * a remote partition cannot be created underneath an existing + * local or remote partition. + */ + if ((parent == &top_cpuset) && + cpumask_intersects(cs->exclusive_cpus, subpartitions_cpus)) { + err = PERR_REMOTE; + goto out; + } + + /* * If parent is valid partition, enable local partiion. * Otherwise, enable a remote partition. */ @@ -2835,8 +2894,9 @@ static int update_prstate(struct cpuset *cs, int new_prs) } else if (old_prs && new_prs) { /* * A change in load balance state only, no change in cpumasks. + * Need to update isolated_cpus. */ - new_xcpus_state = true; + isolcpus_updated = true; } else { /* * Switching back to member is always allowed even if it @@ -2860,7 +2920,7 @@ static int update_prstate(struct cpuset *cs, int new_prs) */ if (err) { new_prs = -new_prs; - update_partition_exclusive(cs, new_prs); + update_partition_exclusive_flag(cs, new_prs); } spin_lock_irq(&callback_lock); @@ -2868,14 +2928,18 @@ static int update_prstate(struct cpuset *cs, int new_prs) WRITE_ONCE(cs->prs_err, err); if (!is_partition_valid(cs)) reset_partition_data(cs); - else if (new_xcpus_state) - partition_xcpus_newstate(old_prs, new_prs, cs->effective_xcpus); + else if (isolcpus_updated) + isolated_cpus_update(old_prs, new_prs, cs->effective_xcpus); spin_unlock_irq(&callback_lock); - update_unbound_workqueue_cpumask(new_xcpus_state); + update_unbound_workqueue_cpumask(isolcpus_updated); - /* Force update if switching back to member */ + /* Force update if switching back to member & update effective_xcpus */ update_cpumasks_hier(cs, &tmpmask, !new_prs); + /* A newly created partition must have effective_xcpus set */ + WARN_ON_ONCE(!old_prs && (new_prs > 0) + && cpumask_empty(cs->effective_xcpus)); + /* Update sched domains and load balance flag */ update_partition_sd_lb(cs, old_prs); @@ -3208,7 +3272,7 @@ int cpuset_common_seq_show(struct seq_file *sf, void *v) return ret; } -static int sched_partition_show(struct seq_file *seq, void *v) +static int cpuset_partition_show(struct seq_file *seq, void *v) { struct cpuset *cs = css_cs(seq_css(seq)); const char *err, *type = NULL; @@ -3239,7 +3303,7 @@ static int sched_partition_show(struct seq_file *seq, void *v) return 0; } -static ssize_t sched_partition_write(struct kernfs_open_file *of, char *buf, +static ssize_t cpuset_partition_write(struct kernfs_open_file *of, char *buf, size_t nbytes, loff_t off) { struct cpuset *cs = css_cs(of_css(of)); @@ -3260,11 +3324,8 @@ static ssize_t sched_partition_write(struct kernfs_open_file *of, char *buf, css_get(&cs->css); cpus_read_lock(); mutex_lock(&cpuset_mutex); - if (!is_cpuset_online(cs)) - goto out_unlock; - - retval = update_prstate(cs, val); -out_unlock: + if (is_cpuset_online(cs)) + retval = update_prstate(cs, val); mutex_unlock(&cpuset_mutex); cpus_read_unlock(); css_put(&cs->css); @@ -3308,8 +3369,8 @@ static struct cftype dfl_files[] = { { .name = "cpus.partition", - .seq_show = sched_partition_show, - .write = sched_partition_write, + .seq_show = cpuset_partition_show, + .write = cpuset_partition_write, .private = FILE_PARTITION_ROOT, .flags = CFTYPE_NOT_ON_ROOT, .file_offset = offsetof(struct cpuset, partition_file), @@ -3475,9 +3536,6 @@ static void cpuset_css_offline(struct cgroup_subsys_state *css) cpus_read_lock(); mutex_lock(&cpuset_mutex); - if (is_partition_valid(cs)) - update_prstate(cs, 0); - if (!cpuset_v2() && is_sched_load_balance(cs)) cpuset_update_flag(CS_SCHED_LOAD_BALANCE, cs, 0); @@ -3488,6 +3546,22 @@ static void cpuset_css_offline(struct cgroup_subsys_state *css) cpus_read_unlock(); } +static void cpuset_css_killed(struct cgroup_subsys_state *css) +{ + struct cpuset *cs = css_cs(css); + + cpus_read_lock(); + mutex_lock(&cpuset_mutex); + + /* Reset valid partition back to member */ + if (is_partition_valid(cs)) + update_prstate(cs, PRS_MEMBER); + + mutex_unlock(&cpuset_mutex); + cpus_read_unlock(); + +} + static void cpuset_css_free(struct cgroup_subsys_state *css) { struct cpuset *cs = css_cs(css); @@ -3609,6 +3683,7 @@ struct cgroup_subsys cpuset_cgrp_subsys = { .css_alloc = cpuset_css_alloc, .css_online = cpuset_css_online, .css_offline = cpuset_css_offline, + .css_killed = cpuset_css_killed, .css_free = cpuset_css_free, .can_attach = cpuset_can_attach, .cancel_attach = cpuset_cancel_attach, @@ -3739,10 +3814,10 @@ static void cpuset_hotplug_update_tasks(struct cpuset *cs, struct tmpmasks *tmp) if (remote && cpumask_empty(&new_cpus) && partition_is_populated(cs, NULL)) { + cs->prs_err = PERR_HOTPLUG; remote_partition_disable(cs, tmp); compute_effective_cpumask(&new_cpus, cs, parent); remote = false; - cpuset_force_rebuild(); } /*
diff --git a/kernel/cgroup/rstat.c b/kernel/cgroup/rstat.c index 4bb587d..b223915 100644 --- a/kernel/cgroup/rstat.c +++ b/kernel/cgroup/rstat.c
@@ -318,10 +318,11 @@ __bpf_kfunc void cgroup_rstat_flush(struct cgroup *cgrp) might_sleep(); for_each_possible_cpu(cpu) { - struct cgroup *pos = cgroup_rstat_updated_list(cgrp, cpu); + struct cgroup *pos; /* Reacquire for each CPU to avoid disabling IRQs too long */ __cgroup_rstat_lock(cgrp, cpu); + pos = cgroup_rstat_updated_list(cgrp, cpu); for (; pos; pos = pos->rstat_flush_next) { struct cgroup_subsys_state *css;
diff --git a/kernel/debug/debug_core.c b/kernel/debug/debug_core.c index ce1bb23..0b94951 100644 --- a/kernel/debug/debug_core.c +++ b/kernel/debug/debug_core.c
@@ -837,10 +837,6 @@ kgdb_handle_exception(int evector, int signo, int ecode, struct pt_regs *regs) { struct kgdb_state kgdb_var; struct kgdb_state *ks = &kgdb_var; - int ret = 0; - - if (arch_kgdb_ops.enable_nmi) - arch_kgdb_ops.enable_nmi(0); /* * Avoid entering the debugger if we were triggered due to an oops * but panic_timeout indicates the system should automatically @@ -858,15 +854,11 @@ kgdb_handle_exception(int evector, int signo, int ecode, struct pt_regs *regs) ks->linux_regs = regs; if (kgdb_reenter_check(ks)) - goto out; /* Ouch, double exception ! */ + return 0; /* Ouch, double exception ! */ if (kgdb_info[ks->cpu].enter_kgdb != 0) - goto out; + return 0; - ret = kgdb_cpu_enter(ks, regs, DCPU_WANT_MASTER); -out: - if (arch_kgdb_ops.enable_nmi) - arch_kgdb_ops.enable_nmi(1); - return ret; + return kgdb_cpu_enter(ks, regs, DCPU_WANT_MASTER); } NOKPROBE_SYMBOL(kgdb_handle_exception);
diff --git a/kernel/debug/kdb/kdb_io.c b/kernel/debug/kdb/kdb_io.c index 6a77f1c..9b11b10 100644 --- a/kernel/debug/kdb/kdb_io.c +++ b/kernel/debug/kdb/kdb_io.c
@@ -334,7 +334,7 @@ static char *kdb_read(char *buffer, size_t bufsize) *cp = '\0'; p_tmp = strrchr(buffer, ' '); p_tmp = (p_tmp ? p_tmp + 1 : buffer); - strscpy(tmpbuffer, p_tmp, sizeof(tmpbuffer)); + strscpy(tmpbuffer, p_tmp); *cp = tmp; len = strlen(tmpbuffer); @@ -452,7 +452,7 @@ static char *kdb_read(char *buffer, size_t bufsize) char *kdb_getstr(char *buffer, size_t bufsize, const char *prompt) { if (prompt && kdb_prompt_str != prompt) - strscpy(kdb_prompt_str, prompt, CMD_BUFLEN); + strscpy(kdb_prompt_str, prompt); kdb_printf("%s", kdb_prompt_str); kdb_nextline = 1; /* Prompt and input resets line number */ return kdb_read(buffer, bufsize);
diff --git a/kernel/debug/kdb/kdb_main.c b/kernel/debug/kdb/kdb_main.c index 5f4be50..7a4d2d4 100644 --- a/kernel/debug/kdb/kdb_main.c +++ b/kernel/debug/kdb/kdb_main.c
@@ -25,7 +25,6 @@ #include <linux/smp.h> #include <linux/utsname.h> #include <linux/vmalloc.h> -#include <linux/atomic.h> #include <linux/moduleparam.h> #include <linux/mm.h> #include <linux/init.h> @@ -105,7 +104,7 @@ static kdbmsg_t kdbmsgs[] = { KDBMSG(NOENVVALUE, "Environment variable should have value"), KDBMSG(NOTIMP, "Command not implemented"), KDBMSG(ENVFULL, "Environment full"), - KDBMSG(ENVBUFFULL, "Environment buffer full"), + KDBMSG(KMALLOCFAILED, "Failed to allocate memory"), KDBMSG(TOOMANYBPT, "Too many breakpoints defined"), #ifdef CONFIG_CPU_XSCALE KDBMSG(TOOMANYDBREGS, "More breakpoints than ibcr registers defined"), @@ -130,13 +129,9 @@ static const int __nkdb_err = ARRAY_SIZE(kdbmsgs); /* - * Initial environment. This is all kept static and local to - * this file. We don't want to rely on the memory allocation - * mechanisms in the kernel, so we use a very limited allocate-only - * heap for new and altered environment variables. The entire - * environment is limited to a fixed number of entries (add more - * to __env[] if required) and a fixed amount of heap (add more to - * KDB_ENVBUFSIZE if required). + * Initial environment. This is all kept static and local to this file. + * The entire environment is limited to a fixed number of entries + * (add more to __env[] if required) */ static char *__env[31] = { @@ -259,35 +254,6 @@ char *kdbgetenv(const char *match) } /* - * kdballocenv - This function is used to allocate bytes for - * environment entries. - * Parameters: - * bytes The number of bytes to allocate in the static buffer. - * Returns: - * A pointer to the allocated space in the buffer on success. - * NULL if bytes > size available in the envbuffer. - * Remarks: - * We use a static environment buffer (envbuffer) to hold the values - * of dynamically generated environment variables (see kdb_set). Buffer - * space once allocated is never free'd, so over time, the amount of space - * (currently 512 bytes) will be exhausted if env variables are changed - * frequently. - */ -static char *kdballocenv(size_t bytes) -{ -#define KDB_ENVBUFSIZE 512 - static char envbuffer[KDB_ENVBUFSIZE]; - static int envbufsize; - char *ep = NULL; - - if ((KDB_ENVBUFSIZE - envbufsize) >= bytes) { - ep = &envbuffer[envbufsize]; - envbufsize += bytes; - } - return ep; -} - -/* * kdbgetulenv - This function will return the value of an unsigned * long-valued environment variable. * Parameters: @@ -348,9 +314,9 @@ static int kdb_setenv(const char *var, const char *val) varlen = strlen(var); vallen = strlen(val); - ep = kdballocenv(varlen + vallen + 2); - if (ep == (char *)0) - return KDB_ENVBUFFULL; + ep = kmalloc(varlen + vallen + 2, GFP_KDB); + if (!ep) + return KDB_KMALLOCFAILED; sprintf(ep, "%s=%s", var, val); @@ -359,6 +325,7 @@ static int kdb_setenv(const char *var, const char *val) && ((strncmp(__env[i], var, varlen) == 0) && ((__env[i][varlen] == '\0') || (__env[i][varlen] == '=')))) { + kfree_const(__env[i]); __env[i] = ep; return 0; } @@ -2119,32 +2086,6 @@ static int kdb_dmesg(int argc, const char **argv) return 0; } #endif /* CONFIG_PRINTK */ - -/* Make sure we balance enable/disable calls, must disable first. */ -static atomic_t kdb_nmi_disabled; - -static int kdb_disable_nmi(int argc, const char *argv[]) -{ - if (atomic_read(&kdb_nmi_disabled)) - return 0; - atomic_set(&kdb_nmi_disabled, 1); - arch_kgdb_ops.enable_nmi(0); - return 0; -} - -static int kdb_param_enable_nmi(const char *val, const struct kernel_param *kp) -{ - if (!atomic_add_unless(&kdb_nmi_disabled, -1, 0)) - return -EINVAL; - arch_kgdb_ops.enable_nmi(1); - return 0; -} - -static const struct kernel_param_ops kdb_param_ops_enable_nmi = { - .set = kdb_param_enable_nmi, -}; -module_param_cb(enable_nmi, &kdb_param_ops_enable_nmi, NULL, 0600); - /* * kdb_cpu - This function implements the 'cpu' command. * cpu [<cpunum>] @@ -2836,20 +2777,10 @@ static kdbtab_t maintab[] = { }, }; -static kdbtab_t nmicmd = { - .name = "disable_nmi", - .func = kdb_disable_nmi, - .usage = "", - .help = "Disable NMI entry to KDB", - .flags = KDB_ENABLE_ALWAYS_SAFE, -}; - /* Initialize the kdb command table. */ static void __init kdb_inittab(void) { kdb_register_table(maintab, ARRAY_SIZE(maintab)); - if (arch_kgdb_ops.enable_nmi) - kdb_register_table(&nmicmd, 1); } /* Execute any commands defined in kdb_cmds. */
diff --git a/kernel/events/core.c b/kernel/events/core.c index 0bb2165..128db74 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c
@@ -2451,6 +2451,7 @@ ctx_time_update_event(struct perf_event_context *ctx, struct perf_event *event) #define DETACH_GROUP 0x01UL #define DETACH_CHILD 0x02UL #define DETACH_DEAD 0x04UL +#define DETACH_EXIT 0x08UL /* * Cross CPU call to remove a performance event @@ -2465,6 +2466,7 @@ __perf_remove_from_context(struct perf_event *event, void *info) { struct perf_event_pmu_context *pmu_ctx = event->pmu_ctx; + enum perf_event_state state = PERF_EVENT_STATE_OFF; unsigned long flags = (unsigned long)info; ctx_time_update(cpuctx, ctx); @@ -2473,16 +2475,19 @@ __perf_remove_from_context(struct perf_event *event, * Ensure event_sched_out() switches to OFF, at the very least * this avoids raising perf_pending_task() at this time. */ - if (flags & DETACH_DEAD) + if (flags & DETACH_EXIT) + state = PERF_EVENT_STATE_EXIT; + if (flags & DETACH_DEAD) { event->pending_disable = 1; + state = PERF_EVENT_STATE_DEAD; + } event_sched_out(event, ctx); + perf_event_set_state(event, min(event->state, state)); if (flags & DETACH_GROUP) perf_group_detach(event); if (flags & DETACH_CHILD) perf_child_detach(event); list_del_event(event, ctx); - if (flags & DETACH_DEAD) - event->state = PERF_EVENT_STATE_DEAD; if (!pmu_ctx->nr_events) { pmu_ctx->rotate_necessary = 0; @@ -13731,12 +13736,7 @@ perf_event_exit_event(struct perf_event *event, struct perf_event_context *ctx) mutex_lock(&parent_event->child_mutex); } - perf_remove_from_context(event, detach_flags); - - raw_spin_lock_irq(&ctx->lock); - if (event->state > PERF_EVENT_STATE_EXIT) - perf_event_set_state(event, PERF_EVENT_STATE_EXIT); - raw_spin_unlock_irq(&ctx->lock); + perf_remove_from_context(event, detach_flags | DETACH_EXIT); /* * Child events can be freed.
diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c index 2746791..615b4e6d 100644 --- a/kernel/events/uprobes.c +++ b/kernel/events/uprobes.c
@@ -1703,7 +1703,8 @@ static int xol_add_vma(struct mm_struct *mm, struct xol_area *area) } vma = _install_special_mapping(mm, area->vaddr, PAGE_SIZE, - VM_EXEC|VM_MAYEXEC|VM_DONTCOPY|VM_IO, + VM_EXEC|VM_MAYEXEC|VM_DONTCOPY|VM_IO| + VM_SEALED_SYSMAP, &xol_mapping); if (IS_ERR(vma)) { ret = PTR_ERR(vma);
diff --git a/kernel/exit.c b/kernel/exit.c index c2e6c7b..1b51dc0 100644 --- a/kernel/exit.c +++ b/kernel/exit.c
@@ -268,6 +268,9 @@ void release_task(struct task_struct *p) leader = p->group_leader; if (leader != p && thread_group_empty(leader) && leader->exit_state == EXIT_ZOMBIE) { + /* for pidfs_exit() and do_notify_parent() */ + if (leader->signal->flags & SIGNAL_GROUP_EXIT) + leader->exit_code = leader->signal->group_exit_code; /* * If we were the last child thread and the leader has * exited already, and the leader's parent ignores SIGCHLD, @@ -756,12 +759,6 @@ static void exit_notify(struct task_struct *tsk, int group_dead) kill_orphaned_pgrp(tsk->group_leader, NULL); tsk->exit_state = EXIT_ZOMBIE; - /* - * Ignore thread-group leaders that exited before all - * subthreads did. - */ - if (!delay_group_leader(tsk)) - do_notify_pidfd(tsk); if (unlikely(tsk->ptrace)) { int sig = thread_group_leader(tsk) && @@ -774,6 +771,8 @@ static void exit_notify(struct task_struct *tsk, int group_dead) do_notify_parent(tsk, tsk->exit_signal); } else { autoreap = true; + /* untraced sub-thread */ + do_notify_pidfd(tsk); } if (autoreap) {
diff --git a/kernel/gen_kheaders.sh b/kernel/gen_kheaders.sh index 00529c8..c9e5dc0 100755 --- a/kernel/gen_kheaders.sh +++ b/kernel/gen_kheaders.sh
@@ -89,7 +89,6 @@ # Create archive and try to normalize metadata for reproducibility. tar "${KBUILD_BUILD_TIMESTAMP:+--mtime=$KBUILD_BUILD_TIMESTAMP}" \ - --exclude=".__afs*" --exclude=".nfs*" \ --owner=0 --group=0 --sort=name --numeric-owner --mode=u=rw,go=r,a+X \ -I $XZ -cf $tarfile -C "${tmpdir}/" . > /dev/null
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c index 2861f89..9d5c865 100644 --- a/kernel/irq/irqdomain.c +++ b/kernel/irq/irqdomain.c
@@ -398,7 +398,7 @@ void irq_domain_remove(struct irq_domain *domain) * If the going away domain is the default one, reset it. */ if (unlikely(irq_default_domain == domain)) - irq_set_default_host(NULL); + irq_set_default_domain(NULL); mutex_unlock(&irq_domain_mutex); @@ -573,7 +573,7 @@ struct irq_domain *irq_find_matching_fwspec(struct irq_fwspec *fwspec, EXPORT_SYMBOL_GPL(irq_find_matching_fwspec); /** - * irq_set_default_host() - Set a "default" irq domain + * irq_set_default_domain() - Set a "default" irq domain * @domain: default domain pointer * * For convenience, it's possible to set a "default" domain that will be used @@ -581,16 +581,16 @@ EXPORT_SYMBOL_GPL(irq_find_matching_fwspec); * platforms that want to manipulate a few hard coded interrupt numbers that * aren't properly represented in the device-tree. */ -void irq_set_default_host(struct irq_domain *domain) +void irq_set_default_domain(struct irq_domain *domain) { pr_debug("Default domain set to @0x%p\n", domain); irq_default_domain = domain; } -EXPORT_SYMBOL_GPL(irq_set_default_host); +EXPORT_SYMBOL_GPL(irq_set_default_domain); /** - * irq_get_default_host() - Retrieve the "default" irq domain + * irq_get_default_domain() - Retrieve the "default" irq domain * * Returns: the default domain, if any. * @@ -598,11 +598,11 @@ EXPORT_SYMBOL_GPL(irq_set_default_host); * systems that cannot implement a firmware->fwnode mapping (which * both DT and ACPI provide). */ -struct irq_domain *irq_get_default_host(void) +struct irq_domain *irq_get_default_domain(void) { return irq_default_domain; } -EXPORT_SYMBOL_GPL(irq_get_default_host); +EXPORT_SYMBOL_GPL(irq_get_default_domain); static bool irq_domain_is_nomap(struct irq_domain *domain) {
diff --git a/kernel/irq/migration.c b/kernel/irq/migration.c index 147cabb..f2b29299 100644 --- a/kernel/irq/migration.c +++ b/kernel/irq/migration.c
@@ -37,7 +37,7 @@ bool irq_fixup_move_pending(struct irq_desc *desc, bool force_clear) void irq_force_complete_move(struct irq_desc *desc) { - for (struct irq_data *d = irq_desc_get_irq_data(desc); d; d = d->parent_data) { + for (struct irq_data *d = irq_desc_get_irq_data(desc); d; d = irqd_get_parent_data(d)) { if (d->chip && d->chip->irq_force_complete_move) { d->chip->irq_force_complete_move(d); return;
diff --git a/kernel/kcsan/kcsan_test.c b/kernel/kcsan/kcsan_test.c index 117d9d4..6ce73cc 100644 --- a/kernel/kcsan/kcsan_test.c +++ b/kernel/kcsan/kcsan_test.c
@@ -1500,7 +1500,7 @@ static int access_thread(void *arg) func(); } } while (!torture_must_stop()); - del_timer_sync(&timer); + timer_delete_sync(&timer); destroy_timer_on_stack(&timer); torture_kthread_stopping("access_thread");
diff --git a/kernel/kthread.c b/kernel/kthread.c index 5dc5b0d..77c4492 100644 --- a/kernel/kthread.c +++ b/kernel/kthread.c
@@ -1362,14 +1362,14 @@ static void kthread_cancel_delayed_work_timer(struct kthread_work *work, struct kthread_worker *worker = work->worker; /* - * del_timer_sync() must be called to make sure that the timer + * timer_delete_sync() must be called to make sure that the timer * callback is not running. The lock must be temporary released * to avoid a deadlock with the callback. In the meantime, * any queuing is blocked by setting the canceling counter. */ work->canceling++; raw_spin_unlock_irqrestore(&worker->lock, *flags); - del_timer_sync(&dwork->timer); + timer_delete_sync(&dwork->timer); raw_spin_lock_irqsave(&worker->lock, *flags); work->canceling--; }
diff --git a/kernel/panic.c b/kernel/panic.c index 0c55eec..a3889f3 100644 --- a/kernel/panic.c +++ b/kernel/panic.c
@@ -833,9 +833,15 @@ device_initcall(register_warn_debugfs); */ __visible noinstr void __stack_chk_fail(void) { + unsigned long flags; + instrumentation_begin(); + flags = user_access_save(); + panic("stack-protector: Kernel stack is corrupted in: %pB", __builtin_return_address(0)); + + user_access_restore(flags); instrumentation_end(); } EXPORT_SYMBOL(__stack_chk_fail);
diff --git a/kernel/rcu/Kconfig b/kernel/rcu/Kconfig index aa42de4..4d9b21f 100644 --- a/kernel/rcu/Kconfig +++ b/kernel/rcu/Kconfig
@@ -68,6 +68,8 @@ config FORCE_NEED_SRCU_NMI_SAFE bool "Force selection of NEED_SRCU_NMI_SAFE" depends on !TINY_SRCU + depends on RCU_EXPERT + depends on ARCH_HAS_NMI_SAFE_THIS_CPU_OPS select NEED_SRCU_NMI_SAFE default n help
diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c index 6509566..4fa7772 100644 --- a/kernel/rcu/rcutorture.c +++ b/kernel/rcu/rcutorture.c
@@ -2324,7 +2324,7 @@ rcu_torture_reader(void *arg) stutter_wait("rcu_torture_reader"); } while (!torture_must_stop()); if (irqreader && cur_ops->irq_capable) { - del_timer_sync(&t); + timer_delete_sync(&t); destroy_timer_on_stack(&t); } tick_dep_clear_task(current, TICK_DEP_BIT_RCU);
diff --git a/kernel/rcu/srcutree.c b/kernel/rcu/srcutree.c index d2a6949..9a59b07 100644 --- a/kernel/rcu/srcutree.c +++ b/kernel/rcu/srcutree.c
@@ -690,7 +690,7 @@ void cleanup_srcu_struct(struct srcu_struct *ssp) for_each_possible_cpu(cpu) { struct srcu_data *sdp = per_cpu_ptr(ssp->sda, cpu); - del_timer_sync(&sdp->delay_work); + timer_delete_sync(&sdp->delay_work); flush_work(&sdp->work); if (WARN_ON(rcu_segcblist_n_cbs(&sdp->srcu_cblist))) return; /* Forgot srcu_barrier(), so just leak it! */
diff --git a/kernel/rcu/tasks.h b/kernel/rcu/tasks.h index 466668e..c0cc7ae 100644 --- a/kernel/rcu/tasks.h +++ b/kernel/rcu/tasks.h
@@ -1086,7 +1086,7 @@ static void rcu_tasks_postscan(struct list_head *hop) } if (!IS_ENABLED(CONFIG_TINY_RCU)) - del_timer_sync(&tasks_rcu_exit_srcu_stall_timer); + timer_delete_sync(&tasks_rcu_exit_srcu_stall_timer); } /* See if tasks are still holding out, complain if so. */
diff --git a/kernel/rcu/tree_nocb.h b/kernel/rcu/tree_nocb.h index 5ff3bc5..fa269d34 100644 --- a/kernel/rcu/tree_nocb.h +++ b/kernel/rcu/tree_nocb.h
@@ -206,7 +206,7 @@ static bool __wake_nocb_gp(struct rcu_data *rdp_gp, if (rdp_gp->nocb_defer_wakeup > RCU_NOCB_WAKE_NOT) { WRITE_ONCE(rdp_gp->nocb_defer_wakeup, RCU_NOCB_WAKE_NOT); - del_timer(&rdp_gp->nocb_timer); + timer_delete(&rdp_gp->nocb_timer); } if (force || READ_ONCE(rdp_gp->nocb_gp_sleep)) { @@ -822,7 +822,7 @@ static void nocb_gp_wait(struct rcu_data *my_rdp) if (my_rdp->nocb_defer_wakeup > RCU_NOCB_WAKE_NOT) { WRITE_ONCE(my_rdp->nocb_defer_wakeup, RCU_NOCB_WAKE_NOT); - del_timer(&my_rdp->nocb_timer); + timer_delete(&my_rdp->nocb_timer); } WRITE_ONCE(my_rdp->nocb_gp_sleep, true); raw_spin_unlock_irqrestore(&my_rdp->nocb_gp_lock, flags);
diff --git a/kernel/sched/core.c b/kernel/sched/core.c index cfaca30..c81cf64 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c
@@ -10703,7 +10703,6 @@ void sched_mm_cid_after_execve(struct task_struct *t) smp_mb(); t->last_mm_cid = t->mm_cid = mm_cid_get(rq, t, mm); } - rseq_set_notify_resume(t); } void sched_mm_cid_fork(struct task_struct *t)
diff --git a/kernel/sched/ext.c b/kernel/sched/ext.c index 21575d3..66bcd40 100644 --- a/kernel/sched/ext.c +++ b/kernel/sched/ext.c
@@ -4171,8 +4171,8 @@ static struct scx_dispatch_q *create_dsq(u64 dsq_id, int node) init_dsq(dsq, dsq_id); - ret = rhashtable_insert_fast(&dsq_hash, &dsq->hash_node, - dsq_hash_params); + ret = rhashtable_lookup_insert_fast(&dsq_hash, &dsq->hash_node, + dsq_hash_params); if (ret) { kfree(dsq); return ERR_PTR(ret); @@ -5361,6 +5361,8 @@ static int scx_ops_enable(struct sched_ext_ops *ops, struct bpf_link *link) */ cpus_read_lock(); + scx_idle_enable(ops); + if (scx_ops.init) { ret = SCX_CALL_OP_RET(SCX_KF_UNLOCKED, init); if (ret) { @@ -5427,8 +5429,6 @@ static int scx_ops_enable(struct sched_ext_ops *ops, struct bpf_link *link) if (scx_ops.cpu_acquire || scx_ops.cpu_release) static_branch_enable(&scx_ops_cpu_preempt); - scx_idle_enable(ops); - /* * Lock out forks, cgroup on/offlining and moves before opening the * floodgate so that they don't wander into the operations prematurely.
diff --git a/kernel/sched/ext_idle.c b/kernel/sched/ext_idle.c index 52c36a7..cb343ca 100644 --- a/kernel/sched/ext_idle.c +++ b/kernel/sched/ext_idle.c
@@ -544,7 +544,7 @@ s32 scx_select_cpu_dfl(struct task_struct *p, s32 prev_cpu, u64 wake_flags, u64 * core. */ if (flags & SCX_PICK_IDLE_CORE) { - cpu = prev_cpu; + cpu = -EBUSY; goto out_unlock; } } @@ -584,8 +584,6 @@ s32 scx_select_cpu_dfl(struct task_struct *p, s32 prev_cpu, u64 wake_flags, u64 * increasing distance. */ cpu = scx_pick_idle_cpu(p->cpus_ptr, node, flags); - if (cpu >= 0) - goto out_unlock; out_unlock: rcu_read_unlock(); @@ -723,14 +721,14 @@ static void reset_idle_masks(struct sched_ext_ops *ops) void scx_idle_enable(struct sched_ext_ops *ops) { if (!ops->update_idle || (ops->flags & SCX_OPS_KEEP_BUILTIN_IDLE)) - static_branch_enable(&scx_builtin_idle_enabled); + static_branch_enable_cpuslocked(&scx_builtin_idle_enabled); else - static_branch_disable(&scx_builtin_idle_enabled); + static_branch_disable_cpuslocked(&scx_builtin_idle_enabled); if (ops->flags & SCX_OPS_BUILTIN_IDLE_PER_NODE) - static_branch_enable(&scx_builtin_idle_per_node); + static_branch_enable_cpuslocked(&scx_builtin_idle_per_node); else - static_branch_disable(&scx_builtin_idle_per_node); + static_branch_disable_cpuslocked(&scx_builtin_idle_per_node); #ifdef CONFIG_SMP reset_idle_masks(ops);
diff --git a/kernel/sched/psi.c b/kernel/sched/psi.c index bb56805..1396674f 100644 --- a/kernel/sched/psi.c +++ b/kernel/sched/psi.c
@@ -1440,7 +1440,7 @@ void psi_trigger_destroy(struct psi_trigger *t) group->rtpoll_task, lockdep_is_held(&group->rtpoll_trigger_lock)); rcu_assign_pointer(group->rtpoll_task, NULL); - del_timer(&group->rtpoll_timer); + timer_delete(&group->rtpoll_timer); } } mutex_unlock(&group->rtpoll_trigger_lock);
diff --git a/kernel/signal.c b/kernel/signal.c index 614d78f..f8859fa 100644 --- a/kernel/signal.c +++ b/kernel/signal.c
@@ -2180,11 +2180,9 @@ bool do_notify_parent(struct task_struct *tsk, int sig) WARN_ON_ONCE(!tsk->ptrace && (tsk->group_leader != tsk || !thread_group_empty(tsk))); - /* - * Notify for thread-group leaders without subthreads. - */ - if (thread_group_empty(tsk)) - do_notify_pidfd(tsk); + + /* ptraced, or group-leader without sub-threads */ + do_notify_pidfd(tsk); if (sig != SIGCHLD) { /*
diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c index e0eeacb..bb48498 100644 --- a/kernel/time/clocksource.c +++ b/kernel/time/clocksource.c
@@ -619,7 +619,7 @@ static inline void clocksource_stop_watchdog(void) { if (!watchdog_running || (watchdog && !list_empty(&watchdog_list))) return; - del_timer(&watchdog_timer); + timer_delete(&watchdog_timer); watchdog_running = 0; }
diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c index 22376a1..517ee25 100644 --- a/kernel/time/hrtimer.c +++ b/kernel/time/hrtimer.c
@@ -465,19 +465,17 @@ static inline void debug_hrtimer_activate(struct hrtimer *timer, static inline void debug_hrtimer_deactivate(struct hrtimer *timer) { } #endif -static inline void -debug_init(struct hrtimer *timer, clockid_t clockid, - enum hrtimer_mode mode) +static inline void debug_setup(struct hrtimer *timer, clockid_t clockid, enum hrtimer_mode mode) { debug_hrtimer_init(timer); - trace_hrtimer_init(timer, clockid, mode); + trace_hrtimer_setup(timer, clockid, mode); } -static inline void debug_init_on_stack(struct hrtimer *timer, clockid_t clockid, - enum hrtimer_mode mode) +static inline void debug_setup_on_stack(struct hrtimer *timer, clockid_t clockid, + enum hrtimer_mode mode) { debug_hrtimer_init_on_stack(timer); - trace_hrtimer_init(timer, clockid, mode); + trace_hrtimer_setup(timer, clockid, mode); } static inline void debug_activate(struct hrtimer *timer, @@ -1316,8 +1314,6 @@ void hrtimer_start_range_ns(struct hrtimer *timer, ktime_t tim, struct hrtimer_clock_base *base; unsigned long flags; - if (WARN_ON_ONCE(!timer->function)) - return; /* * Check whether the HRTIMER_MODE_SOFT bit and hrtimer.is_soft * match on CONFIG_PREEMPT_RT = n. With PREEMPT_RT check the hard @@ -1429,7 +1425,7 @@ static __always_inline bool is_migration_base(struct hrtimer_clock_base *base) * running. * * This prevents priority inversion: if the soft irq thread is preempted - * in the middle of a timer callback, then calling del_timer_sync() can + * in the middle of a timer callback, then calling hrtimer_cancel() can * lead to two issues: * * - If the caller is on a remote CPU then it has to spin wait for the timer @@ -1592,8 +1588,9 @@ static inline int hrtimer_clockid_to_base(clockid_t clock_id) } } -static void __hrtimer_init(struct hrtimer *timer, clockid_t clock_id, - enum hrtimer_mode mode) +static void __hrtimer_setup(struct hrtimer *timer, + enum hrtimer_restart (*function)(struct hrtimer *), + clockid_t clock_id, enum hrtimer_mode mode) { bool softtimer = !!(mode & HRTIMER_MODE_SOFT); struct hrtimer_cpu_base *cpu_base; @@ -1626,41 +1623,14 @@ static void __hrtimer_init(struct hrtimer *timer, clockid_t clock_id, timer->is_hard = !!(mode & HRTIMER_MODE_HARD); timer->base = &cpu_base->clock_base[base]; timerqueue_init(&timer->node); -} - -static void __hrtimer_setup(struct hrtimer *timer, - enum hrtimer_restart (*function)(struct hrtimer *), - clockid_t clock_id, enum hrtimer_mode mode) -{ - __hrtimer_init(timer, clock_id, mode); if (WARN_ON_ONCE(!function)) - timer->function = hrtimer_dummy_timeout; + ACCESS_PRIVATE(timer, function) = hrtimer_dummy_timeout; else - timer->function = function; + ACCESS_PRIVATE(timer, function) = function; } /** - * hrtimer_init - initialize a timer to the given clock - * @timer: the timer to be initialized - * @clock_id: the clock to be used - * @mode: The modes which are relevant for initialization: - * HRTIMER_MODE_ABS, HRTIMER_MODE_REL, HRTIMER_MODE_ABS_SOFT, - * HRTIMER_MODE_REL_SOFT - * - * The PINNED variants of the above can be handed in, - * but the PINNED bit is ignored as pinning happens - * when the hrtimer is started - */ -void hrtimer_init(struct hrtimer *timer, clockid_t clock_id, - enum hrtimer_mode mode) -{ - debug_init(timer, clock_id, mode); - __hrtimer_init(timer, clock_id, mode); -} -EXPORT_SYMBOL_GPL(hrtimer_init); - -/** * hrtimer_setup - initialize a timer to the given clock * @timer: the timer to be initialized * @function: the callback function @@ -1676,7 +1646,7 @@ EXPORT_SYMBOL_GPL(hrtimer_init); void hrtimer_setup(struct hrtimer *timer, enum hrtimer_restart (*function)(struct hrtimer *), clockid_t clock_id, enum hrtimer_mode mode) { - debug_init(timer, clock_id, mode); + debug_setup(timer, clock_id, mode); __hrtimer_setup(timer, function, clock_id, mode); } EXPORT_SYMBOL_GPL(hrtimer_setup); @@ -1695,7 +1665,7 @@ void hrtimer_setup_on_stack(struct hrtimer *timer, enum hrtimer_restart (*function)(struct hrtimer *), clockid_t clock_id, enum hrtimer_mode mode) { - debug_init_on_stack(timer, clock_id, mode); + debug_setup_on_stack(timer, clock_id, mode); __hrtimer_setup(timer, function, clock_id, mode); } EXPORT_SYMBOL_GPL(hrtimer_setup_on_stack); @@ -1769,7 +1739,7 @@ static void __run_hrtimer(struct hrtimer_cpu_base *cpu_base, raw_write_seqcount_barrier(&base->seq); __remove_hrtimer(timer, base, HRTIMER_STATE_INACTIVE, 0); - fn = timer->function; + fn = ACCESS_PRIVATE(timer, function); /* * Clear the 'is relative' flag for the TIME_LOW_RES case. If the @@ -2044,7 +2014,7 @@ void hrtimer_sleeper_start_expires(struct hrtimer_sleeper *sl, * Make the enqueue delivery mode check work on RT. If the sleeper * was initialized for hard interrupt delivery, force the mode bit. * This is a special case for hrtimer_sleepers because - * __hrtimer_init_sleeper() determines the delivery mode on RT so the + * __hrtimer_setup_sleeper() determines the delivery mode on RT so the * fiddling with this decision is avoided at the call sites. */ if (IS_ENABLED(CONFIG_PREEMPT_RT) && sl->timer.is_hard) @@ -2054,8 +2024,8 @@ void hrtimer_sleeper_start_expires(struct hrtimer_sleeper *sl, } EXPORT_SYMBOL_GPL(hrtimer_sleeper_start_expires); -static void __hrtimer_init_sleeper(struct hrtimer_sleeper *sl, - clockid_t clock_id, enum hrtimer_mode mode) +static void __hrtimer_setup_sleeper(struct hrtimer_sleeper *sl, + clockid_t clock_id, enum hrtimer_mode mode) { /* * On PREEMPT_RT enabled kernels hrtimers which are not explicitly @@ -2081,8 +2051,7 @@ static void __hrtimer_init_sleeper(struct hrtimer_sleeper *sl, mode |= HRTIMER_MODE_HARD; } - __hrtimer_init(&sl->timer, clock_id, mode); - sl->timer.function = hrtimer_wakeup; + __hrtimer_setup(&sl->timer, hrtimer_wakeup, clock_id, mode); sl->task = current; } @@ -2095,8 +2064,8 @@ static void __hrtimer_init_sleeper(struct hrtimer_sleeper *sl, void hrtimer_setup_sleeper_on_stack(struct hrtimer_sleeper *sl, clockid_t clock_id, enum hrtimer_mode mode) { - debug_init_on_stack(&sl->timer, clock_id, mode); - __hrtimer_init_sleeper(sl, clock_id, mode); + debug_setup_on_stack(&sl->timer, clock_id, mode); + __hrtimer_setup_sleeper(sl, clock_id, mode); } EXPORT_SYMBOL_GPL(hrtimer_setup_sleeper_on_stack);
diff --git a/kernel/time/sleep_timeout.c b/kernel/time/sleep_timeout.c index dfe939f..c0e960a 100644 --- a/kernel/time/sleep_timeout.c +++ b/kernel/time/sleep_timeout.c
@@ -97,7 +97,7 @@ signed long __sched schedule_timeout(signed long timeout) timer.timer.expires = expire; add_timer(&timer.timer); schedule(); - del_timer_sync(&timer.timer); + timer_delete_sync(&timer.timer); /* Remove the timer from the object tracker */ destroy_timer_on_stack(&timer.timer);
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index 929846b..1e67d07 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c
@@ -682,19 +682,20 @@ static void timekeeping_update_from_shadow(struct tk_data *tkd, unsigned int act } /** - * timekeeping_forward - update clock to given cycle now value + * timekeeping_forward_now - update clock to the current time * @tk: Pointer to the timekeeper to update - * @cycle_now: Current clocksource read value * * Forward the current clock to update its state since the last call to * update_wall_time(). This is useful before significant clock changes, * as it avoids having to deal with this time offset explicitly. */ -static void timekeeping_forward(struct timekeeper *tk, u64 cycle_now) +static void timekeeping_forward_now(struct timekeeper *tk) { - u64 delta = clocksource_delta(cycle_now, tk->tkr_mono.cycle_last, tk->tkr_mono.mask, - tk->tkr_mono.clock->max_raw_delta); + u64 cycle_now, delta; + cycle_now = tk_clock_read(&tk->tkr_mono); + delta = clocksource_delta(cycle_now, tk->tkr_mono.cycle_last, tk->tkr_mono.mask, + tk->tkr_mono.clock->max_raw_delta); tk->tkr_mono.cycle_last = cycle_now; tk->tkr_raw.cycle_last = cycle_now; @@ -710,21 +711,6 @@ static void timekeeping_forward(struct timekeeper *tk, u64 cycle_now) } /** - * timekeeping_forward_now - update clock to the current time - * @tk: Pointer to the timekeeper to update - * - * Forward the current clock to update its state since the last call to - * update_wall_time(). This is useful before significant clock changes, - * as it avoids having to deal with this time offset explicitly. - */ -static void timekeeping_forward_now(struct timekeeper *tk) -{ - u64 cycle_now = tk_clock_read(&tk->tkr_mono); - - timekeeping_forward(tk, cycle_now); -} - -/** * ktime_get_real_ts64 - Returns the time of day in a timespec64. * @ts: pointer to the timespec to be set * @@ -2165,54 +2151,6 @@ static u64 logarithmic_accumulation(struct timekeeper *tk, u64 offset, return offset; } -static u64 timekeeping_accumulate(struct timekeeper *tk, u64 offset, - enum timekeeping_adv_mode mode, - unsigned int *clock_set) -{ - int shift = 0, maxshift; - - /* - * TK_ADV_FREQ indicates that adjtimex(2) directly set the - * frequency or the tick length. - * - * Accumulate the offset, so that the new multiplier starts from - * now. This is required as otherwise for offsets, which are - * smaller than tk::cycle_interval, timekeeping_adjust() could set - * xtime_nsec backwards, which subsequently causes time going - * backwards in the coarse time getters. But even for the case - * where offset is greater than tk::cycle_interval the periodic - * accumulation does not have much value. - * - * Also reset tk::ntp_error as it does not make sense to keep the - * old accumulated error around in this case. - */ - if (mode == TK_ADV_FREQ) { - timekeeping_forward(tk, tk->tkr_mono.cycle_last + offset); - tk->ntp_error = 0; - return 0; - } - - /* - * With NO_HZ we may have to accumulate many cycle_intervals - * (think "ticks") worth of time at once. To do this efficiently, - * we calculate the largest doubling multiple of cycle_intervals - * that is smaller than the offset. We then accumulate that - * chunk in one go, and then try to consume the next smaller - * doubled multiple. - */ - shift = ilog2(offset) - ilog2(tk->cycle_interval); - shift = max(0, shift); - /* Bound shift to one less than what overflows tick_length */ - maxshift = (64 - (ilog2(ntp_tick_length()) + 1)) - 1; - shift = min(shift, maxshift); - while (offset >= tk->cycle_interval) { - offset = logarithmic_accumulation(tk, offset, shift, clock_set); - if (offset < tk->cycle_interval << shift) - shift--; - } - return offset; -} - /* * timekeeping_advance - Updates the timekeeper to the current time and * current NTP tick length @@ -2222,6 +2160,7 @@ static bool timekeeping_advance(enum timekeeping_adv_mode mode) struct timekeeper *tk = &tk_core.shadow_timekeeper; struct timekeeper *real_tk = &tk_core.timekeeper; unsigned int clock_set = 0; + int shift = 0, maxshift; u64 offset; guard(raw_spinlock_irqsave)(&tk_core.lock); @@ -2238,7 +2177,24 @@ static bool timekeeping_advance(enum timekeeping_adv_mode mode) if (offset < real_tk->cycle_interval && mode == TK_ADV_TICK) return false; - offset = timekeeping_accumulate(tk, offset, mode, &clock_set); + /* + * With NO_HZ we may have to accumulate many cycle_intervals + * (think "ticks") worth of time at once. To do this efficiently, + * we calculate the largest doubling multiple of cycle_intervals + * that is smaller than the offset. We then accumulate that + * chunk in one go, and then try to consume the next smaller + * doubled multiple. + */ + shift = ilog2(offset) - ilog2(tk->cycle_interval); + shift = max(0, shift); + /* Bound shift to one less than what overflows tick_length */ + maxshift = (64 - (ilog2(ntp_tick_length())+1)) - 1; + shift = min(shift, maxshift); + while (offset >= tk->cycle_interval) { + offset = logarithmic_accumulation(tk, offset, shift, &clock_set); + if (offset < tk->cycle_interval<<shift) + shift--; + } /* Adjust the multiplier to correct NTP error */ timekeeping_adjust(tk, offset);
diff --git a/kernel/time/timer.c b/kernel/time/timer.c index c8f776d..4d915c0 100644 --- a/kernel/time/timer.c +++ b/kernel/time/timer.c
@@ -744,7 +744,7 @@ static bool timer_fixup_init(void *addr, enum debug_obj_state state) switch (state) { case ODEBUG_STATE_ACTIVE: - del_timer_sync(timer); + timer_delete_sync(timer); debug_object_init(timer, &timer_debug_descr); return true; default: @@ -790,7 +790,7 @@ static bool timer_fixup_free(void *addr, enum debug_obj_state state) switch (state) { case ODEBUG_STATE_ACTIVE: - del_timer_sync(timer); + timer_delete_sync(timer); debug_object_free(timer, &timer_debug_descr); return true; default: @@ -1212,10 +1212,10 @@ EXPORT_SYMBOL(mod_timer_pending); * * mod_timer(timer, expires) is equivalent to: * - * del_timer(timer); timer->expires = expires; add_timer(timer); + * timer_delete(timer); timer->expires = expires; add_timer(timer); * * mod_timer() is more efficient than the above open coded sequence. In - * case that the timer is inactive, the del_timer() part is a NOP. The + * case that the timer is inactive, the timer_delete() part is a NOP. The * timer is in any case activated with the new expiry time @expires. * * Note that if there are multiple unserialized concurrent users of the
diff --git a/kernel/time/timer_list.c b/kernel/time/timer_list.c index cfbb46cc..b03d0ad 100644 --- a/kernel/time/timer_list.c +++ b/kernel/time/timer_list.c
@@ -46,7 +46,7 @@ static void print_timer(struct seq_file *m, struct hrtimer *taddr, struct hrtimer *timer, int idx, u64 now) { - SEQ_printf(m, " #%d: <%p>, %ps", idx, taddr, timer->function); + SEQ_printf(m, " #%d: <%p>, %ps", idx, taddr, ACCESS_PRIVATE(timer, function)); SEQ_printf(m, ", S:%02x", timer->state); SEQ_printf(m, "\n"); SEQ_printf(m, " # expires at %Lu-%Lu nsecs [in %Ld to %Ld nsecs]\n",
diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig index 033fba0..a3f35c7d 100644 --- a/kernel/trace/Kconfig +++ b/kernel/trace/Kconfig
@@ -265,8 +265,7 @@ config FUNCTION_TRACE_ARGS bool - depends on HAVE_FUNCTION_ARG_ACCESS_API - depends on DEBUG_INFO_BTF + depends on PROBE_EVENTS_BTF_ARGS default y help If supported with function argument access API and BTF, then
diff --git a/kernel/trace/fprobe.c b/kernel/trace/fprobe.c index 33082c4..95c6e34 100644 --- a/kernel/trace/fprobe.c +++ b/kernel/trace/fprobe.c
@@ -89,8 +89,11 @@ static bool delete_fprobe_node(struct fprobe_hlist_node *node) { lockdep_assert_held(&fprobe_mutex); - WRITE_ONCE(node->fp, NULL); - hlist_del_rcu(&node->hlist); + /* Avoid double deleting */ + if (READ_ONCE(node->fp) != NULL) { + WRITE_ONCE(node->fp, NULL); + hlist_del_rcu(&node->hlist); + } return !!find_first_fprobe_node(node->addr); } @@ -411,6 +414,102 @@ static void fprobe_graph_remove_ips(unsigned long *addrs, int num) ftrace_set_filter_ips(&fprobe_graph_ops.ops, addrs, num, 1, 0); } +#ifdef CONFIG_MODULES + +#define FPROBE_IPS_BATCH_INIT 8 +/* instruction pointer address list */ +struct fprobe_addr_list { + int index; + int size; + unsigned long *addrs; +}; + +static int fprobe_addr_list_add(struct fprobe_addr_list *alist, unsigned long addr) +{ + unsigned long *addrs; + + if (alist->index >= alist->size) + return -ENOMEM; + + alist->addrs[alist->index++] = addr; + if (alist->index < alist->size) + return 0; + + /* Expand the address list */ + addrs = kcalloc(alist->size * 2, sizeof(*addrs), GFP_KERNEL); + if (!addrs) + return -ENOMEM; + + memcpy(addrs, alist->addrs, alist->size * sizeof(*addrs)); + alist->size *= 2; + kfree(alist->addrs); + alist->addrs = addrs; + + return 0; +} + +static void fprobe_remove_node_in_module(struct module *mod, struct hlist_head *head, + struct fprobe_addr_list *alist) +{ + struct fprobe_hlist_node *node; + int ret = 0; + + hlist_for_each_entry_rcu(node, head, hlist) { + if (!within_module(node->addr, mod)) + continue; + if (delete_fprobe_node(node)) + continue; + /* + * If failed to update alist, just continue to update hlist. + * Therefore, at list user handler will not hit anymore. + */ + if (!ret) + ret = fprobe_addr_list_add(alist, node->addr); + } +} + +/* Handle module unloading to manage fprobe_ip_table. */ +static int fprobe_module_callback(struct notifier_block *nb, + unsigned long val, void *data) +{ + struct fprobe_addr_list alist = {.size = FPROBE_IPS_BATCH_INIT}; + struct module *mod = data; + int i; + + if (val != MODULE_STATE_GOING) + return NOTIFY_DONE; + + alist.addrs = kcalloc(alist.size, sizeof(*alist.addrs), GFP_KERNEL); + /* If failed to alloc memory, we can not remove ips from hash. */ + if (!alist.addrs) + return NOTIFY_DONE; + + mutex_lock(&fprobe_mutex); + for (i = 0; i < FPROBE_IP_TABLE_SIZE; i++) + fprobe_remove_node_in_module(mod, &fprobe_ip_table[i], &alist); + + if (alist.index < alist.size && alist.index > 0) + ftrace_set_filter_ips(&fprobe_graph_ops.ops, + alist.addrs, alist.index, 1, 0); + mutex_unlock(&fprobe_mutex); + + kfree(alist.addrs); + + return NOTIFY_DONE; +} + +static struct notifier_block fprobe_module_nb = { + .notifier_call = fprobe_module_callback, + .priority = 0, +}; + +static int __init init_fprobe_module(void) +{ + return register_module_notifier(&fprobe_module_nb); +} +early_initcall(init_fprobe_module); +#endif + static int symbols_cmp(const void *a, const void *b) { const char **str_a = (const char **) a; @@ -445,6 +544,7 @@ struct filter_match_data { size_t index; size_t size; unsigned long *addrs; + struct module **mods; }; static int filter_match_callback(void *data, const char *name, unsigned long addr) @@ -458,30 +558,47 @@ static int filter_match_callback(void *data, const char *name, unsigned long add if (!ftrace_location(addr)) return 0; - if (match->addrs) - match->addrs[match->index] = addr; + if (match->addrs) { + struct module *mod = __module_text_address(addr); + if (mod && !try_module_get(mod)) + return 0; + + match->mods[match->index] = mod; + match->addrs[match->index] = addr; + } match->index++; return match->index == match->size; } /* * Make IP list from the filter/no-filter glob patterns. - * Return the number of matched symbols, or -ENOENT. + * Return the number of matched symbols, or errno. + * If @addrs == NULL, this just counts the number of matched symbols. If @addrs + * is passed with an array, we need to pass the an @mods array of the same size + * to increment the module refcount for each symbol. + * This means we also need to call `module_put` for each element of @mods after + * using the @addrs. */ -static int ip_list_from_filter(const char *filter, const char *notfilter, - unsigned long *addrs, size_t size) +static int get_ips_from_filter(const char *filter, const char *notfilter, + unsigned long *addrs, struct module **mods, + size_t size) { struct filter_match_data match = { .filter = filter, .notfilter = notfilter, - .index = 0, .size = size, .addrs = addrs}; + .index = 0, .size = size, .addrs = addrs, .mods = mods}; int ret; + if (addrs && !mods) + return -EINVAL; + ret = kallsyms_on_each_symbol(filter_match_callback, &match); if (ret < 0) return ret; - ret = module_kallsyms_on_each_symbol(NULL, filter_match_callback, &match); - if (ret < 0) - return ret; + if (IS_ENABLED(CONFIG_MODULES)) { + ret = module_kallsyms_on_each_symbol(NULL, filter_match_callback, &match); + if (ret < 0) + return ret; + } return match.index ?: -ENOENT; } @@ -543,24 +660,35 @@ static int fprobe_init(struct fprobe *fp, unsigned long *addrs, int num) */ int register_fprobe(struct fprobe *fp, const char *filter, const char *notfilter) { - unsigned long *addrs; - int ret; + unsigned long *addrs __free(kfree) = NULL; + struct module **mods __free(kfree) = NULL; + int ret, num; if (!fp || !filter) return -EINVAL; - ret = ip_list_from_filter(filter, notfilter, NULL, FPROBE_IPS_MAX); + num = get_ips_from_filter(filter, notfilter, NULL, NULL, FPROBE_IPS_MAX); + if (num < 0) + return num; + + addrs = kcalloc(num, sizeof(*addrs), GFP_KERNEL); + if (!addrs) + return -ENOMEM; + + mods = kcalloc(num, sizeof(*mods), GFP_KERNEL); + if (!mods) + return -ENOMEM; + + ret = get_ips_from_filter(filter, notfilter, addrs, mods, num); if (ret < 0) return ret; - addrs = kcalloc(ret, sizeof(unsigned long), GFP_KERNEL); - if (!addrs) - return -ENOMEM; - ret = ip_list_from_filter(filter, notfilter, addrs, ret); - if (ret > 0) - ret = register_fprobe_ips(fp, addrs, ret); + ret = register_fprobe_ips(fp, addrs, ret); - kfree(addrs); + for (int i = 0; i < num; i++) { + if (mods[i]) + module_put(mods[i]); + } return ret; } EXPORT_SYMBOL_GPL(register_fprobe);
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 92015de..1a48aed 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c
@@ -6855,6 +6855,7 @@ ftrace_graph_set_hash(struct ftrace_hash *hash, char *buffer) } } } + cond_resched(); } while_for_each_ftrace_rec(); return fail ? -EINVAL : 0;
diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index d8d7b28..c0f877d 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c
@@ -6016,7 +6016,7 @@ static void rb_update_meta_page(struct ring_buffer_per_cpu *cpu_buffer) meta->read = cpu_buffer->read; /* Some archs do not have data cache coherency between kernel and user-space */ - flush_dcache_folio(virt_to_folio(cpu_buffer->meta_page)); + flush_kernel_vmap_range(cpu_buffer->meta_page, PAGE_SIZE); } static void @@ -7319,7 +7319,8 @@ int ring_buffer_map_get_reader(struct trace_buffer *buffer, int cpu) out: /* Some archs do not have data cache coherency between kernel and user-space */ - flush_dcache_folio(virt_to_folio(cpu_buffer->reader_page->page)); + flush_kernel_vmap_range(cpu_buffer->reader_page->page, + buffer->subbuf_size + BUF_PAGE_HDR_SIZE); rb_update_meta_page(cpu_buffer);
diff --git a/kernel/trace/rv/rv.c b/kernel/trace/rv/rv.c index 50344aa..968c5c3 100644 --- a/kernel/trace/rv/rv.c +++ b/kernel/trace/rv/rv.c
@@ -809,7 +809,8 @@ int rv_register_monitor(struct rv_monitor *monitor, struct rv_monitor *parent) if (p && rv_is_nested_monitor(p)) { pr_info("Parent monitor %s is already nested, cannot nest further\n", parent->name); - return -EINVAL; + retval = -EINVAL; + goto out_unlock; } r = kzalloc(sizeof(struct rv_monitor_def), GFP_KERNEL);
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 103b193..b581e38 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c
@@ -50,6 +50,7 @@ #include <linux/irq_work.h> #include <linux/workqueue.h> #include <linux/sort.h> +#include <linux/io.h> /* vmap_page_range() */ #include <asm/setup.h> /* COMMAND_LINE_SIZE */ @@ -3341,10 +3342,9 @@ int trace_vbprintk(unsigned long ip, const char *fmt, va_list args) } EXPORT_SYMBOL_GPL(trace_vbprintk); -__printf(3, 0) -static int -__trace_array_vprintk(struct trace_buffer *buffer, - unsigned long ip, const char *fmt, va_list args) +static __printf(3, 0) +int __trace_array_vprintk(struct trace_buffer *buffer, + unsigned long ip, const char *fmt, va_list args) { struct ring_buffer_event *event; int len = 0, size; @@ -3394,7 +3394,6 @@ __trace_array_vprintk(struct trace_buffer *buffer, return len; } -__printf(3, 0) int trace_array_vprintk(struct trace_array *tr, unsigned long ip, const char *fmt, va_list args) { @@ -3424,7 +3423,6 @@ int trace_array_vprintk(struct trace_array *tr, * Note, trace_array_init_printk() must be called on @tr before this * can be used. */ -__printf(3, 0) int trace_array_printk(struct trace_array *tr, unsigned long ip, const char *fmt, ...) { @@ -3469,7 +3467,6 @@ int trace_array_init_printk(struct trace_array *tr) } EXPORT_SYMBOL_GPL(trace_array_init_printk); -__printf(3, 4) int trace_array_printk_buf(struct trace_buffer *buffer, unsigned long ip, const char *fmt, ...) { @@ -3485,7 +3482,6 @@ int trace_array_printk_buf(struct trace_buffer *buffer, return ret; } -__printf(2, 0) int trace_vprintk(unsigned long ip, const char *fmt, va_list args) { return trace_array_vprintk(printk_trace, ip, fmt, args); @@ -8505,6 +8501,10 @@ static int tracing_buffers_mmap(struct file *filp, struct vm_area_struct *vma) struct trace_iterator *iter = &info->iter; int ret = 0; + /* A memmap'ed buffer is not supported for user space mmap */ + if (iter->tr->flags & TRACE_ARRAY_FL_MEMMAP) + return -ENODEV; + /* Currently the boot mapped buffer is not supported for mmap */ if (iter->tr->flags & TRACE_ARRAY_FL_BOOT) return -ENODEV; @@ -9609,13 +9609,11 @@ static void free_trace_buffers(struct trace_array *tr) return; free_trace_buffer(&tr->array_buffer); + kfree(tr->module_delta); #ifdef CONFIG_TRACER_MAX_TRACE free_trace_buffer(&tr->max_buffer); #endif - - if (tr->range_addr_start) - vunmap((void *)tr->range_addr_start); } static void init_trace_flags_index(struct trace_array *tr) @@ -9808,29 +9806,27 @@ static int instance_mkdir(const char *name) return ret; } -static u64 map_pages(u64 start, u64 size) +static u64 map_pages(unsigned long start, unsigned long size) { - struct page **pages; - phys_addr_t page_start; - unsigned int page_count; - unsigned int i; - void *vaddr; + unsigned long vmap_start, vmap_end; + struct vm_struct *area; + int ret; - page_count = DIV_ROUND_UP(size, PAGE_SIZE); - - page_start = start; - pages = kmalloc_array(page_count, sizeof(struct page *), GFP_KERNEL); - if (!pages) + area = get_vm_area(size, VM_IOREMAP); + if (!area) return 0; - for (i = 0; i < page_count; i++) { - phys_addr_t addr = page_start + i * PAGE_SIZE; - pages[i] = pfn_to_page(addr >> PAGE_SHIFT); - } - vaddr = vmap(pages, page_count, VM_MAP, PAGE_KERNEL); - kfree(pages); + vmap_start = (unsigned long) area->addr; + vmap_end = vmap_start + size; - return (u64)(unsigned long)vaddr; + ret = vmap_page_range(vmap_start, vmap_end, + start, pgprot_nx(PAGE_KERNEL)); + if (ret < 0) { + free_vm_area(area); + return 0; + } + + return (u64)vmap_start; } /** @@ -10709,6 +10705,7 @@ static inline void do_allocate_snapshot(const char *name) { } __init static void enable_instances(void) { struct trace_array *tr; + bool memmap_area = false; char *curr_str; char *name; char *str; @@ -10777,6 +10774,7 @@ __init static void enable_instances(void) name); continue; } + memmap_area = true; } else if (tok) { if (!reserve_mem_find_by_name(tok, &start, &size)) { start = 0; @@ -10787,7 +10785,20 @@ __init static void enable_instances(void) } if (start) { - addr = map_pages(start, size); + /* Start and size must be page aligned */ + if (start & ~PAGE_MASK) { + pr_warn("Tracing: mapping start addr %pa is not page aligned\n", &start); + continue; + } + if (size & ~PAGE_MASK) { + pr_warn("Tracing: mapping size %pa is not page aligned\n", &size); + continue; + } + + if (memmap_area) + addr = map_pages(start, size); + else + addr = (unsigned long)phys_to_virt(start); if (addr) { pr_info("Tracing: mapped boot instance %s at physical memory %pa of size 0x%lx\n", name, &start, (unsigned long)size); @@ -10814,10 +10825,13 @@ __init static void enable_instances(void) update_printk_trace(tr); /* - * If start is set, then this is a mapped buffer, and - * cannot be deleted by user space, so keep the reference - * to it. + * memmap'd buffers can not be freed. */ + if (memmap_area) { + tr->flags |= TRACE_ARRAY_FL_MEMMAP; + tr->ref++; + } + if (start) { tr->flags |= TRACE_ARRAY_FL_BOOT | TRACE_ARRAY_FL_LAST_BOOT; tr->range_name = no_free_ptr(rname);
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index c20f6bc..79be199 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h
@@ -447,6 +447,7 @@ enum { TRACE_ARRAY_FL_BOOT = BIT(1), TRACE_ARRAY_FL_LAST_BOOT = BIT(2), TRACE_ARRAY_FL_MOD_INIT = BIT(3), + TRACE_ARRAY_FL_MEMMAP = BIT(4), }; #ifdef CONFIG_MODULES @@ -852,13 +853,15 @@ static inline void __init disable_tracing_selftest(const char *reason) extern void *head_page(struct trace_array_cpu *data); extern unsigned long long ns2usecs(u64 nsec); -extern int -trace_vbprintk(unsigned long ip, const char *fmt, va_list args); -extern int -trace_vprintk(unsigned long ip, const char *fmt, va_list args); -extern int -trace_array_vprintk(struct trace_array *tr, - unsigned long ip, const char *fmt, va_list args); + +__printf(2, 0) +int trace_vbprintk(unsigned long ip, const char *fmt, va_list args); +__printf(2, 0) +int trace_vprintk(unsigned long ip, const char *fmt, va_list args); +__printf(3, 0) +int trace_array_vprintk(struct trace_array *tr, + unsigned long ip, const char *fmt, va_list args); +__printf(3, 4) int trace_array_printk_buf(struct trace_buffer *buffer, unsigned long ip, const char *fmt, ...); void trace_printk_seq(struct trace_seq *s);
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index 8638b7f..069e928 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c
@@ -470,6 +470,7 @@ static void test_event_printk(struct trace_event_call *call) case '%': continue; case 'p': + do_pointer: /* Find dereferencing fields */ switch (fmt[i + 1]) { case 'B': case 'R': case 'r': @@ -498,6 +499,12 @@ static void test_event_printk(struct trace_event_call *call) continue; if (fmt[i + j] == '*') { star = true; + /* Handle %*pbl case */ + if (!j && fmt[i + 1] == 'p') { + arg++; + i++; + goto do_pointer; + } continue; } if ((fmt[i + j] == 's')) {
diff --git a/kernel/trace/trace_fprobe.c b/kernel/trace/trace_fprobe.c index 5d7ca80..b40fa59 100644 --- a/kernel/trace/trace_fprobe.c +++ b/kernel/trace/trace_fprobe.c
@@ -919,9 +919,15 @@ static void __find_tracepoint_module_cb(struct tracepoint *tp, struct module *mo struct __find_tracepoint_cb_data *data = priv; if (!data->tpoint && !strcmp(data->tp_name, tp->name)) { - data->tpoint = tp; - if (!data->mod) + /* If module is not specified, try getting module refcount. */ + if (!data->mod && mod) { + /* If failed to get refcount, ignore this tracepoint. */ + if (!try_module_get(mod)) + return; + data->mod = mod; + } + data->tpoint = tp; } } @@ -933,7 +939,11 @@ static void __find_tracepoint_cb(struct tracepoint *tp, void *priv) data->tpoint = tp; } -/* Find a tracepoint from kernel and module. */ +/* + * Find a tracepoint from kernel and module. If the tracepoint is on the module, + * the module's refcount is incremented and returned as *@tp_mod. Thus, if it is + * not NULL, caller must call module_put(*tp_mod) after used the tracepoint. + */ static struct tracepoint *find_tracepoint(const char *tp_name, struct module **tp_mod) { @@ -962,7 +972,10 @@ static void reenable_trace_fprobe(struct trace_fprobe *tf) } } -/* Find a tracepoint from specified module. */ +/* + * Find a tracepoint from specified module. In this case, this does not get the + * module's refcount. The caller must ensure the module is not freed. + */ static struct tracepoint *find_tracepoint_in_module(struct module *mod, const char *tp_name) { @@ -1169,11 +1182,6 @@ static int trace_fprobe_create_internal(int argc, const char *argv[], if (is_tracepoint) { ctx->flags |= TPARG_FL_TPOINT; tpoint = find_tracepoint(symbol, &tp_mod); - /* lock module until register this tprobe. */ - if (tp_mod && !try_module_get(tp_mod)) { - tpoint = NULL; - tp_mod = NULL; - } if (tpoint) { ctx->funcname = kallsyms_lookup( (unsigned long)tpoint->probestub,
diff --git a/kernel/workqueue.c b/kernel/workqueue.c index bfe030b..cf62032 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c
@@ -2057,11 +2057,11 @@ static int try_to_grab_pending(struct work_struct *work, u32 cflags, struct delayed_work *dwork = to_delayed_work(work); /* - * dwork->timer is irqsafe. If del_timer() fails, it's + * dwork->timer is irqsafe. If timer_delete() fails, it's * guaranteed that the timer is not queued anywhere and not * running on the local CPU. */ - if (likely(del_timer(&dwork->timer))) + if (likely(timer_delete(&dwork->timer))) return 1; } @@ -3069,7 +3069,7 @@ __acquires(&pool->lock) break; } - del_timer_sync(&pool->mayday_timer); + timer_delete_sync(&pool->mayday_timer); raw_spin_lock_irq(&pool->lock); /* * This is necessary even after a new worker was just successfully @@ -4281,7 +4281,7 @@ EXPORT_SYMBOL_GPL(flush_work); bool flush_delayed_work(struct delayed_work *dwork) { local_irq_disable(); - if (del_timer_sync(&dwork->timer)) + if (timer_delete_sync(&dwork->timer)) __queue_work(dwork->cpu, dwork->wq, &dwork->work); local_irq_enable(); return flush_work(&dwork->work); @@ -4984,9 +4984,9 @@ static void put_unbound_pool(struct worker_pool *pool) reap_dying_workers(&cull_list); /* shut down the timers */ - del_timer_sync(&pool->idle_timer); + timer_delete_sync(&pool->idle_timer); cancel_work_sync(&pool->idle_cull_work); - del_timer_sync(&pool->mayday_timer); + timer_delete_sync(&pool->mayday_timer); /* RCU protected to allow dereferences from get_work_pool() */ call_rcu(&pool->rcu, rcu_free_pool); @@ -7637,7 +7637,7 @@ notrace void wq_watchdog_touch(int cpu) static void wq_watchdog_set_thresh(unsigned long thresh) { wq_watchdog_thresh = 0; - del_timer_sync(&wq_watchdog_timer); + timer_delete_sync(&wq_watchdog_timer); if (thresh) { wq_watchdog_thresh = thresh;
diff --git a/lib/Kconfig b/lib/Kconfig index 61cce06..6c1b8f1 100644 --- a/lib/Kconfig +++ b/lib/Kconfig
@@ -139,27 +139,22 @@ source "lib/crypto/Kconfig" config CRC_CCITT - tristate "CRC-CCITT functions" + tristate help - This option is provided for the case where no in-kernel-tree - modules require CRC-CCITT functions, but a module built outside - the kernel tree does. Such modules that use library CRC-CCITT - functions require M here. + The CRC-CCITT library functions. Select this if your module uses any + of the functions from <linux/crc-ccitt.h>. config CRC16 - tristate "CRC16 functions" + tristate help - This option is provided for the case where no in-kernel-tree - modules require CRC16 functions, but a module built outside - the kernel tree does. Such modules that use library CRC16 - functions require M here. + The CRC16 library functions. Select this if your module uses any of + the functions from <linux/crc16.h>. config CRC_T10DIF - tristate "CRC calculation for the T10 Data Integrity Field" + tristate help - This option is only needed if a module that's not in the - kernel tree needs to calculate CRC checks for use with the - SCSI data integrity subsystem. + The CRC-T10DIF library functions. Select this if your module uses + any of the functions from <linux/crc-t10dif.h>. config ARCH_HAS_CRC_T10DIF bool @@ -169,22 +164,17 @@ default CRC_T10DIF if ARCH_HAS_CRC_T10DIF && CRC_OPTIMIZATIONS config CRC_ITU_T - tristate "CRC ITU-T V.41 functions" + tristate help - This option is provided for the case where no in-kernel-tree - modules require CRC ITU-T V.41 functions, but a module built outside - the kernel tree does. Such modules that use library CRC ITU-T V.41 - functions require M here. + The CRC-ITU-T library functions. Select this if your module uses + any of the functions from <linux/crc-itu-t.h>. config CRC32 - tristate "CRC32/CRC32c functions" - default y + tristate select BITREVERSE help - This option is provided for the case where no in-kernel-tree - modules require CRC32/CRC32c functions, but a module built outside - the kernel tree does. Such modules that use library CRC32/CRC32c - functions require M here. + The CRC32 library functions. Select this if your module uses any of + the functions from <linux/crc32.h> or <linux/crc32c.h>. config ARCH_HAS_CRC32 bool @@ -195,6 +185,9 @@ config CRC64 tristate + help + The CRC64 library functions. Select this if your module uses any of + the functions from <linux/crc64.h>. config ARCH_HAS_CRC64 bool @@ -205,19 +198,21 @@ config CRC4 tristate + help + The CRC4 library functions. Select this if your module uses any of + the functions from <linux/crc4.h>. config CRC7 tristate - -config LIBCRC32C - tristate - select CRC32 help - This option just selects CRC32 and is provided for compatibility - purposes until the users are updated to select CRC32 directly. + The CRC7 library functions. Select this if your module uses any of + the functions from <linux/crc7.h>. config CRC8 tristate + help + The CRC8 library functions. Select this if your module uses any of + the functions from <linux/crc8.h>. config CRC_OPTIMIZATIONS bool "Enable optimized CRC implementations" if EXPERT
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index df9587a..9fe4d8d 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug
@@ -335,12 +335,12 @@ Compress the debug information using zlib. Requires GCC 5.0+ or Clang 5.0+, binutils 2.26+, and zlib. - Users of dpkg-deb via scripts/package/builddeb may find an increase in + Users of dpkg-deb via debian/rules may find an increase in size of their debug .deb packages with this config set, due to the debug info being compressed with zlib, then the object files being recompressed with a different compression scheme. But this is still - preferable to setting $KDEB_COMPRESS to "none" which would be even - larger. + preferable to setting KDEB_COMPRESS or DPKG_DEB_COMPRESSOR_TYPE to + "none" which would be even larger. config DEBUG_INFO_COMPRESSED_ZSTD bool "Compress debugging information with zstd" @@ -473,7 +473,6 @@ config HEADERS_INSTALL bool "Install uapi headers to usr/include" - depends on !UML help This option will install uapi headers (headers exported to user-space) into the usr/include directory for use during the kernel build.
diff --git a/lib/sg_split.c b/lib/sg_split.c index 60a0bab..0f89aab 100644 --- a/lib/sg_split.c +++ b/lib/sg_split.c
@@ -88,8 +88,6 @@ static void sg_split_phys(struct sg_splitter *splitters, const int nb_splits) if (!j) { out_sg->offset += split->skip_sg0; out_sg->length -= split->skip_sg0; - } else { - out_sg->offset = 0; } sg_dma_address(out_sg) = 0; sg_dma_len(out_sg) = 0;
diff --git a/lib/sort.c b/lib/sort.c index 8e73dc5..5236399 100644 --- a/lib/sort.c +++ b/lib/sort.c
@@ -186,36 +186,13 @@ static size_t parent(size_t i, unsigned int lsbit, size_t size) return i / 2; } -/** - * sort_r - sort an array of elements - * @base: pointer to data to sort - * @num: number of elements - * @size: size of each element - * @cmp_func: pointer to comparison function - * @swap_func: pointer to swap function or NULL - * @priv: third argument passed to comparison function - * - * This function does a heapsort on the given array. You may provide - * a swap_func function if you need to do something more than a memory - * copy (e.g. fix up pointers or auxiliary data), but the built-in swap - * avoids a slow retpoline and so is significantly faster. - * - * The comparison function must adhere to specific mathematical - * properties to ensure correct and stable sorting: - * - Antisymmetry: cmp_func(a, b) must return the opposite sign of - * cmp_func(b, a). - * - Transitivity: if cmp_func(a, b) <= 0 and cmp_func(b, c) <= 0, then - * cmp_func(a, c) <= 0. - * - * Sorting time is O(n log n) both on average and worst-case. While - * quicksort is slightly faster on average, it suffers from exploitable - * O(n*n) worst-case behavior and extra memory requirements that make - * it less suitable for kernel use. - */ -void sort_r(void *base, size_t num, size_t size, - cmp_r_func_t cmp_func, - swap_r_func_t swap_func, - const void *priv) +#include <linux/sched.h> + +static void __sort_r(void *base, size_t num, size_t size, + cmp_r_func_t cmp_func, + swap_r_func_t swap_func, + const void *priv, + bool may_schedule) { /* pre-scale counters for performance */ size_t n = num * size, a = (num/2) * size; @@ -286,6 +263,9 @@ void sort_r(void *base, size_t num, size_t size, b = parent(b, lsbit, size); do_swap(base + b, base + c, size, swap_func, priv); } + + if (may_schedule) + cond_resched(); } n -= size; @@ -293,8 +273,63 @@ void sort_r(void *base, size_t num, size_t size, if (n == size * 2 && do_cmp(base, base + size, cmp_func, priv) > 0) do_swap(base, base + size, size, swap_func, priv); } + +/** + * sort_r - sort an array of elements + * @base: pointer to data to sort + * @num: number of elements + * @size: size of each element + * @cmp_func: pointer to comparison function + * @swap_func: pointer to swap function or NULL + * @priv: third argument passed to comparison function + * + * This function does a heapsort on the given array. You may provide + * a swap_func function if you need to do something more than a memory + * copy (e.g. fix up pointers or auxiliary data), but the built-in swap + * avoids a slow retpoline and so is significantly faster. + * + * The comparison function must adhere to specific mathematical + * properties to ensure correct and stable sorting: + * - Antisymmetry: cmp_func(a, b) must return the opposite sign of + * cmp_func(b, a). + * - Transitivity: if cmp_func(a, b) <= 0 and cmp_func(b, c) <= 0, then + * cmp_func(a, c) <= 0. + * + * Sorting time is O(n log n) both on average and worst-case. While + * quicksort is slightly faster on average, it suffers from exploitable + * O(n*n) worst-case behavior and extra memory requirements that make + * it less suitable for kernel use. + */ +void sort_r(void *base, size_t num, size_t size, + cmp_r_func_t cmp_func, + swap_r_func_t swap_func, + const void *priv) +{ + __sort_r(base, num, size, cmp_func, swap_func, priv, false); +} EXPORT_SYMBOL(sort_r); +/** + * sort_r_nonatomic - sort an array of elements, with cond_resched + * @base: pointer to data to sort + * @num: number of elements + * @size: size of each element + * @cmp_func: pointer to comparison function + * @swap_func: pointer to swap function or NULL + * @priv: third argument passed to comparison function + * + * Same as sort_r, but preferred for larger arrays as it does a periodic + * cond_resched(). + */ +void sort_r_nonatomic(void *base, size_t num, size_t size, + cmp_r_func_t cmp_func, + swap_r_func_t swap_func, + const void *priv) +{ + __sort_r(base, num, size, cmp_func, swap_func, priv, true); +} +EXPORT_SYMBOL(sort_r_nonatomic); + void sort(void *base, size_t num, size_t size, cmp_func_t cmp_func, swap_func_t swap_func) @@ -304,6 +339,19 @@ void sort(void *base, size_t num, size_t size, .swap = swap_func, }; - return sort_r(base, num, size, _CMP_WRAPPER, SWAP_WRAPPER, &w); + return __sort_r(base, num, size, _CMP_WRAPPER, SWAP_WRAPPER, &w, false); } EXPORT_SYMBOL(sort); + +void sort_nonatomic(void *base, size_t num, size_t size, + cmp_func_t cmp_func, + swap_func_t swap_func) +{ + struct wrapper w = { + .cmp = cmp_func, + .swap = swap_func, + }; + + return __sort_r(base, num, size, _CMP_WRAPPER, SWAP_WRAPPER, &w, true); +} +EXPORT_SYMBOL(sort_nonatomic);
diff --git a/lib/vdso/datastore.c b/lib/vdso/datastore.c index c715e21..3693c6c 100644 --- a/lib/vdso/datastore.c +++ b/lib/vdso/datastore.c
@@ -99,7 +99,8 @@ const struct vm_special_mapping vdso_vvar_mapping = { struct vm_area_struct *vdso_install_vvar_mapping(struct mm_struct *mm, unsigned long addr) { return _install_special_mapping(mm, addr, VDSO_NR_PAGES * PAGE_SIZE, - VM_READ | VM_MAYREAD | VM_IO | VM_DONTDUMP | VM_PFNMAP, + VM_READ | VM_MAYREAD | VM_IO | VM_DONTDUMP | + VM_PFNMAP | VM_SEALED_SYSMAP, &vdso_vvar_mapping); }
diff --git a/lib/vsprintf.c b/lib/vsprintf.c index abf40eb..0169985 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c
@@ -1699,8 +1699,12 @@ char *escaped_string(char *buf, char *end, u8 *addr, struct printf_spec spec, return buf; } +#pragma GCC diagnostic push +#ifndef __clang__ +#pragma GCC diagnostic ignored "-Wsuggest-attribute=format" +#endif static char *va_format(char *buf, char *end, struct va_format *va_fmt, - struct printf_spec spec, const char *fmt) + struct printf_spec spec) { va_list va; @@ -1713,6 +1717,7 @@ static char *va_format(char *buf, char *end, struct va_format *va_fmt, return buf; } +#pragma GCC diagnostic pop static noinline_for_stack char *uuid_string(char *buf, char *end, const u8 *addr, @@ -2466,7 +2471,7 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr, case 'U': return uuid_string(buf, end, ptr, spec, fmt); case 'V': - return va_format(buf, end, ptr, spec, fmt); + return va_format(buf, end, ptr, spec); case 'K': return restricted_pointer(buf, end, ptr, spec); case 'N':
diff --git a/mm/Kconfig b/mm/Kconfig index d3fb376..e113f71 100644 --- a/mm/Kconfig +++ b/mm/Kconfig
@@ -201,7 +201,7 @@ config SLUB_TINY bool "Configure for minimal memory footprint" - depends on EXPERT + depends on EXPERT && !COMPILE_TEST select SLAB_MERGE_DEFAULT help Configures the slab allocator in a way to achieve minimal memory
diff --git a/mm/backing-dev.c b/mm/backing-dev.c index e61bbb1..783904d 100644 --- a/mm/backing-dev.c +++ b/mm/backing-dev.c
@@ -1151,7 +1151,7 @@ static void bdi_remove_from_list(struct backing_dev_info *bdi) void bdi_unregister(struct backing_dev_info *bdi) { - del_timer_sync(&bdi->laptop_mode_wb_timer); + timer_delete_sync(&bdi->laptop_mode_wb_timer); /* make sure nobody finds us on the bdi_list anymore */ bdi_remove_from_list(bdi);
diff --git a/mm/damon/core.c b/mm/damon/core.c index fc1eba3..f0c1676 100644 --- a/mm/damon/core.c +++ b/mm/damon/core.c
@@ -76,14 +76,13 @@ int damon_register_ops(struct damon_operations *ops) if (ops->id >= NR_DAMON_OPS) return -EINVAL; + mutex_lock(&damon_ops_lock); /* Fail for already registered ops */ - if (__damon_is_registered_ops(ops->id)) { + if (__damon_is_registered_ops(ops->id)) err = -EINVAL; - goto out; - } - damon_registered_ops[ops->id] = *ops; -out: + else + damon_registered_ops[ops->id] = *ops; mutex_unlock(&damon_ops_lock); return err; }
diff --git a/mm/hugetlb.c b/mm/hugetlb.c index 6fccfe6..39f92aa 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c
@@ -5179,7 +5179,7 @@ static const struct ctl_table hugetlb_table[] = { }, }; -static void hugetlb_sysctl_init(void) +static void __init hugetlb_sysctl_init(void) { register_sysctl_init("vm", hugetlb_table); }
diff --git a/mm/kasan/kasan_test_c.c b/mm/kasan/kasan_test_c.c index 59d6734..3ea3178 100644 --- a/mm/kasan/kasan_test_c.c +++ b/mm/kasan/kasan_test_c.c
@@ -1073,14 +1073,11 @@ static void kmem_cache_rcu_uaf(struct kunit *test) kmem_cache_destroy(cache); } -static void empty_cache_ctor(void *object) { } - static void kmem_cache_double_destroy(struct kunit *test) { struct kmem_cache *cache; - /* Provide a constructor to prevent cache merging. */ - cache = kmem_cache_create("test_cache", 200, 0, 0, empty_cache_ctor); + cache = kmem_cache_create("test_cache", 200, 0, SLAB_NO_MERGE, NULL); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, cache); kmem_cache_destroy(cache); KUNIT_EXPECT_KASAN_FAIL(test, kmem_cache_destroy(cache));
diff --git a/mm/memblock.c b/mm/memblock.c index 2841544..0a53db4d 100644 --- a/mm/memblock.c +++ b/mm/memblock.c
@@ -2167,6 +2167,9 @@ static unsigned long __init __free_memory_core(phys_addr_t start, unsigned long start_pfn = PFN_UP(start); unsigned long end_pfn = PFN_DOWN(end); + if (!IS_ENABLED(CONFIG_HIGHMEM) && end_pfn > max_low_pfn) + end_pfn = max_low_pfn; + if (start_pfn >= end_pfn) return 0;
diff --git a/mm/memory.c b/mm/memory.c index 6ea3551e..2d8c265f 100644 --- a/mm/memory.c +++ b/mm/memory.c
@@ -6670,6 +6670,7 @@ static inline void pfnmap_args_setup(struct follow_pfnmap_args *args, args->lock = lock; args->ptep = ptep; args->pfn = pfn_base + ((args->address & ~addr_mask) >> PAGE_SHIFT); + args->addr_mask = addr_mask; args->pgprot = pgprot; args->writable = writable; args->special = special;
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index 7540186..8305483 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c
@@ -1813,21 +1813,15 @@ static void do_migrate_range(unsigned long start_pfn, unsigned long end_pfn) page = pfn_to_page(pfn); folio = page_folio(page); - /* - * No reference or lock is held on the folio, so it might - * be modified concurrently (e.g. split). As such, - * folio_nr_pages() may read garbage. This is fine as the outer - * loop will revisit the split folio later. - */ - if (folio_test_large(folio)) - pfn = folio_pfn(folio) + folio_nr_pages(folio) - 1; - if (!folio_try_get(folio)) continue; if (unlikely(page_folio(page) != folio)) goto put_folio; + if (folio_test_large(folio)) + pfn = folio_pfn(folio) + folio_nr_pages(folio) - 1; + if (folio_contain_hwpoisoned_page(folio)) { if (WARN_ON(folio_test_lru(folio))) folio_isolate_lru(folio);
diff --git a/mm/mm_init.c b/mm/mm_init.c index a38a190..84f14fa 100644 --- a/mm/mm_init.c +++ b/mm/mm_init.c
@@ -984,19 +984,19 @@ static void __init memmap_init(void) } } -#ifdef CONFIG_SPARSEMEM /* * Initialize the memory map for hole in the range [memory_end, - * section_end]. + * section_end] for SPARSEMEM and in the range [memory_end, memmap_end] + * for FLATMEM. * Append the pages in this hole to the highest zone in the last * node. - * The call to init_unavailable_range() is outside the ifdef to - * silence the compiler warining about zone_id set but not used; - * for FLATMEM it is a nop anyway */ +#ifdef CONFIG_SPARSEMEM end_pfn = round_up(end_pfn, PAGES_PER_SECTION); - if (hole_pfn < end_pfn) +#else + end_pfn = round_up(end_pfn, MAX_ORDER_NR_PAGES); #endif + if (hole_pfn < end_pfn) init_unavailable_range(hole_pfn, end_pfn, zone_id, nid); }
diff --git a/mm/mremap.c b/mm/mremap.c index 0865387..7db9da6 100644 --- a/mm/mremap.c +++ b/mm/mremap.c
@@ -1561,11 +1561,12 @@ static unsigned long expand_vma_in_place(struct vma_remap_struct *vrm) * adjacent to the expanded vma and otherwise * compatible. */ - vma = vrm->vma = vma_merge_extend(&vmi, vma, vrm->delta); + vma = vma_merge_extend(&vmi, vma, vrm->delta); if (!vma) { vrm_uncharge(vrm); return -ENOMEM; } + vrm->vma = vma; vrm_stat_account(vrm, vrm->delta);
diff --git a/mm/page-writeback.c b/mm/page-writeback.c index 18456dd..c81624b 100644 --- a/mm/page-writeback.c +++ b/mm/page-writeback.c
@@ -640,7 +640,7 @@ int wb_domain_init(struct wb_domain *dom, gfp_t gfp) #ifdef CONFIG_CGROUP_WRITEBACK void wb_domain_exit(struct wb_domain *dom) { - del_timer_sync(&dom->period_timer); + timer_delete_sync(&dom->period_timer); fprop_global_destroy(&dom->completions); } #endif @@ -2229,7 +2229,7 @@ void laptop_sync_completion(void) rcu_read_lock(); list_for_each_entry_rcu(bdi, &bdi_list, bdi_list) - del_timer(&bdi->laptop_mode_wb_timer); + timer_delete(&bdi->laptop_mode_wb_timer); rcu_read_unlock(); }
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index f51aa60..fd6b865 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c
@@ -1593,7 +1593,7 @@ static __always_inline void page_del_and_expand(struct zone *zone, static void check_new_page_bad(struct page *page) { - if (unlikely(page->flags & __PG_HWPOISON)) { + if (unlikely(PageHWPoison(page))) { /* Don't complain about hwpoisoned pages */ if (PageBuddy(page)) __ClearPageBuddy(page); @@ -4604,8 +4604,8 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order, goto retry; /* Reclaim/compaction failed to prevent the fallback */ - if (defrag_mode) { - alloc_flags &= ALLOC_NOFRAGMENT; + if (defrag_mode && (alloc_flags & ALLOC_NOFRAGMENT)) { + alloc_flags &= ~ALLOC_NOFRAGMENT; goto retry; } @@ -7385,6 +7385,9 @@ struct page *try_alloc_pages_noprof(int nid, unsigned int order) /* Unlike regular alloc_pages() there is no __alloc_pages_slowpath(). */ + if (page) + set_page_refcounted(page); + if (memcg_kmem_online() && page && unlikely(__memcg_kmem_charge_page(page, alloc_gfp, order) != 0)) { free_pages_nolock(page, order);
diff --git a/mm/page_isolation.c b/mm/page_isolation.c index a051a29..b2fc526 100644 --- a/mm/page_isolation.c +++ b/mm/page_isolation.c
@@ -83,7 +83,14 @@ static struct page *has_unmovable_pages(unsigned long start_pfn, unsigned long e unsigned int skip_pages; if (PageHuge(page)) { - if (!hugepage_migration_supported(folio_hstate(folio))) + struct hstate *h; + + /* + * The huge page may be freed so can not + * use folio_hstate() directly. + */ + h = size_to_hstate(folio_size(folio)); + if (h && !hugepage_migration_supported(h)) return page; } else if (!folio_test_lru(folio) && !__folio_test_movable(folio)) { return page;
diff --git a/mm/zswap.c b/mm/zswap.c index 0dcc54e..204fb59 100644 --- a/mm/zswap.c +++ b/mm/zswap.c
@@ -883,18 +883,32 @@ static int zswap_cpu_comp_dead(unsigned int cpu, struct hlist_node *node) { struct zswap_pool *pool = hlist_entry(node, struct zswap_pool, node); struct crypto_acomp_ctx *acomp_ctx = per_cpu_ptr(pool->acomp_ctx, cpu); + struct acomp_req *req; + struct crypto_acomp *acomp; + u8 *buffer; + + if (IS_ERR_OR_NULL(acomp_ctx)) + return 0; mutex_lock(&acomp_ctx->mutex); - if (!IS_ERR_OR_NULL(acomp_ctx)) { - if (!IS_ERR_OR_NULL(acomp_ctx->req)) - acomp_request_free(acomp_ctx->req); - acomp_ctx->req = NULL; - if (!IS_ERR_OR_NULL(acomp_ctx->acomp)) - crypto_free_acomp(acomp_ctx->acomp); - kfree(acomp_ctx->buffer); - } + req = acomp_ctx->req; + acomp = acomp_ctx->acomp; + buffer = acomp_ctx->buffer; + acomp_ctx->req = NULL; + acomp_ctx->acomp = NULL; + acomp_ctx->buffer = NULL; mutex_unlock(&acomp_ctx->mutex); + /* + * Do the actual freeing after releasing the mutex to avoid subtle + * locking dependencies causing deadlocks. + */ + if (!IS_ERR_OR_NULL(req)) + acomp_request_free(req); + if (!IS_ERR_OR_NULL(acomp)) + crypto_free_acomp(acomp); + kfree(buffer); + return 0; }
diff --git a/net/9p/client.c b/net/9p/client.c index 09f8ced..61461b9 100644 --- a/net/9p/client.c +++ b/net/9p/client.c
@@ -1548,7 +1548,8 @@ p9_client_read_once(struct p9_fid *fid, u64 offset, struct iov_iter *to, struct p9_client *clnt = fid->clnt; struct p9_req_t *req; int count = iov_iter_count(to); - int rsize, received, non_zc = 0; + u32 rsize, received; + bool non_zc = false; char *dataptr; *err = 0; @@ -1571,7 +1572,7 @@ p9_client_read_once(struct p9_fid *fid, u64 offset, struct iov_iter *to, 0, 11, "dqd", fid->fid, offset, rsize); } else { - non_zc = 1; + non_zc = true; req = p9_client_rpc(clnt, P9_TREAD, "dqd", fid->fid, offset, rsize); } @@ -1592,11 +1593,13 @@ p9_client_read_once(struct p9_fid *fid, u64 offset, struct iov_iter *to, return 0; } if (rsize < received) { - pr_err("bogus RREAD count (%d > %d)\n", received, rsize); - received = rsize; + pr_err("bogus RREAD count (%u > %u)\n", received, rsize); + *err = -EIO; + p9_req_put(clnt, req); + return 0; } - p9_debug(P9_DEBUG_9P, "<<< RREAD count %d\n", received); + p9_debug(P9_DEBUG_9P, "<<< RREAD count %u\n", received); if (non_zc) { int n = copy_to_iter(dataptr, received, to); @@ -1623,9 +1626,9 @@ p9_client_write(struct p9_fid *fid, u64 offset, struct iov_iter *from, int *err) *err = 0; while (iov_iter_count(from)) { - int count = iov_iter_count(from); - int rsize = fid->iounit; - int written; + size_t count = iov_iter_count(from); + u32 rsize = fid->iounit; + u32 written; if (!rsize || rsize > clnt->msize - P9_IOHDRSZ) rsize = clnt->msize - P9_IOHDRSZ; @@ -1633,7 +1636,7 @@ p9_client_write(struct p9_fid *fid, u64 offset, struct iov_iter *from, int *err) if (count < rsize) rsize = count; - p9_debug(P9_DEBUG_9P, ">>> TWRITE fid %d offset %llu count %d (/%d)\n", + p9_debug(P9_DEBUG_9P, ">>> TWRITE fid %d offset %llu count %u (/%zu)\n", fid->fid, offset, rsize, count); /* Don't bother zerocopy for small IO (< 1024) */ @@ -1659,11 +1662,14 @@ p9_client_write(struct p9_fid *fid, u64 offset, struct iov_iter *from, int *err) break; } if (rsize < written) { - pr_err("bogus RWRITE count (%d > %d)\n", written, rsize); - written = rsize; + pr_err("bogus RWRITE count (%u > %u)\n", written, rsize); + *err = -EIO; + iov_iter_revert(from, count - iov_iter_count(from)); + p9_req_put(clnt, req); + break; } - p9_debug(P9_DEBUG_9P, "<<< RWRITE count %d\n", written); + p9_debug(P9_DEBUG_9P, "<<< RWRITE count %u\n", written); p9_req_put(clnt, req); iov_iter_revert(from, count - written - iov_iter_count(from)); @@ -1712,7 +1718,7 @@ p9_client_write_subreq(struct netfs_io_subrequest *subreq) if (written > len) { pr_err("bogus RWRITE count (%d > %u)\n", written, len); - written = len; + written = -EIO; } p9_debug(P9_DEBUG_9P, "<<< RWRITE count %d\n", len); @@ -2098,7 +2104,8 @@ EXPORT_SYMBOL_GPL(p9_client_xattrcreate); int p9_client_readdir(struct p9_fid *fid, char *data, u32 count, u64 offset) { - int err, rsize, non_zc = 0; + int err, non_zc = 0; + u32 rsize; struct p9_client *clnt; struct p9_req_t *req; char *dataptr; @@ -2107,7 +2114,7 @@ int p9_client_readdir(struct p9_fid *fid, char *data, u32 count, u64 offset) iov_iter_kvec(&to, ITER_DEST, &kv, 1, count); - p9_debug(P9_DEBUG_9P, ">>> TREADDIR fid %d offset %llu count %d\n", + p9_debug(P9_DEBUG_9P, ">>> TREADDIR fid %d offset %llu count %u\n", fid->fid, offset, count); clnt = fid->clnt; @@ -2142,11 +2149,12 @@ int p9_client_readdir(struct p9_fid *fid, char *data, u32 count, u64 offset) goto free_and_error; } if (rsize < count) { - pr_err("bogus RREADDIR count (%d > %d)\n", count, rsize); - count = rsize; + pr_err("bogus RREADDIR count (%u > %u)\n", count, rsize); + err = -EIO; + goto free_and_error; } - p9_debug(P9_DEBUG_9P, "<<< RREADDIR count %d\n", count); + p9_debug(P9_DEBUG_9P, "<<< RREADDIR count %u\n", count); if (non_zc) memmove(data, dataptr, count);
diff --git a/net/9p/error.c b/net/9p/error.c index 8da7444..8ba8afc 100644 --- a/net/9p/error.c +++ b/net/9p/error.c
@@ -16,6 +16,7 @@ #include <linux/list.h> #include <linux/jhash.h> #include <linux/errno.h> +#include <linux/hashtable.h> #include <net/9p/9p.h> /** @@ -33,8 +34,8 @@ struct errormap { struct hlist_node list; }; -#define ERRHASHSZ 32 -static struct hlist_head hash_errmap[ERRHASHSZ]; +#define ERRHASH_BITS 5 +static DEFINE_HASHTABLE(hash_errmap, ERRHASH_BITS); /* FixMe - reduce to a reasonable size */ static struct errormap errmap[] = { @@ -176,18 +177,14 @@ static struct errormap errmap[] = { int p9_error_init(void) { struct errormap *c; - int bucket; - - /* initialize hash table */ - for (bucket = 0; bucket < ERRHASHSZ; bucket++) - INIT_HLIST_HEAD(&hash_errmap[bucket]); + u32 hash; /* load initial error map into hash table */ for (c = errmap; c->name; c++) { c->namelen = strlen(c->name); - bucket = jhash(c->name, c->namelen, 0) % ERRHASHSZ; + hash = jhash(c->name, c->namelen, 0); INIT_HLIST_NODE(&c->list); - hlist_add_head(&c->list, &hash_errmap[bucket]); + hash_add(hash_errmap, &c->list, hash); } return 1; @@ -205,12 +202,12 @@ int p9_errstr2errno(char *errstr, int len) { int errno; struct errormap *c; - int bucket; + u32 hash; errno = 0; c = NULL; - bucket = jhash(errstr, len, 0) % ERRHASHSZ; - hlist_for_each_entry(c, &hash_errmap[bucket], list) { + hash = jhash(errstr, len, 0); + hash_for_each_possible(hash_errmap, c, list, hash) { if (c->namelen == len && !memcmp(c->name, errstr, len)) { errno = c->val; break;
diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c index 196060d..339ec4e 100644 --- a/net/9p/trans_fd.c +++ b/net/9p/trans_fd.c
@@ -11,6 +11,7 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include <linux/in.h> +#include <linux/in6.h> #include <linux/module.h> #include <linux/net.h> #include <linux/ipv6.h> @@ -191,12 +192,13 @@ static void p9_conn_cancel(struct p9_conn *m, int err) spin_lock(&m->req_lock); - if (m->err) { + if (READ_ONCE(m->err)) { spin_unlock(&m->req_lock); return; } - m->err = err; + WRITE_ONCE(m->err, err); + ASSERT_EXCLUSIVE_WRITER(m->err); list_for_each_entry_safe(req, rtmp, &m->req_list, req_list) { list_move(&req->req_list, &cancel_list); @@ -283,7 +285,7 @@ static void p9_read_work(struct work_struct *work) m = container_of(work, struct p9_conn, rq); - if (m->err < 0) + if (READ_ONCE(m->err) < 0) return; p9_debug(P9_DEBUG_TRANS, "start mux %p pos %zd\n", m, m->rc.offset); @@ -450,7 +452,7 @@ static void p9_write_work(struct work_struct *work) m = container_of(work, struct p9_conn, wq); - if (m->err < 0) { + if (READ_ONCE(m->err) < 0) { clear_bit(Wworksched, &m->wsched); return; } @@ -622,7 +624,7 @@ static void p9_poll_mux(struct p9_conn *m) __poll_t n; int err = -ECONNRESET; - if (m->err < 0) + if (READ_ONCE(m->err) < 0) return; n = p9_fd_poll(m->client, NULL, &err); @@ -665,6 +667,7 @@ static void p9_poll_mux(struct p9_conn *m) static int p9_fd_request(struct p9_client *client, struct p9_req_t *req) { __poll_t n; + int err; struct p9_trans_fd *ts = client->trans; struct p9_conn *m = &ts->conn; @@ -673,9 +676,10 @@ static int p9_fd_request(struct p9_client *client, struct p9_req_t *req) spin_lock(&m->req_lock); - if (m->err < 0) { + err = READ_ONCE(m->err); + if (err < 0) { spin_unlock(&m->req_lock); - return m->err; + return err; } WRITE_ONCE(req->status, REQ_STATUS_UNSENT); @@ -954,64 +958,55 @@ static void p9_fd_close(struct p9_client *client) kfree(ts); } -/* - * stolen from NFS - maybe should be made a generic function? - */ -static inline int valid_ipaddr4(const char *buf) -{ - int rc, count, in[4]; - - rc = sscanf(buf, "%d.%d.%d.%d", &in[0], &in[1], &in[2], &in[3]); - if (rc != 4) - return -EINVAL; - for (count = 0; count < 4; count++) { - if (in[count] > 255) - return -EINVAL; - } - return 0; -} - static int p9_bind_privport(struct socket *sock) { - struct sockaddr_in cl; + struct sockaddr_storage stor = { 0 }; int port, err = -EINVAL; - memset(&cl, 0, sizeof(cl)); - cl.sin_family = AF_INET; - cl.sin_addr.s_addr = htonl(INADDR_ANY); + stor.ss_family = sock->ops->family; + if (stor.ss_family == AF_INET) + ((struct sockaddr_in *)&stor)->sin_addr.s_addr = htonl(INADDR_ANY); + else + ((struct sockaddr_in6 *)&stor)->sin6_addr = in6addr_any; for (port = p9_ipport_resv_max; port >= p9_ipport_resv_min; port--) { - cl.sin_port = htons((ushort)port); - err = kernel_bind(sock, (struct sockaddr *)&cl, sizeof(cl)); + if (stor.ss_family == AF_INET) + ((struct sockaddr_in *)&stor)->sin_port = htons((ushort)port); + else + ((struct sockaddr_in6 *)&stor)->sin6_port = htons((ushort)port); + err = kernel_bind(sock, (struct sockaddr *)&stor, sizeof(stor)); if (err != -EADDRINUSE) break; } return err; } - static int p9_fd_create_tcp(struct p9_client *client, const char *addr, char *args) { int err; + char port_str[6]; struct socket *csocket; - struct sockaddr_in sin_server; + struct sockaddr_storage stor = { 0 }; struct p9_fd_opts opts; err = parse_opts(args, &opts); if (err < 0) return err; - if (addr == NULL || valid_ipaddr4(addr) < 0) + if (!addr) return -EINVAL; + sprintf(port_str, "%u", opts.port); + err = inet_pton_with_scope(current->nsproxy->net_ns, AF_UNSPEC, addr, + port_str, &stor); + if (err < 0) + return err; + csocket = NULL; client->trans_opts.tcp.port = opts.port; client->trans_opts.tcp.privport = opts.privport; - sin_server.sin_family = AF_INET; - sin_server.sin_addr.s_addr = in_aton(addr); - sin_server.sin_port = htons(opts.port); - err = __sock_create(current->nsproxy->net_ns, PF_INET, + err = __sock_create(current->nsproxy->net_ns, stor.ss_family, SOCK_STREAM, IPPROTO_TCP, &csocket, 1); if (err) { pr_err("%s (%d): problem creating socket\n", @@ -1030,8 +1025,8 @@ p9_fd_create_tcp(struct p9_client *client, const char *addr, char *args) } err = READ_ONCE(csocket->ops)->connect(csocket, - (struct sockaddr *)&sin_server, - sizeof(struct sockaddr_in), 0); + (struct sockaddr *)&stor, + sizeof(stor), 0); if (err < 0) { pr_err("%s (%d): problem connecting socket to %s\n", __func__, task_pid_nr(current), addr);
diff --git a/net/appletalk/aarp.c b/net/appletalk/aarp.c index 05cbb3c..9c787e2 100644 --- a/net/appletalk/aarp.c +++ b/net/appletalk/aarp.c
@@ -856,7 +856,7 @@ int __init aarp_proto_init(void) add_timer(&aarp_timer); rc = register_netdevice_notifier(&aarp_notifier); if (rc) { - del_timer_sync(&aarp_timer); + timer_delete_sync(&aarp_timer); unregister_snap_client(aarp_dl); } return rc; @@ -1011,7 +1011,7 @@ const struct seq_operations aarp_seq_ops = { /* General module cleanup. Called from cleanup_module() in ddp.c. */ void aarp_cleanup_module(void) { - del_timer_sync(&aarp_timer); + timer_delete_sync(&aarp_timer); unregister_netdevice_notifier(&aarp_notifier); unregister_snap_client(aarp_dl); aarp_purge();
diff --git a/net/atm/clip.c b/net/atm/clip.c index 42b910c..61b5b70 100644 --- a/net/atm/clip.c +++ b/net/atm/clip.c
@@ -904,7 +904,7 @@ static void atm_clip_exit_noproc(void) /* First, stop the idle timer, so it stops banging * on the table. */ - del_timer_sync(&idle_timer); + timer_delete_sync(&idle_timer); dev = clip_devs; while (dev) {
diff --git a/net/atm/lec.c b/net/atm/lec.c index a948dd4..ded2f0d 100644 --- a/net/atm/lec.c +++ b/net/atm/lec.c
@@ -1302,7 +1302,7 @@ lec_arp_remove(struct lec_priv *priv, struct lec_arp_table *to_remove) return -1; hlist_del(&to_remove->next); - del_timer(&to_remove->timer); + timer_delete(&to_remove->timer); /* * If this is the only MAC connected to this VCC, @@ -1482,7 +1482,7 @@ static void lec_arp_destroy(struct lec_priv *priv) hlist_for_each_entry_safe(entry, next, &priv->lec_arp_empty_ones, next) { - del_timer_sync(&entry->timer); + timer_delete_sync(&entry->timer); lec_arp_clear_vccs(entry); hlist_del(&entry->next); lec_arp_put(entry); @@ -1491,7 +1491,7 @@ static void lec_arp_destroy(struct lec_priv *priv) hlist_for_each_entry_safe(entry, next, &priv->lec_no_forward, next) { - del_timer_sync(&entry->timer); + timer_delete_sync(&entry->timer); lec_arp_clear_vccs(entry); hlist_del(&entry->next); lec_arp_put(entry); @@ -1575,7 +1575,7 @@ static void lec_arp_expire_vcc(struct timer_list *t) struct lec_arp_table *to_remove = from_timer(to_remove, t, timer); struct lec_priv *priv = to_remove->priv; - del_timer(&to_remove->timer); + timer_delete(&to_remove->timer); pr_debug("%p %p: vpi:%d vci:%d\n", to_remove, priv, @@ -1843,16 +1843,16 @@ lec_arp_update(struct lec_priv *priv, const unsigned char *mac_addr, &priv->lec_arp_empty_ones, next) { if (memcmp(entry->atm_addr, atm_addr, ATM_ESA_LEN) == 0) { hlist_del(&entry->next); - del_timer(&entry->timer); + timer_delete(&entry->timer); tmp = lec_arp_find(priv, mac_addr); if (tmp) { - del_timer(&tmp->timer); + timer_delete(&tmp->timer); tmp->status = ESI_FORWARD_DIRECT; memcpy(tmp->atm_addr, atm_addr, ATM_ESA_LEN); tmp->vcc = entry->vcc; tmp->old_push = entry->old_push; tmp->last_used = jiffies; - del_timer(&entry->timer); + timer_delete(&entry->timer); lec_arp_put(entry); entry = tmp; } else { @@ -1883,7 +1883,7 @@ lec_arp_update(struct lec_priv *priv, const unsigned char *mac_addr, /* Temporary, changes before end of function */ } memcpy(entry->atm_addr, atm_addr, ATM_ESA_LEN); - del_timer(&entry->timer); + timer_delete(&entry->timer); for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) { hlist_for_each_entry(tmp, &priv->lec_arp_tables[i], next) { @@ -1946,7 +1946,7 @@ lec_vcc_added(struct lec_priv *priv, const struct atmlec_ioc *ioc_data, entry = make_entry(priv, bus_mac); if (entry == NULL) goto out; - del_timer(&entry->timer); + timer_delete(&entry->timer); memcpy(entry->atm_addr, ioc_data->atm_addr, ATM_ESA_LEN); entry->recv_vcc = vcc; entry->old_recv_push = old_push; @@ -1988,7 +1988,7 @@ lec_vcc_added(struct lec_priv *priv, const struct atmlec_ioc *ioc_data, entry->recv_vcc ? entry->recv_vcc-> vci : 0); found_entry = 1; - del_timer(&entry->timer); + timer_delete(&entry->timer); entry->vcc = vcc; entry->old_push = old_push; if (entry->status == ESI_VC_PENDING) { @@ -2172,7 +2172,7 @@ static void lec_vcc_close(struct lec_priv *priv, struct atm_vcc *vcc) &priv->lec_arp_empty_ones, next) { if (entry->vcc == vcc) { lec_arp_clear_vccs(entry); - del_timer(&entry->timer); + timer_delete(&entry->timer); hlist_del(&entry->next); lec_arp_put(entry); } @@ -2182,7 +2182,7 @@ static void lec_vcc_close(struct lec_priv *priv, struct atm_vcc *vcc) &priv->lec_no_forward, next) { if (entry->recv_vcc == vcc) { lec_arp_clear_vccs(entry); - del_timer(&entry->timer); + timer_delete(&entry->timer); hlist_del(&entry->next); lec_arp_put(entry); } @@ -2215,7 +2215,7 @@ lec_arp_check_empties(struct lec_priv *priv, hlist_for_each_entry_safe(entry, next, &priv->lec_arp_empty_ones, next) { if (vcc == entry->vcc) { - del_timer(&entry->timer); + timer_delete(&entry->timer); ether_addr_copy(entry->mac_addr, src); entry->status = ESI_FORWARD_DIRECT; entry->last_used = jiffies;
diff --git a/net/atm/mpc.c b/net/atm/mpc.c index 12da026..f6b447b 100644 --- a/net/atm/mpc.c +++ b/net/atm/mpc.c
@@ -804,7 +804,7 @@ static int atm_mpoa_mpoad_attach(struct atm_vcc *vcc, int arg) /* This lets us now how our LECs are doing */ err = register_netdevice_notifier(&mpoa_notifier); if (err < 0) { - del_timer(&mpc_timer); + timer_delete(&mpc_timer); return err; } } @@ -1495,7 +1495,7 @@ static void __exit atm_mpoa_cleanup(void) mpc_proc_clean(); - del_timer_sync(&mpc_timer); + timer_delete_sync(&mpc_timer); unregister_netdevice_notifier(&mpoa_notifier); deregister_atm_ioctl(&atm_ioctl_ops);
diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c index 3ee7dba..b790bb9 100644 --- a/net/ax25/af_ax25.c +++ b/net/ax25/af_ax25.c
@@ -1071,11 +1071,11 @@ static int ax25_release(struct socket *sock) } if (ax25_dev) { if (!ax25_dev->device_up) { - del_timer_sync(&ax25->timer); - del_timer_sync(&ax25->t1timer); - del_timer_sync(&ax25->t2timer); - del_timer_sync(&ax25->t3timer); - del_timer_sync(&ax25->idletimer); + timer_delete_sync(&ax25->timer); + timer_delete_sync(&ax25->t1timer); + timer_delete_sync(&ax25->t2timer); + timer_delete_sync(&ax25->t3timer); + timer_delete_sync(&ax25->idletimer); } netdev_put(ax25_dev->dev, &ax25->dev_tracker); ax25_dev_put(ax25_dev);
diff --git a/net/ax25/ax25_ds_timer.c b/net/ax25/ax25_ds_timer.c index c4f8adb..8d9fba0 100644 --- a/net/ax25/ax25_ds_timer.c +++ b/net/ax25/ax25_ds_timer.c
@@ -44,7 +44,7 @@ void ax25_ds_setup_timer(ax25_dev *ax25_dev) void ax25_ds_del_timer(ax25_dev *ax25_dev) { if (ax25_dev) - del_timer(&ax25_dev->dama.slave_timer); + timer_delete(&ax25_dev->dama.slave_timer); } void ax25_ds_set_timer(ax25_dev *ax25_dev)
diff --git a/net/ax25/ax25_subr.c b/net/ax25/ax25_subr.c index 9ff98f4..bff4b20 100644 --- a/net/ax25/ax25_subr.c +++ b/net/ax25/ax25_subr.c
@@ -262,11 +262,11 @@ void ax25_disconnect(ax25_cb *ax25, int reason) ax25_clear_queues(ax25); if (reason == ENETUNREACH) { - del_timer_sync(&ax25->timer); - del_timer_sync(&ax25->t1timer); - del_timer_sync(&ax25->t2timer); - del_timer_sync(&ax25->t3timer); - del_timer_sync(&ax25->idletimer); + timer_delete_sync(&ax25->timer); + timer_delete_sync(&ax25->t1timer); + timer_delete_sync(&ax25->t2timer); + timer_delete_sync(&ax25->t3timer); + timer_delete_sync(&ax25->idletimer); } else { if (ax25->sk && !sock_flag(ax25->sk, SOCK_DESTROY)) ax25_stop_heartbeat(ax25);
diff --git a/net/ax25/ax25_timer.c b/net/ax25/ax25_timer.c index 9f7cb0a..3891a39 100644 --- a/net/ax25/ax25_timer.c +++ b/net/ax25/ax25_timer.c
@@ -65,7 +65,7 @@ void ax25_start_t3timer(ax25_cb *ax25) if (ax25->t3 > 0) mod_timer(&ax25->t3timer, jiffies + ax25->t3); else - del_timer(&ax25->t3timer); + timer_delete(&ax25->t3timer); } void ax25_start_idletimer(ax25_cb *ax25) @@ -73,32 +73,32 @@ void ax25_start_idletimer(ax25_cb *ax25) if (ax25->idle > 0) mod_timer(&ax25->idletimer, jiffies + ax25->idle); else - del_timer(&ax25->idletimer); + timer_delete(&ax25->idletimer); } void ax25_stop_heartbeat(ax25_cb *ax25) { - del_timer(&ax25->timer); + timer_delete(&ax25->timer); } void ax25_stop_t1timer(ax25_cb *ax25) { - del_timer(&ax25->t1timer); + timer_delete(&ax25->t1timer); } void ax25_stop_t2timer(ax25_cb *ax25) { - del_timer(&ax25->t2timer); + timer_delete(&ax25->t2timer); } void ax25_stop_t3timer(ax25_cb *ax25) { - del_timer(&ax25->t3timer); + timer_delete(&ax25->t3timer); } void ax25_stop_idletimer(ax25_cb *ax25) { - del_timer(&ax25->idletimer); + timer_delete(&ax25->idletimer); } int ax25_t1timer_running(ax25_cb *ax25)
diff --git a/net/batman-adv/Kconfig b/net/batman-adv/Kconfig index 860a078..20b3162 100644 --- a/net/batman-adv/Kconfig +++ b/net/batman-adv/Kconfig
@@ -9,7 +9,7 @@ config BATMAN_ADV tristate "B.A.T.M.A.N. Advanced Meshing Protocol" - select LIBCRC32C + select CRC32 help B.A.T.M.A.N. (better approach to mobile ad-hoc networking) is a routing protocol for multi-hop ad-hoc mesh networks. The
diff --git a/net/batman-adv/tp_meter.c b/net/batman-adv/tp_meter.c index 9fb14e40..adbadb4 100644 --- a/net/batman-adv/tp_meter.c +++ b/net/batman-adv/tp_meter.c
@@ -384,13 +384,13 @@ static void batadv_tp_sender_cleanup(struct batadv_priv *bat_priv, atomic_dec(&tp_vars->bat_priv->tp_num); /* kill the timer and remove its reference */ - del_timer_sync(&tp_vars->timer); + timer_delete_sync(&tp_vars->timer); /* the worker might have rearmed itself therefore we kill it again. Note * that if the worker should run again before invoking the following - * del_timer(), it would not re-arm itself once again because the status + * timer_delete(), it would not re-arm itself once again because the status * is OFF now */ - del_timer(&tp_vars->timer); + timer_delete(&tp_vars->timer); batadv_tp_vars_put(tp_vars); }
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c index 707f229..fc5af86 100644 --- a/net/bluetooth/hidp/core.c +++ b/net/bluetooth/hidp/core.c
@@ -433,7 +433,7 @@ static void hidp_set_timer(struct hidp_session *session) static void hidp_del_timer(struct hidp_session *session) { if (session->idle_to > 0) - del_timer_sync(&session->timer); + timer_delete_sync(&session->timer); } static void hidp_process_report(struct hidp_session *session, int type,
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index ad5177e..20ea7db 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c
@@ -254,7 +254,7 @@ static void rfcomm_session_clear_timer(struct rfcomm_session *s) { BT_DBG("session %p state %ld", s, s->state); - del_timer_sync(&s->timer); + timer_delete_sync(&s->timer); } /* ---- RFCOMM DLCs ---- */ @@ -281,7 +281,7 @@ static void rfcomm_dlc_clear_timer(struct rfcomm_dlc *d) { BT_DBG("dlc %p state %ld", d, d->state); - if (del_timer(&d->timer)) + if (timer_delete(&d->timer)) rfcomm_dlc_put(d); }
diff --git a/net/bridge/br_mdb.c b/net/bridge/br_mdb.c index 7e1ad22..722203b 100644 --- a/net/bridge/br_mdb.c +++ b/net/bridge/br_mdb.c
@@ -732,7 +732,7 @@ static int br_mdb_replace_group_sg(const struct br_mdb_config *cfg, mod_timer(&pg->timer, now + brmctx->multicast_membership_interval); else - del_timer(&pg->timer); + timer_delete(&pg->timer); br_mdb_notify(cfg->br->dev, mp, pg, RTM_NEWMDB); @@ -853,7 +853,7 @@ static int br_mdb_add_group_src(const struct br_mdb_config *cfg, cfg->entry->state == MDB_TEMPORARY) mod_timer(&ent->timer, now + br_multicast_gmi(brmctx)); else - del_timer(&ent->timer); + timer_delete(&ent->timer); /* Install a (S, G) forwarding entry for the source. */ err = br_mdb_add_group_src_fwd(cfg, &src->addr, brmctx, extack); @@ -953,7 +953,7 @@ static int br_mdb_replace_group_star_g(const struct br_mdb_config *cfg, mod_timer(&pg->timer, now + brmctx->multicast_membership_interval); else - del_timer(&pg->timer); + timer_delete(&pg->timer); br_mdb_notify(cfg->br->dev, mp, pg, RTM_NEWMDB);
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index b2ae0d2..dcbf058d 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c
@@ -546,7 +546,7 @@ static void br_multicast_fwd_src_add(struct net_bridge_group_src *src) return; /* the kernel is now responsible for removing this S,G */ - del_timer(&sg->timer); + timer_delete(&sg->timer); star_mp = br_mdb_ip_get(src->br, &src->pg->key.addr); if (!star_mp) return; @@ -2015,9 +2015,9 @@ void br_multicast_port_ctx_init(struct net_bridge_port *port, void br_multicast_port_ctx_deinit(struct net_bridge_mcast_port *pmctx) { #if IS_ENABLED(CONFIG_IPV6) - del_timer_sync(&pmctx->ip6_mc_router_timer); + timer_delete_sync(&pmctx->ip6_mc_router_timer); #endif - del_timer_sync(&pmctx->ip4_mc_router_timer); + timer_delete_sync(&pmctx->ip4_mc_router_timer); } int br_multicast_add_port(struct net_bridge_port *port) @@ -2062,7 +2062,7 @@ static void br_multicast_enable(struct bridge_mcast_own_query *query) query->startup_sent = 0; if (try_to_del_timer_sync(&query->timer) >= 0 || - del_timer(&query->timer)) + timer_delete(&query->timer)) mod_timer(&query->timer, jiffies); } @@ -2127,12 +2127,12 @@ static void __br_multicast_disable_port_ctx(struct net_bridge_mcast_port *pmctx) br_multicast_find_del_pg(pmctx->port->br, pg); del |= br_ip4_multicast_rport_del(pmctx); - del_timer(&pmctx->ip4_mc_router_timer); - del_timer(&pmctx->ip4_own_query.timer); + timer_delete(&pmctx->ip4_mc_router_timer); + timer_delete(&pmctx->ip4_own_query.timer); del |= br_ip6_multicast_rport_del(pmctx); #if IS_ENABLED(CONFIG_IPV6) - del_timer(&pmctx->ip6_mc_router_timer); - del_timer(&pmctx->ip6_own_query.timer); + timer_delete(&pmctx->ip6_mc_router_timer); + timer_delete(&pmctx->ip6_own_query.timer); #endif br_multicast_rport_del_notify(pmctx, del); } @@ -4199,15 +4199,15 @@ void br_multicast_open(struct net_bridge *br) static void __br_multicast_stop(struct net_bridge_mcast *brmctx) { - del_timer_sync(&brmctx->ip4_mc_router_timer); - del_timer_sync(&brmctx->ip4_other_query.timer); - del_timer_sync(&brmctx->ip4_other_query.delay_timer); - del_timer_sync(&brmctx->ip4_own_query.timer); + timer_delete_sync(&brmctx->ip4_mc_router_timer); + timer_delete_sync(&brmctx->ip4_other_query.timer); + timer_delete_sync(&brmctx->ip4_other_query.delay_timer); + timer_delete_sync(&brmctx->ip4_own_query.timer); #if IS_ENABLED(CONFIG_IPV6) - del_timer_sync(&brmctx->ip6_mc_router_timer); - del_timer_sync(&brmctx->ip6_other_query.timer); - del_timer_sync(&brmctx->ip6_other_query.delay_timer); - del_timer_sync(&brmctx->ip6_own_query.timer); + timer_delete_sync(&brmctx->ip6_mc_router_timer); + timer_delete_sync(&brmctx->ip6_other_query.timer); + timer_delete_sync(&brmctx->ip6_other_query.delay_timer); + timer_delete_sync(&brmctx->ip6_own_query.timer); #endif } @@ -4384,9 +4384,9 @@ int br_multicast_set_router(struct net_bridge_mcast *brmctx, unsigned long val) case MDB_RTR_TYPE_DISABLED: case MDB_RTR_TYPE_PERM: br_mc_router_state_change(brmctx->br, val == MDB_RTR_TYPE_PERM); - del_timer(&brmctx->ip4_mc_router_timer); + timer_delete(&brmctx->ip4_mc_router_timer); #if IS_ENABLED(CONFIG_IPV6) - del_timer(&brmctx->ip6_mc_router_timer); + timer_delete(&brmctx->ip6_mc_router_timer); #endif brmctx->multicast_router = val; err = 0; @@ -4455,10 +4455,10 @@ int br_multicast_set_port_router(struct net_bridge_mcast_port *pmctx, case MDB_RTR_TYPE_DISABLED: pmctx->multicast_router = MDB_RTR_TYPE_DISABLED; del |= br_ip4_multicast_rport_del(pmctx); - del_timer(&pmctx->ip4_mc_router_timer); + timer_delete(&pmctx->ip4_mc_router_timer); del |= br_ip6_multicast_rport_del(pmctx); #if IS_ENABLED(CONFIG_IPV6) - del_timer(&pmctx->ip6_mc_router_timer); + timer_delete(&pmctx->ip6_mc_router_timer); #endif br_multicast_rport_del_notify(pmctx, del); break; @@ -4470,10 +4470,10 @@ int br_multicast_set_port_router(struct net_bridge_mcast_port *pmctx, break; case MDB_RTR_TYPE_PERM: pmctx->multicast_router = MDB_RTR_TYPE_PERM; - del_timer(&pmctx->ip4_mc_router_timer); + timer_delete(&pmctx->ip4_mc_router_timer); br_ip4_multicast_add_router(brmctx, pmctx); #if IS_ENABLED(CONFIG_IPV6) - del_timer(&pmctx->ip6_mc_router_timer); + timer_delete(&pmctx->ip6_mc_router_timer); #endif br_ip6_multicast_add_router(brmctx, pmctx); break;
diff --git a/net/bridge/br_stp.c b/net/bridge/br_stp.c index 7d27b2e..024210f 100644 --- a/net/bridge/br_stp.c +++ b/net/bridge/br_stp.c
@@ -198,7 +198,7 @@ void br_become_root_bridge(struct net_bridge *br) br->hello_time = br->bridge_hello_time; br->forward_delay = br->bridge_forward_delay; br_topology_change_detection(br); - del_timer(&br->tcn_timer); + timer_delete(&br->tcn_timer); if (br->dev->flags & IFF_UP) { br_config_bpdu_generation(br); @@ -363,7 +363,7 @@ static int br_supersedes_port_info(const struct net_bridge_port *p, static void br_topology_change_acknowledged(struct net_bridge *br) { br->topology_change_detected = 0; - del_timer(&br->tcn_timer); + timer_delete(&br->tcn_timer); } /* called under bridge lock */ @@ -439,7 +439,7 @@ static void br_make_blocking(struct net_bridge_port *p) br_set_state(p, BR_STATE_BLOCKING); br_ifinfo_notify(RTM_NEWLINK, NULL, p); - del_timer(&p->forward_delay_timer); + timer_delete(&p->forward_delay_timer); } } @@ -454,7 +454,7 @@ static void br_make_forwarding(struct net_bridge_port *p) if (br->stp_enabled == BR_NO_STP || br->forward_delay == 0) { br_set_state(p, BR_STATE_FORWARDING); br_topology_change_detection(br); - del_timer(&p->forward_delay_timer); + timer_delete(&p->forward_delay_timer); } else if (br->stp_enabled == BR_KERNEL_STP) br_set_state(p, BR_STATE_LISTENING); else @@ -483,7 +483,7 @@ void br_port_state_selection(struct net_bridge *br) p->topology_change_ack = 0; br_make_forwarding(p); } else if (br_is_designated_port(p)) { - del_timer(&p->message_age_timer); + timer_delete(&p->message_age_timer); br_make_forwarding(p); } else { p->config_pending = 0; @@ -533,9 +533,9 @@ void br_received_config_bpdu(struct net_bridge_port *p, br_port_state_selection(br); if (!br_is_root_bridge(br) && was_root) { - del_timer(&br->hello_timer); + timer_delete(&br->hello_timer); if (br->topology_change_detected) { - del_timer(&br->topology_change_timer); + timer_delete(&br->topology_change_timer); br_transmit_tcn(br); mod_timer(&br->tcn_timer,
diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c index 75204d3..c20a41b 100644 --- a/net/bridge/br_stp_if.c +++ b/net/bridge/br_stp_if.c
@@ -81,9 +81,9 @@ void br_stp_disable_bridge(struct net_bridge *br) br->topology_change_detected = 0; spin_unlock_bh(&br->lock); - del_timer_sync(&br->hello_timer); - del_timer_sync(&br->topology_change_timer); - del_timer_sync(&br->tcn_timer); + timer_delete_sync(&br->hello_timer); + timer_delete_sync(&br->topology_change_timer); + timer_delete_sync(&br->tcn_timer); cancel_delayed_work_sync(&br->gc_work); } @@ -109,9 +109,9 @@ void br_stp_disable_port(struct net_bridge_port *p) br_ifinfo_notify(RTM_NEWLINK, NULL, p); - del_timer(&p->message_age_timer); - del_timer(&p->forward_delay_timer); - del_timer(&p->hold_timer); + timer_delete(&p->message_age_timer); + timer_delete(&p->forward_delay_timer); + timer_delete(&p->hold_timer); if (!rcu_access_pointer(p->backup_port)) br_fdb_delete_by_port(br, p, 0, 0);
diff --git a/net/can/af_can.c b/net/can/af_can.c index 4c059e4..4aab703 100644 --- a/net/can/af_can.c +++ b/net/can/af_can.c
@@ -825,7 +825,7 @@ static void can_pernet_exit(struct net *net) if (IS_ENABLED(CONFIG_PROC_FS)) { can_remove_proc(net); if (stats_timer) - del_timer_sync(&net->can.stattimer); + timer_delete_sync(&net->can.stattimer); } kfree(net->can.rx_alldev_list);
diff --git a/net/ceph/Kconfig b/net/ceph/Kconfig index c5c4eef..0aa21fc 100644 --- a/net/ceph/Kconfig +++ b/net/ceph/Kconfig
@@ -2,7 +2,7 @@ config CEPH_LIB tristate "Ceph core library" depends on INET - select LIBCRC32C + select CRC32 select CRYPTO_AES select CRYPTO_CBC select CRYPTO_GCM
diff --git a/net/core/Makefile b/net/core/Makefile index a10c3bd..b2a76ce 100644 --- a/net/core/Makefile +++ b/net/core/Makefile
@@ -45,5 +45,5 @@ obj-$(CONFIG_OF) += of_net.o obj-$(CONFIG_NET_TEST) += net_test.o obj-$(CONFIG_NET_DEVMEM) += devmem.o -obj-$(CONFIG_DEBUG_NET_SMALL_RTNL) += rtnl_net_debug.o +obj-$(CONFIG_DEBUG_NET) += lock_debug.o obj-$(CONFIG_FAIL_SKB_REALLOC) += skb_fault_injection.o
diff --git a/net/core/dev.c b/net/core/dev.c index be17e06..0608605 100644 --- a/net/core/dev.c +++ b/net/core/dev.c
@@ -1771,6 +1771,7 @@ void netif_disable_lro(struct net_device *dev) netdev_unlock_ops(lower_dev); } } +EXPORT_IPV6_MOD(netif_disable_lro); /** * dev_disable_gro_hw - disable HW Generic Receive Offload on a device @@ -1858,7 +1859,9 @@ static int call_netdevice_register_net_notifiers(struct notifier_block *nb, int err; for_each_netdev(net, dev) { + netdev_lock_ops(dev); err = call_netdevice_register_notifiers(nb, dev); + netdev_unlock_ops(dev); if (err) goto rollback; } @@ -10284,7 +10287,9 @@ int bpf_xdp_link_attach(const union bpf_attr *attr, struct bpf_prog *prog) goto unlock; } + netdev_lock_ops(dev); err = dev_xdp_attach_link(dev, &extack, link); + netdev_unlock_ops(dev); rtnl_unlock(); if (err) { @@ -11045,7 +11050,9 @@ int register_netdevice(struct net_device *dev) memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); /* Notify protocols, that a new device appeared. */ + netdev_lock_ops(dev); ret = call_netdevice_notifiers(NETDEV_REGISTER, dev); + netdev_unlock_ops(dev); ret = notifier_to_errno(ret); if (ret) { /* Expect explicit free_netdev() on failure */ @@ -12057,7 +12064,7 @@ void unregister_netdev(struct net_device *dev) } EXPORT_SYMBOL(unregister_netdev); -int netif_change_net_namespace(struct net_device *dev, struct net *net, +int __dev_change_net_namespace(struct net_device *dev, struct net *net, const char *pat, int new_ifindex, struct netlink_ext_ack *extack) { @@ -12142,11 +12149,12 @@ int netif_change_net_namespace(struct net_device *dev, struct net *net, * And now a mini version of register_netdevice unregister_netdevice. */ + netdev_lock_ops(dev); /* If device is running close it first. */ netif_close(dev); - /* And unlink it from device chain */ unlist_netdevice(dev); + netdev_unlock_ops(dev); synchronize_net(); @@ -12208,11 +12216,12 @@ int netif_change_net_namespace(struct net_device *dev, struct net *net, err = netdev_change_owner(dev, net_old, net); WARN_ON(err); + netdev_lock_ops(dev); /* Add the device back in the hashes */ list_netdevice(dev); - /* Notify protocols, that a new device appeared. */ call_netdevice_notifiers(NETDEV_REGISTER, dev); + netdev_unlock_ops(dev); /* * Prevent userspace races by waiting until the network
diff --git a/net/core/dev_api.c b/net/core/dev_api.c index 8dbc6061..90bafb0 100644 --- a/net/core/dev_api.c +++ b/net/core/dev_api.c
@@ -117,13 +117,7 @@ EXPORT_SYMBOL(dev_set_mac_address_user); int dev_change_net_namespace(struct net_device *dev, struct net *net, const char *pat) { - int ret; - - netdev_lock_ops(dev); - ret = netif_change_net_namespace(dev, net, pat, 0, NULL); - netdev_unlock_ops(dev); - - return ret; + return __dev_change_net_namespace(dev, net, pat, 0, NULL); } EXPORT_SYMBOL_GPL(dev_change_net_namespace);
diff --git a/net/core/devmem.c b/net/core/devmem.c index ee145a2a..6e27a47 100644 --- a/net/core/devmem.c +++ b/net/core/devmem.c
@@ -8,7 +8,6 @@ */ #include <linux/dma-buf.h> -#include <linux/ethtool_netlink.h> #include <linux/genalloc.h> #include <linux/mm.h> #include <linux/netdevice.h> @@ -117,21 +116,19 @@ void net_devmem_unbind_dmabuf(struct net_devmem_dmabuf_binding *binding) struct netdev_rx_queue *rxq; unsigned long xa_idx; unsigned int rxq_idx; - int err; if (binding->list.next) list_del(&binding->list); xa_for_each(&binding->bound_rxqs, xa_idx, rxq) { - WARN_ON(rxq->mp_params.mp_priv != binding); - - rxq->mp_params.mp_priv = NULL; - rxq->mp_params.mp_ops = NULL; + const struct pp_memory_provider_params mp_params = { + .mp_priv = binding, + .mp_ops = &dmabuf_devmem_ops, + }; rxq_idx = get_netdev_rx_queue_index(rxq); - err = netdev_rx_queue_restart(binding->dev, rxq_idx); - WARN_ON(err && err != -ENETDOWN); + __net_mp_close_rxq(binding->dev, rxq_idx, &mp_params); } xa_erase(&net_devmem_dmabuf_bindings, binding->id); @@ -143,57 +140,28 @@ int net_devmem_bind_dmabuf_to_queue(struct net_device *dev, u32 rxq_idx, struct net_devmem_dmabuf_binding *binding, struct netlink_ext_ack *extack) { + struct pp_memory_provider_params mp_params = { + .mp_priv = binding, + .mp_ops = &dmabuf_devmem_ops, + }; struct netdev_rx_queue *rxq; u32 xa_idx; int err; - if (rxq_idx >= dev->real_num_rx_queues) { - NL_SET_ERR_MSG(extack, "rx queue index out of range"); - return -ERANGE; - } - - if (dev->cfg->hds_config != ETHTOOL_TCP_DATA_SPLIT_ENABLED) { - NL_SET_ERR_MSG(extack, "tcp-data-split is disabled"); - return -EINVAL; - } - - if (dev->cfg->hds_thresh) { - NL_SET_ERR_MSG(extack, "hds-thresh is not zero"); - return -EINVAL; - } - - rxq = __netif_get_rx_queue(dev, rxq_idx); - if (rxq->mp_params.mp_ops) { - NL_SET_ERR_MSG(extack, "designated queue already memory provider bound"); - return -EEXIST; - } - -#ifdef CONFIG_XDP_SOCKETS - if (rxq->pool) { - NL_SET_ERR_MSG(extack, "designated queue already in use by AF_XDP"); - return -EBUSY; - } -#endif - - err = xa_alloc(&binding->bound_rxqs, &xa_idx, rxq, xa_limit_32b, - GFP_KERNEL); + err = __net_mp_open_rxq(dev, rxq_idx, &mp_params, extack); if (err) return err; - rxq->mp_params.mp_priv = binding; - rxq->mp_params.mp_ops = &dmabuf_devmem_ops; - - err = netdev_rx_queue_restart(dev, rxq_idx); + rxq = __netif_get_rx_queue(dev, rxq_idx); + err = xa_alloc(&binding->bound_rxqs, &xa_idx, rxq, xa_limit_32b, + GFP_KERNEL); if (err) - goto err_xa_erase; + goto err_close_rxq; return 0; -err_xa_erase: - rxq->mp_params.mp_priv = NULL; - rxq->mp_params.mp_ops = NULL; - xa_erase(&binding->bound_rxqs, xa_idx); - +err_close_rxq: + __net_mp_close_rxq(dev, rxq_idx, &mp_params); return err; }
diff --git a/net/core/drop_monitor.c b/net/core/drop_monitor.c index 212f0a0..8a7ce640 100644 --- a/net/core/drop_monitor.c +++ b/net/core/drop_monitor.c
@@ -1088,7 +1088,7 @@ static int net_dm_hw_monitor_start(struct netlink_ext_ack *extack) struct per_cpu_dm_data *hw_data = &per_cpu(dm_hw_cpu_data, cpu); struct sk_buff *skb; - del_timer_sync(&hw_data->send_timer); + timer_delete_sync(&hw_data->send_timer); cancel_work_sync(&hw_data->dm_alert_work); while ((skb = __skb_dequeue(&hw_data->drop_queue))) { struct devlink_trap_metadata *hw_metadata; @@ -1122,7 +1122,7 @@ static void net_dm_hw_monitor_stop(struct netlink_ext_ack *extack) struct per_cpu_dm_data *hw_data = &per_cpu(dm_hw_cpu_data, cpu); struct sk_buff *skb; - del_timer_sync(&hw_data->send_timer); + timer_delete_sync(&hw_data->send_timer); cancel_work_sync(&hw_data->dm_alert_work); while ((skb = __skb_dequeue(&hw_data->drop_queue))) { struct devlink_trap_metadata *hw_metadata; @@ -1183,7 +1183,7 @@ static int net_dm_trace_on_set(struct netlink_ext_ack *extack) struct per_cpu_dm_data *data = &per_cpu(dm_cpu_data, cpu); struct sk_buff *skb; - del_timer_sync(&data->send_timer); + timer_delete_sync(&data->send_timer); cancel_work_sync(&data->dm_alert_work); while ((skb = __skb_dequeue(&data->drop_queue))) consume_skb(skb); @@ -1211,7 +1211,7 @@ static void net_dm_trace_off_set(void) struct per_cpu_dm_data *data = &per_cpu(dm_cpu_data, cpu); struct sk_buff *skb; - del_timer_sync(&data->send_timer); + timer_delete_sync(&data->send_timer); cancel_work_sync(&data->dm_alert_work); while ((skb = __skb_dequeue(&data->drop_queue))) consume_skb(skb);
diff --git a/net/core/dst.c b/net/core/dst.c index c99b95c..795ca07 100644 --- a/net/core/dst.c +++ b/net/core/dst.c
@@ -165,6 +165,14 @@ static void dst_count_dec(struct dst_entry *dst) void dst_release(struct dst_entry *dst) { if (dst && rcuref_put(&dst->__rcuref)) { +#ifdef CONFIG_DST_CACHE + if (dst->flags & DST_METADATA) { + struct metadata_dst *md_dst = (struct metadata_dst *)dst; + + if (md_dst->type == METADATA_IP_TUNNEL) + dst_cache_reset_now(&md_dst->u.tun_info.dst_cache); + } +#endif dst_count_dec(dst); call_rcu_hurry(&dst->rcu_head, dst_destroy_rcu); }
diff --git a/net/core/gen_estimator.c b/net/core/gen_estimator.c index 4128160..2b821b9 100644 --- a/net/core/gen_estimator.c +++ b/net/core/gen_estimator.c
@@ -177,7 +177,7 @@ int gen_new_estimator(struct gnet_stats_basic_sync *bstats, spin_lock_bh(lock); old = rcu_dereference_protected(*rate_est, 1); if (old) { - del_timer_sync(&old->timer); + timer_delete_sync(&old->timer); est->avbps = old->avbps; est->avpps = old->avpps; }
diff --git a/net/core/rtnl_net_debug.c b/net/core/lock_debug.c similarity index 87% rename from net/core/rtnl_net_debug.c rename to net/core/lock_debug.c index 7ecd28c..b7f22dc 100644 --- a/net/core/rtnl_net_debug.c +++ b/net/core/lock_debug.c
@@ -6,10 +6,11 @@ #include <linux/notifier.h> #include <linux/rtnetlink.h> #include <net/net_namespace.h> +#include <net/netdev_lock.h> #include <net/netns/generic.h> -static int rtnl_net_debug_event(struct notifier_block *nb, - unsigned long event, void *ptr) +int netdev_debug_event(struct notifier_block *nb, unsigned long event, + void *ptr) { struct net_device *dev = netdev_notifier_info_to_dev(ptr); struct net *net = dev_net(dev); @@ -17,11 +18,13 @@ static int rtnl_net_debug_event(struct notifier_block *nb, /* Keep enum and don't add default to trigger -Werror=switch */ switch (cmd) { + case NETDEV_REGISTER: case NETDEV_UP: + netdev_ops_assert_locked(dev); + fallthrough; case NETDEV_DOWN: case NETDEV_REBOOT: case NETDEV_CHANGE: - case NETDEV_REGISTER: case NETDEV_UNREGISTER: case NETDEV_CHANGEMTU: case NETDEV_CHANGEADDR: @@ -66,6 +69,7 @@ static int rtnl_net_debug_event(struct notifier_block *nb, return NOTIFY_DONE; } +EXPORT_SYMBOL_NS_GPL(netdev_debug_event, "NETDEV_INTERNAL"); static int rtnl_net_debug_net_id; @@ -74,7 +78,7 @@ static int __net_init rtnl_net_debug_net_init(struct net *net) struct notifier_block *nb; nb = net_generic(net, rtnl_net_debug_net_id); - nb->notifier_call = rtnl_net_debug_event; + nb->notifier_call = netdev_debug_event; return register_netdevice_notifier_net(net, nb); } @@ -95,14 +99,14 @@ static struct pernet_operations rtnl_net_debug_net_ops __net_initdata = { }; static struct notifier_block rtnl_net_debug_block = { - .notifier_call = rtnl_net_debug_event, + .notifier_call = netdev_debug_event, }; static int __init rtnl_net_debug_init(void) { int ret; - ret = register_pernet_device(&rtnl_net_debug_net_ops); + ret = register_pernet_subsys(&rtnl_net_debug_net_ops); if (ret) return ret;
diff --git a/net/core/neighbour.c b/net/core/neighbour.c index 0738aa6..a07249b 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c
@@ -309,7 +309,7 @@ static void neigh_add_timer(struct neighbour *n, unsigned long when) static int neigh_del_timer(struct neighbour *n) { if ((n->nud_state & NUD_IN_TIMER) && - del_timer(&n->timer)) { + timer_delete(&n->timer)) { neigh_release(n); return 1; } @@ -427,7 +427,7 @@ static int __neigh_ifdown(struct neigh_table *tbl, struct net_device *dev, pneigh_queue_purge(&tbl->proxy_queue, dev ? dev_net(dev) : NULL, tbl->family); if (skb_queue_empty_lockless(&tbl->proxy_queue)) - del_timer_sync(&tbl->proxy_timer); + timer_delete_sync(&tbl->proxy_timer); return 0; } @@ -1597,7 +1597,7 @@ static void neigh_proxy_process(struct timer_list *t) } else if (!sched_next || tdif < sched_next) sched_next = tdif; } - del_timer(&tbl->proxy_timer); + timer_delete(&tbl->proxy_timer); if (sched_next) mod_timer(&tbl->proxy_timer, jiffies + sched_next); spin_unlock(&tbl->proxy_queue.lock); @@ -1628,7 +1628,7 @@ void pneigh_enqueue(struct neigh_table *tbl, struct neigh_parms *p, NEIGH_CB(skb)->flags |= LOCALLY_ENQUEUED; spin_lock(&tbl->proxy_queue.lock); - if (del_timer(&tbl->proxy_timer)) { + if (timer_delete(&tbl->proxy_timer)) { if (time_before(tbl->proxy_timer.expires, sched_next)) sched_next = tbl->proxy_timer.expires; } @@ -1786,7 +1786,7 @@ int neigh_table_clear(int index, struct neigh_table *tbl) /* It is not clean... Fix it to unload IPv6 module safely */ cancel_delayed_work_sync(&tbl->managed_work); cancel_delayed_work_sync(&tbl->gc_work); - del_timer_sync(&tbl->proxy_timer); + timer_delete_sync(&tbl->proxy_timer); pneigh_queue_purge(&tbl->proxy_queue, NULL, tbl->family); neigh_ifdown(tbl, NULL); if (atomic_read(&tbl->entries))
diff --git a/net/core/netdev-genl.c b/net/core/netdev-genl.c index fd1cfa9..5d7af50 100644 --- a/net/core/netdev-genl.c +++ b/net/core/netdev-genl.c
@@ -874,12 +874,6 @@ int netdev_nl_bind_rx_doit(struct sk_buff *skb, struct genl_info *info) goto err_unlock; } - if (dev_xdp_prog_count(netdev)) { - NL_SET_ERR_MSG(info->extack, "unable to bind dmabuf to device with XDP program attached"); - err = -EEXIST; - goto err_unlock; - } - binding = net_devmem_bind_dmabuf(netdev, dmabuf_fd, info->extack); if (IS_ERR(binding)) { err = PTR_ERR(binding); @@ -951,12 +945,14 @@ void netdev_nl_sock_priv_destroy(struct netdev_nl_sock *priv) { struct net_devmem_dmabuf_binding *binding; struct net_devmem_dmabuf_binding *temp; + struct net_device *dev; mutex_lock(&priv->lock); list_for_each_entry_safe(binding, temp, &priv->bindings, list) { - netdev_lock(binding->dev); + dev = binding->dev; + netdev_lock(dev); net_devmem_unbind_dmabuf(binding); - netdev_unlock(binding->dev); + netdev_unlock(dev); } mutex_unlock(&priv->lock); }
diff --git a/net/core/netdev_rx_queue.c b/net/core/netdev_rx_queue.c index 3af716f..d126f10 100644 --- a/net/core/netdev_rx_queue.c +++ b/net/core/netdev_rx_queue.c
@@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later +#include <linux/ethtool_netlink.h> #include <linux/netdevice.h> #include <net/netdev_lock.h> #include <net/netdev_queues.h> @@ -86,8 +87,9 @@ int netdev_rx_queue_restart(struct net_device *dev, unsigned int rxq_idx) } EXPORT_SYMBOL_NS_GPL(netdev_rx_queue_restart, "NETDEV_INTERNAL"); -static int __net_mp_open_rxq(struct net_device *dev, unsigned ifq_idx, - struct pp_memory_provider_params *p) +int __net_mp_open_rxq(struct net_device *dev, unsigned int rxq_idx, + const struct pp_memory_provider_params *p, + struct netlink_ext_ack *extack) { struct netdev_rx_queue *rxq; int ret; @@ -95,16 +97,41 @@ static int __net_mp_open_rxq(struct net_device *dev, unsigned ifq_idx, if (!netdev_need_ops_lock(dev)) return -EOPNOTSUPP; - if (ifq_idx >= dev->real_num_rx_queues) + if (rxq_idx >= dev->real_num_rx_queues) return -EINVAL; - ifq_idx = array_index_nospec(ifq_idx, dev->real_num_rx_queues); + rxq_idx = array_index_nospec(rxq_idx, dev->real_num_rx_queues); - rxq = __netif_get_rx_queue(dev, ifq_idx); - if (rxq->mp_params.mp_ops) + if (rxq_idx >= dev->real_num_rx_queues) { + NL_SET_ERR_MSG(extack, "rx queue index out of range"); + return -ERANGE; + } + if (dev->cfg->hds_config != ETHTOOL_TCP_DATA_SPLIT_ENABLED) { + NL_SET_ERR_MSG(extack, "tcp-data-split is disabled"); + return -EINVAL; + } + if (dev->cfg->hds_thresh) { + NL_SET_ERR_MSG(extack, "hds-thresh is not zero"); + return -EINVAL; + } + if (dev_xdp_prog_count(dev)) { + NL_SET_ERR_MSG(extack, "unable to custom memory provider to device with XDP program attached"); return -EEXIST; + } + + rxq = __netif_get_rx_queue(dev, rxq_idx); + if (rxq->mp_params.mp_ops) { + NL_SET_ERR_MSG(extack, "designated queue already memory provider bound"); + return -EEXIST; + } +#ifdef CONFIG_XDP_SOCKETS + if (rxq->pool) { + NL_SET_ERR_MSG(extack, "designated queue already in use by AF_XDP"); + return -EBUSY; + } +#endif rxq->mp_params = *p; - ret = netdev_rx_queue_restart(dev, ifq_idx); + ret = netdev_rx_queue_restart(dev, rxq_idx); if (ret) { rxq->mp_params.mp_ops = NULL; rxq->mp_params.mp_priv = NULL; @@ -112,21 +139,22 @@ static int __net_mp_open_rxq(struct net_device *dev, unsigned ifq_idx, return ret; } -int net_mp_open_rxq(struct net_device *dev, unsigned ifq_idx, +int net_mp_open_rxq(struct net_device *dev, unsigned int rxq_idx, struct pp_memory_provider_params *p) { int ret; netdev_lock(dev); - ret = __net_mp_open_rxq(dev, ifq_idx, p); + ret = __net_mp_open_rxq(dev, rxq_idx, p, NULL); netdev_unlock(dev); return ret; } -static void __net_mp_close_rxq(struct net_device *dev, unsigned ifq_idx, - struct pp_memory_provider_params *old_p) +void __net_mp_close_rxq(struct net_device *dev, unsigned int ifq_idx, + const struct pp_memory_provider_params *old_p) { struct netdev_rx_queue *rxq; + int err; if (WARN_ON_ONCE(ifq_idx >= dev->real_num_rx_queues)) return; @@ -146,7 +174,8 @@ static void __net_mp_close_rxq(struct net_device *dev, unsigned ifq_idx, rxq->mp_params.mp_ops = NULL; rxq->mp_params.mp_priv = NULL; - WARN_ON(netdev_rx_queue_restart(dev, ifq_idx)); + err = netdev_rx_queue_restart(dev, ifq_idx); + WARN_ON(err && err != -ENETDOWN); } void net_mp_close_rxq(struct net_device *dev, unsigned ifq_idx,
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 5a24a30..c238528 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c
@@ -1177,6 +1177,9 @@ static inline int rtnl_vfinfo_size(const struct net_device *dev, /* IFLA_VF_STATS_TX_DROPPED */ nla_total_size_64bit(sizeof(__u64))); } + if (dev->netdev_ops->ndo_get_vf_guid) + size += num_vfs * 2 * + nla_total_size(sizeof(struct ifla_vf_guid)); return size; } else return 0; @@ -3022,8 +3025,6 @@ static int do_setlink(const struct sk_buff *skb, struct net_device *dev, char ifname[IFNAMSIZ]; int err; - netdev_lock_ops(dev); - err = validate_linkmsg(dev, tb, extack); if (err < 0) goto errout; @@ -3039,14 +3040,16 @@ static int do_setlink(const struct sk_buff *skb, struct net_device *dev, new_ifindex = nla_get_s32_default(tb[IFLA_NEW_IFINDEX], 0); - err = netif_change_net_namespace(dev, tgt_net, pat, + err = __dev_change_net_namespace(dev, tgt_net, pat, new_ifindex, extack); if (err) - goto errout; + return err; status |= DO_SETLINK_MODIFIED; } + netdev_lock_ops(dev); + if (tb[IFLA_MAP]) { struct rtnl_link_ifmap *u_map; struct ifmap k_map;
diff --git a/net/core/sock.c b/net/core/sock.c index 3238920..f67a3c5b 100644 --- a/net/core/sock.c +++ b/net/core/sock.c
@@ -3598,14 +3598,14 @@ EXPORT_SYMBOL(sk_reset_timer); void sk_stop_timer(struct sock *sk, struct timer_list* timer) { - if (del_timer(timer)) + if (timer_delete(timer)) __sock_put(sk); } EXPORT_SYMBOL(sk_stop_timer); void sk_stop_timer_sync(struct sock *sk, struct timer_list *timer) { - if (del_timer_sync(timer)) + if (timer_delete_sync(timer)) __sock_put(sk); } EXPORT_SYMBOL(sk_stop_timer_sync);
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index 754f60f..77e5705 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c
@@ -281,7 +281,7 @@ static struct in_device *inetdev_init(struct net_device *dev) if (!in_dev->arp_parms) goto out_kfree; if (IPV4_DEVCONF(in_dev->cnf, FORWARDING)) - dev_disable_lro(dev); + netif_disable_lro(dev); /* Reference in_dev->dev */ netdev_hold(dev, &in_dev->dev_tracker, GFP_KERNEL); /* Account for reference dev->ip_ptr (below) */
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index 2c394c3..ca7d539 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c
@@ -205,7 +205,7 @@ static void ip_sf_list_clear_all(struct ip_sf_list *psf) static void igmp_stop_timer(struct ip_mc_list *im) { spin_lock_bh(&im->lock); - if (del_timer(&im->timer)) + if (timer_delete(&im->timer)) refcount_dec(&im->refcnt); im->tm_running = 0; im->reporter = 0; @@ -251,7 +251,7 @@ static void igmp_mod_timer(struct ip_mc_list *im, int max_delay) { spin_lock_bh(&im->lock); im->unsolicit_count = 0; - if (del_timer(&im->timer)) { + if (timer_delete(&im->timer)) { if ((long)(im->timer.expires-jiffies) < max_delay) { add_timer(&im->timer); im->tm_running = 1; @@ -974,7 +974,7 @@ static bool igmp_heard_query(struct in_device *in_dev, struct sk_buff *skb, } /* cancel the interface change timer */ WRITE_ONCE(in_dev->mr_ifc_count, 0); - if (del_timer(&in_dev->mr_ifc_timer)) + if (timer_delete(&in_dev->mr_ifc_timer)) __in_dev_put(in_dev); /* clear deleted report items */ igmpv3_clear_delrec(in_dev); @@ -1830,10 +1830,10 @@ void ip_mc_down(struct in_device *in_dev) #ifdef CONFIG_IP_MULTICAST WRITE_ONCE(in_dev->mr_ifc_count, 0); - if (del_timer(&in_dev->mr_ifc_timer)) + if (timer_delete(&in_dev->mr_ifc_timer)) __in_dev_put(in_dev); in_dev->mr_gq_running = 0; - if (del_timer(&in_dev->mr_gq_timer)) + if (timer_delete(&in_dev->mr_gq_timer)) __in_dev_put(in_dev); #endif
diff --git a/net/ipv4/inet_fragment.c b/net/ipv4/inet_fragment.c index 19fae48..470ab17 100644 --- a/net/ipv4/inet_fragment.c +++ b/net/ipv4/inet_fragment.c
@@ -133,7 +133,7 @@ static void inet_frags_free_cb(void *ptr, void *arg) struct inet_frag_queue *fq = ptr; int count; - count = del_timer_sync(&fq->timer) ? 1 : 0; + count = timer_delete_sync(&fq->timer) ? 1 : 0; spin_lock_bh(&fq->lock); fq->flags |= INET_FRAG_DROP; @@ -227,7 +227,7 @@ EXPORT_SYMBOL(fqdir_exit); void inet_frag_kill(struct inet_frag_queue *fq, int *refs) { - if (del_timer(&fq->timer)) + if (timer_delete(&fq->timer)) (*refs)++; if (!(fq->flags & INET_FRAG_COMPLETE)) { @@ -297,7 +297,7 @@ void inet_frag_destroy(struct inet_frag_queue *q) reason = (q->flags & INET_FRAG_DROP) ? SKB_DROP_REASON_FRAG_REASM_TIMEOUT : SKB_CONSUMED; - WARN_ON(del_timer(&q->timer) != 0); + WARN_ON(timer_delete(&q->timer) != 0); /* Release all fragment data. */ fqdir = q->fqdir;
diff --git a/net/ipv4/ip_tunnel_core.c b/net/ipv4/ip_tunnel_core.c index a367615..f65d2f7 100644 --- a/net/ipv4/ip_tunnel_core.c +++ b/net/ipv4/ip_tunnel_core.c
@@ -416,7 +416,7 @@ int skb_tunnel_check_pmtu(struct sk_buff *skb, struct dst_entry *encap_dst, skb_dst_update_pmtu_no_confirm(skb, mtu); - if (!reply || skb->pkt_type == PACKET_HOST) + if (!reply) return 0; if (skb->protocol == htons(ETH_P_IP)) @@ -451,7 +451,7 @@ static const struct nla_policy geneve_opt_policy[LWTUNNEL_IP_OPT_GENEVE_MAX + 1] = { [LWTUNNEL_IP_OPT_GENEVE_CLASS] = { .type = NLA_U16 }, [LWTUNNEL_IP_OPT_GENEVE_TYPE] = { .type = NLA_U8 }, - [LWTUNNEL_IP_OPT_GENEVE_DATA] = { .type = NLA_BINARY, .len = 128 }, + [LWTUNNEL_IP_OPT_GENEVE_DATA] = { .type = NLA_BINARY, .len = 127 }, }; static const struct nla_policy
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index b81c813..a8b04d4 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c
@@ -1289,7 +1289,7 @@ static int ipmr_mfc_add(struct net *net, struct mr_table *mrt, } } if (list_empty(&mrt->mfc_unres_queue)) - del_timer(&mrt->ipmr_expire_timer); + timer_delete(&mrt->ipmr_expire_timer); spin_unlock_bh(&mfc_unres_lock); if (found) {
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index ea8de00..6edc441 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c
@@ -1525,25 +1525,11 @@ void tcp_cleanup_rbuf(struct sock *sk, int copied) __tcp_cleanup_rbuf(sk, copied); } -/* private version of sock_rfree() avoiding one atomic_sub() */ -void tcp_sock_rfree(struct sk_buff *skb) -{ - struct sock *sk = skb->sk; - unsigned int len = skb->truesize; - - sock_owned_by_me(sk); - atomic_set(&sk->sk_rmem_alloc, - atomic_read(&sk->sk_rmem_alloc) - len); - - sk_forward_alloc_add(sk, len); - sk_mem_reclaim(sk); -} - static void tcp_eat_recv_skb(struct sock *sk, struct sk_buff *skb) { __skb_unlink(skb, &sk->sk_receive_queue); - if (likely(skb->destructor == tcp_sock_rfree)) { - tcp_sock_rfree(skb); + if (likely(skb->destructor == sock_rfree)) { + sock_rfree(skb); skb->destructor = NULL; skb->sk = NULL; return skb_attempt_defer_free(skb);
diff --git a/net/ipv4/tcp_fastopen.c b/net/ipv4/tcp_fastopen.c index ca40665..1a6b1bc 100644 --- a/net/ipv4/tcp_fastopen.c +++ b/net/ipv4/tcp_fastopen.c
@@ -189,7 +189,7 @@ void tcp_fastopen_add_skb(struct sock *sk, struct sk_buff *skb) tcp_segs_in(tp, skb); __skb_pull(skb, tcp_hdrlen(skb)); sk_forced_mem_schedule(sk, skb->truesize); - tcp_skb_set_owner_r(skb, sk); + skb_set_owner_r(skb, sk); TCP_SKB_CB(skb)->seq++; TCP_SKB_CB(skb)->tcp_flags &= ~TCPHDR_SYN;
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index e1f952f..a35018e 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c
@@ -5171,7 +5171,7 @@ static void tcp_data_queue_ofo(struct sock *sk, struct sk_buff *skb) if (tcp_is_sack(tp)) tcp_grow_window(sk, skb, false); skb_condense(skb); - tcp_skb_set_owner_r(skb, sk); + skb_set_owner_r(skb, sk); } } @@ -5187,7 +5187,7 @@ static int __must_check tcp_queue_rcv(struct sock *sk, struct sk_buff *skb, tcp_rcv_nxt_update(tcp_sk(sk), TCP_SKB_CB(skb)->end_seq); if (!eaten) { tcp_add_receive_queue(sk, skb); - tcp_skb_set_owner_r(skb, sk); + skb_set_owner_r(skb, sk); } return eaten; } @@ -5504,7 +5504,7 @@ tcp_collapse(struct sock *sk, struct sk_buff_head *list, struct rb_root *root, __skb_queue_before(list, skb, nskb); else __skb_queue_tail(&tmp, nskb); /* defer rbtree insertion */ - tcp_skb_set_owner_r(nskb, sk); + skb_set_owner_r(nskb, sk); mptcp_skb_ext_move(nskb, skb); /* Copy data, releasing collapsed skbs. */
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index d0bffcf..2742cc7 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c
@@ -1625,12 +1625,12 @@ static bool udp_skb_has_head_state(struct sk_buff *skb) } /* fully reclaim rmem/fwd memory allocated for skb */ -static void udp_rmem_release(struct sock *sk, int size, int partial, - bool rx_queue_lock_held) +static void udp_rmem_release(struct sock *sk, unsigned int size, + int partial, bool rx_queue_lock_held) { struct udp_sock *up = udp_sk(sk); struct sk_buff_head *sk_queue; - int amt; + unsigned int amt; if (likely(partial)) { up->forward_deficit += size; @@ -1650,10 +1650,8 @@ static void udp_rmem_release(struct sock *sk, int size, int partial, if (!rx_queue_lock_held) spin_lock(&sk_queue->lock); - - sk_forward_alloc_add(sk, size); - amt = (sk->sk_forward_alloc - partial) & ~(PAGE_SIZE - 1); - sk_forward_alloc_add(sk, -amt); + amt = (size + sk->sk_forward_alloc - partial) & ~(PAGE_SIZE - 1); + sk_forward_alloc_add(sk, size - amt); if (amt) __sk_mem_reduce_allocated(sk, amt >> PAGE_SHIFT); @@ -1725,17 +1723,25 @@ static int udp_rmem_schedule(struct sock *sk, int size) int __udp_enqueue_schedule_skb(struct sock *sk, struct sk_buff *skb) { struct sk_buff_head *list = &sk->sk_receive_queue; - int rmem, err = -ENOMEM; + unsigned int rmem, rcvbuf; spinlock_t *busy = NULL; - int size, rcvbuf; + int size, err = -ENOMEM; - /* Immediately drop when the receive queue is full. - * Always allow at least one packet. - */ rmem = atomic_read(&sk->sk_rmem_alloc); rcvbuf = READ_ONCE(sk->sk_rcvbuf); - if (rmem > rcvbuf) - goto drop; + size = skb->truesize; + + /* Immediately drop when the receive queue is full. + * Cast to unsigned int performs the boundary check for INT_MAX. + */ + if (rmem + size > rcvbuf) { + if (rcvbuf > INT_MAX >> 1) + goto drop; + + /* Always allow at least one packet for small buffer. */ + if (rmem > rcvbuf) + goto drop; + } /* Under mem pressure, it might be helpful to help udp_recvmsg() * having linear skbs : @@ -1745,10 +1751,10 @@ int __udp_enqueue_schedule_skb(struct sock *sk, struct sk_buff *skb) */ if (rmem > (rcvbuf >> 1)) { skb_condense(skb); - + size = skb->truesize; busy = busylock_acquire(sk); } - size = skb->truesize; + udp_set_dev_scratch(skb); atomic_add(size, &sk->sk_rmem_alloc); @@ -1835,7 +1841,7 @@ EXPORT_IPV6_MOD_GPL(skb_consume_udp); static struct sk_buff *__first_packet_length(struct sock *sk, struct sk_buff_head *rcvq, - int *total) + unsigned int *total) { struct sk_buff *skb; @@ -1868,8 +1874,8 @@ static int first_packet_length(struct sock *sk) { struct sk_buff_head *rcvq = &udp_sk(sk)->reader_queue; struct sk_buff_head *sk_queue = &sk->sk_receive_queue; + unsigned int total = 0; struct sk_buff *skb; - int total = 0; int res; spin_lock_bh(&rcvq->lock);
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index ac8cc10..2cffb8f 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c
@@ -80,6 +80,7 @@ #include <net/netlink.h> #include <net/pkt_sched.h> #include <net/l3mdev.h> +#include <net/netdev_lock.h> #include <linux/if_tunnel.h> #include <linux/rtnetlink.h> #include <linux/netconf.h> @@ -312,7 +313,7 @@ static inline bool addrconf_link_ready(const struct net_device *dev) static void addrconf_del_rs_timer(struct inet6_dev *idev) { - if (del_timer(&idev->rs_timer)) + if (timer_delete(&idev->rs_timer)) __in6_dev_put(idev); } @@ -377,6 +378,7 @@ static struct inet6_dev *ipv6_add_dev(struct net_device *dev) int err = -ENOMEM; ASSERT_RTNL(); + netdev_ops_assert_locked(dev); if (dev->mtu < IPV6_MIN_MTU && dev != blackhole_netdev) return ERR_PTR(-EINVAL); @@ -402,7 +404,7 @@ static struct inet6_dev *ipv6_add_dev(struct net_device *dev) return ERR_PTR(err); } if (ndev->cnf.forwarding) - dev_disable_lro(dev); + netif_disable_lro(dev); /* We refer to the device */ netdev_hold(dev, &ndev->dev_tracker, GFP_KERNEL); @@ -3152,10 +3154,12 @@ int addrconf_add_ifaddr(struct net *net, void __user *arg) rtnl_net_lock(net); dev = __dev_get_by_index(net, ireq.ifr6_ifindex); + netdev_lock_ops(dev); if (dev) err = inet6_addr_add(net, dev, &cfg, 0, 0, NULL); else err = -ENODEV; + netdev_unlock_ops(dev); rtnl_net_unlock(net); return err; } @@ -5026,9 +5030,10 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, if (!dev) { NL_SET_ERR_MSG_MOD(extack, "Unable to find the interface"); err = -ENODEV; - goto unlock; + goto unlock_rtnl; } + netdev_lock_ops(dev); idev = ipv6_find_idev(dev); if (IS_ERR(idev)) { err = PTR_ERR(idev); @@ -5065,6 +5070,8 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, in6_ifa_put(ifa); unlock: + netdev_unlock_ops(dev); +unlock_rtnl: rtnl_net_unlock(net); return err; @@ -5784,6 +5791,27 @@ static void snmp6_fill_stats(u64 *stats, struct inet6_dev *idev, int attrtype, } } +static int inet6_fill_ifla6_stats_attrs(struct sk_buff *skb, + struct inet6_dev *idev) +{ + struct nlattr *nla; + + nla = nla_reserve(skb, IFLA_INET6_STATS, IPSTATS_MIB_MAX * sizeof(u64)); + if (!nla) + goto nla_put_failure; + snmp6_fill_stats(nla_data(nla), idev, IFLA_INET6_STATS, nla_len(nla)); + + nla = nla_reserve(skb, IFLA_INET6_ICMP6STATS, ICMP6_MIB_MAX * sizeof(u64)); + if (!nla) + goto nla_put_failure; + snmp6_fill_stats(nla_data(nla), idev, IFLA_INET6_ICMP6STATS, nla_len(nla)); + + return 0; + +nla_put_failure: + return -EMSGSIZE; +} + static int inet6_fill_ifla6_attrs(struct sk_buff *skb, struct inet6_dev *idev, u32 ext_filter_mask) { @@ -5806,18 +5834,10 @@ static int inet6_fill_ifla6_attrs(struct sk_buff *skb, struct inet6_dev *idev, /* XXX - MC not implemented */ - if (ext_filter_mask & RTEXT_FILTER_SKIP_STATS) - return 0; - - nla = nla_reserve(skb, IFLA_INET6_STATS, IPSTATS_MIB_MAX * sizeof(u64)); - if (!nla) - goto nla_put_failure; - snmp6_fill_stats(nla_data(nla), idev, IFLA_INET6_STATS, nla_len(nla)); - - nla = nla_reserve(skb, IFLA_INET6_ICMP6STATS, ICMP6_MIB_MAX * sizeof(u64)); - if (!nla) - goto nla_put_failure; - snmp6_fill_stats(nla_data(nla), idev, IFLA_INET6_ICMP6STATS, nla_len(nla)); + if (!(ext_filter_mask & RTEXT_FILTER_SKIP_STATS)) { + if (inet6_fill_ifla6_stats_attrs(skb, idev) < 0) + goto nla_put_failure; + } nla = nla_reserve(skb, IFLA_INET6_TOKEN, sizeof(struct in6_addr)); if (!nla) @@ -6503,7 +6523,9 @@ static int addrconf_sysctl_addr_gen_mode(const struct ctl_table *ctl, int write, if (idev->cnf.addr_gen_mode != new_val) { WRITE_ONCE(idev->cnf.addr_gen_mode, new_val); + netdev_lock_ops(idev->dev); addrconf_init_auto_addrs(idev->dev); + netdev_unlock_ops(idev->dev); } } else if (&net->ipv6.devconf_all->addr_gen_mode == ctl->data) { struct net_device *dev; @@ -6515,7 +6537,9 @@ static int addrconf_sysctl_addr_gen_mode(const struct ctl_table *ctl, int write, idev->cnf.addr_gen_mode != new_val) { WRITE_ONCE(idev->cnf.addr_gen_mode, new_val); + netdev_lock_ops(idev->dev); addrconf_init_auto_addrs(idev->dev); + netdev_unlock_ops(idev->dev); } } }
diff --git a/net/ipv6/calipso.c b/net/ipv6/calipso.c index dbcea9f..62618a0 100644 --- a/net/ipv6/calipso.c +++ b/net/ipv6/calipso.c
@@ -1072,8 +1072,13 @@ static int calipso_sock_getattr(struct sock *sk, struct ipv6_opt_hdr *hop; int opt_len, len, ret_val = -ENOMSG, offset; unsigned char *opt; - struct ipv6_txoptions *txopts = txopt_get(inet6_sk(sk)); + struct ipv6_pinfo *pinfo = inet6_sk(sk); + struct ipv6_txoptions *txopts; + if (!pinfo) + return -EAFNOSUPPORT; + + txopts = txopt_get(pinfo); if (!txopts || !txopts->hopopt) goto done; @@ -1125,8 +1130,13 @@ static int calipso_sock_setattr(struct sock *sk, { int ret_val; struct ipv6_opt_hdr *old, *new; - struct ipv6_txoptions *txopts = txopt_get(inet6_sk(sk)); + struct ipv6_pinfo *pinfo = inet6_sk(sk); + struct ipv6_txoptions *txopts; + if (!pinfo) + return -EAFNOSUPPORT; + + txopts = txopt_get(pinfo); old = NULL; if (txopts) old = txopts->hopopt; @@ -1153,8 +1163,13 @@ static int calipso_sock_setattr(struct sock *sk, static void calipso_sock_delattr(struct sock *sk) { struct ipv6_opt_hdr *new_hop; - struct ipv6_txoptions *txopts = txopt_get(inet6_sk(sk)); + struct ipv6_pinfo *pinfo = inet6_sk(sk); + struct ipv6_txoptions *txopts; + if (!pinfo) + return; + + txopts = txopt_get(pinfo); if (!txopts || !txopts->hopopt) goto done;
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index c134ba2..bf72714 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c
@@ -2383,7 +2383,7 @@ void fib6_run_gc(unsigned long expires, struct net *net, bool force) round_jiffies(now + net->ipv6.sysctl.ip6_rt_gc_interval)); else - del_timer(&net->ipv6.ip6_fib_timer); + timer_delete(&net->ipv6.ip6_fib_timer); spin_unlock_bh(&net->ipv6.fib6_gc_lock); } @@ -2470,7 +2470,7 @@ static void fib6_net_exit(struct net *net) { unsigned int i; - del_timer_sync(&net->ipv6.ip6_fib_timer); + timer_delete_sync(&net->ipv6.ip6_fib_timer); for (i = 0; i < FIB6_TABLE_HASHSZ; i++) { struct hlist_head *head = &net->ipv6.fib_table_hash[i];
diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c index eca07e1..a3ff575 100644 --- a/net/ipv6/ip6_flowlabel.c +++ b/net/ipv6/ip6_flowlabel.c
@@ -907,6 +907,6 @@ int ip6_flowlabel_init(void) void ip6_flowlabel_cleanup(void) { static_key_deferred_flush(&ipv6_flowlabel_exclusive); - del_timer(&ip6_fl_gc_timer); + timer_delete(&ip6_fl_gc_timer); unregister_pernet_subsys(&ip6_flowlabel_net_ops); }
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c index e8ade93..b413c9c 100644 --- a/net/ipv6/ip6mr.c +++ b/net/ipv6/ip6mr.c
@@ -1526,7 +1526,7 @@ static int ip6mr_mfc_add(struct net *net, struct mr_table *mrt, } } if (list_empty(&mrt->mfc_unres_queue)) - del_timer(&mrt->ipmr_expire_timer); + timer_delete(&mrt->ipmr_expire_timer); spin_unlock_bh(&mfc_unres_lock); if (found) {
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index c3406a0..ab12b81 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c
@@ -412,12 +412,37 @@ static bool rt6_check_expired(const struct rt6_info *rt) return false; } +static struct fib6_info * +rt6_multipath_first_sibling_rcu(const struct fib6_info *rt) +{ + struct fib6_info *iter; + struct fib6_node *fn; + + fn = rcu_dereference(rt->fib6_node); + if (!fn) + goto out; + iter = rcu_dereference(fn->leaf); + if (!iter) + goto out; + + while (iter) { + if (iter->fib6_metric == rt->fib6_metric && + rt6_qualify_for_ecmp(iter)) + return iter; + iter = rcu_dereference(iter->fib6_next); + } + +out: + return NULL; +} + void fib6_select_path(const struct net *net, struct fib6_result *res, struct flowi6 *fl6, int oif, bool have_oif_match, const struct sk_buff *skb, int strict) { - struct fib6_info *match = res->f6i; + struct fib6_info *first, *match = res->f6i; struct fib6_info *sibling; + int hash; if (!match->nh && (!match->fib6_nsiblings || have_oif_match)) goto out; @@ -440,16 +465,25 @@ void fib6_select_path(const struct net *net, struct fib6_result *res, return; } - if (fl6->mp_hash <= atomic_read(&match->fib6_nh->fib_nh_upper_bound)) + first = rt6_multipath_first_sibling_rcu(match); + if (!first) goto out; - list_for_each_entry_rcu(sibling, &match->fib6_siblings, + hash = fl6->mp_hash; + if (hash <= atomic_read(&first->fib6_nh->fib_nh_upper_bound) && + rt6_score_route(first->fib6_nh, first->fib6_flags, oif, + strict) >= 0) { + match = first; + goto out; + } + + list_for_each_entry_rcu(sibling, &first->fib6_siblings, fib6_siblings) { const struct fib6_nh *nh = sibling->fib6_nh; int nh_upper_bound; nh_upper_bound = atomic_read(&nh->fib_nh_upper_bound); - if (fl6->mp_hash > nh_upper_bound) + if (hash > nh_upper_bound) continue; if (rt6_score_route(nh, sibling->fib6_flags, oif, strict) < 0) break;
diff --git a/net/lapb/lapb_iface.c b/net/lapb/lapb_iface.c index 0971ca4..a0596e1 100644 --- a/net/lapb/lapb_iface.c +++ b/net/lapb/lapb_iface.c
@@ -194,8 +194,8 @@ int lapb_unregister(struct net_device *dev) spin_unlock_bh(&lapb->lock); /* Wait for running timers to stop */ - del_timer_sync(&lapb->t1timer); - del_timer_sync(&lapb->t2timer); + timer_delete_sync(&lapb->t1timer); + timer_delete_sync(&lapb->t2timer); __lapb_remove_cb(lapb);
diff --git a/net/lapb/lapb_timer.c b/net/lapb/lapb_timer.c index 5be6886..5b3f3b4 100644 --- a/net/lapb/lapb_timer.c +++ b/net/lapb/lapb_timer.c
@@ -35,7 +35,7 @@ static void lapb_t2timer_expiry(struct timer_list *); void lapb_start_t1timer(struct lapb_cb *lapb) { - del_timer(&lapb->t1timer); + timer_delete(&lapb->t1timer); lapb->t1timer.function = lapb_t1timer_expiry; lapb->t1timer.expires = jiffies + lapb->t1; @@ -46,7 +46,7 @@ void lapb_start_t1timer(struct lapb_cb *lapb) void lapb_start_t2timer(struct lapb_cb *lapb) { - del_timer(&lapb->t2timer); + timer_delete(&lapb->t2timer); lapb->t2timer.function = lapb_t2timer_expiry; lapb->t2timer.expires = jiffies + lapb->t2; @@ -58,13 +58,13 @@ void lapb_start_t2timer(struct lapb_cb *lapb) void lapb_stop_t1timer(struct lapb_cb *lapb) { lapb->t1timer_running = false; - del_timer(&lapb->t1timer); + timer_delete(&lapb->t1timer); } void lapb_stop_t2timer(struct lapb_cb *lapb) { lapb->t2timer_running = false; - del_timer(&lapb->t2timer); + timer_delete(&lapb->t2timer); } int lapb_t1timer_running(struct lapb_cb *lapb)
diff --git a/net/llc/llc_c_ac.c b/net/llc/llc_c_ac.c index 40ca3c1..7e8fc71 100644 --- a/net/llc/llc_c_ac.c +++ b/net/llc/llc_c_ac.c
@@ -51,7 +51,7 @@ int llc_conn_ac_clear_remote_busy(struct sock *sk, struct sk_buff *skb) struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); llc->remote_busy_flag = 0; - del_timer(&llc->busy_state_timer.timer); + timer_delete(&llc->busy_state_timer.timer); nr = LLC_I_GET_NR(pdu); llc_conn_resend_i_pdu_as_cmd(sk, nr, 0); } @@ -191,7 +191,7 @@ int llc_conn_ac_stop_rej_tmr_if_data_flag_eq_2(struct sock *sk, struct llc_sock *llc = llc_sk(sk); if (llc->data_flag == 2) - del_timer(&llc->rej_sent_timer.timer); + timer_delete(&llc->rej_sent_timer.timer); return 0; } @@ -1111,9 +1111,9 @@ int llc_conn_ac_stop_other_timers(struct sock *sk, struct sk_buff *skb) { struct llc_sock *llc = llc_sk(sk); - del_timer(&llc->rej_sent_timer.timer); - del_timer(&llc->pf_cycle_timer.timer); - del_timer(&llc->busy_state_timer.timer); + timer_delete(&llc->rej_sent_timer.timer); + timer_delete(&llc->pf_cycle_timer.timer); + timer_delete(&llc->busy_state_timer.timer); llc->ack_must_be_send = 0; llc->ack_pf = 0; return 0; @@ -1149,7 +1149,7 @@ int llc_conn_ac_start_ack_tmr_if_not_running(struct sock *sk, int llc_conn_ac_stop_ack_timer(struct sock *sk, struct sk_buff *skb) { - del_timer(&llc_sk(sk)->ack_timer.timer); + timer_delete(&llc_sk(sk)->ack_timer.timer); return 0; } @@ -1157,14 +1157,14 @@ int llc_conn_ac_stop_p_timer(struct sock *sk, struct sk_buff *skb) { struct llc_sock *llc = llc_sk(sk); - del_timer(&llc->pf_cycle_timer.timer); + timer_delete(&llc->pf_cycle_timer.timer); llc_conn_set_p_flag(sk, 0); return 0; } int llc_conn_ac_stop_rej_timer(struct sock *sk, struct sk_buff *skb) { - del_timer(&llc_sk(sk)->rej_sent_timer.timer); + timer_delete(&llc_sk(sk)->rej_sent_timer.timer); return 0; } @@ -1180,7 +1180,7 @@ int llc_conn_ac_upd_nr_received(struct sock *sk, struct sk_buff *skb) /* On loopback we don't queue I frames in unack_pdu_q queue. */ if (acked > 0 || (llc->dev->flags & IFF_LOOPBACK)) { llc->retry_count = 0; - del_timer(&llc->ack_timer.timer); + timer_delete(&llc->ack_timer.timer); if (llc->failed_data_req) { /* already, we did not accept data from upper layer * (tx_window full or unacceptable state). Now, we
diff --git a/net/llc/llc_conn.c b/net/llc/llc_conn.c index afc6974..5c0ac24 100644 --- a/net/llc/llc_conn.c +++ b/net/llc/llc_conn.c
@@ -949,15 +949,15 @@ void llc_sk_stop_all_timers(struct sock *sk, bool sync) struct llc_sock *llc = llc_sk(sk); if (sync) { - del_timer_sync(&llc->pf_cycle_timer.timer); - del_timer_sync(&llc->ack_timer.timer); - del_timer_sync(&llc->rej_sent_timer.timer); - del_timer_sync(&llc->busy_state_timer.timer); + timer_delete_sync(&llc->pf_cycle_timer.timer); + timer_delete_sync(&llc->ack_timer.timer); + timer_delete_sync(&llc->rej_sent_timer.timer); + timer_delete_sync(&llc->busy_state_timer.timer); } else { - del_timer(&llc->pf_cycle_timer.timer); - del_timer(&llc->ack_timer.timer); - del_timer(&llc->rej_sent_timer.timer); - del_timer(&llc->busy_state_timer.timer); + timer_delete(&llc->pf_cycle_timer.timer); + timer_delete(&llc->ack_timer.timer); + timer_delete(&llc->rej_sent_timer.timer); + timer_delete(&llc->busy_state_timer.timer); } llc->ack_must_be_send = 0;
diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c index aeb99d1..8561223 100644 --- a/net/mac80211/agg-rx.c +++ b/net/mac80211/agg-rx.c
@@ -103,13 +103,13 @@ void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, if (!tid_rx) return; - del_timer_sync(&tid_rx->session_timer); + timer_delete_sync(&tid_rx->session_timer); /* make sure ieee80211_sta_reorder_release() doesn't re-arm the timer */ spin_lock_bh(&tid_rx->reorder_lock); tid_rx->removed = true; spin_unlock_bh(&tid_rx->reorder_lock); - del_timer_sync(&tid_rx->reorder_timer); + timer_delete_sync(&tid_rx->reorder_timer); call_rcu(&tid_rx->rcu_head, ieee80211_free_tid_rx); }
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index 63a5e48..8dc8c3c9 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c
@@ -362,8 +362,8 @@ int __ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, ht_dbg(sta->sdata, "Tx BA session stop requested for %pM tid %u\n", sta->sta.addr, tid); - del_timer_sync(&tid_tx->addba_resp_timer); - del_timer_sync(&tid_tx->session_timer); + timer_delete_sync(&tid_tx->addba_resp_timer); + timer_delete_sync(&tid_tx->session_timer); /* * After this packets are no longer handed right through @@ -1002,7 +1002,7 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local, return; } - del_timer_sync(&tid_tx->addba_resp_timer); + timer_delete_sync(&tid_tx->addba_resp_timer); ht_dbg(sta->sdata, "switched off addBA timer for %pM tid %d\n", sta->sta.addr, tid);
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 05a945df..4246d16 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c
@@ -1844,7 +1844,7 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata) skb_queue_purge(&sdata->skb_queue); - del_timer_sync(&sdata->u.ibss.timer); + timer_delete_sync(&sdata->u.ibss.timer); return 0; }
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index b042304..f0f4a25 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c
@@ -526,7 +526,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, bool going_do netif_addr_unlock_bh(sdata->dev); } - del_timer_sync(&local->dynamic_ps_timer); + timer_delete_sync(&local->dynamic_ps_timer); wiphy_work_cancel(local->hw.wiphy, &local->dynamic_ps_enable_work); WARN(ieee80211_vif_is_mld(&sdata->vif),
diff --git a/net/mac80211/led.c b/net/mac80211/led.c index 2dc7321..885fa6aa 100644 --- a/net/mac80211/led.c +++ b/net/mac80211/led.c
@@ -342,7 +342,7 @@ static void ieee80211_stop_tpt_led_trig(struct ieee80211_local *local) return; tpt_trig->running = false; - del_timer_sync(&tpt_trig->timer); + timer_delete_sync(&tpt_trig->timer); led_trigger_event(&local->tpt_led, LED_OFF); }
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 9740813..7257f56 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c
@@ -706,7 +706,7 @@ void ieee80211_mesh_root_setup(struct ieee80211_if_mesh *ifmsh) else { clear_bit(MESH_WORK_ROOT, &ifmsh->wrkq_flags); /* stop running timer */ - del_timer_sync(&ifmsh->mesh_path_root_timer); + timer_delete_sync(&ifmsh->mesh_path_root_timer); } } @@ -1241,9 +1241,9 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata) local->total_ps_buffered -= skb_queue_len(&ifmsh->ps.bc_buf); skb_queue_purge(&ifmsh->ps.bc_buf); - del_timer_sync(&sdata->u.mesh.housekeeping_timer); - del_timer_sync(&sdata->u.mesh.mesh_path_root_timer); - del_timer_sync(&sdata->u.mesh.mesh_path_timer); + timer_delete_sync(&sdata->u.mesh.housekeeping_timer); + timer_delete_sync(&sdata->u.mesh.mesh_path_root_timer); + timer_delete_sync(&sdata->u.mesh.mesh_path_timer); /* clear any mesh work (for next join) we may have accrued */ ifmsh->wrkq_flags = 0;
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index 5a0156e..96e0a86 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c
@@ -417,7 +417,7 @@ u64 mesh_plink_deactivate(struct sta_info *sta) } spin_unlock_bh(&sta->mesh->plink_lock); if (!sdata->u.mesh.user_mpm) - del_timer_sync(&sta->mesh->plink_timer); + timer_delete_sync(&sta->mesh->plink_timer); mesh_path_flush_by_nexthop(sta); /* make sure no readers can access nexthop sta from here on */ @@ -666,7 +666,7 @@ void mesh_plink_timer(struct timer_list *t) /* * This STA is valid because sta_info_destroy() will - * del_timer_sync() this timer after having made sure + * timer_delete_sync() this timer after having made sure * it cannot be re-added (by deleting the plink.) */ sta = mesh->plink_sta; @@ -689,7 +689,7 @@ void mesh_plink_timer(struct timer_list *t) return; } - /* del_timer() and handler may race when entering these states */ + /* timer_delete() and handler may race when entering these states */ if (sta->mesh->plink_state == NL80211_PLINK_LISTEN || sta->mesh->plink_state == NL80211_PLINK_ESTAB) { mpl_dbg(sta->sdata, @@ -735,7 +735,7 @@ void mesh_plink_timer(struct timer_list *t) break; case NL80211_PLINK_HOLDING: /* holding timer */ - del_timer(&sta->mesh->plink_timer); + timer_delete(&sta->mesh->plink_timer); mesh_plink_fsm_restart(sta); break; default: @@ -848,7 +848,7 @@ static u64 mesh_plink_establish(struct ieee80211_sub_if_data *sdata, struct mesh_config *mshcfg = &sdata->u.mesh.mshcfg; u64 changed = 0; - del_timer(&sta->mesh->plink_timer); + timer_delete(&sta->mesh->plink_timer); sta->mesh->plink_state = NL80211_PLINK_ESTAB; changed |= mesh_plink_inc_estab_count(sdata); changed |= mesh_set_ht_prot_mode(sdata); @@ -975,7 +975,7 @@ static u64 mesh_plink_fsm(struct ieee80211_sub_if_data *sdata, case NL80211_PLINK_HOLDING: switch (event) { case CLS_ACPT: - del_timer(&sta->mesh->plink_timer); + timer_delete(&sta->mesh->plink_timer); mesh_plink_fsm_restart(sta); break; case OPN_ACPT:
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index c010bb3..5d1f2d6 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c
@@ -3194,7 +3194,7 @@ static void ieee80211_change_ps(struct ieee80211_local *local) } else if (conf->flags & IEEE80211_CONF_PS) { conf->flags &= ~IEEE80211_CONF_PS; ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); - del_timer_sync(&local->dynamic_ps_timer); + timer_delete_sync(&local->dynamic_ps_timer); wiphy_work_cancel(local->hw.wiphy, &local->dynamic_ps_enable_work); } @@ -4069,7 +4069,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, sdata->deflink.ap_power_level = IEEE80211_UNSET_POWER_LEVEL; - del_timer_sync(&local->dynamic_ps_timer); + timer_delete_sync(&local->dynamic_ps_timer); wiphy_work_cancel(local->hw.wiphy, &local->dynamic_ps_enable_work); /* Disable ARP filtering */ @@ -4097,9 +4097,9 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, /* disassociated - set to defaults now */ ieee80211_set_wmm_default(&sdata->deflink, false, false); - del_timer_sync(&sdata->u.mgd.conn_mon_timer); - del_timer_sync(&sdata->u.mgd.bcn_mon_timer); - del_timer_sync(&sdata->u.mgd.timer); + timer_delete_sync(&sdata->u.mgd.conn_mon_timer); + timer_delete_sync(&sdata->u.mgd.bcn_mon_timer); + timer_delete_sync(&sdata->u.mgd.timer); sdata->vif.bss_conf.dtim_period = 0; sdata->vif.bss_conf.beacon_rate = NULL; @@ -4589,7 +4589,7 @@ static void ieee80211_destroy_auth_data(struct ieee80211_sub_if_data *sdata, * running is the timeout for the authentication response which * which is not relevant anymore. */ - del_timer_sync(&sdata->u.mgd.timer); + timer_delete_sync(&sdata->u.mgd.timer); sta_info_destroy_addr(sdata, auth_data->ap_addr); /* other links are destroyed */ @@ -4628,7 +4628,7 @@ static void ieee80211_destroy_assoc_data(struct ieee80211_sub_if_data *sdata, * running is the timeout for the association response which * which is not relevant anymore. */ - del_timer_sync(&sdata->u.mgd.timer); + timer_delete_sync(&sdata->u.mgd.timer); sta_info_destroy_addr(sdata, assoc_data->ap_addr); eth_zero_addr(sdata->deflink.u.mgd.bssid); @@ -9852,7 +9852,7 @@ void ieee80211_mgd_stop(struct ieee80211_sub_if_data *sdata) ifmgd->assoc_req_ies = NULL; ifmgd->assoc_req_ies_len = 0; spin_unlock_bh(&ifmgd->teardown_lock); - del_timer_sync(&ifmgd->timer); + timer_delete_sync(&ifmgd->timer); } void ieee80211_cqm_rssi_notify(struct ieee80211_vif *vif,
diff --git a/net/mac80211/ocb.c b/net/mac80211/ocb.c index 6218abc..ece1e83 100644 --- a/net/mac80211/ocb.c +++ b/net/mac80211/ocb.c
@@ -230,7 +230,7 @@ int ieee80211_ocb_leave(struct ieee80211_sub_if_data *sdata) skb_queue_purge(&sdata->skb_queue); - del_timer_sync(&sdata->u.ocb.housekeeping_timer); + timer_delete_sync(&sdata->u.ocb.housekeeping_timer); /* If the timer fired while we waited for it, it will have * requeued the work. Now the work will be running again * but will not rearm the timer again because it checks
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c index 29fab7a..2b9abc2 100644 --- a/net/mac80211/offchannel.c +++ b/net/mac80211/offchannel.c
@@ -30,9 +30,9 @@ static void ieee80211_offchannel_ps_enable(struct ieee80211_sub_if_data *sdata) /* FIXME: what to do when local->pspolling is true? */ - del_timer_sync(&local->dynamic_ps_timer); - del_timer_sync(&ifmgd->bcn_mon_timer); - del_timer_sync(&ifmgd->conn_mon_timer); + timer_delete_sync(&local->dynamic_ps_timer); + timer_delete_sync(&ifmgd->bcn_mon_timer); + timer_delete_sync(&ifmgd->conn_mon_timer); wiphy_work_cancel(local->hw.wiphy, &local->dynamic_ps_enable_work);
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c index 7be52345..a9cc832 100644 --- a/net/mac80211/pm.c +++ b/net/mac80211/pm.c
@@ -69,14 +69,14 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) flush_workqueue(local->workqueue); /* Don't try to run timers while suspended. */ - del_timer_sync(&local->sta_cleanup); + timer_delete_sync(&local->sta_cleanup); /* * Note that this particular timer doesn't need to be * restarted at resume. */ wiphy_work_cancel(local->hw.wiphy, &local->dynamic_ps_enable_work); - del_timer_sync(&local->dynamic_ps_timer); + timer_delete_sync(&local->dynamic_ps_timer); local->wowlan = wowlan; if (local->wowlan) {
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index f7f89cd..09beb65 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c
@@ -1242,7 +1242,7 @@ static void ieee80211_sta_reorder_release(struct ieee80211_sub_if_data *sdata, tid_agg_rx->reorder_time[j] + 1 + HT_RX_REORDER_BUF_TIMEOUT); } else { - del_timer(&tid_agg_rx->reorder_timer); + timer_delete(&tid_agg_rx->reorder_timer); } }
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 30cdc78..248e1f6 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c
@@ -1592,7 +1592,7 @@ int sta_info_init(struct ieee80211_local *local) void sta_info_stop(struct ieee80211_local *local) { - del_timer_sync(&local->sta_cleanup); + timer_delete_sync(&local->sta_cleanup); rhltable_destroy(&local->sta_hash); rhltable_destroy(&local->link_sta_hash); }
diff --git a/net/mctp/af_mctp.c b/net/mctp/af_mctp.c index f6de136..dd89561 100644 --- a/net/mctp/af_mctp.c +++ b/net/mctp/af_mctp.c
@@ -663,7 +663,7 @@ static void mctp_sk_unhash(struct sock *sk) * keys), stop any pending expiry events. the timer cannot be re-queued * as the sk is no longer observable */ - del_timer_sync(&msk->key_expiry); + timer_delete_sync(&msk->key_expiry); } static void mctp_sk_destruct(struct sock *sk)
diff --git a/net/mptcp/pm.c b/net/mptcp/pm.c index 18b19db..31747f9 100644 --- a/net/mptcp/pm.c +++ b/net/mptcp/pm.c
@@ -327,7 +327,7 @@ mptcp_pm_del_add_timer(struct mptcp_sock *msk, list_del(&entry->list); spin_unlock_bh(&msk->pm.lock); - /* no lock, because sk_stop_timer_sync() is calling del_timer_sync() */ + /* no lock, because sk_stop_timer_sync() is calling timer_delete_sync() */ if (add_timer) sk_stop_timer_sync(sk, add_timer);
diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c index efe8d86..409bd41 100644 --- a/net/mptcp/subflow.c +++ b/net/mptcp/subflow.c
@@ -754,8 +754,6 @@ static bool subflow_hmac_valid(const struct request_sock *req, subflow_req = mptcp_subflow_rsk(req); msk = subflow_req->msk; - if (!msk) - return false; subflow_generate_hmac(READ_ONCE(msk->remote_key), READ_ONCE(msk->local_key), @@ -850,12 +848,8 @@ static struct sock *subflow_syn_recv_sock(const struct sock *sk, } else if (subflow_req->mp_join) { mptcp_get_options(skb, &mp_opt); - if (!(mp_opt.suboptions & OPTION_MPTCP_MPJ_ACK) || - !subflow_hmac_valid(req, &mp_opt) || - !mptcp_can_accept_new_subflow(subflow_req->msk)) { - SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_JOINACKMAC); + if (!(mp_opt.suboptions & OPTION_MPTCP_MPJ_ACK)) fallback = true; - } } create_child: @@ -905,6 +899,13 @@ static struct sock *subflow_syn_recv_sock(const struct sock *sk, goto dispose_child; } + if (!subflow_hmac_valid(req, &mp_opt) || + !mptcp_can_accept_new_subflow(subflow_req->msk)) { + SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_JOINACKMAC); + subflow_add_reset_reason(skb, MPTCP_RST_EPROHIBIT); + goto dispose_child; + } + /* move the msk reference ownership to the subflow */ subflow_req->msk = NULL; ctx->conn = (struct sock *)owner;
diff --git a/net/ncsi/ncsi-manage.c b/net/ncsi/ncsi-manage.c index 7891a53..b369470 100644 --- a/net/ncsi/ncsi-manage.c +++ b/net/ncsi/ncsi-manage.c
@@ -189,7 +189,7 @@ void ncsi_stop_channel_monitor(struct ncsi_channel *nc) nc->monitor.enabled = false; spin_unlock_irqrestore(&nc->lock, flags); - del_timer_sync(&nc->monitor.timer); + timer_delete_sync(&nc->monitor.timer); } struct ncsi_channel *ncsi_find_channel(struct ncsi_package *np, @@ -396,7 +396,7 @@ void ncsi_free_request(struct ncsi_request *nr) if (nr->enabled) { nr->enabled = false; - del_timer_sync(&nr->timer); + timer_delete_sync(&nr->timer); } spin_lock_irqsave(&ndp->lock, flags);
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig index df2dc21..047ba81 100644 --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig
@@ -212,7 +212,7 @@ bool 'SCTP protocol connection tracking support' depends on NETFILTER_ADVANCED default y - select LIBCRC32C + select CRC32 help With this option enabled, the layer 3 independent connection tracking code will be able to do state tracking on SCTP connections. @@ -475,7 +475,7 @@ config NF_TABLES select NETFILTER_NETLINK - select LIBCRC32C + select CRC32 tristate "Netfilter nf_tables support" help nftables is the new packet classification framework that intends to
diff --git a/net/netfilter/ipset/ip_set_bitmap_gen.h b/net/netfilter/ipset/ip_set_bitmap_gen.h index cb48a2b..6ae042f 100644 --- a/net/netfilter/ipset/ip_set_bitmap_gen.h +++ b/net/netfilter/ipset/ip_set_bitmap_gen.h
@@ -294,7 +294,7 @@ mtype_cancel_gc(struct ip_set *set) struct mtype *map = set->data; if (SET_WITH_TIMEOUT(set)) - del_timer_sync(&map->gc); + timer_delete_sync(&map->gc); } static const struct ip_set_type_variant mtype = {
diff --git a/net/netfilter/ipvs/Kconfig b/net/netfilter/ipvs/Kconfig index 2a3017b..8c5b1fe 100644 --- a/net/netfilter/ipvs/Kconfig +++ b/net/netfilter/ipvs/Kconfig
@@ -105,7 +105,7 @@ config IP_VS_PROTO_SCTP bool "SCTP load balancing support" - select LIBCRC32C + select CRC32 help This option enables support for load balancing SCTP transport protocol. Say Y if unsure.
diff --git a/net/netfilter/ipvs/ip_vs_conn.c b/net/netfilter/ipvs/ip_vs_conn.c index 20a1727..8699944 100644 --- a/net/netfilter/ipvs/ip_vs_conn.c +++ b/net/netfilter/ipvs/ip_vs_conn.c
@@ -822,7 +822,7 @@ static void ip_vs_conn_rcu_free(struct rcu_head *head) /* Try to delete connection while not holding reference */ static void ip_vs_conn_del(struct ip_vs_conn *cp) { - if (del_timer(&cp->timer)) { + if (timer_delete(&cp->timer)) { /* Drop cp->control chain too */ if (cp->control) cp->timeout = 0; @@ -833,7 +833,7 @@ static void ip_vs_conn_del(struct ip_vs_conn *cp) /* Try to delete connection while holding reference */ static void ip_vs_conn_del_put(struct ip_vs_conn *cp) { - if (del_timer(&cp->timer)) { + if (timer_delete(&cp->timer)) { /* Drop cp->control chain too */ if (cp->control) cp->timeout = 0; @@ -860,7 +860,7 @@ static void ip_vs_conn_expire(struct timer_list *t) struct ip_vs_conn *ct = cp->control; /* delete the timer if it is activated by other users */ - del_timer(&cp->timer); + timer_delete(&cp->timer); /* does anybody control me? */ if (ct) {
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c index 0633276..7d5b741 100644 --- a/net/netfilter/ipvs/ip_vs_ctl.c +++ b/net/netfilter/ipvs/ip_vs_ctl.c
@@ -848,7 +848,7 @@ static void ip_vs_trash_cleanup(struct netns_ipvs *ipvs) { struct ip_vs_dest *dest, *nxt; - del_timer_sync(&ipvs->dest_trash_timer); + timer_delete_sync(&ipvs->dest_trash_timer); /* No need to use dest_trash_lock */ list_for_each_entry_safe(dest, nxt, &ipvs->dest_trash, t_list) { list_del(&dest->t_list);
diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c index 21fa550..21d22fa 100644 --- a/net/netfilter/nf_conntrack_expect.c +++ b/net/netfilter/nf_conntrack_expect.c
@@ -118,7 +118,7 @@ nf_ct_exp_equal(const struct nf_conntrack_tuple *tuple, bool nf_ct_remove_expect(struct nf_conntrack_expect *exp) { - if (del_timer(&exp->timeout)) { + if (timer_delete(&exp->timeout)) { nf_ct_unlink_expect(exp); nf_ct_expect_put(exp); return true; @@ -214,11 +214,11 @@ nf_ct_find_expectation(struct net *net, if (exp->flags & NF_CT_EXPECT_PERMANENT || !unlink) { refcount_inc(&exp->use); return exp; - } else if (del_timer(&exp->timeout)) { + } else if (timer_delete(&exp->timeout)) { nf_ct_unlink_expect(exp); return exp; } - /* Undo exp->master refcnt increase, if del_timer() failed */ + /* Undo exp->master refcnt increase, if timer_delete() failed */ nf_ct_put(exp->master); return NULL; @@ -520,7 +520,7 @@ void nf_ct_expect_iterate_destroy(bool (*iter)(struct nf_conntrack_expect *e, vo hlist_for_each_entry_safe(exp, next, &nf_ct_expect_hash[i], hnode) { - if (iter(exp, data) && del_timer(&exp->timeout)) { + if (iter(exp, data) && timer_delete(&exp->timeout)) { nf_ct_unlink_expect(exp); nf_ct_expect_put(exp); } @@ -550,7 +550,7 @@ void nf_ct_expect_iterate_net(struct net *net, if (!net_eq(nf_ct_exp_net(exp), net)) continue; - if (iter(exp, data) && del_timer(&exp->timeout)) { + if (iter(exp, data) && timer_delete(&exp->timeout)) { nf_ct_unlink_expect_report(exp, portid, report); nf_ct_expect_put(exp); }
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index db23876..2cc0fde 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c
@@ -3448,7 +3448,7 @@ static int ctnetlink_del_expect(struct sk_buff *skb, /* after list removal, usage count == 1 */ spin_lock_bh(&nf_conntrack_expect_lock); - if (del_timer(&exp->timeout)) { + if (timer_delete(&exp->timeout)) { nf_ct_unlink_expect_report(exp, NETLINK_CB(skb).portid, nlmsg_report(info->nlh)); nf_ct_expect_put(exp); @@ -3477,7 +3477,7 @@ ctnetlink_change_expect(struct nf_conntrack_expect *x, const struct nlattr * const cda[]) { if (cda[CTA_EXPECT_TIMEOUT]) { - if (!del_timer(&x->timeout)) + if (!timer_delete(&x->timeout)) return -ETIME; x->timeout.expires = jiffies +
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index c2df81b..a133e1c 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c
@@ -2839,11 +2839,11 @@ static int nf_tables_updchain(struct nft_ctx *ctx, u8 genmask, u8 policy, err = nft_netdev_register_hooks(ctx->net, &hook.list); if (err < 0) goto err_hooks; + + unregister = true; } } - unregister = true; - if (nla[NFTA_CHAIN_COUNTERS]) { if (!nft_is_base_chain(chain)) { err = -EOPNOTSUPP;
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index 134e05d..882962f 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c
@@ -381,7 +381,7 @@ static void __nfulnl_flush(struct nfulnl_instance *inst) { /* timer holds a reference */ - if (del_timer(&inst->timer)) + if (timer_delete(&inst->timer)) instance_put(inst); if (inst->skb) __nfulnl_send(inst);
diff --git a/net/netfilter/nft_set_hash.c b/net/netfilter/nft_set_hash.c index 8bfac41..abb0c8e 100644 --- a/net/netfilter/nft_set_hash.c +++ b/net/netfilter/nft_set_hash.c
@@ -309,7 +309,8 @@ static bool nft_rhash_expr_needs_gc_run(const struct nft_set *set, nft_setelem_expr_foreach(expr, elem_expr, size) { if (expr->ops->gc && - expr->ops->gc(read_pnet(&set->net), expr)) + expr->ops->gc(read_pnet(&set->net), expr) && + set->flags & NFT_SET_EVAL) return true; }
diff --git a/net/netfilter/nft_tunnel.c b/net/netfilter/nft_tunnel.c index 681301b..0c63d13 100644 --- a/net/netfilter/nft_tunnel.c +++ b/net/netfilter/nft_tunnel.c
@@ -335,13 +335,13 @@ static int nft_tunnel_obj_erspan_init(const struct nlattr *attr, static const struct nla_policy nft_tunnel_opts_geneve_policy[NFTA_TUNNEL_KEY_GENEVE_MAX + 1] = { [NFTA_TUNNEL_KEY_GENEVE_CLASS] = { .type = NLA_U16 }, [NFTA_TUNNEL_KEY_GENEVE_TYPE] = { .type = NLA_U8 }, - [NFTA_TUNNEL_KEY_GENEVE_DATA] = { .type = NLA_BINARY, .len = 128 }, + [NFTA_TUNNEL_KEY_GENEVE_DATA] = { .type = NLA_BINARY, .len = 127 }, }; static int nft_tunnel_obj_geneve_init(const struct nlattr *attr, struct nft_tunnel_opts *opts) { - struct geneve_opt *opt = (struct geneve_opt *)opts->u.data + opts->len; + struct geneve_opt *opt = (struct geneve_opt *)(opts->u.data + opts->len); struct nlattr *tb[NFTA_TUNNEL_KEY_GENEVE_MAX + 1]; int err, data_len; @@ -625,7 +625,7 @@ static int nft_tunnel_opts_dump(struct sk_buff *skb, if (!inner) goto failure; while (opts->len > offset) { - opt = (struct geneve_opt *)opts->u.data + offset; + opt = (struct geneve_opt *)(opts->u.data + offset); if (nla_put_be16(skb, NFTA_TUNNEL_KEY_GENEVE_CLASS, opt->opt_class) || nla_put_u8(skb, NFTA_TUNNEL_KEY_GENEVE_TYPE,
diff --git a/net/netrom/nr_loopback.c b/net/netrom/nr_loopback.c index 511819f..7a9d765b 100644 --- a/net/netrom/nr_loopback.c +++ b/net/netrom/nr_loopback.c
@@ -68,6 +68,6 @@ static void nr_loopback_timer(struct timer_list *unused) void nr_loopback_clear(void) { - del_timer_sync(&loopback_timer); + timer_delete_sync(&loopback_timer); skb_queue_purge(&loopback_queue); }
diff --git a/net/nfc/core.c b/net/nfc/core.c index e58dc64..75ed8a9 100644 --- a/net/nfc/core.c +++ b/net/nfc/core.c
@@ -464,7 +464,7 @@ int nfc_deactivate_target(struct nfc_dev *dev, u32 target_idx, u8 mode) } if (dev->ops->check_presence) - del_timer_sync(&dev->check_pres_timer); + timer_delete_sync(&dev->check_pres_timer); dev->ops->deactivate_target(dev, dev->active_target, mode); dev->active_target = NULL; @@ -509,7 +509,7 @@ int nfc_data_exchange(struct nfc_dev *dev, u32 target_idx, struct sk_buff *skb, } if (dev->ops->check_presence) - del_timer_sync(&dev->check_pres_timer); + timer_delete_sync(&dev->check_pres_timer); rc = dev->ops->im_transceive(dev, dev->active_target, skb, cb, cb_context); @@ -1172,7 +1172,7 @@ void nfc_unregister_device(struct nfc_dev *dev) device_unlock(&dev->dev); if (dev->ops->check_presence) { - del_timer_sync(&dev->check_pres_timer); + timer_delete_sync(&dev->check_pres_timer); cancel_work_sync(&dev->check_pres_work); }
diff --git a/net/nfc/hci/core.c b/net/nfc/hci/core.c index ceb87db..aa49334 100644 --- a/net/nfc/hci/core.c +++ b/net/nfc/hci/core.c
@@ -148,7 +148,7 @@ static void nfc_hci_msg_rx_work(struct work_struct *work) static void __nfc_hci_cmd_completion(struct nfc_hci_dev *hdev, int err, struct sk_buff *skb) { - del_timer_sync(&hdev->cmd_timer); + timer_delete_sync(&hdev->cmd_timer); if (hdev->cmd_pending_msg->cb) hdev->cmd_pending_msg->cb(hdev->cmd_pending_msg->cb_context, @@ -1046,7 +1046,7 @@ void nfc_hci_unregister_device(struct nfc_hci_dev *hdev) mutex_unlock(&hdev->msg_tx_mutex); - del_timer_sync(&hdev->cmd_timer); + timer_delete_sync(&hdev->cmd_timer); cancel_work_sync(&hdev->msg_tx_work); cancel_work_sync(&hdev->msg_rx_work);
diff --git a/net/nfc/hci/llc_shdlc.c b/net/nfc/hci/llc_shdlc.c index e90f703..ce9c683 100644 --- a/net/nfc/hci/llc_shdlc.c +++ b/net/nfc/hci/llc_shdlc.c
@@ -198,7 +198,7 @@ static void llc_shdlc_reset_t2(struct llc_shdlc *shdlc, int y_nr) if (skb_queue_empty(&shdlc->ack_pending_q)) { if (shdlc->t2_active) { - del_timer_sync(&shdlc->t2_timer); + timer_delete_sync(&shdlc->t2_timer); shdlc->t2_active = false; pr_debug("All sent frames acked. Stopped T2(retransmit)\n"); @@ -289,7 +289,7 @@ static void llc_shdlc_rcv_rej(struct llc_shdlc *shdlc, int y_nr) if (llc_shdlc_x_lteq_y_lt_z(shdlc->dnr, y_nr, shdlc->ns)) { if (shdlc->t2_active) { - del_timer_sync(&shdlc->t2_timer); + timer_delete_sync(&shdlc->t2_timer); shdlc->t2_active = false; pr_debug("Stopped T2(retransmit)\n"); } @@ -342,7 +342,7 @@ static void llc_shdlc_connect_complete(struct llc_shdlc *shdlc, int r) { pr_debug("result=%d\n", r); - del_timer_sync(&shdlc->connect_timer); + timer_delete_sync(&shdlc->connect_timer); if (r == 0) { shdlc->ns = 0; @@ -526,7 +526,7 @@ static void llc_shdlc_handle_send_queue(struct llc_shdlc *shdlc) (shdlc->rnr == false)) { if (shdlc->t1_active) { - del_timer_sync(&shdlc->t1_timer); + timer_delete_sync(&shdlc->t1_timer); shdlc->t1_active = false; pr_debug("Stopped T1(send ack)\n"); }
diff --git a/net/nfc/llcp_core.c b/net/nfc/llcp_core.c index 18be13f..27e863f 100644 --- a/net/nfc/llcp_core.c +++ b/net/nfc/llcp_core.c
@@ -160,14 +160,14 @@ static struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local) static void local_cleanup(struct nfc_llcp_local *local) { nfc_llcp_socket_release(local, false, ENXIO); - del_timer_sync(&local->link_timer); + timer_delete_sync(&local->link_timer); skb_queue_purge(&local->tx_queue); cancel_work_sync(&local->tx_work); cancel_work_sync(&local->rx_work); cancel_work_sync(&local->timeout_work); kfree_skb(local->rx_pending); local->rx_pending = NULL; - del_timer_sync(&local->sdreq_timer); + timer_delete_sync(&local->sdreq_timer); cancel_work_sync(&local->sdreq_timeout_work); nfc_llcp_free_sdp_tlv_list(&local->pending_sdreqs); } @@ -1536,7 +1536,7 @@ static void nfc_llcp_rx_work(struct work_struct *work) static void __nfc_llcp_recv(struct nfc_llcp_local *local, struct sk_buff *skb) { local->rx_pending = skb; - del_timer(&local->link_timer); + timer_delete(&local->link_timer); schedule_work(&local->rx_work); }
diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c index 1ec5955..0171bf3 100644 --- a/net/nfc/nci/core.c +++ b/net/nfc/nci/core.c
@@ -565,8 +565,8 @@ static int nci_close_device(struct nci_dev *ndev) * there is a queued/running cmd_work */ flush_workqueue(ndev->cmd_wq); - del_timer_sync(&ndev->cmd_timer); - del_timer_sync(&ndev->data_timer); + timer_delete_sync(&ndev->cmd_timer); + timer_delete_sync(&ndev->data_timer); mutex_unlock(&ndev->req_lock); return 0; } @@ -597,7 +597,7 @@ static int nci_close_device(struct nci_dev *ndev) /* Flush cmd wq */ flush_workqueue(ndev->cmd_wq); - del_timer_sync(&ndev->cmd_timer); + timer_delete_sync(&ndev->cmd_timer); /* Clear flags except NCI_UNREG */ ndev->flags &= BIT(NCI_UNREG);
diff --git a/net/nfc/nci/data.c b/net/nfc/nci/data.c index 3d36ea5..78f4131 100644 --- a/net/nfc/nci/data.c +++ b/net/nfc/nci/data.c
@@ -42,7 +42,7 @@ void nci_data_exchange_complete(struct nci_dev *ndev, struct sk_buff *skb, pr_debug("len %d, err %d\n", skb ? skb->len : 0, err); /* data exchange is complete, stop the data timer */ - del_timer_sync(&ndev->data_timer); + timer_delete_sync(&ndev->data_timer); clear_bit(NCI_DATA_EXCHANGE_TO, &ndev->flags); if (cb) {
diff --git a/net/nfc/nci/rsp.c b/net/nfc/nci/rsp.c index b911ab7..9eeb862 100644 --- a/net/nfc/nci/rsp.c +++ b/net/nfc/nci/rsp.c
@@ -347,7 +347,7 @@ void nci_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb) __u16 rsp_opcode = nci_opcode(skb->data); /* we got a rsp, stop the cmd timer */ - del_timer(&ndev->cmd_timer); + timer_delete(&ndev->cmd_timer); pr_debug("NCI RX: MT=rsp, PBF=%d, GID=0x%x, OID=0x%x, plen=%d\n", nci_pbf(skb->data),
diff --git a/net/openvswitch/Kconfig b/net/openvswitch/Kconfig index 2535f3f..5481bd56 100644 --- a/net/openvswitch/Kconfig +++ b/net/openvswitch/Kconfig
@@ -11,7 +11,7 @@ (!NF_NAT || NF_NAT) && \ (!NETFILTER_CONNCOUNT || NETFILTER_CONNCOUNT))) depends on PSAMPLE || !PSAMPLE - select LIBCRC32C + select CRC32 select MPLS select NET_MPLS_GSO select DST_CACHE
diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c index 704c858..61fea7b 100644 --- a/net/openvswitch/actions.c +++ b/net/openvswitch/actions.c
@@ -947,12 +947,6 @@ static void do_output(struct datapath *dp, struct sk_buff *skb, int out_port, pskb_trim(skb, ovs_mac_header_len(key)); } - /* Need to set the pkt_type to involve the routing layer. The - * packet movement through the OVS datapath doesn't generally - * use routing, but this is needed for tunnel cases. - */ - skb->pkt_type = PACKET_OUTGOING; - if (likely(!mru || (skb->len <= mru + vport->dev->hard_header_len))) { ovs_vport_send(vport, skb, ovs_key_mac_proto(key));
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 3e9ddf7..d4dba06 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c
@@ -581,7 +581,7 @@ static __be16 vlan_get_protocol_dgram(const struct sk_buff *skb) static void prb_del_retire_blk_timer(struct tpacket_kbdq_core *pkc) { - del_timer_sync(&pkc->retire_blk_timer); + timer_delete_sync(&pkc->retire_blk_timer); } static void prb_shutdown_retire_blk_timer(struct packet_sock *po,
diff --git a/net/rose/rose_link.c b/net/rose/rose_link.c index 0f77ae8..9f9629e 100644 --- a/net/rose/rose_link.c +++ b/net/rose/rose_link.c
@@ -32,7 +32,7 @@ static void rose_transmit_restart_request(struct rose_neigh *neigh); void rose_start_ftimer(struct rose_neigh *neigh) { - del_timer(&neigh->ftimer); + timer_delete(&neigh->ftimer); neigh->ftimer.function = rose_ftimer_expiry; neigh->ftimer.expires = @@ -43,7 +43,7 @@ void rose_start_ftimer(struct rose_neigh *neigh) static void rose_start_t0timer(struct rose_neigh *neigh) { - del_timer(&neigh->t0timer); + timer_delete(&neigh->t0timer); neigh->t0timer.function = rose_t0timer_expiry; neigh->t0timer.expires = @@ -54,12 +54,12 @@ static void rose_start_t0timer(struct rose_neigh *neigh) void rose_stop_ftimer(struct rose_neigh *neigh) { - del_timer(&neigh->ftimer); + timer_delete(&neigh->ftimer); } void rose_stop_t0timer(struct rose_neigh *neigh) { - del_timer(&neigh->t0timer); + timer_delete(&neigh->t0timer); } int rose_ftimer_running(struct rose_neigh *neigh)
diff --git a/net/rose/rose_loopback.c b/net/rose/rose_loopback.c index 036d92c..b538e39 100644 --- a/net/rose/rose_loopback.c +++ b/net/rose/rose_loopback.c
@@ -124,7 +124,7 @@ void __exit rose_loopback_clear(void) { struct sk_buff *skb; - del_timer(&loopback_timer); + timer_delete(&loopback_timer); while ((skb = skb_dequeue(&loopback_queue)) != NULL) { skb->sk = NULL;
diff --git a/net/rose/rose_route.c b/net/rose/rose_route.c index fee772b..2dd6bd3 100644 --- a/net/rose/rose_route.c +++ b/net/rose/rose_route.c
@@ -227,8 +227,8 @@ static void rose_remove_neigh(struct rose_neigh *rose_neigh) { struct rose_neigh *s; - del_timer_sync(&rose_neigh->ftimer); - del_timer_sync(&rose_neigh->t0timer); + timer_delete_sync(&rose_neigh->ftimer); + timer_delete_sync(&rose_neigh->t0timer); skb_queue_purge(&rose_neigh->queue);
diff --git a/net/rxrpc/call_event.c b/net/rxrpc/call_event.c index 8e477f7..fec59d9 100644 --- a/net/rxrpc/call_event.c +++ b/net/rxrpc/call_event.c
@@ -469,7 +469,7 @@ bool rxrpc_input_call_event(struct rxrpc_call *call) out: if (__rxrpc_call_is_complete(call)) { - del_timer_sync(&call->timer); + timer_delete_sync(&call->timer); if (!test_bit(RXRPC_CALL_DISCONNECTED, &call->flags)) rxrpc_disconnect_call(call); if (call->security)
diff --git a/net/rxrpc/call_object.c b/net/rxrpc/call_object.c index c4c8b46..fce58be 100644 --- a/net/rxrpc/call_object.c +++ b/net/rxrpc/call_object.c
@@ -688,7 +688,7 @@ static void rxrpc_destroy_call(struct work_struct *work) { struct rxrpc_call *call = container_of(work, struct rxrpc_call, destroyer); - del_timer_sync(&call->timer); + timer_delete_sync(&call->timer); rxrpc_cleanup_tx_buffers(call); rxrpc_cleanup_rx_buffers(call); @@ -711,7 +711,7 @@ void rxrpc_cleanup_call(struct rxrpc_call *call) ASSERTCMP(__rxrpc_call_state(call), ==, RXRPC_CALL_COMPLETE); ASSERT(test_bit(RXRPC_CALL_RELEASED, &call->flags)); - del_timer(&call->timer); + timer_delete(&call->timer); if (rcu_read_lock_held()) /* Can't use the rxrpc workqueue as we need to cancel/flush
diff --git a/net/rxrpc/conn_client.c b/net/rxrpc/conn_client.c index db00991..63bbcc5 100644 --- a/net/rxrpc/conn_client.c +++ b/net/rxrpc/conn_client.c
@@ -818,7 +818,7 @@ void rxrpc_clean_up_local_conns(struct rxrpc_local *local) local->kill_all_client_conns = true; - del_timer_sync(&local->client_conn_reap_timer); + timer_delete_sync(&local->client_conn_reap_timer); while ((conn = list_first_entry_or_null(&local->idle_client_conns, struct rxrpc_connection, cache_link))) {
diff --git a/net/rxrpc/conn_object.c b/net/rxrpc/conn_object.c index 2f1fd1e..8ac22dd 100644 --- a/net/rxrpc/conn_object.c +++ b/net/rxrpc/conn_object.c
@@ -314,9 +314,9 @@ static void rxrpc_clean_up_connection(struct work_struct *work) !conn->channels[3].call); ASSERT(list_empty(&conn->cache_link)); - del_timer_sync(&conn->timer); + timer_delete_sync(&conn->timer); cancel_work_sync(&conn->processor); /* Processing may restart the timer */ - del_timer_sync(&conn->timer); + timer_delete_sync(&conn->timer); write_lock(&rxnet->conn_lock); list_del_init(&conn->proc_link); @@ -365,7 +365,7 @@ void rxrpc_put_connection(struct rxrpc_connection *conn, dead = __refcount_dec_and_test(&conn->ref, &r); trace_rxrpc_conn(debug_id, r - 1, why); if (dead) { - del_timer(&conn->timer); + timer_delete(&conn->timer); cancel_work(&conn->processor); if (in_softirq() || work_busy(&conn->processor) || @@ -470,7 +470,7 @@ void rxrpc_destroy_all_connections(struct rxrpc_net *rxnet) atomic_dec(&rxnet->nr_conns); - del_timer_sync(&rxnet->service_conn_reap_timer); + timer_delete_sync(&rxnet->service_conn_reap_timer); rxrpc_queue_work(&rxnet->service_conn_reaper); flush_workqueue(rxrpc_workqueue);
diff --git a/net/rxrpc/net_ns.c b/net/rxrpc/net_ns.c index a4c135d..9a98341 100644 --- a/net/rxrpc/net_ns.c +++ b/net/rxrpc/net_ns.c
@@ -105,10 +105,10 @@ static __net_exit void rxrpc_exit_net(struct net *net) struct rxrpc_net *rxnet = rxrpc_net(net); rxnet->live = false; - del_timer_sync(&rxnet->peer_keepalive_timer); + timer_delete_sync(&rxnet->peer_keepalive_timer); cancel_work_sync(&rxnet->peer_keepalive_work); /* Remove the timer again as the worker may have restarted it. */ - del_timer_sync(&rxnet->peer_keepalive_timer); + timer_delete_sync(&rxnet->peer_keepalive_timer); rxrpc_destroy_all_calls(rxnet); rxrpc_destroy_all_connections(rxnet); rxrpc_destroy_all_peers(rxnet);
diff --git a/net/sched/Kconfig b/net/sched/Kconfig index 8180d0c..a800127 100644 --- a/net/sched/Kconfig +++ b/net/sched/Kconfig
@@ -784,7 +784,7 @@ config NET_ACT_CSUM tristate "Checksum Updating" depends on NET_CLS_ACT && INET - select LIBCRC32C + select CRC32 help Say Y here to update some common checksum after some direct packet alterations.
diff --git a/net/sched/act_tunnel_key.c b/net/sched/act_tunnel_key.c index ae5dea7..2cef4b0 100644 --- a/net/sched/act_tunnel_key.c +++ b/net/sched/act_tunnel_key.c
@@ -68,7 +68,7 @@ geneve_opt_policy[TCA_TUNNEL_KEY_ENC_OPT_GENEVE_MAX + 1] = { [TCA_TUNNEL_KEY_ENC_OPT_GENEVE_CLASS] = { .type = NLA_U16 }, [TCA_TUNNEL_KEY_ENC_OPT_GENEVE_TYPE] = { .type = NLA_U8 }, [TCA_TUNNEL_KEY_ENC_OPT_GENEVE_DATA] = { .type = NLA_BINARY, - .len = 128 }, + .len = 127 }, }; static const struct nla_policy
diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c index 0350567..099ff6a 100644 --- a/net/sched/cls_flower.c +++ b/net/sched/cls_flower.c
@@ -766,7 +766,7 @@ geneve_opt_policy[TCA_FLOWER_KEY_ENC_OPT_GENEVE_MAX + 1] = { [TCA_FLOWER_KEY_ENC_OPT_GENEVE_CLASS] = { .type = NLA_U16 }, [TCA_FLOWER_KEY_ENC_OPT_GENEVE_TYPE] = { .type = NLA_U8 }, [TCA_FLOWER_KEY_ENC_OPT_GENEVE_DATA] = { .type = NLA_BINARY, - .len = 128 }, + .len = 127 }, }; static const struct nla_policy
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index defb05c..f74a097 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c
@@ -1267,38 +1267,8 @@ static struct Qdisc *qdisc_create(struct net_device *dev, struct qdisc_size_table *stab; ops = qdisc_lookup_ops(kind); -#ifdef CONFIG_MODULES - if (ops == NULL && kind != NULL) { - char name[IFNAMSIZ]; - if (nla_strscpy(name, kind, IFNAMSIZ) >= 0) { - /* We dropped the RTNL semaphore in order to - * perform the module load. So, even if we - * succeeded in loading the module we have to - * tell the caller to replay the request. We - * indicate this using -EAGAIN. - * We replay the request because the device may - * go away in the mean time. - */ - netdev_unlock_ops(dev); - rtnl_unlock(); - request_module(NET_SCH_ALIAS_PREFIX "%s", name); - rtnl_lock(); - netdev_lock_ops(dev); - ops = qdisc_lookup_ops(kind); - if (ops != NULL) { - /* We will try again qdisc_lookup_ops, - * so don't keep a reference. - */ - module_put(ops->owner); - err = -EAGAIN; - goto err_out; - } - } - } -#endif - - err = -ENOENT; if (!ops) { + err = -ENOENT; NL_SET_ERR_MSG(extack, "Specified qdisc kind is unknown"); goto err_out; } @@ -1623,8 +1593,7 @@ static int __tc_modify_qdisc(struct sk_buff *skb, struct nlmsghdr *n, struct netlink_ext_ack *extack, struct net_device *dev, struct nlattr *tca[TCA_MAX + 1], - struct tcmsg *tcm, - bool *replay) + struct tcmsg *tcm) { struct Qdisc *q = NULL; struct Qdisc *p = NULL; @@ -1789,13 +1758,8 @@ static int __tc_modify_qdisc(struct sk_buff *skb, struct nlmsghdr *n, tcm->tcm_parent, tcm->tcm_handle, tca, &err, extack); } - if (q == NULL) { - if (err == -EAGAIN) { - *replay = true; - return 0; - } + if (!q) return err; - } graft: err = qdisc_graft(dev, p, skb, n, clid, q, NULL, extack); @@ -1808,6 +1772,27 @@ static int __tc_modify_qdisc(struct sk_buff *skb, struct nlmsghdr *n, return 0; } +static void request_qdisc_module(struct nlattr *kind) +{ + struct Qdisc_ops *ops; + char name[IFNAMSIZ]; + + if (!kind) + return; + + ops = qdisc_lookup_ops(kind); + if (ops) { + module_put(ops->owner); + return; + } + + if (nla_strscpy(name, kind, IFNAMSIZ) >= 0) { + rtnl_unlock(); + request_module(NET_SCH_ALIAS_PREFIX "%s", name); + rtnl_lock(); + } +} + /* * Create/change qdisc. */ @@ -1818,27 +1803,23 @@ static int tc_modify_qdisc(struct sk_buff *skb, struct nlmsghdr *n, struct nlattr *tca[TCA_MAX + 1]; struct net_device *dev; struct tcmsg *tcm; - bool replay; int err; -replay: - /* Reinit, just in case something touches this. */ err = nlmsg_parse_deprecated(n, sizeof(*tcm), tca, TCA_MAX, rtm_tca_policy, extack); if (err < 0) return err; + request_qdisc_module(tca[TCA_KIND]); + tcm = nlmsg_data(n); dev = __dev_get_by_index(net, tcm->tcm_ifindex); if (!dev) return -ENODEV; - replay = false; netdev_lock_ops(dev); - err = __tc_modify_qdisc(skb, n, extack, dev, tca, tcm, &replay); + err = __tc_modify_qdisc(skb, n, extack, dev, tca, tcm); netdev_unlock_ops(dev); - if (replay) - goto replay; return err; }
diff --git a/net/sched/sch_fq_pie.c b/net/sched/sch_fq_pie.c index 93c36af..f3b8203 100644 --- a/net/sched/sch_fq_pie.c +++ b/net/sched/sch_fq_pie.c
@@ -555,7 +555,7 @@ static void fq_pie_destroy(struct Qdisc *sch) tcf_block_put(q->block); q->p_params.tupdate = 0; - del_timer_sync(&q->adapt_timer); + timer_delete_sync(&q->adapt_timer); kvfree(q->flows); }
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index 14ab2f4..514b1b6 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c
@@ -567,7 +567,7 @@ EXPORT_SYMBOL_GPL(netdev_watchdog_up); static void netdev_watchdog_down(struct net_device *dev) { netif_tx_lock_bh(dev); - if (del_timer(&dev->watchdog_timer)) + if (timer_delete(&dev->watchdog_timer)) netdev_put(dev, &dev->watchdog_dev_tracker); netif_tx_unlock_bh(dev); }
diff --git a/net/sched/sch_pie.c b/net/sched/sch_pie.c index bb1fa9a..3771d00 100644 --- a/net/sched/sch_pie.c +++ b/net/sched/sch_pie.c
@@ -545,7 +545,7 @@ static void pie_destroy(struct Qdisc *sch) struct pie_sched_data *q = qdisc_priv(sch); q->params.tupdate = 0; - del_timer_sync(&q->adapt_timer); + timer_delete_sync(&q->adapt_timer); } static struct Qdisc_ops pie_qdisc_ops __read_mostly = {
diff --git a/net/sched/sch_red.c b/net/sched/sch_red.c index ef8a2af..1ba3e0b 100644 --- a/net/sched/sch_red.c +++ b/net/sched/sch_red.c
@@ -218,7 +218,7 @@ static void red_destroy(struct Qdisc *sch) tcf_qevent_destroy(&q->qe_mark, sch); tcf_qevent_destroy(&q->qe_early_drop, sch); - del_timer_sync(&q->adapt_timer); + timer_delete_sync(&q->adapt_timer); red_offload(sch, false); qdisc_put(q->qdisc); } @@ -297,7 +297,7 @@ static int __red_change(struct Qdisc *sch, struct nlattr **tb, max_P); red_set_vars(&q->vars); - del_timer(&q->adapt_timer); + timer_delete(&q->adapt_timer); if (ctl->flags & TC_RED_ADAPTATIVE) mod_timer(&q->adapt_timer, jiffies + HZ/2);
diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c index 65d5b59..9ed197e 100644 --- a/net/sched/sch_sfq.c +++ b/net/sched/sch_sfq.c
@@ -696,7 +696,7 @@ static int sfq_change(struct Qdisc *sch, struct nlattr *opt, rtnl_kfree_skbs(to_free, tail); qdisc_tree_reduce_backlog(sch, qlen - sch->q.qlen, dropped); - del_timer(&q->perturb_timer); + timer_delete(&q->perturb_timer); if (q->perturb_period) { mod_timer(&q->perturb_timer, jiffies + q->perturb_period); get_random_bytes(&q->perturbation, sizeof(q->perturbation)); @@ -722,7 +722,7 @@ static void sfq_destroy(struct Qdisc *sch) tcf_block_put(q->block); WRITE_ONCE(q->perturb_period, 0); - del_timer_sync(&q->perturb_timer); + timer_delete_sync(&q->perturb_timer); sfq_free(q->ht); sfq_free(q->slots); kfree(q->red_parms);
diff --git a/net/sched/sch_skbprio.c b/net/sched/sch_skbprio.c index 20ff738..f485f62 100644 --- a/net/sched/sch_skbprio.c +++ b/net/sched/sch_skbprio.c
@@ -123,8 +123,6 @@ static int skbprio_enqueue(struct sk_buff *skb, struct Qdisc *sch, /* Check to update highest and lowest priorities. */ if (skb_queue_empty(lp_qdisc)) { if (q->lowest_prio == q->highest_prio) { - /* The incoming packet is the only packet in queue. */ - BUG_ON(sch->q.qlen != 1); q->lowest_prio = prio; q->highest_prio = prio; } else { @@ -156,7 +154,6 @@ static struct sk_buff *skbprio_dequeue(struct Qdisc *sch) /* Update highest priority field. */ if (skb_queue_empty(hpq)) { if (q->lowest_prio == q->highest_prio) { - BUG_ON(sch->q.qlen); q->highest_prio = 0; q->lowest_prio = SKBPRIO_MAX_PRIORITY - 1; } else {
diff --git a/net/sctp/Kconfig b/net/sctp/Kconfig index 5da599f..d18a72d 100644 --- a/net/sctp/Kconfig +++ b/net/sctp/Kconfig
@@ -7,10 +7,10 @@ tristate "The SCTP Protocol" depends on INET depends on IPV6 || IPV6=n + select CRC32 select CRYPTO select CRYPTO_HMAC select CRYPTO_SHA1 - select LIBCRC32C select NET_UDP_TUNNEL help Stream Control Transmission Protocol
diff --git a/net/sctp/associola.c b/net/sctp/associola.c index 0b0794f..760152e 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c
@@ -362,7 +362,7 @@ void sctp_association_free(struct sctp_association *asoc) * on our state. */ for (i = SCTP_EVENT_TIMEOUT_NONE; i < SCTP_NUM_TIMEOUT_TYPES; ++i) { - if (del_timer(&asoc->timers[i])) + if (timer_delete(&asoc->timers[i])) sctp_association_put(asoc); } @@ -1521,7 +1521,7 @@ void sctp_assoc_rwnd_increase(struct sctp_association *asoc, unsigned int len) /* Stop the SACK timer. */ timer = &asoc->timers[SCTP_EVENT_TIMEOUT_SACK]; - if (del_timer(timer)) + if (timer_delete(timer)) sctp_association_put(asoc); } }
diff --git a/net/sctp/input.c b/net/sctp/input.c index a8a254a..0c0d275 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c
@@ -446,7 +446,7 @@ void sctp_icmp_proto_unreachable(struct sock *sk, pr_debug("%s: unrecognized next header type " "encountered!\n", __func__); - if (del_timer(&t->proto_unreach_timer)) + if (timer_delete(&t->proto_unreach_timer)) sctp_transport_put(t); sctp_do_sm(net, SCTP_EVENT_T_OTHER,
diff --git a/net/sctp/output.c b/net/sctp/output.c index a63df05..23e9630 100644 --- a/net/sctp/output.c +++ b/net/sctp/output.c
@@ -312,7 +312,7 @@ static enum sctp_xmit sctp_packet_bundle_sack(struct sctp_packet *pkt, SCTP_MIB_OUTCTRLCHUNKS); asoc->stats.octrlchunks++; asoc->peer.sack_needed = 0; - if (del_timer(timer)) + if (timer_delete(timer)) sctp_association_put(asoc); } }
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c index 0dc6b8a..f6b8c13 100644 --- a/net/sctp/outqueue.c +++ b/net/sctp/outqueue.c
@@ -1630,8 +1630,7 @@ static void sctp_check_transmitted(struct sctp_outq *q, * as the receiver acknowledged any data. */ if (asoc->state == SCTP_STATE_SHUTDOWN_PENDING && - del_timer(&asoc->timers - [SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD])) + timer_delete(&asoc->timers[SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD])) sctp_association_put(asoc); /* Mark the destination transport address as @@ -1688,7 +1687,7 @@ static void sctp_check_transmitted(struct sctp_outq *q, * address. */ if (!transport->flight_size) { - if (del_timer(&transport->T3_rtx_timer)) + if (timer_delete(&transport->T3_rtx_timer)) sctp_transport_put(transport); } else if (restart_timer) { if (!mod_timer(&transport->T3_rtx_timer,
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index 5407a39..8c3b80c 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c
@@ -695,7 +695,7 @@ static void sctp_free_addr_wq(struct net *net) struct sctp_sockaddr_entry *temp; spin_lock_bh(&net->sctp.addr_wq_lock); - del_timer(&net->sctp.addr_wq_timer); + timer_delete(&net->sctp.addr_wq_timer); list_for_each_entry_safe(addrw, temp, &net->sctp.addr_waitq, list) { list_del(&addrw->list); kfree(addrw);
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index 23d6633..3aa5da5 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c
@@ -734,7 +734,7 @@ static void sctp_cmd_hb_timers_stop(struct sctp_cmd_seq *cmds, list_for_each_entry(t, &asoc->peer.transport_addr_list, transports) { - if (del_timer(&t->hb_timer)) + if (timer_delete(&t->hb_timer)) sctp_transport_put(t); } } @@ -747,7 +747,7 @@ static void sctp_cmd_t3_rtx_timers_stop(struct sctp_cmd_seq *cmds, list_for_each_entry(t, &asoc->peer.transport_addr_list, transports) { - if (del_timer(&t->T3_rtx_timer)) + if (timer_delete(&t->T3_rtx_timer)) sctp_transport_put(t); } } @@ -1557,7 +1557,7 @@ static int sctp_cmd_interpreter(enum sctp_event_type event_type, case SCTP_CMD_TIMER_STOP: timer = &asoc->timers[cmd->obj.to]; - if (del_timer(timer)) + if (timer_delete(timer)) sctp_association_put(asoc); break;
diff --git a/net/sctp/stream.c b/net/sctp/stream.c index bfcff6d..f205556 100644 --- a/net/sctp/stream.c +++ b/net/sctp/stream.c
@@ -576,7 +576,7 @@ struct sctp_chunk *sctp_process_strreset_outreq( struct sctp_transport *t; t = asoc->strreset_chunk->transport; - if (del_timer(&t->reconf_timer)) + if (timer_delete(&t->reconf_timer)) sctp_transport_put(t); sctp_chunk_put(asoc->strreset_chunk); @@ -825,7 +825,7 @@ struct sctp_chunk *sctp_process_strreset_addstrm_out( struct sctp_transport *t; t = asoc->strreset_chunk->transport; - if (del_timer(&t->reconf_timer)) + if (timer_delete(&t->reconf_timer)) sctp_transport_put(t); sctp_chunk_put(asoc->strreset_chunk); @@ -1076,7 +1076,7 @@ struct sctp_chunk *sctp_process_strreset_resp( /* remove everything for this reconf request */ if (!asoc->strreset_outstanding) { t = asoc->strreset_chunk->transport; - if (del_timer(&t->reconf_timer)) + if (timer_delete(&t->reconf_timer)) sctp_transport_put(t); sctp_chunk_put(asoc->strreset_chunk);
diff --git a/net/sctp/sysctl.c b/net/sctp/sysctl.c index 8e1e97b..ee3eac3 100644 --- a/net/sctp/sysctl.c +++ b/net/sctp/sysctl.c
@@ -525,6 +525,8 @@ static int proc_sctp_do_auth(const struct ctl_table *ctl, int write, return ret; } +static DEFINE_MUTEX(sctp_sysctl_mutex); + static int proc_sctp_do_udp_port(const struct ctl_table *ctl, int write, void *buffer, size_t *lenp, loff_t *ppos) { @@ -549,6 +551,7 @@ static int proc_sctp_do_udp_port(const struct ctl_table *ctl, int write, if (new_value > max || new_value < min) return -EINVAL; + mutex_lock(&sctp_sysctl_mutex); net->sctp.udp_port = new_value; sctp_udp_sock_stop(net); if (new_value) { @@ -561,6 +564,7 @@ static int proc_sctp_do_udp_port(const struct ctl_table *ctl, int write, lock_sock(sk); sctp_sk(sk)->udp_port = htons(net->sctp.udp_port); release_sock(sk); + mutex_unlock(&sctp_sysctl_mutex); } return ret;
diff --git a/net/sctp/transport.c b/net/sctp/transport.c index 2abe45a..59675f6 100644 --- a/net/sctp/transport.c +++ b/net/sctp/transport.c
@@ -118,7 +118,7 @@ struct sctp_transport *sctp_transport_new(struct net *net, void sctp_transport_free(struct sctp_transport *transport) { /* Try to delete the heartbeat timer. */ - if (del_timer(&transport->hb_timer)) + if (timer_delete(&transport->hb_timer)) sctp_transport_put(transport); /* Delete the T3_rtx timer if it's active. @@ -126,17 +126,17 @@ void sctp_transport_free(struct sctp_transport *transport) * structure hang around in memory since we know * the transport is going away. */ - if (del_timer(&transport->T3_rtx_timer)) + if (timer_delete(&transport->T3_rtx_timer)) sctp_transport_put(transport); - if (del_timer(&transport->reconf_timer)) + if (timer_delete(&transport->reconf_timer)) sctp_transport_put(transport); - if (del_timer(&transport->probe_timer)) + if (timer_delete(&transport->probe_timer)) sctp_transport_put(transport); /* Delete the ICMP proto unreachable timer if it's active. */ - if (del_timer(&transport->proto_unreach_timer)) + if (timer_delete(&transport->proto_unreach_timer)) sctp_transport_put(transport); sctp_transport_put(transport); @@ -829,7 +829,7 @@ void sctp_transport_reset(struct sctp_transport *t) void sctp_transport_immediate_rtx(struct sctp_transport *t) { /* Stop pending T3_rtx_timer */ - if (del_timer(&t->T3_rtx_timer)) + if (timer_delete(&t->T3_rtx_timer)) sctp_transport_put(t); sctp_retransmit(&t->asoc->outqueue, t, SCTP_RTXR_T3_RTX);
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 2fe88ea..6f75862 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c
@@ -270,9 +270,6 @@ static struct rpc_xprt *rpc_clnt_set_transport(struct rpc_clnt *clnt, old = rcu_dereference_protected(clnt->cl_xprt, lockdep_is_held(&clnt->cl_lock)); - if (!xprt_bound(xprt)) - clnt->cl_autobind = 1; - clnt->cl_timeout = timeout; rcu_assign_pointer(clnt->cl_xprt, xprt); spin_unlock(&clnt->cl_lock); @@ -512,6 +509,8 @@ static struct rpc_clnt *rpc_create_xprt(struct rpc_create_args *args, clnt->cl_discrtry = 1; if (!(args->flags & RPC_CLNT_CREATE_QUIET)) clnt->cl_chatty = 1; + if (args->flags & RPC_CLNT_CREATE_NETUNREACH_FATAL) + clnt->cl_netunreach_fatal = 1; return clnt; } @@ -662,6 +661,7 @@ static struct rpc_clnt *__rpc_clone_client(struct rpc_create_args *args, new->cl_noretranstimeo = clnt->cl_noretranstimeo; new->cl_discrtry = clnt->cl_discrtry; new->cl_chatty = clnt->cl_chatty; + new->cl_netunreach_fatal = clnt->cl_netunreach_fatal; new->cl_principal = clnt->cl_principal; new->cl_max_connect = clnt->cl_max_connect; return new; @@ -1195,6 +1195,8 @@ void rpc_task_set_client(struct rpc_task *task, struct rpc_clnt *clnt) task->tk_flags |= RPC_TASK_TIMEOUT; if (clnt->cl_noretranstimeo) task->tk_flags |= RPC_TASK_NO_RETRANS_TIMEOUT; + if (clnt->cl_netunreach_fatal) + task->tk_flags |= RPC_TASK_NETUNREACH_FATAL; atomic_inc(&clnt->cl_task_count); } @@ -2102,14 +2104,17 @@ call_bind_status(struct rpc_task *task) case -EPROTONOSUPPORT: trace_rpcb_bind_version_err(task); goto retry_timeout; + case -ENETDOWN: + case -ENETUNREACH: + if (task->tk_flags & RPC_TASK_NETUNREACH_FATAL) + break; + fallthrough; case -ECONNREFUSED: /* connection problems */ case -ECONNRESET: case -ECONNABORTED: case -ENOTCONN: case -EHOSTDOWN: - case -ENETDOWN: case -EHOSTUNREACH: - case -ENETUNREACH: case -EPIPE: trace_rpcb_unreachable_err(task); if (!RPC_IS_SOFTCONN(task)) { @@ -2191,19 +2196,22 @@ call_connect_status(struct rpc_task *task) task->tk_status = 0; switch (status) { + case -ENETDOWN: + case -ENETUNREACH: + if (task->tk_flags & RPC_TASK_NETUNREACH_FATAL) + break; + fallthrough; case -ECONNREFUSED: case -ECONNRESET: /* A positive refusal suggests a rebind is needed. */ - if (RPC_IS_SOFTCONN(task)) - break; if (clnt->cl_autobind) { rpc_force_rebind(clnt); + if (RPC_IS_SOFTCONN(task)) + break; goto out_retry; } fallthrough; case -ECONNABORTED: - case -ENETDOWN: - case -ENETUNREACH: case -EHOSTUNREACH: case -EPIPE: case -EPROTO: @@ -2455,10 +2463,13 @@ call_status(struct rpc_task *task) trace_rpc_call_status(task); task->tk_status = 0; switch(status) { - case -EHOSTDOWN: case -ENETDOWN: - case -EHOSTUNREACH: case -ENETUNREACH: + if (task->tk_flags & RPC_TASK_NETUNREACH_FATAL) + goto out_exit; + fallthrough; + case -EHOSTDOWN: + case -EHOSTUNREACH: case -EPERM: if (RPC_IS_SOFTCONN(task)) goto out_exit;
diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c index 102c381..53bcca3 100644 --- a/net/sunrpc/rpcb_clnt.c +++ b/net/sunrpc/rpcb_clnt.c
@@ -820,9 +820,10 @@ static void rpcb_getport_done(struct rpc_task *child, void *data) } trace_rpcb_setport(child, map->r_status, map->r_port); - xprt->ops->set_port(xprt, map->r_port); - if (map->r_port) + if (map->r_port) { + xprt->ops->set_port(xprt, map->r_port); xprt_set_bound(xprt); + } } /*
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index 9b45fbd..73bc392 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c
@@ -276,6 +276,8 @@ EXPORT_SYMBOL_GPL(rpc_destroy_wait_queue); static int rpc_wait_bit_killable(struct wait_bit_key *key, int mode) { + if (unlikely(current->flags & PF_EXITING)) + return -EINTR; schedule(); if (signal_pending_state(mode, current)) return -ERESTARTSYS;
diff --git a/net/sunrpc/sysfs.c b/net/sunrpc/sysfs.c index 5c8ecda..09434e1 100644 --- a/net/sunrpc/sysfs.c +++ b/net/sunrpc/sysfs.c
@@ -59,6 +59,16 @@ static struct kobject *rpc_sysfs_object_alloc(const char *name, return NULL; } +static inline struct rpc_clnt * +rpc_sysfs_client_kobj_get_clnt(struct kobject *kobj) +{ + struct rpc_sysfs_client *c = container_of(kobj, + struct rpc_sysfs_client, kobject); + struct rpc_clnt *ret = c->clnt; + + return refcount_inc_not_zero(&ret->cl_count) ? ret : NULL; +} + static inline struct rpc_xprt * rpc_sysfs_xprt_kobj_get_xprt(struct kobject *kobj) { @@ -86,6 +96,51 @@ rpc_sysfs_xprt_switch_kobj_get_xprt(struct kobject *kobj) return xprt_switch_get(x->xprt_switch); } +static ssize_t rpc_sysfs_clnt_version_show(struct kobject *kobj, + struct kobj_attribute *attr, + char *buf) +{ + struct rpc_clnt *clnt = rpc_sysfs_client_kobj_get_clnt(kobj); + ssize_t ret; + + if (!clnt) + return sprintf(buf, "<closed>\n"); + + ret = sprintf(buf, "%u", clnt->cl_vers); + refcount_dec(&clnt->cl_count); + return ret; +} + +static ssize_t rpc_sysfs_clnt_program_show(struct kobject *kobj, + struct kobj_attribute *attr, + char *buf) +{ + struct rpc_clnt *clnt = rpc_sysfs_client_kobj_get_clnt(kobj); + ssize_t ret; + + if (!clnt) + return sprintf(buf, "<closed>\n"); + + ret = sprintf(buf, "%s", clnt->cl_program->name); + refcount_dec(&clnt->cl_count); + return ret; +} + +static ssize_t rpc_sysfs_clnt_max_connect_show(struct kobject *kobj, + struct kobj_attribute *attr, + char *buf) +{ + struct rpc_clnt *clnt = rpc_sysfs_client_kobj_get_clnt(kobj); + ssize_t ret; + + if (!clnt) + return sprintf(buf, "<closed>\n"); + + ret = sprintf(buf, "%u\n", clnt->cl_max_connect); + refcount_dec(&clnt->cl_count); + return ret; +} + static ssize_t rpc_sysfs_xprt_dstaddr_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) @@ -129,6 +184,31 @@ static ssize_t rpc_sysfs_xprt_srcaddr_show(struct kobject *kobj, return ret; } +static const char *xprtsec_strings[] = { + [RPC_XPRTSEC_NONE] = "none", + [RPC_XPRTSEC_TLS_ANON] = "tls-anon", + [RPC_XPRTSEC_TLS_X509] = "tls-x509", +}; + +static ssize_t rpc_sysfs_xprt_xprtsec_show(struct kobject *kobj, + struct kobj_attribute *attr, + char *buf) +{ + struct rpc_xprt *xprt = rpc_sysfs_xprt_kobj_get_xprt(kobj); + ssize_t ret; + + if (!xprt) { + ret = sprintf(buf, "<closed>\n"); + goto out; + } + + ret = sprintf(buf, "%s\n", xprtsec_strings[xprt->xprtsec.policy]); + xprt_put(xprt); +out: + return ret; + +} + static ssize_t rpc_sysfs_xprt_info_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { @@ -206,6 +286,14 @@ static ssize_t rpc_sysfs_xprt_state_show(struct kobject *kobj, return ret; } +static ssize_t rpc_sysfs_xprt_del_xprt_show(struct kobject *kobj, + struct kobj_attribute *attr, + char *buf) +{ + return sprintf(buf, "# delete this xprt\n"); +} + + static ssize_t rpc_sysfs_xprt_switch_info_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) @@ -225,6 +313,55 @@ static ssize_t rpc_sysfs_xprt_switch_info_show(struct kobject *kobj, return ret; } +static ssize_t rpc_sysfs_xprt_switch_add_xprt_show(struct kobject *kobj, + struct kobj_attribute *attr, + char *buf) +{ + return sprintf(buf, "# add one xprt to this xprt_switch\n"); +} + +static ssize_t rpc_sysfs_xprt_switch_add_xprt_store(struct kobject *kobj, + struct kobj_attribute *attr, + const char *buf, size_t count) +{ + struct rpc_xprt_switch *xprt_switch = + rpc_sysfs_xprt_switch_kobj_get_xprt(kobj); + struct xprt_create xprt_create_args; + struct rpc_xprt *xprt, *new; + + if (!xprt_switch) + return 0; + + xprt = rpc_xprt_switch_get_main_xprt(xprt_switch); + if (!xprt) + goto out; + + xprt_create_args.ident = xprt->xprt_class->ident; + xprt_create_args.net = xprt->xprt_net; + xprt_create_args.dstaddr = (struct sockaddr *)&xprt->addr; + xprt_create_args.addrlen = xprt->addrlen; + xprt_create_args.servername = xprt->servername; + xprt_create_args.bc_xprt = xprt->bc_xprt; + xprt_create_args.xprtsec = xprt->xprtsec; + xprt_create_args.connect_timeout = xprt->connect_timeout; + xprt_create_args.reconnect_timeout = xprt->max_reconnect_timeout; + + new = xprt_create_transport(&xprt_create_args); + if (IS_ERR_OR_NULL(new)) { + count = PTR_ERR(new); + goto out_put_xprt; + } + + rpc_xprt_switch_add_xprt(xprt_switch, new); + xprt_put(new); + +out_put_xprt: + xprt_put(xprt); +out: + xprt_switch_put(xprt_switch); + return count; +} + static ssize_t rpc_sysfs_xprt_dstaddr_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count) @@ -335,6 +472,40 @@ static ssize_t rpc_sysfs_xprt_state_change(struct kobject *kobj, return count; } +static ssize_t rpc_sysfs_xprt_del_xprt(struct kobject *kobj, + struct kobj_attribute *attr, + const char *buf, size_t count) +{ + struct rpc_xprt *xprt = rpc_sysfs_xprt_kobj_get_xprt(kobj); + struct rpc_xprt_switch *xps = rpc_sysfs_xprt_kobj_get_xprt_switch(kobj); + + if (!xprt || !xps) { + count = 0; + goto out; + } + + if (xprt->main) { + count = -EINVAL; + goto release_tasks; + } + + if (wait_on_bit_lock(&xprt->state, XPRT_LOCKED, TASK_KILLABLE)) { + count = -EINTR; + goto out_put; + } + + xprt_set_offline_locked(xprt, xps); + xprt_delete_locked(xprt, xps); + +release_tasks: + xprt_release_write(xprt, NULL); +out_put: + xprt_put(xprt); + xprt_switch_put(xps); +out: + return count; +} + int rpc_sysfs_init(void) { rpc_sunrpc_kset = kset_create_and_add("sunrpc", NULL, kernel_kobj); @@ -398,23 +569,48 @@ static const void *rpc_sysfs_xprt_namespace(const struct kobject *kobj) kobject)->xprt->xprt_net; } +static struct kobj_attribute rpc_sysfs_clnt_version = __ATTR(rpc_version, + 0444, rpc_sysfs_clnt_version_show, NULL); + +static struct kobj_attribute rpc_sysfs_clnt_program = __ATTR(program, + 0444, rpc_sysfs_clnt_program_show, NULL); + +static struct kobj_attribute rpc_sysfs_clnt_max_connect = __ATTR(max_connect, + 0444, rpc_sysfs_clnt_max_connect_show, NULL); + +static struct attribute *rpc_sysfs_rpc_clnt_attrs[] = { + &rpc_sysfs_clnt_version.attr, + &rpc_sysfs_clnt_program.attr, + &rpc_sysfs_clnt_max_connect.attr, + NULL, +}; +ATTRIBUTE_GROUPS(rpc_sysfs_rpc_clnt); + static struct kobj_attribute rpc_sysfs_xprt_dstaddr = __ATTR(dstaddr, 0644, rpc_sysfs_xprt_dstaddr_show, rpc_sysfs_xprt_dstaddr_store); static struct kobj_attribute rpc_sysfs_xprt_srcaddr = __ATTR(srcaddr, 0644, rpc_sysfs_xprt_srcaddr_show, NULL); +static struct kobj_attribute rpc_sysfs_xprt_xprtsec = __ATTR(xprtsec, + 0644, rpc_sysfs_xprt_xprtsec_show, NULL); + static struct kobj_attribute rpc_sysfs_xprt_info = __ATTR(xprt_info, 0444, rpc_sysfs_xprt_info_show, NULL); static struct kobj_attribute rpc_sysfs_xprt_change_state = __ATTR(xprt_state, 0644, rpc_sysfs_xprt_state_show, rpc_sysfs_xprt_state_change); +static struct kobj_attribute rpc_sysfs_xprt_del = __ATTR(del_xprt, + 0644, rpc_sysfs_xprt_del_xprt_show, rpc_sysfs_xprt_del_xprt); + static struct attribute *rpc_sysfs_xprt_attrs[] = { &rpc_sysfs_xprt_dstaddr.attr, &rpc_sysfs_xprt_srcaddr.attr, + &rpc_sysfs_xprt_xprtsec.attr, &rpc_sysfs_xprt_info.attr, &rpc_sysfs_xprt_change_state.attr, + &rpc_sysfs_xprt_del.attr, NULL, }; ATTRIBUTE_GROUPS(rpc_sysfs_xprt); @@ -422,14 +618,20 @@ ATTRIBUTE_GROUPS(rpc_sysfs_xprt); static struct kobj_attribute rpc_sysfs_xprt_switch_info = __ATTR(xprt_switch_info, 0444, rpc_sysfs_xprt_switch_info_show, NULL); +static struct kobj_attribute rpc_sysfs_xprt_switch_add_xprt = + __ATTR(add_xprt, 0644, rpc_sysfs_xprt_switch_add_xprt_show, + rpc_sysfs_xprt_switch_add_xprt_store); + static struct attribute *rpc_sysfs_xprt_switch_attrs[] = { &rpc_sysfs_xprt_switch_info.attr, + &rpc_sysfs_xprt_switch_add_xprt.attr, NULL, }; ATTRIBUTE_GROUPS(rpc_sysfs_xprt_switch); static const struct kobj_type rpc_sysfs_client_type = { .release = rpc_sysfs_client_release, + .default_groups = rpc_sysfs_rpc_clnt_groups, .sysfs_ops = &kobj_sysfs_ops, .namespace = rpc_sysfs_client_namespace, };
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index 09f245c..0eab154 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c
@@ -1167,7 +1167,7 @@ xprt_request_enqueue_receive(struct rpc_task *task) spin_unlock(&xprt->queue_lock); /* Turn off autodisconnect */ - del_timer_sync(&xprt->timer); + timer_delete_sync(&xprt->timer); return 0; } @@ -2138,7 +2138,7 @@ static void xprt_destroy(struct rpc_xprt *xprt) * can only run *before* del_time_sync(), never after. */ spin_lock(&xprt->transport_lock); - del_timer_sync(&xprt->timer); + timer_delete_sync(&xprt->timer); spin_unlock(&xprt->transport_lock); /*
diff --git a/net/sunrpc/xprtmultipath.c b/net/sunrpc/xprtmultipath.c index 7e98d4d..4c5e08b 100644 --- a/net/sunrpc/xprtmultipath.c +++ b/net/sunrpc/xprtmultipath.c
@@ -92,6 +92,27 @@ void rpc_xprt_switch_remove_xprt(struct rpc_xprt_switch *xps, xprt_put(xprt); } +/** + * rpc_xprt_switch_get_main_xprt - Get the 'main' xprt for an xprt switch. + * @xps: pointer to struct rpc_xprt_switch. + */ +struct rpc_xprt *rpc_xprt_switch_get_main_xprt(struct rpc_xprt_switch *xps) +{ + struct rpc_xprt_iter xpi; + struct rpc_xprt *xprt; + + xprt_iter_init_listall(&xpi, xps); + + xprt = xprt_iter_get_next(&xpi); + while (xprt && !xprt->main) { + xprt_put(xprt); + xprt = xprt_iter_get_next(&xpi); + } + + xprt_iter_destroy(&xpi); + return xprt; +} + static DEFINE_IDA(rpc_xprtswitch_ids); void xprt_multipath_cleanup_ids(void)
diff --git a/net/tipc/node.c b/net/tipc/node.c index 500320e..ccf5e42 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c
@@ -638,7 +638,7 @@ static void tipc_node_delete(struct tipc_node *node) trace_tipc_node_delete(node, true, " "); tipc_node_delete_from_list(node); - del_timer_sync(&node->timer); + timer_delete_sync(&node->timer); tipc_node_put(node); }
diff --git a/net/tipc/subscr.c b/net/tipc/subscr.c index 05d49ad..621adda 100644 --- a/net/tipc/subscr.c +++ b/net/tipc/subscr.c
@@ -177,7 +177,7 @@ void tipc_sub_unsubscribe(struct tipc_subscription *sub) { tipc_nametbl_unsubscribe(sub); if (sub->evt.s.timeout != TIPC_WAIT_FOREVER) - del_timer_sync(&sub->timer); + timer_delete_sync(&sub->timer); list_del(&sub->sub_list); tipc_sub_put(sub); }
diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c index 7e3db87..fc6afbc 100644 --- a/net/vmw_vsock/af_vsock.c +++ b/net/vmw_vsock/af_vsock.c
@@ -1551,7 +1551,11 @@ static int vsock_connect(struct socket *sock, struct sockaddr *addr, timeout = vsk->connect_timeout; prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); - while (sk->sk_state != TCP_ESTABLISHED && sk->sk_err == 0) { + /* If the socket is already closing or it is in an error state, there + * is no point in waiting. + */ + while (sk->sk_state != TCP_ESTABLISHED && + sk->sk_state != TCP_CLOSING && sk->sk_err == 0) { if (flags & O_NONBLOCK) { /* If we're not going to block, we schedule a timeout * function to generate a timeout on the connection
diff --git a/net/wireless/core.c b/net/wireless/core.c index 9e6b3190..dcce326 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c
@@ -1722,7 +1722,7 @@ void wiphy_delayed_work_queue(struct wiphy *wiphy, trace_wiphy_delayed_work_queue(wiphy, &dwork->work, delay); if (!delay) { - del_timer(&dwork->timer); + timer_delete(&dwork->timer); wiphy_work_queue(wiphy, &dwork->work); return; } @@ -1737,7 +1737,7 @@ void wiphy_delayed_work_cancel(struct wiphy *wiphy, { lockdep_assert_held(&wiphy->mtx); - del_timer_sync(&dwork->timer); + timer_delete_sync(&dwork->timer); wiphy_work_cancel(wiphy, &dwork->work); } EXPORT_SYMBOL_GPL(wiphy_delayed_work_cancel); @@ -1747,7 +1747,7 @@ void wiphy_delayed_work_flush(struct wiphy *wiphy, { lockdep_assert_held(&wiphy->mtx); - del_timer_sync(&dwork->timer); + timer_delete_sync(&dwork->timer); wiphy_work_flush(wiphy, &dwork->work); } EXPORT_SYMBOL_GPL(wiphy_delayed_work_flush);
diff --git a/net/x25/x25_link.c b/net/x25/x25_link.c index 5460b914..37b1904 100644 --- a/net/x25/x25_link.c +++ b/net/x25/x25_link.c
@@ -55,7 +55,7 @@ static void x25_t20timer_expiry(struct timer_list *t) static inline void x25_stop_t20timer(struct x25_neigh *nb) { - del_timer(&nb->t20timer); + timer_delete(&nb->t20timer); } /*
diff --git a/net/x25/x25_timer.c b/net/x25/x25_timer.c index 9376365..e4c5ad5 100644 --- a/net/x25/x25_timer.c +++ b/net/x25/x25_timer.c
@@ -41,7 +41,7 @@ void x25_start_heartbeat(struct sock *sk) void x25_stop_heartbeat(struct sock *sk) { - del_timer(&sk->sk_timer); + timer_delete(&sk->sk_timer); } void x25_start_t2timer(struct sock *sk) @@ -74,7 +74,7 @@ void x25_start_t23timer(struct sock *sk) void x25_stop_timer(struct sock *sk) { - del_timer(&x25_sk(sk)->timer); + timer_delete(&x25_sk(sk)->timer); } unsigned long x25_display_timer(struct sock *sk)
diff --git a/net/xdp/xsk.c b/net/xdp/xsk.c index e5d104c..5696af4 100644 --- a/net/xdp/xsk.c +++ b/net/xdp/xsk.c
@@ -806,8 +806,11 @@ static int __xsk_generic_xmit(struct sock *sk) * if there is space in it. This avoids having to implement * any buffering in the Tx path. */ - if (xsk_cq_reserve_addr_locked(xs->pool, desc.addr)) + err = xsk_cq_reserve_addr_locked(xs->pool, desc.addr); + if (err) { + err = -EAGAIN; goto out; + } skb = xsk_build_skb(xs, &desc); if (IS_ERR(skb)) {
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 30970d4..143ac3a 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c
@@ -462,7 +462,7 @@ void xfrm_policy_destroy(struct xfrm_policy *policy) { BUG_ON(!policy->walk.dead); - if (del_timer(&policy->timer) || del_timer(&policy->polq.hold_timer)) + if (timer_delete(&policy->timer) || timer_delete(&policy->polq.hold_timer)) BUG(); xfrm_dev_policy_free(policy); @@ -487,11 +487,11 @@ static void xfrm_policy_kill(struct xfrm_policy *policy) atomic_inc(&policy->genid); - if (del_timer(&policy->polq.hold_timer)) + if (timer_delete(&policy->polq.hold_timer)) xfrm_pol_put(policy); skb_queue_purge(&policy->polq.hold_queue); - if (del_timer(&policy->timer)) + if (timer_delete(&policy->timer)) xfrm_pol_put(policy); /* XXX: Flush state cache */ @@ -1469,7 +1469,7 @@ static void xfrm_policy_requeue(struct xfrm_policy *old, spin_lock_bh(&pq->hold_queue.lock); skb_queue_splice_init(&pq->hold_queue, &list); - if (del_timer(&pq->hold_timer)) + if (timer_delete(&pq->hold_timer)) xfrm_pol_put(old); spin_unlock_bh(&pq->hold_queue.lock); @@ -3004,7 +3004,7 @@ static int xdst_queue_output(struct net *net, struct sock *sk, struct sk_buff *s sched_next = jiffies + pq->timeout; - if (del_timer(&pq->hold_timer)) { + if (timer_delete(&pq->hold_timer)) { if (time_before(pq->hold_timer.expires, sched_next)) sched_next = pq->hold_timer.expires; xfrm_pol_put(pol);
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index d896c3f..341d79e 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c
@@ -598,7 +598,7 @@ static void ___xfrm_state_destroy(struct xfrm_state *x) if (x->mode_cbs && x->mode_cbs->destroy_state) x->mode_cbs->destroy_state(x); hrtimer_cancel(&x->mtimer); - del_timer_sync(&x->rtimer); + timer_delete_sync(&x->rtimer); kfree(x->aead); kfree(x->aalg); kfree(x->ealg);
diff --git a/rust/Makefile b/rust/Makefile index b9cc810..fa0eea8 100644 --- a/rust/Makefile +++ b/rust/Makefile
@@ -60,10 +60,14 @@ core-cfgs = \ --cfg no_fp_fmt_parse +# `rustc` recognizes `--remap-path-prefix` since 1.26.0, but `rustdoc` only +# since Rust 1.81.0. Moreover, `rustdoc` ICEs on out-of-tree builds since Rust +# 1.82.0 (https://github.com/rust-lang/rust/issues/138520). Thus workaround both +# issues skipping the flag. The former also applies to `RUSTDOC TK`. quiet_cmd_rustdoc = RUSTDOC $(if $(rustdoc_host),H, ) $< cmd_rustdoc = \ OBJTREE=$(abspath $(objtree)) \ - $(RUSTDOC) $(filter-out $(skip_flags),$(if $(rustdoc_host),$(rust_common_flags),$(rust_flags))) \ + $(RUSTDOC) $(filter-out $(skip_flags) --remap-path-prefix=%,$(if $(rustdoc_host),$(rust_common_flags),$(rust_flags))) \ $(rustc_target_flags) -L$(objtree)/$(obj) \ -Zunstable-options --generate-link-to-definition \ --output $(rustdoc_output) \ @@ -199,7 +203,7 @@ rm -rf $(objtree)/$(obj)/test/doctests/kernel; \ mkdir -p $(objtree)/$(obj)/test/doctests/kernel; \ OBJTREE=$(abspath $(objtree)) \ - $(RUSTDOC) --test $(rust_flags) \ + $(RUSTDOC) --test $(filter-out --remap-path-prefix=%,$(rust_flags)) \ -L$(objtree)/$(obj) --extern ffi --extern pin_init \ --extern kernel --extern build_error --extern macros \ --extern bindings --extern uapi \ @@ -260,7 +264,8 @@ -mfunction-return=thunk-extern -mrecord-mcount -mabi=lp64 \ -mindirect-branch-cs-prefix -mstack-protector-guard% -mtraceback=no \ -mno-pointers-to-nested-functions -mno-string \ - -mno-strict-align -mstrict-align \ + -mno-strict-align -mstrict-align -mdirect-extern-access \ + -mexplicit-relocs -mno-check-zero-division \ -fconserve-stack -falign-jumps=% -falign-loops=% \ -femit-struct-debug-baseonly -fno-ipa-cp-clone -fno-ipa-sra \ -fno-partial-inlining -fplugin-arg-arm_ssp_per_task_plugin-% \ @@ -274,6 +279,8 @@ # Derived from `scripts/Makefile.clang`. BINDGEN_TARGET_x86 := x86_64-linux-gnu BINDGEN_TARGET_arm64 := aarch64-linux-gnu +BINDGEN_TARGET_arm := arm-linux-gnueabi +BINDGEN_TARGET_loongarch := loongarch64-linux-gnusf BINDGEN_TARGET_um := $(BINDGEN_TARGET_$(SUBARCH)) BINDGEN_TARGET := $(BINDGEN_TARGET_$(SRCARCH)) @@ -431,6 +438,13 @@ __muloti4 __multi3 \ __udivmodti4 __udivti3 __umodti3 +ifdef CONFIG_ARM + # Add eabi initrinsics for ARM 32-bit + redirect-intrinsics += \ + __aeabi_fadd __aeabi_fmul __aeabi_fcmpeq __aeabi_fcmple __aeabi_fcmplt __aeabi_fcmpun \ + __aeabi_dadd __aeabi_dmul __aeabi_dcmple __aeabi_dcmplt __aeabi_dcmpun \ + __aeabi_uldivmod +endif ifneq ($(or $(CONFIG_ARM64),$(and $(CONFIG_RISCV),$(CONFIG_64BIT))),) # These intrinsics are defined for ARM64 and RISCV64 redirect-intrinsics += \
diff --git a/rust/compiler_builtins.rs b/rust/compiler_builtins.rs index f14b8d7..dd16c1d 100644 --- a/rust/compiler_builtins.rs +++ b/rust/compiler_builtins.rs
@@ -73,5 +73,29 @@ pub extern "C" fn $ident() { __umodti3, }); +#[cfg(target_arch = "arm")] +define_panicking_intrinsics!("`f32` should not be used", { + __aeabi_fadd, + __aeabi_fmul, + __aeabi_fcmpeq, + __aeabi_fcmple, + __aeabi_fcmplt, + __aeabi_fcmpun, +}); + +#[cfg(target_arch = "arm")] +define_panicking_intrinsics!("`f64` should not be used", { + __aeabi_dadd, + __aeabi_dmul, + __aeabi_dcmple, + __aeabi_dcmplt, + __aeabi_dcmpun, +}); + +#[cfg(target_arch = "arm")] +define_panicking_intrinsics!("`u64` division/modulo should not be used", { + __aeabi_uldivmod, +}); + // NOTE: if you are adding a new intrinsic here, you should also add it to // `redirect-intrinsics` in `rust/Makefile`.
diff --git a/samples/connector/cn_test.c b/samples/connector/cn_test.c index 0958a17..73d50b4 100644 --- a/samples/connector/cn_test.c +++ b/samples/connector/cn_test.c
@@ -172,7 +172,7 @@ static int cn_test_init(void) static void cn_test_fini(void) { - del_timer_sync(&cn_test_timer); + timer_delete_sync(&cn_test_timer); cn_del_callback(&cn_test_id); cn_test_id.val--; cn_del_callback(&cn_test_id);
diff --git a/samples/ftrace/sample-trace-array.c b/samples/ftrace/sample-trace-array.c index d0ee900..dac67c3 100644 --- a/samples/ftrace/sample-trace-array.c +++ b/samples/ftrace/sample-trace-array.c
@@ -82,7 +82,7 @@ static int simple_thread(void *arg) while (!kthread_should_stop()) simple_thread_func(count++); - del_timer(&mytimer); + timer_delete(&mytimer); cancel_work_sync(&trace_work); /*
diff --git a/samples/trace_events/trace-events-sample.h b/samples/trace_events/trace-events-sample.h index 999f78d..1a05fc1 100644 --- a/samples/trace_events/trace-events-sample.h +++ b/samples/trace_events/trace-events-sample.h
@@ -319,7 +319,8 @@ TRACE_EVENT(foo_bar, __assign_cpumask(cpum, cpumask_bits(mask)); ), - TP_printk("foo %s %d %s %s %s %s %s %s (%s) (%s) %s", __entry->foo, __entry->bar, + TP_printk("foo %s %d %s %s %s %s %s %s (%s) (%s) %s [%d] %*pbl", + __entry->foo, __entry->bar, /* * Notice here the use of some helper functions. This includes: @@ -370,7 +371,10 @@ TRACE_EVENT(foo_bar, __get_str(str), __get_str(lstr), __get_bitmask(cpus), __get_cpumask(cpum), - __get_str(vstr)) + __get_str(vstr), + __get_dynamic_array_len(cpus), + __get_dynamic_array_len(cpus), + __get_dynamic_array(cpus)) ); /*
diff --git a/scripts/Makefile.build b/scripts/Makefile.build index 56be830..13dcd86 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build
@@ -20,10 +20,6 @@ targets := subdir-y := subdir-m := -EXTRA_AFLAGS := -EXTRA_CFLAGS := -EXTRA_CPPFLAGS := -EXTRA_LDFLAGS := asflags-y := ccflags-y := rustflags-y :=
diff --git a/scripts/Makefile.compiler b/scripts/Makefile.compiler index 8c10296..8956587 100644 --- a/scripts/Makefile.compiler +++ b/scripts/Makefile.compiler
@@ -67,6 +67,10 @@ # Usage: cflags-$(call clang-min-version, 110000) += -foo clang-min-version = $(call test-ge, $(CONFIG_CLANG_VERSION), $1) +# rustc-min-version +# Usage: rustc-$(call rustc-min-version, 108500) += -Cfoo +rustc-min-version = $(call test-ge, $(CONFIG_RUSTC_VERSION), $1) + # ld-option # Usage: KBUILD_LDFLAGS += $(call ld-option, -X, -Y) ld-option = $(call try-run, $(LD) $(KBUILD_LDFLAGS) $(1) -v,$(1),$(2),$(3))
diff --git a/scripts/Makefile.extrawarn b/scripts/Makefile.extrawarn index dc081cf..d758975 100644 --- a/scripts/Makefile.extrawarn +++ b/scripts/Makefile.extrawarn
@@ -82,9 +82,6 @@ # Warn if there is an enum types mismatch KBUILD_CFLAGS += $(call cc-option,-Wenum-conversion) -# Explicitly clear padding bits during variable initialization -KBUILD_CFLAGS += $(call cc-option,-fzero-init-padding-bits=all) - KBUILD_CFLAGS += -Wextra KBUILD_CFLAGS += -Wunused
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index 57620b4..2fe73cd 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib
@@ -1,9 +1,4 @@ # SPDX-License-Identifier: GPL-2.0 -# Backward compatibility -asflags-y += $(EXTRA_AFLAGS) -ccflags-y += $(EXTRA_CFLAGS) -cppflags-y += $(EXTRA_CPPFLAGS) -ldflags-y += $(EXTRA_LDFLAGS) # flags that take effect in current and sub directories KBUILD_AFLAGS += $(subdir-asflags-y) @@ -275,9 +270,9 @@ objtool-args-$(CONFIG_STACK_VALIDATION) += --stackval objtool-args-$(CONFIG_HAVE_STATIC_CALL_INLINE) += --static-call objtool-args-$(CONFIG_HAVE_UACCESS_VALIDATION) += --uaccess -objtool-args-$(CONFIG_GCOV_KERNEL) += --no-unreachable +objtool-args-$(or $(CONFIG_GCOV_KERNEL),$(CONFIG_KCOV)) += --no-unreachable objtool-args-$(CONFIG_PREFIX_SYMBOLS) += --prefix=$(CONFIG_FUNCTION_PADDING_BYTES) -objtool-args-$(CONFIG_OBJTOOL_WERROR) += --Werror --backtrace +objtool-args-$(CONFIG_OBJTOOL_WERROR) += --Werror objtool-args = $(objtool-args-y) \ $(if $(delay-objtool), --link) \ @@ -377,9 +372,6 @@ quiet_cmd_objcopy = OBJCOPY $@ cmd_objcopy = $(OBJCOPY) $(OBJCOPYFLAGS) $(OBJCOPYFLAGS_$(@F)) $< $@ -quiet_cmd_strip_relocs = RSTRIP $@ -cmd_strip_relocs = $(OBJCOPY) --remove-section='.rel*' $@ - # Gzip # ---------------------------------------------------------------------------
diff --git a/scripts/Makefile.vmlinux b/scripts/Makefile.vmlinux index 873caaa..b0a6cd5 100644 --- a/scripts/Makefile.vmlinux +++ b/scripts/Makefile.vmlinux
@@ -9,6 +9,20 @@ targets := +ifdef CONFIG_ARCH_VMLINUX_NEEDS_RELOCS +vmlinux-final := vmlinux.unstripped + +quiet_cmd_strip_relocs = RSTRIP $@ + cmd_strip_relocs = $(OBJCOPY) --remove-section='.rel*' $< $@ + +vmlinux: $(vmlinux-final) FORCE + $(call if_changed,strip_relocs) + +targets += vmlinux +else +vmlinux-final := vmlinux +endif + %.o: %.c FORCE $(call if_changed_rule,cc_o_c) @@ -47,7 +61,7 @@ ifdef CONFIG_GENERIC_BUILTIN_DTB targets += .builtin-dtbs.S .builtin-dtbs.o -vmlinux: .builtin-dtbs.o +$(vmlinux-final): .builtin-dtbs.o endif # vmlinux @@ -55,11 +69,11 @@ ifdef CONFIG_MODULES targets += .vmlinux.export.o -vmlinux: .vmlinux.export.o +$(vmlinux-final): .vmlinux.export.o endif ifdef CONFIG_ARCH_WANTS_PRE_LINK_VMLINUX -vmlinux: arch/$(SRCARCH)/tools/vmlinux.arch.o +$(vmlinux-final): arch/$(SRCARCH)/tools/vmlinux.arch.o arch/$(SRCARCH)/tools/vmlinux.arch.o: vmlinux.o FORCE $(Q)$(MAKE) $(build)=arch/$(SRCARCH)/tools $@ @@ -69,14 +83,18 @@ # Final link of vmlinux with optional arch pass after final link cmd_link_vmlinux = \ - $< "$(LD)" "$(KBUILD_LDFLAGS)" "$(LDFLAGS_vmlinux)"; \ + $< "$(LD)" "$(KBUILD_LDFLAGS)" "$(LDFLAGS_vmlinux)" "$@"; \ $(if $(ARCH_POSTLINK), $(MAKE) -f $(ARCH_POSTLINK) $@, true) -targets += vmlinux -vmlinux: scripts/link-vmlinux.sh vmlinux.o $(KBUILD_LDS) FORCE +targets += $(vmlinux-final) +$(vmlinux-final): scripts/link-vmlinux.sh vmlinux.o $(KBUILD_LDS) FORCE +$(call if_changed_dep,link_vmlinux) ifdef CONFIG_DEBUG_INFO_BTF -vmlinux: $(RESOLVE_BTFIDS) +$(vmlinux-final): $(RESOLVE_BTFIDS) +endif + +ifdef CONFIG_BUILDTIME_TABLE_SORT +vmlinux: scripts/sorttable endif # module.builtin.ranges @@ -92,7 +110,7 @@ modules.builtin vmlinux.map vmlinux.o.map FORCE $(call if_changed,modules_builtin_ranges) -vmlinux.map: vmlinux +vmlinux.map: $(vmlinux-final) @: endif
diff --git a/scripts/Makefile.vmlinux_o b/scripts/Makefile.vmlinux_o index 0b6e2eb..938c745 100644 --- a/scripts/Makefile.vmlinux_o +++ b/scripts/Makefile.vmlinux_o
@@ -30,13 +30,20 @@ # objtool for vmlinux.o # --------------------------------------------------------------------------- # -# For LTO and IBT, objtool doesn't run on individual translation units. -# Run everything on vmlinux instead. +# For delay-objtool (IBT or LTO), objtool doesn't run on individual translation +# units. Instead it runs on vmlinux.o. +# +# For !delay-objtool + CONFIG_NOINSTR_VALIDATION, it runs on both translation +# units and vmlinux.o, with the latter only used for noinstr/unret validation. objtool-enabled := $(or $(delay-objtool),$(CONFIG_NOINSTR_VALIDATION)) -vmlinux-objtool-args-$(delay-objtool) += $(objtool-args-y) -vmlinux-objtool-args-$(CONFIG_GCOV_KERNEL) += --no-unreachable +ifeq ($(delay-objtool),y) +vmlinux-objtool-args-y += $(objtool-args-y) +else +vmlinux-objtool-args-$(CONFIG_OBJTOOL_WERROR) += --Werror +endif + vmlinux-objtool-args-$(CONFIG_NOINSTR_VALIDATION) += --noinstr \ $(if $(or $(CONFIG_MITIGATION_UNRET_ENTRY),$(CONFIG_MITIGATION_SRSO)), --unret)
diff --git a/scripts/bash-completion/make b/scripts/bash-completion/make new file mode 100644 index 0000000..42e8dcea --- /dev/null +++ b/scripts/bash-completion/make
@@ -0,0 +1,451 @@ +# SPDX-License-Identifier: GPL-2.0-only +# bash completion for GNU make with kbuild extension -*- shell-script -*- + +# Load the default completion script for make. It is typically located at +# /usr/share/bash-completion/completions/make, but we do not rely on it. +__kbuild_load_default_make_completion() +{ + local -a dirs=("${BASH_COMPLETION_USER_DIR:-${XDG_DATA_HOME:-$HOME/.local/share}/bash-completion}/completions") + local ifs=$IFS IFS=: dir compfile this_dir + + for dir in ${XDG_DATA_DIRS:-/usr/local/share:/usr/share}; do + dirs+=("$dir"/bash-completion/completions) + done + IFS=$ifs + + this_dir="$(realpath "$(dirname "${BASH_SOURCE[0]}")")" + + for dir in "${dirs[@]}"; do + if [[ ! -d ${dir} || ${dir} = "${this_dir}" ]]; then + continue + fi + + for compfile in make make.bash _make; do + compfile=$dir/$compfile + # Avoid trying to source dirs; https://bugzilla.redhat.com/903540 + if [[ -f ${compfile} ]] && . "${compfile}" &>/dev/null; then + + __kbuild_default_make_completion=$( + # shellcheck disable=SC2046 # word splitting is the point here + set -- $(complete -p make) + + while [[ $# -gt 1 && "$1" != -F ]]; do + shift + done + + if [[ "$1" = -F ]]; then + echo "$2" + fi + ) + + return + fi + done + done +} + +__kbuild_load_default_make_completion + +__kbuild_handle_variable() +{ + local var=${1%%=*} + local cur=${cur#"${var}"=} + local srctree=$2 + local keywords=() + + case $var in + ARCH) + # sub-directories under arch/ + keywords+=($(find "${srctree}/arch" -mindepth 1 -maxdepth 1 -type d -printf '%P\n')) + # architectures hard-coded in the top Makefile + keywords+=(i386 x86_64 sparc32 sparc64 parisc64) + ;; + CROSS_COMPILE) + # toolchains with a full path + local cross_compile=() + local c c2 + _filedir + + for c in "${COMPREPLY[@]}"; do + # eval for tilde expansion + # suppress error, as this fails when it contains a space + eval "c2=${c}" 2>/dev/null || continue + if [[ ${c} == *-elfedit && ! -d ${c2} && -x ${c2} ]]; then + cross_compile+=("${c%elfedit}") + fi + done + + # toolchains in the PATH environment + while read -r c; do + if [[ ${c} == *-elfedit ]]; then + keywords+=("${c%elfedit}") + fi + done < <(compgen -c) + + COMPREPLY=() + _filedir -d + + # Add cross_compile directly without passing it to compgen. + # Otherwise, toolchain paths with a tilde do not work. + # e.g.) + # CROSS_COMPILE=~/0day/gcc-14.2.0-nolibc/aarch64-linux/bin/aarch64-linux- + COMPREPLY+=("${cross_compile[@]}") + ;; + LLVM) + # LLVM=1 uses the default 'clang' etc. + keywords+=(1) + + # suffix for a particular version. LLVM=-18 uses 'clang-18' etc. + while read -r c; do + if [[ ${c} == clang-[0-9]* ]]; then + keywords+=("${c#clang}") + fi + done < <(compgen -c) + + # directory path to LLVM toolchains + _filedir -d + ;; + KCONFIG_ALLCONFIG) + # KCONFIG_ALLCONFIG=1 selects the default fragment + keywords+=(1) + # or the path to a fragment file + _filedir + ;; + C | KBUILD_CHECKSRC) + keywords+=(1 2) + ;; + V | KBUILD_VERBOSE) + keywords+=({,1}{,2}) + ;; + W | KBUILD_EXTRA_WARN) + keywords+=({,1}{,2}{,3}{,c}{,e}) + ;; + KBUILD_ABS_SRCTREE | KBUILD_MODPOST_NOFINAL | KBUILD_MODPOST_WARN | \ + CLIPPY | KBUILD_CLIPPY | KCONFIG_NOSILENTUPDATE | \ + KCONFIG_OVERWRITECONFIG | KCONFIG_WARN_UNKNOWN_SYMBOL | \ + KCONFIG_WERROR ) + keywords+=(1) + ;; + INSTALL_MOD_STRIP) + keywords+=(1 --strip-debug --strip-unneeded) + ;; + O | KBUILD_OUTPUT | M | KBUILD_EXTMOD | MO | KBUILD_EXTMOD_OUTPUT | *_PATH) + # variables that take a directory. + _filedir -d + return + ;; + KBUILD_EXTRA_SYMBOL | KBUILD_KCONFIG | KCONFIG_CONFIG) + # variables that take a file. + _filedir + return + esac + + COMPREPLY+=($(compgen -W "${keywords[*]}" -- "${cur}")) +} + +# Check the -C, -f options and 'source' symlink. Return the source tree we are +# working in. +__kbuild_get_srctree() +{ + local words=("$@") + local cwd makef_dir + + # see if a path was specified with -C/--directory + for ((i = 1; i < ${#words[@]}; i++)); do + if [[ ${words[i]} == -@(C|-directory) ]]; then + # eval for tilde expansion. + # suppress error, as this fails when it contains a space + eval "cwd=${words[i + 1]}" 2>/dev/null + break + fi + done + + if [[ -z ${cwd} ]]; then + cwd=. + fi + + # see if a Makefile was specified with -f/--file/--makefile + for ((i = 1; i < ${#words[@]}; i++)); do + if [[ ${words[i]} == -@(f|-?(make)file) ]]; then + # eval for tilde expansion + # suppress error, as this fails when it contains a space + eval "makef_dir=${words[i + 1]%/*}" 2>/dev/null + break + fi + done + + if [ -z "${makef_dir}" ]; then + makef_dir=${cwd} + elif [[ ${makef_dir} != /* ]]; then + makef_dir=${cwd}/${makef_dir} + fi + + # If ${makef_dir} is a build directory created by the O= option, there + # is a symbolic link 'source', which points to the kernel source tree. + if [[ -L ${makef_dir}/source ]]; then + makef_dir=$(readlink "${makef_dir}/source") + fi + + echo "${makef_dir}" +} + +# Get SRCARCH to do a little more clever things +__kbuild_get_srcarch() +{ + local words=("$@") + local arch srcarch uname_m + + # see if ARCH= is explicitly specified + for ((i = 1; i < ${#words[@]}; i++)); do + if [[ ${words[i]} == ARCH=* ]]; then + arch=${words[i]#ARCH=} + break + fi + done + + # If ARCH= is not specified, check the build marchine's architecture + if [[ -z ${arch} ]]; then + uname_m=$(uname -m) + + # shellcheck disable=SC2209 # 'sh' is SuperH, not a shell command + case ${uname_m} in + arm64 | aarch64*) arch=arm64 ;; + arm* | sa110) arch=arm ;; + i?86 | x86_64) arch=x86 ;; + loongarch*) arch=loongarch ;; + mips*) arch=mips ;; + ppc*) arch=powerpc ;; + riscv*) arch=riscv ;; + s390x) arch=s390 ;; + sh[234]*) arch=sh ;; + sun4u) arch=sparc64 ;; + *) arch=${uname_m} ;; + esac + fi + + case ${arch} in + parisc64) srcarch=parisc ;; + sparc32 | sparc64) srcarch=sparc ;; + i386 | x86_64) srcarch=x86 ;; + *) srcarch=${arch} ;; + esac + + echo "$srcarch" +} + +# small Makefile to parse obj-* syntax +__kbuild_tmp_makefile() +{ +cat <<'EOF' +.PHONY: __default +__default: + $(foreach m,$(obj-y) $(obj-m) $(obj-),$(foreach s, -objs -y -m -,$($(m:%.o=%$s))) $(m)) +EOF +echo "include ${1}" +} + +_make_for_kbuild () +{ + # shellcheck disable=SC2034 # these are set by _init_completion + local cur prev words cword split + _init_completion -s || return + + local srctree + srctree=$(__kbuild_get_srctree "${words[@]}") + + # If 'kernel' and 'Documentation' directories are found, we assume this + # is a kernel tree. Otherwise, we fall back to the generic rule provided + # by the bash-completion project. + if [[ ! -d ${srctree}/kernel || ! -d ${srctree}/Documentation ]]; then + if [ -n "${__kbuild_default_make_completion}" ]; then + "${__kbuild_default_make_completion}" "$@" + fi + return + fi + + # make options with a parameter (copied from the bash-completion project) + case ${prev} in + --file | --makefile | --old-file | --assume-old | --what-if | --new-file | \ + --assume-new | -!(-*)[foW]) + _filedir + return + ;; + --include-dir | --directory | -!(-*)[ICm]) + _filedir -d + return + ;; + -!(-*)E) + COMPREPLY=($(compgen -v -- "$cur")) + return + ;; + --eval | -!(-*)[DVx]) + return + ;; + --jobs | -!(-*)j) + COMPREPLY=($(compgen -W "{1..$(($(_ncpus) * 2))}" -- "$cur")) + return + ;; + esac + + local keywords=() + + case ${cur} in + -*) + # make options (copied from the bash-completion project) + local opts + opts="$(_parse_help "$1")" + COMPREPLY=($(compgen -W "${opts:-$(_parse_usage "$1")}" -- "$cur")) + if [[ ${COMPREPLY-} == *= ]]; then + compopt -o nospace + fi + return + ;; + *=*) + __kbuild_handle_variable "${cur}" "${srctree}" + return + ;; + KBUILD_*) + # There are many variables prefixed with 'KBUILD_'. + # Display them only when 'KBUILD_' is entered. + # shellcheck disable=SC2191 # '=' is appended for variables + keywords+=( + KBUILD_{CHECKSRC,EXTMOD,EXTMOD_OUTPUT,OUTPUT,VERBOSE,EXTRA_WARN,CLIPPY}= + KBUILD_BUILD_{USER,HOST,TIMESTAMP}= + KBUILD_MODPOST_{NOFINAL,WARN}= + KBUILD_{ABS_SRCTREE,EXTRA_SYMBOLS,KCONFIG}= + ) + ;; + KCONFIG_*) + # There are many variables prefixed with 'KCONFIG_'. + # Display them only when 'KCONFIG_' is entered. + # shellcheck disable=SC2191 # '=' is appended for variables + keywords+=( + KCONFIG_{CONFIG,ALLCONFIG,NOSILENTUPDATE,OVERWRITECONFIG}= + KCONFIG_{SEED,PROBABILITY}= + KCONFIG_WARN_UNKNOWN_SYMBOL= + KCONFIG_WERROR= + ) + ;; + *) + # By default, hide KBUILD_* and KCONFIG_* variables. + # Instead, display only the prefix parts. + keywords+=(KBUILD_ KCONFIG_) + ;; + esac + + if [[ ${cur} != /* && ${cur} != *//* ]]; then + local dir srcarch kbuild_file tmp + srcarch=$(__kbuild_get_srcarch "${words[@]}") + + # single build + dir=${cur} + while true; do + if [[ ${dir} == */* ]]; then + dir=${dir%/*} + else + dir=. + fi + + # Search for 'Kbuild' or 'Makefile' in the parent + # directories (may not be a direct parent) + if [[ -f ${srctree}/${dir}/Kbuild ]]; then + kbuild_file=${srctree}/${dir}/Kbuild + break + fi + if [[ -f ${srctree}/${dir}/Makefile ]]; then + kbuild_file=${srctree}/${dir}/Makefile + break + fi + + if [[ ${dir} == . ]]; then + break + fi + done + + if [[ -n ${kbuild_file} ]]; then + tmp=($(__kbuild_tmp_makefile "${kbuild_file}" | + SRCARCH=${srcarch} obj=${dir} src=${srctree}/${dir} \ + "${1}" -n -f - 2>/dev/null)) + + # Add $(obj)/ prefix + if [[ ${dir} != . ]]; then + tmp=("${tmp[@]/#/${dir}\/}") + fi + + keywords+=("${tmp[@]}") + fi + + # *_defconfig and *.config files. These might be grouped into + # subdirectories, e.g., arch/powerpc/configs/*/*_defconfig. + if [[ ${cur} == */* ]]; then + dir=${cur%/*} + else + dir=. + fi + + tmp=($(find "${srctree}/arch/${srcarch}/configs/${dir}" \ + "${srctree}/kernel/configs/${dir}" \ + -mindepth 1 -maxdepth 1 -type d -printf '%P/\n' \ + -o -printf '%P\n' 2>/dev/null)) + + if [[ ${dir} != . ]]; then + tmp=("${tmp[@]/#/${dir}\/}") + fi + + keywords+=("${tmp[@]}") + fi + + # shellcheck disable=SC2191 # '=' is appended for variables + keywords+=( + # + # variables (append =) + # + ARCH= + CROSS_COMPILE= + LLVM= + C= M= MO= O= V= W= + INSTALL{,_MOD,_HDR,_DTBS}_PATH= + KERNELRELEASE= + + # + # targets + # + all help + clean mrproper distclean + clang-{tidy,analyzer} compile_commands.json + coccicheck + dtbs{,_check,_install} dt_binding_{check,schemas} + headers{,_install} + vmlinux install + modules{,_prepare,_install,_sign} + vdso_install + tags TAGS cscope gtags + rust{available,fmt,fmtcheck} + kernel{version,release} image_name + kselftest{,-all,-install,-clean,-merge} + + # configuration + {,old,olddef,sync,def,savedef,rand,listnew,helpnew,test,tiny}config + {,build_}{menu,n,g,x}config + local{mod,yes}config + all{no,yes,mod,def}config + {yes2mod,mod2yes,mod2no}config + + # docs + {html,textinfo,info,latex,pdf,epub,xml,linkcheck,refcheck,clean}docs + + # package + {,bin,src}{rpm,deb}-pkg + {pacman,dir,tar}-pkg + tar{,gz,bz2,xz,zst}-pkg + perf-tar{,gz,bz2,xz,zst}-src-pkg + ) + + COMPREPLY=($(compgen -W "${keywords[*]}" -- "${cur}")) + + # Do not append a space for variables, subdirs, "KBUILD_", "KCONFIG_". + if [[ ${COMPREPLY-} == *[=/] || ${COMPREPLY-} =~ ^(KBUILD|KCONFIG)_$ ]]; then + compopt -o nospace + fi + +} && complete -F _make_for_kbuild make
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 784912f..3d22bf8 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl
@@ -3690,20 +3690,6 @@ } } - if (($realfile =~ /Makefile.*/ || $realfile =~ /Kbuild.*/) && - ($line =~ /\+(EXTRA_[A-Z]+FLAGS).*/)) { - my $flag = $1; - my $replacement = { - 'EXTRA_AFLAGS' => 'asflags-y', - 'EXTRA_CFLAGS' => 'ccflags-y', - 'EXTRA_CPPFLAGS' => 'cppflags-y', - 'EXTRA_LDFLAGS' => 'ldflags-y', - }; - - WARN("DEPRECATED_VARIABLE", - "Use of $flag is deprecated, please use \`$replacement->{$flag} instead.\n" . $herecurr) if ($replacement->{$flag}); - } - # check for DT compatible documentation if (defined $root && (($realfile =~ /\.dtsi?$/ && $line =~ /^\+\s*compatible\s*=\s*\"/) ||
diff --git a/scripts/clang-tools/gen_compile_commands.py b/scripts/clang-tools/gen_compile_commands.py index e4fb686..96e6e46 100755 --- a/scripts/clang-tools/gen_compile_commands.py +++ b/scripts/clang-tools/gen_compile_commands.py
@@ -167,10 +167,10 @@ root_directory or file_directory. """ # The .cmd files are intended to be included directly by Make, so they - # escape the pound sign '#', either as '\#' or '$(pound)' (depending on the - # kernel version). The compile_commands.json file is not interepreted - # by Make, so this code replaces the escaped version with '#'. - prefix = command_prefix.replace(r'\#', '#').replace('$(pound)', '#') + # escape the pound sign '#' as '$(pound)'. The compile_commands.json file + # is not interepreted by Make, so this code replaces the escaped version + # with '#'. + prefix = command_prefix.replace('$(pound)', '#') # Return the canonical path, eliminating any symbolic links encountered in the path. abs_path = os.path.realpath(os.path.join(root_directory, file_path))
diff --git a/scripts/config b/scripts/config index ff88e2f..ea475c0 100755 --- a/scripts/config +++ b/scripts/config
@@ -32,6 +32,7 @@ Disable option directly after other option --module-after|-M beforeopt option Turn option into module directly after other option + --refresh Refresh the config using old settings commands can be repeated multiple times @@ -124,16 +125,22 @@ txt_delete "^# $name is not set" "$FN" } -if [ "$1" = "--file" ]; then - FN="$2" - if [ "$FN" = "" ] ; then - usage +FN=.config +CMDS=() +while [[ $# -gt 0 ]]; do + if [ "$1" = "--file" ]; then + if [ "$2" = "" ]; then + usage + fi + FN="$2" + shift 2 + else + CMDS+=("$1") + shift fi - shift 2 -else - FN=.config -fi +done +set -- "${CMDS[@]}" if [ "$1" = "" ] ; then usage fi @@ -217,9 +224,8 @@ set_var "${CONFIG_}$B" "${CONFIG_}$B=m" "${CONFIG_}$A" ;; - # undocumented because it ignores --file (fixme) --refresh) - yes "" | make oldconfig + yes "" | make oldconfig KCONFIG_CONFIG=$FN ;; *)
diff --git a/scripts/gendwarfksyms/die.c b/scripts/gendwarfksyms/die.c index 66bd4c9..6183bbb 100644 --- a/scripts/gendwarfksyms/die.c +++ b/scripts/gendwarfksyms/die.c
@@ -6,7 +6,7 @@ #include <string.h> #include "gendwarfksyms.h" -#define DIE_HASH_BITS 15 +#define DIE_HASH_BITS 16 /* {die->addr, state} -> struct die * */ static HASHTABLE_DEFINE(die_map, 1 << DIE_HASH_BITS);
diff --git a/scripts/gendwarfksyms/dwarf.c b/scripts/gendwarfksyms/dwarf.c index 534d9aa..eed247d 100644 --- a/scripts/gendwarfksyms/dwarf.c +++ b/scripts/gendwarfksyms/dwarf.c
@@ -3,6 +3,7 @@ * Copyright (C) 2024 Google LLC */ +#define _GNU_SOURCE #include <assert.h> #include <inttypes.h> #include <stdarg.h> @@ -193,79 +194,17 @@ static void process_fmt(struct die *cache, const char *fmt, ...) va_end(args); } -#define MAX_FQN_SIZE 64 - -/* Get a fully qualified name from DWARF scopes */ -static char *get_fqn(Dwarf_Die *die) -{ - const char *list[MAX_FQN_SIZE]; - Dwarf_Die *scopes = NULL; - bool has_name = false; - char *fqn = NULL; - char *p; - int count = 0; - int len = 0; - int res; - int i; - - res = checkp(dwarf_getscopes_die(die, &scopes)); - if (!res) { - list[count] = get_name_attr(die); - - if (!list[count]) - return NULL; - - len += strlen(list[count]); - count++; - - goto done; - } - - for (i = res - 1; i >= 0 && count < MAX_FQN_SIZE; i--) { - if (dwarf_tag(&scopes[i]) == DW_TAG_compile_unit) - continue; - - list[count] = get_name_attr(&scopes[i]); - - if (list[count]) { - has_name = true; - } else { - list[count] = "<anonymous>"; - has_name = false; - } - - len += strlen(list[count]); - count++; - - if (i > 0) { - list[count++] = "::"; - len += 2; - } - } - - free(scopes); - - if (count == MAX_FQN_SIZE) - warn("increase MAX_FQN_SIZE: reached the maximum"); - - /* Consider the DIE unnamed if the last scope doesn't have a name */ - if (!has_name) - return NULL; -done: - fqn = xmalloc(len + 1); - *fqn = '\0'; - - p = fqn; - for (i = 0; i < count; i++) - p = stpcpy(p, list[i]); - - return fqn; -} - static void update_fqn(struct die *cache, Dwarf_Die *die) { - if (!cache->fqn) - cache->fqn = get_fqn(die) ?: ""; + struct die *fqn; + + if (!cache->fqn) { + if (!__die_map_get((uintptr_t)die->addr, DIE_FQN, &fqn) && + *fqn->fqn) + cache->fqn = xstrdup(fqn->fqn); + else + cache->fqn = ""; + } } static void process_fqn(struct die *cache, Dwarf_Die *die) @@ -1148,8 +1087,81 @@ static void process_symbol_ptr(struct symbol *sym, void *arg) cache_free(&state.expansion_cache); } +static int resolve_fqns(struct state *parent, struct die *unused, + Dwarf_Die *die) +{ + struct state state; + struct die *cache; + const char *name; + bool use_prefix; + char *prefix = NULL; + char *fqn = ""; + int tag; + + if (!__die_map_get((uintptr_t)die->addr, DIE_FQN, &cache)) + return 0; + + tag = dwarf_tag(die); + + /* + * Only namespaces and structures need to pass a prefix to the next + * scope. + */ + use_prefix = tag == DW_TAG_namespace || tag == DW_TAG_class_type || + tag == DW_TAG_structure_type; + + state.expand.current_fqn = NULL; + name = get_name_attr(die); + + if (parent && parent->expand.current_fqn && (use_prefix || name)) { + /* + * The fqn for the current DIE, and if needed, a prefix for the + * next scope. + */ + if (asprintf(&prefix, "%s::%s", parent->expand.current_fqn, + name ? name : "<anonymous>") < 0) + error("asprintf failed"); + + if (use_prefix) + state.expand.current_fqn = prefix; + + /* + * Use fqn only if the DIE has a name. Otherwise fqn will + * remain empty. + */ + if (name) { + fqn = prefix; + /* prefix will be freed by die_map. */ + prefix = NULL; + } + } else if (name) { + /* No prefix from the previous scope. Use only the name. */ + fqn = xstrdup(name); + + if (use_prefix) + state.expand.current_fqn = fqn; + } + + /* If the DIE has a non-empty name, cache it. */ + if (*fqn) { + cache = die_map_get(die, DIE_FQN); + /* Move ownership of fqn to die_map. */ + cache->fqn = fqn; + cache->state = DIE_FQN; + } + + check(process_die_container(&state, NULL, die, resolve_fqns, + match_all)); + + free(prefix); + return 0; +} + void process_cu(Dwarf_Die *cudie) { + check(process_die_container(NULL, NULL, cudie, resolve_fqns, + match_all)); + check(process_die_container(NULL, NULL, cudie, process_exported_symbols, match_all));
diff --git a/scripts/gendwarfksyms/gendwarfksyms.h b/scripts/gendwarfksyms/gendwarfksyms.h index 197a1a8..2feec16 100644 --- a/scripts/gendwarfksyms/gendwarfksyms.h +++ b/scripts/gendwarfksyms/gendwarfksyms.h
@@ -139,6 +139,7 @@ void symbol_free(void); enum die_state { DIE_INCOMPLETE, + DIE_FQN, DIE_UNEXPANDED, DIE_COMPLETE, DIE_SYMBOL, @@ -170,6 +171,7 @@ static inline const char *die_state_name(enum die_state state) { switch (state) { CASE_CONST_TO_STR(DIE_INCOMPLETE) + CASE_CONST_TO_STR(DIE_FQN) CASE_CONST_TO_STR(DIE_UNEXPANDED) CASE_CONST_TO_STR(DIE_COMPLETE) CASE_CONST_TO_STR(DIE_SYMBOL)
diff --git a/scripts/gendwarfksyms/types.c b/scripts/gendwarfksyms/types.c index 6c03265..6f37289 100644 --- a/scripts/gendwarfksyms/types.c +++ b/scripts/gendwarfksyms/types.c
@@ -248,7 +248,7 @@ static char *get_type_name(struct die *cache) warn("found incomplete cache entry: %p", cache); return NULL; } - if (cache->state == DIE_SYMBOL) + if (cache->state == DIE_SYMBOL || cache->state == DIE_FQN) return NULL; if (!cache->fqn || !*cache->fqn) return NULL;
diff --git a/scripts/generate_builtin_ranges.awk b/scripts/generate_builtin_ranges.awk index b9ec761..d4bd5c2 100755 --- a/scripts/generate_builtin_ranges.awk +++ b/scripts/generate_builtin_ranges.awk
@@ -282,6 +282,11 @@ # section. # ARGIND == 2 && sect && NF == 4 && /^ [^ \*]/ && !($1 in sect_addend) { + # There are a few sections with constant data (without symbols) that + # can get resized during linking, so it is best to ignore them. + if ($1 ~ /^\.rodata\.(cst|str)[0-9]/) + next; + if (!($1 in sect_base)) { sect_base[$1] = base;
diff --git a/scripts/generate_rust_target.rs b/scripts/generate_rust_target.rs index 4fd6b6a..8667d0a 100644 --- a/scripts/generate_rust_target.rs +++ b/scripts/generate_rust_target.rs
@@ -184,7 +184,9 @@ fn main() { let mut ts = TargetSpec::new(); // `llvm-target`s are taken from `scripts/Makefile.clang`. - if cfg.has("ARM64") { + if cfg.has("ARM") { + panic!("arm uses the builtin rustc target"); + } else if cfg.has("ARM64") { panic!("arm64 uses the builtin rustc aarch64-unknown-none target"); } else if cfg.has("RISCV") { if cfg.has("64BIT") {
diff --git a/scripts/genksyms/lex.l b/scripts/genksyms/lex.l index 22aeb57..f81033a 100644 --- a/scripts/genksyms/lex.l +++ b/scripts/genksyms/lex.l
@@ -176,10 +176,10 @@ switch (lexstate) { case ST_NORMAL: + APP; switch (token) { case IDENT: - APP; { int r = is_reserved_word(yytext, yyleng); if (r >= 0) @@ -224,13 +224,11 @@ break; case '[': - APP; lexstate = ST_BRACKET; count = 1; goto repeat; case '{': - APP; if (dont_want_brace_phrase) break; lexstate = ST_BRACE; @@ -238,12 +236,10 @@ goto repeat; case '=': case ':': - APP; lexstate = ST_EXPRESSION; break; default: - APP; break; } break;
diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c index 3b55e7a..ac95661 100644 --- a/scripts/kconfig/confdata.c +++ b/scripts/kconfig/confdata.c
@@ -385,7 +385,7 @@ int conf_read_simple(const char *name, int def) def_flags = SYMBOL_DEF << def; for_all_symbols(sym) { - sym->flags &= ~(def_flags|SYMBOL_VALID); + sym->flags &= ~def_flags; switch (sym->type) { case S_INT: case S_HEX: @@ -398,7 +398,11 @@ int conf_read_simple(const char *name, int def) } } - expr_invalidate_all(); + if (def == S_DEF_USER) { + for_all_symbols(sym) + sym->flags &= ~SYMBOL_VALID; + expr_invalidate_all(); + } while (getline_stripped(&line, &line_asize, in) != -1) { struct menu *choice; @@ -464,6 +468,9 @@ int conf_read_simple(const char *name, int def) if (conf_set_sym_val(sym, def, def_flags, val)) continue; + if (def != S_DEF_USER) + continue; + /* * If this is a choice member, give it the highest priority. * If conflicting CONFIG options are given from an input file, @@ -967,10 +974,8 @@ static int conf_touch_deps(void) depfile_path[depfile_prefix_len] = 0; conf_read_simple(name, S_DEF_AUTO); - sym_calc_value(modules_sym); for_all_symbols(sym) { - sym_calc_value(sym); if (sym_is_choice(sym)) continue; if (sym->flags & SYMBOL_WRITE) { @@ -1084,12 +1089,12 @@ int conf_write_autoconf(int overwrite) if (ret) return -1; - if (conf_touch_deps()) - return 1; - for_all_symbols(sym) sym_calc_value(sym); + if (conf_touch_deps()) + return 1; + ret = __conf_write_autoconf(conf_get_autoheader_name(), print_symbol_for_c, &comment_style_c);
diff --git a/scripts/kconfig/merge_config.sh b/scripts/kconfig/merge_config.sh index 0b79524..79c09b3 100755 --- a/scripts/kconfig/merge_config.sh +++ b/scripts/kconfig/merge_config.sh
@@ -112,8 +112,8 @@ shift; if [ ! -r "$INITFILE" ]; then - echo "The base file '$INITFILE' does not exist. Exit." >&2 - exit 1 + echo "The base file '$INITFILE' does not exist. Creating one..." >&2 + touch "$INITFILE" fi MERGE_LIST=$*
diff --git a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c index 7beb59d..d57f8cb 100644 --- a/scripts/kconfig/symbol.c +++ b/scripts/kconfig/symbol.c
@@ -879,7 +879,7 @@ const char *sym_get_string_value(struct symbol *sym) default: ; } - return (const char *)sym->curr.val; + return sym->curr.val; } bool sym_is_changeable(const struct symbol *sym)
diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh index 94c7824..51367c2 100755 --- a/scripts/link-vmlinux.sh +++ b/scripts/link-vmlinux.sh
@@ -31,6 +31,7 @@ LD="$1" KBUILD_LDFLAGS="$2" LDFLAGS_vmlinux="$3" +VMLINUX="$4" is_enabled() { grep -q "^$1=y" include/config/auto.conf @@ -97,8 +98,8 @@ ldflags="${ldflags} ${wl}--strip-debug" fi - if is_enabled CONFIG_VMLINUX_MAP; then - ldflags="${ldflags} ${wl}-Map=${output}.map" + if [ -n "${generate_map}" ]; then + ldflags="${ldflags} ${wl}-Map=vmlinux.map" fi ${ld} ${ldflags} -o ${output} \ @@ -208,6 +209,7 @@ btf_vmlinux_bin_o= kallsymso= strip_debug= +generate_map= if is_enabled CONFIG_KALLSYMS; then true > .tmp_vmlinux0.syms @@ -276,23 +278,27 @@ strip_debug= -vmlinux_link vmlinux +if is_enabled CONFIG_VMLINUX_MAP; then + generate_map=1 +fi + +vmlinux_link "${VMLINUX}" # fill in BTF IDs if is_enabled CONFIG_DEBUG_INFO_BTF; then - info BTFIDS vmlinux + info BTFIDS "${VMLINUX}" RESOLVE_BTFIDS_ARGS="" if is_enabled CONFIG_WERROR; then RESOLVE_BTFIDS_ARGS=" --fatal_warnings " fi - ${RESOLVE_BTFIDS} ${RESOLVE_BTFIDS_ARGS} vmlinux + ${RESOLVE_BTFIDS} ${RESOLVE_BTFIDS_ARGS} "${VMLINUX}" fi -mksysmap vmlinux System.map +mksysmap "${VMLINUX}" System.map if is_enabled CONFIG_BUILDTIME_TABLE_SORT; then - info SORTTAB vmlinux - if ! sorttable vmlinux; then + info SORTTAB "${VMLINUX}" + if ! sorttable "${VMLINUX}"; then echo >&2 Failed to sort kernel tables exit 1 fi @@ -308,4 +314,4 @@ fi # For fixdep -echo "vmlinux: $0" > .vmlinux.d +echo "${VMLINUX}: $0" > ".${VMLINUX}.d"
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index c35d226..be89921 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c
@@ -98,6 +98,18 @@ static inline bool strends(const char *str, const char *postfix) return strcmp(str + strlen(str) - strlen(postfix), postfix) == 0; } +/** + * get_basename - return the last part of a pathname. + * + * @path: path to extract the filename from. + */ +const char *get_basename(const char *path) +{ + const char *tail = strrchr(path, '/'); + + return tail ? tail + 1 : path; +} + char *read_text_file(const char *filename) { struct stat st; @@ -1461,14 +1473,8 @@ static void extract_crcs_for_object(const char *object, struct module *mod) const char *base; int dirlen, ret; - base = strrchr(object, '/'); - if (base) { - base++; - dirlen = base - object; - } else { - dirlen = 0; - base = object; - } + base = get_basename(object); + dirlen = base - object; ret = snprintf(cmd_file, sizeof(cmd_file), "%.*s.%s.cmd", dirlen, object, base); @@ -1596,7 +1602,7 @@ static void read_symbols(const char *modname) namespace); } - if (extra_warn && !get_modinfo(&info, "description")) + if (!get_modinfo(&info, "description")) warn("missing MODULE_DESCRIPTION() in %s\n", modname); } @@ -1703,11 +1709,7 @@ static void check_exports(struct module *mod) s->crc_valid = exp->crc_valid; s->crc = exp->crc; - basename = strrchr(mod->name, '/'); - if (basename) - basename++; - else - basename = mod->name; + basename = get_basename(mod->name); if (!contains_namespace(&mod->imported_namespaces, exp->namespace)) { modpost_log(!allow_missing_ns_imports, @@ -1765,11 +1767,8 @@ static void check_modname_len(struct module *mod) { const char *mod_name; - mod_name = strrchr(mod->name, '/'); - if (mod_name == NULL) - mod_name = mod->name; - else - mod_name++; + mod_name = get_basename(mod->name); + if (strlen(mod_name) >= MODULE_NAME_LEN) error("module name is too long [%s.ko]\n", mod->name); } @@ -1946,11 +1945,7 @@ static void add_depends(struct buffer *b, struct module *mod) continue; s->module->seen = true; - p = strrchr(s->module->name, '/'); - if (p) - p++; - else - p = s->module->name; + p = get_basename(s->module->name); buf_printf(b, "%s%s", first ? "" : ",", p); first = 0; }
diff --git a/scripts/mod/modpost.h b/scripts/mod/modpost.h index 59366f4..9133e4c 100644 --- a/scripts/mod/modpost.h +++ b/scripts/mod/modpost.h
@@ -216,6 +216,7 @@ void get_src_version(const char *modname, char sum[], unsigned sumlen); /* from modpost.c */ extern bool target_is_big_endian; extern bool host_is_big_endian; +const char *get_basename(const char *path); char *read_text_file(const char *filename); char *get_line(char **stringp); void *sym_get_data(const struct elf_info *info, const Elf_Sym *sym);
diff --git a/scripts/mod/sumversion.c b/scripts/mod/sumversion.c index 6de9af1..3dd28b4 100644 --- a/scripts/mod/sumversion.c +++ b/scripts/mod/sumversion.c
@@ -309,15 +309,10 @@ static int parse_source_files(const char *objfile, struct md4_ctx *md) cmd = xmalloc(strlen(objfile) + sizeof("..cmd")); - base = strrchr(objfile, '/'); - if (base) { - base++; - dirlen = base - objfile; - sprintf(cmd, "%.*s.%s.cmd", dirlen, objfile, base); - } else { - dirlen = 0; - sprintf(cmd, ".%s.cmd", objfile); - } + base = get_basename(objfile); + dirlen = base - objfile; + sprintf(cmd, "%.*s.%s.cmd", dirlen, objfile, base); + dir = xmalloc(dirlen + 1); strncpy(dir, objfile, dirlen); dir[dirlen] = '\0'; @@ -335,7 +330,7 @@ static int parse_source_files(const char *objfile, struct md4_ctx *md) line++; p = line; - if (strncmp(line, "source_", sizeof("source_")-1) == 0) { + if (strstarts(line, "source_")) { p = strrchr(line, ' '); if (!p) { warn("malformed line: %s\n", line); @@ -349,7 +344,7 @@ static int parse_source_files(const char *objfile, struct md4_ctx *md) } continue; } - if (strncmp(line, "deps_", sizeof("deps_")-1) == 0) { + if (strstarts(line, "deps_")) { check_files = 1; continue; }
diff --git a/scripts/package/PKGBUILD b/scripts/package/PKGBUILD index 0cf3a55b..452374d 100644 --- a/scripts/package/PKGBUILD +++ b/scripts/package/PKGBUILD
@@ -53,7 +53,7 @@ _package() { pkgdesc="The ${pkgdesc} kernel and modules" - local modulesdir="${pkgdir}/usr/${MODLIB}" + local modulesdir="${pkgdir}/usr/lib/modules/${KERNELRELEASE}" _prologue @@ -81,7 +81,7 @@ _package-headers() { pkgdesc="Headers and scripts for building modules for the ${pkgdesc} kernel" - local builddir="${pkgdir}/usr/${MODLIB}/build" + local builddir="${pkgdir}/usr/lib/modules/${KERNELRELEASE}/build" _prologue @@ -114,7 +114,7 @@ pkgdesc="Non-stripped vmlinux file for the ${pkgdesc} kernel" local debugdir="${pkgdir}/usr/src/debug/${pkgbase}" - local builddir="${pkgdir}/usr/${MODLIB}/build" + local builddir="${pkgdir}/usr/lib/modules/${KERNELRELEASE}/build" _prologue
diff --git a/scripts/package/debian/rules b/scripts/package/debian/rules index ca07243b..a417a7f 100755 --- a/scripts/package/debian/rules +++ b/scripts/package/debian/rules
@@ -21,9 +21,11 @@ endif endif -revision = $(lastword $(subst -, ,$(shell dpkg-parsechangelog -S Version))) +revision = $(shell dpkg-parsechangelog -S Version | sed -n 's/.*-//p') CROSS_COMPILE ?= $(filter-out $(DEB_BUILD_GNU_TYPE)-, $(DEB_HOST_GNU_TYPE)-) -make-opts = ARCH=$(ARCH) KERNELRELEASE=$(KERNELRELEASE) KBUILD_BUILD_VERSION=$(revision) $(addprefix CROSS_COMPILE=,$(CROSS_COMPILE)) +make-opts = ARCH=$(ARCH) KERNELRELEASE=$(KERNELRELEASE) \ + $(addprefix KBUILD_BUILD_VERSION=,$(revision)) \ + $(addprefix CROSS_COMPILE=,$(CROSS_COMPILE)) binary-targets := $(addprefix binary-, image image-dbg headers libc-dev) @@ -41,6 +43,10 @@ # which package is being processed in the build log. DH_OPTIONS = -p$(package) +# Note: future removal of KDEB_COMPRESS +# dpkg-deb >= 1.21.10 supports the DPKG_DEB_COMPRESSOR_TYPE environment +# variable, which provides the same functionality as KDEB_COMPRESS. The +# KDEB_COMPRESS variable will be removed in the future. define binary $(Q)dh_testdir $(DH_OPTIONS) $(Q)dh_testroot $(DH_OPTIONS)
diff --git a/scripts/package/kernel.spec b/scripts/package/kernel.spec index ac3e5ac..726f34e 100644 --- a/scripts/package/kernel.spec +++ b/scripts/package/kernel.spec
@@ -2,8 +2,6 @@ %{!?_arch: %define _arch dummy} %{!?make: %define make make} %define makeflags %{?_smp_mflags} ARCH=%{ARCH} -%define __spec_install_post /usr/lib/rpm/brp-compress || : -%define debug_package %{nil} Name: kernel Summary: The Linux Kernel @@ -46,6 +44,36 @@ against the %{version} kernel package. %endif +%if %{with_debuginfo} +# list of debuginfo-related options taken from distribution kernel.spec +# files +%undefine _include_minidebuginfo +%undefine _find_debuginfo_dwz_opts +%undefine _unique_build_ids +%undefine _unique_debug_names +%undefine _unique_debug_srcs +%undefine _debugsource_packages +%undefine _debuginfo_subpackages +%global _find_debuginfo_opts -r +%global _missing_build_ids_terminate_build 1 +%global _no_recompute_build_ids 1 +%{debug_package} +%endif +# some (but not all) versions of rpmbuild emit %%debug_package with +# %%install. since we've already emitted it manually, that would cause +# a package redefinition error. ensure that doesn't happen +%define debug_package %{nil} + +# later, we make all modules executable so that find-debuginfo.sh strips +# them up. but they don't actually need to be executable, so remove the +# executable bit, taking care to do it _after_ find-debuginfo.sh has run +%define __spec_install_post \ + %{?__debug_package:%{__debug_install_post}} \ + %{__arch_install_post} \ + %{__os_install_post} \ + find %{buildroot}/lib/modules/%{KERNELRELEASE} -name "*.ko" -type f \\\ + | xargs --no-run-if-empty chmod u-x + %prep %setup -q -n linux cp %{SOURCE1} .config @@ -89,8 +117,22 @@ echo "%exclude /lib/modules/%{KERNELRELEASE}/build" } > %{buildroot}/kernel.list +# make modules executable so that find-debuginfo.sh strips them. this +# will be undone later in %%__spec_install_post +find %{buildroot}/lib/modules/%{KERNELRELEASE} -name "*.ko" -type f \ + | xargs --no-run-if-empty chmod u+x + +%if %{with_debuginfo} +# copying vmlinux directly to the debug directory means it will not get +# stripped (but its source paths will still be collected + fixed up) +mkdir -p %{buildroot}/usr/lib/debug/lib/modules/%{KERNELRELEASE} +cp vmlinux %{buildroot}/usr/lib/debug/lib/modules/%{KERNELRELEASE} +%endif + %clean rm -rf %{buildroot} +rm -f debugfiles.list debuglinks.list debugsourcefiles.list debugsources.list \ + elfbins.list %post if [ -x /usr/bin/kernel-install ]; then
diff --git a/scripts/package/mkdebian b/scripts/package/mkdebian index b6dd98c..744ddba 100755 --- a/scripts/package/mkdebian +++ b/scripts/package/mkdebian
@@ -77,6 +77,8 @@ debarch=i386 fi ;; + loongarch64) + debarch=loong64 ;; esac if [ -z "$debarch" ]; then debarch=$(dpkg-architecture -qDEB_HOST_ARCH) @@ -155,11 +157,12 @@ done # Some variables and settings used throughout the script -version=$KERNELRELEASE if [ "${KDEB_PKGVERSION:+set}" ]; then packageversion=$KDEB_PKGVERSION else - packageversion=$(${srctree}/scripts/setlocalversion --no-local ${srctree})-$($srctree/scripts/build-version) + upstream_version=$("${srctree}/scripts/setlocalversion" --no-local "${srctree}" | sed 's/-\(rc[1-9]\)/~\1/') + debian_revision=$("${srctree}/scripts/build-version") + packageversion=${upstream_version}-${debian_revision} fi sourcename=${KDEB_SOURCENAME:-linux-upstream} @@ -212,11 +215,11 @@ python3:native, rsync Homepage: https://www.kernel.org/ -Package: $packagename-$version +Package: $packagename-${KERNELRELEASE} Architecture: $debarch -Description: Linux kernel, version $version +Description: Linux kernel, version ${KERNELRELEASE} This package contains the Linux kernel, modules and corresponding other - files, version: $version. + files, version: ${KERNELRELEASE}. EOF if [ "${SRCARCH}" != um ]; then @@ -235,11 +238,11 @@ if is_enabled CONFIG_MODULES; then cat <<EOF >> debian/control -Package: linux-headers-$version +Package: linux-headers-${KERNELRELEASE} Architecture: $debarch Build-Profiles: <!pkg.${sourcename}.nokernelheaders> -Description: Linux kernel headers for $version on $debarch - This package provides kernel header files for $version on $debarch +Description: Linux kernel headers for ${KERNELRELEASE} on $debarch + This package provides kernel header files for ${KERNELRELEASE} on $debarch . This is useful for people who need to build external modules EOF @@ -249,11 +252,11 @@ if is_enabled CONFIG_DEBUG_INFO; then cat <<EOF >> debian/control -Package: linux-image-$version-dbg +Package: linux-image-${KERNELRELEASE}-dbg Section: debug Architecture: $debarch Build-Profiles: <!pkg.${sourcename}.nokerneldbg> -Description: Linux kernel debugging symbols for $version +Description: Linux kernel debugging symbols for ${KERNELRELEASE} This package will come in handy if you need to debug the kernel. It provides all the necessary debug symbols for the kernel and its modules. EOF
diff --git a/scripts/package/mkspec b/scripts/package/mkspec index 4dc1466..c7375bf 100755 --- a/scripts/package/mkspec +++ b/scripts/package/mkspec
@@ -23,6 +23,16 @@ echo '%define with_devel 0' fi +# debuginfo package generation uses find-debuginfo.sh under the hood, +# which only works on uncompressed modules that contain debuginfo +if grep -q CONFIG_DEBUG_INFO=y include/config/auto.conf && + (! grep -q CONFIG_MODULE_COMPRESS=y include/config/auto.conf) && + (! grep -q CONFIG_DEBUG_INFO_SPLIT=y include/config/auto.conf); then +echo '%define with_debuginfo %{?_without_debuginfo: 0} %{?!_without_debuginfo: 1}' +else +echo '%define with_debuginfo 0' +fi + cat<<EOF %define ARCH ${ARCH} %define KERNELRELEASE ${KERNELRELEASE}
diff --git a/scripts/show_delta b/scripts/show_delta index 291ad65..3755b6c 100755 --- a/scripts/show_delta +++ b/scripts/show_delta
@@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # SPDX-License-Identifier: GPL-2.0-only # # show_deltas: Read list of printk messages instrumented with
diff --git a/scripts/sorttable.c b/scripts/sorttable.c index 7b4b371..deed676 100644 --- a/scripts/sorttable.c +++ b/scripts/sorttable.c
@@ -857,7 +857,7 @@ static void *sort_mcount_loc(void *arg) for (void *ptr = vals; ptr < vals + size; ptr += long_size) { uint64_t key; - key = long_size == 4 ? r((uint32_t *)ptr) : r8((uint64_t *)ptr); + key = long_size == 4 ? *(uint32_t *)ptr : *(uint64_t *)ptr; if (!find_func(key)) { if (long_size == 4) *(uint32_t *)ptr = 0;
diff --git a/security/Kconfig b/security/Kconfig index 536061c..4816fc7 100644 --- a/security/Kconfig +++ b/security/Kconfig
@@ -51,6 +51,27 @@ endchoice +config MSEAL_SYSTEM_MAPPINGS + bool "mseal system mappings" + depends on 64BIT + depends on ARCH_SUPPORTS_MSEAL_SYSTEM_MAPPINGS + depends on !CHECKPOINT_RESTORE + help + Apply mseal on system mappings. + The system mappings includes vdso, vvar, vvar_vclock, + vectors (arm compat-mode), sigpage (arm compat-mode), uprobes. + + A 64-bit kernel is required for the memory sealing feature. + No specific hardware features from the CPU are needed. + + WARNING: This feature breaks programs which rely on relocating + or unmapping system mappings. Known broken software at the time + of writing includes CHECKPOINT_RESTORE, UML, gVisor, rr. Therefore + this config can't be enabled universally. + + For complete descriptions of memory sealing, please see + Documentation/userspace-api/mseal.rst + config SECURITY bool "Enable different security models" depends on SYSFS
diff --git a/sound/core/timer.c b/sound/core/timer.c index d774b9b..1de4b90 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c
@@ -1152,7 +1152,7 @@ static int snd_timer_s_stop(struct snd_timer * timer) unsigned long jiff; priv = (struct snd_timer_system_private *) timer->private_data; - del_timer(&priv->tlist); + timer_delete(&priv->tlist); jiff = jiffies; if (time_before(jiff, priv->last_expires)) timer->sticks = priv->last_expires - jiff; @@ -1167,7 +1167,7 @@ static int snd_timer_s_close(struct snd_timer *timer) struct snd_timer_system_private *priv; priv = (struct snd_timer_system_private *)timer->private_data; - del_timer_sync(&priv->tlist); + timer_delete_sync(&priv->tlist); return 0; }
diff --git a/sound/drivers/aloop.c b/sound/drivers/aloop.c index eb8a68a..4b02ec1 100644 --- a/sound/drivers/aloop.c +++ b/sound/drivers/aloop.c
@@ -261,7 +261,7 @@ static int loopback_snd_timer_start(struct loopback_pcm *dpcm) /* call in cable->lock */ static inline int loopback_jiffies_timer_stop(struct loopback_pcm *dpcm) { - del_timer(&dpcm->timer); + timer_delete(&dpcm->timer); dpcm->timer.expires = 0; return 0; @@ -292,7 +292,7 @@ static int loopback_snd_timer_stop(struct loopback_pcm *dpcm) static inline int loopback_jiffies_timer_stop_sync(struct loopback_pcm *dpcm) { - del_timer_sync(&dpcm->timer); + timer_delete_sync(&dpcm->timer); return 0; }
diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c index c1a3efb..1d923cb 100644 --- a/sound/drivers/dummy.c +++ b/sound/drivers/dummy.c
@@ -279,7 +279,7 @@ static int dummy_systimer_stop(struct snd_pcm_substream *substream) { struct dummy_systimer_pcm *dpcm = substream->runtime->private_data; spin_lock(&dpcm->lock); - del_timer(&dpcm->timer); + timer_delete(&dpcm->timer); spin_unlock(&dpcm->lock); return 0; }
diff --git a/sound/drivers/mpu401/mpu401_uart.c b/sound/drivers/mpu401/mpu401_uart.c index 8e3318e..a63e755 100644 --- a/sound/drivers/mpu401/mpu401_uart.c +++ b/sound/drivers/mpu401/mpu401_uart.c
@@ -197,7 +197,7 @@ static void snd_mpu401_uart_remove_timer (struct snd_mpu401 *mpu, int input) mpu->timer_invoked &= input ? ~MPU401_MODE_INPUT_TIMER : ~MPU401_MODE_OUTPUT_TIMER; if (! mpu->timer_invoked) - del_timer(&mpu->timer); + timer_delete(&mpu->timer); } spin_unlock_irqrestore (&mpu->timer_lock, flags); }
diff --git a/sound/drivers/mtpav.c b/sound/drivers/mtpav.c index 946184a..dffcdf9 100644 --- a/sound/drivers/mtpav.c +++ b/sound/drivers/mtpav.c
@@ -412,7 +412,7 @@ static void snd_mtpav_add_output_timer(struct mtpav *chip) /* spinlock held! */ static void snd_mtpav_remove_output_timer(struct mtpav *chip) { - del_timer(&chip->timer); + timer_delete(&chip->timer); } /*
diff --git a/sound/drivers/opl3/opl3_seq.c b/sound/drivers/opl3/opl3_seq.c index 75de129..9fc78b7 100644 --- a/sound/drivers/opl3/opl3_seq.c +++ b/sound/drivers/opl3/opl3_seq.c
@@ -74,7 +74,7 @@ void snd_opl3_synth_cleanup(struct snd_opl3 * opl3) /* Stop system timer */ spin_lock_irqsave(&opl3->sys_timer_lock, flags); if (opl3->sys_timer_status) { - del_timer(&opl3->tlist); + timer_delete(&opl3->tlist); opl3->sys_timer_status = 0; } spin_unlock_irqrestore(&opl3->sys_timer_lock, flags);
diff --git a/sound/drivers/serial-u16550.c b/sound/drivers/serial-u16550.c index f66e016..1857a78 100644 --- a/sound/drivers/serial-u16550.c +++ b/sound/drivers/serial-u16550.c
@@ -166,7 +166,7 @@ static inline void snd_uart16550_add_timer(struct snd_uart16550 *uart) static inline void snd_uart16550_del_timer(struct snd_uart16550 *uart) { if (uart->timer_running) { - del_timer(&uart->buffer_timer); + timer_delete(&uart->buffer_timer); uart->timer_running = 0; } }
diff --git a/sound/hda/intel-sdw-acpi.c b/sound/hda/intel-sdw-acpi.c index 49d3e0e..8686ada 100644 --- a/sound/hda/intel-sdw-acpi.c +++ b/sound/hda/intel-sdw-acpi.c
@@ -11,8 +11,8 @@ #include <linux/device.h> #include <linux/errno.h> #include <linux/export.h> -#include <linux/fwnode.h> #include <linux/module.h> +#include <linux/property.h> #include <linux/soundwire/sdw_intel.h> #include <linux/string.h>
diff --git a/sound/i2c/other/ak4117.c b/sound/i2c/other/ak4117.c index 165fdda..657b331 100644 --- a/sound/i2c/other/ak4117.c +++ b/sound/i2c/other/ak4117.c
@@ -99,7 +99,7 @@ void snd_ak4117_reinit(struct ak4117 *chip) { unsigned char old = chip->regmap[AK4117_REG_PWRDN], reg; - del_timer(&chip->timer); + timer_delete(&chip->timer); chip->init = 1; /* bring the chip to reset state and powerdown state */ reg_write(chip, AK4117_REG_PWRDN, 0);
diff --git a/sound/isa/sb/emu8000_pcm.c b/sound/isa/sb/emu8000_pcm.c index 9234d4fe..0162352 100644 --- a/sound/isa/sb/emu8000_pcm.c +++ b/sound/isa/sb/emu8000_pcm.c
@@ -364,7 +364,7 @@ static void stop_voice(struct snd_emu8k_pcm *rec, int ch) /* stop timer */ spin_lock_irqsave(&rec->timer_lock, flags); if (rec->timer_running) { - del_timer(&rec->timer); + timer_delete(&rec->timer); rec->timer_running = 0; } spin_unlock_irqrestore(&rec->timer_lock, flags);
diff --git a/sound/isa/sb/sb8_midi.c b/sound/isa/sb/sb8_midi.c index 618366d..d2908fc 100644 --- a/sound/isa/sb/sb8_midi.c +++ b/sound/isa/sb/sb8_midi.c
@@ -125,7 +125,7 @@ static int snd_sb8dsp_midi_output_close(struct snd_rawmidi_substream *substream) struct snd_sb *chip; chip = substream->rmidi->private_data; - del_timer_sync(&chip->midi_timer); + timer_delete_sync(&chip->midi_timer); spin_lock_irqsave(&chip->open_lock, flags); chip->open &= ~(SB_OPEN_MIDI_OUTPUT | SB_OPEN_MIDI_OUTPUT_TRIGGER); chip->midi_substream_output = NULL; @@ -174,7 +174,7 @@ static void snd_sb8dsp_midi_output_write(struct snd_rawmidi_substream *substream spin_lock_irqsave(&chip->open_lock, flags); if (snd_rawmidi_transmit_peek(substream, &byte, 1) != 1) { chip->open &= ~SB_OPEN_MIDI_OUTPUT_TRIGGER; - del_timer(&chip->midi_timer); + timer_delete(&chip->midi_timer); spin_unlock_irqrestore(&chip->open_lock, flags); break; }
diff --git a/sound/isa/wavefront/wavefront_midi.c b/sound/isa/wavefront/wavefront_midi.c index ead8cbe..fcc2a0d 100644 --- a/sound/isa/wavefront/wavefront_midi.c +++ b/sound/isa/wavefront/wavefront_midi.c
@@ -157,7 +157,7 @@ static void snd_wavefront_midi_output_write(snd_wavefront_card_t *card) } else { if (midi->istimer) { if (--midi->istimer <= 0) - del_timer(&midi->timer); + timer_delete(&midi->timer); } midi->mode[midi->output_mpu] &= ~MPU401_MODE_OUTPUT_TRIGGER; spin_unlock_irqrestore (&midi->virtual, flags); @@ -212,7 +212,7 @@ static void snd_wavefront_midi_output_write(snd_wavefront_card_t *card) __timer: if (midi->istimer) { if (--midi->istimer <= 0) - del_timer(&midi->timer); + timer_delete(&midi->timer); } midi->mode[mpu] &= ~MPU401_MODE_OUTPUT_TRIGGER; spin_unlock_irqrestore (&midi->virtual, flags);
diff --git a/sound/pci/asihpi/asihpi.c b/sound/pci/asihpi/asihpi.c index 5a84591..65100f9 100644 --- a/sound/pci/asihpi/asihpi.c +++ b/sound/pci/asihpi/asihpi.c
@@ -518,7 +518,7 @@ static void snd_card_asihpi_pcm_timer_stop(struct snd_pcm_substream *substream) struct snd_card_asihpi_pcm *dpcm = runtime->private_data; dpcm->respawn_timer = 0; - del_timer(&dpcm->timer); + timer_delete(&dpcm->timer); } static void snd_card_asihpi_pcm_int_start(struct snd_pcm_substream *substream)
diff --git a/sound/pci/ctxfi/cttimer.c b/sound/pci/ctxfi/cttimer.c index 0bb447ccd..89e47fa 100644 --- a/sound/pci/ctxfi/cttimer.c +++ b/sound/pci/ctxfi/cttimer.c
@@ -112,7 +112,7 @@ static void ct_systimer_stop(struct ct_timer_instance *ti) spin_lock_irqsave(&ti->lock, flags); ti->running = 0; - del_timer(&ti->timer); + timer_delete(&ti->timer); spin_unlock_irqrestore(&ti->lock, flags); }
diff --git a/sound/pci/echoaudio/midi.c b/sound/pci/echoaudio/midi.c index 47b2c02..2ef5918 100644 --- a/sound/pci/echoaudio/midi.c +++ b/sound/pci/echoaudio/midi.c
@@ -264,7 +264,7 @@ static void snd_echo_midi_output_trigger(struct snd_rawmidi_substream *substream if (chip->tinuse) { chip->tinuse = 0; spin_unlock_irq(&chip->lock); - del_timer_sync(&chip->timer); + timer_delete_sync(&chip->timer); dev_dbg(chip->card->dev, "Timer removed\n"); return; }
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index b4fe681..79004bc 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c
@@ -4743,6 +4743,22 @@ static void alc245_fixup_hp_mute_led_coefbit(struct hda_codec *codec, } } +static void alc245_fixup_hp_mute_led_v1_coefbit(struct hda_codec *codec, + const struct hda_fixup *fix, + int action) +{ + struct alc_spec *spec = codec->spec; + + if (action == HDA_FIXUP_ACT_PRE_PROBE) { + spec->mute_led_polarity = 0; + spec->mute_led_coef.idx = 0x0b; + spec->mute_led_coef.mask = 1 << 3; + spec->mute_led_coef.on = 1 << 3; + spec->mute_led_coef.off = 0; + snd_hda_gen_add_mute_led_cdev(codec, coef_mute_led_set); + } +} + /* turn on/off mic-mute LED per capture hook by coef bit */ static int coef_micmute_led_set(struct led_classdev *led_cdev, enum led_brightness brightness) @@ -7574,6 +7590,24 @@ static void alc245_fixup_hp_spectre_x360_16_aa0xxx(struct hda_codec *codec, alc245_fixup_hp_gpio_led(codec, fix, action); } +static void alc245_fixup_hp_zbook_firefly_g12a(struct hda_codec *codec, + const struct hda_fixup *fix, int action) +{ + struct alc_spec *spec = codec->spec; + static const hda_nid_t conn[] = { 0x02 }; + + switch (action) { + case HDA_FIXUP_ACT_PRE_PROBE: + spec->gen.auto_mute_via_amp = 1; + snd_hda_override_conn_list(codec, 0x17, ARRAY_SIZE(conn), conn); + break; + } + + cs35l41_fixup_i2c_two(codec, fix, action); + alc245_fixup_hp_mute_led_coefbit(codec, fix, action); + alc285_fixup_hp_coef_micmute_led(codec, fix, action); +} + /* * ALC287 PCM hooks */ @@ -7911,6 +7945,7 @@ enum { ALC245_FIXUP_TAS2781_SPI_2, ALC287_FIXUP_YOGA7_14ARB7_I2C, ALC245_FIXUP_HP_MUTE_LED_COEFBIT, + ALC245_FIXUP_HP_MUTE_LED_V1_COEFBIT, ALC245_FIXUP_HP_X360_MUTE_LEDS, ALC287_FIXUP_THINKPAD_I2S_SPK, ALC287_FIXUP_MG_RTKC_CSAMP_CS35L41_I2C_THINKPAD, @@ -7921,6 +7956,7 @@ enum { ALC256_FIXUP_HEADPHONE_AMP_VOL, ALC245_FIXUP_HP_SPECTRE_X360_EU0XXX, ALC245_FIXUP_HP_SPECTRE_X360_16_AA0XXX, + ALC245_FIXUP_HP_ZBOOK_FIREFLY_G12A, ALC285_FIXUP_ASUS_GA403U, ALC285_FIXUP_ASUS_GA403U_HEADSET_MIC, ALC285_FIXUP_ASUS_GA403U_I2C_SPEAKER2_TO_DAC1, @@ -10164,6 +10200,10 @@ static const struct hda_fixup alc269_fixups[] = { .type = HDA_FIXUP_FUNC, .v.func = alc245_fixup_hp_mute_led_coefbit, }, + [ALC245_FIXUP_HP_MUTE_LED_V1_COEFBIT] = { + .type = HDA_FIXUP_FUNC, + .v.func = alc245_fixup_hp_mute_led_v1_coefbit, + }, [ALC245_FIXUP_HP_X360_MUTE_LEDS] = { .type = HDA_FIXUP_FUNC, .v.func = alc245_fixup_hp_mute_led_coefbit, @@ -10212,6 +10252,10 @@ static const struct hda_fixup alc269_fixups[] = { .type = HDA_FIXUP_FUNC, .v.func = alc245_fixup_hp_spectre_x360_16_aa0xxx, }, + [ALC245_FIXUP_HP_ZBOOK_FIREFLY_G12A] = { + .type = HDA_FIXUP_FUNC, + .v.func = alc245_fixup_hp_zbook_firefly_g12a, + }, [ALC285_FIXUP_ASUS_GA403U] = { .type = HDA_FIXUP_FUNC, .v.func = alc285_fixup_asus_ga403u, @@ -10658,6 +10702,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x103c, 0x8b97, "HP", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF), SND_PCI_QUIRK(0x103c, 0x8bb3, "HP Slim OMEN", ALC287_FIXUP_CS35L41_I2C_2), SND_PCI_QUIRK(0x103c, 0x8bb4, "HP Slim OMEN", ALC287_FIXUP_CS35L41_I2C_2), + SND_PCI_QUIRK(0x103c, 0x8bcd, "HP Omen 16-xd0xxx", ALC245_FIXUP_HP_MUTE_LED_V1_COEFBIT), SND_PCI_QUIRK(0x103c, 0x8bdd, "HP Envy 17", ALC287_FIXUP_CS35L41_I2C_2), SND_PCI_QUIRK(0x103c, 0x8bde, "HP Envy 17", ALC287_FIXUP_CS35L41_I2C_2), SND_PCI_QUIRK(0x103c, 0x8bdf, "HP Envy 15", ALC287_FIXUP_CS35L41_I2C_2), @@ -10751,15 +10796,15 @@ static const struct hda_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x103c, 0x8e11, "HP Trekker", ALC287_FIXUP_CS35L41_I2C_2), SND_PCI_QUIRK(0x103c, 0x8e12, "HP Trekker", ALC287_FIXUP_CS35L41_I2C_2), SND_PCI_QUIRK(0x103c, 0x8e13, "HP Trekker", ALC287_FIXUP_CS35L41_I2C_2), - SND_PCI_QUIRK(0x103c, 0x8e14, "HP ZBook Firefly 14 G12", ALC285_FIXUP_HP_GPIO_LED), - SND_PCI_QUIRK(0x103c, 0x8e15, "HP ZBook Firefly 14 G12", ALC285_FIXUP_HP_GPIO_LED), - SND_PCI_QUIRK(0x103c, 0x8e16, "HP ZBook Firefly 14 G12", ALC285_FIXUP_HP_GPIO_LED), - SND_PCI_QUIRK(0x103c, 0x8e17, "HP ZBook Firefly 14 G12", ALC285_FIXUP_HP_GPIO_LED), - SND_PCI_QUIRK(0x103c, 0x8e18, "HP ZBook Firefly 14 G12A", ALC285_FIXUP_HP_GPIO_LED), - SND_PCI_QUIRK(0x103c, 0x8e19, "HP ZBook Firefly 14 G12A", ALC285_FIXUP_HP_GPIO_LED), - SND_PCI_QUIRK(0x103c, 0x8e1a, "HP ZBook Firefly 14 G12A", ALC285_FIXUP_HP_GPIO_LED), - SND_PCI_QUIRK(0x103c, 0x8e1b, "HP EliteBook G12", ALC285_FIXUP_HP_GPIO_LED), - SND_PCI_QUIRK(0x103c, 0x8e1c, "HP EliteBook G12", ALC285_FIXUP_HP_GPIO_LED), + SND_PCI_QUIRK(0x103c, 0x8e14, "HP ZBook Firefly 14 G12", ALC245_FIXUP_HP_ZBOOK_FIREFLY_G12A), + SND_PCI_QUIRK(0x103c, 0x8e15, "HP ZBook Firefly 14 G12", ALC245_FIXUP_HP_ZBOOK_FIREFLY_G12A), + SND_PCI_QUIRK(0x103c, 0x8e16, "HP ZBook Firefly 14 G12", ALC245_FIXUP_HP_ZBOOK_FIREFLY_G12A), + SND_PCI_QUIRK(0x103c, 0x8e17, "HP ZBook Firefly 14 G12", ALC245_FIXUP_HP_ZBOOK_FIREFLY_G12A), + SND_PCI_QUIRK(0x103c, 0x8e18, "HP ZBook Firefly 14 G12A", ALC245_FIXUP_HP_ZBOOK_FIREFLY_G12A), + SND_PCI_QUIRK(0x103c, 0x8e19, "HP ZBook Firefly 14 G12A", ALC245_FIXUP_HP_ZBOOK_FIREFLY_G12A), + SND_PCI_QUIRK(0x103c, 0x8e1a, "HP ZBook Firefly 14 G12A", ALC245_FIXUP_HP_ZBOOK_FIREFLY_G12A), + SND_PCI_QUIRK(0x103c, 0x8e1b, "HP EliteBook G12", ALC245_FIXUP_HP_ZBOOK_FIREFLY_G12A), + SND_PCI_QUIRK(0x103c, 0x8e1c, "HP EliteBook G12", ALC245_FIXUP_HP_ZBOOK_FIREFLY_G12A), SND_PCI_QUIRK(0x103c, 0x8e2c, "HP EliteBook 16 G12", ALC285_FIXUP_HP_GPIO_LED), SND_PCI_QUIRK(0x103c, 0x8e36, "HP 14 Enstrom OmniBook X", ALC287_FIXUP_CS35L41_I2C_2), SND_PCI_QUIRK(0x103c, 0x8e37, "HP 16 Piston OmniBook X", ALC287_FIXUP_CS35L41_I2C_2), @@ -10804,6 +10849,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1043, 0x1493, "ASUS GV601VV/VU/VJ/VQ/VI", ALC285_FIXUP_ASUS_HEADSET_MIC), SND_PCI_QUIRK(0x1043, 0x14d3, "ASUS G614JY/JZ/JG", ALC245_FIXUP_CS35L41_SPI_2), SND_PCI_QUIRK(0x1043, 0x14e3, "ASUS G513PI/PU/PV", ALC287_FIXUP_CS35L41_I2C_2), + SND_PCI_QUIRK(0x1043, 0x14f2, "ASUS VivoBook X515JA", ALC256_FIXUP_ASUS_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1043, 0x1503, "ASUS G733PY/PZ/PZV/PYV", ALC287_FIXUP_CS35L41_I2C_2), SND_PCI_QUIRK(0x1043, 0x1517, "Asus Zenbook UX31A", ALC269VB_FIXUP_ASUS_ZENBOOK_UX31A), SND_PCI_QUIRK(0x1043, 0x1533, "ASUS GV302XA/XJ/XQ/XU/XV/XI", ALC287_FIXUP_CS35L41_I2C_2), @@ -10843,6 +10889,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1043, 0x1c43, "ASUS UX8406MA", ALC245_FIXUP_CS35L41_SPI_2), SND_PCI_QUIRK(0x1043, 0x1c62, "ASUS GU603", ALC289_FIXUP_ASUS_GA401), SND_PCI_QUIRK(0x1043, 0x1c63, "ASUS GU605M", ALC285_FIXUP_ASUS_GU605_SPI_SPEAKER2_TO_DAC1), + SND_PCI_QUIRK(0x1043, 0x1c80, "ASUS VivoBook TP401", ALC256_FIXUP_ASUS_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1043, 0x1c92, "ASUS ROG Strix G15", ALC285_FIXUP_ASUS_G533Z_PINS), SND_PCI_QUIRK(0x1043, 0x1c9f, "ASUS G614JU/JV/JI", ALC285_FIXUP_ASUS_HEADSET_MIC), SND_PCI_QUIRK(0x1043, 0x1caf, "ASUS G634JY/JZ/JI/JG", ALC285_FIXUP_ASUS_SPI_REAR_SPEAKERS),
diff --git a/sound/pci/hda/tas2781_hda_i2c.c b/sound/pci/hda/tas2781_hda_i2c.c index 9ed49b0..29dc4f5 100644 --- a/sound/pci/hda/tas2781_hda_i2c.c +++ b/sound/pci/hda/tas2781_hda_i2c.c
@@ -558,28 +558,38 @@ static int tas2563_save_calibration(struct tasdevice_priv *tas_priv) static void tas2781_apply_calib(struct tasdevice_priv *tas_priv) { - static const unsigned char page_array[CALIB_MAX] = { - 0x17, 0x18, 0x18, 0x13, 0x18, + struct calidata *cali_data = &tas_priv->cali_data; + struct cali_reg *r = &cali_data->cali_reg_array; + unsigned int cali_reg[CALIB_MAX] = { + TASDEVICE_REG(0, 0x17, 0x74), + TASDEVICE_REG(0, 0x18, 0x0c), + TASDEVICE_REG(0, 0x18, 0x14), + TASDEVICE_REG(0, 0x13, 0x70), + TASDEVICE_REG(0, 0x18, 0x7c), }; - static const unsigned char rgno_array[CALIB_MAX] = { - 0x74, 0x0c, 0x14, 0x70, 0x7c, - }; - int offset = 0; int i, j, rc; + int oft = 0; __be32 data; + if (tas_priv->dspbin_typ != TASDEV_BASIC) { + cali_reg[0] = r->r0_reg; + cali_reg[1] = r->invr0_reg; + cali_reg[2] = r->r0_low_reg; + cali_reg[3] = r->pow_reg; + cali_reg[4] = r->tlimit_reg; + } + for (i = 0; i < tas_priv->ndev; i++) { for (j = 0; j < CALIB_MAX; j++) { data = cpu_to_be32( - *(uint32_t *)&tas_priv->cali_data.data[offset]); + *(uint32_t *)&tas_priv->cali_data.data[oft]); rc = tasdevice_dev_bulk_write(tas_priv, i, - TASDEVICE_REG(0, page_array[j], rgno_array[j]), - (unsigned char *)&data, 4); + cali_reg[j], (unsigned char *)&data, 4); if (rc < 0) dev_err(tas_priv->dev, "chn %d calib %d bulk_wr err = %d\n", i, j, rc); - offset += 4; + oft += 4; } } }
diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c index fd3dfba..dc326fa 100644 --- a/sound/pci/rme9652/hdsp.c +++ b/sound/pci/rme9652/hdsp.c
@@ -1427,7 +1427,7 @@ static void snd_hdsp_midi_output_trigger(struct snd_rawmidi_substream *substream } } else { if (hmidi->istimer && --hmidi->istimer <= 0) - del_timer (&hmidi->timer); + timer_delete(&hmidi->timer); } spin_unlock_irqrestore (&hmidi->lock, flags); if (up)
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index f89718b..1935de0 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c
@@ -1978,7 +1978,7 @@ snd_hdspm_midi_output_trigger(struct snd_rawmidi_substream *substream, int up) } } else { if (hmidi->istimer && --hmidi->istimer <= 0) - del_timer (&hmidi->timer); + timer_delete(&hmidi->timer); } spin_unlock_irqrestore (&hmidi->lock, flags); if (up)
diff --git a/sound/sh/aica.c b/sound/sh/aica.c index 39bf51f..5a93f45 100644 --- a/sound/sh/aica.c +++ b/sound/sh/aica.c
@@ -354,7 +354,7 @@ static int snd_aicapcm_pcm_sync_stop(struct snd_pcm_substream *substream) { struct snd_card_aica *dreamcastcard = substream->pcm->private_data; - del_timer_sync(&dreamcastcard->timer); + timer_delete_sync(&dreamcastcard->timer); cancel_work_sync(&dreamcastcard->spu_dma_work); return 0; }
diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c index 343e3bc..dba78ef 100644 --- a/sound/soc/codecs/rt5645.c +++ b/sound/soc/codecs/rt5645.c
@@ -4286,7 +4286,7 @@ static void rt5645_i2c_remove(struct i2c_client *i2c) * Since the rt5645_btn_check_callback() can queue jack_detect_work, * the timer need to be delted first */ - del_timer_sync(&rt5645->btn_check_timer); + timer_delete_sync(&rt5645->btn_check_timer); cancel_delayed_work_sync(&rt5645->jack_detect_work); cancel_delayed_work_sync(&rt5645->rcclock_work); @@ -4318,7 +4318,7 @@ static int rt5645_sys_suspend(struct device *dev) { struct rt5645_priv *rt5645 = dev_get_drvdata(dev); - del_timer_sync(&rt5645->btn_check_timer); + timer_delete_sync(&rt5645->btn_check_timer); cancel_delayed_work_sync(&rt5645->jack_detect_work); cancel_delayed_work_sync(&rt5645->rcclock_work);
diff --git a/sound/soc/codecs/rt5665.c b/sound/soc/codecs/rt5665.c index e0d1991..bcb6d7c 100644 --- a/sound/soc/codecs/rt5665.c +++ b/sound/soc/codecs/rt5665.c
@@ -31,9 +31,7 @@ #include "rl6231.h" #include "rt5665.h" -#define RT5665_NUM_SUPPLIES 3 - -static const char *rt5665_supply_names[RT5665_NUM_SUPPLIES] = { +static const char * const rt5665_supply_names[] = { "AVDD", "MICVDD", "VBAT", @@ -46,7 +44,6 @@ struct rt5665_priv { struct gpio_desc *gpiod_ldo1_en; struct gpio_desc *gpiod_reset; struct snd_soc_jack *hs_jack; - struct regulator_bulk_data supplies[RT5665_NUM_SUPPLIES]; struct delayed_work jack_detect_work; struct delayed_work calibrate_work; struct delayed_work jd_check_work; @@ -4471,8 +4468,6 @@ static void rt5665_remove(struct snd_soc_component *component) struct rt5665_priv *rt5665 = snd_soc_component_get_drvdata(component); regmap_write(rt5665->regmap, RT5665_RESET, 0); - - regulator_bulk_disable(ARRAY_SIZE(rt5665->supplies), rt5665->supplies); } #ifdef CONFIG_PM @@ -4758,7 +4753,7 @@ static int rt5665_i2c_probe(struct i2c_client *i2c) { struct rt5665_platform_data *pdata = dev_get_platdata(&i2c->dev); struct rt5665_priv *rt5665; - int i, ret; + int ret; unsigned int val; rt5665 = devm_kzalloc(&i2c->dev, sizeof(struct rt5665_priv), @@ -4774,24 +4769,13 @@ static int rt5665_i2c_probe(struct i2c_client *i2c) else rt5665_parse_dt(rt5665, &i2c->dev); - for (i = 0; i < ARRAY_SIZE(rt5665->supplies); i++) - rt5665->supplies[i].supply = rt5665_supply_names[i]; - - ret = devm_regulator_bulk_get(&i2c->dev, ARRAY_SIZE(rt5665->supplies), - rt5665->supplies); + ret = devm_regulator_bulk_get_enable(&i2c->dev, ARRAY_SIZE(rt5665_supply_names), + rt5665_supply_names); if (ret != 0) { dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret); return ret; } - ret = regulator_bulk_enable(ARRAY_SIZE(rt5665->supplies), - rt5665->supplies); - if (ret != 0) { - dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret); - return ret; - } - - rt5665->gpiod_ldo1_en = devm_gpiod_get_optional(&i2c->dev, "realtek,ldo1-en", GPIOD_OUT_HIGH);
diff --git a/sound/soc/codecs/sma1307.c b/sound/soc/codecs/sma1307.c index f5c303d..498189a 100644 --- a/sound/soc/codecs/sma1307.c +++ b/sound/soc/codecs/sma1307.c
@@ -1705,7 +1705,7 @@ static void sma1307_check_fault_worker(struct work_struct *work) static void sma1307_setting_loaded(struct sma1307_priv *sma1307, const char *file) { const struct firmware *fw; - int *data, size, offset, num_mode; + int size, offset, num_mode; int ret; ret = request_firmware(&fw, file, sma1307->dev); @@ -1722,7 +1722,7 @@ static void sma1307_setting_loaded(struct sma1307_priv *sma1307, const char *fil return; } - data = kzalloc(fw->size, GFP_KERNEL); + int *data __free(kfree) = kzalloc(fw->size, GFP_KERNEL); if (!data) { release_firmware(fw); sma1307->set.status = false; @@ -1742,7 +1742,6 @@ static void sma1307_setting_loaded(struct sma1307_priv *sma1307, const char *fil sma1307->set.header_size, GFP_KERNEL); if (!sma1307->set.header) { - kfree(data); sma1307->set.status = false; return; } @@ -1763,8 +1762,6 @@ static void sma1307_setting_loaded(struct sma1307_priv *sma1307, const char *fil = devm_kzalloc(sma1307->dev, sma1307->set.def_size * sizeof(int), GFP_KERNEL); if (!sma1307->set.def) { - kfree(data); - kfree(sma1307->set.header); sma1307->set.status = false; return; } @@ -1782,9 +1779,6 @@ static void sma1307_setting_loaded(struct sma1307_priv *sma1307, const char *fil sma1307->set.mode_size * 2 * sizeof(int), GFP_KERNEL); if (!sma1307->set.mode_set[i]) { - kfree(data); - kfree(sma1307->set.header); - kfree(sma1307->set.def); for (int j = 0; j < i; j++) kfree(sma1307->set.mode_set[j]); sma1307->set.status = false; @@ -1799,7 +1793,6 @@ static void sma1307_setting_loaded(struct sma1307_priv *sma1307, const char *fil } } - kfree(data); sma1307->set.status = true; }
diff --git a/sound/soc/codecs/wcd934x.c b/sound/soc/codecs/wcd934x.c index dd0cda3..fa69817 100644 --- a/sound/soc/codecs/wcd934x.c +++ b/sound/soc/codecs/wcd934x.c
@@ -2263,7 +2263,7 @@ static irqreturn_t wcd934x_slim_irq_handler(int irq, void *data) { struct wcd934x_codec *wcd = data; unsigned long status = 0; - int i, j, port_id; + unsigned int i, j, port_id; unsigned int val, int_val = 0; irqreturn_t ret = IRQ_NONE; bool tx;
diff --git a/sound/soc/codecs/wsa883x.c b/sound/soc/codecs/wsa883x.c index d259e1d..1c9df7c 100644 --- a/sound/soc/codecs/wsa883x.c +++ b/sound/soc/codecs/wsa883x.c
@@ -568,7 +568,7 @@ static const struct sdw_port_config wsa883x_pconfig[WSA883X_MAX_SWR_PORTS] = { }, [WSA883X_PORT_VISENSE] = { .num = WSA883X_PORT_VISENSE + 1, - .ch_mask = 0x3, + .ch_mask = 0x1, }, };
diff --git a/sound/soc/codecs/wsa884x.c b/sound/soc/codecs/wsa884x.c index 8051483..daada1a 100644 --- a/sound/soc/codecs/wsa884x.c +++ b/sound/soc/codecs/wsa884x.c
@@ -891,7 +891,7 @@ static const struct sdw_port_config wsa884x_pconfig[WSA884X_MAX_SWR_PORTS] = { }, [WSA884X_PORT_VISENSE] = { .num = WSA884X_PORT_VISENSE + 1, - .ch_mask = 0x3, + .ch_mask = 0x1, }, [WSA884X_PORT_CPS] = { .num = WSA884X_PORT_CPS + 1,
diff --git a/sound/soc/fsl/imx-card.c b/sound/soc/fsl/imx-card.c index 9052946..3686d46 100644 --- a/sound/soc/fsl/imx-card.c +++ b/sound/soc/fsl/imx-card.c
@@ -772,6 +772,8 @@ static int imx_card_probe(struct platform_device *pdev) data->dapm_routes[i].sink = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%d %s", i + 1, "Playback"); + if (!data->dapm_routes[i].sink) + return -ENOMEM; data->dapm_routes[i].source = "CPU-Playback"; } } @@ -789,6 +791,8 @@ static int imx_card_probe(struct platform_device *pdev) data->dapm_routes[i].source = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%d %s", i + 1, "Capture"); + if (!data->dapm_routes[i].source) + return -ENOMEM; data->dapm_routes[i].sink = "CPU-Capture"; } }
diff --git a/sound/soc/fsl/imx-pcm-rpmsg.c b/sound/soc/fsl/imx-pcm-rpmsg.c index 1daf0be..de5f876 100644 --- a/sound/soc/fsl/imx-pcm-rpmsg.c +++ b/sound/soc/fsl/imx-pcm-rpmsg.c
@@ -301,7 +301,7 @@ static int imx_rpmsg_pcm_close(struct snd_soc_component *component, info->send_message(msg, info); - del_timer(&info->stream_timer[substream->stream].timer); + timer_delete(&info->stream_timer[substream->stream].timer); rtd->dai_link->ignore_suspend = 0; @@ -452,7 +452,7 @@ static int imx_rpmsg_terminate_all(struct snd_soc_component *component, info->msg[RX_POINTER].r_msg.param.buffer_offset = 0; } - del_timer(&info->stream_timer[substream->stream].timer); + timer_delete(&info->stream_timer[substream->stream].timer); return imx_rpmsg_insert_workqueue(substream, msg, info); }
diff --git a/sound/soc/qcom/qdsp6/q6apm-dai.c b/sound/soc/qcom/qdsp6/q6apm-dai.c index c9404b59..2cd5221 100644 --- a/sound/soc/qcom/qdsp6/q6apm-dai.c +++ b/sound/soc/qcom/qdsp6/q6apm-dai.c
@@ -24,8 +24,8 @@ #define PLAYBACK_MIN_PERIOD_SIZE 128 #define CAPTURE_MIN_NUM_PERIODS 2 #define CAPTURE_MAX_NUM_PERIODS 8 -#define CAPTURE_MAX_PERIOD_SIZE 4096 -#define CAPTURE_MIN_PERIOD_SIZE 320 +#define CAPTURE_MAX_PERIOD_SIZE 65536 +#define CAPTURE_MIN_PERIOD_SIZE 6144 #define BUFFER_BYTES_MAX (PLAYBACK_MAX_NUM_PERIODS * PLAYBACK_MAX_PERIOD_SIZE) #define BUFFER_BYTES_MIN (PLAYBACK_MIN_NUM_PERIODS * PLAYBACK_MIN_PERIOD_SIZE) #define COMPR_PLAYBACK_MAX_FRAGMENT_SIZE (128 * 1024) @@ -64,12 +64,12 @@ struct q6apm_dai_rtd { phys_addr_t phys; unsigned int pcm_size; unsigned int pcm_count; - unsigned int pos; /* Buffer position */ unsigned int periods; unsigned int bytes_sent; unsigned int bytes_received; unsigned int copied_total; uint16_t bits_per_sample; + snd_pcm_uframes_t queue_ptr; bool next_track; enum stream_state state; struct q6apm_graph *graph; @@ -123,25 +123,16 @@ static void event_handler(uint32_t opcode, uint32_t token, void *payload, void * { struct q6apm_dai_rtd *prtd = priv; struct snd_pcm_substream *substream = prtd->substream; - unsigned long flags; switch (opcode) { case APM_CLIENT_EVENT_CMD_EOS_DONE: prtd->state = Q6APM_STREAM_STOPPED; break; case APM_CLIENT_EVENT_DATA_WRITE_DONE: - spin_lock_irqsave(&prtd->lock, flags); - prtd->pos += prtd->pcm_count; - spin_unlock_irqrestore(&prtd->lock, flags); snd_pcm_period_elapsed(substream); - if (prtd->state == Q6APM_STREAM_RUNNING) - q6apm_write_async(prtd->graph, prtd->pcm_count, 0, 0, 0); break; case APM_CLIENT_EVENT_DATA_READ_DONE: - spin_lock_irqsave(&prtd->lock, flags); - prtd->pos += prtd->pcm_count; - spin_unlock_irqrestore(&prtd->lock, flags); snd_pcm_period_elapsed(substream); if (prtd->state == Q6APM_STREAM_RUNNING) q6apm_read(prtd->graph); @@ -248,7 +239,6 @@ static int q6apm_dai_prepare(struct snd_soc_component *component, } prtd->pcm_count = snd_pcm_lib_period_bytes(substream); - prtd->pos = 0; /* rate and channels are sent to audio driver */ ret = q6apm_graph_media_format_shmem(prtd->graph, &cfg); if (ret < 0) { @@ -294,6 +284,27 @@ static int q6apm_dai_prepare(struct snd_soc_component *component, return 0; } +static int q6apm_dai_ack(struct snd_soc_component *component, struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct q6apm_dai_rtd *prtd = runtime->private_data; + int i, ret = 0, avail_periods; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + avail_periods = (runtime->control->appl_ptr - prtd->queue_ptr)/runtime->period_size; + for (i = 0; i < avail_periods; i++) { + ret = q6apm_write_async(prtd->graph, prtd->pcm_count, 0, 0, NO_TIMESTAMP); + if (ret < 0) { + dev_err(component->dev, "Error queuing playback buffer %d\n", ret); + return ret; + } + prtd->queue_ptr += runtime->period_size; + } + } + + return ret; +} + static int q6apm_dai_trigger(struct snd_soc_component *component, struct snd_pcm_substream *substream, int cmd) { @@ -305,9 +316,6 @@ static int q6apm_dai_trigger(struct snd_soc_component *component, case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - /* start writing buffers for playback only as we already queued capture buffers */ - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - ret = q6apm_write_async(prtd->graph, prtd->pcm_count, 0, 0, 0); break; case SNDRV_PCM_TRIGGER_STOP: /* TODO support be handled via SoftPause Module */ @@ -377,13 +385,14 @@ static int q6apm_dai_open(struct snd_soc_component *component, } } - ret = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 32); + /* setup 10ms latency to accommodate DSP restrictions */ + ret = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 480); if (ret < 0) { dev_err(dev, "constraint for period bytes step ret = %d\n", ret); goto err; } - ret = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 32); + ret = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 480); if (ret < 0) { dev_err(dev, "constraint for buffer bytes step ret = %d\n", ret); goto err; @@ -428,16 +437,12 @@ static snd_pcm_uframes_t q6apm_dai_pointer(struct snd_soc_component *component, struct snd_pcm_runtime *runtime = substream->runtime; struct q6apm_dai_rtd *prtd = runtime->private_data; snd_pcm_uframes_t ptr; - unsigned long flags; - spin_lock_irqsave(&prtd->lock, flags); - if (prtd->pos == prtd->pcm_size) - prtd->pos = 0; + ptr = q6apm_get_hw_pointer(prtd->graph, substream->stream) * runtime->period_size; + if (ptr) + return ptr - 1; - ptr = bytes_to_frames(runtime, prtd->pos); - spin_unlock_irqrestore(&prtd->lock, flags); - - return ptr; + return 0; } static int q6apm_dai_hw_params(struct snd_soc_component *component, @@ -652,8 +657,6 @@ static int q6apm_dai_compr_set_params(struct snd_soc_component *component, prtd->pcm_size = runtime->fragments * runtime->fragment_size; prtd->bits_per_sample = 16; - prtd->pos = 0; - if (prtd->next_track != true) { memcpy(&prtd->codec, codec, sizeof(*codec)); @@ -836,6 +839,7 @@ static const struct snd_soc_component_driver q6apm_fe_dai_component = { .hw_params = q6apm_dai_hw_params, .pointer = q6apm_dai_pointer, .trigger = q6apm_dai_trigger, + .ack = q6apm_dai_ack, .compress_ops = &q6apm_dai_compress_ops, .use_dai_pcm_id = true, };
diff --git a/sound/soc/qcom/qdsp6/q6apm.c b/sound/soc/qcom/qdsp6/q6apm.c index 11e252a..b4ffa0f 100644 --- a/sound/soc/qcom/qdsp6/q6apm.c +++ b/sound/soc/qcom/qdsp6/q6apm.c
@@ -494,6 +494,19 @@ int q6apm_read(struct q6apm_graph *graph) } EXPORT_SYMBOL_GPL(q6apm_read); +int q6apm_get_hw_pointer(struct q6apm_graph *graph, int dir) +{ + struct audioreach_graph_data *data; + + if (dir == SNDRV_PCM_STREAM_PLAYBACK) + data = &graph->rx_data; + else + data = &graph->tx_data; + + return (int)atomic_read(&data->hw_ptr); +} +EXPORT_SYMBOL_GPL(q6apm_get_hw_pointer); + static int graph_callback(struct gpr_resp_pkt *data, void *priv, int op) { struct data_cmd_rsp_rd_sh_mem_ep_data_buffer_done_v2 *rd_done; @@ -520,7 +533,8 @@ static int graph_callback(struct gpr_resp_pkt *data, void *priv, int op) done = data->payload; phys = graph->rx_data.buf[token].phys; mutex_unlock(&graph->lock); - + /* token numbering starts at 0 */ + atomic_set(&graph->rx_data.hw_ptr, token + 1); if (lower_32_bits(phys) == done->buf_addr_lsw && upper_32_bits(phys) == done->buf_addr_msw) { graph->result.opcode = hdr->opcode; @@ -553,6 +567,8 @@ static int graph_callback(struct gpr_resp_pkt *data, void *priv, int op) rd_done = data->payload; phys = graph->tx_data.buf[hdr->token].phys; mutex_unlock(&graph->lock); + /* token numbering starts at 0 */ + atomic_set(&graph->tx_data.hw_ptr, hdr->token + 1); if (upper_32_bits(phys) == rd_done->buf_addr_msw && lower_32_bits(phys) == rd_done->buf_addr_lsw) {
diff --git a/sound/soc/qcom/qdsp6/q6apm.h b/sound/soc/qcom/qdsp6/q6apm.h index c248c8d..7ce08b4 100644 --- a/sound/soc/qcom/qdsp6/q6apm.h +++ b/sound/soc/qcom/qdsp6/q6apm.h
@@ -2,6 +2,7 @@ #ifndef __Q6APM_H__ #define __Q6APM_H__ #include <linux/types.h> +#include <linux/atomic.h> #include <linux/slab.h> #include <linux/wait.h> #include <linux/kernel.h> @@ -77,6 +78,7 @@ struct audioreach_graph_data { uint32_t num_periods; uint32_t dsp_buf; uint32_t mem_map_handle; + atomic_t hw_ptr; }; struct audioreach_graph { @@ -150,4 +152,5 @@ int q6apm_enable_compress_module(struct device *dev, struct q6apm_graph *graph, int q6apm_remove_initial_silence(struct device *dev, struct q6apm_graph *graph, uint32_t samples); int q6apm_remove_trailing_silence(struct device *dev, struct q6apm_graph *graph, uint32_t samples); int q6apm_set_real_module_id(struct device *dev, struct q6apm_graph *graph, uint32_t codec_id); +int q6apm_get_hw_pointer(struct q6apm_graph *graph, int dir); #endif /* __APM_GRAPH_ */
diff --git a/sound/soc/qcom/qdsp6/q6asm-dai.c b/sound/soc/qcom/qdsp6/q6asm-dai.c index 045100c9..a400c9a 100644 --- a/sound/soc/qcom/qdsp6/q6asm-dai.c +++ b/sound/soc/qcom/qdsp6/q6asm-dai.c
@@ -892,9 +892,7 @@ static int q6asm_dai_compr_set_params(struct snd_soc_component *component, if (ret < 0) { dev_err(dev, "q6asm_open_write failed\n"); - q6asm_audio_client_free(prtd->audio_client); - prtd->audio_client = NULL; - return ret; + goto open_err; } } @@ -903,7 +901,7 @@ static int q6asm_dai_compr_set_params(struct snd_soc_component *component, prtd->session_id, dir); if (ret) { dev_err(dev, "Stream reg failed ret:%d\n", ret); - return ret; + goto q6_err; } ret = __q6asm_dai_compr_set_codec_params(component, stream, @@ -911,7 +909,7 @@ static int q6asm_dai_compr_set_params(struct snd_soc_component *component, prtd->stream_id); if (ret) { dev_err(dev, "codec param setup failed ret:%d\n", ret); - return ret; + goto q6_err; } ret = q6asm_map_memory_regions(dir, prtd->audio_client, prtd->phys, @@ -920,12 +918,21 @@ static int q6asm_dai_compr_set_params(struct snd_soc_component *component, if (ret < 0) { dev_err(dev, "Buffer Mapping failed ret:%d\n", ret); - return -ENOMEM; + ret = -ENOMEM; + goto q6_err; } prtd->state = Q6ASM_STREAM_RUNNING; return 0; + +q6_err: + q6asm_cmd(prtd->audio_client, prtd->stream_id, CMD_CLOSE); + +open_err: + q6asm_audio_client_free(prtd->audio_client); + prtd->audio_client = NULL; + return ret; } static int q6asm_dai_compr_set_metadata(struct snd_soc_component *component,
diff --git a/sound/soc/sof/intel/Kconfig b/sound/soc/sof/intel/Kconfig index fae3598..dc1d21d 100644 --- a/sound/soc/sof/intel/Kconfig +++ b/sound/soc/sof/intel/Kconfig
@@ -345,6 +345,7 @@ config SND_SOF_SOF_HDA_SDW_BPT tristate + select SND_HDA_EXT_CORE help This option is not user-selectable but automagically handled by 'select' statements at a higher level.
diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c index ccf8eef..f64e8a6 100644 --- a/sound/soc/sof/intel/hda-dsp.c +++ b/sound/soc/sof/intel/hda-dsp.c
@@ -991,6 +991,10 @@ int hda_dsp_runtime_suspend(struct snd_sof_dev *sdev) if (!sdev->dspless_mode_selected) { /* cancel any attempt for DSP D0I3 */ cancel_delayed_work_sync(&hda->d0i3_work); + + /* Cancel the microphone privacy work if mic privacy is active */ + if (hda->mic_privacy.active) + cancel_work_sync(&hda->mic_privacy.work); } /* stop hda controller and power dsp off */ @@ -1017,6 +1021,10 @@ int hda_dsp_suspend(struct snd_sof_dev *sdev, u32 target_state) if (!sdev->dspless_mode_selected) { /* cancel any attempt for DSP D0I3 */ cancel_delayed_work_sync(&hda->d0i3_work); + + /* Cancel the microphone privacy work if mic privacy is active */ + if (hda->mic_privacy.active) + cancel_work_sync(&hda->mic_privacy.work); } if (target_state == SOF_DSP_PM_D0) {
diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 6b1ada5..b34e5fdf 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c
@@ -968,6 +968,10 @@ void hda_dsp_remove(struct snd_sof_dev *sdev) if (sdev->dspless_mode_selected) goto skip_disable_dsp; + /* Cancel the microphone privacy work if mic privacy is active */ + if (hda->mic_privacy.active) + cancel_work_sync(&hda->mic_privacy.work); + /* no need to check for error as the DSP will be disabled anyway */ if (chip && chip->power_down_dsp) chip->power_down_dsp(sdev);
diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index 7615462..108cad0 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h
@@ -487,6 +487,11 @@ enum sof_hda_D0_substate { SOF_HDA_DSP_PM_D0I3, /* low power D0 substate */ }; +struct sof_ace3_mic_privacy { + bool active; + struct work_struct work; +}; + /* represents DSP HDA controller frontend - i.e. host facing control */ struct sof_intel_hda_dev { bool imrboot_supported; @@ -542,6 +547,9 @@ struct sof_intel_hda_dev { /* Intel NHLT information */ struct nhlt_acpi_table *nhlt; + /* work queue for mic privacy state change notification sending */ + struct sof_ace3_mic_privacy mic_privacy; + /* * Pointing to the IPC message if immediate sending was not possible * because the downlink communication channel was BUSY at the time.
diff --git a/sound/soc/sof/intel/ptl.c b/sound/soc/sof/intel/ptl.c index 8fa4bdc..aa0b772 100644 --- a/sound/soc/sof/intel/ptl.c +++ b/sound/soc/sof/intel/ptl.c
@@ -27,22 +27,44 @@ static bool sof_ptl_check_mic_privacy_irq(struct snd_sof_dev *sdev, bool alt, return hdac_bus_eml_is_mic_privacy_changed(sof_to_bus(sdev), alt, elid); } +static void sof_ptl_mic_privacy_work(struct work_struct *work) +{ + struct sof_intel_hda_dev *hdev = container_of(work, + struct sof_intel_hda_dev, + mic_privacy.work); + struct hdac_bus *bus = &hdev->hbus.core; + struct snd_sof_dev *sdev = dev_get_drvdata(bus->dev); + bool state; + + /* + * The microphone privacy state is only available via Soundwire shim + * in PTL + * The work is only scheduled on change. + */ + state = hdac_bus_eml_get_mic_privacy_state(bus, 1, + AZX_REG_ML_LEPTR_ID_SDW); + sof_ipc4_mic_privacy_state_change(sdev, state); +} + static void sof_ptl_process_mic_privacy(struct snd_sof_dev *sdev, bool alt, int elid) { - bool state; + struct sof_intel_hda_dev *hdev = sdev->pdata->hw_pdata; if (!alt || elid != AZX_REG_ML_LEPTR_ID_SDW) return; - state = hdac_bus_eml_get_mic_privacy_state(sof_to_bus(sdev), alt, elid); - - sof_ipc4_mic_privacy_state_change(sdev, state); + /* + * Schedule the work to read the microphone privacy state and send IPC + * message about the new state to the firmware + */ + schedule_work(&hdev->mic_privacy.work); } static void sof_ptl_set_mic_privacy(struct snd_sof_dev *sdev, struct sof_ipc4_intel_mic_privacy_cap *caps) { + struct sof_intel_hda_dev *hdev = sdev->pdata->hw_pdata; u32 micpvcp; if (!caps || !caps->capabilities_length) @@ -58,6 +80,9 @@ static void sof_ptl_set_mic_privacy(struct snd_sof_dev *sdev, hdac_bus_eml_set_mic_privacy_mask(sof_to_bus(sdev), true, AZX_REG_ML_LEPTR_ID_SDW, PTL_MICPVCP_GET_SDW_MASK(micpvcp)); + + INIT_WORK(&hdev->mic_privacy.work, sof_ptl_mic_privacy_work); + hdev->mic_privacy.active = true; } int sof_ptl_set_ops(struct snd_sof_dev *sdev, struct snd_sof_dsp_ops *dsp_ops)
diff --git a/sound/soc/ti/ams-delta.c b/sound/soc/ti/ams-delta.c index 8a44236..9b8cb80 100644 --- a/sound/soc/ti/ams-delta.c +++ b/sound/soc/ti/ams-delta.c
@@ -303,7 +303,7 @@ static void cx81801_close(struct tty_struct *tty) struct snd_soc_component *component = tty->disc_data; struct snd_soc_dapm_context *dapm; - del_timer_sync(&cx81801_timer); + timer_delete_sync(&cx81801_timer); /* Prevent the hook switch from further changing the DAPM pins */ INIT_LIST_HEAD(&ams_delta_hook_switch.pins);
diff --git a/sound/usb/midi.c b/sound/usb/midi.c index 826ac87..dcdd7e9 100644 --- a/sound/usb/midi.c +++ b/sound/usb/midi.c
@@ -1553,7 +1553,7 @@ void snd_usbmidi_disconnect(struct list_head *p) spin_unlock_irq(&umidi->disc_lock); up_write(&umidi->disc_rwsem); - del_timer_sync(&umidi->error_timer); + timer_delete_sync(&umidi->error_timer); for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) { struct snd_usb_midi_endpoint *ep = &umidi->endpoints[i];
diff --git a/sound/virtio/virtio_pcm.c b/sound/virtio/virtio_pcm.c index 967e4c4..2f7c5e7 100644 --- a/sound/virtio/virtio_pcm.c +++ b/sound/virtio/virtio_pcm.c
@@ -339,6 +339,21 @@ int virtsnd_pcm_parse_cfg(struct virtio_snd *snd) if (!snd->substreams) return -ENOMEM; + /* + * Initialize critical substream fields early in case we hit an + * error path and end up trying to clean up uninitialized structures + * elsewhere. + */ + for (i = 0; i < snd->nsubstreams; ++i) { + struct virtio_pcm_substream *vss = &snd->substreams[i]; + + vss->snd = snd; + vss->sid = i; + INIT_WORK(&vss->elapsed_period, virtsnd_pcm_period_elapsed); + init_waitqueue_head(&vss->msg_empty); + spin_lock_init(&vss->lock); + } + info = kcalloc(snd->nsubstreams, sizeof(*info), GFP_KERNEL); if (!info) return -ENOMEM; @@ -352,12 +367,6 @@ int virtsnd_pcm_parse_cfg(struct virtio_snd *snd) struct virtio_pcm_substream *vss = &snd->substreams[i]; struct virtio_pcm *vpcm; - vss->snd = snd; - vss->sid = i; - INIT_WORK(&vss->elapsed_period, virtsnd_pcm_period_elapsed); - init_waitqueue_head(&vss->msg_empty); - spin_lock_init(&vss->lock); - rc = virtsnd_pcm_build_hw(vss, &info[i]); if (rc) goto on_exit;
diff --git a/tools/include/uapi/linux/types.h b/tools/include/uapi/linux/types.h index 91fa51a..85aa327 100644 --- a/tools/include/uapi/linux/types.h +++ b/tools/include/uapi/linux/types.h
@@ -4,6 +4,8 @@ #include <asm-generic/int-ll64.h> +#ifndef __ASSEMBLER__ + /* copied from linux:include/uapi/linux/types.h */ #define __bitwise typedef __u16 __bitwise __le16; @@ -20,4 +22,5 @@ typedef __u32 __bitwise __wsum; #define __aligned_be64 __be64 __attribute__((aligned(8))) #define __aligned_le64 __le64 __attribute__((aligned(8))) +#endif /* __ASSEMBLER__ */ #endif /* _UAPI_LINUX_TYPES_H */
diff --git a/tools/objtool/Documentation/objtool.txt b/tools/objtool/Documentation/objtool.txt index 28ac57b..9e97fc2 100644 --- a/tools/objtool/Documentation/objtool.txt +++ b/tools/objtool/Documentation/objtool.txt
@@ -34,7 +34,7 @@ - Return thunk annotation -- annotates all return thunk sites so kernel can patch them inline, depending on enabled mitigations -- Return thunk training valiation -- validate that all entry paths +- Return thunk untraining validation -- validate that all entry paths untrain a "safe return" before the first return (or call) - Non-instrumentation validation -- validates non-instrumentable @@ -281,8 +281,8 @@ If the error is for an asm file, and func() is indeed a callable function, add proper frame pointer logic using the FRAME_BEGIN and FRAME_END macros. Otherwise, if it's not a callable function, remove - its ELF function annotation by changing ENDPROC to END, and instead - use the manual unwind hint macros in asm/unwind_hints.h. + its ELF function annotation by using SYM_CODE_{START,END} and use the + manual unwind hint macros in asm/unwind_hints.h. If it's a GCC-compiled .c file, the error may be because the function uses an inline asm() statement which has a "call" instruction. An @@ -352,7 +352,7 @@ This is a kernel entry/exit instruction like sysenter or iret. Such instructions aren't allowed in a callable function, and are most likely part of the kernel entry code. Such code should probably be - placed in a SYM_FUNC_CODE block with unwind hints. + placed in a SYM_CODE_{START,END} block with unwind hints. 6. file.o: warning: objtool: func()+0x26: sibling call from callable instruction with modified stack frame @@ -381,7 +381,7 @@ Another possibility is that the code has some asm or inline asm which does some unusual things to the stack or the frame pointer. In such - cases it's probably appropriate to use SYM_FUNC_CODE with unwind + cases it's probably appropriate to use SYM_CODE_{START,END} with unwind hints.
diff --git a/tools/objtool/arch/loongarch/decode.c b/tools/objtool/arch/loongarch/decode.c index 02e4905..b6fdc68 100644 --- a/tools/objtool/arch/loongarch/decode.c +++ b/tools/objtool/arch/loongarch/decode.c
@@ -63,7 +63,7 @@ static bool is_loongarch(const struct elf *elf) if (elf->ehdr.e_machine == EM_LOONGARCH) return true; - WARN("unexpected ELF machine type %d", elf->ehdr.e_machine); + ERROR("unexpected ELF machine type %d", elf->ehdr.e_machine); return false; } @@ -327,8 +327,10 @@ const char *arch_nop_insn(int len) { static u32 nop; - if (len != LOONGARCH_INSN_SIZE) - WARN("invalid NOP size: %d\n", len); + if (len != LOONGARCH_INSN_SIZE) { + ERROR("invalid NOP size: %d\n", len); + return NULL; + } nop = LOONGARCH_INSN_NOP; @@ -339,8 +341,10 @@ const char *arch_ret_insn(int len) { static u32 ret; - if (len != LOONGARCH_INSN_SIZE) - WARN("invalid RET size: %d\n", len); + if (len != LOONGARCH_INSN_SIZE) { + ERROR("invalid RET size: %d\n", len); + return NULL; + } emit_jirl((union loongarch_instruction *)&ret, LOONGARCH_GPR_RA, LOONGARCH_GPR_ZERO, 0);
diff --git a/tools/objtool/arch/loongarch/orc.c b/tools/objtool/arch/loongarch/orc.c index 873536d..b58c5ff 100644 --- a/tools/objtool/arch/loongarch/orc.c +++ b/tools/objtool/arch/loongarch/orc.c
@@ -41,7 +41,7 @@ int init_orc_entry(struct orc_entry *orc, struct cfi_state *cfi, struct instruct orc->type = ORC_TYPE_REGS_PARTIAL; break; default: - WARN_INSN(insn, "unknown unwind hint type %d", cfi->type); + ERROR_INSN(insn, "unknown unwind hint type %d", cfi->type); return -1; } @@ -55,7 +55,7 @@ int init_orc_entry(struct orc_entry *orc, struct cfi_state *cfi, struct instruct orc->sp_reg = ORC_REG_FP; break; default: - WARN_INSN(insn, "unknown CFA base reg %d", cfi->cfa.base); + ERROR_INSN(insn, "unknown CFA base reg %d", cfi->cfa.base); return -1; } @@ -72,7 +72,7 @@ int init_orc_entry(struct orc_entry *orc, struct cfi_state *cfi, struct instruct orc->fp_reg = ORC_REG_FP; break; default: - WARN_INSN(insn, "unknown FP base reg %d", fp->base); + ERROR_INSN(insn, "unknown FP base reg %d", fp->base); return -1; } @@ -89,7 +89,7 @@ int init_orc_entry(struct orc_entry *orc, struct cfi_state *cfi, struct instruct orc->ra_reg = ORC_REG_FP; break; default: - WARN_INSN(insn, "unknown RA base reg %d", ra->base); + ERROR_INSN(insn, "unknown RA base reg %d", ra->base); return -1; }
diff --git a/tools/objtool/arch/x86/decode.c b/tools/objtool/arch/x86/decode.c index 7567c89..33d861c 100644 --- a/tools/objtool/arch/x86/decode.c +++ b/tools/objtool/arch/x86/decode.c
@@ -36,7 +36,7 @@ static int is_x86_64(const struct elf *elf) case EM_386: return 0; default: - WARN("unexpected ELF machine type %d", elf->ehdr.e_machine); + ERROR("unexpected ELF machine type %d", elf->ehdr.e_machine); return -1; } } @@ -173,7 +173,7 @@ int arch_decode_instruction(struct objtool_file *file, const struct section *sec ret = insn_decode(&ins, sec->data->d_buf + offset, maxlen, x86_64 ? INSN_MODE_64 : INSN_MODE_32); if (ret < 0) { - WARN("can't decode instruction at %s:0x%lx", sec->name, offset); + ERROR("can't decode instruction at %s:0x%lx", sec->name, offset); return -1; } @@ -321,7 +321,7 @@ int arch_decode_instruction(struct objtool_file *file, const struct section *sec break; default: - /* WARN ? */ + /* ERROR ? */ break; } @@ -561,8 +561,7 @@ int arch_decode_instruction(struct objtool_file *file, const struct section *sec if (ins.prefixes.nbytes == 1 && ins.prefixes.bytes[0] == 0xf2) { /* ENQCMD cannot be used in the kernel. */ - WARN("ENQCMD instruction at %s:%lx", sec->name, - offset); + WARN("ENQCMD instruction at %s:%lx", sec->name, offset); } } else if (op2 == 0xa0 || op2 == 0xa8) { @@ -646,7 +645,7 @@ int arch_decode_instruction(struct objtool_file *file, const struct section *sec if (disp->sym->type == STT_SECTION) func = find_symbol_by_offset(disp->sym->sec, reloc_addend(disp)); if (!func) { - WARN("no func for pv_ops[]"); + ERROR("no func for pv_ops[]"); return -1; } @@ -776,7 +775,7 @@ const char *arch_nop_insn(int len) }; if (len < 1 || len > 5) { - WARN("invalid NOP size: %d\n", len); + ERROR("invalid NOP size: %d\n", len); return NULL; } @@ -796,7 +795,7 @@ const char *arch_ret_insn(int len) }; if (len < 1 || len > 5) { - WARN("invalid RET size: %d\n", len); + ERROR("invalid RET size: %d\n", len); return NULL; }
diff --git a/tools/objtool/arch/x86/orc.c b/tools/objtool/arch/x86/orc.c index b6cd943..7176b9e 100644 --- a/tools/objtool/arch/x86/orc.c +++ b/tools/objtool/arch/x86/orc.c
@@ -40,7 +40,7 @@ int init_orc_entry(struct orc_entry *orc, struct cfi_state *cfi, struct instruct orc->type = ORC_TYPE_REGS_PARTIAL; break; default: - WARN_INSN(insn, "unknown unwind hint type %d", cfi->type); + ERROR_INSN(insn, "unknown unwind hint type %d", cfi->type); return -1; } @@ -72,7 +72,7 @@ int init_orc_entry(struct orc_entry *orc, struct cfi_state *cfi, struct instruct orc->sp_reg = ORC_REG_DX; break; default: - WARN_INSN(insn, "unknown CFA base reg %d", cfi->cfa.base); + ERROR_INSN(insn, "unknown CFA base reg %d", cfi->cfa.base); return -1; } @@ -87,7 +87,7 @@ int init_orc_entry(struct orc_entry *orc, struct cfi_state *cfi, struct instruct orc->bp_reg = ORC_REG_BP; break; default: - WARN_INSN(insn, "unknown BP base reg %d", bp->base); + ERROR_INSN(insn, "unknown BP base reg %d", bp->base); return -1; }
diff --git a/tools/objtool/arch/x86/special.c b/tools/objtool/arch/x86/special.c index 9c1c9df..403e587 100644 --- a/tools/objtool/arch/x86/special.c +++ b/tools/objtool/arch/x86/special.c
@@ -3,11 +3,9 @@ #include <objtool/special.h> #include <objtool/builtin.h> +#include <objtool/warn.h> -#define X86_FEATURE_POPCNT (4 * 32 + 23) -#define X86_FEATURE_SMAP (9 * 32 + 20) - -void arch_handle_alternative(unsigned short feature, struct special_alt *alt) +void arch_handle_alternative(struct special_alt *alt) { static struct special_alt *group, *prev; @@ -31,34 +29,6 @@ void arch_handle_alternative(unsigned short feature, struct special_alt *alt) } else group = alt; prev = alt; - - switch (feature) { - case X86_FEATURE_SMAP: - /* - * If UACCESS validation is enabled; force that alternative; - * otherwise force it the other way. - * - * What we want to avoid is having both the original and the - * alternative code flow at the same time, in that case we can - * find paths that see the STAC but take the NOP instead of - * CLAC and the other way around. - */ - if (opts.uaccess) - alt->skip_orig = true; - else - alt->skip_alt = true; - break; - case X86_FEATURE_POPCNT: - /* - * It has been requested that we don't validate the !POPCNT - * feature path which is a "very very small percentage of - * machines". - */ - alt->skip_orig = true; - break; - default: - break; - } } bool arch_support_alt_relocation(struct special_alt *special_alt, @@ -156,8 +126,10 @@ struct reloc *arch_find_switch_table(struct objtool_file *file, * indicates a rare GCC quirk/bug which can leave dead * code behind. */ - if (reloc_type(text_reloc) == R_X86_64_PC32) + if (reloc_type(text_reloc) == R_X86_64_PC32) { + WARN_INSN(insn, "ignoring unreachables due to jump table quirk"); file->ignore_unreachables = true; + } *table_size = 0; return rodata_reloc;
diff --git a/tools/objtool/builtin-check.c b/tools/objtool/builtin-check.c index 5f761f4..8023984 100644 --- a/tools/objtool/builtin-check.c +++ b/tools/objtool/builtin-check.c
@@ -8,18 +8,18 @@ #include <stdlib.h> #include <fcntl.h> #include <unistd.h> +#include <errno.h> #include <sys/stat.h> #include <sys/sendfile.h> #include <objtool/builtin.h> #include <objtool/objtool.h> +#include <objtool/warn.h> -#define ERROR(format, ...) \ - fprintf(stderr, \ - "error: objtool: " format "\n", \ - ##__VA_ARGS__) +#define ORIG_SUFFIX ".orig" +int orig_argc; +static char **orig_argv; const char *objname; - struct opts opts; static const char * const check_usage[] = { @@ -194,30 +194,30 @@ static int copy_file(const char *src, const char *dst) src_fd = open(src, O_RDONLY); if (src_fd == -1) { - ERROR("can't open '%s' for reading", src); + ERROR("can't open %s for reading: %s", src, strerror(errno)); return 1; } dst_fd = open(dst, O_WRONLY | O_CREAT | O_TRUNC, 0400); if (dst_fd == -1) { - ERROR("can't open '%s' for writing", dst); + ERROR("can't open %s for writing: %s", dst, strerror(errno)); return 1; } if (fstat(src_fd, &stat) == -1) { - perror("fstat"); + ERROR_GLIBC("fstat"); return 1; } if (fchmod(dst_fd, stat.st_mode) == -1) { - perror("fchmod"); + ERROR_GLIBC("fchmod"); return 1; } for (to_copy = stat.st_size; to_copy > 0; to_copy -= copied) { copied = sendfile(dst_fd, src_fd, &offset, to_copy); if (copied == -1) { - perror("sendfile"); + ERROR_GLIBC("sendfile"); return 1; } } @@ -227,39 +227,73 @@ static int copy_file(const char *src, const char *dst) return 0; } -static char **save_argv(int argc, const char **argv) +static void save_argv(int argc, const char **argv) { - char **orig_argv; - orig_argv = calloc(argc, sizeof(char *)); if (!orig_argv) { - perror("calloc"); - return NULL; + ERROR_GLIBC("calloc"); + exit(1); } for (int i = 0; i < argc; i++) { orig_argv[i] = strdup(argv[i]); if (!orig_argv[i]) { - perror("strdup"); - return NULL; + ERROR_GLIBC("strdup(%s)", argv[i]); + exit(1); } }; - - return orig_argv; } -#define ORIG_SUFFIX ".orig" +void print_args(void) +{ + char *backup = NULL; + + if (opts.output || opts.dryrun) + goto print; + + /* + * Make a backup before kbuild deletes the file so the error + * can be recreated without recompiling or relinking. + */ + backup = malloc(strlen(objname) + strlen(ORIG_SUFFIX) + 1); + if (!backup) { + ERROR_GLIBC("malloc"); + goto print; + } + + strcpy(backup, objname); + strcat(backup, ORIG_SUFFIX); + if (copy_file(objname, backup)) { + backup = NULL; + goto print; + } + +print: + /* + * Print the cmdline args to make it easier to recreate. If '--output' + * wasn't used, add it to the printed args with the backup as input. + */ + fprintf(stderr, "%s", orig_argv[0]); + + for (int i = 1; i < orig_argc; i++) { + char *arg = orig_argv[i]; + + if (backup && !strcmp(arg, objname)) + fprintf(stderr, " %s -o %s", backup, objname); + else + fprintf(stderr, " %s", arg); + } + + fprintf(stderr, "\n"); +} int objtool_run(int argc, const char **argv) { struct objtool_file *file; - char *backup = NULL; - char **orig_argv; int ret = 0; - orig_argv = save_argv(argc, argv); - if (!orig_argv) - return 1; + orig_argc = argc; + save_argv(argc, argv); cmd_parse_options(argc, argv, check_usage); @@ -282,59 +316,19 @@ int objtool_run(int argc, const char **argv) file = objtool_open_read(objname); if (!file) - goto err; + return 1; if (!opts.link && has_multiple_files(file->elf)) { ERROR("Linked object requires --link"); - goto err; + return 1; } ret = check(file); if (ret) - goto err; + return ret; if (!opts.dryrun && file->elf->changed && elf_write(file->elf)) - goto err; + return 1; return 0; - -err: - if (opts.dryrun) - goto err_msg; - - if (opts.output) { - unlink(opts.output); - goto err_msg; - } - - /* - * Make a backup before kbuild deletes the file so the error - * can be recreated without recompiling or relinking. - */ - backup = malloc(strlen(objname) + strlen(ORIG_SUFFIX) + 1); - if (!backup) { - perror("malloc"); - return 1; - } - - strcpy(backup, objname); - strcat(backup, ORIG_SUFFIX); - if (copy_file(objname, backup)) - return 1; - -err_msg: - fprintf(stderr, "%s", orig_argv[0]); - - for (int i = 1; i < argc; i++) { - char *arg = orig_argv[i]; - - if (backup && !strcmp(arg, objname)) - fprintf(stderr, " %s -o %s", backup, objname); - else - fprintf(stderr, " %s", arg); - } - - fprintf(stderr, "\n"); - - return 1; }
diff --git a/tools/objtool/check.c b/tools/objtool/check.c index ca3435a..4a1f6c3 100644 --- a/tools/objtool/check.c +++ b/tools/objtool/check.c
@@ -25,7 +25,6 @@ struct alternative { struct alternative *next; struct instruction *insn; - bool skip_orig; }; static unsigned long nr_cfi, nr_cfi_reused, nr_cfi_cache; @@ -341,12 +340,7 @@ static void init_insn_state(struct objtool_file *file, struct insn_state *state, memset(state, 0, sizeof(*state)); init_cfi_state(&state->cfi); - /* - * We need the full vmlinux for noinstr validation, otherwise we can - * not correctly determine insn_call_dest(insn)->sec (external symbols - * do not have a section). - */ - if (opts.link && opts.noinstr && sec) + if (opts.noinstr && sec) state->noinstr = sec->noinstr; } @@ -354,7 +348,7 @@ static struct cfi_state *cfi_alloc(void) { struct cfi_state *cfi = calloc(1, sizeof(struct cfi_state)); if (!cfi) { - WARN("calloc failed"); + ERROR_GLIBC("calloc"); exit(1); } nr_cfi++; @@ -410,7 +404,7 @@ static void *cfi_hash_alloc(unsigned long size) PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0); if (cfi_hash == (void *)-1L) { - WARN("mmap fail cfi_hash"); + ERROR_GLIBC("mmap fail cfi_hash"); cfi_hash = NULL; } else if (opts.stats) { printf("cfi_bits: %d\n", cfi_bits); @@ -466,7 +460,7 @@ static int decode_instructions(struct objtool_file *file) if (!insns || idx == INSN_CHUNK_MAX) { insns = calloc(sizeof(*insn), INSN_CHUNK_SIZE); if (!insns) { - WARN("malloc failed"); + ERROR_GLIBC("calloc"); return -1; } idx = 0; @@ -501,8 +495,6 @@ static int decode_instructions(struct objtool_file *file) nr_insns++; } -// printf("%s: last chunk used: %d\n", sec->name, (int)idx); - sec_for_each_sym(sec, func) { if (func->type != STT_NOTYPE && func->type != STT_FUNC) continue; @@ -511,8 +503,7 @@ static int decode_instructions(struct objtool_file *file) /* Heuristic: likely an "end" symbol */ if (func->type == STT_NOTYPE) continue; - WARN("%s(): STT_FUNC at end of section", - func->name); + ERROR("%s(): STT_FUNC at end of section", func->name); return -1; } @@ -520,8 +511,7 @@ static int decode_instructions(struct objtool_file *file) continue; if (!find_insn(file, sec, func->offset)) { - WARN("%s(): can't find starting instruction", - func->name); + ERROR("%s(): can't find starting instruction", func->name); return -1; } @@ -568,14 +558,20 @@ static int add_pv_ops(struct objtool_file *file, const char *symname) if (!reloc) break; + idx = (reloc_offset(reloc) - sym->offset) / sizeof(unsigned long); + func = reloc->sym; if (func->type == STT_SECTION) func = find_symbol_by_offset(reloc->sym->sec, reloc_addend(reloc)); + if (!func) { + ERROR_FUNC(reloc->sym->sec, reloc_addend(reloc), + "can't find func at %s[%d]", symname, idx); + return -1; + } - idx = (reloc_offset(reloc) - sym->offset) / sizeof(unsigned long); - - objtool_pv_add(file, idx, func); + if (objtool_pv_add(file, idx, func)) + return -1; off = reloc_offset(reloc) + 1; if (off > end) @@ -599,7 +595,7 @@ static int init_pv_ops(struct objtool_file *file) }; const char *pv_ops; struct symbol *sym; - int idx, nr; + int idx, nr, ret; if (!opts.noinstr) return 0; @@ -612,14 +608,19 @@ static int init_pv_ops(struct objtool_file *file) nr = sym->len / sizeof(unsigned long); file->pv_ops = calloc(sizeof(struct pv_state), nr); - if (!file->pv_ops) + if (!file->pv_ops) { + ERROR_GLIBC("calloc"); return -1; + } for (idx = 0; idx < nr; idx++) INIT_LIST_HEAD(&file->pv_ops[idx].targets); - for (idx = 0; (pv_ops = pv_ops_tables[idx]); idx++) - add_pv_ops(file, pv_ops); + for (idx = 0; (pv_ops = pv_ops_tables[idx]); idx++) { + ret = add_pv_ops(file, pv_ops); + if (ret) + return ret; + } return 0; } @@ -667,13 +668,12 @@ static int create_static_call_sections(struct objtool_file *file) /* find key symbol */ key_name = strdup(insn_call_dest(insn)->name); if (!key_name) { - perror("strdup"); + ERROR_GLIBC("strdup"); return -1; } if (strncmp(key_name, STATIC_CALL_TRAMP_PREFIX_STR, STATIC_CALL_TRAMP_PREFIX_LEN)) { - WARN("static_call: trampoline name malformed: %s", key_name); - free(key_name); + ERROR("static_call: trampoline name malformed: %s", key_name); return -1; } tmp = key_name + STATIC_CALL_TRAMP_PREFIX_LEN - STATIC_CALL_KEY_PREFIX_LEN; @@ -682,8 +682,7 @@ static int create_static_call_sections(struct objtool_file *file) key_sym = find_symbol_by_name(file->elf, tmp); if (!key_sym) { if (!opts.module) { - WARN("static_call: can't find static_call_key symbol: %s", tmp); - free(key_name); + ERROR("static_call: can't find static_call_key symbol: %s", tmp); return -1; } @@ -698,7 +697,6 @@ static int create_static_call_sections(struct objtool_file *file) */ key_sym = insn_call_dest(insn); } - free(key_name); /* populate reloc for 'key' */ if (!elf_init_reloc_data_sym(file->elf, sec, @@ -829,8 +827,11 @@ static int create_ibt_endbr_seal_sections(struct objtool_file *file) if (opts.module && sym && sym->type == STT_FUNC && insn->offset == sym->offset && (!strcmp(sym->name, "init_module") || - !strcmp(sym->name, "cleanup_module"))) - WARN("%s(): not an indirect call target", sym->name); + !strcmp(sym->name, "cleanup_module"))) { + ERROR("%s(): Magic init_module() function name is deprecated, use module_init(fn) instead", + sym->name); + return -1; + } if (!elf_init_reloc_text_sym(file->elf, sec, idx * sizeof(int), idx, @@ -979,16 +980,15 @@ static int create_direct_call_sections(struct objtool_file *file) /* * Warnings shouldn't be reported for ignored functions. */ -static void add_ignores(struct objtool_file *file) +static int add_ignores(struct objtool_file *file) { - struct instruction *insn; struct section *rsec; struct symbol *func; struct reloc *reloc; rsec = find_section_by_name(file->elf, ".rela.discard.func_stack_frame_non_standard"); if (!rsec) - return; + return 0; for_each_reloc(rsec, reloc) { switch (reloc->sym->type) { @@ -1003,14 +1003,17 @@ static void add_ignores(struct objtool_file *file) break; default: - WARN("unexpected relocation symbol type in %s: %d", - rsec->name, reloc->sym->type); - continue; + ERROR("unexpected relocation symbol type in %s: %d", + rsec->name, reloc->sym->type); + return -1; } - func_for_each_insn(file, func, insn) - insn->ignore = true; + func->ignore = true; + if (func->cfunc) + func->cfunc->ignore = true; } + + return 0; } /* @@ -1188,12 +1191,15 @@ static const char *uaccess_safe_builtin[] = { "__ubsan_handle_load_invalid_value", /* STACKLEAK */ "stackleak_track_stack", + /* TRACE_BRANCH_PROFILING */ + "ftrace_likely_update", + /* STACKPROTECTOR */ + "__stack_chk_fail", /* misc */ "csum_partial_copy_generic", "copy_mc_fragile", "copy_mc_fragile_handle_tail", "copy_mc_enhanced_fast_string", - "ftrace_likely_update", /* CONFIG_TRACE_BRANCH_PROFILING */ "rep_stos_alternative", "rep_movs_alternative", "__copy_user_nocache", @@ -1275,7 +1281,7 @@ static void remove_insn_ops(struct instruction *insn) insn->stack_ops = NULL; } -static void annotate_call_site(struct objtool_file *file, +static int annotate_call_site(struct objtool_file *file, struct instruction *insn, bool sibling) { struct reloc *reloc = insn_reloc(file, insn); @@ -1286,12 +1292,12 @@ static void annotate_call_site(struct objtool_file *file, if (sym->static_call_tramp) { list_add_tail(&insn->call_node, &file->static_call_list); - return; + return 0; } if (sym->retpoline_thunk) { list_add_tail(&insn->call_node, &file->retpoline_call_list); - return; + return 0; } /* @@ -1303,10 +1309,12 @@ static void annotate_call_site(struct objtool_file *file, if (reloc) set_reloc_type(file->elf, reloc, R_NONE); - elf_write_insn(file->elf, insn->sec, - insn->offset, insn->len, - sibling ? arch_ret_insn(insn->len) - : arch_nop_insn(insn->len)); + if (elf_write_insn(file->elf, insn->sec, + insn->offset, insn->len, + sibling ? arch_ret_insn(insn->len) + : arch_nop_insn(insn->len))) { + return -1; + } insn->type = sibling ? INSN_RETURN : INSN_NOP; @@ -1320,7 +1328,7 @@ static void annotate_call_site(struct objtool_file *file, insn->retpoline_safe = true; } - return; + return 0; } if (opts.mcount && sym->fentry) { @@ -1330,15 +1338,17 @@ static void annotate_call_site(struct objtool_file *file, if (reloc) set_reloc_type(file->elf, reloc, R_NONE); - elf_write_insn(file->elf, insn->sec, - insn->offset, insn->len, - arch_nop_insn(insn->len)); + if (elf_write_insn(file->elf, insn->sec, + insn->offset, insn->len, + arch_nop_insn(insn->len))) { + return -1; + } insn->type = INSN_NOP; } list_add_tail(&insn->call_node, &file->mcount_loc_list); - return; + return 0; } if (insn->type == INSN_CALL && !insn->sec->init && @@ -1347,14 +1357,16 @@ static void annotate_call_site(struct objtool_file *file, if (!sibling && dead_end_function(file, sym)) insn->dead_end = true; + + return 0; } -static void add_call_dest(struct objtool_file *file, struct instruction *insn, +static int add_call_dest(struct objtool_file *file, struct instruction *insn, struct symbol *dest, bool sibling) { insn->_call_dest = dest; if (!dest) - return; + return 0; /* * Whatever stack impact regular CALLs have, should be undone @@ -1365,10 +1377,10 @@ static void add_call_dest(struct objtool_file *file, struct instruction *insn, */ remove_insn_ops(insn); - annotate_call_site(file, insn, sibling); + return annotate_call_site(file, insn, sibling); } -static void add_retpoline_call(struct objtool_file *file, struct instruction *insn) +static int add_retpoline_call(struct objtool_file *file, struct instruction *insn) { /* * Retpoline calls/jumps are really dynamic calls/jumps in disguise, @@ -1385,7 +1397,7 @@ static void add_retpoline_call(struct objtool_file *file, struct instruction *in insn->type = INSN_JUMP_DYNAMIC_CONDITIONAL; break; default: - return; + return 0; } insn->retpoline_safe = true; @@ -1399,7 +1411,7 @@ static void add_retpoline_call(struct objtool_file *file, struct instruction *in */ remove_insn_ops(insn); - annotate_call_site(file, insn, false); + return annotate_call_site(file, insn, false); } static void add_return_call(struct objtool_file *file, struct instruction *insn, bool add) @@ -1468,8 +1480,11 @@ static int add_jump_destinations(struct objtool_file *file) struct reloc *reloc; struct section *dest_sec; unsigned long dest_off; + int ret; for_each_insn(file, insn) { + struct symbol *func = insn_func(insn); + if (insn->jump_dest) { /* * handle_group_alt() may have previously set @@ -1488,17 +1503,21 @@ static int add_jump_destinations(struct objtool_file *file) dest_sec = reloc->sym->sec; dest_off = arch_dest_reloc_offset(reloc_addend(reloc)); } else if (reloc->sym->retpoline_thunk) { - add_retpoline_call(file, insn); + ret = add_retpoline_call(file, insn); + if (ret) + return ret; continue; } else if (reloc->sym->return_thunk) { add_return_call(file, insn, true); continue; - } else if (insn_func(insn)) { + } else if (func) { /* * External sibling call or internal sibling call with * STT_FUNC reloc. */ - add_call_dest(file, insn, reloc->sym, true); + ret = add_call_dest(file, insn, reloc->sym, true); + if (ret) + return ret; continue; } else if (reloc->sym->sec->idx) { dest_sec = reloc->sym->sec; @@ -1526,8 +1545,17 @@ static int add_jump_destinations(struct objtool_file *file) continue; } - WARN_INSN(insn, "can't find jump dest instruction at %s+0x%lx", - dest_sec->name, dest_off); + /* + * GCOV/KCOV dead code can jump to the end of the + * function/section. + */ + if (file->ignore_unreachables && func && + dest_sec == insn->sec && + dest_off == func->offset + func->len) + continue; + + ERROR_INSN(insn, "can't find jump dest instruction at %s+0x%lx", + dest_sec->name, dest_off); return -1; } @@ -1538,7 +1566,9 @@ static int add_jump_destinations(struct objtool_file *file) */ if (jump_dest->sym && jump_dest->offset == jump_dest->sym->offset) { if (jump_dest->sym->retpoline_thunk) { - add_retpoline_call(file, insn); + ret = add_retpoline_call(file, insn); + if (ret) + return ret; continue; } if (jump_dest->sym->return_thunk) { @@ -1550,8 +1580,7 @@ static int add_jump_destinations(struct objtool_file *file) /* * Cross-function jump. */ - if (insn_func(insn) && insn_func(jump_dest) && - insn_func(insn) != insn_func(jump_dest)) { + if (func && insn_func(jump_dest) && func != insn_func(jump_dest)) { /* * For GCC 8+, create parent/child links for any cold @@ -1568,10 +1597,10 @@ static int add_jump_destinations(struct objtool_file *file) * case where the parent function's only reference to a * subfunction is through a jump table. */ - if (!strstr(insn_func(insn)->name, ".cold") && + if (!strstr(func->name, ".cold") && strstr(insn_func(jump_dest)->name, ".cold")) { - insn_func(insn)->cfunc = insn_func(jump_dest); - insn_func(jump_dest)->pfunc = insn_func(insn); + func->cfunc = insn_func(jump_dest); + insn_func(jump_dest)->pfunc = func; } } @@ -1580,7 +1609,9 @@ static int add_jump_destinations(struct objtool_file *file) * Internal sibling call without reloc or with * STT_SECTION reloc. */ - add_call_dest(file, insn, insn_func(jump_dest), true); + ret = add_call_dest(file, insn, insn_func(jump_dest), true); + if (ret) + return ret; continue; } @@ -1610,8 +1641,10 @@ static int add_call_destinations(struct objtool_file *file) unsigned long dest_off; struct symbol *dest; struct reloc *reloc; + int ret; for_each_insn(file, insn) { + struct symbol *func = insn_func(insn); if (insn->type != INSN_CALL) continue; @@ -1620,18 +1653,20 @@ static int add_call_destinations(struct objtool_file *file) dest_off = arch_jump_destination(insn); dest = find_call_destination(insn->sec, dest_off); - add_call_dest(file, insn, dest, false); + ret = add_call_dest(file, insn, dest, false); + if (ret) + return ret; - if (insn->ignore) + if (func && func->ignore) continue; if (!insn_call_dest(insn)) { - WARN_INSN(insn, "unannotated intra-function call"); + ERROR_INSN(insn, "unannotated intra-function call"); return -1; } - if (insn_func(insn) && insn_call_dest(insn)->type != STT_FUNC) { - WARN_INSN(insn, "unsupported call to non-function"); + if (func && insn_call_dest(insn)->type != STT_FUNC) { + ERROR_INSN(insn, "unsupported call to non-function"); return -1; } @@ -1639,18 +1674,25 @@ static int add_call_destinations(struct objtool_file *file) dest_off = arch_dest_reloc_offset(reloc_addend(reloc)); dest = find_call_destination(reloc->sym->sec, dest_off); if (!dest) { - WARN_INSN(insn, "can't find call dest symbol at %s+0x%lx", - reloc->sym->sec->name, dest_off); + ERROR_INSN(insn, "can't find call dest symbol at %s+0x%lx", + reloc->sym->sec->name, dest_off); return -1; } - add_call_dest(file, insn, dest, false); + ret = add_call_dest(file, insn, dest, false); + if (ret) + return ret; } else if (reloc->sym->retpoline_thunk) { - add_retpoline_call(file, insn); + ret = add_retpoline_call(file, insn); + if (ret) + return ret; - } else - add_call_dest(file, insn, reloc->sym, false); + } else { + ret = add_call_dest(file, insn, reloc->sym, false); + if (ret) + return ret; + } } return 0; @@ -1673,15 +1715,15 @@ static int handle_group_alt(struct objtool_file *file, if (!orig_alt_group) { struct instruction *last_orig_insn = NULL; - orig_alt_group = malloc(sizeof(*orig_alt_group)); + orig_alt_group = calloc(1, sizeof(*orig_alt_group)); if (!orig_alt_group) { - WARN("malloc failed"); + ERROR_GLIBC("calloc"); return -1; } orig_alt_group->cfi = calloc(special_alt->orig_len, sizeof(struct cfi_state *)); if (!orig_alt_group->cfi) { - WARN("calloc failed"); + ERROR_GLIBC("calloc"); return -1; } @@ -1697,21 +1739,22 @@ static int handle_group_alt(struct objtool_file *file, orig_alt_group->first_insn = orig_insn; orig_alt_group->last_insn = last_orig_insn; orig_alt_group->nop = NULL; + orig_alt_group->ignore = orig_insn->ignore_alts; } else { if (orig_alt_group->last_insn->offset + orig_alt_group->last_insn->len - orig_alt_group->first_insn->offset != special_alt->orig_len) { - WARN_INSN(orig_insn, "weirdly overlapping alternative! %ld != %d", - orig_alt_group->last_insn->offset + - orig_alt_group->last_insn->len - - orig_alt_group->first_insn->offset, - special_alt->orig_len); + ERROR_INSN(orig_insn, "weirdly overlapping alternative! %ld != %d", + orig_alt_group->last_insn->offset + + orig_alt_group->last_insn->len - + orig_alt_group->first_insn->offset, + special_alt->orig_len); return -1; } } - new_alt_group = malloc(sizeof(*new_alt_group)); + new_alt_group = calloc(1, sizeof(*new_alt_group)); if (!new_alt_group) { - WARN("malloc failed"); + ERROR_GLIBC("calloc"); return -1; } @@ -1723,9 +1766,9 @@ static int handle_group_alt(struct objtool_file *file, * instruction affects the stack, the instruction after it (the * nop) will propagate the new state to the shared CFI array. */ - nop = malloc(sizeof(*nop)); + nop = calloc(1, sizeof(*nop)); if (!nop) { - WARN("malloc failed"); + ERROR_GLIBC("calloc"); return -1; } memset(nop, 0, sizeof(*nop)); @@ -1736,7 +1779,6 @@ static int handle_group_alt(struct objtool_file *file, nop->type = INSN_NOP; nop->sym = orig_insn->sym; nop->alt_group = new_alt_group; - nop->ignore = orig_insn->ignore_alts; } if (!special_alt->new_len) { @@ -1753,7 +1795,6 @@ static int handle_group_alt(struct objtool_file *file, last_new_insn = insn; - insn->ignore = orig_insn->ignore_alts; insn->sym = orig_insn->sym; insn->alt_group = new_alt_group; @@ -1769,7 +1810,7 @@ static int handle_group_alt(struct objtool_file *file, if (alt_reloc && arch_pc_relative_reloc(alt_reloc) && !arch_support_alt_relocation(special_alt, insn, alt_reloc)) { - WARN_INSN(insn, "unsupported relocation in alternatives section"); + ERROR_INSN(insn, "unsupported relocation in alternatives section"); return -1; } @@ -1783,15 +1824,15 @@ static int handle_group_alt(struct objtool_file *file, if (dest_off == special_alt->new_off + special_alt->new_len) { insn->jump_dest = next_insn_same_sec(file, orig_alt_group->last_insn); if (!insn->jump_dest) { - WARN_INSN(insn, "can't find alternative jump destination"); + ERROR_INSN(insn, "can't find alternative jump destination"); return -1; } } } if (!last_new_insn) { - WARN_FUNC("can't find last new alternative instruction", - special_alt->new_sec, special_alt->new_off); + ERROR_FUNC(special_alt->new_sec, special_alt->new_off, + "can't find last new alternative instruction"); return -1; } @@ -1800,6 +1841,7 @@ static int handle_group_alt(struct objtool_file *file, new_alt_group->first_insn = *new_insn; new_alt_group->last_insn = last_new_insn; new_alt_group->nop = nop; + new_alt_group->ignore = (*new_insn)->ignore_alts; new_alt_group->cfi = orig_alt_group->cfi; return 0; } @@ -1817,7 +1859,7 @@ static int handle_jump_alt(struct objtool_file *file, if (orig_insn->type != INSN_JUMP_UNCONDITIONAL && orig_insn->type != INSN_NOP) { - WARN_INSN(orig_insn, "unsupported instruction at jump label"); + ERROR_INSN(orig_insn, "unsupported instruction at jump label"); return -1; } @@ -1826,9 +1868,13 @@ static int handle_jump_alt(struct objtool_file *file, if (reloc) set_reloc_type(file->elf, reloc, R_NONE); - elf_write_insn(file->elf, orig_insn->sec, - orig_insn->offset, orig_insn->len, - arch_nop_insn(orig_insn->len)); + + if (elf_write_insn(file->elf, orig_insn->sec, + orig_insn->offset, orig_insn->len, + arch_nop_insn(orig_insn->len))) { + return -1; + } + orig_insn->type = INSN_NOP; } @@ -1864,19 +1910,17 @@ static int add_special_section_alts(struct objtool_file *file) struct alternative *alt; int ret; - ret = special_get_alts(file->elf, &special_alts); - if (ret) - return ret; + if (special_get_alts(file->elf, &special_alts)) + return -1; list_for_each_entry_safe(special_alt, tmp, &special_alts, list) { orig_insn = find_insn(file, special_alt->orig_sec, special_alt->orig_off); if (!orig_insn) { - WARN_FUNC("special: can't find orig instruction", - special_alt->orig_sec, special_alt->orig_off); - ret = -1; - goto out; + ERROR_FUNC(special_alt->orig_sec, special_alt->orig_off, + "special: can't find orig instruction"); + return -1; } new_insn = NULL; @@ -1884,41 +1928,37 @@ static int add_special_section_alts(struct objtool_file *file) new_insn = find_insn(file, special_alt->new_sec, special_alt->new_off); if (!new_insn) { - WARN_FUNC("special: can't find new instruction", - special_alt->new_sec, - special_alt->new_off); - ret = -1; - goto out; + ERROR_FUNC(special_alt->new_sec, special_alt->new_off, + "special: can't find new instruction"); + return -1; } } if (special_alt->group) { if (!special_alt->orig_len) { - WARN_INSN(orig_insn, "empty alternative entry"); + ERROR_INSN(orig_insn, "empty alternative entry"); continue; } ret = handle_group_alt(file, special_alt, orig_insn, &new_insn); if (ret) - goto out; + return ret; + } else if (special_alt->jump_or_nop) { ret = handle_jump_alt(file, special_alt, orig_insn, &new_insn); if (ret) - goto out; + return ret; } - alt = malloc(sizeof(*alt)); + alt = calloc(1, sizeof(*alt)); if (!alt) { - WARN("malloc failed"); - ret = -1; - goto out; + ERROR_GLIBC("calloc"); + return -1; } alt->insn = new_insn; - alt->skip_orig = special_alt->skip_orig; - orig_insn->ignore_alts |= special_alt->skip_alt; alt->next = orig_insn->alts; orig_insn->alts = alt; @@ -1932,8 +1972,7 @@ static int add_special_section_alts(struct objtool_file *file) printf("long:\t%ld\t%ld\n", file->jl_nop_long, file->jl_long); } -out: - return ret; + return 0; } __weak unsigned long arch_jump_table_sym_offset(struct reloc *reloc, struct reloc *table) @@ -1941,8 +1980,7 @@ __weak unsigned long arch_jump_table_sym_offset(struct reloc *reloc, struct relo return reloc->sym->offset + reloc_addend(reloc); } -static int add_jump_table(struct objtool_file *file, struct instruction *insn, - struct reloc *next_table) +static int add_jump_table(struct objtool_file *file, struct instruction *insn) { unsigned long table_size = insn_jump_table_size(insn); struct symbol *pfunc = insn_func(insn)->pfunc; @@ -1962,7 +2000,7 @@ static int add_jump_table(struct objtool_file *file, struct instruction *insn, /* Check for the end of the table: */ if (table_size && reloc_offset(reloc) - reloc_offset(table) >= table_size) break; - if (reloc != table && reloc == next_table) + if (reloc != table && is_jump_table(reloc)) break; /* Make sure the table entries are consecutive: */ @@ -1991,9 +2029,9 @@ static int add_jump_table(struct objtool_file *file, struct instruction *insn, if (!insn_func(dest_insn) || insn_func(dest_insn)->pfunc != pfunc) break; - alt = malloc(sizeof(*alt)); + alt = calloc(1, sizeof(*alt)); if (!alt) { - WARN("malloc failed"); + ERROR_GLIBC("calloc"); return -1; } @@ -2005,7 +2043,7 @@ static int add_jump_table(struct objtool_file *file, struct instruction *insn, } if (!prev_offset) { - WARN_INSN(insn, "can't find switch jump table"); + ERROR_INSN(insn, "can't find switch jump table"); return -1; } @@ -2041,7 +2079,7 @@ static void find_jump_table(struct objtool_file *file, struct symbol *func, insn->jump_dest && (insn->jump_dest->offset <= insn->offset || insn->jump_dest->offset > orig_insn->offset)) - break; + break; table_reloc = arch_find_switch_table(file, insn, &table_size); if (!table_reloc) @@ -2053,8 +2091,10 @@ static void find_jump_table(struct objtool_file *file, struct symbol *func, if (!dest_insn || !insn_func(dest_insn) || insn_func(dest_insn)->pfunc != func) continue; + set_jump_table(table_reloc); orig_insn->_jump_table = table_reloc; orig_insn->_jump_table_size = table_size; + break; } } @@ -2096,31 +2136,19 @@ static void mark_func_jump_tables(struct objtool_file *file, static int add_func_jump_tables(struct objtool_file *file, struct symbol *func) { - struct instruction *insn, *insn_t1 = NULL, *insn_t2; - int ret = 0; + struct instruction *insn; + int ret; func_for_each_insn(file, func, insn) { if (!insn_jump_table(insn)) continue; - if (!insn_t1) { - insn_t1 = insn; - continue; - } - - insn_t2 = insn; - - ret = add_jump_table(file, insn_t1, insn_jump_table(insn_t2)); + ret = add_jump_table(file, insn); if (ret) return ret; - - insn_t1 = insn_t2; } - if (insn_t1) - ret = add_jump_table(file, insn_t1, NULL); - - return ret; + return 0; } /* @@ -2173,12 +2201,12 @@ static int read_unwind_hints(struct objtool_file *file) return 0; if (!sec->rsec) { - WARN("missing .rela.discard.unwind_hints section"); + ERROR("missing .rela.discard.unwind_hints section"); return -1; } if (sec->sh.sh_size % sizeof(struct unwind_hint)) { - WARN("struct unwind_hint size mismatch"); + ERROR("struct unwind_hint size mismatch"); return -1; } @@ -2189,7 +2217,7 @@ static int read_unwind_hints(struct objtool_file *file) reloc = find_reloc_by_dest(file->elf, sec, i * sizeof(*hint)); if (!reloc) { - WARN("can't find reloc for unwind_hints[%d]", i); + ERROR("can't find reloc for unwind_hints[%d]", i); return -1; } @@ -2198,13 +2226,13 @@ static int read_unwind_hints(struct objtool_file *file) } else if (reloc->sym->local_label) { offset = reloc->sym->offset; } else { - WARN("unexpected relocation symbol type in %s", sec->rsec->name); + ERROR("unexpected relocation symbol type in %s", sec->rsec->name); return -1; } insn = find_insn(file, reloc->sym->sec, offset); if (!insn) { - WARN("can't find insn for unwind_hints[%d]", i); + ERROR("can't find insn for unwind_hints[%d]", i); return -1; } @@ -2231,7 +2259,8 @@ static int read_unwind_hints(struct objtool_file *file) if (sym && sym->bind == STB_GLOBAL) { if (opts.ibt && insn->type != INSN_ENDBR && !insn->noendbr) { - WARN_INSN(insn, "UNWIND_HINT_IRET_REGS without ENDBR"); + ERROR_INSN(insn, "UNWIND_HINT_IRET_REGS without ENDBR"); + return -1; } } } @@ -2245,7 +2274,7 @@ static int read_unwind_hints(struct objtool_file *file) cfi = *(insn->cfi); if (arch_decode_hint_reg(hint->sp_reg, &cfi.cfa.base)) { - WARN_INSN(insn, "unsupported unwind_hint sp base reg %d", hint->sp_reg); + ERROR_INSN(insn, "unsupported unwind_hint sp base reg %d", hint->sp_reg); return -1; } @@ -2291,7 +2320,7 @@ static int read_annotate(struct objtool_file *file, insn = find_insn(file, reloc->sym->sec, offset); if (!insn) { - WARN("bad .discard.annotate_insn entry: %d of type %d", reloc_idx(reloc), type); + ERROR("bad .discard.annotate_insn entry: %d of type %d", reloc_idx(reloc), type); return -1; } @@ -2306,6 +2335,8 @@ static int read_annotate(struct objtool_file *file, static int __annotate_early(struct objtool_file *file, int type, struct instruction *insn) { switch (type) { + + /* Must be before add_special_section_alts() */ case ANNOTYPE_IGNORE_ALTS: insn->ignore_alts = true; break; @@ -2332,7 +2363,7 @@ static int __annotate_ifc(struct objtool_file *file, int type, struct instructio return 0; if (insn->type != INSN_CALL) { - WARN_INSN(insn, "intra_function_call not a direct call"); + ERROR_INSN(insn, "intra_function_call not a direct call"); return -1; } @@ -2346,8 +2377,8 @@ static int __annotate_ifc(struct objtool_file *file, int type, struct instructio dest_off = arch_jump_destination(insn); insn->jump_dest = find_insn(file, insn->sec, dest_off); if (!insn->jump_dest) { - WARN_INSN(insn, "can't find call dest at %s+0x%lx", - insn->sec->name, dest_off); + ERROR_INSN(insn, "can't find call dest at %s+0x%lx", + insn->sec->name, dest_off); return -1; } @@ -2366,7 +2397,7 @@ static int __annotate_late(struct objtool_file *file, int type, struct instructi insn->type != INSN_CALL_DYNAMIC && insn->type != INSN_RETURN && insn->type != INSN_NOP) { - WARN_INSN(insn, "retpoline_safe hint not an indirect jump/call/ret/nop"); + ERROR_INSN(insn, "retpoline_safe hint not an indirect jump/call/ret/nop"); return -1; } @@ -2398,8 +2429,8 @@ static int __annotate_late(struct objtool_file *file, int type, struct instructi break; default: - WARN_INSN(insn, "Unknown annotation type: %d", type); - break; + ERROR_INSN(insn, "Unknown annotation type: %d", type); + return -1; } return 0; @@ -2512,7 +2543,10 @@ static int decode_sections(struct objtool_file *file) if (ret) return ret; - add_ignores(file); + ret = add_ignores(file); + if (ret) + return ret; + add_uaccess_safe(file); ret = read_annotate(file, __annotate_early); @@ -2732,7 +2766,7 @@ static int update_cfi_state(struct instruction *insn, if (cfa->base == CFI_UNDEFINED) { if (insn_func(insn)) { WARN_INSN(insn, "undefined stack state"); - return -1; + return 1; } return 0; } @@ -3175,9 +3209,8 @@ static int propagate_alt_cfi(struct objtool_file *file, struct instruction *insn if (cficmp(alt_cfi[group_off], insn->cfi)) { struct alt_group *orig_group = insn->alt_group->orig_group ?: insn->alt_group; struct instruction *orig = orig_group->first_insn; - char *where = offstr(insn->sec, insn->offset); - WARN_INSN(orig, "stack layout conflict in alternatives: %s", where); - free(where); + WARN_INSN(orig, "stack layout conflict in alternatives: %s", + offstr(insn->sec, insn->offset)); return -1; } } @@ -3190,13 +3223,15 @@ static int handle_insn_ops(struct instruction *insn, struct insn_state *state) { struct stack_op *op; + int ret; for (op = insn->stack_ops; op; op = op->next) { - if (update_cfi_state(insn, next_insn, &state->cfi, op)) - return 1; + ret = update_cfi_state(insn, next_insn, &state->cfi, op); + if (ret) + return ret; - if (!insn->alt_group) + if (!opts.uaccess || !insn->alt_group) continue; if (op->dest.type == OP_DEST_PUSHF) { @@ -3238,36 +3273,41 @@ static bool insn_cfi_match(struct instruction *insn, struct cfi_state *cfi2) WARN_INSN(insn, "stack state mismatch: cfa1=%d%+d cfa2=%d%+d", cfi1->cfa.base, cfi1->cfa.offset, cfi2->cfa.base, cfi2->cfa.offset); + return false; - } else if (memcmp(&cfi1->regs, &cfi2->regs, sizeof(cfi1->regs))) { + } + + if (memcmp(&cfi1->regs, &cfi2->regs, sizeof(cfi1->regs))) { for (i = 0; i < CFI_NUM_REGS; i++) { - if (!memcmp(&cfi1->regs[i], &cfi2->regs[i], - sizeof(struct cfi_reg))) + + if (!memcmp(&cfi1->regs[i], &cfi2->regs[i], sizeof(struct cfi_reg))) continue; WARN_INSN(insn, "stack state mismatch: reg1[%d]=%d%+d reg2[%d]=%d%+d", i, cfi1->regs[i].base, cfi1->regs[i].offset, i, cfi2->regs[i].base, cfi2->regs[i].offset); - break; } + return false; + } - } else if (cfi1->type != cfi2->type) { + if (cfi1->type != cfi2->type) { WARN_INSN(insn, "stack state mismatch: type1=%d type2=%d", cfi1->type, cfi2->type); + return false; + } - } else if (cfi1->drap != cfi2->drap || + if (cfi1->drap != cfi2->drap || (cfi1->drap && cfi1->drap_reg != cfi2->drap_reg) || (cfi1->drap && cfi1->drap_offset != cfi2->drap_offset)) { WARN_INSN(insn, "stack state mismatch: drap1=%d(%d,%d) drap2=%d(%d,%d)", cfi1->drap, cfi1->drap_reg, cfi1->drap_offset, cfi2->drap, cfi2->drap_reg, cfi2->drap_offset); + return false; + } - } else - return true; - - return false; + return true; } static inline bool func_uaccess_safe(struct symbol *func) @@ -3480,6 +3520,9 @@ static int validate_branch(struct objtool_file *file, struct symbol *func, u8 visited; int ret; + if (func && func->ignore) + return 0; + sec = insn->sec; while (1) { @@ -3491,13 +3534,13 @@ static int validate_branch(struct objtool_file *file, struct symbol *func, !strncmp(func->name, "__pfx_", 6)) return 0; + if (file->ignore_unreachables) + return 0; + WARN("%s() falls through to next function %s()", func->name, insn_func(insn)->name); - return 1; - } + func->warned = 1; - if (func && insn->ignore) { - WARN_INSN(insn, "BUG: why am I validating an ignored function?"); return 1; } @@ -3572,24 +3615,19 @@ static int validate_branch(struct objtool_file *file, struct symbol *func, if (propagate_alt_cfi(file, insn)) return 1; - if (!insn->ignore_alts && insn->alts) { - bool skip_orig = false; - + if (insn->alts) { for (alt = insn->alts; alt; alt = alt->next) { - if (alt->skip_orig) - skip_orig = true; - ret = validate_branch(file, func, alt->insn, state); if (ret) { BT_INSN(insn, "(alt)"); return ret; } } - - if (skip_orig) - return 0; } + if (insn->alt_group && insn->alt_group->ignore) + return 0; + if (handle_insn_ops(insn, next_insn, &state)) return 1; @@ -3610,9 +3648,6 @@ static int validate_branch(struct objtool_file *file, struct symbol *func, return 1; } - if (insn->dead_end) - return 0; - break; case INSN_JUMP_CONDITIONAL: @@ -3660,6 +3695,9 @@ static int validate_branch(struct objtool_file *file, struct symbol *func, return 0; case INSN_STAC: + if (!opts.uaccess) + break; + if (state.uaccess) { WARN_INSN(insn, "recursive UACCESS enable"); return 1; @@ -3669,6 +3707,9 @@ static int validate_branch(struct objtool_file *file, struct symbol *func, break; case INSN_CLAC: + if (!opts.uaccess) + break; + if (!state.uaccess && func) { WARN_INSN(insn, "redundant UACCESS disable"); return 1; @@ -3710,7 +3751,12 @@ static int validate_branch(struct objtool_file *file, struct symbol *func, if (!next_insn) { if (state.cfi.cfa.base == CFI_UNDEFINED) return 0; - WARN("%s: unexpected end of section", sec->name); + if (file->ignore_unreachables) + return 0; + + WARN("%s%sunexpected end of section %s", + func ? func->name : "", func ? "(): " : "", + sec->name); return 1; } @@ -3725,7 +3771,7 @@ static int validate_unwind_hint(struct objtool_file *file, struct instruction *insn, struct insn_state *state) { - if (insn->hint && !insn->visited && !insn->ignore) { + if (insn->hint && !insn->visited) { int ret = validate_branch(file, insn_func(insn), insn, *state); if (ret) BT_INSN(insn, "<=== (hint)"); @@ -3776,23 +3822,15 @@ static int validate_unret(struct objtool_file *file, struct instruction *insn) insn->visited |= VISITED_UNRET; - if (!insn->ignore_alts && insn->alts) { + if (insn->alts) { struct alternative *alt; - bool skip_orig = false; - for (alt = insn->alts; alt; alt = alt->next) { - if (alt->skip_orig) - skip_orig = true; - ret = validate_unret(file, alt->insn); if (ret) { BT_INSN(insn, "(alt)"); return ret; } } - - if (skip_orig) - return 0; } switch (insn->type) { @@ -3808,7 +3846,7 @@ static int validate_unret(struct objtool_file *file, struct instruction *insn) if (!is_sibling_call(insn)) { if (!insn->jump_dest) { WARN_INSN(insn, "unresolved jump target after linking?!?"); - return -1; + return 1; } ret = validate_unret(file, insn->jump_dest); if (ret) { @@ -3830,7 +3868,7 @@ static int validate_unret(struct objtool_file *file, struct instruction *insn) if (!dest) { WARN("Unresolved function after linking!?: %s", insn_call_dest(insn)->name); - return -1; + return 1; } ret = validate_unret(file, dest); @@ -3859,7 +3897,7 @@ static int validate_unret(struct objtool_file *file, struct instruction *insn) if (!next) { WARN_INSN(insn, "teh end!"); - return -1; + return 1; } insn = next; } @@ -3874,18 +3912,13 @@ static int validate_unret(struct objtool_file *file, struct instruction *insn) static int validate_unrets(struct objtool_file *file) { struct instruction *insn; - int ret, warnings = 0; + int warnings = 0; for_each_insn(file, insn) { if (!insn->unret) continue; - ret = validate_unret(file, insn); - if (ret < 0) { - WARN_INSN(insn, "Failed UNRET validation"); - return ret; - } - warnings += ret; + warnings += validate_unret(file, insn); } return warnings; @@ -3911,13 +3944,13 @@ static int validate_retpoline(struct objtool_file *file) if (insn->type == INSN_RETURN) { if (opts.rethunk) { WARN_INSN(insn, "'naked' return found in MITIGATION_RETHUNK build"); - } else - continue; - } else { - WARN_INSN(insn, "indirect %s found in MITIGATION_RETPOLINE build", - insn->type == INSN_JUMP_DYNAMIC ? "jump" : "call"); + warnings++; + } + continue; } + WARN_INSN(insn, "indirect %s found in MITIGATION_RETPOLINE build", + insn->type == INSN_JUMP_DYNAMIC ? "jump" : "call"); warnings++; } @@ -3939,10 +3972,11 @@ static bool is_ubsan_insn(struct instruction *insn) static bool ignore_unreachable_insn(struct objtool_file *file, struct instruction *insn) { - int i; + struct symbol *func = insn_func(insn); struct instruction *prev_insn; + int i; - if (insn->ignore || insn->type == INSN_NOP || insn->type == INSN_TRAP) + if (insn->type == INSN_NOP || insn->type == INSN_TRAP || (func && func->ignore)) return true; /* @@ -3961,7 +3995,7 @@ static bool ignore_unreachable_insn(struct objtool_file *file, struct instructio * In this case we'll find a piece of code (whole function) that is not * covered by a !section symbol. Ignore them. */ - if (opts.link && !insn_func(insn)) { + if (opts.link && !func) { int size = find_symbol_hole_containing(insn->sec, insn->offset); unsigned long end = insn->offset + size; @@ -3987,19 +4021,17 @@ static bool ignore_unreachable_insn(struct objtool_file *file, struct instructio */ if (insn->jump_dest && insn_func(insn->jump_dest) && strstr(insn_func(insn->jump_dest)->name, ".cold")) { - struct instruction *dest = insn->jump_dest; - func_for_each_insn(file, insn_func(dest), dest) - dest->ignore = true; + insn_func(insn->jump_dest)->ignore = true; } } return false; } - if (!insn_func(insn)) + if (!func) return false; - if (insn_func(insn)->static_call_tramp) + if (func->static_call_tramp) return true; /* @@ -4011,7 +4043,7 @@ static bool ignore_unreachable_insn(struct objtool_file *file, struct instructio * It may also insert a UD2 after calling a __noreturn function. */ prev_insn = prev_insn_same_sec(file, insn); - if (prev_insn->dead_end && + if (prev_insn && prev_insn->dead_end && (insn->type == INSN_BUG || (insn->type == INSN_JUMP_UNCONDITIONAL && insn->jump_dest && insn->jump_dest->type == INSN_BUG))) @@ -4030,7 +4062,7 @@ static bool ignore_unreachable_insn(struct objtool_file *file, struct instructio if (insn->type == INSN_JUMP_UNCONDITIONAL) { if (insn->jump_dest && - insn_func(insn->jump_dest) == insn_func(insn)) { + insn_func(insn->jump_dest) == func) { insn = insn->jump_dest; continue; } @@ -4038,7 +4070,7 @@ static bool ignore_unreachable_insn(struct objtool_file *file, struct instructio break; } - if (insn->offset + insn->len >= insn_func(insn)->offset + insn_func(insn)->len) + if (insn->offset + insn->len >= func->offset + func->len) break; insn = next_insn_same_sec(file, insn); @@ -4130,10 +4162,11 @@ static int validate_symbol(struct objtool_file *file, struct section *sec, return 0; insn = find_insn(file, sec, sym->offset); - if (!insn || insn->ignore || insn->visited) + if (!insn || insn->visited) return 0; - state->uaccess = sym->uaccess_safe; + if (opts.uaccess) + state->uaccess = sym->uaccess_safe; ret = validate_branch(file, insn_func(insn), insn, *state); if (ret) @@ -4354,9 +4387,8 @@ static int validate_ibt_data_reloc(struct objtool_file *file, if (dest->noendbr) return 0; - WARN_FUNC("data relocation to !ENDBR: %s", - reloc->sec->base, reloc_offset(reloc), - offstr(dest->sec, dest->offset)); + WARN_FUNC(reloc->sec->base, reloc_offset(reloc), + "data relocation to !ENDBR: %s", offstr(dest->sec, dest->offset)); return 1; } @@ -4484,13 +4516,15 @@ static int validate_reachable_instructions(struct objtool_file *file) } /* 'funcs' is a space-separated list of function names */ -static int disas_funcs(const char *funcs) +static void disas_funcs(const char *funcs) { const char *objdump_str, *cross_compile; int size, ret; char *cmd; cross_compile = getenv("CROSS_COMPILE"); + if (!cross_compile) + cross_compile = ""; objdump_str = "%sobjdump -wdr %s | gawk -M -v _funcs='%s' '" "BEGIN { split(_funcs, funcs); }" @@ -4517,7 +4551,7 @@ static int disas_funcs(const char *funcs) size = snprintf(NULL, 0, objdump_str, cross_compile, objname, funcs) + 1; if (size <= 0) { WARN("objdump string size calculation failed"); - return -1; + return; } cmd = malloc(size); @@ -4527,24 +4561,30 @@ static int disas_funcs(const char *funcs) ret = system(cmd); if (ret) { WARN("disassembly failed: %d", ret); - return -1; + return; } - - return 0; } -static int disas_warned_funcs(struct objtool_file *file) +static void disas_warned_funcs(struct objtool_file *file) { struct symbol *sym; char *funcs = NULL, *tmp; for_each_sym(file, sym) { - if (sym->warnings) { + if (sym->warned) { if (!funcs) { funcs = malloc(strlen(sym->name) + 1); + if (!funcs) { + ERROR_GLIBC("malloc"); + return; + } strcpy(funcs, sym->name); } else { tmp = malloc(strlen(funcs) + strlen(sym->name) + 2); + if (!tmp) { + ERROR_GLIBC("malloc"); + return; + } sprintf(tmp, "%s %s", funcs, sym->name); free(funcs); funcs = tmp; @@ -4554,8 +4594,6 @@ static int disas_warned_funcs(struct objtool_file *file) if (funcs) disas_funcs(funcs); - - return 0; } struct insn_chunk { @@ -4588,7 +4626,7 @@ static void free_insns(struct objtool_file *file) int check(struct objtool_file *file) { - int ret, warnings = 0; + int ret = 0, warnings = 0; arch_initial_func_cfi_state(&initial_func_cfi); init_cfi_state(&init_cfi); @@ -4606,44 +4644,27 @@ int check(struct objtool_file *file) cfi_hash_add(&func_cfi); ret = decode_sections(file); - if (ret < 0) + if (ret) goto out; - warnings += ret; - if (!nr_insns) goto out; - if (opts.retpoline) { - ret = validate_retpoline(file); - if (ret < 0) - goto out; - warnings += ret; - } + if (opts.retpoline) + warnings += validate_retpoline(file); if (opts.stackval || opts.orc || opts.uaccess) { - ret = validate_functions(file); - if (ret < 0) - goto out; - warnings += ret; + int w = 0; - ret = validate_unwind_hints(file, NULL); - if (ret < 0) - goto out; - warnings += ret; + w += validate_functions(file); + w += validate_unwind_hints(file, NULL); + if (!w) + w += validate_reachable_instructions(file); - if (!warnings) { - ret = validate_reachable_instructions(file); - if (ret < 0) - goto out; - warnings += ret; - } + warnings += w; } else if (opts.noinstr) { - ret = validate_noinstr_sections(file); - if (ret < 0) - goto out; - warnings += ret; + warnings += validate_noinstr_sections(file); } if (opts.unret) { @@ -4651,94 +4672,71 @@ int check(struct objtool_file *file) * Must be after validate_branch() and friends, it plays * further games with insn->visited. */ - ret = validate_unrets(file); - if (ret < 0) - goto out; - warnings += ret; + warnings += validate_unrets(file); } - if (opts.ibt) { - ret = validate_ibt(file); - if (ret < 0) - goto out; - warnings += ret; - } + if (opts.ibt) + warnings += validate_ibt(file); - if (opts.sls) { - ret = validate_sls(file); - if (ret < 0) - goto out; - warnings += ret; - } + if (opts.sls) + warnings += validate_sls(file); if (opts.static_call) { ret = create_static_call_sections(file); - if (ret < 0) + if (ret) goto out; - warnings += ret; } if (opts.retpoline) { ret = create_retpoline_sites_sections(file); - if (ret < 0) + if (ret) goto out; - warnings += ret; } if (opts.cfi) { ret = create_cfi_sections(file); - if (ret < 0) + if (ret) goto out; - warnings += ret; } if (opts.rethunk) { ret = create_return_sites_sections(file); - if (ret < 0) + if (ret) goto out; - warnings += ret; if (opts.hack_skylake) { ret = create_direct_call_sections(file); - if (ret < 0) + if (ret) goto out; - warnings += ret; } } if (opts.mcount) { ret = create_mcount_loc_sections(file); - if (ret < 0) + if (ret) goto out; - warnings += ret; } if (opts.prefix) { ret = add_prefix_symbols(file); - if (ret < 0) + if (ret) goto out; - warnings += ret; } if (opts.ibt) { ret = create_ibt_endbr_seal_sections(file); - if (ret < 0) + if (ret) goto out; - warnings += ret; } if (opts.orc && nr_insns) { ret = orc_create(file); - if (ret < 0) + if (ret) goto out; - warnings += ret; } free_insns(file); - if (opts.verbose) - disas_warned_funcs(file); - if (opts.stats) { printf("nr_insns_visited: %ld\n", nr_insns_visited); printf("nr_cfi: %ld\n", nr_cfi); @@ -4747,19 +4745,18 @@ int check(struct objtool_file *file) } out: - /* - * CONFIG_OBJTOOL_WERROR upgrades all warnings (and errors) to actual - * errors. - * - * Note that even "fatal" type errors don't actually return an error - * without CONFIG_OBJTOOL_WERROR. That probably needs improved at some - * point. - */ - if (opts.werror && (ret || warnings)) { - if (warnings) + if (!ret && !warnings) + return 0; + + if (opts.werror && warnings) + ret = 1; + + if (opts.verbose) { + if (opts.werror && warnings) WARN("%d warning(s) upgraded to errors", warnings); - return 1; + print_args(); + disas_warned_funcs(file); } - return 0; + return ret; }
diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c index be4f4b6..727a3a4 100644 --- a/tools/objtool/elf.c +++ b/tools/objtool/elf.c
@@ -72,17 +72,17 @@ static inline void __elf_hash_del(struct elf_hash_node *node, obj; \ obj = elf_list_entry(obj->member.next, typeof(*(obj)), member)) -#define elf_alloc_hash(name, size) \ -({ \ - __elf_bits(name) = max(10, ilog2(size)); \ +#define elf_alloc_hash(name, size) \ +({ \ + __elf_bits(name) = max(10, ilog2(size)); \ __elf_table(name) = mmap(NULL, sizeof(struct elf_hash_node *) << __elf_bits(name), \ - PROT_READ|PROT_WRITE, \ - MAP_PRIVATE|MAP_ANON, -1, 0); \ - if (__elf_table(name) == (void *)-1L) { \ - WARN("mmap fail " #name); \ - __elf_table(name) = NULL; \ - } \ - __elf_table(name); \ + PROT_READ|PROT_WRITE, \ + MAP_PRIVATE|MAP_ANON, -1, 0); \ + if (__elf_table(name) == (void *)-1L) { \ + ERROR_GLIBC("mmap fail " #name); \ + __elf_table(name) = NULL; \ + } \ + __elf_table(name); \ }) static inline unsigned long __sym_start(struct symbol *s) @@ -316,12 +316,12 @@ static int read_sections(struct elf *elf) int i; if (elf_getshdrnum(elf->elf, §ions_nr)) { - WARN_ELF("elf_getshdrnum"); + ERROR_ELF("elf_getshdrnum"); return -1; } if (elf_getshdrstrndx(elf->elf, &shstrndx)) { - WARN_ELF("elf_getshdrstrndx"); + ERROR_ELF("elf_getshdrstrndx"); return -1; } @@ -331,7 +331,7 @@ static int read_sections(struct elf *elf) elf->section_data = calloc(sections_nr, sizeof(*sec)); if (!elf->section_data) { - perror("calloc"); + ERROR_GLIBC("calloc"); return -1; } for (i = 0; i < sections_nr; i++) { @@ -341,33 +341,32 @@ static int read_sections(struct elf *elf) s = elf_getscn(elf->elf, i); if (!s) { - WARN_ELF("elf_getscn"); + ERROR_ELF("elf_getscn"); return -1; } sec->idx = elf_ndxscn(s); if (!gelf_getshdr(s, &sec->sh)) { - WARN_ELF("gelf_getshdr"); + ERROR_ELF("gelf_getshdr"); return -1; } sec->name = elf_strptr(elf->elf, shstrndx, sec->sh.sh_name); if (!sec->name) { - WARN_ELF("elf_strptr"); + ERROR_ELF("elf_strptr"); return -1; } if (sec->sh.sh_size != 0 && !is_dwarf_section(sec)) { sec->data = elf_getdata(s, NULL); if (!sec->data) { - WARN_ELF("elf_getdata"); + ERROR_ELF("elf_getdata"); return -1; } if (sec->data->d_off != 0 || sec->data->d_size != sec->sh.sh_size) { - WARN("unexpected data attributes for %s", - sec->name); + ERROR("unexpected data attributes for %s", sec->name); return -1; } } @@ -387,7 +386,7 @@ static int read_sections(struct elf *elf) /* sanity check, one more call to elf_nextscn() should return NULL */ if (elf_nextscn(elf->elf, s)) { - WARN("section entry mismatch"); + ERROR("section entry mismatch"); return -1; } @@ -467,7 +466,7 @@ static int read_symbols(struct elf *elf) elf->symbol_data = calloc(symbols_nr, sizeof(*sym)); if (!elf->symbol_data) { - perror("calloc"); + ERROR_GLIBC("calloc"); return -1; } for (i = 0; i < symbols_nr; i++) { @@ -477,14 +476,14 @@ static int read_symbols(struct elf *elf) if (!gelf_getsymshndx(symtab->data, shndx_data, i, &sym->sym, &shndx)) { - WARN_ELF("gelf_getsymshndx"); + ERROR_ELF("gelf_getsymshndx"); goto err; } sym->name = elf_strptr(elf->elf, symtab->sh.sh_link, sym->sym.st_name); if (!sym->name) { - WARN_ELF("elf_strptr"); + ERROR_ELF("elf_strptr"); goto err; } @@ -496,8 +495,7 @@ static int read_symbols(struct elf *elf) sym->sec = find_section_by_index(elf, shndx); if (!sym->sec) { - WARN("couldn't find section for symbol %s", - sym->name); + ERROR("couldn't find section for symbol %s", sym->name); goto err; } if (GELF_ST_TYPE(sym->sym.st_info) == STT_SECTION) { @@ -536,8 +534,7 @@ static int read_symbols(struct elf *elf) pnamelen = coldstr - sym->name; pname = strndup(sym->name, pnamelen); if (!pname) { - WARN("%s(): failed to allocate memory", - sym->name); + ERROR("%s(): failed to allocate memory", sym->name); return -1; } @@ -545,8 +542,7 @@ static int read_symbols(struct elf *elf) free(pname); if (!pfunc) { - WARN("%s(): can't find parent function", - sym->name); + ERROR("%s(): can't find parent function", sym->name); return -1; } @@ -583,7 +579,7 @@ static int elf_update_sym_relocs(struct elf *elf, struct symbol *sym) { struct reloc *reloc; - for (reloc = sym->relocs; reloc; reloc = reloc->sym_next_reloc) + for (reloc = sym->relocs; reloc; reloc = sym_next_reloc(reloc)) set_reloc_sym(elf, reloc, reloc->sym->idx); return 0; @@ -613,14 +609,14 @@ static int elf_update_symbol(struct elf *elf, struct section *symtab, s = elf_getscn(elf->elf, symtab->idx); if (!s) { - WARN_ELF("elf_getscn"); + ERROR_ELF("elf_getscn"); return -1; } if (symtab_shndx) { t = elf_getscn(elf->elf, symtab_shndx->idx); if (!t) { - WARN_ELF("elf_getscn"); + ERROR_ELF("elf_getscn"); return -1; } } @@ -643,7 +639,7 @@ static int elf_update_symbol(struct elf *elf, struct section *symtab, if (idx) { /* we don't do holes in symbol tables */ - WARN("index out of range"); + ERROR("index out of range"); return -1; } @@ -654,7 +650,7 @@ static int elf_update_symbol(struct elf *elf, struct section *symtab, buf = calloc(num, entsize); if (!buf) { - WARN("malloc"); + ERROR_GLIBC("calloc"); return -1; } @@ -669,7 +665,7 @@ static int elf_update_symbol(struct elf *elf, struct section *symtab, if (t) { buf = calloc(num, sizeof(Elf32_Word)); if (!buf) { - WARN("malloc"); + ERROR_GLIBC("calloc"); return -1; } @@ -687,7 +683,7 @@ static int elf_update_symbol(struct elf *elf, struct section *symtab, /* empty blocks should not happen */ if (!symtab_data->d_size) { - WARN("zero size data"); + ERROR("zero size data"); return -1; } @@ -702,7 +698,7 @@ static int elf_update_symbol(struct elf *elf, struct section *symtab, /* something went side-ways */ if (idx < 0) { - WARN("negative index"); + ERROR("negative index"); return -1; } @@ -714,13 +710,13 @@ static int elf_update_symbol(struct elf *elf, struct section *symtab, } else { sym->sym.st_shndx = SHN_XINDEX; if (!shndx_data) { - WARN("no .symtab_shndx"); + ERROR("no .symtab_shndx"); return -1; } } if (!gelf_update_symshndx(symtab_data, shndx_data, idx, &sym->sym, shndx)) { - WARN_ELF("gelf_update_symshndx"); + ERROR_ELF("gelf_update_symshndx"); return -1; } @@ -738,7 +734,7 @@ __elf_create_symbol(struct elf *elf, struct symbol *sym) if (symtab) { symtab_shndx = find_section_by_name(elf, ".symtab_shndx"); } else { - WARN("no .symtab"); + ERROR("no .symtab"); return NULL; } @@ -760,7 +756,7 @@ __elf_create_symbol(struct elf *elf, struct symbol *sym) old->idx = new_idx; if (elf_update_symbol(elf, symtab, symtab_shndx, old)) { - WARN("elf_update_symbol move"); + ERROR("elf_update_symbol move"); return NULL; } @@ -778,7 +774,7 @@ __elf_create_symbol(struct elf *elf, struct symbol *sym) non_local: sym->idx = new_idx; if (elf_update_symbol(elf, symtab, symtab_shndx, sym)) { - WARN("elf_update_symbol"); + ERROR("elf_update_symbol"); return NULL; } @@ -799,7 +795,7 @@ elf_create_section_symbol(struct elf *elf, struct section *sec) struct symbol *sym = calloc(1, sizeof(*sym)); if (!sym) { - perror("malloc"); + ERROR_GLIBC("malloc"); return NULL; } @@ -829,7 +825,7 @@ elf_create_prefix_symbol(struct elf *elf, struct symbol *orig, long size) char *name = malloc(namelen); if (!sym || !name) { - perror("malloc"); + ERROR_GLIBC("malloc"); return NULL; } @@ -858,16 +854,16 @@ static struct reloc *elf_init_reloc(struct elf *elf, struct section *rsec, struct reloc *reloc, empty = { 0 }; if (reloc_idx >= sec_num_entries(rsec)) { - WARN("%s: bad reloc_idx %u for %s with %d relocs", - __func__, reloc_idx, rsec->name, sec_num_entries(rsec)); + ERROR("%s: bad reloc_idx %u for %s with %d relocs", + __func__, reloc_idx, rsec->name, sec_num_entries(rsec)); return NULL; } reloc = &rsec->relocs[reloc_idx]; if (memcmp(reloc, &empty, sizeof(empty))) { - WARN("%s: %s: reloc %d already initialized!", - __func__, rsec->name, reloc_idx); + ERROR("%s: %s: reloc %d already initialized!", + __func__, rsec->name, reloc_idx); return NULL; } @@ -880,7 +876,7 @@ static struct reloc *elf_init_reloc(struct elf *elf, struct section *rsec, set_reloc_addend(elf, reloc, addend); elf_hash_add(reloc, &reloc->hash, reloc_hash(reloc)); - reloc->sym_next_reloc = sym->relocs; + set_sym_next_reloc(reloc, sym->relocs); sym->relocs = reloc; return reloc; @@ -896,8 +892,7 @@ struct reloc *elf_init_reloc_text_sym(struct elf *elf, struct section *sec, int addend = insn_off; if (!(insn_sec->sh.sh_flags & SHF_EXECINSTR)) { - WARN("bad call to %s() for data symbol %s", - __func__, sym->name); + ERROR("bad call to %s() for data symbol %s", __func__, sym->name); return NULL; } @@ -926,8 +921,7 @@ struct reloc *elf_init_reloc_data_sym(struct elf *elf, struct section *sec, s64 addend) { if (sym->sec && (sec->sh.sh_flags & SHF_EXECINSTR)) { - WARN("bad call to %s() for text symbol %s", - __func__, sym->name); + ERROR("bad call to %s() for text symbol %s", __func__, sym->name); return NULL; } @@ -953,8 +947,7 @@ static int read_relocs(struct elf *elf) rsec->base = find_section_by_index(elf, rsec->sh.sh_info); if (!rsec->base) { - WARN("can't find base section for reloc section %s", - rsec->name); + ERROR("can't find base section for reloc section %s", rsec->name); return -1; } @@ -963,7 +956,7 @@ static int read_relocs(struct elf *elf) nr_reloc = 0; rsec->relocs = calloc(sec_num_entries(rsec), sizeof(*reloc)); if (!rsec->relocs) { - perror("calloc"); + ERROR_GLIBC("calloc"); return -1; } for (i = 0; i < sec_num_entries(rsec); i++) { @@ -973,13 +966,12 @@ static int read_relocs(struct elf *elf) symndx = reloc_sym(reloc); reloc->sym = sym = find_symbol_by_index(elf, symndx); if (!reloc->sym) { - WARN("can't find reloc entry symbol %d for %s", - symndx, rsec->name); + ERROR("can't find reloc entry symbol %d for %s", symndx, rsec->name); return -1; } elf_hash_add(reloc, &reloc->hash, reloc_hash(reloc)); - reloc->sym_next_reloc = sym->relocs; + set_sym_next_reloc(reloc, sym->relocs); sym->relocs = reloc; nr_reloc++; @@ -1005,7 +997,7 @@ struct elf *elf_open_read(const char *name, int flags) elf = malloc(sizeof(*elf)); if (!elf) { - perror("malloc"); + ERROR_GLIBC("malloc"); return NULL; } memset(elf, 0, sizeof(*elf)); @@ -1028,12 +1020,12 @@ struct elf *elf_open_read(const char *name, int flags) elf->elf = elf_begin(elf->fd, cmd, NULL); if (!elf->elf) { - WARN_ELF("elf_begin"); + ERROR_ELF("elf_begin"); goto err; } if (!gelf_getehdr(elf->elf, &elf->ehdr)) { - WARN_ELF("gelf_getehdr"); + ERROR_ELF("gelf_getehdr"); goto err; } @@ -1062,19 +1054,19 @@ static int elf_add_string(struct elf *elf, struct section *strtab, char *str) if (!strtab) strtab = find_section_by_name(elf, ".strtab"); if (!strtab) { - WARN("can't find .strtab section"); + ERROR("can't find .strtab section"); return -1; } s = elf_getscn(elf->elf, strtab->idx); if (!s) { - WARN_ELF("elf_getscn"); + ERROR_ELF("elf_getscn"); return -1; } data = elf_newdata(s); if (!data) { - WARN_ELF("elf_newdata"); + ERROR_ELF("elf_newdata"); return -1; } @@ -1099,7 +1091,7 @@ struct section *elf_create_section(struct elf *elf, const char *name, sec = malloc(sizeof(*sec)); if (!sec) { - perror("malloc"); + ERROR_GLIBC("malloc"); return NULL; } memset(sec, 0, sizeof(*sec)); @@ -1108,13 +1100,13 @@ struct section *elf_create_section(struct elf *elf, const char *name, s = elf_newscn(elf->elf); if (!s) { - WARN_ELF("elf_newscn"); + ERROR_ELF("elf_newscn"); return NULL; } sec->name = strdup(name); if (!sec->name) { - perror("strdup"); + ERROR_GLIBC("strdup"); return NULL; } @@ -1122,7 +1114,7 @@ struct section *elf_create_section(struct elf *elf, const char *name, sec->data = elf_newdata(s); if (!sec->data) { - WARN_ELF("elf_newdata"); + ERROR_ELF("elf_newdata"); return NULL; } @@ -1132,14 +1124,14 @@ struct section *elf_create_section(struct elf *elf, const char *name, if (size) { sec->data->d_buf = malloc(size); if (!sec->data->d_buf) { - perror("malloc"); + ERROR_GLIBC("malloc"); return NULL; } memset(sec->data->d_buf, 0, size); } if (!gelf_getshdr(s, &sec->sh)) { - WARN_ELF("gelf_getshdr"); + ERROR_ELF("gelf_getshdr"); return NULL; } @@ -1154,7 +1146,7 @@ struct section *elf_create_section(struct elf *elf, const char *name, if (!shstrtab) shstrtab = find_section_by_name(elf, ".strtab"); if (!shstrtab) { - WARN("can't find .shstrtab or .strtab section"); + ERROR("can't find .shstrtab or .strtab section"); return NULL; } sec->sh.sh_name = elf_add_string(elf, shstrtab, sec->name); @@ -1179,7 +1171,7 @@ static struct section *elf_create_rela_section(struct elf *elf, rsec_name = malloc(strlen(sec->name) + strlen(".rela") + 1); if (!rsec_name) { - perror("malloc"); + ERROR_GLIBC("malloc"); return NULL; } strcpy(rsec_name, ".rela"); @@ -1199,7 +1191,7 @@ static struct section *elf_create_rela_section(struct elf *elf, rsec->relocs = calloc(sec_num_entries(rsec), sizeof(struct reloc)); if (!rsec->relocs) { - perror("calloc"); + ERROR_GLIBC("calloc"); return NULL; } @@ -1232,7 +1224,7 @@ int elf_write_insn(struct elf *elf, struct section *sec, Elf_Data *data = sec->data; if (data->d_type != ELF_T_BYTE || data->d_off) { - WARN("write to unexpected data for section: %s", sec->name); + ERROR("write to unexpected data for section: %s", sec->name); return -1; } @@ -1261,7 +1253,7 @@ static int elf_truncate_section(struct elf *elf, struct section *sec) s = elf_getscn(elf->elf, sec->idx); if (!s) { - WARN_ELF("elf_getscn"); + ERROR_ELF("elf_getscn"); return -1; } @@ -1271,7 +1263,7 @@ static int elf_truncate_section(struct elf *elf, struct section *sec) if (!data) { if (size) { - WARN("end of section data but non-zero size left\n"); + ERROR("end of section data but non-zero size left\n"); return -1; } return 0; @@ -1279,12 +1271,12 @@ static int elf_truncate_section(struct elf *elf, struct section *sec) if (truncated) { /* when we remove symbols */ - WARN("truncated; but more data\n"); + ERROR("truncated; but more data\n"); return -1; } if (!data->d_size) { - WARN("zero size data"); + ERROR("zero size data"); return -1; } @@ -1310,13 +1302,13 @@ int elf_write(struct elf *elf) if (sec_changed(sec)) { s = elf_getscn(elf->elf, sec->idx); if (!s) { - WARN_ELF("elf_getscn"); + ERROR_ELF("elf_getscn"); return -1; } /* Note this also flags the section dirty */ if (!gelf_update_shdr(s, &sec->sh)) { - WARN_ELF("gelf_update_shdr"); + ERROR_ELF("gelf_update_shdr"); return -1; } @@ -1329,7 +1321,7 @@ int elf_write(struct elf *elf) /* Write all changes to the file. */ if (elf_update(elf->elf, ELF_C_WRITE) < 0) { - WARN_ELF("elf_update"); + ERROR_ELF("elf_update"); return -1; }
diff --git a/tools/objtool/include/objtool/builtin.h b/tools/objtool/include/objtool/builtin.h index 0fafd0f..6b08666 100644 --- a/tools/objtool/include/objtool/builtin.h +++ b/tools/objtool/include/objtool/builtin.h
@@ -43,8 +43,10 @@ struct opts { extern struct opts opts; -extern int cmd_parse_options(int argc, const char **argv, const char * const usage[]); +int cmd_parse_options(int argc, const char **argv, const char * const usage[]); -extern int objtool_run(int argc, const char **argv); +int objtool_run(int argc, const char **argv); + +void print_args(void); #endif /* _BUILTIN_H */
diff --git a/tools/objtool/include/objtool/check.h b/tools/objtool/include/objtool/check.h index e1cd13c..00fb745 100644 --- a/tools/objtool/include/objtool/check.h +++ b/tools/objtool/include/objtool/check.h
@@ -34,6 +34,8 @@ struct alt_group { * This is shared with the other alt_groups in the same alternative. */ struct cfi_state **cfi; + + bool ignore; }; #define INSN_CHUNK_BITS 8 @@ -54,7 +56,6 @@ struct instruction { u32 idx : INSN_CHUNK_BITS, dead_end : 1, - ignore : 1, ignore_alts : 1, hint : 1, save : 1,
diff --git a/tools/objtool/include/objtool/elf.h b/tools/objtool/include/objtool/elf.h index 223ac1c..c7c4e87 100644 --- a/tools/objtool/include/objtool/elf.h +++ b/tools/objtool/include/objtool/elf.h
@@ -65,10 +65,11 @@ struct symbol { u8 return_thunk : 1; u8 fentry : 1; u8 profiling_func : 1; + u8 warned : 1; u8 embedded_insn : 1; u8 local_label : 1; u8 frame_pointer : 1; - u8 warnings : 2; + u8 ignore : 1; struct list_head pv_target; struct reloc *relocs; }; @@ -77,7 +78,7 @@ struct reloc { struct elf_hash_node hash; struct section *sec; struct symbol *sym; - struct reloc *sym_next_reloc; + unsigned long _sym_next_reloc; }; struct elf { @@ -297,6 +298,31 @@ static inline void set_reloc_type(struct elf *elf, struct reloc *reloc, unsigned mark_sec_changed(elf, reloc->sec, true); } +#define RELOC_JUMP_TABLE_BIT 1UL + +/* Does reloc mark the beginning of a jump table? */ +static inline bool is_jump_table(struct reloc *reloc) +{ + return reloc->_sym_next_reloc & RELOC_JUMP_TABLE_BIT; +} + +static inline void set_jump_table(struct reloc *reloc) +{ + reloc->_sym_next_reloc |= RELOC_JUMP_TABLE_BIT; +} + +static inline struct reloc *sym_next_reloc(struct reloc *reloc) +{ + return (struct reloc *)(reloc->_sym_next_reloc & ~RELOC_JUMP_TABLE_BIT); +} + +static inline void set_sym_next_reloc(struct reloc *reloc, struct reloc *next) +{ + unsigned long bit = reloc->_sym_next_reloc & RELOC_JUMP_TABLE_BIT; + + reloc->_sym_next_reloc = (unsigned long)next | bit; +} + #define for_each_sec(file, sec) \ list_for_each_entry(sec, &file->elf->sections, list)
diff --git a/tools/objtool/include/objtool/objtool.h b/tools/objtool/include/objtool/objtool.h index 94a33ee..c0dc86a 100644 --- a/tools/objtool/include/objtool/objtool.h +++ b/tools/objtool/include/objtool/objtool.h
@@ -41,7 +41,7 @@ struct objtool_file { struct objtool_file *objtool_open_read(const char *_objname); -void objtool_pv_add(struct objtool_file *file, int idx, struct symbol *func); +int objtool_pv_add(struct objtool_file *file, int idx, struct symbol *func); int check(struct objtool_file *file); int orc_dump(const char *objname);
diff --git a/tools/objtool/include/objtool/special.h b/tools/objtool/include/objtool/special.h index e049679..72d09c0 100644 --- a/tools/objtool/include/objtool/special.h +++ b/tools/objtool/include/objtool/special.h
@@ -16,8 +16,6 @@ struct special_alt { struct list_head list; bool group; - bool skip_orig; - bool skip_alt; bool jump_or_nop; u8 key_addend; @@ -32,7 +30,7 @@ struct special_alt { int special_get_alts(struct elf *elf, struct list_head *alts); -void arch_handle_alternative(unsigned short feature, struct special_alt *alt); +void arch_handle_alternative(struct special_alt *alt); bool arch_support_alt_relocation(struct special_alt *special_alt, struct instruction *insn,
diff --git a/tools/objtool/include/objtool/warn.h b/tools/objtool/include/objtool/warn.h index e72b9d6..cb8fe846 100644 --- a/tools/objtool/include/objtool/warn.h +++ b/tools/objtool/include/objtool/warn.h
@@ -11,6 +11,7 @@ #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> +#include <errno.h> #include <objtool/builtin.h> #include <objtool/elf.h> @@ -41,36 +42,46 @@ static inline char *offstr(struct section *sec, unsigned long offset) return str; } -#define WARN(format, ...) \ - fprintf(stderr, \ - "%s: %s: objtool: " format "\n", \ - objname, \ - opts.werror ? "error" : "warning", \ +#define ___WARN(severity, extra, format, ...) \ + fprintf(stderr, \ + "%s%s%s: objtool" extra ": " format "\n", \ + objname ?: "", \ + objname ? ": " : "", \ + severity, \ ##__VA_ARGS__) -#define WARN_FUNC(format, sec, offset, ...) \ -({ \ - char *_str = offstr(sec, offset); \ - WARN("%s: " format, _str, ##__VA_ARGS__); \ - free(_str); \ +#define __WARN(severity, format, ...) \ + ___WARN(severity, "", format, ##__VA_ARGS__) + +#define __WARN_LINE(severity, format, ...) \ + ___WARN(severity, " [%s:%d]", format, __FILE__, __LINE__, ##__VA_ARGS__) + +#define __WARN_ELF(severity, format, ...) \ + __WARN_LINE(severity, "%s: " format " failed: %s", __func__, ##__VA_ARGS__, elf_errmsg(-1)) + +#define __WARN_GLIBC(severity, format, ...) \ + __WARN_LINE(severity, "%s: " format " failed: %s", __func__, ##__VA_ARGS__, strerror(errno)) + +#define __WARN_FUNC(severity, sec, offset, format, ...) \ +({ \ + char *_str = offstr(sec, offset); \ + __WARN(severity, "%s: " format, _str, ##__VA_ARGS__); \ + free(_str); \ }) -#define WARN_LIMIT 2 +#define WARN_STR (opts.werror ? "error" : "warning") + +#define WARN(format, ...) __WARN(WARN_STR, format, ##__VA_ARGS__) +#define WARN_FUNC(sec, offset, format, ...) __WARN_FUNC(WARN_STR, sec, offset, format, ##__VA_ARGS__) #define WARN_INSN(insn, format, ...) \ ({ \ struct instruction *_insn = (insn); \ - BUILD_BUG_ON(WARN_LIMIT > 2); \ - if (!_insn->sym || _insn->sym->warnings < WARN_LIMIT) { \ - WARN_FUNC(format, _insn->sec, _insn->offset, \ + if (!_insn->sym || !_insn->sym->warned) \ + WARN_FUNC(_insn->sec, _insn->offset, format, \ ##__VA_ARGS__); \ - if (_insn->sym) \ - _insn->sym->warnings++; \ - } else if (_insn->sym && _insn->sym->warnings == WARN_LIMIT) { \ - WARN_FUNC("skipping duplicate warning(s)", \ - _insn->sec, _insn->offset); \ - _insn->sym->warnings++; \ - } \ + if (_insn->sym) \ + _insn->sym->warned = 1; \ }) #define BT_INSN(insn, format, ...) \ @@ -83,7 +94,12 @@ static inline char *offstr(struct section *sec, unsigned long offset) } \ }) -#define WARN_ELF(format, ...) \ - WARN(format ": %s", ##__VA_ARGS__, elf_errmsg(-1)) +#define ERROR_STR "error" + +#define ERROR(format, ...) __WARN(ERROR_STR, format, ##__VA_ARGS__) +#define ERROR_ELF(format, ...) __WARN_ELF(ERROR_STR, format, ##__VA_ARGS__) +#define ERROR_GLIBC(format, ...) __WARN_GLIBC(ERROR_STR, format, ##__VA_ARGS__) +#define ERROR_FUNC(sec, offset, format, ...) __WARN_FUNC(ERROR_STR, sec, offset, format, ##__VA_ARGS__) +#define ERROR_INSN(insn, format, ...) WARN_FUNC(insn->sec, insn->offset, format, ##__VA_ARGS__) #endif /* _WARN_H */
diff --git a/tools/objtool/objtool.c b/tools/objtool/objtool.c index 1c73fb6..5c8b974 100644 --- a/tools/objtool/objtool.c +++ b/tools/objtool/objtool.c
@@ -23,7 +23,7 @@ static struct objtool_file file; struct objtool_file *objtool_open_read(const char *filename) { if (file.elf) { - WARN("won't handle more than one file at a time"); + ERROR("won't handle more than one file at a time"); return NULL; } @@ -44,14 +44,14 @@ struct objtool_file *objtool_open_read(const char *filename) return &file; } -void objtool_pv_add(struct objtool_file *f, int idx, struct symbol *func) +int objtool_pv_add(struct objtool_file *f, int idx, struct symbol *func) { if (!opts.noinstr) - return; + return 0; if (!f->pv_ops) { - WARN("paravirt confusion"); - return; + ERROR("paravirt confusion"); + return -1; } /* @@ -60,14 +60,15 @@ void objtool_pv_add(struct objtool_file *f, int idx, struct symbol *func) */ if (!strcmp(func->name, "_paravirt_nop") || !strcmp(func->name, "_paravirt_ident_64")) - return; + return 0; /* already added this function */ if (!list_empty(&func->pv_target)) - return; + return 0; list_add(&func->pv_target, &f->pv_ops[idx].targets); f->pv_ops[idx].clean = false; + return 0; } int main(int argc, const char **argv)
diff --git a/tools/objtool/orc_dump.c b/tools/objtool/orc_dump.c index 05ef0e2..1dd9fc1 100644 --- a/tools/objtool/orc_dump.c +++ b/tools/objtool/orc_dump.c
@@ -36,47 +36,47 @@ int orc_dump(const char *filename) elf = elf_begin(fd, ELF_C_READ_MMAP, NULL); if (!elf) { - WARN_ELF("elf_begin"); + ERROR_ELF("elf_begin"); return -1; } if (!elf64_getehdr(elf)) { - WARN_ELF("elf64_getehdr"); + ERROR_ELF("elf64_getehdr"); return -1; } memcpy(&dummy_elf.ehdr, elf64_getehdr(elf), sizeof(dummy_elf.ehdr)); if (elf_getshdrnum(elf, &nr_sections)) { - WARN_ELF("elf_getshdrnum"); + ERROR_ELF("elf_getshdrnum"); return -1; } if (elf_getshdrstrndx(elf, &shstrtab_idx)) { - WARN_ELF("elf_getshdrstrndx"); + ERROR_ELF("elf_getshdrstrndx"); return -1; } for (i = 0; i < nr_sections; i++) { scn = elf_getscn(elf, i); if (!scn) { - WARN_ELF("elf_getscn"); + ERROR_ELF("elf_getscn"); return -1; } if (!gelf_getshdr(scn, &sh)) { - WARN_ELF("gelf_getshdr"); + ERROR_ELF("gelf_getshdr"); return -1; } name = elf_strptr(elf, shstrtab_idx, sh.sh_name); if (!name) { - WARN_ELF("elf_strptr"); + ERROR_ELF("elf_strptr"); return -1; } data = elf_getdata(scn, NULL); if (!data) { - WARN_ELF("elf_getdata"); + ERROR_ELF("elf_getdata"); return -1; } @@ -99,7 +99,7 @@ int orc_dump(const char *filename) return 0; if (orc_size % sizeof(*orc) != 0) { - WARN("bad .orc_unwind section size"); + ERROR("bad .orc_unwind section size"); return -1; } @@ -107,36 +107,36 @@ int orc_dump(const char *filename) for (i = 0; i < nr_entries; i++) { if (rela_orc_ip) { if (!gelf_getrela(rela_orc_ip, i, &rela)) { - WARN_ELF("gelf_getrela"); + ERROR_ELF("gelf_getrela"); return -1; } if (!gelf_getsym(symtab, GELF_R_SYM(rela.r_info), &sym)) { - WARN_ELF("gelf_getsym"); + ERROR_ELF("gelf_getsym"); return -1; } if (GELF_ST_TYPE(sym.st_info) == STT_SECTION) { scn = elf_getscn(elf, sym.st_shndx); if (!scn) { - WARN_ELF("elf_getscn"); + ERROR_ELF("elf_getscn"); return -1; } if (!gelf_getshdr(scn, &sh)) { - WARN_ELF("gelf_getshdr"); + ERROR_ELF("gelf_getshdr"); return -1; } name = elf_strptr(elf, shstrtab_idx, sh.sh_name); if (!name) { - WARN_ELF("elf_strptr"); + ERROR_ELF("elf_strptr"); return -1; } } else { name = elf_strptr(elf, strtab_idx, sym.st_name); if (!name) { - WARN_ELF("elf_strptr"); + ERROR_ELF("elf_strptr"); return -1; } }
diff --git a/tools/objtool/special.c b/tools/objtool/special.c index 097a69d..c80fed8 100644 --- a/tools/objtool/special.c +++ b/tools/objtool/special.c
@@ -54,7 +54,7 @@ static const struct special_entry entries[] = { {}, }; -void __weak arch_handle_alternative(unsigned short feature, struct special_alt *alt) +void __weak arch_handle_alternative(struct special_alt *alt) { } @@ -86,27 +86,18 @@ static int get_alt_entry(struct elf *elf, const struct special_entry *entry, orig_reloc = find_reloc_by_dest(elf, sec, offset + entry->orig); if (!orig_reloc) { - WARN_FUNC("can't find orig reloc", sec, offset + entry->orig); + ERROR_FUNC(sec, offset + entry->orig, "can't find orig reloc"); return -1; } reloc_to_sec_off(orig_reloc, &alt->orig_sec, &alt->orig_off); - if (entry->feature) { - unsigned short feature; - - feature = bswap_if_needed(elf, - *(unsigned short *)(sec->data->d_buf + - offset + - entry->feature)); - arch_handle_alternative(feature, alt); - } + arch_handle_alternative(alt); if (!entry->group || alt->new_len) { new_reloc = find_reloc_by_dest(elf, sec, offset + entry->new); if (!new_reloc) { - WARN_FUNC("can't find new reloc", - sec, offset + entry->new); + ERROR_FUNC(sec, offset + entry->new, "can't find new reloc"); return -1; } @@ -122,8 +113,7 @@ static int get_alt_entry(struct elf *elf, const struct special_entry *entry, key_reloc = find_reloc_by_dest(elf, sec, offset + entry->key); if (!key_reloc) { - WARN_FUNC("can't find key reloc", - sec, offset + entry->key); + ERROR_FUNC(sec, offset + entry->key, "can't find key reloc"); return -1; } alt->key_addend = reloc_addend(key_reloc); @@ -153,8 +143,7 @@ int special_get_alts(struct elf *elf, struct list_head *alts) continue; if (sec->sh.sh_size % entry->size != 0) { - WARN("%s size not a multiple of %d", - sec->name, entry->size); + ERROR("%s size not a multiple of %d", sec->name, entry->size); return -1; } @@ -163,7 +152,7 @@ int special_get_alts(struct elf *elf, struct list_head *alts) for (idx = 0; idx < nr_entries; idx++) { alt = malloc(sizeof(*alt)); if (!alt) { - WARN("malloc failed"); + ERROR_GLIBC("malloc failed"); return -1; } memset(alt, 0, sizeof(*alt));
diff --git a/tools/perf/tests/shell/trace_btf_enum.sh b/tools/perf/tests/shell/trace_btf_enum.sh index 60b3fa2..f0b49f7 100755 --- a/tools/perf/tests/shell/trace_btf_enum.sh +++ b/tools/perf/tests/shell/trace_btf_enum.sh
@@ -6,7 +6,7 @@ set -e syscall="landlock_add_rule" -non_syscall="timer:hrtimer_init,timer:hrtimer_start" +non_syscall="timer:hrtimer_setup,timer:hrtimer_start" TESTPROG="perf test -w landlock"
diff --git a/tools/power/x86/turbostat/turbostat.8 b/tools/power/x86/turbostat/turbostat.8 index 99bf905..b74ed91 100644 --- a/tools/power/x86/turbostat/turbostat.8 +++ b/tools/power/x86/turbostat/turbostat.8
@@ -100,7 +100,7 @@ .PP \fB--show column\fP show only the specified built-in columns. May be invoked multiple times, or with a comma-separated list of column names. .PP -\fB--show CATEGORY --hide CATEGORY\fP Show and hide also accept a single CATEGORY of columns: "all", "topology", "idle", "frequency", "power", "sysfs", "other". +\fB--show CATEGORY --hide CATEGORY\fP Show and hide also accept a single CATEGORY of columns: "all", "topology", "idle", "frequency", "power", "cpuidle", "hwidle", "swidle", "other". "idle" (enabled by default), includes "hwidle" and "idle_pct". "cpuidle" (default disabled) includes cpuidle software invocation counters. "swidle" includes "cpuidle" plus "idle_pct". "hwidle" includes only hardware based idle residency counters. Older versions of turbostat used the term "sysfs" for what is now "swidle". .PP \fB--Dump\fP displays the raw counter values. .PP @@ -158,16 +158,22 @@ .PP \fBSMI\fP The number of System Management Interrupts serviced CPU during the measurement interval. While this counter is actually per-CPU, SMI are triggered on all processors, so the number should be the same for all CPUs. .PP -\fBC1, C2, C3...\fP The number times Linux requested the C1, C2, C3 idle state during the measurement interval. The system summary line shows the sum for all CPUs. These are C-state names as exported in /sys/devices/system/cpu/cpu*/cpuidle/state*/name. While their names are generic, their attributes are processor specific. They the system description section of output shows what MWAIT sub-states they are mapped to on each system. +\fBC1, C2, C3...\fP The number times Linux requested the C1, C2, C3 idle state during the measurement interval. The system summary line shows the sum for all CPUs. These are C-state names as exported in /sys/devices/system/cpu/cpu*/cpuidle/state*/name. While their names are generic, their attributes are processor specific. They the system description section of output shows what MWAIT sub-states they are mapped to on each system. These counters are in the "cpuidle" group, which is disabled, by default. .PP -\fBC1%, C2%, C3%\fP The residency percentage that Linux requested C1, C2, C3.... The system summary is the average of all CPUs in the system. Note that these are software, reflecting what was requested. The hardware counters reflect what was actually achieved. +\fBC1+, C2+, C3+...\fP The idle governor idle state misprediction statistics. Inidcates the number times Linux requested the C1, C2, C3 idle state during the measurement interval, but should have requested a deeper idle state (if it exists and enabled). These statistics come from the /sys/devices/system/cpu/cpu*/cpuidle/state*/below file. These counters are in the "cpuidle" group, which is disabled, by default. .PP -\fBCPU%c1, CPU%c3, CPU%c6, CPU%c7\fP show the percentage residency in hardware core idle states. These numbers are from hardware residency counters. +\fBC1-, C2-, C3-...\fP The idle governor idle state misprediction statistics. Inidcates the number times Linux requested the C1, C2, C3 idle state during the measurement interval, but should have requested a shallower idle state (if it exists and enabled). These statistics come from the /sys/devices/system/cpu/cpu*/cpuidle/state*/above file. These counters are in the "cpuidle" group, which is disabled, by default. +.PP +\fBC1%, C2%, C3%\fP The residency percentage that Linux requested C1, C2, C3.... The system summary is the average of all CPUs in the system. Note that these are software, reflecting what was requested. The hardware counters reflect what was actually achieved. These counters are in the "pct_idle" group, which is enabled by default. +.PP +\fBCPU%c1, CPU%c3, CPU%c6, CPU%c7\fP show the percentage residency in hardware core idle states. These numbers are from hardware residency counters and are in the "hwidle" group, which is enabled, by default. .PP \fBCoreTmp\fP Degrees Celsius reported by the per-core Digital Thermal Sensor. .PP \fBPkgTmp\fP Degrees Celsius reported by the per-package Package Thermal Monitor. .PP +\fBCoreThr\fP Core Thermal Throttling events during the measurement interval. Note that events since boot can be find in /sys/devices/system/cpu/cpu*/thermal_throttle/* +.PP \fBGFX%rc6\fP The percentage of time the GPU is in the "render C6" state, rc6, during the measurement interval. From /sys/class/drm/card0/power/rc6_residency_ms or /sys/class/drm/card0/gt/gt0/rc6_residency_ms or /sys/class/drm/card0/device/tile0/gtN/gtidle/idle_residency_ms depending on the graphics driver being used. .PP \fBGFXMHz\fP Instantaneous snapshot of what sysfs presents at the end of the measurement interval. From /sys/class/graphics/fb0/device/drm/card0/gt_cur_freq_mhz or /sys/class/drm/card0/gt_cur_freq_mhz or /sys/class/drm/card0/gt/gt0/rps_cur_freq_mhz or /sys/class/drm/card0/device/tile0/gtN/freq0/cur_freq depending on the graphics driver being used. @@ -199,6 +205,8 @@ \fBUncMHz\fP per-package uncore MHz, instantaneous sample. .PP \fBUMHz1.0\fP per-package uncore MHz for domain=1 and fabric_cluster=0, instantaneous sample. System summary is the average of all packages. +Intel Granite Rapids systems use domains 0-2 for CPUs, and 3-4 for IO, with cluster always 0. +For the "--show" and "--hide" options, use "UncMHz" to operate on all UMHz*.* as a group. .SH TOO MUCH INFORMATION EXAMPLE By default, turbostat dumps all possible information -- a system configuration header, followed by columns for all counters. This is ideal for remote debugging, use the "--out" option to save everything to a text file, and get that file to the expert helping you debug.
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 26057af..0170d3c 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c
@@ -153,7 +153,7 @@ struct msr_counter bic[] = { { 0x0, "TSC_MHz", NULL, 0, 0, 0, NULL, 0 }, { 0x0, "IRQ", NULL, 0, 0, 0, NULL, 0 }, { 0x0, "SMI", NULL, 32, 0, FORMAT_DELTA, NULL, 0 }, - { 0x0, "sysfs", NULL, 0, 0, 0, NULL, 0 }, + { 0x0, "cpuidle", NULL, 0, 0, 0, NULL, 0 }, { 0x0, "CPU%c1", NULL, 0, 0, 0, NULL, 0 }, { 0x0, "CPU%c3", NULL, 0, 0, 0, NULL, 0 }, { 0x0, "CPU%c6", NULL, 0, 0, 0, NULL, 0 }, @@ -206,6 +206,7 @@ struct msr_counter bic[] = { { 0x0, "Sys_J", NULL, 0, 0, 0, NULL, 0 }, { 0x0, "NMI", NULL, 0, 0, 0, NULL, 0 }, { 0x0, "CPU%c1e", NULL, 0, 0, 0, NULL, 0 }, + { 0x0, "pct_idle", NULL, 0, 0, 0, NULL, 0 }, }; #define MAX_BIC (sizeof(bic) / sizeof(struct msr_counter)) @@ -219,7 +220,7 @@ struct msr_counter bic[] = { #define BIC_TSC_MHz (1ULL << 7) #define BIC_IRQ (1ULL << 8) #define BIC_SMI (1ULL << 9) -#define BIC_sysfs (1ULL << 10) +#define BIC_cpuidle (1ULL << 10) #define BIC_CPU_c1 (1ULL << 11) #define BIC_CPU_c3 (1ULL << 12) #define BIC_CPU_c6 (1ULL << 13) @@ -272,17 +273,20 @@ struct msr_counter bic[] = { #define BIC_Sys_J (1ULL << 60) #define BIC_NMI (1ULL << 61) #define BIC_CPU_c1e (1ULL << 62) +#define BIC_pct_idle (1ULL << 63) -#define BIC_TOPOLOGY (BIC_Package | BIC_Node | BIC_CoreCnt | BIC_PkgCnt | BIC_Core | BIC_CPU | BIC_Die) -#define BIC_THERMAL_PWR (BIC_CoreTmp | BIC_PkgTmp | BIC_PkgWatt | BIC_CorWatt | BIC_GFXWatt | BIC_RAMWatt | BIC_PKG__ | BIC_RAM__ | BIC_SysWatt) -#define BIC_FREQUENCY (BIC_Avg_MHz | BIC_Busy | BIC_Bzy_MHz | BIC_TSC_MHz | BIC_GFXMHz | BIC_GFXACTMHz | BIC_SAMMHz | BIC_SAMACTMHz | BIC_UNCORE_MHZ) -#define BIC_IDLE (BIC_Busy | BIC_sysfs | BIC_CPU_c1 | BIC_CPU_c3 | BIC_CPU_c6 | BIC_CPU_c7 | BIC_GFX_rc6 | BIC_Pkgpc2 | BIC_Pkgpc3 | BIC_Pkgpc6 | BIC_Pkgpc7 | BIC_Pkgpc8 | BIC_Pkgpc9 | BIC_Pkgpc10 | BIC_CPU_LPI | BIC_SYS_LPI | BIC_Mod_c6 | BIC_Totl_c0 | BIC_Any_c0 | BIC_GFX_c0 | BIC_CPUGFX | BIC_SAM_mc6 | BIC_Diec6) +#define BIC_GROUP_TOPOLOGY (BIC_Package | BIC_Node | BIC_CoreCnt | BIC_PkgCnt | BIC_Core | BIC_CPU | BIC_Die) +#define BIC_GROUP_THERMAL_PWR (BIC_CoreTmp | BIC_PkgTmp | BIC_PkgWatt | BIC_CorWatt | BIC_GFXWatt | BIC_RAMWatt | BIC_PKG__ | BIC_RAM__ | BIC_SysWatt) +#define BIC_GROUP_FREQUENCY (BIC_Avg_MHz | BIC_Busy | BIC_Bzy_MHz | BIC_TSC_MHz | BIC_GFXMHz | BIC_GFXACTMHz | BIC_SAMMHz | BIC_SAMACTMHz | BIC_UNCORE_MHZ) +#define BIC_GROUP_HW_IDLE (BIC_Busy | BIC_CPU_c1 | BIC_CPU_c3 | BIC_CPU_c6 | BIC_CPU_c7 | BIC_GFX_rc6 | BIC_Pkgpc2 | BIC_Pkgpc3 | BIC_Pkgpc6 | BIC_Pkgpc7 | BIC_Pkgpc8 | BIC_Pkgpc9 | BIC_Pkgpc10 | BIC_CPU_LPI | BIC_SYS_LPI | BIC_Mod_c6 | BIC_Totl_c0 | BIC_Any_c0 | BIC_GFX_c0 | BIC_CPUGFX | BIC_SAM_mc6 | BIC_Diec6) +#define BIC_GROUP_SW_IDLE (BIC_Busy | BIC_cpuidle | BIC_pct_idle ) +#define BIC_GROUP_IDLE (BIC_GROUP_HW_IDLE | BIC_pct_idle) #define BIC_OTHER (BIC_IRQ | BIC_NMI | BIC_SMI | BIC_ThreadC | BIC_CoreTmp | BIC_IPC) -#define BIC_DISABLED_BY_DEFAULT (BIC_USEC | BIC_TOD | BIC_APIC | BIC_X2APIC) +#define BIC_DISABLED_BY_DEFAULT (BIC_USEC | BIC_TOD | BIC_APIC | BIC_X2APIC | BIC_cpuidle) unsigned long long bic_enabled = (0xFFFFFFFFFFFFFFFFULL & ~BIC_DISABLED_BY_DEFAULT); -unsigned long long bic_present = BIC_USEC | BIC_TOD | BIC_sysfs | BIC_APIC | BIC_X2APIC; +unsigned long long bic_present = BIC_USEC | BIC_TOD | BIC_cpuidle | BIC_pct_idle | BIC_APIC | BIC_X2APIC; #define DO_BIC(COUNTER_NAME) (bic_enabled & bic_present & COUNTER_NAME) #define DO_BIC_READ(COUNTER_NAME) (bic_present & COUNTER_NAME) @@ -1121,7 +1125,7 @@ void probe_platform_features(unsigned int family, unsigned int model) int backwards_count; char *progname; -#define CPU_SUBSET_MAXCPUS 1024 /* need to use before probe... */ +#define CPU_SUBSET_MAXCPUS 8192 /* need to use before probe... */ cpu_set_t *cpu_present_set, *cpu_possible_set, *cpu_effective_set, *cpu_allowed_set, *cpu_affinity_set, *cpu_subset; size_t cpu_present_setsize, cpu_possible_setsize, cpu_effective_setsize, cpu_allowed_setsize, cpu_affinity_setsize, cpu_subset_size; #define MAX_ADDED_THREAD_COUNTERS 24 @@ -2211,7 +2215,7 @@ int get_msr(int cpu, off_t offset, unsigned long long *msr) return 0; } -int probe_msr(int cpu, off_t offset) +int probe_rapl_msr(int cpu, off_t offset, int index) { ssize_t retval; unsigned long long value; @@ -2220,13 +2224,22 @@ int probe_msr(int cpu, off_t offset) retval = pread(get_msr_fd(cpu), &value, sizeof(value), offset); - /* - * Expect MSRs to accumulate some non-zero value since the system was powered on. - * Treat zero as a read failure. - */ - if (retval != sizeof(value) || value == 0) + /* if the read failed, the probe fails */ + if (retval != sizeof(value)) return 1; + /* If an Energy Status Counter MSR returns 0, the probe fails */ + switch (index) { + case RAPL_RCI_INDEX_ENERGY_PKG: + case RAPL_RCI_INDEX_ENERGY_CORES: + case RAPL_RCI_INDEX_DRAM: + case RAPL_RCI_INDEX_GFX: + case RAPL_RCI_INDEX_ENERGY_PLATFORM: + if (value == 0) + return 1; + } + + /* PKG,DRAM_PERF_STATUS MSRs, can return any value */ return 0; } @@ -2345,16 +2358,25 @@ unsigned long long bic_lookup(char *name_list, enum show_hide_mode mode) retval |= ~0; break; } else if (!strcmp(name_list, "topology")) { - retval |= BIC_TOPOLOGY; + retval |= BIC_GROUP_TOPOLOGY; break; } else if (!strcmp(name_list, "power")) { - retval |= BIC_THERMAL_PWR; + retval |= BIC_GROUP_THERMAL_PWR; break; } else if (!strcmp(name_list, "idle")) { - retval |= BIC_IDLE; + retval |= BIC_GROUP_IDLE; + break; + } else if (!strcmp(name_list, "swidle")) { + retval |= BIC_GROUP_SW_IDLE; + break; + } else if (!strcmp(name_list, "sysfs")) { /* legacy compatibility */ + retval |= BIC_GROUP_SW_IDLE; + break; + } else if (!strcmp(name_list, "hwidle")) { + retval |= BIC_GROUP_HW_IDLE; break; } else if (!strcmp(name_list, "frequency")) { - retval |= BIC_FREQUENCY; + retval |= BIC_GROUP_FREQUENCY; break; } else if (!strcmp(name_list, "other")) { retval |= BIC_OTHER; @@ -2363,6 +2385,7 @@ unsigned long long bic_lookup(char *name_list, enum show_hide_mode mode) } if (i == MAX_BIC) { + fprintf(stderr, "deferred %s\n", name_list); if (mode == SHOW_LIST) { deferred_add_names[deferred_add_index++] = name_list; if (deferred_add_index >= MAX_DEFERRED) { @@ -3476,7 +3499,7 @@ void delta_core(struct core_data *new, struct core_data *old) old->c6 = new->c6 - old->c6; old->c7 = new->c7 - old->c7; old->core_temp_c = new->core_temp_c; - old->core_throt_cnt = new->core_throt_cnt; + old->core_throt_cnt = new->core_throt_cnt - old->core_throt_cnt; old->mc6_us = new->mc6_us - old->mc6_us; DELTA_WRAP32(new->core_energy.raw_value, old->core_energy.raw_value); @@ -6030,6 +6053,7 @@ int snapshot_graphics(int idx) int retval; rewind(gfx_info[idx].fp); + fflush(gfx_info[idx].fp); switch (idx) { case GFX_rc6: @@ -6703,7 +6727,18 @@ static void probe_intel_uncore_frequency_cluster(void) sprintf(path, "%s/current_freq_khz", path_base); sprintf(name_buf, "UMHz%d.%d", domain_id, cluster_id); - add_counter(0, path, name_buf, 0, SCOPE_PACKAGE, COUNTER_K2M, FORMAT_AVERAGE, 0, package_id); + /* + * Once add_couter() is called, that counter is always read + * and reported -- So it is effectively (enabled & present). + * Only call add_counter() here if legacy BIC_UNCORE_MHZ (UncMHz) + * is (enabled). Since we are in this routine, we + * know we will not probe and set (present) the legacy counter. + * + * This allows "--show/--hide UncMHz" to be effective for + * the clustered MHz counters, as a group. + */ + if BIC_IS_ENABLED(BIC_UNCORE_MHZ) + add_counter(0, path, name_buf, 0, SCOPE_PACKAGE, COUNTER_K2M, FORMAT_AVERAGE, 0, package_id); if (quiet) continue; @@ -7896,7 +7931,7 @@ void rapl_perf_init(void) rci->flags[cai->rci_index] = cai->flags; /* Use MSR for this counter */ - } else if (!no_msr && cai->msr && probe_msr(cpu, cai->msr) == 0) { + } else if (!no_msr && cai->msr && probe_rapl_msr(cpu, cai->msr, cai->rci_index) == 0) { rci->source[cai->rci_index] = COUNTER_SOURCE_MSR; rci->msr[cai->rci_index] = cai->msr; rci->msr_mask[cai->rci_index] = cai->msr_mask; @@ -8034,7 +8069,7 @@ void msr_perf_init_(void) cai->present = true; /* User MSR for this counter */ - } else if (!no_msr && cai->msr && probe_msr(cpu, cai->msr) == 0) { + } else if (!no_msr && cai->msr && probe_rapl_msr(cpu, cai->msr, cai->rci_index) == 0) { cci->source[cai->rci_index] = COUNTER_SOURCE_MSR; cci->msr[cai->rci_index] = cai->msr; cci->msr_mask[cai->rci_index] = cai->msr_mask; @@ -8148,7 +8183,7 @@ void cstate_perf_init_(bool soft_c1) /* User MSR for this counter */ } else if (!no_msr && cai->msr && pkg_cstate_limit >= cai->pkg_cstate_limit - && probe_msr(cpu, cai->msr) == 0) { + && probe_rapl_msr(cpu, cai->msr, cai->rci_index) == 0) { cci->source[cai->rci_index] = COUNTER_SOURCE_MSR; cci->msr[cai->rci_index] = cai->msr; } @@ -9559,7 +9594,7 @@ int get_and_dump_counters(void) void print_version() { - fprintf(outf, "turbostat version 2025.02.02 - Len Brown <lenb@kernel.org>\n"); + fprintf(outf, "turbostat version 2025.04.06 - Len Brown <lenb@kernel.org>\n"); } #define COMMAND_LINE_SIZE 2048 @@ -9592,7 +9627,7 @@ struct msr_counter *find_msrp_by_name(struct msr_counter *head, char *name) for (mp = head; mp; mp = mp->next) { if (debug) fprintf(stderr, "%s: %s %s\n", __func__, name, mp->name); - if (!strncmp(name, mp->name, strlen(mp->name))) + if (!strcmp(name, mp->name)) return mp; } return NULL; @@ -10239,14 +10274,18 @@ int is_deferred_skip(char *name) return 0; } -void probe_sysfs(void) +void probe_cpuidle_residency(void) { char path[64]; char name_buf[16]; FILE *input; int state; + int min_state = 1024, max_state = 0; char *sp; + if (!DO_BIC(BIC_pct_idle)) + return; + for (state = 10; state >= 0; --state) { sprintf(path, "/sys/devices/system/cpu/cpu%d/cpuidle/state%d/name", base_cpu, state); @@ -10269,14 +10308,32 @@ void probe_sysfs(void) sprintf(path, "cpuidle/state%d/time", state); - if (!DO_BIC(BIC_sysfs) && !is_deferred_add(name_buf)) + if (!DO_BIC(BIC_pct_idle) && !is_deferred_add(name_buf)) continue; if (is_deferred_skip(name_buf)) continue; add_counter(0, path, name_buf, 64, SCOPE_CPU, COUNTER_USEC, FORMAT_PERCENT, SYSFS_PERCPU, 0); + + if (state > max_state) + max_state = state; + if (state < min_state) + min_state = state; } +} + +void probe_cpuidle_counts(void) +{ + char path[64]; + char name_buf[16]; + FILE *input; + int state; + int min_state = 1024, max_state = 0; + char *sp; + + if (!DO_BIC(BIC_cpuidle)) + return; for (state = 10; state >= 0; --state) { @@ -10286,26 +10343,52 @@ void probe_sysfs(void) continue; if (!fgets(name_buf, sizeof(name_buf), input)) err(1, "%s: failed to read file", path); - /* truncate "C1-HSW\n" to "C1", or truncate "C1\n" to "C1" */ - sp = strchr(name_buf, '-'); - if (!sp) - sp = strchrnul(name_buf, '\n'); - *sp = '\0'; fclose(input); remove_underbar(name_buf); - sprintf(path, "cpuidle/state%d/usage", state); - - if (!DO_BIC(BIC_sysfs) && !is_deferred_add(name_buf)) + if (!DO_BIC(BIC_cpuidle) && !is_deferred_add(name_buf)) continue; if (is_deferred_skip(name_buf)) continue; - add_counter(0, path, name_buf, 64, SCOPE_CPU, COUNTER_ITEMS, FORMAT_DELTA, SYSFS_PERCPU, 0); - } + /* truncate "C1-HSW\n" to "C1", or truncate "C1\n" to "C1" */ + sp = strchr(name_buf, '-'); + if (!sp) + sp = strchrnul(name_buf, '\n'); + /* + * The 'below' sysfs file always contains 0 for the deepest state (largest index), + * do not add it. + */ + if (state != max_state) { + /* + * Add 'C1+' for C1, and so on. The 'below' sysfs file always contains 0 for + * the last state, so do not add it. + */ + + *sp = '+'; + *(sp + 1) = '\0'; + sprintf(path, "cpuidle/state%d/below", state); + add_counter(0, path, name_buf, 64, SCOPE_CPU, COUNTER_ITEMS, FORMAT_DELTA, SYSFS_PERCPU, 0); + } + + *sp = '\0'; + sprintf(path, "cpuidle/state%d/usage", state); + add_counter(0, path, name_buf, 64, SCOPE_CPU, COUNTER_ITEMS, FORMAT_DELTA, SYSFS_PERCPU, 0); + + /* + * The 'above' sysfs file always contains 0 for the shallowest state (smallest + * index), do not add it. + */ + if (state != min_state) { + *sp = '-'; + *(sp + 1) = '\0'; + sprintf(path, "cpuidle/state%d/above", state); + add_counter(0, path, name_buf, 64, SCOPE_CPU, COUNTER_ITEMS, FORMAT_DELTA, SYSFS_PERCPU, 0); + } + } } /* @@ -10549,7 +10632,8 @@ int main(int argc, char **argv) print_bootcmd(); } - probe_sysfs(); + probe_cpuidle_residency(); + probe_cpuidle_counts(); if (!getuid()) set_rlimit();
diff --git a/tools/sched_ext/include/scx/common.bpf.h b/tools/sched_ext/include/scx/common.bpf.h index dc4333d..8787048 100644 --- a/tools/sched_ext/include/scx/common.bpf.h +++ b/tools/sched_ext/include/scx/common.bpf.h
@@ -586,36 +586,48 @@ static __always_inline void __write_once_size(volatile void *p, void *res, int s } } -#define READ_ONCE(x) \ -({ \ - union { typeof(x) __val; char __c[1]; } __u = \ - { .__c = { 0 } }; \ - __read_once_size(&(x), __u.__c, sizeof(x)); \ - __u.__val; \ +/* + * __unqual_typeof(x) - Declare an unqualified scalar type, leaving + * non-scalar types unchanged, + * + * Prefer C11 _Generic for better compile-times and simpler code. Note: 'char' + * is not type-compatible with 'signed char', and we define a separate case. + * + * This is copied verbatim from kernel's include/linux/compiler_types.h, but + * with default expression (for pointers) changed from (x) to (typeof(x)0). + * + * This is because LLVM has a bug where for lvalue (x), it does not get rid of + * an extra address_space qualifier, but does in case of rvalue (typeof(x)0). + * Hence, for pointers, we need to create an rvalue expression to get the + * desired type. See https://github.com/llvm/llvm-project/issues/53400. + */ +#define __scalar_type_to_expr_cases(type) \ + unsigned type : (unsigned type)0, signed type : (signed type)0 + +#define __unqual_typeof(x) \ + typeof(_Generic((x), \ + char: (char)0, \ + __scalar_type_to_expr_cases(char), \ + __scalar_type_to_expr_cases(short), \ + __scalar_type_to_expr_cases(int), \ + __scalar_type_to_expr_cases(long), \ + __scalar_type_to_expr_cases(long long), \ + default: (typeof(x))0)) + +#define READ_ONCE(x) \ +({ \ + union { __unqual_typeof(x) __val; char __c[1]; } __u = \ + { .__c = { 0 } }; \ + __read_once_size((__unqual_typeof(x) *)&(x), __u.__c, sizeof(x)); \ + __u.__val; \ }) -#define WRITE_ONCE(x, val) \ -({ \ - union { typeof(x) __val; char __c[1]; } __u = \ - { .__val = (val) }; \ - __write_once_size(&(x), __u.__c, sizeof(x)); \ - __u.__val; \ -}) - -#define READ_ONCE_ARENA(type, x) \ -({ \ - union { type __val; char __c[1]; } __u = \ - { .__c = { 0 } }; \ - __read_once_size((void *)&(x), __u.__c, sizeof(x)); \ - __u.__val; \ -}) - -#define WRITE_ONCE_ARENA(type, x, val) \ -({ \ - union { type __val; char __c[1]; } __u = \ - { .__val = (val) }; \ - __write_once_size((void *)&(x), __u.__c, sizeof(x)); \ - __u.__val; \ +#define WRITE_ONCE(x, val) \ +({ \ + union { __unqual_typeof(x) __val; char __c[1]; } __u = \ + { .__val = (val) }; \ + __write_once_size((__unqual_typeof(x) *)&(x), __u.__c, sizeof(x)); \ + __u.__val; \ }) /* @@ -648,6 +660,23 @@ static inline u32 log2_u64(u64 v) return log2_u32(v) + 1; } +/* + * Return a value proportionally scaled to the task's weight. + */ +static inline u64 scale_by_task_weight(const struct task_struct *p, u64 value) +{ + return (value * p->scx.weight) / 100; +} + +/* + * Return a value inversely proportional to the task's weight. + */ +static inline u64 scale_by_task_weight_inverse(const struct task_struct *p, u64 value) +{ + return value * 100 / p->scx.weight; +} + + #include "compat.bpf.h" #include "enums.bpf.h"
diff --git a/tools/sched_ext/include/scx/enum_defs.autogen.h b/tools/sched_ext/include/scx/enum_defs.autogen.h index 6e6c45f..c2c33df 100644 --- a/tools/sched_ext/include/scx/enum_defs.autogen.h +++ b/tools/sched_ext/include/scx/enum_defs.autogen.h
@@ -88,6 +88,8 @@ #define HAVE_SCX_OPS_ENQ_LAST #define HAVE_SCX_OPS_ENQ_EXITING #define HAVE_SCX_OPS_SWITCH_PARTIAL +#define HAVE_SCX_OPS_ENQ_MIGRATION_DISABLED +#define HAVE_SCX_OPS_ALLOW_QUEUED_WAKEUP #define HAVE_SCX_OPS_HAS_CGROUP_WEIGHT #define HAVE_SCX_OPS_ALL_FLAGS #define HAVE_SCX_OPSS_NONE @@ -104,6 +106,7 @@ #define HAVE_SCX_RQ_BAL_PENDING #define HAVE_SCX_RQ_BAL_KEEP #define HAVE_SCX_RQ_BYPASSING +#define HAVE_SCX_RQ_CLK_VALID #define HAVE_SCX_RQ_IN_WAKEUP #define HAVE_SCX_RQ_IN_BALANCE #define HAVE_SCX_TASK_NONE
diff --git a/tools/sched_ext/include/scx/enums.autogen.bpf.h b/tools/sched_ext/include/scx/enums.autogen.bpf.h index 0e941a0..2f8002b 100644 --- a/tools/sched_ext/include/scx/enums.autogen.bpf.h +++ b/tools/sched_ext/include/scx/enums.autogen.bpf.h
@@ -13,6 +13,30 @@ const volatile u64 __SCX_SLICE_DFL __weak; const volatile u64 __SCX_SLICE_INF __weak; #define SCX_SLICE_INF __SCX_SLICE_INF +const volatile u64 __SCX_RQ_ONLINE __weak; +#define SCX_RQ_ONLINE __SCX_RQ_ONLINE + +const volatile u64 __SCX_RQ_CAN_STOP_TICK __weak; +#define SCX_RQ_CAN_STOP_TICK __SCX_RQ_CAN_STOP_TICK + +const volatile u64 __SCX_RQ_BAL_PENDING __weak; +#define SCX_RQ_BAL_PENDING __SCX_RQ_BAL_PENDING + +const volatile u64 __SCX_RQ_BAL_KEEP __weak; +#define SCX_RQ_BAL_KEEP __SCX_RQ_BAL_KEEP + +const volatile u64 __SCX_RQ_BYPASSING __weak; +#define SCX_RQ_BYPASSING __SCX_RQ_BYPASSING + +const volatile u64 __SCX_RQ_CLK_VALID __weak; +#define SCX_RQ_CLK_VALID __SCX_RQ_CLK_VALID + +const volatile u64 __SCX_RQ_IN_WAKEUP __weak; +#define SCX_RQ_IN_WAKEUP __SCX_RQ_IN_WAKEUP + +const volatile u64 __SCX_RQ_IN_BALANCE __weak; +#define SCX_RQ_IN_BALANCE __SCX_RQ_IN_BALANCE + const volatile u64 __SCX_DSQ_FLAG_BUILTIN __weak; #define SCX_DSQ_FLAG_BUILTIN __SCX_DSQ_FLAG_BUILTIN
diff --git a/tools/sched_ext/include/scx/enums.autogen.h b/tools/sched_ext/include/scx/enums.autogen.h index 88137a1..fedec93 100644 --- a/tools/sched_ext/include/scx/enums.autogen.h +++ b/tools/sched_ext/include/scx/enums.autogen.h
@@ -8,6 +8,14 @@ SCX_ENUM_SET(skel, scx_public_consts, SCX_OPS_NAME_LEN); \ SCX_ENUM_SET(skel, scx_public_consts, SCX_SLICE_DFL); \ SCX_ENUM_SET(skel, scx_public_consts, SCX_SLICE_INF); \ + SCX_ENUM_SET(skel, scx_rq_flags, SCX_RQ_ONLINE); \ + SCX_ENUM_SET(skel, scx_rq_flags, SCX_RQ_CAN_STOP_TICK); \ + SCX_ENUM_SET(skel, scx_rq_flags, SCX_RQ_BAL_PENDING); \ + SCX_ENUM_SET(skel, scx_rq_flags, SCX_RQ_BAL_KEEP); \ + SCX_ENUM_SET(skel, scx_rq_flags, SCX_RQ_BYPASSING); \ + SCX_ENUM_SET(skel, scx_rq_flags, SCX_RQ_CLK_VALID); \ + SCX_ENUM_SET(skel, scx_rq_flags, SCX_RQ_IN_WAKEUP); \ + SCX_ENUM_SET(skel, scx_rq_flags, SCX_RQ_IN_BALANCE); \ SCX_ENUM_SET(skel, scx_dsq_id_flags, SCX_DSQ_FLAG_BUILTIN); \ SCX_ENUM_SET(skel, scx_dsq_id_flags, SCX_DSQ_FLAG_LOCAL_ON); \ SCX_ENUM_SET(skel, scx_dsq_id_flags, SCX_DSQ_INVALID); \
diff --git a/tools/sched_ext/include/scx/enums.h b/tools/sched_ext/include/scx/enums.h index 34cbebe..8e7c915 100644 --- a/tools/sched_ext/include/scx/enums.h +++ b/tools/sched_ext/include/scx/enums.h
@@ -14,7 +14,8 @@ static inline void __ENUM_set(u64 *val, char *type, char *name) bool res; res = __COMPAT_read_enum(type, name, val); - SCX_BUG_ON(!res, "enum not found(%s)", name); + if (!res) + *val = 0; } #define SCX_ENUM_SET(skel, type, name) do { \
diff --git a/tools/testing/cxl/Kbuild b/tools/testing/cxl/Kbuild index 0a6572a..387f3df 100644 --- a/tools/testing/cxl/Kbuild +++ b/tools/testing/cxl/Kbuild
@@ -61,8 +61,11 @@ cxl_core-y += $(CXL_CORE_SRC)/hdm.o cxl_core-y += $(CXL_CORE_SRC)/pmu.o cxl_core-y += $(CXL_CORE_SRC)/cdat.o +cxl_core-y += $(CXL_CORE_SRC)/ras.o +cxl_core-y += $(CXL_CORE_SRC)/acpi.o cxl_core-$(CONFIG_TRACING) += $(CXL_CORE_SRC)/trace.o cxl_core-$(CONFIG_CXL_REGION) += $(CXL_CORE_SRC)/region.o +cxl_core-$(CONFIG_CXL_MCE) += $(CXL_CORE_SRC)/mce.o cxl_core-$(CONFIG_CXL_FEATURES) += $(CXL_CORE_SRC)/features.o cxl_core-y += config_check.o cxl_core-y += cxl_core_test.o
diff --git a/tools/testing/cxl/test/cxl.c b/tools/testing/cxl/test/cxl.c index cc8948f..1c333609 100644 --- a/tools/testing/cxl/test/cxl.c +++ b/tools/testing/cxl/test/cxl.c
@@ -155,7 +155,7 @@ static struct { } cfmws7; struct { struct acpi_cedt_cfmws cfmws; - u32 target[4]; + u32 target[3]; } cfmws8; struct { struct acpi_cedt_cxims cxims; @@ -331,14 +331,14 @@ static struct { .length = sizeof(mock_cedt.cfmws8), }, .interleave_arithmetic = ACPI_CEDT_CFMWS_ARITHMETIC_XOR, - .interleave_ways = 2, - .granularity = 0, + .interleave_ways = 8, + .granularity = 1, .restrictions = ACPI_CEDT_CFMWS_RESTRICT_TYPE3 | ACPI_CEDT_CFMWS_RESTRICT_PMEM, .qtg_id = FAKE_QTG_ID, - .window_size = SZ_256M * 16UL, + .window_size = SZ_512M * 6UL, }, - .target = { 0, 1, 0, 1, }, + .target = { 0, 1, 2, }, }, .cxims0 = { .cxims = { @@ -1000,25 +1000,21 @@ static void mock_cxl_endpoint_parse_cdat(struct cxl_port *port) find_cxl_root(port); struct cxl_memdev *cxlmd = to_cxl_memdev(port->uport_dev); struct cxl_dev_state *cxlds = cxlmd->cxlds; - struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlds); struct access_coordinate ep_c[ACCESS_COORDINATE_MAX]; - struct range pmem_range = { - .start = cxlds->pmem_res.start, - .end = cxlds->pmem_res.end, - }; - struct range ram_range = { - .start = cxlds->ram_res.start, - .end = cxlds->ram_res.end, - }; if (!cxl_root) return; - if (range_len(&ram_range)) - dpa_perf_setup(port, &ram_range, &mds->ram_perf); + for (int i = 0; i < cxlds->nr_partitions; i++) { + struct resource *res = &cxlds->part[i].res; + struct cxl_dpa_perf *perf = &cxlds->part[i].perf; + struct range range = { + .start = res->start, + .end = res->end, + }; - if (range_len(&pmem_range)) - dpa_perf_setup(port, &pmem_range, &mds->pmem_perf); + dpa_perf_setup(port, &range, perf); + } cxl_memdev_update_perf(cxlmd);
diff --git a/tools/testing/cxl/test/mem.c b/tools/testing/cxl/test/mem.c index 9495dbcc..f2957a3 100644 --- a/tools/testing/cxl/test/mem.c +++ b/tools/testing/cxl/test/mem.c
@@ -78,6 +78,10 @@ static struct cxl_cel_entry mock_cel[] = { .effect = CXL_CMD_EFFECT_NONE, }, { + .opcode = cpu_to_le16(CXL_MBOX_OP_SET_SHUTDOWN_STATE), + .effect = POLICY_CHANGE_IMMEDIATE, + }, + { .opcode = cpu_to_le16(CXL_MBOX_OP_GET_POISON), .effect = CXL_CMD_EFFECT_NONE, }, @@ -178,6 +182,7 @@ struct cxl_mockmem_data { u64 timestamp; unsigned long sanitize_timeout; struct vendor_test_feat test_feat; + u8 shutdown_state; }; static struct mock_event_log *event_find_log(struct device *dev, int log_type) @@ -1105,6 +1110,21 @@ static int mock_health_info(struct cxl_mbox_cmd *cmd) return 0; } +static int mock_set_shutdown_state(struct cxl_mockmem_data *mdata, + struct cxl_mbox_cmd *cmd) +{ + struct cxl_mbox_set_shutdown_state_in *ss = cmd->payload_in; + + if (cmd->size_in != sizeof(*ss)) + return -EINVAL; + + if (cmd->size_out != 0) + return -EINVAL; + + mdata->shutdown_state = ss->state; + return 0; +} + static struct mock_poison { struct cxl_dev_state *cxlds; u64 dpa; @@ -1583,6 +1603,9 @@ static int cxl_mock_mbox_send(struct cxl_mailbox *cxl_mbox, case CXL_MBOX_OP_PASSPHRASE_SECURE_ERASE: rc = mock_passphrase_secure_erase(mdata, cmd); break; + case CXL_MBOX_OP_SET_SHUTDOWN_STATE: + rc = mock_set_shutdown_state(mdata, cmd); + break; case CXL_MBOX_OP_GET_POISON: rc = mock_get_poison(cxlds, cmd); break; @@ -1670,6 +1693,7 @@ static int cxl_mock_mem_probe(struct platform_device *pdev) struct cxl_dev_state *cxlds; struct cxl_mockmem_data *mdata; struct cxl_mailbox *cxl_mbox; + struct cxl_dpa_info range_info = { 0 }; int rc; mdata = devm_kzalloc(dev, sizeof(*mdata), GFP_KERNEL); @@ -1709,7 +1733,7 @@ static int cxl_mock_mem_probe(struct platform_device *pdev) mds->event.buf = (struct cxl_get_event_payload *) mdata->event_buf; INIT_DELAYED_WORK(&mds->security.poll_dwork, cxl_mockmem_sanitize_work); - cxlds->serial = pdev->id; + cxlds->serial = pdev->id + 1; if (is_rcd(pdev)) cxlds->rcd = true; @@ -1730,7 +1754,11 @@ static int cxl_mock_mem_probe(struct platform_device *pdev) if (rc) return rc; - rc = cxl_mem_create_range_info(mds); + rc = cxl_mem_dpa_fetch(mds, &range_info); + if (rc) + return rc; + + rc = cxl_dpa_setup(cxlds, &range_info); if (rc) return rc;
diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile index 2694344..c77c8c8 100644 --- a/tools/testing/selftests/Makefile +++ b/tools/testing/selftests/Makefile
@@ -62,6 +62,7 @@ TARGETS += mount_setattr TARGETS += move_mount_set_group TARGETS += mqueue +TARGETS += mseal_system_mappings TARGETS += nci TARGETS += net TARGETS += net/af_unix
diff --git a/tools/testing/selftests/bpf/config.x86_64 b/tools/testing/selftests/bpf/config.x86_64 index 5680bef..5e713ef 100644 --- a/tools/testing/selftests/bpf/config.x86_64 +++ b/tools/testing/selftests/bpf/config.x86_64
@@ -39,7 +39,6 @@ CONFIG_CPU_FREQ_STAT=y CONFIG_CPU_IDLE_GOV_LADDER=y CONFIG_CPUSETS=y -CONFIG_CRC_T10DIF=y CONFIG_CRYPTO_BLAKE2B=y CONFIG_CRYPTO_SEQIV=y CONFIG_CRYPTO_XXHASH=y
diff --git a/tools/testing/selftests/bpf/progs/test_module_attach.c b/tools/testing/selftests/bpf/progs/test_module_attach.c index fb07f57..7f3c233 100644 --- a/tools/testing/selftests/bpf/progs/test_module_attach.c +++ b/tools/testing/selftests/bpf/progs/test_module_attach.c
@@ -117,7 +117,7 @@ int BPF_PROG(handle_fexit_ret, int arg, struct file *ret) bpf_probe_read_kernel(&buf, 8, ret); bpf_probe_read_kernel(&buf, 8, (char *)ret + 256); - *(volatile long long *)ret; + *(volatile int *)ret; *(volatile int *)&ret->f_mode; return 0; }
diff --git a/tools/testing/selftests/bpf/progs/test_subprogs_extable.c b/tools/testing/selftests/bpf/progs/test_subprogs_extable.c index e2a21fb..dcac69f 100644 --- a/tools/testing/selftests/bpf/progs/test_subprogs_extable.c +++ b/tools/testing/selftests/bpf/progs/test_subprogs_extable.c
@@ -21,7 +21,7 @@ static __u64 test_cb(struct bpf_map *map, __u32 *key, __u64 *val, void *data) SEC("fexit/bpf_testmod_return_ptr") int BPF_PROG(handle_fexit_ret_subprogs, int arg, struct file *ret) { - *(volatile long *)ret; + *(volatile int *)ret; *(volatile int *)&ret->f_mode; bpf_for_each_map_elem(&test_array, test_cb, NULL, 0); triggered++; @@ -31,7 +31,7 @@ int BPF_PROG(handle_fexit_ret_subprogs, int arg, struct file *ret) SEC("fexit/bpf_testmod_return_ptr") int BPF_PROG(handle_fexit_ret_subprogs2, int arg, struct file *ret) { - *(volatile long *)ret; + *(volatile int *)ret; *(volatile int *)&ret->f_mode; bpf_for_each_map_elem(&test_array, test_cb, NULL, 0); triggered++; @@ -41,7 +41,7 @@ int BPF_PROG(handle_fexit_ret_subprogs2, int arg, struct file *ret) SEC("fexit/bpf_testmod_return_ptr") int BPF_PROG(handle_fexit_ret_subprogs3, int arg, struct file *ret) { - *(volatile long *)ret; + *(volatile int *)ret; *(volatile int *)&ret->f_mode; bpf_for_each_map_elem(&test_array, test_cb, NULL, 0); triggered++;
diff --git a/tools/testing/selftests/bpf/progs/verifier_bpf_fastcall.c b/tools/testing/selftests/bpf/progs/verifier_bpf_fastcall.c index a9be6ae..c258b07 100644 --- a/tools/testing/selftests/bpf/progs/verifier_bpf_fastcall.c +++ b/tools/testing/selftests/bpf/progs/verifier_bpf_fastcall.c
@@ -12,7 +12,7 @@ SEC("raw_tp") __arch_x86_64 __log_level(4) __msg("stack depth 8") __xlated("4: r5 = 5") -__xlated("5: w0 = ") +__xlated("5: r0 = ") __xlated("6: r0 = &(void __percpu *)(r0)") __xlated("7: r0 = *(u32 *)(r0 +0)") __xlated("8: exit") @@ -704,7 +704,7 @@ SEC("raw_tp") __arch_x86_64 __log_level(4) __msg("stack depth 32+0") __xlated("2: r1 = 1") -__xlated("3: w0 =") +__xlated("3: r0 =") __xlated("4: r0 = &(void __percpu *)(r0)") __xlated("5: r0 = *(u32 *)(r0 +0)") /* bpf_loop params setup */ @@ -753,7 +753,7 @@ __arch_x86_64 __log_level(4) __msg("stack depth 40+0") /* call bpf_get_smp_processor_id */ __xlated("2: r1 = 42") -__xlated("3: w0 =") +__xlated("3: r0 =") __xlated("4: r0 = &(void __percpu *)(r0)") __xlated("5: r0 = *(u32 *)(r0 +0)") /* call bpf_get_prandom_u32 */
diff --git a/tools/testing/selftests/bpf/progs/verifier_private_stack.c b/tools/testing/selftests/bpf/progs/verifier_private_stack.c index b1fbdf1..fc91b41 100644 --- a/tools/testing/selftests/bpf/progs/verifier_private_stack.c +++ b/tools/testing/selftests/bpf/progs/verifier_private_stack.c
@@ -27,7 +27,7 @@ __description("Private stack, single prog") __success __arch_x86_64 __jited(" movabsq $0x{{.*}}, %r9") -__jited(" addq %gs:0x{{.*}}, %r9") +__jited(" addq %gs:{{.*}}, %r9") __jited(" movl $0x2a, %edi") __jited(" movq %rdi, -0x100(%r9)") __naked void private_stack_single_prog(void) @@ -74,7 +74,7 @@ __success __arch_x86_64 /* private stack fp for the main prog */ __jited(" movabsq $0x{{.*}}, %r9") -__jited(" addq %gs:0x{{.*}}, %r9") +__jited(" addq %gs:{{.*}}, %r9") __jited(" movl $0x2a, %edi") __jited(" movq %rdi, -0x200(%r9)") __jited(" pushq %r9") @@ -122,7 +122,7 @@ __jited(" pushq %rbp") __jited(" movq %rsp, %rbp") __jited(" endbr64") __jited(" movabsq $0x{{.*}}, %r9") -__jited(" addq %gs:0x{{.*}}, %r9") +__jited(" addq %gs:{{.*}}, %r9") __jited(" pushq %r9") __jited(" callq") __jited(" popq %r9")
diff --git a/tools/testing/selftests/cgroup/test_cpuset_prs.sh b/tools/testing/selftests/cgroup/test_cpuset_prs.sh index 400a696..a17256d 100755 --- a/tools/testing/selftests/cgroup/test_cpuset_prs.sh +++ b/tools/testing/selftests/cgroup/test_cpuset_prs.sh
@@ -88,22 +88,32 @@ # If isolated CPUs have been reserved at boot time (as shown in # cpuset.cpus.isolated), these isolated CPUs should be outside of CPUs 0-8 # that will be used by this script for testing purpose. If not, some of -# the tests may fail incorrectly. These pre-isolated CPUs should stay in -# an isolated state throughout the testing process for now. +# the tests may fail incorrectly. Wait a bit and retry again just in case +# these isolated CPUs are leftover from previous run and have just been +# cleaned up earlier in this script. +# +# These pre-isolated CPUs should stay in an isolated state throughout the +# testing process for now. # BOOT_ISOLCPUS=$(cat $CGROUP2/cpuset.cpus.isolated) +[[ -n "$BOOT_ISOLCPUS" ]] && { + sleep 0.5 + BOOT_ISOLCPUS=$(cat $CGROUP2/cpuset.cpus.isolated) +} if [[ -n "$BOOT_ISOLCPUS" ]] then [[ $(echo $BOOT_ISOLCPUS | sed -e "s/[,-].*//") -le 8 ]] && skip_test "Pre-isolated CPUs ($BOOT_ISOLCPUS) overlap CPUs to be tested" echo "Pre-isolated CPUs: $BOOT_ISOLCPUS" fi + cleanup() { online_cpus cd $CGROUP2 - rmdir A1/A2/A3 A1/A2 A1 B1 > /dev/null 2>&1 - rmdir test > /dev/null 2>&1 + rmdir A1/A2/A3 A1/A2 A1 B1 test/A1 test/B1 test > /dev/null 2>&1 + rmdir rtest/p1/c11 rtest/p1/c12 rtest/p2/c21 \ + rtest/p2/c22 rtest/p1 rtest/p2 rtest > /dev/null 2>&1 [[ -n "$SCHED_DEBUG" ]] && echo "$SCHED_DEBUG" > /sys/kernel/debug/sched/verbose } @@ -173,14 +183,22 @@ # # Cgroup test hierarchy # -# root -- A1 -- A2 -- A3 -# +- B1 +# root +# | +# +------+------+ +# | | +# A1 B1 +# | +# A2 +# | +# A3 # # P<v> = set cpus.partition (0:member, 1:root, 2:isolated) # C<l> = add cpu-list to cpuset.cpus # X<l> = add cpu-list to cpuset.cpus.exclusive # S<p> = use prefix in subtree_control # T = put a task into cgroup +# CX<l> = add cpu-list to both cpuset.cpus and cpuset.cpus.exclusive # O<c>=<v> = Write <v> to CPU online file of <c> # # ECPUs - effective CPUs of cpusets @@ -207,130 +225,129 @@ " C0-1:P1 . . C2-3 S+:C4-5 . . . 0 A1:4-5" " C0-1 . . C2-3:P1 . . . C2 0 " " C0-1 . . C2-3:P1 . . . C4-5 0 B1:4-5" - "C0-3:P1:S+ C2-3:P1 . . . . . . 0 A1:0-1,A2:2-3" - "C0-3:P1:S+ C2-3:P1 . . C1-3 . . . 0 A1:1,A2:2-3" - "C2-3:P1:S+ C3:P1 . . C3 . . . 0 A1:,A2:3 A1:P1,A2:P1" - "C2-3:P1:S+ C3:P1 . . C3 P0 . . 0 A1:3,A2:3 A1:P1,A2:P0" - "C2-3:P1:S+ C2:P1 . . C2-4 . . . 0 A1:3-4,A2:2" - "C2-3:P1:S+ C3:P1 . . C3 . . C0-2 0 A1:,B1:0-2 A1:P1,A2:P1" - "$SETUP_A123_PARTITIONS . C2-3 . . . 0 A1:,A2:2,A3:3 A1:P1,A2:P1,A3:P1" + "C0-3:P1:S+ C2-3:P1 . . . . . . 0 A1:0-1|A2:2-3|XA2:2-3" + "C0-3:P1:S+ C2-3:P1 . . C1-3 . . . 0 A1:1|A2:2-3|XA2:2-3" + "C2-3:P1:S+ C3:P1 . . C3 . . . 0 A1:|A2:3|XA2:3 A1:P1|A2:P1" + "C2-3:P1:S+ C3:P1 . . C3 P0 . . 0 A1:3|A2:3 A1:P1|A2:P0" + "C2-3:P1:S+ C2:P1 . . C2-4 . . . 0 A1:3-4|A2:2" + "C2-3:P1:S+ C3:P1 . . C3 . . C0-2 0 A1:|B1:0-2 A1:P1|A2:P1" + "$SETUP_A123_PARTITIONS . C2-3 . . . 0 A1:|A2:2|A3:3 A1:P1|A2:P1|A3:P1" # CPU offlining cases: - " C0-1 . . C2-3 S+ C4-5 . O2=0 0 A1:0-1,B1:3" - "C0-3:P1:S+ C2-3:P1 . . O2=0 . . . 0 A1:0-1,A2:3" - "C0-3:P1:S+ C2-3:P1 . . O2=0 O2=1 . . 0 A1:0-1,A2:2-3" - "C0-3:P1:S+ C2-3:P1 . . O1=0 . . . 0 A1:0,A2:2-3" - "C0-3:P1:S+ C2-3:P1 . . O1=0 O1=1 . . 0 A1:0-1,A2:2-3" - "C2-3:P1:S+ C3:P1 . . O3=0 O3=1 . . 0 A1:2,A2:3 A1:P1,A2:P1" - "C2-3:P1:S+ C3:P2 . . O3=0 O3=1 . . 0 A1:2,A2:3 A1:P1,A2:P2" - "C2-3:P1:S+ C3:P1 . . O2=0 O2=1 . . 0 A1:2,A2:3 A1:P1,A2:P1" - "C2-3:P1:S+ C3:P2 . . O2=0 O2=1 . . 0 A1:2,A2:3 A1:P1,A2:P2" - "C2-3:P1:S+ C3:P1 . . O2=0 . . . 0 A1:,A2:3 A1:P1,A2:P1" - "C2-3:P1:S+ C3:P1 . . O3=0 . . . 0 A1:2,A2: A1:P1,A2:P1" - "C2-3:P1:S+ C3:P1 . . T:O2=0 . . . 0 A1:3,A2:3 A1:P1,A2:P-1" - "C2-3:P1:S+ C3:P1 . . . T:O3=0 . . 0 A1:2,A2:2 A1:P1,A2:P-1" - "$SETUP_A123_PARTITIONS . O1=0 . . . 0 A1:,A2:2,A3:3 A1:P1,A2:P1,A3:P1" - "$SETUP_A123_PARTITIONS . O2=0 . . . 0 A1:1,A2:,A3:3 A1:P1,A2:P1,A3:P1" - "$SETUP_A123_PARTITIONS . O3=0 . . . 0 A1:1,A2:2,A3: A1:P1,A2:P1,A3:P1" - "$SETUP_A123_PARTITIONS . T:O1=0 . . . 0 A1:2-3,A2:2-3,A3:3 A1:P1,A2:P-1,A3:P-1" - "$SETUP_A123_PARTITIONS . . T:O2=0 . . 0 A1:1,A2:3,A3:3 A1:P1,A2:P1,A3:P-1" - "$SETUP_A123_PARTITIONS . . . T:O3=0 . 0 A1:1,A2:2,A3:2 A1:P1,A2:P1,A3:P-1" - "$SETUP_A123_PARTITIONS . T:O1=0 O1=1 . . 0 A1:1,A2:2,A3:3 A1:P1,A2:P1,A3:P1" - "$SETUP_A123_PARTITIONS . . T:O2=0 O2=1 . 0 A1:1,A2:2,A3:3 A1:P1,A2:P1,A3:P1" - "$SETUP_A123_PARTITIONS . . . T:O3=0 O3=1 0 A1:1,A2:2,A3:3 A1:P1,A2:P1,A3:P1" - "$SETUP_A123_PARTITIONS . T:O1=0 O2=0 O1=1 . 0 A1:1,A2:,A3:3 A1:P1,A2:P1,A3:P1" - "$SETUP_A123_PARTITIONS . T:O1=0 O2=0 O2=1 . 0 A1:2-3,A2:2-3,A3:3 A1:P1,A2:P-1,A3:P-1" + " C0-1 . . C2-3 S+ C4-5 . O2=0 0 A1:0-1|B1:3" + "C0-3:P1:S+ C2-3:P1 . . O2=0 . . . 0 A1:0-1|A2:3" + "C0-3:P1:S+ C2-3:P1 . . O2=0 O2=1 . . 0 A1:0-1|A2:2-3" + "C0-3:P1:S+ C2-3:P1 . . O1=0 . . . 0 A1:0|A2:2-3" + "C0-3:P1:S+ C2-3:P1 . . O1=0 O1=1 . . 0 A1:0-1|A2:2-3" + "C2-3:P1:S+ C3:P1 . . O3=0 O3=1 . . 0 A1:2|A2:3 A1:P1|A2:P1" + "C2-3:P1:S+ C3:P2 . . O3=0 O3=1 . . 0 A1:2|A2:3 A1:P1|A2:P2" + "C2-3:P1:S+ C3:P1 . . O2=0 O2=1 . . 0 A1:2|A2:3 A1:P1|A2:P1" + "C2-3:P1:S+ C3:P2 . . O2=0 O2=1 . . 0 A1:2|A2:3 A1:P1|A2:P2" + "C2-3:P1:S+ C3:P1 . . O2=0 . . . 0 A1:|A2:3 A1:P1|A2:P1" + "C2-3:P1:S+ C3:P1 . . O3=0 . . . 0 A1:2|A2: A1:P1|A2:P1" + "C2-3:P1:S+ C3:P1 . . T:O2=0 . . . 0 A1:3|A2:3 A1:P1|A2:P-1" + "C2-3:P1:S+ C3:P1 . . . T:O3=0 . . 0 A1:2|A2:2 A1:P1|A2:P-1" + "$SETUP_A123_PARTITIONS . O1=0 . . . 0 A1:|A2:2|A3:3 A1:P1|A2:P1|A3:P1" + "$SETUP_A123_PARTITIONS . O2=0 . . . 0 A1:1|A2:|A3:3 A1:P1|A2:P1|A3:P1" + "$SETUP_A123_PARTITIONS . O3=0 . . . 0 A1:1|A2:2|A3: A1:P1|A2:P1|A3:P1" + "$SETUP_A123_PARTITIONS . T:O1=0 . . . 0 A1:2-3|A2:2-3|A3:3 A1:P1|A2:P-1|A3:P-1" + "$SETUP_A123_PARTITIONS . . T:O2=0 . . 0 A1:1|A2:3|A3:3 A1:P1|A2:P1|A3:P-1" + "$SETUP_A123_PARTITIONS . . . T:O3=0 . 0 A1:1|A2:2|A3:2 A1:P1|A2:P1|A3:P-1" + "$SETUP_A123_PARTITIONS . T:O1=0 O1=1 . . 0 A1:1|A2:2|A3:3 A1:P1|A2:P1|A3:P1" + "$SETUP_A123_PARTITIONS . . T:O2=0 O2=1 . 0 A1:1|A2:2|A3:3 A1:P1|A2:P1|A3:P1" + "$SETUP_A123_PARTITIONS . . . T:O3=0 O3=1 0 A1:1|A2:2|A3:3 A1:P1|A2:P1|A3:P1" + "$SETUP_A123_PARTITIONS . T:O1=0 O2=0 O1=1 . 0 A1:1|A2:|A3:3 A1:P1|A2:P1|A3:P1" + "$SETUP_A123_PARTITIONS . T:O1=0 O2=0 O2=1 . 0 A1:2-3|A2:2-3|A3:3 A1:P1|A2:P-1|A3:P-1" # old-A1 old-A2 old-A3 old-B1 new-A1 new-A2 new-A3 new-B1 fail ECPUs Pstate ISOLCPUS # ------ ------ ------ ------ ------ ------ ------ ------ ---- ----- ------ -------- # # Remote partition and cpuset.cpus.exclusive tests # - " C0-3:S+ C1-3:S+ C2-3 . X2-3 . . . 0 A1:0-3,A2:1-3,A3:2-3,XA1:2-3" - " C0-3:S+ C1-3:S+ C2-3 . X2-3 X2-3:P2 . . 0 A1:0-1,A2:2-3,A3:2-3 A1:P0,A2:P2 2-3" - " C0-3:S+ C1-3:S+ C2-3 . X2-3 X3:P2 . . 0 A1:0-2,A2:3,A3:3 A1:P0,A2:P2 3" - " C0-3:S+ C1-3:S+ C2-3 . X2-3 X2-3 X2-3:P2 . 0 A1:0-1,A2:1,A3:2-3 A1:P0,A3:P2 2-3" - " C0-3:S+ C1-3:S+ C2-3 . X2-3 X2-3 X2-3:P2:C3 . 0 A1:0-1,A2:1,A3:2-3 A1:P0,A3:P2 2-3" - " C0-3:S+ C1-3:S+ C2-3 C2-3 . . . P2 0 A1:0-3,A2:1-3,A3:2-3,B1:2-3 A1:P0,A3:P0,B1:P-2" + " C0-3:S+ C1-3:S+ C2-3 . X2-3 . . . 0 A1:0-3|A2:1-3|A3:2-3|XA1:2-3" + " C0-3:S+ C1-3:S+ C2-3 . X2-3 X2-3:P2 . . 0 A1:0-1|A2:2-3|A3:2-3 A1:P0|A2:P2 2-3" + " C0-3:S+ C1-3:S+ C2-3 . X2-3 X3:P2 . . 0 A1:0-2|A2:3|A3:3 A1:P0|A2:P2 3" + " C0-3:S+ C1-3:S+ C2-3 . X2-3 X2-3 X2-3:P2 . 0 A1:0-1|A2:1|A3:2-3 A1:P0|A3:P2 2-3" + " C0-3:S+ C1-3:S+ C2-3 . X2-3 X2-3 X2-3:P2:C3 . 0 A1:0-1|A2:1|A3:2-3 A1:P0|A3:P2 2-3" + " C0-3:S+ C1-3:S+ C2-3 C2-3 . . . P2 0 A1:0-3|A2:1-3|A3:2-3|B1:2-3 A1:P0|A3:P0|B1:P-2" " C0-3:S+ C1-3:S+ C2-3 C4-5 . . . P2 0 B1:4-5 B1:P2 4-5" - " C0-3:S+ C1-3:S+ C2-3 C4 X2-3 X2-3 X2-3:P2 P2 0 A3:2-3,B1:4 A3:P2,B1:P2 2-4" - " C0-3:S+ C1-3:S+ C2-3 C4 X2-3 X2-3 X2-3:P2:C1-3 P2 0 A3:2-3,B1:4 A3:P2,B1:P2 2-4" - " C0-3:S+ C1-3:S+ C2-3 C4 X1-3 X1-3:P2 P2 . 0 A2:1,A3:2-3 A2:P2,A3:P2 1-3" - " C0-3:S+ C1-3:S+ C2-3 C4 X2-3 X2-3 X2-3:P2 P2:C4-5 0 A3:2-3,B1:4-5 A3:P2,B1:P2 2-5" - " C4:X0-3:S+ X1-3:S+ X2-3 . . P2 . . 0 A1:4,A2:1-3,A3:1-3 A2:P2 1-3" - " C4:X0-3:S+ X1-3:S+ X2-3 . . . P2 . 0 A1:4,A2:4,A3:2-3 A3:P2 2-3" + " C0-3:S+ C1-3:S+ C2-3 C4 X2-3 X2-3 X2-3:P2 P2 0 A3:2-3|B1:4 A3:P2|B1:P2 2-4" + " C0-3:S+ C1-3:S+ C2-3 C4 X2-3 X2-3 X2-3:P2:C1-3 P2 0 A3:2-3|B1:4 A3:P2|B1:P2 2-4" + " C0-3:S+ C1-3:S+ C2-3 C4 X1-3 X1-3:P2 P2 . 0 A2:1|A3:2-3 A2:P2|A3:P2 1-3" + " C0-3:S+ C1-3:S+ C2-3 C4 X2-3 X2-3 X2-3:P2 P2:C4-5 0 A3:2-3|B1:4-5 A3:P2|B1:P2 2-5" + " C4:X0-3:S+ X1-3:S+ X2-3 . . P2 . . 0 A1:4|A2:1-3|A3:1-3 A2:P2 1-3" + " C4:X0-3:S+ X1-3:S+ X2-3 . . . P2 . 0 A1:4|A2:4|A3:2-3 A3:P2 2-3" # Nested remote/local partition tests - " C0-3:S+ C1-3:S+ C2-3 C4-5 X2-3 X2-3:P1 P2 P1 0 A1:0-1,A2:,A3:2-3,B1:4-5 \ - A1:P0,A2:P1,A3:P2,B1:P1 2-3" - " C0-3:S+ C1-3:S+ C2-3 C4 X2-3 X2-3:P1 P2 P1 0 A1:0-1,A2:,A3:2-3,B1:4 \ - A1:P0,A2:P1,A3:P2,B1:P1 2-4,2-3" - " C0-3:S+ C1-3:S+ C2-3 C4 X2-3 X2-3:P1 . P1 0 A1:0-1,A2:2-3,A3:2-3,B1:4 \ - A1:P0,A2:P1,A3:P0,B1:P1" - " C0-3:S+ C1-3:S+ C3 C4 X2-3 X2-3:P1 P2 P1 0 A1:0-1,A2:2,A3:3,B1:4 \ - A1:P0,A2:P1,A3:P2,B1:P1 2-4,3" - " C0-4:S+ C1-4:S+ C2-4 . X2-4 X2-4:P2 X4:P1 . 0 A1:0-1,A2:2-3,A3:4 \ - A1:P0,A2:P2,A3:P1 2-4,2-3" - " C0-4:S+ C1-4:S+ C2-4 . X2-4 X2-4:P2 X3-4:P1 . 0 A1:0-1,A2:2,A3:3-4 \ - A1:P0,A2:P2,A3:P1 2" + " C0-3:S+ C1-3:S+ C2-3 C4-5 X2-3 X2-3:P1 P2 P1 0 A1:0-1|A2:|A3:2-3|B1:4-5 \ + A1:P0|A2:P1|A3:P2|B1:P1 2-3" + " C0-3:S+ C1-3:S+ C2-3 C4 X2-3 X2-3:P1 P2 P1 0 A1:0-1|A2:|A3:2-3|B1:4 \ + A1:P0|A2:P1|A3:P2|B1:P1 2-4|2-3" + " C0-3:S+ C1-3:S+ C2-3 C4 X2-3 X2-3:P1 . P1 0 A1:0-1|A2:2-3|A3:2-3|B1:4 \ + A1:P0|A2:P1|A3:P0|B1:P1" + " C0-3:S+ C1-3:S+ C3 C4 X2-3 X2-3:P1 P2 P1 0 A1:0-1|A2:2|A3:3|B1:4 \ + A1:P0|A2:P1|A3:P2|B1:P1 2-4|3" + " C0-4:S+ C1-4:S+ C2-4 . X2-4 X2-4:P2 X4:P1 . 0 A1:0-1|A2:2-3|A3:4 \ + A1:P0|A2:P2|A3:P1 2-4|2-3" + " C0-4:S+ C1-4:S+ C2-4 . X2-4 X2-4:P2 X3-4:P1 . 0 A1:0-1|A2:2|A3:3-4 \ + A1:P0|A2:P2|A3:P1 2" " C0-4:X2-4:S+ C1-4:X2-4:S+:P2 C2-4:X4:P1 \ - . . X5 . . 0 A1:0-4,A2:1-4,A3:2-4 \ - A1:P0,A2:P-2,A3:P-1" + . . X5 . . 0 A1:0-4|A2:1-4|A3:2-4 \ + A1:P0|A2:P-2|A3:P-1 ." " C0-4:X2-4:S+ C1-4:X2-4:S+:P2 C2-4:X4:P1 \ - . . . X1 . 0 A1:0-1,A2:2-4,A3:2-4 \ - A1:P0,A2:P2,A3:P-1 2-4" + . . . X1 . 0 A1:0-1|A2:2-4|A3:2-4 \ + A1:P0|A2:P2|A3:P-1 2-4" # Remote partition offline tests - " C0-3:S+ C1-3:S+ C2-3 . X2-3 X2-3 X2-3:P2:O2=0 . 0 A1:0-1,A2:1,A3:3 A1:P0,A3:P2 2-3" - " C0-3:S+ C1-3:S+ C2-3 . X2-3 X2-3 X2-3:P2:O2=0 O2=1 0 A1:0-1,A2:1,A3:2-3 A1:P0,A3:P2 2-3" - " C0-3:S+ C1-3:S+ C3 . X2-3 X2-3 P2:O3=0 . 0 A1:0-2,A2:1-2,A3: A1:P0,A3:P2 3" - " C0-3:S+ C1-3:S+ C3 . X2-3 X2-3 T:P2:O3=0 . 0 A1:0-2,A2:1-2,A3:1-2 A1:P0,A3:P-2 3," + " C0-3:S+ C1-3:S+ C2-3 . X2-3 X2-3 X2-3:P2:O2=0 . 0 A1:0-1|A2:1|A3:3 A1:P0|A3:P2 2-3" + " C0-3:S+ C1-3:S+ C2-3 . X2-3 X2-3 X2-3:P2:O2=0 O2=1 0 A1:0-1|A2:1|A3:2-3 A1:P0|A3:P2 2-3" + " C0-3:S+ C1-3:S+ C3 . X2-3 X2-3 P2:O3=0 . 0 A1:0-2|A2:1-2|A3: A1:P0|A3:P2 3" + " C0-3:S+ C1-3:S+ C3 . X2-3 X2-3 T:P2:O3=0 . 0 A1:0-2|A2:1-2|A3:1-2 A1:P0|A3:P-2 3|" # An invalidated remote partition cannot self-recover from hotplug - " C0-3:S+ C1-3:S+ C2 . X2-3 X2-3 T:P2:O2=0 O2=1 0 A1:0-3,A2:1-3,A3:2 A1:P0,A3:P-2" + " C0-3:S+ C1-3:S+ C2 . X2-3 X2-3 T:P2:O2=0 O2=1 0 A1:0-3|A2:1-3|A3:2 A1:P0|A3:P-2 ." # cpus.exclusive.effective clearing test - " C0-3:S+ C1-3:S+ C2 . X2-3:X . . . 0 A1:0-3,A2:1-3,A3:2,XA1:" + " C0-3:S+ C1-3:S+ C2 . X2-3:X . . . 0 A1:0-3|A2:1-3|A3:2|XA1:" # Invalid to valid remote partition transition test - " C0-3:S+ C1-3 . . . X3:P2 . . 0 A1:0-3,A2:1-3,XA2: A2:P-2" + " C0-3:S+ C1-3 . . . X3:P2 . . 0 A1:0-3|A2:1-3|XA2: A2:P-2 ." " C0-3:S+ C1-3:X3:P2 - . . X2-3 P2 . . 0 A1:0-2,A2:3,XA2:3 A2:P2 3" + . . X2-3 P2 . . 0 A1:0-2|A2:3|XA2:3 A2:P2 3" # Invalid to valid local partition direct transition tests - " C1-3:S+:P2 X4:P2 . . . . . . 0 A1:1-3,XA1:1-3,A2:1-3:XA2: A1:P2,A2:P-2 1-3" - " C1-3:S+:P2 X4:P2 . . . X3:P2 . . 0 A1:1-2,XA1:1-3,A2:3:XA2:3 A1:P2,A2:P2 1-3" - " C0-3:P2 . . C4-6 C0-4 . . . 0 A1:0-4,B1:4-6 A1:P-2,B1:P0" - " C0-3:P2 . . C4-6 C0-4:C0-3 . . . 0 A1:0-3,B1:4-6 A1:P2,B1:P0 0-3" - " C0-3:P2 . . C3-5:C4-5 . . . . 0 A1:0-3,B1:4-5 A1:P2,B1:P0 0-3" + " C1-3:S+:P2 X4:P2 . . . . . . 0 A1:1-3|XA1:1-3|A2:1-3:XA2: A1:P2|A2:P-2 1-3" + " C1-3:S+:P2 X4:P2 . . . X3:P2 . . 0 A1:1-2|XA1:1-3|A2:3:XA2:3 A1:P2|A2:P2 1-3" + " C0-3:P2 . . C4-6 C0-4 . . . 0 A1:0-4|B1:4-6 A1:P-2|B1:P0" + " C0-3:P2 . . C4-6 C0-4:C0-3 . . . 0 A1:0-3|B1:4-6 A1:P2|B1:P0 0-3" # Local partition invalidation tests " C0-3:X1-3:S+:P2 C1-3:X2-3:S+:P2 C2-3:X3:P2 \ - . . . . . 0 A1:1,A2:2,A3:3 A1:P2,A2:P2,A3:P2 1-3" + . . . . . 0 A1:1|A2:2|A3:3 A1:P2|A2:P2|A3:P2 1-3" " C0-3:X1-3:S+:P2 C1-3:X2-3:S+:P2 C2-3:X3:P2 \ - . . X4 . . 0 A1:1-3,A2:1-3,A3:2-3,XA2:,XA3: A1:P2,A2:P-2,A3:P-2 1-3" + . . X4 . . 0 A1:1-3|A2:1-3|A3:2-3|XA2:|XA3: A1:P2|A2:P-2|A3:P-2 1-3" " C0-3:X1-3:S+:P2 C1-3:X2-3:S+:P2 C2-3:X3:P2 \ - . . C4:X . . 0 A1:1-3,A2:1-3,A3:2-3,XA2:,XA3: A1:P2,A2:P-2,A3:P-2 1-3" + . . C4:X . . 0 A1:1-3|A2:1-3|A3:2-3|XA2:|XA3: A1:P2|A2:P-2|A3:P-2 1-3" # Local partition CPU change tests - " C0-5:S+:P2 C4-5:S+:P1 . . . C3-5 . . 0 A1:0-2,A2:3-5 A1:P2,A2:P1 0-2" - " C0-5:S+:P2 C4-5:S+:P1 . . C1-5 . . . 0 A1:1-3,A2:4-5 A1:P2,A2:P1 1-3" + " C0-5:S+:P2 C4-5:S+:P1 . . . C3-5 . . 0 A1:0-2|A2:3-5 A1:P2|A2:P1 0-2" + " C0-5:S+:P2 C4-5:S+:P1 . . C1-5 . . . 0 A1:1-3|A2:4-5 A1:P2|A2:P1 1-3" # cpus_allowed/exclusive_cpus update tests " C0-3:X2-3:S+ C1-3:X2-3:S+ C2-3:X2-3 \ - . X:C4 . P2 . 0 A1:4,A2:4,XA2:,XA3:,A3:4 \ - A1:P0,A3:P-2" + . X:C4 . P2 . 0 A1:4|A2:4|XA2:|XA3:|A3:4 \ + A1:P0|A3:P-2 ." " C0-3:X2-3:S+ C1-3:X2-3:S+ C2-3:X2-3 \ - . X1 . P2 . 0 A1:0-3,A2:1-3,XA1:1,XA2:,XA3:,A3:2-3 \ - A1:P0,A3:P-2" + . X1 . P2 . 0 A1:0-3|A2:1-3|XA1:1|XA2:|XA3:|A3:2-3 \ + A1:P0|A3:P-2 ." " C0-3:X2-3:S+ C1-3:X2-3:S+ C2-3:X2-3 \ - . . X3 P2 . 0 A1:0-2,A2:1-2,XA2:3,XA3:3,A3:3 \ - A1:P0,A3:P2 3" + . . X3 P2 . 0 A1:0-2|A2:1-2|XA2:3|XA3:3|A3:3 \ + A1:P0|A3:P2 3" " C0-3:X2-3:S+ C1-3:X2-3:S+ C2-3:X2-3:P2 \ - . . X3 . . 0 A1:0-3,A2:1-3,XA2:3,XA3:3,A3:2-3 \ - A1:P0,A3:P-2" + . . X3 . . 0 A1:0-2|A2:1-2|XA2:3|XA3:3|A3:3|XA3:3 \ + A1:P0|A3:P2 3" " C0-3:X2-3:S+ C1-3:X2-3:S+ C2-3:X2-3:P2 \ - . X4 . . . 0 A1:0-3,A2:1-3,A3:2-3,XA1:4,XA2:,XA3 \ - A1:P0,A3:P-2" + . X4 . . . 0 A1:0-3|A2:1-3|A3:2-3|XA1:4|XA2:|XA3 \ + A1:P0|A3:P-2" # old-A1 old-A2 old-A3 old-B1 new-A1 new-A2 new-A3 new-B1 fail ECPUs Pstate ISOLCPUS # ------ ------ ------ ------ ------ ------ ------ ------ ---- ----- ------ -------- @@ -339,68 +356,127 @@ # # Adding CPUs to partition root that are not in parent's # cpuset.cpus is allowed, but those extra CPUs are ignored. - "C2-3:P1:S+ C3:P1 . . . C2-4 . . 0 A1:,A2:2-3 A1:P1,A2:P1" + "C2-3:P1:S+ C3:P1 . . . C2-4 . . 0 A1:|A2:2-3 A1:P1|A2:P1" # Taking away all CPUs from parent or itself if there are tasks # will make the partition invalid. - "C2-3:P1:S+ C3:P1 . . T C2-3 . . 0 A1:2-3,A2:2-3 A1:P1,A2:P-1" - " C3:P1:S+ C3 . . T P1 . . 0 A1:3,A2:3 A1:P1,A2:P-1" - "$SETUP_A123_PARTITIONS . T:C2-3 . . . 0 A1:2-3,A2:2-3,A3:3 A1:P1,A2:P-1,A3:P-1" - "$SETUP_A123_PARTITIONS . T:C2-3:C1-3 . . . 0 A1:1,A2:2,A3:3 A1:P1,A2:P1,A3:P1" + "C2-3:P1:S+ C3:P1 . . T C2-3 . . 0 A1:2-3|A2:2-3 A1:P1|A2:P-1" + " C3:P1:S+ C3 . . T P1 . . 0 A1:3|A2:3 A1:P1|A2:P-1" + "$SETUP_A123_PARTITIONS . T:C2-3 . . . 0 A1:2-3|A2:2-3|A3:3 A1:P1|A2:P-1|A3:P-1" + "$SETUP_A123_PARTITIONS . T:C2-3:C1-3 . . . 0 A1:1|A2:2|A3:3 A1:P1|A2:P1|A3:P1" # Changing a partition root to member makes child partitions invalid - "C2-3:P1:S+ C3:P1 . . P0 . . . 0 A1:2-3,A2:3 A1:P0,A2:P-1" - "$SETUP_A123_PARTITIONS . C2-3 P0 . . 0 A1:2-3,A2:2-3,A3:3 A1:P1,A2:P0,A3:P-1" + "C2-3:P1:S+ C3:P1 . . P0 . . . 0 A1:2-3|A2:3 A1:P0|A2:P-1" + "$SETUP_A123_PARTITIONS . C2-3 P0 . . 0 A1:2-3|A2:2-3|A3:3 A1:P1|A2:P0|A3:P-1" # cpuset.cpus can contains cpus not in parent's cpuset.cpus as long # as they overlap. - "C2-3:P1:S+ . . . . C3-4:P1 . . 0 A1:2,A2:3 A1:P1,A2:P1" + "C2-3:P1:S+ . . . . C3-4:P1 . . 0 A1:2|A2:3 A1:P1|A2:P1" # Deletion of CPUs distributed to child cgroup is allowed. - "C0-1:P1:S+ C1 . C2-3 C4-5 . . . 0 A1:4-5,A2:4-5" + "C0-1:P1:S+ C1 . C2-3 C4-5 . . . 0 A1:4-5|A2:4-5" # To become a valid partition root, cpuset.cpus must overlap parent's # cpuset.cpus. - " C0-1:P1 . . C2-3 S+ C4-5:P1 . . 0 A1:0-1,A2:0-1 A1:P1,A2:P-1" + " C0-1:P1 . . C2-3 S+ C4-5:P1 . . 0 A1:0-1|A2:0-1 A1:P1|A2:P-1" # Enabling partition with child cpusets is allowed - " C0-1:S+ C1 . C2-3 P1 . . . 0 A1:0-1,A2:1 A1:P1" + " C0-1:S+ C1 . C2-3 P1 . . . 0 A1:0-1|A2:1 A1:P1" - # A partition root with non-partition root parent is invalid, but it + # A partition root with non-partition root parent is invalid| but it # can be made valid if its parent becomes a partition root too. - " C0-1:S+ C1 . C2-3 . P2 . . 0 A1:0-1,A2:1 A1:P0,A2:P-2" - " C0-1:S+ C1:P2 . C2-3 P1 . . . 0 A1:0,A2:1 A1:P1,A2:P2" + " C0-1:S+ C1 . C2-3 . P2 . . 0 A1:0-1|A2:1 A1:P0|A2:P-2" + " C0-1:S+ C1:P2 . C2-3 P1 . . . 0 A1:0|A2:1 A1:P1|A2:P2 0-1|1" # A non-exclusive cpuset.cpus change will invalidate partition and its siblings - " C0-1:P1 . . C2-3 C0-2 . . . 0 A1:0-2,B1:2-3 A1:P-1,B1:P0" - " C0-1:P1 . . P1:C2-3 C0-2 . . . 0 A1:0-2,B1:2-3 A1:P-1,B1:P-1" - " C0-1 . . P1:C2-3 C0-2 . . . 0 A1:0-2,B1:2-3 A1:P0,B1:P-1" + " C0-1:P1 . . C2-3 C0-2 . . . 0 A1:0-2|B1:2-3 A1:P-1|B1:P0" + " C0-1:P1 . . P1:C2-3 C0-2 . . . 0 A1:0-2|B1:2-3 A1:P-1|B1:P-1" + " C0-1 . . P1:C2-3 C0-2 . . . 0 A1:0-2|B1:2-3 A1:P0|B1:P-1" # cpuset.cpus can overlap with sibling cpuset.cpus.exclusive but not subsumed by it - " C0-3 . . C4-5 X5 . . . 0 A1:0-3,B1:4-5" + " C0-3 . . C4-5 X5 . . . 0 A1:0-3|B1:4-5" # Child partition root that try to take all CPUs from parent partition # with tasks will remain invalid. - " C1-4:P1:S+ P1 . . . . . . 0 A1:1-4,A2:1-4 A1:P1,A2:P-1" - " C1-4:P1:S+ P1 . . . C1-4 . . 0 A1,A2:1-4 A1:P1,A2:P1" - " C1-4:P1:S+ P1 . . T C1-4 . . 0 A1:1-4,A2:1-4 A1:P1,A2:P-1" + " C1-4:P1:S+ P1 . . . . . . 0 A1:1-4|A2:1-4 A1:P1|A2:P-1" + " C1-4:P1:S+ P1 . . . C1-4 . . 0 A1|A2:1-4 A1:P1|A2:P1" + " C1-4:P1:S+ P1 . . T C1-4 . . 0 A1:1-4|A2:1-4 A1:P1|A2:P-1" # Clearing of cpuset.cpus with a preset cpuset.cpus.exclusive shouldn't # affect cpuset.cpus.exclusive.effective. - " C1-4:X3:S+ C1:X3 . . . C . . 0 A2:1-4,XA2:3" + " C1-4:X3:S+ C1:X3 . . . C . . 0 A2:1-4|XA2:3" + + # cpuset.cpus can contain CPUs that overlap a sibling cpuset with cpus.exclusive + # but creating a local partition out of it is not allowed. Similarly and change + # in cpuset.cpus of a local partition that overlaps sibling exclusive CPUs will + # invalidate it. + " CX1-4:S+ CX2-4:P2 . C5-6 . . . P1 0 A1:1|A2:2-4|B1:5-6|XB1:5-6 \ + A1:P0|A2:P2:B1:P1 2-4" + " CX1-4:S+ CX2-4:P2 . C3-6 . . . P1 0 A1:1|A2:2-4|B1:5-6 \ + A1:P0|A2:P2:B1:P-1 2-4" + " CX1-4:S+ CX2-4:P2 . C5-6 . . . P1:C3-6 0 A1:1|A2:2-4|B1:5-6 \ + A1:P0|A2:P2:B1:P-1 2-4" # old-A1 old-A2 old-A3 old-B1 new-A1 new-A2 new-A3 new-B1 fail ECPUs Pstate ISOLCPUS # ------ ------ ------ ------ ------ ------ ------ ------ ---- ----- ------ -------- # Failure cases: # A task cannot be added to a partition with no cpu - "C2-3:P1:S+ C3:P1 . . O2=0:T . . . 1 A1:,A2:3 A1:P1,A2:P1" + "C2-3:P1:S+ C3:P1 . . O2=0:T . . . 1 A1:|A2:3 A1:P1|A2:P1" # Changes to cpuset.cpus.exclusive that violate exclusivity rule is rejected - " C0-3 . . C4-5 X0-3 . . X3-5 1 A1:0-3,B1:4-5" + " C0-3 . . C4-5 X0-3 . . X3-5 1 A1:0-3|B1:4-5" # cpuset.cpus cannot be a subset of sibling cpuset.cpus.exclusive - " C0-3 . . C4-5 X3-5 . . . 1 A1:0-3,B1:4-5" + " C0-3 . . C4-5 X3-5 . . . 1 A1:0-3|B1:4-5" +) + +# +# Cpuset controller remote partition test matrix. +# +# Cgroup test hierarchy +# +# root +# | +# rtest (cpuset.cpus.exclusive=1-7) +# | +# +------+------+ +# | | +# p1 p2 +# +--+--+ +--+--+ +# | | | | +# c11 c12 c21 c22 +# +# REMOTE_TEST_MATRIX uses the same notational convention as TEST_MATRIX. +# Only CPUs 1-7 should be used. +# +REMOTE_TEST_MATRIX=( + # old-p1 old-p2 old-c11 old-c12 old-c21 old-c22 + # new-p1 new-p2 new-c11 new-c12 new-c21 new-c22 ECPUs Pstate ISOLCPUS + # ------ ------ ------- ------- ------- ------- ----- ------ -------- + " X1-3:S+ X4-6:S+ X1-2 X3 X4-5 X6 \ + . . P2 P2 P2 P2 c11:1-2|c12:3|c21:4-5|c22:6 \ + c11:P2|c12:P2|c21:P2|c22:P2 1-6" + " CX1-4:S+ . X1-2:P2 C3 . . \ + . . . C3-4 . . p1:3-4|c11:1-2|c12:3-4 \ + p1:P0|c11:P2|c12:P0 1-2" + " CX1-4:S+ . X1-2:P2 . . . \ + X2-4 . . . . . p1:1,3-4|c11:2 \ + p1:P0|c11:P2 2" + " CX1-5:S+ . X1-2:P2 X3-5:P1 . . \ + X2-4 . . . . . p1:1,5|c11:2|c12:3-4 \ + p1:P0|c11:P2|c12:P1 2" + " CX1-4:S+ . X1-2:P2 X3-4:P1 . . \ + . . X2 . . . p1:1|c11:2|c12:3-4 \ + p1:P0|c11:P2|c12:P1 2" + # p1 as member, will get its effective CPUs from its parent rtest + " CX1-4:S+ . X1-2:P2 X3-4:P1 . . \ + . . X1 CX2-4 . . p1:5-7|c11:1|c12:2-4 \ + p1:P0|c11:P2|c12:P1 1" + " CX1-4:S+ X5-6:P1:S+ . . . . \ + . . X1-2:P2 X4-5:P1 . X1-7:P2 p1:3|c11:1-2|c12:4:c22:5-6 \ + p1:P0|p2:P1|c11:P2|c12:P1|c22:P2 \ + 1-2,4-6|1-2,5-6" ) # @@ -453,25 +529,26 @@ PFILE=$CGRP/cpuset.cpus.partition CFILE=$CGRP/cpuset.cpus XFILE=$CGRP/cpuset.cpus.exclusive - S=$(expr substr $CMD 1 1) - if [[ $S = S ]] - then - PREFIX=${CMD#?} + case $CMD in + S*) PREFIX=${CMD#?} COMM="echo ${PREFIX}${CTRL} > $SFILE" eval $COMM $REDIRECT - elif [[ $S = X ]] - then + ;; + X*) CPUS=${CMD#?} COMM="echo $CPUS > $XFILE" eval $COMM $REDIRECT - elif [[ $S = C ]] - then - CPUS=${CMD#?} + ;; + CX*) + CPUS=${CMD#??} + COMM="echo $CPUS > $CFILE; echo $CPUS > $XFILE" + eval $COMM $REDIRECT + ;; + C*) CPUS=${CMD#?} COMM="echo $CPUS > $CFILE" eval $COMM $REDIRECT - elif [[ $S = P ]] - then - VAL=${CMD#?} + ;; + P*) VAL=${CMD#?} case $VAL in 0) VAL=member ;; @@ -486,15 +563,17 @@ esac COMM="echo $VAL > $PFILE" eval $COMM $REDIRECT - elif [[ $S = O ]] - then - VAL=${CMD#?} + ;; + O*) VAL=${CMD#?} write_cpu_online $VAL - elif [[ $S = T ]] - then - COMM="echo 0 > $TFILE" + ;; + T*) COMM="echo 0 > $TFILE" eval $COMM $REDIRECT - fi + ;; + *) echo "Unknown command: $CMD" + exit 1 + ;; + esac RET=$? [[ $RET -ne 0 ]] && { [[ -n "$SHOWERR" ]] && { @@ -532,21 +611,18 @@ } # -# Return 1 if the list of effective cpus isn't the same as the initial list. +# Remove all the test cgroup directories # reset_cgroup_states() { echo 0 > $CGROUP2/cgroup.procs online_cpus - rmdir A1/A2/A3 A1/A2 A1 B1 > /dev/null 2>&1 - pause 0.02 - set_ctrl_state . R- - pause 0.01 + rmdir $RESET_LIST > /dev/null 2>&1 } dump_states() { - for DIR in . A1 A1/A2 A1/A2/A3 B1 + for DIR in $CGROUP_LIST do CPUS=$DIR/cpuset.cpus ECPUS=$DIR/cpuset.cpus.effective @@ -566,17 +642,33 @@ } # +# Set the actual cgroup directory into $CGRP_DIR +# $1 - cgroup name +# +set_cgroup_dir() +{ + CGRP_DIR=$1 + [[ $CGRP_DIR = A2 ]] && CGRP_DIR=A1/A2 + [[ $CGRP_DIR = A3 ]] && CGRP_DIR=A1/A2/A3 + [[ $CGRP_DIR = c11 ]] && CGRP_DIR=p1/c11 + [[ $CGRP_DIR = c12 ]] && CGRP_DIR=p1/c12 + [[ $CGRP_DIR = c21 ]] && CGRP_DIR=p2/c21 + [[ $CGRP_DIR = c22 ]] && CGRP_DIR=p2/c22 +} + +# # Check effective cpus -# $1 - check string, format: <cgroup>:<cpu-list>[,<cgroup>:<cpu-list>]* +# $1 - check string, format: <cgroup>:<cpu-list>[|<cgroup>:<cpu-list>]* # check_effective_cpus() { CHK_STR=$1 - for CHK in $(echo $CHK_STR | sed -e "s/,/ /g") + for CHK in $(echo $CHK_STR | sed -e "s/|/ /g") do set -- $(echo $CHK | sed -e "s/:/ /g") CGRP=$1 - CPUS=$2 + EXPECTED_CPUS=$2 + ACTUAL_CPUS= if [[ $CGRP = X* ]] then CGRP=${CGRP#X} @@ -584,41 +676,39 @@ else FILE=cpuset.cpus.effective fi - [[ $CGRP = A2 ]] && CGRP=A1/A2 - [[ $CGRP = A3 ]] && CGRP=A1/A2/A3 - [[ -e $CGRP/$FILE ]] || return 1 - [[ $CPUS = $(cat $CGRP/$FILE) ]] || return 1 + set_cgroup_dir $CGRP + [[ -e $CGRP_DIR/$FILE ]] || return 1 + ACTUAL_CPUS=$(cat $CGRP_DIR/$FILE) + [[ $EXPECTED_CPUS = $ACTUAL_CPUS ]] || return 1 done } # # Check cgroup states -# $1 - check string, format: <cgroup>:<state>[,<cgroup>:<state>]* +# $1 - check string, format: <cgroup>:<state>[|<cgroup>:<state>]* # check_cgroup_states() { CHK_STR=$1 - for CHK in $(echo $CHK_STR | sed -e "s/,/ /g") + for CHK in $(echo $CHK_STR | sed -e "s/|/ /g") do set -- $(echo $CHK | sed -e "s/:/ /g") CGRP=$1 - CGRP_DIR=$CGRP - STATE=$2 + EXPECTED_STATE=$2 FILE= - EVAL=$(expr substr $STATE 2 2) - [[ $CGRP = A2 ]] && CGRP_DIR=A1/A2 - [[ $CGRP = A3 ]] && CGRP_DIR=A1/A2/A3 + EVAL=$(expr substr $EXPECTED_STATE 2 2) - case $STATE in + set_cgroup_dir $CGRP + case $EXPECTED_STATE in P*) FILE=$CGRP_DIR/cpuset.cpus.partition ;; - *) echo "Unknown state: $STATE!" + *) echo "Unknown state: $EXPECTED_STATE!" exit 1 ;; esac - VAL=$(cat $FILE) + ACTUAL_STATE=$(cat $FILE) - case "$VAL" in + case "$ACTUAL_STATE" in member) VAL=0 ;; root) VAL=1 @@ -642,7 +732,7 @@ [[ $VAL -eq 1 && $VERBOSE -gt 0 ]] && { DOMS=$(cat $CGRP_DIR/cpuset.cpus.effective) [[ -n "$DOMS" ]] && - echo " [$CGRP] sched-domain: $DOMS" > $CONSOLE + echo " [$CGRP_DIR] sched-domain: $DOMS" > $CONSOLE } done return 0 @@ -665,22 +755,22 @@ # check_isolcpus() { - EXPECT_VAL=$1 - ISOLCPUS= + EXPECTED_ISOLCPUS=$1 + ISCPUS=${CGROUP2}/cpuset.cpus.isolated + ISOLCPUS=$(cat $ISCPUS) LASTISOLCPU= SCHED_DOMAINS=/sys/kernel/debug/sched/domains - ISCPUS=${CGROUP2}/cpuset.cpus.isolated - if [[ $EXPECT_VAL = . ]] + if [[ $EXPECTED_ISOLCPUS = . ]] then - EXPECT_VAL= - EXPECT_VAL2= - elif [[ $(expr $EXPECT_VAL : ".*,.*") > 0 ]] + EXPECTED_ISOLCPUS= + EXPECTED_SDOMAIN= + elif [[ $(expr $EXPECTED_ISOLCPUS : ".*|.*") > 0 ]] then - set -- $(echo $EXPECT_VAL | sed -e "s/,/ /g") - EXPECT_VAL=$1 - EXPECT_VAL2=$2 + set -- $(echo $EXPECTED_ISOLCPUS | sed -e "s/|/ /g") + EXPECTED_ISOLCPUS=$2 + EXPECTED_SDOMAIN=$1 else - EXPECT_VAL2=$EXPECT_VAL + EXPECTED_SDOMAIN=$EXPECTED_ISOLCPUS fi # @@ -689,20 +779,21 @@ # to make appending those CPUs easier. # [[ -n "$BOOT_ISOLCPUS" ]] && { - EXPECT_VAL=${EXPECT_VAL:+${EXPECT_VAL},}${BOOT_ISOLCPUS} - EXPECT_VAL2=${EXPECT_VAL2:+${EXPECT_VAL2},}${BOOT_ISOLCPUS} + EXPECTED_ISOLCPUS=${EXPECTED_ISOLCPUS:+${EXPECTED_ISOLCPUS},}${BOOT_ISOLCPUS} + EXPECTED_SDOMAIN=${EXPECTED_SDOMAIN:+${EXPECTED_SDOMAIN},}${BOOT_ISOLCPUS} } # # Check cpuset.cpus.isolated cpumask # - [[ "$EXPECT_VAL2" != "$ISOLCPUS" ]] && { + [[ "$EXPECTED_ISOLCPUS" != "$ISOLCPUS" ]] && { # Take a 50ms pause and try again pause 0.05 ISOLCPUS=$(cat $ISCPUS) } - [[ "$EXPECT_VAL2" != "$ISOLCPUS" ]] && return 1 + [[ "$EXPECTED_ISOLCPUS" != "$ISOLCPUS" ]] && return 1 ISOLCPUS= + EXPECTED_ISOLCPUS=$EXPECTED_SDOMAIN # # Use the sched domain in debugfs to check isolated CPUs, if available @@ -736,7 +827,7 @@ done [[ "$ISOLCPUS" = *- ]] && ISOLCPUS=${ISOLCPUS}$LASTISOLCPU - [[ "$EXPECT_VAL" = "$ISOLCPUS" ]] + [[ "$EXPECTED_SDOMAIN" = "$ISOLCPUS" ]] } test_fail() @@ -774,6 +865,63 @@ } # +# Check state transition test result +# $1 - Test number +# $2 - Expected effective CPU values +# $3 - Expected partition states +# $4 - Expected isolated CPUs +# +check_test_results() +{ + _NR=$1 + _ECPUS="$2" + _PSTATES="$3" + _ISOLCPUS="$4" + + [[ -n "$_ECPUS" && "$_ECPUS" != . ]] && { + check_effective_cpus $_ECPUS + [[ $? -ne 0 ]] && test_fail $_NR "effective CPU" \ + "Cgroup $CGRP: expected $EXPECTED_CPUS, got $ACTUAL_CPUS" + } + + [[ -n "$_PSTATES" && "$_PSTATES" != . ]] && { + check_cgroup_states $_PSTATES + [[ $? -ne 0 ]] && test_fail $_NR states \ + "Cgroup $CGRP: expected $EXPECTED_STATE, got $ACTUAL_STATE" + } + + # Compare the expected isolated CPUs with the actual ones, + # if available + [[ -n "$_ISOLCPUS" ]] && { + check_isolcpus $_ISOLCPUS + [[ $? -ne 0 ]] && { + [[ -n "$BOOT_ISOLCPUS" ]] && _ISOLCPUS=${_ISOLCPUS},${BOOT_ISOLCPUS} + test_fail $_NR "isolated CPU" \ + "Expect $_ISOLCPUS, get $ISOLCPUS instead" + } + } + reset_cgroup_states + # + # Check to see if effective cpu list changes + # + _NEWLIST=$(cat $CGROUP2/cpuset.cpus.effective) + RETRY=0 + while [[ $_NEWLIST != $CPULIST && $RETRY -lt 8 ]] + do + # Wait a bit longer & recheck a few times + pause 0.02 + ((RETRY++)) + _NEWLIST=$(cat $CGROUP2/cpuset.cpus.effective) + done + [[ $_NEWLIST != $CPULIST ]] && { + echo "Effective cpus changed to $_NEWLIST after test $_NR!" + exit 1 + } + null_isolcpus_check + [[ $VERBOSE -gt 0 ]] && echo "Test $I done." +} + +# # Run cpuset state transition test # $1 - test matrix name # @@ -785,6 +933,8 @@ { TEST=$1 CONTROLLER=cpuset + CGROUP_LIST=". A1 A1/A2 A1/A2/A3 B1" + RESET_LIST="A1/A2/A3 A1/A2 A1 B1" I=0 eval CNT="\${#$TEST[@]}" @@ -812,10 +962,11 @@ STATES=${11} ICPUS=${12} - set_ctrl_state_noerr B1 $OLD_B1 set_ctrl_state_noerr A1 $OLD_A1 set_ctrl_state_noerr A1/A2 $OLD_A2 set_ctrl_state_noerr A1/A2/A3 $OLD_A3 + set_ctrl_state_noerr B1 $OLD_B1 + RETVAL=0 set_ctrl_state A1 $NEW_A1; ((RETVAL += $?)) set_ctrl_state A1/A2 $NEW_A2; ((RETVAL += $?)) @@ -824,51 +975,83 @@ [[ $RETVAL -ne $RESULT ]] && test_fail $I result - [[ -n "$ECPUS" && "$ECPUS" != . ]] && { - check_effective_cpus $ECPUS - [[ $? -ne 0 ]] && test_fail $I "effective CPU" - } - - [[ -n "$STATES" && "$STATES" != . ]] && { - check_cgroup_states $STATES - [[ $? -ne 0 ]] && test_fail $I states - } - - # Compare the expected isolated CPUs with the actual ones, - # if available - [[ -n "$ICPUS" ]] && { - check_isolcpus $ICPUS - [[ $? -ne 0 ]] && { - [[ -n "$BOOT_ISOLCPUS" ]] && ICPUS=${ICPUS},${BOOT_ISOLCPUS} - test_fail $I "isolated CPU" \ - "Expect $ICPUS, get $ISOLCPUS instead" - } - } - reset_cgroup_states - # - # Check to see if effective cpu list changes - # - NEWLIST=$(cat cpuset.cpus.effective) - RETRY=0 - while [[ $NEWLIST != $CPULIST && $RETRY -lt 8 ]] - do - # Wait a bit longer & recheck a few times - pause 0.02 - ((RETRY++)) - NEWLIST=$(cat cpuset.cpus.effective) - done - [[ $NEWLIST != $CPULIST ]] && { - echo "Effective cpus changed to $NEWLIST after test $I!" - exit 1 - } - null_isolcpus_check - [[ $VERBOSE -gt 0 ]] && echo "Test $I done." + check_test_results $I "$ECPUS" "$STATES" "$ICPUS" ((I++)) done echo "All $I tests of $TEST PASSED." } # +# Run cpuset remote partition state transition test +# $1 - test matrix name +# +run_remote_state_test() +{ + TEST=$1 + CONTROLLER=cpuset + [[ -d rtest ]] || mkdir rtest + cd rtest + echo +cpuset > cgroup.subtree_control + echo "1-7" > cpuset.cpus + echo "1-7" > cpuset.cpus.exclusive + CGROUP_LIST=".. . p1 p2 p1/c11 p1/c12 p2/c21 p2/c22" + RESET_LIST="p1/c11 p1/c12 p2/c21 p2/c22 p1 p2" + I=0 + eval CNT="\${#$TEST[@]}" + + reset_cgroup_states + console_msg "Running remote partition state transition test ..." + + while [[ $I -lt $CNT ]] + do + echo "Running test $I ..." > $CONSOLE + [[ $VERBOSE -gt 1 ]] && { + echo "" + eval echo \${$TEST[$I]} + } + eval set -- "\${$TEST[$I]}" + OLD_p1=$1 + OLD_p2=$2 + OLD_c11=$3 + OLD_c12=$4 + OLD_c21=$5 + OLD_c22=$6 + NEW_p1=$7 + NEW_p2=$8 + NEW_c11=$9 + NEW_c12=${10} + NEW_c21=${11} + NEW_c22=${12} + ECPUS=${13} + STATES=${14} + ICPUS=${15} + + set_ctrl_state_noerr p1 $OLD_p1 + set_ctrl_state_noerr p2 $OLD_p2 + set_ctrl_state_noerr p1/c11 $OLD_c11 + set_ctrl_state_noerr p1/c12 $OLD_c12 + set_ctrl_state_noerr p2/c21 $OLD_c21 + set_ctrl_state_noerr p2/c22 $OLD_c22 + + RETVAL=0 + set_ctrl_state p1 $NEW_p1 ; ((RETVAL += $?)) + set_ctrl_state p2 $NEW_p2 ; ((RETVAL += $?)) + set_ctrl_state p1/c11 $NEW_c11; ((RETVAL += $?)) + set_ctrl_state p1/c12 $NEW_c12; ((RETVAL += $?)) + set_ctrl_state p2/c21 $NEW_c21; ((RETVAL += $?)) + set_ctrl_state p2/c22 $NEW_c22; ((RETVAL += $?)) + + [[ $RETVAL -ne 0 ]] && test_fail $I result + + check_test_results $I "$ECPUS" "$STATES" "$ICPUS" + ((I++)) + done + cd .. + rmdir rtest + echo "All $I tests of $TEST PASSED." +} + +# # Testing the new "isolated" partition root type # test_isolated() @@ -932,6 +1115,7 @@ echo $$ > $CGROUP2/cgroup.procs [[ -d A1 ]] && rmdir A1 null_isolcpus_check + pause 0.05 } # @@ -997,10 +1181,13 @@ else echo "Inotify test PASSED" fi + echo member > cpuset.cpus.partition + echo "" > cpuset.cpus } trap cleanup 0 2 3 6 run_state_test TEST_MATRIX +run_remote_state_test REMOTE_TEST_MATRIX test_isolated test_inotify echo "All tests PASSED."
diff --git a/tools/testing/selftests/clone3/clone3_selftests.h b/tools/testing/selftests/clone3/clone3_selftests.h index 3d2663f..eeca800 100644 --- a/tools/testing/selftests/clone3/clone3_selftests.h +++ b/tools/testing/selftests/clone3/clone3_selftests.h
@@ -16,7 +16,7 @@ #define ptr_to_u64(ptr) ((__u64)((uintptr_t)(ptr))) #ifndef __NR_clone3 -#define __NR_clone3 -1 +#define __NR_clone3 435 #endif struct __clone_args {
diff --git a/tools/testing/selftests/drivers/net/hds.py b/tools/testing/selftests/drivers/net/hds.py index 7cc74fa..8b7f6ac 100755 --- a/tools/testing/selftests/drivers/net/hds.py +++ b/tools/testing/selftests/drivers/net/hds.py
@@ -20,7 +20,7 @@ def _xdp_onoff(cfg): - prog = cfg.rpath("../../net/lib/xdp_dummy.bpf.o") + prog = cfg.net_lib_dir / "xdp_dummy.bpf.o" ip("link set dev %s xdp obj %s sec xdp" % (cfg.ifname, prog)) ip("link set dev %s xdp off" % cfg.ifname)
diff --git a/tools/testing/selftests/drivers/net/hw/csum.py b/tools/testing/selftests/drivers/net/hw/csum.py index 701aca1..cd23af8 100755 --- a/tools/testing/selftests/drivers/net/hw/csum.py +++ b/tools/testing/selftests/drivers/net/hw/csum.py
@@ -88,7 +88,7 @@ with NetDrvEpEnv(__file__, nsim_test=False) as cfg: check_nic_features(cfg) - cfg.bin_local = cfg.rpath("../../../net/lib/csum") + cfg.bin_local = cfg.net_lib_dir / "csum" cfg.bin_remote = cfg.remote.deploy(cfg.bin_local) cases = []
diff --git a/tools/testing/selftests/drivers/net/hw/iou-zcrx.py b/tools/testing/selftests/drivers/net/hw/iou-zcrx.py index d301d9b..9f271ab 100755 --- a/tools/testing/selftests/drivers/net/hw/iou-zcrx.py +++ b/tools/testing/selftests/drivers/net/hw/iou-zcrx.py
@@ -27,7 +27,7 @@ def test_zcrx(cfg) -> None: - cfg.require_v6() + cfg.require_ipver('6') combined_chans = _get_combined_channels(cfg) if combined_chans < 2: @@ -40,7 +40,7 @@ flow_rule_id = _set_flow_rule(cfg, combined_chans - 1) rx_cmd = f"{cfg.bin_remote} -s -p 9999 -i {cfg.ifname} -q {combined_chans - 1}" - tx_cmd = f"{cfg.bin_local} -c -h {cfg.remote_v6} -p 9999 -l 12840" + tx_cmd = f"{cfg.bin_local} -c -h {cfg.remote_addr_v['6']} -p 9999 -l 12840" with bkg(rx_cmd, host=cfg.remote, exit_wait=True): wait_port_listen(9999, proto="tcp", host=cfg.remote) cmd(tx_cmd) @@ -51,7 +51,7 @@ def test_zcrx_oneshot(cfg) -> None: - cfg.require_v6() + cfg.require_ipver('6') combined_chans = _get_combined_channels(cfg) if combined_chans < 2: @@ -64,7 +64,7 @@ flow_rule_id = _set_flow_rule(cfg, combined_chans - 1) rx_cmd = f"{cfg.bin_remote} -s -p 9999 -i {cfg.ifname} -q {combined_chans - 1} -o 4" - tx_cmd = f"{cfg.bin_local} -c -h {cfg.remote_v6} -p 9999 -l 4096 -z 16384" + tx_cmd = f"{cfg.bin_local} -c -h {cfg.remote_addr_v['6']} -p 9999 -l 4096 -z 16384" with bkg(rx_cmd, host=cfg.remote, exit_wait=True): wait_port_listen(9999, proto="tcp", host=cfg.remote) cmd(tx_cmd)
diff --git a/tools/testing/selftests/drivers/net/hw/irq.py b/tools/testing/selftests/drivers/net/hw/irq.py index 42ab983..0699d6a 100755 --- a/tools/testing/selftests/drivers/net/hw/irq.py +++ b/tools/testing/selftests/drivers/net/hw/irq.py
@@ -69,7 +69,7 @@ def check_reconfig_xdp(cfg) -> None: def reconfig(cfg) -> None: ip(f"link set dev %s xdp obj %s sec xdp" % - (cfg.ifname, cfg.rpath("xdp_dummy.bpf.o"))) + (cfg.ifname, cfg.net_lib_dir / "xdp_dummy.bpf.o")) ip(f"link set dev %s xdp off" % cfg.ifname) _check_reconfig(cfg, reconfig)
diff --git a/tools/testing/selftests/drivers/net/hw/xdp_dummy.bpf.c b/tools/testing/selftests/drivers/net/hw/xdp_dummy.bpf.c deleted file mode 100644 index d988b2e..0000000 --- a/tools/testing/selftests/drivers/net/hw/xdp_dummy.bpf.c +++ /dev/null
@@ -1,13 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 - -#define KBUILD_MODNAME "xdp_dummy" -#include <linux/bpf.h> -#include <bpf/bpf_helpers.h> - -SEC("xdp") -int xdp_dummy_prog(struct xdp_md *ctx) -{ - return XDP_PASS; -} - -char _license[] SEC("license") = "GPL";
diff --git a/tools/testing/selftests/drivers/net/lib/py/env.py b/tools/testing/selftests/drivers/net/lib/py/env.py index fd4d674..ad5ff64 100644 --- a/tools/testing/selftests/drivers/net/lib/py/env.py +++ b/tools/testing/selftests/drivers/net/lib/py/env.py
@@ -13,23 +13,18 @@ class NetDrvEnvBase: """ Base class for a NIC / host envirnoments + + Attributes: + test_dir: Path to the source directory of the test + net_lib_dir: Path to the net/lib directory """ def __init__(self, src_path): - self.src_path = src_path + self.src_path = Path(src_path) + self.test_dir = self.src_path.parent.resolve() + self.net_lib_dir = (Path(__file__).parent / "../../../../net/lib").resolve() + self.env = self._load_env_file() - def rpath(self, path): - """ - Get an absolute path to a file based on a path relative to the directory - containing the test which constructed env. - - For example, if the test.py is in the same directory as - a binary (built from helper.c), the test can use env.rpath("helper") - to get the absolute path to the binary - """ - src_dir = Path(self.src_path).parent.resolve() - return (src_dir / path).as_posix() - def _load_env_file(self): env = os.environ.copy()
diff --git a/tools/testing/selftests/drivers/net/ping.py b/tools/testing/selftests/drivers/net/ping.py index 93120e8..4b68228 100755 --- a/tools/testing/selftests/drivers/net/ping.py +++ b/tools/testing/selftests/drivers/net/ping.py
@@ -56,8 +56,7 @@ return def _set_xdp_generic_sb_on(cfg) -> None: - test_dir = os.path.dirname(os.path.realpath(__file__)) - prog = test_dir + "/../../net/lib/xdp_dummy.bpf.o" + prog = cfg.net_lib_dir / "xdp_dummy.bpf.o" cmd(f"ip link set dev {remote_ifname} mtu 1500", shell=True, host=cfg.remote) cmd(f"ip link set dev {cfg.ifname} mtu 1500 xdpgeneric obj {prog} sec xdp", shell=True) defer(cmd, f"ip link set dev {cfg.ifname} xdpgeneric off") @@ -66,8 +65,7 @@ time.sleep(10) def _set_xdp_generic_mb_on(cfg) -> None: - test_dir = os.path.dirname(os.path.realpath(__file__)) - prog = test_dir + "/../../net/lib/xdp_dummy.bpf.o" + prog = cfg.net_lib_dir / "xdp_dummy.bpf.o" cmd(f"ip link set dev {remote_ifname} mtu 9000", shell=True, host=cfg.remote) defer(ip, f"link set dev {remote_ifname} mtu 1500", host=cfg.remote) ip("link set dev %s mtu 9000 xdpgeneric obj %s sec xdp.frags" % (cfg.ifname, prog)) @@ -77,8 +75,7 @@ time.sleep(10) def _set_xdp_native_sb_on(cfg) -> None: - test_dir = os.path.dirname(os.path.realpath(__file__)) - prog = test_dir + "/../../net/lib/xdp_dummy.bpf.o" + prog = cfg.net_lib_dir / "xdp_dummy.bpf.o" cmd(f"ip link set dev {remote_ifname} mtu 1500", shell=True, host=cfg.remote) cmd(f"ip -j link set dev {cfg.ifname} mtu 1500 xdp obj {prog} sec xdp", shell=True) defer(ip, f"link set dev {cfg.ifname} mtu 1500 xdp off") @@ -95,8 +92,7 @@ time.sleep(10) def _set_xdp_native_mb_on(cfg) -> None: - test_dir = os.path.dirname(os.path.realpath(__file__)) - prog = test_dir + "/../../net/lib/xdp_dummy.bpf.o" + prog = cfg.net_lib_dir / "xdp_dummy.bpf.o" cmd(f"ip link set dev {remote_ifname} mtu 9000", shell=True, host=cfg.remote) defer(ip, f"link set dev {remote_ifname} mtu 1500", host=cfg.remote) try: @@ -109,8 +105,7 @@ time.sleep(10) def _set_xdp_offload_on(cfg) -> None: - test_dir = os.path.dirname(os.path.realpath(__file__)) - prog = test_dir + "/../../net/lib/xdp_dummy.bpf.o" + prog = cfg.net_lib_dir / "xdp_dummy.bpf.o" cmd(f"ip link set dev {cfg.ifname} mtu 1500", shell=True) try: cmd(f"ip link set dev {cfg.ifname} xdpoffload obj {prog} sec xdp", shell=True)
diff --git a/tools/testing/selftests/drivers/net/queues.py b/tools/testing/selftests/drivers/net/queues.py index cae923f..06abd3f 100755 --- a/tools/testing/selftests/drivers/net/queues.py +++ b/tools/testing/selftests/drivers/net/queues.py
@@ -26,13 +26,13 @@ def check_xsk(cfg, nl, xdp_queue_id=0) -> None: # Probe for support - xdp = cmd(cfg.rpath("xdp_helper") + ' - -', fail=False) + xdp = cmd(f'{cfg.test_dir / "xdp_helper"} - -', fail=False) if xdp.ret == 255: raise KsftSkipEx('AF_XDP unsupported') elif xdp.ret > 0: raise KsftFailEx('unable to create AF_XDP socket') - with bkg(f'{cfg.rpath("xdp_helper")} {cfg.ifindex} {xdp_queue_id}', + with bkg(f'{cfg.test_dir / "xdp_helper"} {cfg.ifindex} {xdp_queue_id}', ksft_wait=3): rx = tx = False
diff --git a/tools/testing/selftests/hid/config.common b/tools/testing/selftests/hid/config.common index 45b5570..b1f4085 100644 --- a/tools/testing/selftests/hid/config.common +++ b/tools/testing/selftests/hid/config.common
@@ -39,7 +39,6 @@ CONFIG_CPU_FREQ_STAT=y CONFIG_CPU_IDLE_GOV_LADDER=y CONFIG_CPUSETS=y -CONFIG_CRC_T10DIF=y CONFIG_CRYPTO_BLAKE2B=y CONFIG_CRYPTO_DEV_VIRTIO=y CONFIG_CRYPTO_SEQIV=y
diff --git a/tools/testing/selftests/kvm/riscv/get-reg-list.c b/tools/testing/selftests/kvm/riscv/get-reg-list.c index 8515921..569f2d6 100644 --- a/tools/testing/selftests/kvm/riscv/get-reg-list.c +++ b/tools/testing/selftests/kvm/riscv/get-reg-list.c
@@ -53,8 +53,10 @@ bool filter_reg(__u64 reg) case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_SVNAPOT: case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_SVPBMT: case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_SVVPTC: + case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZAAMO: case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZABHA: case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZACAS: + case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZALRSC: case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZAWRS: case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZBA: case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_ZBB: @@ -434,8 +436,10 @@ static const char *isa_ext_single_id_to_str(__u64 reg_off) KVM_ISA_EXT_ARR(SVNAPOT), KVM_ISA_EXT_ARR(SVPBMT), KVM_ISA_EXT_ARR(SVVPTC), + KVM_ISA_EXT_ARR(ZAAMO), KVM_ISA_EXT_ARR(ZABHA), KVM_ISA_EXT_ARR(ZACAS), + KVM_ISA_EXT_ARR(ZALRSC), KVM_ISA_EXT_ARR(ZAWRS), KVM_ISA_EXT_ARR(ZBA), KVM_ISA_EXT_ARR(ZBB), @@ -974,8 +978,10 @@ KVM_ISA_EXT_SIMPLE_CONFIG(svinval, SVINVAL); KVM_ISA_EXT_SIMPLE_CONFIG(svnapot, SVNAPOT); KVM_ISA_EXT_SIMPLE_CONFIG(svpbmt, SVPBMT); KVM_ISA_EXT_SIMPLE_CONFIG(svvptc, SVVPTC); +KVM_ISA_EXT_SIMPLE_CONFIG(zaamo, ZAAMO); KVM_ISA_EXT_SIMPLE_CONFIG(zabha, ZABHA); KVM_ISA_EXT_SIMPLE_CONFIG(zacas, ZACAS); +KVM_ISA_EXT_SIMPLE_CONFIG(zalrsc, ZALRSC); KVM_ISA_EXT_SIMPLE_CONFIG(zawrs, ZAWRS); KVM_ISA_EXT_SIMPLE_CONFIG(zba, ZBA); KVM_ISA_EXT_SIMPLE_CONFIG(zbb, ZBB); @@ -1045,8 +1051,10 @@ struct vcpu_reg_list *vcpu_configs[] = { &config_svnapot, &config_svpbmt, &config_svvptc, + &config_zaamo, &config_zabha, &config_zacas, + &config_zalrsc, &config_zawrs, &config_zba, &config_zbb,
diff --git a/tools/testing/selftests/mm/va_high_addr_switch.sh b/tools/testing/selftests/mm/va_high_addr_switch.sh index 2c72577..1f92e8c 100755 --- a/tools/testing/selftests/mm/va_high_addr_switch.sh +++ b/tools/testing/selftests/mm/va_high_addr_switch.sh
@@ -41,6 +41,31 @@ fi } +check_supported_ppc64() +{ + local config="/proc/config.gz" + [[ -f "${config}" ]] || config="/boot/config-$(uname -r)" + [[ -f "${config}" ]] || fail "Cannot find kernel config in /proc or /boot" + + local pg_table_levels=$(gzip -dcfq "${config}" | grep PGTABLE_LEVELS | cut -d'=' -f 2) + if [[ "${pg_table_levels}" -lt 5 ]]; then + echo "$0: PGTABLE_LEVELS=${pg_table_levels}, must be >= 5 to run this test" + exit $ksft_skip + fi + + local mmu_support=$(grep -m1 "mmu" /proc/cpuinfo | awk '{print $3}') + if [[ "$mmu_support" != "radix" ]]; then + echo "$0: System does not use Radix MMU, required for 5-level paging" + exit $ksft_skip + fi + + local hugepages_total=$(awk '/HugePages_Total/ {print $2}' /proc/meminfo) + if [[ "${hugepages_total}" -eq 0 ]]; then + echo "$0: HugePages are not enabled, required for some tests" + exit $ksft_skip + fi +} + check_test_requirements() { # The test supports x86_64 and powerpc64. We currently have no useful @@ -50,6 +75,9 @@ "x86_64") check_supported_x86_64 ;; + "ppc64le"|"ppc64") + check_supported_ppc64 + ;; *) return 0 ;;
diff --git a/tools/testing/selftests/mseal_system_mappings/.gitignore b/tools/testing/selftests/mseal_system_mappings/.gitignore new file mode 100644 index 0000000..319c497 --- /dev/null +++ b/tools/testing/selftests/mseal_system_mappings/.gitignore
@@ -0,0 +1,2 @@ +# SPDX-License-Identifier: GPL-2.0-only +sysmap_is_sealed
diff --git a/tools/testing/selftests/mseal_system_mappings/Makefile b/tools/testing/selftests/mseal_system_mappings/Makefile new file mode 100644 index 0000000..2b4504e2 --- /dev/null +++ b/tools/testing/selftests/mseal_system_mappings/Makefile
@@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0-only +CFLAGS += -std=c99 -pthread -Wall $(KHDR_INCLUDES) + +TEST_GEN_PROGS := sysmap_is_sealed + +include ../lib.mk
diff --git a/tools/testing/selftests/mseal_system_mappings/config b/tools/testing/selftests/mseal_system_mappings/config new file mode 100644 index 0000000..675cb9f --- /dev/null +++ b/tools/testing/selftests/mseal_system_mappings/config
@@ -0,0 +1 @@ +CONFIG_MSEAL_SYSTEM_MAPPINGS=y
diff --git a/tools/testing/selftests/mseal_system_mappings/sysmap_is_sealed.c b/tools/testing/selftests/mseal_system_mappings/sysmap_is_sealed.c new file mode 100644 index 0000000..0d2af30 --- /dev/null +++ b/tools/testing/selftests/mseal_system_mappings/sysmap_is_sealed.c
@@ -0,0 +1,119 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * test system mappings are sealed when + * KCONFIG_MSEAL_SYSTEM_MAPPINGS=y + */ + +#define _GNU_SOURCE +#include <stdio.h> +#include <errno.h> +#include <unistd.h> +#include <string.h> +#include <stdbool.h> + +#include "../kselftest.h" +#include "../kselftest_harness.h" + +#define VMFLAGS "VmFlags:" +#define MSEAL_FLAGS "sl" +#define MAX_LINE_LEN 512 + +bool has_mapping(char *name, FILE *maps) +{ + char line[MAX_LINE_LEN]; + + while (fgets(line, sizeof(line), maps)) { + if (strstr(line, name)) + return true; + } + + return false; +} + +bool mapping_is_sealed(char *name, FILE *maps) +{ + char line[MAX_LINE_LEN]; + + while (fgets(line, sizeof(line), maps)) { + if (!strncmp(line, VMFLAGS, strlen(VMFLAGS))) { + if (strstr(line, MSEAL_FLAGS)) + return true; + + return false; + } + } + + return false; +} + +FIXTURE(basic) { + FILE *maps; +}; + +FIXTURE_SETUP(basic) +{ + self->maps = fopen("/proc/self/smaps", "r"); + if (!self->maps) + SKIP(return, "Could not open /proc/self/smap, errno=%d", + errno); +}; + +FIXTURE_TEARDOWN(basic) +{ + if (self->maps) + fclose(self->maps); +}; + +FIXTURE_VARIANT(basic) +{ + char *name; + bool sealed; +}; + +FIXTURE_VARIANT_ADD(basic, vdso) { + .name = "[vdso]", + .sealed = true, +}; + +FIXTURE_VARIANT_ADD(basic, vvar) { + .name = "[vvar]", + .sealed = true, +}; + +FIXTURE_VARIANT_ADD(basic, vvar_vclock) { + .name = "[vvar_vclock]", + .sealed = true, +}; + +FIXTURE_VARIANT_ADD(basic, sigpage) { + .name = "[sigpage]", + .sealed = true, +}; + +FIXTURE_VARIANT_ADD(basic, vectors) { + .name = "[vectors]", + .sealed = true, +}; + +FIXTURE_VARIANT_ADD(basic, uprobes) { + .name = "[uprobes]", + .sealed = true, +}; + +FIXTURE_VARIANT_ADD(basic, stack) { + .name = "[stack]", + .sealed = false, +}; + +TEST_F(basic, check_sealed) +{ + if (!has_mapping(variant->name, self->maps)) { + SKIP(return, "could not find the mapping, %s", + variant->name); + } + + EXPECT_EQ(variant->sealed, + mapping_is_sealed(variant->name, self->maps)); +}; + +TEST_HARNESS_MAIN
diff --git a/tools/testing/selftests/net/amt.sh b/tools/testing/selftests/net/amt.sh index d458b45..3ef209c 100755 --- a/tools/testing/selftests/net/amt.sh +++ b/tools/testing/selftests/net/amt.sh
@@ -194,15 +194,21 @@ send_mcast_torture4() { - ip netns exec "${SOURCE}" bash -c \ - 'cat /dev/urandom | head -c 1G | nc -w 1 -u 239.0.0.1 4001' + for i in `seq 10`; do + ip netns exec "${SOURCE}" bash -c \ + 'cat /dev/urandom | head -c 100M | nc -w 1 -u 239.0.0.1 4001' + echo -n "." + done } send_mcast_torture6() { - ip netns exec "${SOURCE}" bash -c \ - 'cat /dev/urandom | head -c 1G | nc -w 1 -u ff0e::5:6 6001' + for i in `seq 10`; do + ip netns exec "${SOURCE}" bash -c \ + 'cat /dev/urandom | head -c 100M | nc -w 1 -u ff0e::5:6 6001' + echo -n "." + done } check_features() @@ -278,10 +284,12 @@ if [ $err -eq 1 ]; then ERR=1 fi +printf "TEST: %-50s" "IPv4 amt traffic forwarding torture" send_mcast_torture4 -printf "TEST: %-60s [ OK ]\n" "IPv4 amt traffic forwarding torture" +printf " [ OK ]\n" +printf "TEST: %-50s" "IPv6 amt traffic forwarding torture" send_mcast_torture6 -printf "TEST: %-60s [ OK ]\n" "IPv6 amt traffic forwarding torture" +printf " [ OK ]\n" sleep 5 if [ "${ERR}" -eq 1 ]; then echo "Some tests failed." >&2
diff --git a/tools/testing/selftests/net/lib.sh b/tools/testing/selftests/net/lib.sh index 975be4f..701905e 100644 --- a/tools/testing/selftests/net/lib.sh +++ b/tools/testing/selftests/net/lib.sh
@@ -222,6 +222,31 @@ NS_LIST+=("${ns_list[@]}") } +# Create netdevsim with given id and net namespace. +create_netdevsim() { + local id="$1" + local ns="$2" + + modprobe netdevsim &> /dev/null + udevadm settle + + echo "$id 1" | ip netns exec $ns tee /sys/bus/netdevsim/new_device >/dev/null + local dev=$(ip netns exec $ns ls /sys/bus/netdevsim/devices/netdevsim$id/net) + ip -netns $ns link set dev $dev name nsim$id + ip -netns $ns link set dev nsim$id up + + echo nsim$id +} + +# Remove netdevsim with given id. +cleanup_netdevsim() { + local id="$1" + + if [ -d "/sys/bus/netdevsim/devices/netdevsim$id/net" ]; then + echo "$id" > /sys/bus/netdevsim/del_device + fi +} + tc_rule_stats_get() { local dev=$1; shift
diff --git a/tools/testing/selftests/net/mptcp/.gitignore b/tools/testing/selftests/net/mptcp/.gitignore index 49daae7..833279f 100644 --- a/tools/testing/selftests/net/mptcp/.gitignore +++ b/tools/testing/selftests/net/mptcp/.gitignore
@@ -1,5 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-only mptcp_connect +mptcp_diag mptcp_inq mptcp_sockopt pm_nl_ctl
diff --git a/tools/testing/selftests/net/mptcp/mptcp_connect.c b/tools/testing/selftests/net/mptcp/mptcp_connect.c index d240d02..c83a8b4 100644 --- a/tools/testing/selftests/net/mptcp/mptcp_connect.c +++ b/tools/testing/selftests/net/mptcp/mptcp_connect.c
@@ -1270,7 +1270,7 @@ int main_loop(void) if (cfg_input && cfg_sockopt_types.mptfo) { fd_in = open(cfg_input, O_RDONLY); - if (fd < 0) + if (fd_in < 0) xerror("can't open %s:%d", cfg_input, errno); } @@ -1293,13 +1293,13 @@ int main_loop(void) if (cfg_input && !cfg_sockopt_types.mptfo) { fd_in = open(cfg_input, O_RDONLY); - if (fd < 0) + if (fd_in < 0) xerror("can't open %s:%d", cfg_input, errno); } ret = copyfd_io(fd_in, fd, 1, 0, &winfo); if (ret) - return ret; + goto out; if (cfg_truncate > 0) { shutdown(fd, SHUT_WR); @@ -1320,7 +1320,10 @@ int main_loop(void) close(fd); } - return 0; +out: + if (cfg_input) + close(fd_in); + return ret; } int parse_proto(const char *proto)
diff --git a/tools/testing/selftests/net/netns-name.sh b/tools/testing/selftests/net/netns-name.sh index 0be1905..38871bd 100755 --- a/tools/testing/selftests/net/netns-name.sh +++ b/tools/testing/selftests/net/netns-name.sh
@@ -7,10 +7,12 @@ DEV=dummy-dev0 DEV2=dummy-dev1 ALT_NAME=some-alt-name +NSIM_ADDR=2025 RET_CODE=0 cleanup() { + cleanup_netdevsim $NSIM_ADDR cleanup_ns $NS $test_ns } @@ -25,12 +27,15 @@ # # Test basic move without a rename +# Use netdevsim because it has extra asserts for notifiers. # -ip -netns $NS link add name $DEV type dummy || fail -ip -netns $NS link set dev $DEV netns $test_ns || + +nsim=$(create_netdevsim $NSIM_ADDR $NS) +ip -netns $NS link set dev $nsim netns $test_ns || fail "Can't perform a netns move" -ip -netns $test_ns link show dev $DEV >> /dev/null || fail "Device not found after move" -ip -netns $test_ns link del $DEV || fail +ip -netns $test_ns link show dev $nsim >> /dev/null || + fail "Device not found after move" +cleanup_netdevsim $NSIM_ADDR # # Test move with a conflict
diff --git a/tools/testing/selftests/net/rtnetlink.py b/tools/testing/selftests/net/rtnetlink.py index 8095088..e9ad5e8 100755 --- a/tools/testing/selftests/net/rtnetlink.py +++ b/tools/testing/selftests/net/rtnetlink.py
@@ -12,10 +12,10 @@ At least the loopback interface should have this address. """ - addresses = rtnl.getmaddrs({"ifa-family": socket.AF_INET}, dump=True) + addresses = rtnl.getmulticast({"ifa-family": socket.AF_INET}, dump=True) all_host_multicasts = [ - addr for addr in addresses if addr['ifa-multicast'] == IPV4_ALL_HOSTS_MULTICAST + addr for addr in addresses if addr['multicast'] == IPV4_ALL_HOSTS_MULTICAST ] ksft_ge(len(all_host_multicasts), 1,
diff --git a/tools/testing/selftests/net/tcp_ao/self-connect.c b/tools/testing/selftests/net/tcp_ao/self-connect.c index 73b2f22..2c73bea6 100644 --- a/tools/testing/selftests/net/tcp_ao/self-connect.c +++ b/tools/testing/selftests/net/tcp_ao/self-connect.c
@@ -16,6 +16,9 @@ static void __setup_lo_intf(const char *lo_intf, if (link_set_up(lo_intf)) test_error("Failed to bring %s up", lo_intf); + + if (ip_route_add(lo_intf, TEST_FAMILY, local_addr, local_addr)) + test_error("Failed to add a local route %s", lo_intf); } static void setup_lo_intf(const char *lo_intf)
diff --git a/tools/testing/selftests/net/udpgro_bench.sh b/tools/testing/selftests/net/udpgro_bench.sh index c51ea90..815fad8 100755 --- a/tools/testing/selftests/net/udpgro_bench.sh +++ b/tools/testing/selftests/net/udpgro_bench.sh
@@ -7,7 +7,7 @@ readonly PEER_NS="ns-peer-$(mktemp -u XXXXXX)" -BPF_FILE="xdp_dummy.bpf.o" +BPF_FILE="lib/xdp_dummy.bpf.o" cleanup() { local -r jobs="$(jobs -p)"
diff --git a/tools/testing/selftests/net/udpgro_frglist.sh b/tools/testing/selftests/net/udpgro_frglist.sh index 17404f4..5f3d1a1 100755 --- a/tools/testing/selftests/net/udpgro_frglist.sh +++ b/tools/testing/selftests/net/udpgro_frglist.sh
@@ -7,7 +7,7 @@ readonly PEER_NS="ns-peer-$(mktemp -u XXXXXX)" -BPF_FILE="xdp_dummy.bpf.o" +BPF_FILE="lib/xdp_dummy.bpf.o" cleanup() { local -r jobs="$(jobs -p)"
diff --git a/tools/testing/selftests/net/udpgro_fwd.sh b/tools/testing/selftests/net/udpgro_fwd.sh index 550d8eb..f22f6c6 100755 --- a/tools/testing/selftests/net/udpgro_fwd.sh +++ b/tools/testing/selftests/net/udpgro_fwd.sh
@@ -3,7 +3,7 @@ source net_helper.sh -BPF_FILE="xdp_dummy.bpf.o" +BPF_FILE="lib/xdp_dummy.bpf.o" readonly BASE="ns-$(mktemp -u XXXXXX)" readonly SRC=2 readonly DST=1
diff --git a/tools/testing/selftests/net/veth.sh b/tools/testing/selftests/net/veth.sh index 6bb7dfa..9709dd0 100755 --- a/tools/testing/selftests/net/veth.sh +++ b/tools/testing/selftests/net/veth.sh
@@ -1,7 +1,7 @@ #!/bin/sh # SPDX-License-Identifier: GPL-2.0 -BPF_FILE="xdp_dummy.bpf.o" +BPF_FILE="lib/xdp_dummy.bpf.o" readonly STATS="$(mktemp -p /tmp ns-XXXXXX)" readonly BASE=`basename $STATS` readonly SRC=2
diff --git a/tools/testing/selftests/net/xdp_dummy.bpf.c b/tools/testing/selftests/net/xdp_dummy.bpf.c deleted file mode 100644 index d988b2e..0000000 --- a/tools/testing/selftests/net/xdp_dummy.bpf.c +++ /dev/null
@@ -1,13 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 - -#define KBUILD_MODNAME "xdp_dummy" -#include <linux/bpf.h> -#include <bpf/bpf_helpers.h> - -SEC("xdp") -int xdp_dummy_prog(struct xdp_md *ctx) -{ - return XDP_PASS; -} - -char _license[] SEC("license") = "GPL";
diff --git a/tools/testing/selftests/pidfd/pidfd.h b/tools/testing/selftests/pidfd/pidfd.h index cec22aa..55bcf81 100644 --- a/tools/testing/selftests/pidfd/pidfd.h +++ b/tools/testing/selftests/pidfd/pidfd.h
@@ -32,19 +32,19 @@ #endif #ifndef __NR_pidfd_open -#define __NR_pidfd_open -1 +#define __NR_pidfd_open 434 #endif #ifndef __NR_pidfd_send_signal -#define __NR_pidfd_send_signal -1 +#define __NR_pidfd_send_signal 424 #endif #ifndef __NR_clone3 -#define __NR_clone3 -1 +#define __NR_clone3 435 #endif #ifndef __NR_pidfd_getfd -#define __NR_pidfd_getfd -1 +#define __NR_pidfd_getfd 438 #endif #ifndef PIDFD_NONBLOCK
diff --git a/tools/testing/selftests/riscv/hwprobe/cbo.c b/tools/testing/selftests/riscv/hwprobe/cbo.c index a40541b..5e96ef7 100644 --- a/tools/testing/selftests/riscv/hwprobe/cbo.c +++ b/tools/testing/selftests/riscv/hwprobe/cbo.c
@@ -50,6 +50,14 @@ static void cbo_clean(char *base) { cbo_insn(base, 1); } static void cbo_flush(char *base) { cbo_insn(base, 2); } static void cbo_zero(char *base) { cbo_insn(base, 4); } +static void test_no_cbo_inval(void *arg) +{ + ksft_print_msg("Testing cbo.inval instruction remain privileged\n"); + illegal_insn = false; + cbo_inval(&mem[0]); + ksft_test_result(illegal_insn, "No cbo.inval\n"); +} + static void test_no_zicbom(void *arg) { ksft_print_msg("Testing Zicbom instructions remain privileged\n"); @@ -61,10 +69,6 @@ static void test_no_zicbom(void *arg) illegal_insn = false; cbo_flush(&mem[0]); ksft_test_result(illegal_insn, "No cbo.flush\n"); - - illegal_insn = false; - cbo_inval(&mem[0]); - ksft_test_result(illegal_insn, "No cbo.inval\n"); } static void test_no_zicboz(void *arg) @@ -81,6 +85,30 @@ static bool is_power_of_2(__u64 n) return n != 0 && (n & (n - 1)) == 0; } +static void test_zicbom(void *arg) +{ + struct riscv_hwprobe pair = { + .key = RISCV_HWPROBE_KEY_ZICBOM_BLOCK_SIZE, + }; + cpu_set_t *cpus = (cpu_set_t *)arg; + __u64 block_size; + long rc; + + rc = riscv_hwprobe(&pair, 1, sizeof(cpu_set_t), (unsigned long *)cpus, 0); + block_size = pair.value; + ksft_test_result(rc == 0 && pair.key == RISCV_HWPROBE_KEY_ZICBOM_BLOCK_SIZE && + is_power_of_2(block_size), "Zicbom block size\n"); + ksft_print_msg("Zicbom block size: %llu\n", block_size); + + illegal_insn = false; + cbo_clean(&mem[block_size]); + ksft_test_result(!illegal_insn, "cbo.clean\n"); + + illegal_insn = false; + cbo_flush(&mem[block_size]); + ksft_test_result(!illegal_insn, "cbo.flush\n"); +} + static void test_zicboz(void *arg) { struct riscv_hwprobe pair = { @@ -129,7 +157,7 @@ static void test_zicboz(void *arg) ksft_test_result_pass("cbo.zero check\n"); } -static void check_no_zicboz_cpus(cpu_set_t *cpus) +static void check_no_zicbo_cpus(cpu_set_t *cpus, __u64 cbo) { struct riscv_hwprobe pair = { .key = RISCV_HWPROBE_KEY_IMA_EXT_0, @@ -137,6 +165,7 @@ static void check_no_zicboz_cpus(cpu_set_t *cpus) cpu_set_t one_cpu; int i = 0, c = 0; long rc; + char *cbostr; while (i++ < CPU_COUNT(cpus)) { while (!CPU_ISSET(c, cpus)) @@ -148,10 +177,13 @@ static void check_no_zicboz_cpus(cpu_set_t *cpus) rc = riscv_hwprobe(&pair, 1, sizeof(cpu_set_t), (unsigned long *)&one_cpu, 0); assert(rc == 0 && pair.key == RISCV_HWPROBE_KEY_IMA_EXT_0); - if (pair.value & RISCV_HWPROBE_EXT_ZICBOZ) - ksft_exit_fail_msg("Zicboz is only present on a subset of harts.\n" - "Use taskset to select a set of harts where Zicboz\n" - "presence (present or not) is consistent for each hart\n"); + cbostr = cbo == RISCV_HWPROBE_EXT_ZICBOZ ? "Zicboz" : "Zicbom"; + + if (pair.value & cbo) + ksft_exit_fail_msg("%s is only present on a subset of harts.\n" + "Use taskset to select a set of harts where %s\n" + "presence (present or not) is consistent for each hart\n", + cbostr, cbostr); ++c; } } @@ -159,7 +191,9 @@ static void check_no_zicboz_cpus(cpu_set_t *cpus) enum { TEST_ZICBOZ, TEST_NO_ZICBOZ, + TEST_ZICBOM, TEST_NO_ZICBOM, + TEST_NO_CBO_INVAL, }; static struct test_info { @@ -169,7 +203,9 @@ static struct test_info { } tests[] = { [TEST_ZICBOZ] = { .nr_tests = 3, test_zicboz }, [TEST_NO_ZICBOZ] = { .nr_tests = 1, test_no_zicboz }, - [TEST_NO_ZICBOM] = { .nr_tests = 3, test_no_zicbom }, + [TEST_ZICBOM] = { .nr_tests = 3, test_zicbom }, + [TEST_NO_ZICBOM] = { .nr_tests = 2, test_no_zicbom }, + [TEST_NO_CBO_INVAL] = { .nr_tests = 1, test_no_cbo_inval }, }; int main(int argc, char **argv) @@ -189,6 +225,7 @@ int main(int argc, char **argv) assert(rc == 0); tests[TEST_NO_ZICBOZ].enabled = true; tests[TEST_NO_ZICBOM].enabled = true; + tests[TEST_NO_CBO_INVAL].enabled = true; } rc = sched_getaffinity(0, sizeof(cpu_set_t), &cpus); @@ -206,7 +243,14 @@ int main(int argc, char **argv) tests[TEST_ZICBOZ].enabled = true; tests[TEST_NO_ZICBOZ].enabled = false; } else { - check_no_zicboz_cpus(&cpus); + check_no_zicbo_cpus(&cpus, RISCV_HWPROBE_EXT_ZICBOZ); + } + + if (pair.value & RISCV_HWPROBE_EXT_ZICBOM) { + tests[TEST_ZICBOM].enabled = true; + tests[TEST_NO_ZICBOM].enabled = false; + } else { + check_no_zicbo_cpus(&cpus, RISCV_HWPROBE_EXT_ZICBOM); } for (i = 0; i < ARRAY_SIZE(tests); ++i)
diff --git a/tools/testing/selftests/riscv/vector/v_exec_initval_nolibc.c b/tools/testing/selftests/riscv/vector/v_exec_initval_nolibc.c index 35c0812e..4dde05e 100644 --- a/tools/testing/selftests/riscv/vector/v_exec_initval_nolibc.c +++ b/tools/testing/selftests/riscv/vector/v_exec_initval_nolibc.c
@@ -6,7 +6,7 @@ * the values. To further ensure consistency, this file is compiled without * libc and without auto-vectorization. * - * To be "clean" all values must be either all ones or all zeroes. + * To be "clean" all values must be all zeroes. */ #define __stringify_1(x...) #x @@ -14,9 +14,8 @@ int main(int argc, char **argv) { - char prev_value = 0, value; + char value = 0; unsigned long vl; - int first = 1; if (argc > 2 && strcmp(argv[2], "x")) asm volatile ( @@ -44,14 +43,11 @@ int main(int argc, char **argv) "vsrl.vi " __stringify(register) ", " __stringify(register) ", 8\n\t" \ ".option pop\n\t" \ : "=r" (value)); \ - if (first) { \ - first = 0; \ - } else if (value != prev_value || !(value == 0x00 || value == 0xff)) { \ + if (value != 0x00) { \ printf("Register " __stringify(register) \ " values not clean! value: %u\n", value); \ exit(-1); \ } \ - prev_value = value; \ } \ })
diff --git a/tools/testing/selftests/rtc/.gitignore b/tools/testing/selftests/rtc/.gitignore index fb2d533aa..a2afe79 100644 --- a/tools/testing/selftests/rtc/.gitignore +++ b/tools/testing/selftests/rtc/.gitignore
@@ -1,3 +1,2 @@ # SPDX-License-Identifier: GPL-2.0-only rtctest -setdate
diff --git a/tools/testing/selftests/rtc/Makefile b/tools/testing/selftests/rtc/Makefile index 9dbb395..547c244 100644 --- a/tools/testing/selftests/rtc/Makefile +++ b/tools/testing/selftests/rtc/Makefile
@@ -4,8 +4,6 @@ TEST_GEN_PROGS = rtctest -TEST_GEN_PROGS_EXTENDED = setdate - TEST_FILES := settings include ../lib.mk
diff --git a/tools/testing/selftests/rtc/rtctest.c b/tools/testing/selftests/rtc/rtctest.c index e103097..be175c0 100644 --- a/tools/testing/selftests/rtc/rtctest.c +++ b/tools/testing/selftests/rtc/rtctest.c
@@ -29,6 +29,7 @@ enum rtc_alarm_state { RTC_ALARM_UNKNOWN, RTC_ALARM_ENABLED, RTC_ALARM_DISABLED, + RTC_ALARM_RES_MINUTE, }; FIXTURE(rtc) { @@ -88,7 +89,7 @@ static void nanosleep_with_retries(long ns) } } -static enum rtc_alarm_state get_rtc_alarm_state(int fd) +static enum rtc_alarm_state get_rtc_alarm_state(int fd, int need_seconds) { struct rtc_param param = { 0 }; int rc; @@ -103,6 +104,10 @@ static enum rtc_alarm_state get_rtc_alarm_state(int fd) if ((param.uvalue & _BITUL(RTC_FEATURE_ALARM)) == 0) return RTC_ALARM_DISABLED; + /* Check if alarm has desired granularity */ + if (need_seconds && (param.uvalue & _BITUL(RTC_FEATURE_ALARM_RES_MINUTE))) + return RTC_ALARM_RES_MINUTE; + return RTC_ALARM_ENABLED; } @@ -227,9 +232,11 @@ TEST_F(rtc, alarm_alm_set) { SKIP(return, "Skipping test since %s does not exist", rtc_file); ASSERT_NE(-1, self->fd); - alarm_state = get_rtc_alarm_state(self->fd); + alarm_state = get_rtc_alarm_state(self->fd, 1); if (alarm_state == RTC_ALARM_DISABLED) SKIP(return, "Skipping test since alarms are not supported."); + if (alarm_state == RTC_ALARM_RES_MINUTE) + SKIP(return, "Skipping test since alarms has only minute granularity."); rc = ioctl(self->fd, RTC_RD_TIME, &tm); ASSERT_NE(-1, rc); @@ -295,9 +302,11 @@ TEST_F(rtc, alarm_wkalm_set) { SKIP(return, "Skipping test since %s does not exist", rtc_file); ASSERT_NE(-1, self->fd); - alarm_state = get_rtc_alarm_state(self->fd); + alarm_state = get_rtc_alarm_state(self->fd, 1); if (alarm_state == RTC_ALARM_DISABLED) SKIP(return, "Skipping test since alarms are not supported."); + if (alarm_state == RTC_ALARM_RES_MINUTE) + SKIP(return, "Skipping test since alarms has only minute granularity."); rc = ioctl(self->fd, RTC_RD_TIME, &alarm.time); ASSERT_NE(-1, rc); @@ -357,7 +366,7 @@ TEST_F_TIMEOUT(rtc, alarm_alm_set_minute, 65) { SKIP(return, "Skipping test since %s does not exist", rtc_file); ASSERT_NE(-1, self->fd); - alarm_state = get_rtc_alarm_state(self->fd); + alarm_state = get_rtc_alarm_state(self->fd, 0); if (alarm_state == RTC_ALARM_DISABLED) SKIP(return, "Skipping test since alarms are not supported."); @@ -425,7 +434,7 @@ TEST_F_TIMEOUT(rtc, alarm_wkalm_set_minute, 65) { SKIP(return, "Skipping test since %s does not exist", rtc_file); ASSERT_NE(-1, self->fd); - alarm_state = get_rtc_alarm_state(self->fd); + alarm_state = get_rtc_alarm_state(self->fd, 0); if (alarm_state == RTC_ALARM_DISABLED) SKIP(return, "Skipping test since alarms are not supported.");
diff --git a/tools/testing/selftests/rtc/setdate.c b/tools/testing/selftests/rtc/setdate.c deleted file mode 100644 index b303890b..0000000 --- a/tools/testing/selftests/rtc/setdate.c +++ /dev/null
@@ -1,77 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* Real Time Clock Driver Test - * by: Benjamin Gaignard (benjamin.gaignard@linaro.org) - * - * To build - * gcc rtctest_setdate.c -o rtctest_setdate - */ - -#include <stdio.h> -#include <linux/rtc.h> -#include <sys/ioctl.h> -#include <sys/time.h> -#include <sys/types.h> -#include <fcntl.h> -#include <unistd.h> -#include <stdlib.h> -#include <errno.h> - -static const char default_time[] = "00:00:00"; - -int main(int argc, char **argv) -{ - int fd, retval; - struct rtc_time new, current; - const char *rtc, *date; - const char *time = default_time; - - switch (argc) { - case 4: - time = argv[3]; - /* FALLTHROUGH */ - case 3: - date = argv[2]; - rtc = argv[1]; - break; - default: - fprintf(stderr, "usage: rtctest_setdate <rtcdev> <DD-MM-YYYY> [HH:MM:SS]\n"); - return 1; - } - - fd = open(rtc, O_RDONLY); - if (fd == -1) { - perror(rtc); - exit(errno); - } - - sscanf(date, "%d-%d-%d", &new.tm_mday, &new.tm_mon, &new.tm_year); - new.tm_mon -= 1; - new.tm_year -= 1900; - sscanf(time, "%d:%d:%d", &new.tm_hour, &new.tm_min, &new.tm_sec); - - fprintf(stderr, "Test will set RTC date/time to %d-%d-%d, %02d:%02d:%02d.\n", - new.tm_mday, new.tm_mon + 1, new.tm_year + 1900, - new.tm_hour, new.tm_min, new.tm_sec); - - /* Write the new date in RTC */ - retval = ioctl(fd, RTC_SET_TIME, &new); - if (retval == -1) { - perror("RTC_SET_TIME ioctl"); - close(fd); - exit(errno); - } - - /* Read back */ - retval = ioctl(fd, RTC_RD_TIME, ¤t); - if (retval == -1) { - perror("RTC_RD_TIME ioctl"); - exit(errno); - } - - fprintf(stderr, "\n\nCurrent RTC date/time is %d-%d-%d, %02d:%02d:%02d.\n", - current.tm_mday, current.tm_mon + 1, current.tm_year + 1900, - current.tm_hour, current.tm_min, current.tm_sec); - - close(fd); - return 0; -}
diff --git a/tools/testing/selftests/tc-testing/tc-tests/actions/nat.json b/tools/testing/selftests/tc-testing/tc-tests/actions/nat.json index ee27929..4f21aeb 100644 --- a/tools/testing/selftests/tc-testing/tc-tests/actions/nat.json +++ b/tools/testing/selftests/tc-testing/tc-tests/actions/nat.json
@@ -305,7 +305,7 @@ "cmdUnderTest": "$TC actions add action nat ingress default 10.10.10.1 index 12", "expExitCode": "0", "verifyCmd": "$TC actions get action nat index 12", - "matchPattern": "action order [0-9]+: nat ingress 0.0.0.0/32 10.10.10.1 pass.*index 12 ref", + "matchPattern": "action order [0-9]+: nat ingress 0.0.0.0/0 10.10.10.1 pass.*index 12 ref", "matchCount": "1", "teardown": [ "$TC actions flush action nat" @@ -332,7 +332,7 @@ "cmdUnderTest": "$TC actions add action nat ingress any 10.10.10.1 index 12", "expExitCode": "0", "verifyCmd": "$TC actions get action nat index 12", - "matchPattern": "action order [0-9]+: nat ingress 0.0.0.0/32 10.10.10.1 pass.*index 12 ref", + "matchPattern": "action order [0-9]+: nat ingress 0.0.0.0/0 10.10.10.1 pass.*index 12 ref", "matchCount": "1", "teardown": [ "$TC actions flush action nat" @@ -359,7 +359,7 @@ "cmdUnderTest": "$TC actions add action nat ingress all 10.10.10.1 index 12", "expExitCode": "0", "verifyCmd": "$TC actions get action nat index 12", - "matchPattern": "action order [0-9]+: nat ingress 0.0.0.0/32 10.10.10.1 pass.*index 12 ref", + "matchPattern": "action order [0-9]+: nat ingress 0.0.0.0/0 10.10.10.1 pass.*index 12 ref", "matchCount": "1", "teardown": [ "$TC actions flush action nat" @@ -548,7 +548,7 @@ "cmdUnderTest": "$TC actions add action nat egress default 20.20.20.1 pipe index 10", "expExitCode": "0", "verifyCmd": "$TC actions get action nat index 10", - "matchPattern": "action order [0-9]+: nat egress 0.0.0.0/32 20.20.20.1 pipe.*index 10 ref", + "matchPattern": "action order [0-9]+: nat egress 0.0.0.0/0 20.20.20.1 pipe.*index 10 ref", "matchCount": "1", "teardown": [ "$TC actions flush action nat" @@ -575,7 +575,7 @@ "cmdUnderTest": "$TC actions add action nat egress any 20.20.20.1 pipe index 10", "expExitCode": "0", "verifyCmd": "$TC actions get action nat index 10", - "matchPattern": "action order [0-9]+: nat egress 0.0.0.0/32 20.20.20.1 pipe.*index 10 ref", + "matchPattern": "action order [0-9]+: nat egress 0.0.0.0/0 20.20.20.1 pipe.*index 10 ref", "matchCount": "1", "teardown": [ "$TC actions flush action nat" @@ -602,7 +602,7 @@ "cmdUnderTest": "$TC actions add action nat egress all 20.20.20.1 pipe index 10", "expExitCode": "0", "verifyCmd": "$TC actions get action nat index 10", - "matchPattern": "action order [0-9]+: nat egress 0.0.0.0/32 20.20.20.1 pipe.*index 10 ref", + "matchPattern": "action order [0-9]+: nat egress 0.0.0.0/0 20.20.20.1 pipe.*index 10 ref", "matchCount": "1", "teardown": [ "$TC actions flush action nat" @@ -629,7 +629,7 @@ "cmdUnderTest": "$TC actions add action nat egress all 20.20.20.1 pipe index 10 cookie aa1bc2d3eeff112233445566778800a1", "expExitCode": "0", "verifyCmd": "$TC actions get action nat index 10", - "matchPattern": "action order [0-9]+: nat egress 0.0.0.0/32 20.20.20.1 pipe.*index 10 ref.*cookie aa1bc2d3eeff112233445566778800a1", + "matchPattern": "action order [0-9]+: nat egress 0.0.0.0/0 20.20.20.1 pipe.*index 10 ref.*cookie aa1bc2d3eeff112233445566778800a1", "matchCount": "1", "teardown": [ "$TC actions flush action nat"
diff --git a/tools/testing/selftests/tc-testing/tc-tests/infra/qdiscs.json b/tools/testing/selftests/tc-testing/tc-tests/infra/qdiscs.json index 9044ac0..25454fd 100644 --- a/tools/testing/selftests/tc-testing/tc-tests/infra/qdiscs.json +++ b/tools/testing/selftests/tc-testing/tc-tests/infra/qdiscs.json
@@ -126,5 +126,37 @@ "$TC qdisc del dev $DUMMY root handle 1: drr", "$IP addr del 10.10.10.10/24 dev $DUMMY" ] - } + }, + { + "id": "c024", + "name": "Test TBF with SKBPRIO - catch qlen corner cases", + "category": [ + "qdisc", + "tbf", + "skbprio" + ], + "plugins": { + "requires": "nsPlugin" + }, + "setup": [ + "$IP link set dev $DUMMY up || true", + "$IP addr add 10.10.10.10/24 dev $DUMMY || true", + "$TC qdisc add dev $DUMMY handle 1: root tbf rate 100bit burst 2000 limit 1000", + "$TC qdisc add dev $DUMMY parent 1: handle 10: skbprio limit 1", + "ping -c 1 -W 0.1 -Q 0x00 -s 1400 -I $DUMMY 10.10.10.1 > /dev/null || true", + "ping -c 1 -W 0.1 -Q 0x1c -s 1400 -I $DUMMY 10.10.10.1 > /dev/null || true", + "ping -c 1 -W 0.1 -Q 0x00 -s 1400 -I $DUMMY 10.10.10.1 > /dev/null || true", + "ping -c 1 -W 0.1 -Q 0x1c -s 1400 -I $DUMMY 10.10.10.1 > /dev/null || true", + "sleep 0.5" + ], + "cmdUnderTest": "$TC -s qdisc show dev $DUMMY", + "expExitCode": "0", + "verifyCmd": "$TC -s qdisc show dev $DUMMY | grep -A 5 'qdisc skbprio'", + "matchPattern": "dropped [1-9][0-9]*", + "matchCount": "1", + "teardown": [ + "$TC qdisc del dev $DUMMY handle 1: root", + "$IP addr del 10.10.10.10/24 dev $DUMMY || true" + ] + } ]
diff --git a/tools/testing/selftests/ublk/Makefile b/tools/testing/selftests/ublk/Makefile index 7817afe..c7781ef 100644 --- a/tools/testing/selftests/ublk/Makefile +++ b/tools/testing/selftests/ublk/Makefile
@@ -4,6 +4,8 @@ LDLIBS += -lpthread -lm -luring TEST_PROGS := test_generic_01.sh +TEST_PROGS += test_generic_02.sh +TEST_PROGS += test_generic_03.sh TEST_PROGS += test_null_01.sh TEST_PROGS += test_null_02.sh @@ -11,8 +13,11 @@ TEST_PROGS += test_loop_02.sh TEST_PROGS += test_loop_03.sh TEST_PROGS += test_loop_04.sh +TEST_PROGS += test_loop_05.sh TEST_PROGS += test_stripe_01.sh TEST_PROGS += test_stripe_02.sh +TEST_PROGS += test_stripe_03.sh +TEST_PROGS += test_stripe_04.sh TEST_PROGS += test_stress_01.sh TEST_PROGS += test_stress_02.sh
diff --git a/tools/testing/selftests/ublk/kublk.c b/tools/testing/selftests/ublk/kublk.c index 05147b5..91c282b 100644 --- a/tools/testing/selftests/ublk/kublk.c +++ b/tools/testing/selftests/ublk/kublk.c
@@ -99,7 +99,7 @@ static int __ublk_ctrl_cmd(struct ublk_dev *dev, static int ublk_ctrl_stop_dev(struct ublk_dev *dev) { struct ublk_ctrl_cmd_data data = { - .cmd_op = UBLK_CMD_STOP_DEV, + .cmd_op = UBLK_U_CMD_STOP_DEV, }; return __ublk_ctrl_cmd(dev, &data); @@ -169,7 +169,7 @@ static int ublk_ctrl_get_params(struct ublk_dev *dev, struct ublk_params *params) { struct ublk_ctrl_cmd_data data = { - .cmd_op = UBLK_CMD_GET_PARAMS, + .cmd_op = UBLK_U_CMD_GET_PARAMS, .flags = CTRL_CMD_HAS_BUF, .addr = (__u64)params, .len = sizeof(*params), @@ -215,7 +215,7 @@ static void ublk_ctrl_dump(struct ublk_dev *dev) ret = ublk_ctrl_get_params(dev, &p); if (ret < 0) { - ublk_err("failed to get params %m\n"); + ublk_err("failed to get params %d %s\n", ret, strerror(-ret)); return; } @@ -322,7 +322,7 @@ static int ublk_queue_init(struct ublk_queue *q) cmd_buf_size = ublk_queue_cmd_buf_sz(q); off = UBLKSRV_CMD_BUF_OFFSET + q->q_id * ublk_queue_max_cmd_buf_sz(); - q->io_cmd_buf = (char *)mmap(0, cmd_buf_size, PROT_READ, + q->io_cmd_buf = mmap(0, cmd_buf_size, PROT_READ, MAP_SHARED | MAP_POPULATE, dev->fds[0], off); if (q->io_cmd_buf == MAP_FAILED) { ublk_err("ublk dev %d queue %d map io_cmd_buf failed %m\n",
diff --git a/tools/testing/selftests/ublk/kublk.h b/tools/testing/selftests/ublk/kublk.h index f31a5c4..760ff8f 100644 --- a/tools/testing/selftests/ublk/kublk.h +++ b/tools/testing/selftests/ublk/kublk.h
@@ -128,7 +128,7 @@ struct ublk_queue { unsigned int io_inflight; struct ublk_dev *dev; const struct ublk_tgt_ops *tgt_ops; - char *io_cmd_buf; + struct ublksrv_io_desc *io_cmd_buf; struct io_uring ring; struct ublk_io ios[UBLK_QUEUE_DEPTH]; #define UBLKSRV_QUEUE_STOPPING (1U << 0) @@ -302,7 +302,7 @@ static inline void ublk_mark_io_done(struct ublk_io *io, int res) static inline const struct ublksrv_io_desc *ublk_get_iod(const struct ublk_queue *q, int tag) { - return (struct ublksrv_io_desc *)&(q->io_cmd_buf[tag * sizeof(struct ublksrv_io_desc)]); + return &q->io_cmd_buf[tag]; } static inline void ublk_set_sqe_cmd_op(struct io_uring_sqe *sqe, __u32 cmd_op)
diff --git a/tools/testing/selftests/ublk/null.c b/tools/testing/selftests/ublk/null.c index 899875ff5..91fec36 100644 --- a/tools/testing/selftests/ublk/null.c +++ b/tools/testing/selftests/ublk/null.c
@@ -17,7 +17,8 @@ static int ublk_null_tgt_init(const struct dev_ctx *ctx, struct ublk_dev *dev) dev->tgt.dev_size = dev_size; dev->tgt.params = (struct ublk_params) { - .types = UBLK_PARAM_TYPE_BASIC, + .types = UBLK_PARAM_TYPE_BASIC | UBLK_PARAM_TYPE_DMA_ALIGN | + UBLK_PARAM_TYPE_SEGMENT, .basic = { .logical_bs_shift = 9, .physical_bs_shift = 12, @@ -26,6 +27,14 @@ static int ublk_null_tgt_init(const struct dev_ctx *ctx, struct ublk_dev *dev) .max_sectors = info->max_io_buf_bytes >> 9, .dev_sectors = dev_size >> 9, }, + .dma = { + .alignment = 4095, + }, + .seg = { + .seg_boundary_mask = 4095, + .max_segment_size = 32 << 10, + .max_segments = 32, + }, }; if (info->flags & UBLK_F_SUPPORT_ZERO_COPY)
diff --git a/tools/testing/selftests/ublk/stripe.c b/tools/testing/selftests/ublk/stripe.c index 98c564b..179731c 100644 --- a/tools/testing/selftests/ublk/stripe.c +++ b/tools/testing/selftests/ublk/stripe.c
@@ -111,43 +111,67 @@ static void calculate_stripe_array(const struct stripe_conf *conf, } } -static inline enum io_uring_op stripe_to_uring_op(const struct ublksrv_io_desc *iod) +static inline enum io_uring_op stripe_to_uring_op( + const struct ublksrv_io_desc *iod, int zc) { unsigned ublk_op = ublksrv_get_op(iod); if (ublk_op == UBLK_IO_OP_READ) - return IORING_OP_READV; + return zc ? IORING_OP_READV_FIXED : IORING_OP_READV; else if (ublk_op == UBLK_IO_OP_WRITE) - return IORING_OP_WRITEV; + return zc ? IORING_OP_WRITEV_FIXED : IORING_OP_WRITEV; assert(0); } static int stripe_queue_tgt_rw_io(struct ublk_queue *q, const struct ublksrv_io_desc *iod, int tag) { const struct stripe_conf *conf = get_chunk_shift(q); - enum io_uring_op op = stripe_to_uring_op(iod); + int zc = !!(ublk_queue_use_zc(q) != 0); + enum io_uring_op op = stripe_to_uring_op(iod, zc); struct io_uring_sqe *sqe[NR_STRIPE]; struct stripe_array *s = alloc_stripe_array(conf, iod); struct ublk_io *io = ublk_get_io(q, tag); - int i; + int i, extra = zc ? 2 : 0; io->private_data = s; calculate_stripe_array(conf, iod, s); - ublk_queue_alloc_sqes(q, sqe, s->nr); - for (i = 0; i < s->nr; i++) { - struct stripe *t = &s->s[i]; + ublk_queue_alloc_sqes(q, sqe, s->nr + extra); + + if (zc) { + io_uring_prep_buf_register(sqe[0], 0, tag, q->q_id, tag); + sqe[0]->flags |= IOSQE_CQE_SKIP_SUCCESS | IOSQE_IO_HARDLINK; + sqe[0]->user_data = build_user_data(tag, + ublk_cmd_op_nr(sqe[0]->cmd_op), 0, 1); + } + + for (i = zc; i < s->nr + extra - zc; i++) { + struct stripe *t = &s->s[i - zc]; io_uring_prep_rw(op, sqe[i], t->seq + 1, (void *)t->vec, t->nr_vec, t->start << 9); - io_uring_sqe_set_flags(sqe[i], IOSQE_FIXED_FILE); + if (zc) { + sqe[i]->buf_index = tag; + io_uring_sqe_set_flags(sqe[i], + IOSQE_FIXED_FILE | IOSQE_IO_HARDLINK); + } else { + io_uring_sqe_set_flags(sqe[i], IOSQE_FIXED_FILE); + } /* bit63 marks us as tgt io */ - sqe[i]->user_data = build_user_data(tag, ublksrv_get_op(iod), i, 1); + sqe[i]->user_data = build_user_data(tag, ublksrv_get_op(iod), i - zc, 1); } - return s->nr; + if (zc) { + struct io_uring_sqe *unreg = sqe[s->nr + 1]; + + io_uring_prep_buf_unregister(unreg, 0, tag, q->q_id, tag); + unreg->user_data = build_user_data(tag, ublk_cmd_op_nr(unreg->cmd_op), 0, 1); + } + + /* register buffer is skip_success */ + return s->nr + zc; } static int handle_flush(struct ublk_queue *q, const struct ublksrv_io_desc *iod, int tag) @@ -208,19 +232,27 @@ static void ublk_stripe_io_done(struct ublk_queue *q, int tag, struct ublk_io *io = ublk_get_io(q, tag); int res = cqe->res; - if (res < 0) { + if (res < 0 || op != ublk_cmd_op_nr(UBLK_U_IO_UNREGISTER_IO_BUF)) { if (!io->result) io->result = res; - ublk_err("%s: io failure %d tag %u\n", __func__, res, tag); + if (res < 0) + ublk_err("%s: io failure %d tag %u\n", __func__, res, tag); } + /* buffer register op is IOSQE_CQE_SKIP_SUCCESS */ + if (op == ublk_cmd_op_nr(UBLK_U_IO_REGISTER_IO_BUF)) + io->tgt_ios += 1; + /* fail short READ/WRITE simply */ if (op == UBLK_IO_OP_READ || op == UBLK_IO_OP_WRITE) { unsigned seq = user_data_to_tgt_data(cqe->user_data); struct stripe_array *s = io->private_data; - if (res < s->s[seq].vec->iov_len) + if (res < s->s[seq].nr_sects << 9) { io->result = -EIO; + ublk_err("%s: short rw op %u res %d exp %u tag %u\n", + __func__, op, res, s->s[seq].vec->iov_len, tag); + } } if (ublk_completed_tgt_io(q, tag)) { @@ -253,7 +285,7 @@ static int ublk_stripe_tgt_init(const struct dev_ctx *ctx, struct ublk_dev *dev) struct stripe_conf *conf; unsigned chunk_shift; loff_t bytes = 0; - int ret, i; + int ret, i, mul = 1; if ((chunk_size & (chunk_size - 1)) || !chunk_size) { ublk_err("invalid chunk size %u\n", chunk_size); @@ -295,8 +327,11 @@ static int ublk_stripe_tgt_init(const struct dev_ctx *ctx, struct ublk_dev *dev) dev->tgt.dev_size = bytes; p.basic.dev_sectors = bytes >> 9; dev->tgt.params = p; - dev->tgt.sq_depth = dev->dev_info.queue_depth * conf->nr_files; - dev->tgt.cq_depth = dev->dev_info.queue_depth * conf->nr_files; + + if (dev->dev_info.flags & UBLK_F_SUPPORT_ZERO_COPY) + mul = 2; + dev->tgt.sq_depth = mul * dev->dev_info.queue_depth * conf->nr_files; + dev->tgt.cq_depth = mul * dev->dev_info.queue_depth * conf->nr_files; printf("%s: shift %u files %u\n", __func__, conf->shift, conf->nr_files);
diff --git a/tools/testing/selftests/ublk/test_common.sh b/tools/testing/selftests/ublk/test_common.sh index 75f54ac6..a88b359 100755 --- a/tools/testing/selftests/ublk/test_common.sh +++ b/tools/testing/selftests/ublk/test_common.sh
@@ -23,6 +23,12 @@ echo $(( (major & 0xfff) << 20 | (minor & 0xfffff) )) } +_run_fio_verify_io() { + fio --name=verify --rw=randwrite --direct=1 --ioengine=libaio \ + --bs=8k --iodepth=32 --verify=crc32c --do_verify=1 \ + --verify_state_save=0 "$@" > /dev/null +} + _create_backfile() { local my_size=$1 local my_file
diff --git a/tools/testing/selftests/ublk/test_generic_02.sh b/tools/testing/selftests/ublk/test_generic_02.sh new file mode 100755 index 0000000..3e80121 --- /dev/null +++ b/tools/testing/selftests/ublk/test_generic_02.sh
@@ -0,0 +1,44 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 + +. "$(cd "$(dirname "$0")" && pwd)"/test_common.sh + +TID="generic_02" +ERR_CODE=0 + +if ! _have_program bpftrace; then + exit "$UBLK_SKIP_CODE" +fi + +_prep_test "null" "sequential io order for MQ" + +dev_id=$(_add_ublk_dev -t null -q 2) +_check_add_dev $TID $? + +dev_t=$(_get_disk_dev_t "$dev_id") +bpftrace trace/seq_io.bt "$dev_t" "W" 1 > "$UBLK_TMP" 2>&1 & +btrace_pid=$! +sleep 2 + +if ! kill -0 "$btrace_pid" > /dev/null 2>&1; then + _cleanup_test "null" + exit "$UBLK_SKIP_CODE" +fi + +# run fio over this ublk disk +fio --name=write_seq \ + --filename=/dev/ublkb"${dev_id}" \ + --ioengine=libaio --iodepth=16 \ + --rw=write \ + --size=512M \ + --direct=1 \ + --bs=4k > /dev/null 2>&1 +ERR_CODE=$? +kill "$btrace_pid" +wait +if grep -q "io_out_of_order" "$UBLK_TMP"; then + cat "$UBLK_TMP" + ERR_CODE=255 +fi +_cleanup_test "null" +_show_result $TID $ERR_CODE
diff --git a/tools/testing/selftests/ublk/test_generic_03.sh b/tools/testing/selftests/ublk/test_generic_03.sh new file mode 100755 index 0000000..b551aa7 --- /dev/null +++ b/tools/testing/selftests/ublk/test_generic_03.sh
@@ -0,0 +1,28 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 + +. "$(cd "$(dirname "$0")" && pwd)"/test_common.sh + +TID="generic_03" +ERR_CODE=0 + +_prep_test "null" "check dma & segment limits for zero copy" + +dev_id=$(_add_ublk_dev -t null -z) +_check_add_dev $TID $? + +sysfs_path=/sys/block/ublkb"${dev_id}" +dma_align=$(cat "$sysfs_path"/queue/dma_alignment) +max_segments=$(cat "$sysfs_path"/queue/max_segments) +max_segment_size=$(cat "$sysfs_path"/queue/max_segment_size) +if [ "$dma_align" != "4095" ]; then + ERR_CODE=255 +fi +if [ "$max_segments" != "32" ]; then + ERR_CODE=255 +fi +if [ "$max_segment_size" != "32768" ]; then + ERR_CODE=255 +fi +_cleanup_test "null" +_show_result $TID $ERR_CODE
diff --git a/tools/testing/selftests/ublk/test_loop_01.sh b/tools/testing/selftests/ublk/test_loop_01.sh index c882d2a..1ef8b60 100755 --- a/tools/testing/selftests/ublk/test_loop_01.sh +++ b/tools/testing/selftests/ublk/test_loop_01.sh
@@ -6,6 +6,10 @@ TID="loop_01" ERR_CODE=0 +if ! _have_program fio; then + exit "$UBLK_SKIP_CODE" +fi + _prep_test "loop" "write and verify test" backfile_0=$(_create_backfile 256M) @@ -14,15 +18,7 @@ _check_add_dev $TID $? "${backfile_0}" # run fio over the ublk disk -fio --name=write_and_verify \ - --filename=/dev/ublkb"${dev_id}" \ - --ioengine=libaio --iodepth=16 \ - --rw=write \ - --size=256M \ - --direct=1 \ - --verify=crc32c \ - --do_verify=1 \ - --bs=4k > /dev/null 2>&1 +_run_fio_verify_io --filename=/dev/ublkb"${dev_id}" --size=256M ERR_CODE=$? _cleanup_test "loop"
diff --git a/tools/testing/selftests/ublk/test_loop_03.sh b/tools/testing/selftests/ublk/test_loop_03.sh index 269c967..e9ca744 100755 --- a/tools/testing/selftests/ublk/test_loop_03.sh +++ b/tools/testing/selftests/ublk/test_loop_03.sh
@@ -6,6 +6,10 @@ TID="loop_03" ERR_CODE=0 +if ! _have_program fio; then + exit "$UBLK_SKIP_CODE" +fi + _prep_test "loop" "write and verify over zero copy" backfile_0=$(_create_backfile 256M) @@ -13,15 +17,7 @@ _check_add_dev $TID $? "$backfile_0" # run fio over the ublk disk -fio --name=write_and_verify \ - --filename=/dev/ublkb"${dev_id}" \ - --ioengine=libaio --iodepth=64 \ - --rw=write \ - --size=256M \ - --direct=1 \ - --verify=crc32c \ - --do_verify=1 \ - --bs=4k > /dev/null 2>&1 +_run_fio_verify_io --filename=/dev/ublkb"${dev_id}" --size=256M ERR_CODE=$? _cleanup_test "loop"
diff --git a/tools/testing/selftests/ublk/test_loop_05.sh b/tools/testing/selftests/ublk/test_loop_05.sh new file mode 100755 index 0000000..2e6e2e6 --- /dev/null +++ b/tools/testing/selftests/ublk/test_loop_05.sh
@@ -0,0 +1,28 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 + +. "$(cd "$(dirname "$0")" && pwd)"/test_common.sh + +TID="loop_05" +ERR_CODE=0 + +if ! _have_program fio; then + exit "$UBLK_SKIP_CODE" +fi + +_prep_test "loop" "write and verify test" + +backfile_0=$(_create_backfile 256M) + +dev_id=$(_add_ublk_dev -q 2 -t loop "$backfile_0") +_check_add_dev $TID $? "${backfile_0}" + +# run fio over the ublk disk +_run_fio_verify_io --filename=/dev/ublkb"${dev_id}" --size=256M +ERR_CODE=$? + +_cleanup_test "loop" + +_remove_backfile "$backfile_0" + +_show_result $TID $ERR_CODE
diff --git a/tools/testing/selftests/ublk/test_stress_01.sh b/tools/testing/selftests/ublk/test_stress_01.sh index 7177f6c..a8be245 100755 --- a/tools/testing/selftests/ublk/test_stress_01.sh +++ b/tools/testing/selftests/ublk/test_stress_01.sh
@@ -27,20 +27,20 @@ _prep_test "stress" "run IO and remove device" -ublk_io_and_remove 8G -t null +ublk_io_and_remove 8G -t null -q 4 ERR_CODE=$? if [ ${ERR_CODE} -ne 0 ]; then _show_result $TID $ERR_CODE fi BACK_FILE=$(_create_backfile 256M) -ublk_io_and_remove 256M -t loop "${BACK_FILE}" +ublk_io_and_remove 256M -t loop -q 4 "${BACK_FILE}" ERR_CODE=$? if [ ${ERR_CODE} -ne 0 ]; then _show_result $TID $ERR_CODE fi -ublk_io_and_remove 256M -t loop -z "${BACK_FILE}" +ublk_io_and_remove 256M -t loop -q 4 -z "${BACK_FILE}" ERR_CODE=$? _cleanup_test "stress" _remove_backfile "${BACK_FILE}"
diff --git a/tools/testing/selftests/ublk/test_stress_02.sh b/tools/testing/selftests/ublk/test_stress_02.sh index 2a8e605..2159e4c 100755 --- a/tools/testing/selftests/ublk/test_stress_02.sh +++ b/tools/testing/selftests/ublk/test_stress_02.sh
@@ -27,20 +27,20 @@ _prep_test "stress" "run IO and kill ublk server" -ublk_io_and_kill_daemon 8G -t null +ublk_io_and_kill_daemon 8G -t null -q 4 ERR_CODE=$? if [ ${ERR_CODE} -ne 0 ]; then _show_result $TID $ERR_CODE fi BACK_FILE=$(_create_backfile 256M) -ublk_io_and_kill_daemon 256M -t loop "${BACK_FILE}" +ublk_io_and_kill_daemon 256M -t loop -q 4 "${BACK_FILE}" ERR_CODE=$? if [ ${ERR_CODE} -ne 0 ]; then _show_result $TID $ERR_CODE fi -ublk_io_and_kill_daemon 256M -t loop -z "${BACK_FILE}" +ublk_io_and_kill_daemon 256M -t loop -q 4 -z "${BACK_FILE}" ERR_CODE=$? _cleanup_test "stress" _remove_backfile "${BACK_FILE}"
diff --git a/tools/testing/selftests/ublk/test_stripe_01.sh b/tools/testing/selftests/ublk/test_stripe_01.sh index c01f3dc..7e387ef 100755 --- a/tools/testing/selftests/ublk/test_stripe_01.sh +++ b/tools/testing/selftests/ublk/test_stripe_01.sh
@@ -6,6 +6,10 @@ TID="stripe_01" ERR_CODE=0 +if ! _have_program fio; then + exit "$UBLK_SKIP_CODE" +fi + _prep_test "stripe" "write and verify test" backfile_0=$(_create_backfile 256M) @@ -15,15 +19,7 @@ _check_add_dev $TID $? "${backfile_0}" # run fio over the ublk disk -fio --name=write_and_verify \ - --filename=/dev/ublkb"${dev_id}" \ - --ioengine=libaio --iodepth=32 \ - --rw=write \ - --size=512M \ - --direct=1 \ - --verify=crc32c \ - --do_verify=1 \ - --bs=4k > /dev/null 2>&1 +_run_fio_verify_io --filename=/dev/ublkb"${dev_id}" --size=512M ERR_CODE=$? _cleanup_test "stripe"
diff --git a/tools/testing/selftests/ublk/test_stripe_03.sh b/tools/testing/selftests/ublk/test_stripe_03.sh new file mode 100755 index 0000000..c1b34af --- /dev/null +++ b/tools/testing/selftests/ublk/test_stripe_03.sh
@@ -0,0 +1,30 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 + +. "$(cd "$(dirname "$0")" && pwd)"/test_common.sh + +TID="stripe_03" +ERR_CODE=0 + +if ! _have_program fio; then + exit "$UBLK_SKIP_CODE" +fi + +_prep_test "stripe" "write and verify test" + +backfile_0=$(_create_backfile 256M) +backfile_1=$(_create_backfile 256M) + +dev_id=$(_add_ublk_dev -q 2 -t stripe "$backfile_0" "$backfile_1") +_check_add_dev $TID $? "${backfile_0}" + +# run fio over the ublk disk +_run_fio_verify_io --filename=/dev/ublkb"${dev_id}" --size=512M +ERR_CODE=$? + +_cleanup_test "stripe" + +_remove_backfile "$backfile_0" +_remove_backfile "$backfile_1" + +_show_result $TID $ERR_CODE
diff --git a/tools/testing/selftests/x86/test_mremap_vdso.c b/tools/testing/selftests/x86/test_mremap_vdso.c index d53959e..94bee6e 100644 --- a/tools/testing/selftests/x86/test_mremap_vdso.c +++ b/tools/testing/selftests/x86/test_mremap_vdso.c
@@ -14,6 +14,7 @@ #include <errno.h> #include <unistd.h> #include <string.h> +#include <stdbool.h> #include <sys/mman.h> #include <sys/auxv.h> @@ -55,13 +56,55 @@ static int try_to_remap(void *vdso_addr, unsigned long size) } +#define VDSO_NAME "[vdso]" +#define VMFLAGS "VmFlags:" +#define MSEAL_FLAGS "sl" +#define MAX_LINE_LEN 512 + +bool vdso_sealed(FILE *maps) +{ + char line[MAX_LINE_LEN]; + bool has_vdso = false; + + while (fgets(line, sizeof(line), maps)) { + if (strstr(line, VDSO_NAME)) + has_vdso = true; + + if (has_vdso && !strncmp(line, VMFLAGS, strlen(VMFLAGS))) { + if (strstr(line, MSEAL_FLAGS)) + return true; + + return false; + } + } + + return false; +} + int main(int argc, char **argv, char **envp) { pid_t child; + FILE *maps; ksft_print_header(); ksft_set_plan(1); + maps = fopen("/proc/self/smaps", "r"); + if (!maps) { + ksft_test_result_skip( + "Could not open /proc/self/smaps, errno=%d\n", + errno); + + return 0; + } + + if (vdso_sealed(maps)) { + ksft_test_result_skip("vdso is sealed\n"); + return 0; + } + + fclose(maps); + child = fork(); if (child == -1) ksft_exit_fail_msg("failed to fork (%d): %m\n", errno);
diff --git a/tools/virtio/linux/compiler.h b/tools/virtio/linux/compiler.h index 1f3a15b..204ef0e 100644 --- a/tools/virtio/linux/compiler.h +++ b/tools/virtio/linux/compiler.h
@@ -10,4 +10,29 @@ #define READ_ONCE(var) (*((volatile typeof(var) *)(&(var)))) #define __aligned(x) __attribute((__aligned__(x))) + +/** + * data_race - mark an expression as containing intentional data races + * + * This data_race() macro is useful for situations in which data races + * should be forgiven. One example is diagnostic code that accesses + * shared variables but is not a part of the core synchronization design. + * For example, if accesses to a given variable are protected by a lock, + * except for diagnostic code, then the accesses under the lock should + * be plain C-language accesses and those in the diagnostic code should + * use data_race(). This way, KCSAN will complain if buggy lockless + * accesses to that variable are introduced, even if the buggy accesses + * are protected by READ_ONCE() or WRITE_ONCE(). + * + * This macro *does not* affect normal code generation, but is a hint + * to tooling that data races here are to be ignored. If the access must + * be atomic *and* KCSAN should ignore the access, use both data_race() + * and READ_ONCE(), for example, data_race(READ_ONCE(x)). + */ +#define data_race(expr) \ +({ \ + __auto_type __v = (expr); \ + __v; \ +}) + #endif
diff --git a/tools/virtio/linux/dma-mapping.h b/tools/virtio/linux/dma-mapping.h index 822ecaa..0959584 100644 --- a/tools/virtio/linux/dma-mapping.h +++ b/tools/virtio/linux/dma-mapping.h
@@ -31,6 +31,7 @@ enum dma_data_direction { #define dma_unmap_page(d, a, s, r) do { (void)(d); (void)(a); (void)(s); (void)(r); } while (0) #define sg_dma_address(sg) (0) +#define sg_dma_len(sg) (0) #define dma_need_sync(v, a) (0) #define dma_unmap_single_attrs(d, a, s, r, t) do { \ (void)(d); (void)(a); (void)(s); (void)(r); (void)(t); \ @@ -43,4 +44,16 @@ enum dma_data_direction { } while (0) #define dma_max_mapping_size(...) SIZE_MAX +/* + * A dma_addr_t can hold any valid DMA or bus address for the platform. It can + * be given to a device to use as a DMA source or target. It is specific to a + * given device and there may be a translation between the CPU physical address + * space and the bus address space. + * + * DMA_MAPPING_ERROR is the magic error code if a mapping failed. It should not + * be used directly in drivers, but checked for using dma_mapping_error() + * instead. + */ +#define DMA_MAPPING_ERROR (~(dma_addr_t)0) + #endif
diff --git a/tools/virtio/linux/module.h b/tools/virtio/linux/module.h index 9dfa96f..b91681f 100644 --- a/tools/virtio/linux/module.h +++ b/tools/virtio/linux/module.h
@@ -5,3 +5,10 @@ static __attribute__((unused)) const char *__MODULE_LICENSE_name = \ __MODULE_LICENSE_value +#ifndef MODULE_AUTHOR +#define MODULE_AUTHOR(x) +#endif + +#ifndef MODULE_DESCRIPTION +#define MODULE_DESCRIPTION(x) +#endif