diff --git a/.mailmap b/.mailmap index e51d76df75c2de..8ee01d9d70464b 100644 --- a/.mailmap +++ b/.mailmap @@ -166,6 +166,7 @@ Daniel Borkmann Daniel Borkmann David Brownell David Collins +David Heidelberg David Rheinsberg David Rheinsberg David Rheinsberg diff --git a/Documentation/ABI/testing/sysfs-bus-i2c-devices-turris-omnia-mcu b/Documentation/ABI/testing/sysfs-bus-i2c-devices-turris-omnia-mcu index 307a55f599cb17..35a8f6dae5bfdd 100644 --- a/Documentation/ABI/testing/sysfs-bus-i2c-devices-turris-omnia-mcu +++ b/Documentation/ABI/testing/sysfs-bus-i2c-devices-turris-omnia-mcu @@ -32,9 +32,9 @@ Description: (RW) The front button on the Turris Omnia router can be interrupt. This file switches between these two modes: - - "mcu" makes the button press event be handled by the MCU to - change the LEDs panel intensity. - - "cpu" makes the button press event be handled by the CPU. + - ``mcu`` makes the button press event be handled by the MCU to + change the LEDs panel intensity. + - ``cpu`` makes the button press event be handled by the CPU. Format: %s. diff --git a/Documentation/ABI/testing/sysfs-devices-system-cpu b/Documentation/ABI/testing/sysfs-devices-system-cpu index 325873385b71fb..de725ca3be825b 100644 --- a/Documentation/ABI/testing/sysfs-devices-system-cpu +++ b/Documentation/ABI/testing/sysfs-devices-system-cpu @@ -562,7 +562,8 @@ Description: Control Symmetric Multi Threading (SMT) ================ ========================================= If control status is "forceoff" or "notsupported" writes - are rejected. + are rejected. Note that enabling SMT on PowerPC skips + offline cores. What: /sys/devices/system/cpu/cpuX/power/energy_perf_bias Date: March 2019 diff --git a/Documentation/admin-guide/cifs/usage.rst b/Documentation/admin-guide/cifs/usage.rst index fd4b56c0996f47..c09674a75a9e3c 100644 --- a/Documentation/admin-guide/cifs/usage.rst +++ b/Documentation/admin-guide/cifs/usage.rst @@ -742,7 +742,7 @@ SecurityFlags Flags which control security negotiation and may use NTLMSSP 0x00080 must use NTLMSSP 0x80080 seal (packet encryption) 0x00040 - must seal (not implemented yet) 0x40040 + must seal 0x40040 cifsFYI If set to non-zero value, additional debug information will be logged to the system error log. This field diff --git a/Documentation/admin-guide/device-mapper/dm-crypt.rst b/Documentation/admin-guide/device-mapper/dm-crypt.rst index e625830d335ea7..552c9155165d7c 100644 --- a/Documentation/admin-guide/device-mapper/dm-crypt.rst +++ b/Documentation/admin-guide/device-mapper/dm-crypt.rst @@ -162,13 +162,14 @@ iv_large_sectors Module parameters:: -max_read_size -max_write_size - Maximum size of read or write requests. When a request larger than this size - is received, dm-crypt will split the request. The splitting improves - concurrency (the split requests could be encrypted in parallel by multiple - cores), but it also causes overhead. The user should tune these parameters to - fit the actual workload. + + max_read_size + max_write_size + Maximum size of read or write requests. When a request larger than this size + is received, dm-crypt will split the request. The splitting improves + concurrency (the split requests could be encrypted in parallel by multiple + cores), but it also causes overhead. The user should tune these parameters to + fit the actual workload. Example scripts diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index f1384c7b59c928..09126bb8cc9ffb 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -4798,11 +4798,9 @@ profile= [KNL] Enable kernel profiling via /proc/profile Format: [,] - Param: : "schedule", "sleep", or "kvm" + Param: : "schedule" or "kvm" [defaults to kernel profiling] Param: "schedule" - profile schedule points. - Param: "sleep" - profile D-state sleeping (millisecs). - Requires CONFIG_SCHEDSTATS Param: "kvm" - profile VM exits. Param: - step/bucket size as a power of 2 for statistical time based profiling. diff --git a/Documentation/arch/arm64/silicon-errata.rst b/Documentation/arch/arm64/silicon-errata.rst index bb83c5d8c67551..50327c05be8d1b 100644 --- a/Documentation/arch/arm64/silicon-errata.rst +++ b/Documentation/arch/arm64/silicon-errata.rst @@ -122,10 +122,18 @@ stable kernels. +----------------+-----------------+-----------------+-----------------------------+ | ARM | Cortex-A76 | #1490853 | N/A | +----------------+-----------------+-----------------+-----------------------------+ +| ARM | Cortex-A76 | #3324349 | ARM64_ERRATUM_3194386 | ++----------------+-----------------+-----------------+-----------------------------+ | ARM | Cortex-A77 | #1491015 | N/A | +----------------+-----------------+-----------------+-----------------------------+ | ARM | Cortex-A77 | #1508412 | ARM64_ERRATUM_1508412 | +----------------+-----------------+-----------------+-----------------------------+ +| ARM | Cortex-A77 | #3324348 | ARM64_ERRATUM_3194386 | ++----------------+-----------------+-----------------+-----------------------------+ +| ARM | Cortex-A78 | #3324344 | ARM64_ERRATUM_3194386 | ++----------------+-----------------+-----------------+-----------------------------+ +| ARM | Cortex-A78C | #3324346,3324347| ARM64_ERRATUM_3194386 | ++----------------+-----------------+-----------------+-----------------------------+ | ARM | Cortex-A710 | #2119858 | ARM64_ERRATUM_2119858 | +----------------+-----------------+-----------------+-----------------------------+ | ARM | Cortex-A710 | #2054223 | ARM64_ERRATUM_2054223 | @@ -138,8 +146,14 @@ stable kernels. +----------------+-----------------+-----------------+-----------------------------+ | ARM | Cortex-A720 | #3456091 | ARM64_ERRATUM_3194386 | +----------------+-----------------+-----------------+-----------------------------+ +| ARM | Cortex-A725 | #3456106 | ARM64_ERRATUM_3194386 | ++----------------+-----------------+-----------------+-----------------------------+ | ARM | Cortex-X1 | #1502854 | N/A | +----------------+-----------------+-----------------+-----------------------------+ +| ARM | Cortex-X1 | #3324344 | ARM64_ERRATUM_3194386 | ++----------------+-----------------+-----------------+-----------------------------+ +| ARM | Cortex-X1C | #3324346 | ARM64_ERRATUM_3194386 | ++----------------+-----------------+-----------------+-----------------------------+ | ARM | Cortex-X2 | #2119858 | ARM64_ERRATUM_2119858 | +----------------+-----------------+-----------------+-----------------------------+ | ARM | Cortex-X2 | #2224489 | ARM64_ERRATUM_2224489 | @@ -160,6 +174,8 @@ stable kernels. +----------------+-----------------+-----------------+-----------------------------+ | ARM | Neoverse-N1 | #1542419 | ARM64_ERRATUM_1542419 | +----------------+-----------------+-----------------+-----------------------------+ +| ARM | Neoverse-N1 | #3324349 | ARM64_ERRATUM_3194386 | ++----------------+-----------------+-----------------+-----------------------------+ | ARM | Neoverse-N2 | #2139208 | ARM64_ERRATUM_2139208 | +----------------+-----------------+-----------------+-----------------------------+ | ARM | Neoverse-N2 | #2067961 | ARM64_ERRATUM_2067961 | @@ -170,6 +186,8 @@ stable kernels. +----------------+-----------------+-----------------+-----------------------------+ | ARM | Neoverse-V1 | #1619801 | N/A | +----------------+-----------------+-----------------+-----------------------------+ +| ARM | Neoverse-V1 | #3324341 | ARM64_ERRATUM_3194386 | ++----------------+-----------------+-----------------+-----------------------------+ | ARM | Neoverse-V2 | #3324336 | ARM64_ERRATUM_3194386 | +----------------+-----------------+-----------------+-----------------------------+ | ARM | Neoverse-V3 | #3312417 | ARM64_ERRATUM_3194386 | diff --git a/Documentation/arch/riscv/hwprobe.rst b/Documentation/arch/riscv/hwprobe.rst index 3db60a0911df65..85b709257918ad 100644 --- a/Documentation/arch/riscv/hwprobe.rst +++ b/Documentation/arch/riscv/hwprobe.rst @@ -239,25 +239,33 @@ The following keys are defined: ratified in commit 98918c844281 ("Merge pull request #1217 from riscv/zawrs") of riscv-isa-manual. -* :c:macro:`RISCV_HWPROBE_KEY_CPUPERF_0`: A bitmask that contains performance - information about the selected set of processors. +* :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. - * :c:macro:`RISCV_HWPROBE_MISALIGNED_UNKNOWN`: The performance of misaligned - accesses is unknown. +* :c:macro:`RISCV_HWPROBE_KEY_MISALIGNED_SCALAR_PERF`: An enum value describing + the performance of misaligned scalar native word accesses on the selected set + of processors. - * :c:macro:`RISCV_HWPROBE_MISALIGNED_EMULATED`: Misaligned accesses are - emulated via software, either in or below the kernel. These accesses are - always extremely slow. + * :c:macro:`RISCV_HWPROBE_MISALIGNED_SCALAR_UNKNOWN`: The performance of + misaligned scalar accesses is unknown. - * :c:macro:`RISCV_HWPROBE_MISALIGNED_SLOW`: Misaligned accesses are slower - than equivalent byte accesses. Misaligned accesses may be supported - directly in hardware, or trapped and emulated by software. + * :c:macro:`RISCV_HWPROBE_MISALIGNED_SCALAR_EMULATED`: Misaligned scalar + accesses are emulated via software, either in or below the kernel. These + accesses are always extremely slow. - * :c:macro:`RISCV_HWPROBE_MISALIGNED_FAST`: Misaligned accesses are faster - than equivalent byte accesses. + * :c:macro:`RISCV_HWPROBE_MISALIGNED_SCALAR_SLOW`: Misaligned scalar native + word sized accesses are slower than the equivalent quantity of byte + accesses. Misaligned accesses may be supported directly in hardware, or + trapped and emulated by software. - * :c:macro:`RISCV_HWPROBE_MISALIGNED_UNSUPPORTED`: Misaligned accesses are - not supported at all and will generate a misaligned address fault. + * :c:macro:`RISCV_HWPROBE_MISALIGNED_SCALAR_FAST`: Misaligned scalar native + word sized accesses are faster than the equivalent quantity of byte + accesses. + + * :c:macro:`RISCV_HWPROBE_MISALIGNED_SCALAR_UNSUPPORTED`: Misaligned scalar + accesses are not supported at all and will generate a misaligned address + fault. * :c:macro:`RISCV_HWPROBE_KEY_ZICBOZ_BLOCK_SIZE`: An unsigned int which represents the size of the Zicboz block in bytes. diff --git a/Documentation/devicetree/bindings/ata/rockchip,dwc-ahci.yaml b/Documentation/devicetree/bindings/ata/rockchip,dwc-ahci.yaml index b5e5767d86988d..13eaa8d9a16e5a 100644 --- a/Documentation/devicetree/bindings/ata/rockchip,dwc-ahci.yaml +++ b/Documentation/devicetree/bindings/ata/rockchip,dwc-ahci.yaml @@ -35,6 +35,9 @@ properties: ports-implemented: const: 1 + power-domains: + maxItems: 1 + sata-port@0: $ref: /schemas/ata/snps,dwc-ahci-common.yaml#/$defs/dwc-ahci-port diff --git a/Documentation/devicetree/bindings/clock/qcom,dispcc-sm6350.yaml b/Documentation/devicetree/bindings/clock/qcom,dispcc-sm6350.yaml index a584b4953e686d..46403b98411f81 100644 --- a/Documentation/devicetree/bindings/clock/qcom,dispcc-sm6350.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,dispcc-sm6350.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Qualcomm Display Clock & Reset Controller on SM6350 maintainers: - - Konrad Dybcio + - Konrad Dybcio description: | Qualcomm display clock control module provides the clocks, resets and power diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-msm8994.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-msm8994.yaml index 6b9c1d198b14d0..10afe984e2fbc1 100644 --- a/Documentation/devicetree/bindings/clock/qcom,gcc-msm8994.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,gcc-msm8994.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Qualcomm Global Clock & Reset Controller on MSM8994 maintainers: - - Konrad Dybcio + - Konrad Dybcio description: | Qualcomm global clock control module provides the clocks, resets and power diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-sm6125.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-sm6125.yaml index a5a29dc75ae11b..1fe68e07a2b208 100644 --- a/Documentation/devicetree/bindings/clock/qcom,gcc-sm6125.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,gcc-sm6125.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Qualcomm Global Clock & Reset Controller on SM6125 maintainers: - - Konrad Dybcio + - Konrad Dybcio description: | Qualcomm global clock control module provides the clocks, resets and power diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-sm6350.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-sm6350.yaml index 2280b859b2ad63..78e232fa95dc60 100644 --- a/Documentation/devicetree/bindings/clock/qcom,gcc-sm6350.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,gcc-sm6350.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Qualcomm Global Clock & Reset Controller on SM6350 maintainers: - - Konrad Dybcio + - Konrad Dybcio description: | Qualcomm global clock control module provides the clocks, resets and power diff --git a/Documentation/devicetree/bindings/clock/qcom,sm6115-gpucc.yaml b/Documentation/devicetree/bindings/clock/qcom,sm6115-gpucc.yaml index cf19f44af77440..4ff17a91344bad 100644 --- a/Documentation/devicetree/bindings/clock/qcom,sm6115-gpucc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,sm6115-gpucc.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Qualcomm Graphics Clock & Reset Controller on SM6115 maintainers: - - Konrad Dybcio + - Konrad Dybcio description: | Qualcomm graphics clock control module provides clocks, resets and power diff --git a/Documentation/devicetree/bindings/clock/qcom,sm6125-gpucc.yaml b/Documentation/devicetree/bindings/clock/qcom,sm6125-gpucc.yaml index 374a1844a159a0..10a9c96a97b6a1 100644 --- a/Documentation/devicetree/bindings/clock/qcom,sm6125-gpucc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,sm6125-gpucc.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Qualcomm Graphics Clock & Reset Controller on SM6125 maintainers: - - Konrad Dybcio + - Konrad Dybcio description: | Qualcomm graphics clock control module provides clocks and power domains on diff --git a/Documentation/devicetree/bindings/clock/qcom,sm6350-camcc.yaml b/Documentation/devicetree/bindings/clock/qcom,sm6350-camcc.yaml index fd6658cb793dbb..c03b30f64f359a 100644 --- a/Documentation/devicetree/bindings/clock/qcom,sm6350-camcc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,sm6350-camcc.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Qualcomm Camera Clock & Reset Controller on SM6350 maintainers: - - Konrad Dybcio + - Konrad Dybcio description: | Qualcomm camera clock control module provides the clocks, resets and power diff --git a/Documentation/devicetree/bindings/clock/qcom,sm6375-dispcc.yaml b/Documentation/devicetree/bindings/clock/qcom,sm6375-dispcc.yaml index 183b1c75dbdf3b..3cd422a645fd87 100644 --- a/Documentation/devicetree/bindings/clock/qcom,sm6375-dispcc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,sm6375-dispcc.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Qualcomm Display Clock & Reset Controller on SM6375 maintainers: - - Konrad Dybcio + - Konrad Dybcio description: | Qualcomm display clock control module provides the clocks, resets and power diff --git a/Documentation/devicetree/bindings/clock/qcom,sm6375-gcc.yaml b/Documentation/devicetree/bindings/clock/qcom,sm6375-gcc.yaml index 147b75a21508f1..de4e9066eeb835 100644 --- a/Documentation/devicetree/bindings/clock/qcom,sm6375-gcc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,sm6375-gcc.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Qualcomm Global Clock & Reset Controller on SM6375 maintainers: - - Konrad Dybcio + - Konrad Dybcio description: | Qualcomm global clock control module provides the clocks, resets and power diff --git a/Documentation/devicetree/bindings/clock/qcom,sm6375-gpucc.yaml b/Documentation/devicetree/bindings/clock/qcom,sm6375-gpucc.yaml index cf4cad76f6c951..d9dd479c17bd63 100644 --- a/Documentation/devicetree/bindings/clock/qcom,sm6375-gpucc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,sm6375-gpucc.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Qualcomm Graphics Clock & Reset Controller on SM6375 maintainers: - - Konrad Dybcio + - Konrad Dybcio description: | Qualcomm graphics clock control module provides clocks, resets and power diff --git a/Documentation/devicetree/bindings/clock/qcom,sm8350-videocc.yaml b/Documentation/devicetree/bindings/clock/qcom,sm8350-videocc.yaml index 46d1d91e3a01ef..5c2ecec0624e35 100644 --- a/Documentation/devicetree/bindings/clock/qcom,sm8350-videocc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,sm8350-videocc.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Qualcomm SM8350 Video Clock & Reset Controller maintainers: - - Konrad Dybcio + - Konrad Dybcio description: | Qualcomm video clock control module provides the clocks, resets and power diff --git a/Documentation/devicetree/bindings/clock/qcom,sm8450-gpucc.yaml b/Documentation/devicetree/bindings/clock/qcom,sm8450-gpucc.yaml index 3c2cac14e6c3a0..d10bb002906e9f 100644 --- a/Documentation/devicetree/bindings/clock/qcom,sm8450-gpucc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,sm8450-gpucc.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Qualcomm Graphics Clock & Reset Controller on SM8450 maintainers: - - Konrad Dybcio + - Konrad Dybcio description: | Qualcomm graphics clock control module provides the clocks, resets and power diff --git a/Documentation/devicetree/bindings/display/msm/qcom,sm6375-mdss.yaml b/Documentation/devicetree/bindings/display/msm/qcom,sm6375-mdss.yaml index 8e8a288d318c34..e22b4c433fd07c 100644 --- a/Documentation/devicetree/bindings/display/msm/qcom,sm6375-mdss.yaml +++ b/Documentation/devicetree/bindings/display/msm/qcom,sm6375-mdss.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Qualcomm SM6375 Display MDSS maintainers: - - Konrad Dybcio + - Konrad Dybcio description: SM6375 MSM Mobile Display Subsystem (MDSS), which encapsulates sub-blocks diff --git a/Documentation/devicetree/bindings/display/panel/asus,z00t-tm5p5-nt35596.yaml b/Documentation/devicetree/bindings/display/panel/asus,z00t-tm5p5-nt35596.yaml index 2399cabf044c2f..dd614e077bbff3 100644 --- a/Documentation/devicetree/bindings/display/panel/asus,z00t-tm5p5-nt35596.yaml +++ b/Documentation/devicetree/bindings/display/panel/asus,z00t-tm5p5-nt35596.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: ASUS Z00T TM5P5 NT35596 5.5" 1080×1920 LCD Panel maintainers: - - Konrad Dybcio + - Konrad Dybcio description: |+ This panel seems to only be found in the Asus Z00T diff --git a/Documentation/devicetree/bindings/display/panel/samsung,atna33xc20.yaml b/Documentation/devicetree/bindings/display/panel/samsung,atna33xc20.yaml index 5192c93fbd67a0..032f783eefc450 100644 --- a/Documentation/devicetree/bindings/display/panel/samsung,atna33xc20.yaml +++ b/Documentation/devicetree/bindings/display/panel/samsung,atna33xc20.yaml @@ -17,9 +17,12 @@ properties: oneOf: # Samsung 13.3" FHD (1920x1080 pixels) eDP AMOLED panel - const: samsung,atna33xc20 - # Samsung 14.5" WQXGA+ (2880x1800 pixels) eDP AMOLED panel - items: - - const: samsung,atna45af01 + - enum: + # Samsung 14.5" WQXGA+ (2880x1800 pixels) eDP AMOLED panel + - samsung,atna45af01 + # Samsung 14.5" 3K (2944x1840 pixels) eDP AMOLED panel + - samsung,atna45dc02 - const: samsung,atna33xc20 enable-gpios: true diff --git a/Documentation/devicetree/bindings/display/panel/sony,td4353-jdi.yaml b/Documentation/devicetree/bindings/display/panel/sony,td4353-jdi.yaml index 191b692125e145..032a989184ff05 100644 --- a/Documentation/devicetree/bindings/display/panel/sony,td4353-jdi.yaml +++ b/Documentation/devicetree/bindings/display/panel/sony,td4353-jdi.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Sony TD4353 JDI 5 / 5.7" 2160x1080 MIPI-DSI Panel maintainers: - - Konrad Dybcio + - Konrad Dybcio description: | The Sony TD4353 JDI is a 5 (XZ2c) / 5.7 (XZ2) inch 2160x1080 diff --git a/Documentation/devicetree/bindings/eeprom/at25.yaml b/Documentation/devicetree/bindings/eeprom/at25.yaml index 1715b0c9feeafe..c31e5e71952501 100644 --- a/Documentation/devicetree/bindings/eeprom/at25.yaml +++ b/Documentation/devicetree/bindings/eeprom/at25.yaml @@ -28,6 +28,7 @@ properties: - anvo,anv32e61w - atmel,at25256B - fujitsu,mb85rs1mt + - fujitsu,mb85rs256 - fujitsu,mb85rs64 - microchip,at25160bn - microchip,25lc040 diff --git a/Documentation/devicetree/bindings/interconnect/qcom,sc7280-rpmh.yaml b/Documentation/devicetree/bindings/interconnect/qcom,sc7280-rpmh.yaml index 9fce7203bd42db..78210791496f84 100644 --- a/Documentation/devicetree/bindings/interconnect/qcom,sc7280-rpmh.yaml +++ b/Documentation/devicetree/bindings/interconnect/qcom,sc7280-rpmh.yaml @@ -8,7 +8,7 @@ title: Qualcomm RPMh Network-On-Chip Interconnect on SC7280 maintainers: - Bjorn Andersson - - Konrad Dybcio + - Konrad Dybcio description: | RPMh interconnect providers support system bandwidth requirements through diff --git a/Documentation/devicetree/bindings/interconnect/qcom,sc8280xp-rpmh.yaml b/Documentation/devicetree/bindings/interconnect/qcom,sc8280xp-rpmh.yaml index 6c2da03f0cd224..100c6863690926 100644 --- a/Documentation/devicetree/bindings/interconnect/qcom,sc8280xp-rpmh.yaml +++ b/Documentation/devicetree/bindings/interconnect/qcom,sc8280xp-rpmh.yaml @@ -8,7 +8,7 @@ title: Qualcomm RPMh Network-On-Chip Interconnect on SC8280XP maintainers: - Bjorn Andersson - - Konrad Dybcio + - Konrad Dybcio description: | RPMh interconnect providers support system bandwidth requirements through diff --git a/Documentation/devicetree/bindings/interconnect/qcom,sm8450-rpmh.yaml b/Documentation/devicetree/bindings/interconnect/qcom,sm8450-rpmh.yaml index 3cff7e66225538..300640a533dd67 100644 --- a/Documentation/devicetree/bindings/interconnect/qcom,sm8450-rpmh.yaml +++ b/Documentation/devicetree/bindings/interconnect/qcom,sm8450-rpmh.yaml @@ -8,7 +8,7 @@ title: Qualcomm RPMh Network-On-Chip Interconnect on SM8450 maintainers: - Bjorn Andersson - - Konrad Dybcio + - Konrad Dybcio description: | RPMh interconnect providers support system bandwidth requirements through diff --git a/Documentation/devicetree/bindings/iommu/qcom,iommu.yaml b/Documentation/devicetree/bindings/iommu/qcom,iommu.yaml index 571e5746d1776f..f8cebc9e8cd9d4 100644 --- a/Documentation/devicetree/bindings/iommu/qcom,iommu.yaml +++ b/Documentation/devicetree/bindings/iommu/qcom,iommu.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Qualcomm Technologies legacy IOMMU implementations maintainers: - - Konrad Dybcio + - Konrad Dybcio description: | Qualcomm "B" family devices which are not compatible with arm-smmu have diff --git a/Documentation/devicetree/bindings/net/fsl,qoriq-mc-dpmac.yaml b/Documentation/devicetree/bindings/net/fsl,qoriq-mc-dpmac.yaml index a1b71b35319e70..42f9843d1868ac 100644 --- a/Documentation/devicetree/bindings/net/fsl,qoriq-mc-dpmac.yaml +++ b/Documentation/devicetree/bindings/net/fsl,qoriq-mc-dpmac.yaml @@ -38,6 +38,10 @@ properties: managed: true + phys: + description: A reference to the SerDes lane(s) + maxItems: 1 + required: - reg diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,mdm9607-tlmm.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,mdm9607-tlmm.yaml index bd3cbb44c99a46..e75393b3d196c5 100644 --- a/Documentation/devicetree/bindings/pinctrl/qcom,mdm9607-tlmm.yaml +++ b/Documentation/devicetree/bindings/pinctrl/qcom,mdm9607-tlmm.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Qualcomm Technologies, Inc. MDM9607 TLMM block maintainers: - - Konrad Dybcio + - Konrad Dybcio description: Top Level Mode Multiplexer pin controller in Qualcomm MDM9607 SoC. diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,sm6350-tlmm.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,sm6350-tlmm.yaml index a4771f87d93645..b262af6be97da3 100644 --- a/Documentation/devicetree/bindings/pinctrl/qcom,sm6350-tlmm.yaml +++ b/Documentation/devicetree/bindings/pinctrl/qcom,sm6350-tlmm.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Qualcomm Technologies, Inc. SM6350 TLMM block maintainers: - - Konrad Dybcio + - Konrad Dybcio description: Top Level Mode Multiplexer pin controller in Qualcomm SM6350 SoC. diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,sm6375-tlmm.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,sm6375-tlmm.yaml index 047f82863f9bbf..c11af09c3f5b89 100644 --- a/Documentation/devicetree/bindings/pinctrl/qcom,sm6375-tlmm.yaml +++ b/Documentation/devicetree/bindings/pinctrl/qcom,sm6375-tlmm.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Qualcomm Technologies, Inc. SM6375 TLMM block maintainers: - - Konrad Dybcio + - Konrad Dybcio description: Top Level Mode Multiplexer pin controller in Qualcomm SM6375 SoC. diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,rpm-proc.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,rpm-proc.yaml index 7afafde17a38bf..61cf4fe19ca53e 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,rpm-proc.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,rpm-proc.yaml @@ -8,7 +8,7 @@ title: Qualcomm Resource Power Manager (RPM) Processor/Subsystem maintainers: - Bjorn Andersson - - Konrad Dybcio + - Konrad Dybcio - Stephan Gerhold description: | diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,rpm-master-stats.yaml b/Documentation/devicetree/bindings/soc/qcom/qcom,rpm-master-stats.yaml index 9410404f87f1af..ad2dcc39a5f548 100644 --- a/Documentation/devicetree/bindings/soc/qcom/qcom,rpm-master-stats.yaml +++ b/Documentation/devicetree/bindings/soc/qcom/qcom,rpm-master-stats.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Qualcomm Technologies, Inc. (QTI) RPM Master Stats maintainers: - - Konrad Dybcio + - Konrad Dybcio description: | The Qualcomm RPM (Resource Power Manager) architecture includes a concept diff --git a/Documentation/devicetree/bindings/sound/qcom,lpass-wsa-macro.yaml b/Documentation/devicetree/bindings/sound/qcom,lpass-wsa-macro.yaml index 06b5f7be360829..6f5644a89febbd 100644 --- a/Documentation/devicetree/bindings/sound/qcom,lpass-wsa-macro.yaml +++ b/Documentation/devicetree/bindings/sound/qcom,lpass-wsa-macro.yaml @@ -64,6 +64,7 @@ allOf: compatible: enum: - qcom,sc7280-lpass-wsa-macro + - qcom,sm8250-lpass-wsa-macro - qcom,sm8450-lpass-wsa-macro - qcom,sc8280xp-lpass-wsa-macro then: @@ -79,24 +80,6 @@ allOf: - const: dcodec - const: fsgen - - if: - properties: - compatible: - enum: - - qcom,sm8250-lpass-wsa-macro - then: - properties: - clocks: - minItems: 6 - clock-names: - items: - - const: mclk - - const: npl - - const: macro - - const: dcodec - - const: va - - const: fsgen - - if: properties: compatible: @@ -130,8 +113,7 @@ examples: <&audiocc 0>, <&q6afecc LPASS_HW_MACRO_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>, <&q6afecc LPASS_HW_DCODEC_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>, - <&aoncc LPASS_CDC_VA_MCLK>, <&vamacro>; - clock-names = "mclk", "npl", "macro", "dcodec", "va", "fsgen"; + clock-names = "mclk", "npl", "macro", "dcodec", "fsgen"; clock-output-names = "mclk"; }; diff --git a/Documentation/devicetree/bindings/sound/qcom,wcd934x.yaml b/Documentation/devicetree/bindings/sound/qcom,wcd934x.yaml index beb0ff0245b0ab..a65b1d1d5fdd9c 100644 --- a/Documentation/devicetree/bindings/sound/qcom,wcd934x.yaml +++ b/Documentation/devicetree/bindings/sound/qcom,wcd934x.yaml @@ -199,10 +199,11 @@ additionalProperties: false examples: - | + #include codec@1,0{ compatible = "slim217,250"; reg = <1 0>; - reset-gpios = <&tlmm 64 0>; + reset-gpios = <&tlmm 64 GPIO_ACTIVE_LOW>; slim-ifc-dev = <&wcd9340_ifd>; #sound-dai-cells = <1>; interrupt-parent = <&tlmm>; diff --git a/Documentation/devicetree/bindings/sound/qcom,wcd937x.yaml b/Documentation/devicetree/bindings/sound/qcom,wcd937x.yaml index de397d879acc2e..f94203798f24b3 100644 --- a/Documentation/devicetree/bindings/sound/qcom,wcd937x.yaml +++ b/Documentation/devicetree/bindings/sound/qcom,wcd937x.yaml @@ -42,7 +42,7 @@ examples: pinctrl-names = "default", "sleep"; pinctrl-0 = <&wcd_reset_n>; pinctrl-1 = <&wcd_reset_n_sleep>; - reset-gpios = <&tlmm 83 GPIO_ACTIVE_HIGH>; + reset-gpios = <&tlmm 83 GPIO_ACTIVE_LOW>; vdd-buck-supply = <&vreg_l17b_1p8>; vdd-rxtx-supply = <&vreg_l18b_1p8>; vdd-px-supply = <&vreg_l18b_1p8>; diff --git a/Documentation/devicetree/bindings/sound/qcom,wcd938x.yaml b/Documentation/devicetree/bindings/sound/qcom,wcd938x.yaml index cf6c3787adfeff..10531350c33627 100644 --- a/Documentation/devicetree/bindings/sound/qcom,wcd938x.yaml +++ b/Documentation/devicetree/bindings/sound/qcom,wcd938x.yaml @@ -34,9 +34,10 @@ unevaluatedProperties: false examples: - | + #include codec { compatible = "qcom,wcd9380-codec"; - reset-gpios = <&tlmm 32 0>; + reset-gpios = <&tlmm 32 GPIO_ACTIVE_LOW>; #sound-dai-cells = <1>; qcom,tx-device = <&wcd938x_tx>; qcom,rx-device = <&wcd938x_rx>; diff --git a/Documentation/devicetree/bindings/sound/qcom,wcd939x.yaml b/Documentation/devicetree/bindings/sound/qcom,wcd939x.yaml index 6e76f6a8634f07..c69291f4d575ca 100644 --- a/Documentation/devicetree/bindings/sound/qcom,wcd939x.yaml +++ b/Documentation/devicetree/bindings/sound/qcom,wcd939x.yaml @@ -52,10 +52,10 @@ unevaluatedProperties: false examples: - | - #include + #include codec { compatible = "qcom,wcd9390-codec"; - reset-gpios = <&tlmm 32 IRQ_TYPE_NONE>; + reset-gpios = <&tlmm 32 GPIO_ACTIVE_LOW>; #sound-dai-cells = <1>; qcom,tx-device = <&wcd939x_tx>; qcom,rx-device = <&wcd939x_rx>; diff --git a/Documentation/devicetree/bindings/sound/samsung,odroid.yaml b/Documentation/devicetree/bindings/sound/samsung,odroid.yaml index b77284e3e26aa7..c3dea852cc8d34 100644 --- a/Documentation/devicetree/bindings/sound/samsung,odroid.yaml +++ b/Documentation/devicetree/bindings/sound/samsung,odroid.yaml @@ -27,11 +27,6 @@ properties: - const: samsung,odroid-xu4-audio deprecated: true - assigned-clock-parents: true - assigned-clock-rates: true - assigned-clocks: true - clocks: true - cpu: type: object additionalProperties: false diff --git a/Documentation/devicetree/bindings/sound/ti,tlv320dac3100.yaml b/Documentation/devicetree/bindings/sound/ti,tlv320dac3100.yaml new file mode 100644 index 00000000000000..85e937e34962da --- /dev/null +++ b/Documentation/devicetree/bindings/sound/ti,tlv320dac3100.yaml @@ -0,0 +1,127 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/ti,tlv320dac3100.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Texas Instruments - tlv320aic31xx Codec module + +maintainers: + - Shenghao Ding + +description: | + CODEC output pins: + * HPL + * HPR + * SPL, devices with stereo speaker amp + * SPR, devices with stereo speaker amp + * SPK, devices with mono speaker amp + * MICBIAS + + CODEC input pins: + * MIC1LP, devices with ADC + * MIC1RP, devices with ADC + * MIC1LM, devices with ADC + * AIN1, devices without ADC + * AIN2, devices without ADC + + The pins can be used in referring sound node's audio-routing property. + +properties: + compatible: + enum: + - ti,tlv320aic310x # - Generic TLV320AIC31xx with mono speaker amp + - ti,tlv320aic311x # - Generic TLV320AIC31xx with stereo speaker amp + - ti,tlv320aic3100 # - TLV320AIC3100 (mono speaker amp, no MiniDSP) + - ti,tlv320aic3110 # - TLV320AIC3110 (stereo speaker amp, no MiniDSP) + - ti,tlv320aic3120 # - TLV320AIC3120 (mono speaker amp, MiniDSP) + - ti,tlv320aic3111 # - TLV320AIC3111 (stereo speaker amp, MiniDSP) + - ti,tlv320dac3100 # - TLV320DAC3100 (no ADC, mono speaker amp, no MiniDSP) + - ti,tlv320dac3101 # - TLV320DAC3101 (no ADC, stereo speaker amp, no MiniDSP) + + reg: + maxItems: 1 + + '#sound-dai-cells': + const: 0 + + HPVDD-supply: true + + SPRVDD-supply: true + + SPLVDD-supply: true + + AVDD-supply: true + + IOVDD-supply: true + + DVDD-supply: true + + reset-gpios: + description: GPIO specification for the active low RESET input. + + ai31xx-micbias-vg: + $ref: /schemas/types.yaml#/definitions/uint32 + default: 1 + enum: [1, 2, 3] + description: | + MicBias Voltage setting + 1 or MICBIAS_2_0V - MICBIAS output is powered to 2.0V + 2 or MICBIAS_2_5V - MICBIAS output is powered to 2.5V + 3 or MICBIAS_AVDD - MICBIAS output is connected to AVDD + + ai31xx-ocmv: + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [0, 1, 2, 3] + description: | + output common-mode voltage setting + 0 - 1.35V, + 1 - 1.5V, + 2 - 1.65V, + 3 - 1.8V + + gpio-reset: + description: gpio pin number used for codec reset + deprecated: true + + +required: + - compatible + - reg + - HPVDD-supply + - SPRVDD-supply + - SPLVDD-supply + - AVDD-supply + - IOVDD-supply + - DVDD-supply + +allOf: + - $ref: dai-common.yaml# + +unevaluatedProperties: false + +examples: + - | + #include + #include + + i2c { + #address-cells = <1>; + #size-cells = <0>; + + sound@18 { + compatible = "ti,tlv320aic311x"; + reg = <0x18>; + + ai31xx-micbias-vg = ; + reset-gpios = <&gpio1 17 GPIO_ACTIVE_LOW>; + + HPVDD-supply = <®ulator>; + SPRVDD-supply = <®ulator>; + SPLVDD-supply = <®ulator>; + AVDD-supply = <®ulator>; + IOVDD-supply = <®ulator>; + DVDD-supply = <®ulator>; + }; + }; + diff --git a/Documentation/devicetree/bindings/sound/ti,tpa6130a2.yaml b/Documentation/devicetree/bindings/sound/ti,tpa6130a2.yaml new file mode 100644 index 00000000000000..a42bf9bde69400 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/ti,tpa6130a2.yaml @@ -0,0 +1,55 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/ti,tpa6130a2.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Texas Instruments - tpa6130a2 Codec module + +maintainers: + - Sebastian Reichel + +description: + Stereo, analog input headphone amplifier + +properties: + compatible: + enum: + - ti,tpa6130a2 + - ti,tpa6140a2 + + reg: + maxItems: 1 + + Vdd-supply: + description: power supply regulator + + power-gpio: + description: gpio pin to power the device + +required: + - compatible + - reg + - Vdd-supply + +allOf: + - $ref: dai-common.yaml# + +unevaluatedProperties: false + +examples: + - | + #include + + i2c { + #address-cells = <1>; + #size-cells = <0>; + + amplifier@60 { + compatible = "ti,tpa6130a2"; + reg = <0x60>; + Vdd-supply = <&vmmc2>; + power-gpio = <&gpio4 2 GPIO_ACTIVE_HIGH>; + }; + }; + diff --git a/Documentation/devicetree/bindings/sound/tlv320aic31xx.txt b/Documentation/devicetree/bindings/sound/tlv320aic31xx.txt deleted file mode 100644 index bbad98d5b98622..00000000000000 --- a/Documentation/devicetree/bindings/sound/tlv320aic31xx.txt +++ /dev/null @@ -1,77 +0,0 @@ -Texas Instruments - tlv320aic31xx Codec module - -The tlv320aic31xx serial control bus communicates through I2C protocols - -Required properties: - -- compatible - "string" - One of: - "ti,tlv320aic310x" - Generic TLV320AIC31xx with mono speaker amp - "ti,tlv320aic311x" - Generic TLV320AIC31xx with stereo speaker amp - "ti,tlv320aic3100" - TLV320AIC3100 (mono speaker amp, no MiniDSP) - "ti,tlv320aic3110" - TLV320AIC3110 (stereo speaker amp, no MiniDSP) - "ti,tlv320aic3120" - TLV320AIC3120 (mono speaker amp, MiniDSP) - "ti,tlv320aic3111" - TLV320AIC3111 (stereo speaker amp, MiniDSP) - "ti,tlv320dac3100" - TLV320DAC3100 (no ADC, mono speaker amp, no MiniDSP) - "ti,tlv320dac3101" - TLV320DAC3101 (no ADC, stereo speaker amp, no MiniDSP) - -- reg - - I2C slave address -- HPVDD-supply, SPRVDD-supply, SPLVDD-supply, AVDD-supply, IOVDD-supply, - DVDD-supply : power supplies for the device as covered in - Documentation/devicetree/bindings/regulator/regulator.txt - - -Optional properties: - -- reset-gpios - GPIO specification for the active low RESET input. -- ai31xx-micbias-vg - MicBias Voltage setting - 1 or MICBIAS_2_0V - MICBIAS output is powered to 2.0V - 2 or MICBIAS_2_5V - MICBIAS output is powered to 2.5V - 3 or MICBIAS_AVDD - MICBIAS output is connected to AVDD - If this node is not mentioned or if the value is unknown, then - micbias is set to 2.0V. -- ai31xx-ocmv - output common-mode voltage setting - 0 - 1.35V, - 1 - 1.5V, - 2 - 1.65V, - 3 - 1.8V - -Deprecated properties: - -- gpio-reset - gpio pin number used for codec reset - -CODEC output pins: - * HPL - * HPR - * SPL, devices with stereo speaker amp - * SPR, devices with stereo speaker amp - * SPK, devices with mono speaker amp - * MICBIAS - -CODEC input pins: - * MIC1LP, devices with ADC - * MIC1RP, devices with ADC - * MIC1LM, devices with ADC - * AIN1, devices without ADC - * AIN2, devices without ADC - -The pins can be used in referring sound node's audio-routing property. - -Example: -#include -#include - -tlv320aic31xx: tlv320aic31xx@18 { - compatible = "ti,tlv320aic311x"; - reg = <0x18>; - - ai31xx-micbias-vg = ; - - reset-gpios = <&gpio1 17 GPIO_ACTIVE_LOW>; - - HPVDD-supply = <®ulator>; - SPRVDD-supply = <®ulator>; - SPLVDD-supply = <®ulator>; - AVDD-supply = <®ulator>; - IOVDD-supply = <®ulator>; - DVDD-supply = <®ulator>; -}; diff --git a/Documentation/devicetree/bindings/sound/tpa6130a2.txt b/Documentation/devicetree/bindings/sound/tpa6130a2.txt deleted file mode 100644 index 6dfa740e4b2d87..00000000000000 --- a/Documentation/devicetree/bindings/sound/tpa6130a2.txt +++ /dev/null @@ -1,27 +0,0 @@ -Texas Instruments - tpa6130a2 Codec module - -The tpa6130a2 serial control bus communicates through I2C protocols - -Required properties: - -- compatible - "string" - One of: - "ti,tpa6130a2" - TPA6130A2 - "ti,tpa6140a2" - TPA6140A2 - - -- reg - - I2C slave address - -- Vdd-supply - - power supply regulator - -Optional properties: - -- power-gpio - gpio pin to power the device - -Example: - -tpa6130a2: tpa6130a2@60 { - compatible = "ti,tpa6130a2"; - reg = <0x60>; - Vdd-supply = <&vmmc2>; - power-gpio = <&gpio4 2 GPIO_ACTIVE_HIGH>; -}; diff --git a/Documentation/devicetree/bindings/usb/microchip,usb2514.yaml b/Documentation/devicetree/bindings/usb/microchip,usb2514.yaml index 783c27591e564c..245e8c3ce66993 100644 --- a/Documentation/devicetree/bindings/usb/microchip,usb2514.yaml +++ b/Documentation/devicetree/bindings/usb/microchip,usb2514.yaml @@ -18,6 +18,7 @@ properties: - usb424,2412 - usb424,2417 - usb424,2514 + - usb424,2517 reg: true diff --git a/Documentation/driver-api/thermal/sysfs-api.rst b/Documentation/driver-api/thermal/sysfs-api.rst index 6c1175c6afba99..978198f8a18bed 100644 --- a/Documentation/driver-api/thermal/sysfs-api.rst +++ b/Documentation/driver-api/thermal/sysfs-api.rst @@ -4,8 +4,6 @@ Generic Thermal Sysfs driver How To Written by Sujith Thomas , Zhang Rui -Updated: 2 January 2008 - Copyright (c) 2008 Intel Corporation @@ -38,23 +36,23 @@ temperature) and throttle appropriate devices. :: - struct thermal_zone_device - *thermal_zone_device_register(char *type, - int trips, int mask, void *devdata, - struct thermal_zone_device_ops *ops, - const struct thermal_zone_params *tzp, - int passive_delay, int polling_delay)) + struct thermal_zone_device * + thermal_zone_device_register_with_trips(const char *type, + const struct thermal_trip *trips, + int num_trips, void *devdata, + const struct thermal_zone_device_ops *ops, + const struct thermal_zone_params *tzp, + unsigned int passive_delay, + unsigned int polling_delay) - This interface function adds a new thermal zone device (sensor) to + This interface function adds a new thermal zone device (sensor) to the /sys/class/thermal folder as `thermal_zone[0-*]`. It tries to bind all the - thermal cooling devices registered at the same time. + thermal cooling devices registered to it at the same time. type: the thermal zone type. trips: - the total number of trip points this thermal zone supports. - mask: - Bit string: If 'n'th bit is set, then trip point 'n' is writable. + the table of trip points for this thermal zone. devdata: device private data ops: @@ -67,32 +65,29 @@ temperature) and throttle appropriate devices. .get_temp: get the current temperature of the thermal zone. .set_trips: - set the trip points window. Whenever the current temperature - is updated, the trip points immediately below and above the - current temperature are found. - .get_mode: - get the current mode (enabled/disabled) of the thermal zone. - - - "enabled" means the kernel thermal management is - enabled. - - "disabled" will prevent kernel thermal driver action - upon trip points so that user applications can take - charge of thermal management. - .set_mode: - set the mode (enabled/disabled) of the thermal zone. - .get_trip_type: - get the type of certain trip point. - .get_trip_temp: - get the temperature above which the certain trip point - will be fired. + set the trip points window. Whenever the current temperature + is updated, the trip points immediately below and above the + current temperature are found. + .change_mode: + change the mode (enabled/disabled) of the thermal zone. + .set_trip_temp: + set the temperature of a given trip point. + .get_crit_temp: + get the critical temperature for this thermal zone. .set_emul_temp: - set the emulation temperature which helps in debugging - different threshold temperature points. + set the emulation temperature which helps in debugging + different threshold temperature points. + .get_trend: + get the trend of most recent zone temperature changes. + .hot: + hot trip point crossing handler. + .critical: + critical trip point crossing handler. tzp: thermal zone platform parameters. passive_delay: - number of milliseconds to wait between polls when - performing passive cooling. + number of milliseconds to wait between polls when performing passive + cooling. polling_delay: number of milliseconds to wait between polls when checking whether trip points have been crossed (0 for interrupt driven systems). diff --git a/Documentation/filesystems/caching/fscache.rst b/Documentation/filesystems/caching/fscache.rst index a74d7b052dc130..de1f32526cc1c4 100644 --- a/Documentation/filesystems/caching/fscache.rst +++ b/Documentation/filesystems/caching/fscache.rst @@ -318,10 +318,10 @@ where the columns are: Debugging ========= -If CONFIG_FSCACHE_DEBUG is enabled, the FS-Cache facility can have runtime -debugging enabled by adjusting the value in:: +If CONFIG_NETFS_DEBUG is enabled, the FS-Cache facility and NETFS support can +have runtime debugging enabled by adjusting the value in:: - /sys/module/fscache/parameters/debug + /sys/module/netfs/parameters/debug This is a bitmask of debugging streams to enable: @@ -343,6 +343,6 @@ This is a bitmask of debugging streams to enable: The appropriate set of values should be OR'd together and the result written to the control file. For example:: - echo $((1|8|512)) >/sys/module/fscache/parameters/debug + echo $((1|8|512)) >/sys/module/netfs/parameters/debug will turn on all function entry debugging. diff --git a/Documentation/netlink/specs/ethtool.yaml b/Documentation/netlink/specs/ethtool.yaml index 495e35fcfb218c..ea21fe135b97eb 100644 --- a/Documentation/netlink/specs/ethtool.yaml +++ b/Documentation/netlink/specs/ethtool.yaml @@ -1753,6 +1753,7 @@ operations: request: attributes: - header + - context reply: attributes: - header @@ -1761,7 +1762,6 @@ operations: - indir - hkey - input_xfrm - dump: *rss-get-op - name: plca-get-cfg doc: Get PLCA params. diff --git a/Documentation/networking/ethtool-netlink.rst b/Documentation/networking/ethtool-netlink.rst index 3ab423b80e913c..d5f246aceb9f48 100644 --- a/Documentation/networking/ethtool-netlink.rst +++ b/Documentation/networking/ethtool-netlink.rst @@ -1875,6 +1875,7 @@ Kernel response contents: ===================================== ====== ========================== ``ETHTOOL_A_RSS_HEADER`` nested reply header + ``ETHTOOL_A_RSS_CONTEXT`` u32 context number ``ETHTOOL_A_RSS_HFUNC`` u32 RSS hash func ``ETHTOOL_A_RSS_INDIR`` binary Indir table bytes ``ETHTOOL_A_RSS_HKEY`` binary Hash key bytes diff --git a/Documentation/process/embargoed-hardware-issues.rst b/Documentation/process/embargoed-hardware-issues.rst index 6e9a4597bf2cbb..daebce49cfdf5f 100644 --- a/Documentation/process/embargoed-hardware-issues.rst +++ b/Documentation/process/embargoed-hardware-issues.rst @@ -13,9 +13,9 @@ kernel. Hardware issues like Meltdown, Spectre, L1TF etc. must be treated differently because they usually affect all Operating Systems ("OS") and therefore need coordination across different OS vendors, distributions, -hardware vendors and other parties. For some of the issues, software -mitigations can depend on microcode or firmware updates, which need further -coordination. +silicon vendors, hardware integrators, and other parties. For some of the +issues, software mitigations can depend on microcode or firmware updates, +which need further coordination. .. _Contact: @@ -32,8 +32,8 @@ Linux kernel security team (:ref:`Documentation/admin-guide/ `) instead. The team can be contacted by email at . This -is a private list of security officers who will help you to coordinate a -fix according to our documented process. +is a private list of security officers who will help you coordinate a fix +according to our documented process. The list is encrypted and email to the list can be sent by either PGP or S/MIME encrypted and must be signed with the reporter's PGP key or S/MIME @@ -43,7 +43,7 @@ the following URLs: - PGP: https://www.kernel.org/static/files/hardware-security.asc - S/MIME: https://www.kernel.org/static/files/hardware-security.crt -While hardware security issues are often handled by the affected hardware +While hardware security issues are often handled by the affected silicon vendor, we welcome contact from researchers or individuals who have identified a potential hardware flaw. @@ -65,7 +65,7 @@ of Linux Foundation's IT operations personnel technically have the ability to access the embargoed information, but are obliged to confidentiality by their employment contract. Linux Foundation IT personnel are also responsible for operating and managing the rest of -kernel.org infrastructure. +kernel.org's infrastructure. The Linux Foundation's current director of IT Project infrastructure is Konstantin Ryabitsev. @@ -85,7 +85,7 @@ Memorandum of Understanding The Linux kernel community has a deep understanding of the requirement to keep hardware security issues under embargo for coordination between -different OS vendors, distributors, hardware vendors and other parties. +different OS vendors, distributors, silicon vendors, and other parties. The Linux kernel community has successfully handled hardware security issues in the past and has the necessary mechanisms in place to allow @@ -103,11 +103,11 @@ the issue in the best technical way. All involved developers pledge to adhere to the embargo rules and to keep the received information confidential. Violation of the pledge will lead to immediate exclusion from the current issue and removal from all related -mailing-lists. In addition, the hardware security team will also exclude +mailing lists. In addition, the hardware security team will also exclude the offender from future issues. The impact of this consequence is a highly effective deterrent in our community. In case a violation happens the hardware security team will inform the involved parties immediately. If you -or anyone becomes aware of a potential violation, please report it +or anyone else becomes aware of a potential violation, please report it immediately to the Hardware security officers. @@ -124,14 +124,16 @@ method for these types of issues. Start of Disclosure """"""""""""""""""" -Disclosure starts by contacting the Linux kernel hardware security team by -email. This initial contact should contain a description of the problem and -a list of any known affected hardware. If your organization builds or -distributes the affected hardware, we encourage you to also consider what -other hardware could be affected. +Disclosure starts by emailing the Linux kernel hardware security team per +the Contact section above. This initial contact should contain a +description of the problem and a list of any known affected silicon. If +your organization builds or distributes the affected hardware, we encourage +you to also consider what other hardware could be affected. The disclosing +party is responsible for contacting the affected silicon vendors in a +timely manner. The hardware security team will provide an incident-specific encrypted -mailing-list which will be used for initial discussion with the reporter, +mailing list which will be used for initial discussion with the reporter, further disclosure, and coordination of fixes. The hardware security team will provide the disclosing party a list of @@ -158,8 +160,8 @@ This serves several purposes: - The disclosed entities can be contacted to name experts who should participate in the mitigation development. - - If an expert which is required to handle an issue is employed by an - listed entity or member of an listed entity, then the response teams can + - If an expert who is required to handle an issue is employed by a listed + entity or member of an listed entity, then the response teams can request the disclosure of that expert from that entity. This ensures that the expert is also part of the entity's response team. @@ -169,8 +171,8 @@ Disclosure The disclosing party provides detailed information to the initial response team via the specific encrypted mailing-list. -From our experience the technical documentation of these issues is usually -a sufficient starting point and further technical clarification is best +From our experience, the technical documentation of these issues is usually +a sufficient starting point, and further technical clarification is best done via email. Mitigation development @@ -179,57 +181,93 @@ Mitigation development The initial response team sets up an encrypted mailing-list or repurposes an existing one if appropriate. -Using a mailing-list is close to the normal Linux development process and -has been successfully used in developing mitigations for various hardware +Using a mailing list is close to the normal Linux development process and +has been successfully used to develop mitigations for various hardware security issues in the past. -The mailing-list operates in the same way as normal Linux development. -Patches are posted, discussed and reviewed and if agreed on applied to a -non-public git repository which is only accessible to the participating +The mailing list operates in the same way as normal Linux development. +Patches are posted, discussed, and reviewed and if agreed upon, applied to +a non-public git repository which is only accessible to the participating developers via a secure connection. The repository contains the main development branch against the mainline kernel and backport branches for stable kernel versions as necessary. The initial response team will identify further experts from the Linux -kernel developer community as needed. Bringing in experts can happen at any -time of the development process and needs to be handled in a timely manner. +kernel developer community as needed. Any involved party can suggest +further experts to be included, each of which will be subject to the same +requirements outlined above. -If an expert is employed by or member of an entity on the disclosure list +Bringing in experts can happen at any time in the development process and +needs to be handled in a timely manner. + +If an expert is employed by or a member of an entity on the disclosure list provided by the disclosing party, then participation will be requested from the relevant entity. -If not, then the disclosing party will be informed about the experts +If not, then the disclosing party will be informed about the experts' participation. The experts are covered by the Memorandum of Understanding -and the disclosing party is requested to acknowledge the participation. In -case that the disclosing party has a compelling reason to object, then this -objection has to be raised within five work days and resolved with the -incident team immediately. If the disclosing party does not react within -five work days this is taken as silent acknowledgement. +and the disclosing party is requested to acknowledge their participation. +In the case where the disclosing party has a compelling reason to object, +any objection must to be raised within five working days and resolved with +the incident team immediately. If the disclosing party does not react +within five working days this is taken as silent acknowledgment. -After acknowledgement or resolution of an objection the expert is disclosed -by the incident team and brought into the development process. +After the incident team acknowledges or resolves an objection, the expert +is disclosed and brought into the development process. List participants may not communicate about the issue outside of the private mailing list. List participants may not use any shared resources (e.g. employer build farms, CI systems, etc) when working on patches. +Early access +"""""""""""" + +The patches discussed and developed on the list can neither be distributed +to any individual who is not a member of the response team nor to any other +organization. + +To allow the affected silicon vendors to work with their internal teams and +industry partners on testing, validation, and logistics, the following +exception is provided: + + Designated representatives of the affected silicon vendors are + allowed to hand over the patches at any time to the silicon + vendor’s response team. The representative must notify the kernel + response team about the handover. The affected silicon vendor must + have and maintain their own documented security process for any + patches shared with their response team that is consistent with + this policy. + + The silicon vendor’s response team can distribute these patches to + their industry partners and to their internal teams under the + silicon vendor’s documented security process. Feedback from the + industry partners goes back to the silicon vendor and is + communicated by the silicon vendor to the kernel response team. + + The handover to the silicon vendor’s response team removes any + responsibility or liability from the kernel response team regarding + premature disclosure, which happens due to the involvement of the + silicon vendor’s internal teams or industry partners. The silicon + vendor guarantees this release of liability by agreeing to this + process. Coordinated release """"""""""""""""""" -The involved parties will negotiate the date and time where the embargo -ends. At that point the prepared mitigations are integrated into the -relevant kernel trees and published. There is no pre-notification process: -fixes are published in public and available to everyone at the same time. +The involved parties will negotiate the date and time when the embargo +ends. At that point, the prepared mitigations are published into the +relevant kernel trees. There is no pre-notification process: the +mitigations are published in public and available to everyone at the same +time. While we understand that hardware security issues need coordinated embargo -time, the embargo time should be constrained to the minimum time which is -required for all involved parties to develop, test and prepare the +time, the embargo time should be constrained to the minimum time that is +required for all involved parties to develop, test, and prepare their mitigations. Extending embargo time artificially to meet conference talk -dates or other non-technical reasons is creating more work and burden for -the involved developers and response teams as the patches need to be kept -up to date in order to follow the ongoing upstream kernel development, -which might create conflicting changes. +dates or other non-technical reasons creates more work and burden for the +involved developers and response teams as the patches need to be kept up to +date in order to follow the ongoing upstream kernel development, which +might create conflicting changes. CVE assignment """""""""""""" @@ -275,34 +313,35 @@ an involved disclosed party. The current ambassadors list: If you want your organization to be added to the ambassadors list, please contact the hardware security team. The nominated ambassador has to -understand and support our process fully and is ideally well connected in +understand and support our process fully and is ideally well-connected in the Linux kernel community. Encrypted mailing-lists ----------------------- -We use encrypted mailing-lists for communication. The operating principle +We use encrypted mailing lists for communication. The operating principle of these lists is that email sent to the list is encrypted either with the -list's PGP key or with the list's S/MIME certificate. The mailing-list +list's PGP key or with the list's S/MIME certificate. The mailing list software decrypts the email and re-encrypts it individually for each subscriber with the subscriber's PGP key or S/MIME certificate. Details -about the mailing-list software and the setup which is used to ensure the +about the mailing list software and the setup that is used to ensure the security of the lists and protection of the data can be found here: https://korg.wiki.kernel.org/userdoc/remail. List keys ^^^^^^^^^ -For initial contact see :ref:`Contact`. For incident specific mailing-lists -the key and S/MIME certificate are conveyed to the subscribers by email -sent from the specific list. +For initial contact see the :ref:`Contact` section above. For incident +specific mailing lists, the key and S/MIME certificate are conveyed to the +subscribers by email sent from the specific list. -Subscription to incident specific lists +Subscription to incident-specific lists ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Subscription is handled by the response teams. Disclosed parties who want -to participate in the communication send a list of potential subscribers to -the response team so the response team can validate subscription requests. +Subscription to incident-specific lists is handled by the response teams. +Disclosed parties who want to participate in the communication send a list +of potential experts to the response team so the response team can validate +subscription requests. Each subscriber needs to send a subscription request to the response team by email. The email must be signed with the subscriber's PGP key or S/MIME diff --git a/Documentation/sound/hd-audio/notes.rst b/Documentation/sound/hd-audio/notes.rst index ef6a4513cce77a..e199131bf5abbb 100644 --- a/Documentation/sound/hd-audio/notes.rst +++ b/Documentation/sound/hd-audio/notes.rst @@ -321,12 +321,6 @@ Kernel Configuration -------------------- In general, I recommend you to enable the sound debug option, ``CONFIG_SND_DEBUG=y``, no matter whether you are debugging or not. -This enables snd_printd() macro and others, and you'll get additional -kernel messages at probing. - -In addition, you can enable ``CONFIG_SND_DEBUG_VERBOSE=y``. But this -will give you far more messages. Thus turn this on only when you are -sure to want it. Don't forget to turn on the appropriate ``CONFIG_SND_HDA_CODEC_*`` options. Note that each of them corresponds to the codec chip, not diff --git a/Documentation/sound/index.rst b/Documentation/sound/index.rst index 7e67e12730d3b4..c437f2a4bc85f0 100644 --- a/Documentation/sound/index.rst +++ b/Documentation/sound/index.rst @@ -13,6 +13,7 @@ Sound Subsystem Documentation alsa-configuration hd-audio/index cards/index + utimers .. only:: subproject and html diff --git a/Documentation/sound/kernel-api/writing-an-alsa-driver.rst b/Documentation/sound/kernel-api/writing-an-alsa-driver.rst index 801b0bb57e9740..895752cbcedd6b 100644 --- a/Documentation/sound/kernel-api/writing-an-alsa-driver.rst +++ b/Documentation/sound/kernel-api/writing-an-alsa-driver.rst @@ -4030,31 +4030,6 @@ located in the new subdirectory, sound/pci/xyz. Useful Functions ================ -:c:func:`snd_printk()` and friends ----------------------------------- - -.. note:: This subsection describes a few helper functions for - decorating a bit more on the standard :c:func:`printk()` & co. - However, in general, the use of such helpers is no longer recommended. - If possible, try to stick with the standard functions like - :c:func:`dev_err()` or :c:func:`pr_err()`. - -ALSA provides a verbose version of the :c:func:`printk()` function. -If a kernel config ``CONFIG_SND_VERBOSE_PRINTK`` is set, this function -prints the given message together with the file name and the line of the -caller. The ``KERN_XXX`` prefix is processed as well as the original -:c:func:`printk()` does, so it's recommended to add this prefix, -e.g. snd_printk(KERN_ERR "Oh my, sorry, it's extremely bad!\\n"); - -There are also :c:func:`printk()`'s for debugging. -:c:func:`snd_printd()` can be used for general debugging purposes. -If ``CONFIG_SND_DEBUG`` is set, this function is compiled, and works -just like :c:func:`snd_printk()`. If the ALSA is compiled without -the debugging flag, it's ignored. - -:c:func:`snd_printdd()` is compiled in only when -``CONFIG_SND_DEBUG_VERBOSE`` is set. - :c:func:`snd_BUG()` ------------------- diff --git a/Documentation/sound/utimers.rst b/Documentation/sound/utimers.rst new file mode 100644 index 00000000000000..ec21567d3f723d --- /dev/null +++ b/Documentation/sound/utimers.rst @@ -0,0 +1,126 @@ +.. SPDX-License-Identifier: GPL-2.0 + +======================= +Userspace-driven timers +======================= + +:Author: Ivan Orlov + +Preface +======= + +This document describes the userspace-driven timers: virtual ALSA timers +which could be created and controlled by userspace applications using +IOCTL calls. Such timers could be useful when synchronizing audio +stream with timer sources which we don't have ALSA timers exported for +(e.g. PTP clocks), and when synchronizing the audio stream going through +two virtual sound devices using ``snd-aloop`` (for instance, when +we have a network application sending frames to one snd-aloop device, +and another sound application listening on the other end of snd-aloop). + +Enabling userspace-driven timers +================================ + +The userspace-driven timers could be enabled in the kernel using the +``CONFIG_SND_UTIMER`` configuration option. It depends on the +``CONFIG_SND_TIMER`` option, so it also should be enabled. + +Userspace-driven timers API +=========================== + +Userspace application can create a userspace-driven ALSA timer by +executing the ``SNDRV_TIMER_IOCTL_CREATE`` ioctl call on the +``/dev/snd/timer`` device file descriptor. The ``snd_timer_uinfo`` +structure should be passed as an ioctl argument: + +:: + + struct snd_timer_uinfo { + __u64 resolution; + int fd; + unsigned int id; + unsigned char reserved[16]; + } + +The ``resolution`` field sets the desired resolution in nanoseconds for +the virtual timer. ``resolution`` field simply provides an information +about the virtual timer, but does not affect the timing itself. ``id`` +field gets overwritten by the ioctl, and the identifier you get in this +field after the call can be used as a timer subdevice number when +passing the timer to ``snd-aloop`` kernel module or other userspace +applications. There could be up to 128 userspace-driven timers in the +system at one moment of time, thus the id value ranges from 0 to 127. + +Besides from overwriting the ``snd_timer_uinfo`` struct, ioctl stores +a timer file descriptor, which can be used to trigger the timer, in the +``fd`` field of the ``snd_timer_uinfo`` struct. Allocation of a file +descriptor for the timer guarantees that the timer can only be triggered +by the process which created it. The timer then can be triggered with +``SNDRV_TIMER_IOCTL_TRIGGER`` ioctl call on the timer file descriptor. + +So, the example code for creating and triggering the timer would be: + +:: + + static struct snd_timer_uinfo utimer_info = { + /* Timer is going to tick (presumably) every 1000000 ns */ + .resolution = 1000000ULL, + .id = -1, + }; + + int timer_device_fd = open("/dev/snd/timer", O_RDWR | O_CLOEXEC); + + if (ioctl(timer_device_fd, SNDRV_TIMER_IOCTL_CREATE, &utimer_info)) { + perror("Failed to create the timer"); + return -1; + } + + ... + + /* + * Now we want to trigger the timer. Callbacks of all of the + * timer instances binded to this timer will be executed after + * this call. + */ + ioctl(utimer_info.fd, SNDRV_TIMER_IOCTL_TRIGGER, NULL); + + ... + + /* Now, destroy the timer */ + close(timer_info.fd); + + +More detailed example of creating and ticking the timer could be found +in the utimer ALSA selftest. + +Userspace-driven timers and snd-aloop +------------------------------------- + +Userspace-driven timers could be easily used with ``snd-aloop`` module +when synchronizing two sound applications on both ends of the virtual +sound loopback. For instance, if one of the applications receives sound +frames from network and sends them to snd-aloop pcm device, and another +application listens for frames on the other snd-aloop pcm device, it +makes sense that the ALSA middle layer should initiate a data +transaction when the new period of data is received through network, but +not when the certain amount of jiffies elapses. Userspace-driven ALSA +timers could be used to achieve this. + +To use userspace-driven ALSA timer as a timer source of snd-aloop, pass +the following string as the snd-aloop ``timer_source`` parameter: + +:: + + # modprobe snd-aloop timer_source="-1.4." + +Where ``utimer_id`` is the id of the timer you created with +``SNDRV_TIMER_IOCTL_CREATE``, and ``4`` is the number of +userspace-driven timers device (``SNDRV_TIMER_GLOBAL_UDRIVEN``). + +``resolution`` for the userspace-driven ALSA timer used with snd-aloop +should be calculated as ``1000000000ULL / frame_rate * period_size`` as +the timer is going to tick every time a new period of frames is ready. + +After that, each time you trigger the timer with +``SNDRV_TIMER_IOCTL_TRIGGER`` the new period of data will be transferred +from one snd-aloop device to another. diff --git a/Documentation/userspace-api/media/v4l/pixfmt-yuv-luma.rst b/Documentation/userspace-api/media/v4l/pixfmt-yuv-luma.rst index f02e6cf3516a20..74df19be91f69d 100644 --- a/Documentation/userspace-api/media/v4l/pixfmt-yuv-luma.rst +++ b/Documentation/userspace-api/media/v4l/pixfmt-yuv-luma.rst @@ -21,9 +21,9 @@ are often referred to as greyscale formats. .. raw:: latex - \scriptsize + \tiny -.. tabularcolumns:: |p{3.6cm}|p{3.0cm}|p{1.3cm}|p{2.6cm}|p{1.3cm}|p{1.3cm}|p{1.3cm}| +.. tabularcolumns:: |p{3.6cm}|p{2.4cm}|p{1.3cm}|p{1.3cm}|p{1.3cm}|p{1.3cm}|p{1.3cm}|p{1.3cm}|p{1.3cm}| .. flat-table:: Luma-Only Image Formats :header-rows: 1 diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst index fe722c5dada9f8..b3be87489108e8 100644 --- a/Documentation/virt/kvm/api.rst +++ b/Documentation/virt/kvm/api.rst @@ -2592,7 +2592,7 @@ Specifically: 0x6030 0000 0010 004a SPSR_ABT 64 spsr[KVM_SPSR_ABT] 0x6030 0000 0010 004c SPSR_UND 64 spsr[KVM_SPSR_UND] 0x6030 0000 0010 004e SPSR_IRQ 64 spsr[KVM_SPSR_IRQ] - 0x6060 0000 0010 0050 SPSR_FIQ 64 spsr[KVM_SPSR_FIQ] + 0x6030 0000 0010 0050 SPSR_FIQ 64 spsr[KVM_SPSR_FIQ] 0x6040 0000 0010 0054 V0 128 fp_regs.vregs[0] [1]_ 0x6040 0000 0010 0058 V1 128 fp_regs.vregs[1] [1]_ ... @@ -6368,7 +6368,7 @@ a single guest_memfd file, but the bound ranges must not overlap). See KVM_SET_USER_MEMORY_REGION2 for additional details. 4.143 KVM_PRE_FAULT_MEMORY ------------------------- +--------------------------- :Capability: KVM_CAP_PRE_FAULT_MEMORY :Architectures: none @@ -6405,6 +6405,12 @@ for the current vCPU state. KVM maps memory as if the vCPU generated a stage-2 read page fault, e.g. faults in memory as needed, but doesn't break CoW. However, KVM does not mark any newly created stage-2 PTE as Accessed. +In the case of confidential VM types where there is an initial set up of +private guest memory before the guest is 'finalized'/measured, this ioctl +should only be issued after completing all the necessary setup to put the +guest into a 'finalized' state so that the above semantics can be reliably +ensured. + In some cases, multiple vCPUs might share the page tables. In this case, the ioctl can be called in parallel. diff --git a/Documentation/wmi/devices/msi-wmi-platform.rst b/Documentation/wmi/devices/msi-wmi-platform.rst index 29b1b2e6d42cdc..31a13694289238 100644 --- a/Documentation/wmi/devices/msi-wmi-platform.rst +++ b/Documentation/wmi/devices/msi-wmi-platform.rst @@ -130,12 +130,12 @@ data using the `bmfdec `_ utility: Due to a peculiarity in how Windows handles the ``CreateByteField()`` ACPI operator (errors only happen when a invalid byte field is ultimately accessed), all methods require a 32 byte input -buffer, even if the Binay MOF says otherwise. +buffer, even if the Binary MOF says otherwise. The input buffer contains a single byte to select the subfeature to be accessed and 31 bytes of input data, the meaning of which depends on the subfeature being accessed. -The output buffer contains a singe byte which signals success or failure (``0x00`` on failure) +The output buffer contains a single byte which signals success or failure (``0x00`` on failure) and 31 bytes of output data, the meaning if which depends on the subfeature being accessed. WMI method Get_EC() @@ -147,7 +147,7 @@ data contains a flag byte and a 28 byte controller firmware version string. The first 4 bits of the flag byte contain the minor version of the embedded controller interface, with the next 2 bits containing the major version of the embedded controller interface. -The 7th bit signals if the embedded controller page chaged (exact meaning is unknown), and the +The 7th bit signals if the embedded controller page changed (exact meaning is unknown), and the last bit signals if the platform is a Tigerlake platform. The MSI software seems to only use this interface when the last bit is set. diff --git a/MAINTAINERS b/MAINTAINERS index 88a40557db32d4..1d12f3fca229e8 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5306,7 +5306,7 @@ F: drivers/media/cec/i2c/ch7322.c CIRRUS LOGIC AUDIO CODEC DRIVERS M: David Rhodes M: Richard Fitzgerald -L: alsa-devel@alsa-project.org (moderated for non-subscribers) +L: linux-sound@vger.kernel.org L: patches@opensource.cirrus.com S: Maintained F: Documentation/devicetree/bindings/sound/cirrus,cs* @@ -5375,7 +5375,7 @@ F: sound/soc/codecs/lochnagar-sc.c CIRRUS LOGIC MADERA CODEC DRIVERS M: Charles Keepax M: Richard Fitzgerald -L: alsa-devel@alsa-project.org (moderated for non-subscribers) +L: linux-sound@vger.kernel.org L: patches@opensource.cirrus.com S: Supported W: https://github.com/CirrusLogic/linux-drivers/wiki @@ -13325,14 +13325,16 @@ F: Documentation/devicetree/bindings/i2c/i2c-mux-ltc4306.txt F: drivers/i2c/muxes/i2c-mux-ltc4306.c LTP (Linux Test Project) +M: Andrea Cervesato M: Cyril Hrubis M: Jan Stancek M: Petr Vorel M: Li Wang M: Yang Xu +M: Xiao Yang L: ltp@lists.linux.it (subscribers-only) S: Maintained -W: http://linux-test-project.github.io/ +W: https://linux-test-project.readthedocs.io/ T: git https://github.com/linux-test-project/ltp.git LTR390 AMBIENT/UV LIGHT SENSOR DRIVER @@ -13540,7 +13542,7 @@ MARVELL GIGABIT ETHERNET DRIVERS (skge/sky2) M: Mirko Lindner M: Stephen Hemminger L: netdev@vger.kernel.org -S: Maintained +S: Odd fixes F: drivers/net/ethernet/marvell/sk* MARVELL LIBERTAS WIRELESS DRIVER @@ -15937,6 +15939,7 @@ F: include/linux/in.h F: include/linux/indirect_call_wrapper.h F: include/linux/net.h F: include/linux/netdevice.h +F: include/linux/skbuff.h F: include/net/ F: include/uapi/linux/in.h F: include/uapi/linux/net.h @@ -18523,7 +18526,6 @@ F: drivers/crypto/intel/qat/ QCOM AUDIO (ASoC) DRIVERS M: Srinivas Kandagatla -M: Banajit Goswami L: alsa-devel@alsa-project.org (moderated for non-subscribers) L: linux-arm-msm@vger.kernel.org S: Supported @@ -18557,7 +18559,7 @@ F: drivers/usb/misc/qcom_eud.c QCOM IPA DRIVER M: Alex Elder L: netdev@vger.kernel.org -S: Supported +S: Maintained F: drivers/net/ipa/ QEMU MACHINE EMULATOR AND VIRTUALIZER SUPPORT @@ -22577,12 +22579,12 @@ F: Documentation/devicetree/bindings/sound/tas2552.txt F: Documentation/devicetree/bindings/sound/ti,tas2562.yaml F: Documentation/devicetree/bindings/sound/ti,tas2770.yaml F: Documentation/devicetree/bindings/sound/ti,tas27xx.yaml +F: Documentation/devicetree/bindings/sound/ti,tpa6130a2.yaml F: Documentation/devicetree/bindings/sound/ti,pcm1681.yaml F: Documentation/devicetree/bindings/sound/ti,pcm3168a.yaml F: Documentation/devicetree/bindings/sound/ti,tlv320*.yaml F: Documentation/devicetree/bindings/sound/ti,tlv320adcx140.yaml F: Documentation/devicetree/bindings/sound/tlv320aic31xx.txt -F: Documentation/devicetree/bindings/sound/tpa6130a2.txt F: include/sound/tas2*.h F: include/sound/tlv320*.h F: include/sound/tpa6130a2-plat.h diff --git a/Makefile b/Makefile index 8ad55d6e7b60f2..68ebd6d6b444df 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ VERSION = 6 PATCHLEVEL = 11 SUBLEVEL = 0 -EXTRAVERSION = -rc1 +EXTRAVERSION = -rc4 NAME = Baby Opossum Posse # *DOCUMENTATION* @@ -1963,7 +1963,7 @@ tags TAGS cscope gtags: FORCE # Protocol). PHONY += rust-analyzer rust-analyzer: - $(Q)$(CONFIG_SHELL) $(srctree)/scripts/rust_is_available.sh + +$(Q)$(CONFIG_SHELL) $(srctree)/scripts/rust_is_available.sh $(Q)$(MAKE) $(build)=rust $@ # Script to generate missing namespace dependencies diff --git a/arch/alpha/include/asm/io.h b/arch/alpha/include/asm/io.h index 2bb8cbeedf9160..b191d87f89c401 100644 --- a/arch/alpha/include/asm/io.h +++ b/arch/alpha/include/asm/io.h @@ -534,8 +534,10 @@ extern inline void writeq(u64 b, volatile void __iomem *addr) #define ioread16be(p) swab16(ioread16(p)) #define ioread32be(p) swab32(ioread32(p)) +#define ioread64be(p) swab64(ioread64(p)) #define iowrite16be(v,p) iowrite16(swab16(v), (p)) #define iowrite32be(v,p) iowrite32(swab32(v), (p)) +#define iowrite64be(v,p) iowrite64(swab64(v), (p)) #define inb_p inb #define inw_p inw @@ -634,8 +636,6 @@ extern void outsl (unsigned long port, const void *src, unsigned long count); */ #define ioread64 ioread64 #define iowrite64 iowrite64 -#define ioread64be ioread64be -#define iowrite64be iowrite64be #define ioread8_rep ioread8_rep #define ioread16_rep ioread16_rep #define ioread32_rep ioread32_rep diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 954a1916a5003b..54b2bb817a7fc0 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -87,6 +87,7 @@ config ARM select HAVE_ARCH_PFN_VALID select HAVE_ARCH_SECCOMP select HAVE_ARCH_SECCOMP_FILTER if AEABI && !OABI_COMPAT + select HAVE_ARCH_STACKLEAK select HAVE_ARCH_THREAD_STRUCT_WHITELIST select HAVE_ARCH_TRACEHOOK select HAVE_ARCH_TRANSPARENT_HUGEPAGE if ARM_LPAE @@ -116,6 +117,7 @@ config ARM 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 select HAVE_MOD_ARCH_SPECIFIC select HAVE_NMI select HAVE_OPTPROBES if !THUMB2_KERNEL @@ -736,7 +738,7 @@ config ARM_ERRATA_764319 bool "ARM errata: Read to DBGPRSR and DBGOSLSR may generate Undefined instruction" depends on CPU_V7 help - This option enables the workaround for the 764319 Cortex A-9 erratum. + This option enables the workaround for the 764319 Cortex-A9 erratum. CP14 read accesses to the DBGPRSR and DBGOSLSR registers generate an unexpected Undefined Instruction exception when the DBGSWENABLE external pin is set to 0, even when the CP14 accesses are performed diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile index 6bca03c0c7f0e2..945b5975fce200 100644 --- a/arch/arm/boot/compressed/Makefile +++ b/arch/arm/boot/compressed/Makefile @@ -9,6 +9,7 @@ OBJS = HEAD = head.o OBJS += misc.o decompress.o +CFLAGS_decompress.o += $(DISABLE_STACKLEAK_PLUGIN) ifeq ($(CONFIG_DEBUG_UNCOMPRESS),y) OBJS += debug.o AFLAGS_head.o += -DDEBUG diff --git a/arch/arm/boot/compressed/vmlinux.lds.S b/arch/arm/boot/compressed/vmlinux.lds.S index 3fcb3e62dc5692..d411abd4310ea9 100644 --- a/arch/arm/boot/compressed/vmlinux.lds.S +++ b/arch/arm/boot/compressed/vmlinux.lds.S @@ -125,7 +125,7 @@ SECTIONS . = BSS_START; __bss_start = .; - .bss : { *(.bss) } + .bss : { *(.bss .bss.*) } _end = .; . = ALIGN(8); /* the stack must be 64-bit aligned */ diff --git a/arch/arm/boot/dts/arm/versatile-ab.dts b/arch/arm/boot/dts/arm/versatile-ab.dts index 6fe6b49f5d8ecf..635ab92688999a 100644 --- a/arch/arm/boot/dts/arm/versatile-ab.dts +++ b/arch/arm/boot/dts/arm/versatile-ab.dts @@ -157,7 +157,7 @@ clocks = <&xtal24mhz>; }; - pclk: clock-24000000 { + pclk: clock-pclk { #clock-cells = <0>; compatible = "fixed-factor-clock"; clock-div = <1>; diff --git a/arch/arm/include/asm/stacktrace.h b/arch/arm/include/asm/stacktrace.h index 360f0d2406bfa0..f80a85b091d6c4 100644 --- a/arch/arm/include/asm/stacktrace.h +++ b/arch/arm/include/asm/stacktrace.h @@ -26,6 +26,13 @@ struct stackframe { #endif }; +static inline bool on_thread_stack(void) +{ + unsigned long delta = current_stack_pointer ^ (unsigned long)current->stack; + + return delta < THREAD_SIZE; +} + static __always_inline void arm_get_current_stackframe(struct pt_regs *regs, struct stackframe *frame) { diff --git a/arch/arm/include/asm/vmlinux.lds.h b/arch/arm/include/asm/vmlinux.lds.h index 4c8632d5c432c3..d60f6e83a9f700 100644 --- a/arch/arm/include/asm/vmlinux.lds.h +++ b/arch/arm/include/asm/vmlinux.lds.h @@ -42,7 +42,7 @@ #define PROC_INFO \ . = ALIGN(4); \ __proc_info_begin = .; \ - *(.proc.info.init) \ + KEEP(*(.proc.info.init)) \ __proc_info_end = .; #define IDMAP_TEXT \ diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index 6150a716828c3e..f01d23a220e65d 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S @@ -1065,6 +1065,7 @@ vector_addrexcptn: .globl vector_fiq .section .vectors, "ax", %progbits + .reloc .text, R_ARM_NONE, . W(b) vector_rst W(b) vector_und ARM( .reloc ., R_ARM_LDR_PC_G0, .L__vector_swi ) @@ -1078,6 +1079,7 @@ THUMB( .reloc ., R_ARM_THM_PC12, .L__vector_swi ) #ifdef CONFIG_HARDEN_BRANCH_HISTORY .section .vectors.bhb.loop8, "ax", %progbits + .reloc .text, R_ARM_NONE, . W(b) vector_rst W(b) vector_bhb_loop8_und ARM( .reloc ., R_ARM_LDR_PC_G0, .L__vector_bhb_loop8_swi ) @@ -1090,6 +1092,7 @@ THUMB( .reloc ., R_ARM_THM_PC12, .L__vector_bhb_loop8_swi ) W(b) vector_bhb_loop8_fiq .section .vectors.bhb.bpiall, "ax", %progbits + .reloc .text, R_ARM_NONE, . W(b) vector_rst W(b) vector_bhb_bpiall_und ARM( .reloc ., R_ARM_LDR_PC_G0, .L__vector_bhb_bpiall_swi ) diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S index 5c31e9de7a602e..f379c852dcb72f 100644 --- a/arch/arm/kernel/entry-common.S +++ b/arch/arm/kernel/entry-common.S @@ -119,6 +119,9 @@ no_work_pending: ct_user_enter save = 0 +#ifdef CONFIG_GCC_PLUGIN_STACKLEAK + bl stackleak_erase_on_task_stack +#endif restore_user_regs fast = 0, offset = 0 ENDPROC(ret_to_user_from_irq) ENDPROC(ret_to_user) diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c index 677f218f7e841a..da488d92e7a00d 100644 --- a/arch/arm/kernel/module.c +++ b/arch/arm/kernel/module.c @@ -395,11 +395,6 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex, return 0; } -struct mod_unwind_map { - const Elf_Shdr *unw_sec; - const Elf_Shdr *txt_sec; -}; - static const Elf_Shdr *find_mod_section(const Elf32_Ehdr *hdr, const Elf_Shdr *sechdrs, const char *name) { diff --git a/arch/arm/kernel/perf_callchain.c b/arch/arm/kernel/perf_callchain.c index 7147edbe56c67c..1d230ac9d0eb5c 100644 --- a/arch/arm/kernel/perf_callchain.c +++ b/arch/arm/kernel/perf_callchain.c @@ -85,8 +85,7 @@ static bool callchain_trace(void *data, unsigned long pc) { struct perf_callchain_entry_ctx *entry = data; - perf_callchain_store(entry, pc); - return true; + return perf_callchain_store(entry, pc) == 0; } void diff --git a/arch/arm/kernel/vmlinux-xip.lds.S b/arch/arm/kernel/vmlinux-xip.lds.S index c16d196b5aad3e..5eddb75a717408 100644 --- a/arch/arm/kernel/vmlinux-xip.lds.S +++ b/arch/arm/kernel/vmlinux-xip.lds.S @@ -63,7 +63,7 @@ SECTIONS . = ALIGN(4); __ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET) { __start___ex_table = .; - ARM_MMU_KEEP(*(__ex_table)) + ARM_MMU_KEEP(KEEP(*(__ex_table))) __stop___ex_table = .; } @@ -83,7 +83,7 @@ SECTIONS } .init.arch.info : { __arch_info_begin = .; - *(.arch.info.init) + KEEP(*(.arch.info.init)) __arch_info_end = .; } .init.tagtable : { diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S index bd9127c4b45101..de373c6c2ae878 100644 --- a/arch/arm/kernel/vmlinux.lds.S +++ b/arch/arm/kernel/vmlinux.lds.S @@ -74,7 +74,7 @@ SECTIONS . = ALIGN(4); __ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET) { __start___ex_table = .; - ARM_MMU_KEEP(*(__ex_table)) + ARM_MMU_KEEP(KEEP(*(__ex_table))) __stop___ex_table = .; } @@ -99,7 +99,7 @@ SECTIONS } .init.arch.info : { __arch_info_begin = .; - *(.arch.info.init) + KEEP(*(.arch.info.init)) __arch_info_end = .; } .init.tagtable : { @@ -116,7 +116,7 @@ SECTIONS #endif .init.pv_table : { __pv_table_begin = .; - *(.pv_table) + KEEP(*(.pv_table)) __pv_table_end = .; } diff --git a/arch/arm/mach-alpine/alpine_cpu_pm.c b/arch/arm/mach-alpine/alpine_cpu_pm.c index 13ae8412e9ce64..b48da6f12b6cc4 100644 --- a/arch/arm/mach-alpine/alpine_cpu_pm.c +++ b/arch/arm/mach-alpine/alpine_cpu_pm.c @@ -29,7 +29,7 @@ int alpine_cpu_wakeup(unsigned int phys_cpu, uint32_t phys_resume_addr) /* * Set CPU resume address - * secure firmware running on boot will jump to this address - * after setting proper CPU mode, and initialiing e.g. secure + * after setting proper CPU mode, and initializing e.g. secure * regs (the same mode all CPUs are booted to - usually HYP) */ writel(phys_resume_addr, diff --git a/arch/arm/mach-pxa/gumstix.c b/arch/arm/mach-pxa/gumstix.c index efa6faa62a2cf0..1713bdf3b71e4b 100644 --- a/arch/arm/mach-pxa/gumstix.c +++ b/arch/arm/mach-pxa/gumstix.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -40,6 +41,7 @@ #include #include "udc.h" #include "gumstix.h" +#include "devices.h" #include "generic.h" @@ -99,8 +101,8 @@ static void __init gumstix_mmc_init(void) } #endif -#ifdef CONFIG_USB_PXA25X -static const struct property_entry spitz_mci_props[] __initconst = { +#if IS_ENABLED(CONFIG_USB_PXA25X) +static const struct property_entry gumstix_vbus_props[] __initconst = { PROPERTY_ENTRY_GPIO("vbus-gpios", &pxa2xx_gpiochip_node, GPIO_GUMSTIX_USB_GPIOn, GPIO_ACTIVE_HIGH), PROPERTY_ENTRY_GPIO("pullup-gpios", &pxa2xx_gpiochip_node, @@ -109,8 +111,9 @@ static const struct property_entry spitz_mci_props[] __initconst = { }; static const struct platform_device_info gumstix_gpio_vbus_info __initconst = { - .name = "gpio-vbus", - .id = PLATFORM_DEVID_NONE, + .name = "gpio-vbus", + .id = PLATFORM_DEVID_NONE, + .properties = gumstix_vbus_props, }; static void __init gumstix_udc_init(void) diff --git a/arch/arm/mach-rpc/ecard.c b/arch/arm/mach-rpc/ecard.c index c30df1097c524b..9f7454b8efa79e 100644 --- a/arch/arm/mach-rpc/ecard.c +++ b/arch/arm/mach-rpc/ecard.c @@ -1109,7 +1109,7 @@ void ecard_remove_driver(struct ecard_driver *drv) driver_unregister(&drv->drv); } -static int ecard_match(struct device *_dev, struct device_driver *_drv) +static int ecard_match(struct device *_dev, const struct device_driver *_drv) { struct expansion_card *ec = ECARD_DEV(_dev); struct ecard_driver *drv = ECARD_DRV(_drv); diff --git a/arch/arm/mm/proc.c b/arch/arm/mm/proc.c index bdbbf65d1b3669..2027845efefb60 100644 --- a/arch/arm/mm/proc.c +++ b/arch/arm/mm/proc.c @@ -17,7 +17,7 @@ void cpu_arm7tdmi_proc_init(void); __ADDRESSABLE(cpu_arm7tdmi_proc_init); void cpu_arm7tdmi_proc_fin(void); __ADDRESSABLE(cpu_arm7tdmi_proc_fin); -void cpu_arm7tdmi_reset(void); +void cpu_arm7tdmi_reset(unsigned long addr, bool hvc); __ADDRESSABLE(cpu_arm7tdmi_reset); int cpu_arm7tdmi_do_idle(void); __ADDRESSABLE(cpu_arm7tdmi_do_idle); @@ -32,7 +32,7 @@ void cpu_arm720_proc_init(void); __ADDRESSABLE(cpu_arm720_proc_init); void cpu_arm720_proc_fin(void); __ADDRESSABLE(cpu_arm720_proc_fin); -void cpu_arm720_reset(void); +void cpu_arm720_reset(unsigned long addr, bool hvc); __ADDRESSABLE(cpu_arm720_reset); int cpu_arm720_do_idle(void); __ADDRESSABLE(cpu_arm720_do_idle); @@ -49,7 +49,7 @@ void cpu_arm740_proc_init(void); __ADDRESSABLE(cpu_arm740_proc_init); void cpu_arm740_proc_fin(void); __ADDRESSABLE(cpu_arm740_proc_fin); -void cpu_arm740_reset(void); +void cpu_arm740_reset(unsigned long addr, bool hvc); __ADDRESSABLE(cpu_arm740_reset); int cpu_arm740_do_idle(void); __ADDRESSABLE(cpu_arm740_do_idle); @@ -64,7 +64,7 @@ void cpu_arm9tdmi_proc_init(void); __ADDRESSABLE(cpu_arm9tdmi_proc_init); void cpu_arm9tdmi_proc_fin(void); __ADDRESSABLE(cpu_arm9tdmi_proc_fin); -void cpu_arm9tdmi_reset(void); +void cpu_arm9tdmi_reset(unsigned long addr, bool hvc); __ADDRESSABLE(cpu_arm9tdmi_reset); int cpu_arm9tdmi_do_idle(void); __ADDRESSABLE(cpu_arm9tdmi_do_idle); @@ -79,7 +79,7 @@ void cpu_arm920_proc_init(void); __ADDRESSABLE(cpu_arm920_proc_init); void cpu_arm920_proc_fin(void); __ADDRESSABLE(cpu_arm920_proc_fin); -void cpu_arm920_reset(void); +void cpu_arm920_reset(unsigned long addr, bool hvc); __ADDRESSABLE(cpu_arm920_reset); int cpu_arm920_do_idle(void); __ADDRESSABLE(cpu_arm920_do_idle); @@ -102,7 +102,7 @@ void cpu_arm922_proc_init(void); __ADDRESSABLE(cpu_arm922_proc_init); void cpu_arm922_proc_fin(void); __ADDRESSABLE(cpu_arm922_proc_fin); -void cpu_arm922_reset(void); +void cpu_arm922_reset(unsigned long addr, bool hvc); __ADDRESSABLE(cpu_arm922_reset); int cpu_arm922_do_idle(void); __ADDRESSABLE(cpu_arm922_do_idle); @@ -119,7 +119,7 @@ void cpu_arm925_proc_init(void); __ADDRESSABLE(cpu_arm925_proc_init); void cpu_arm925_proc_fin(void); __ADDRESSABLE(cpu_arm925_proc_fin); -void cpu_arm925_reset(void); +void cpu_arm925_reset(unsigned long addr, bool hvc); __ADDRESSABLE(cpu_arm925_reset); int cpu_arm925_do_idle(void); __ADDRESSABLE(cpu_arm925_do_idle); @@ -159,7 +159,7 @@ void cpu_arm940_proc_init(void); __ADDRESSABLE(cpu_arm940_proc_init); void cpu_arm940_proc_fin(void); __ADDRESSABLE(cpu_arm940_proc_fin); -void cpu_arm940_reset(void); +void cpu_arm940_reset(unsigned long addr, bool hvc); __ADDRESSABLE(cpu_arm940_reset); int cpu_arm940_do_idle(void); __ADDRESSABLE(cpu_arm940_do_idle); @@ -174,7 +174,7 @@ void cpu_arm946_proc_init(void); __ADDRESSABLE(cpu_arm946_proc_init); void cpu_arm946_proc_fin(void); __ADDRESSABLE(cpu_arm946_proc_fin); -void cpu_arm946_reset(void); +void cpu_arm946_reset(unsigned long addr, bool hvc); __ADDRESSABLE(cpu_arm946_reset); int cpu_arm946_do_idle(void); __ADDRESSABLE(cpu_arm946_do_idle); @@ -429,7 +429,7 @@ void cpu_v7_proc_init(void); __ADDRESSABLE(cpu_v7_proc_init); void cpu_v7_proc_fin(void); __ADDRESSABLE(cpu_v7_proc_fin); -void cpu_v7_reset(void); +void cpu_v7_reset(unsigned long addr, bool hvc); __ADDRESSABLE(cpu_v7_reset); int cpu_v7_do_idle(void); __ADDRESSABLE(cpu_v7_do_idle); diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index b3fc891f154429..a2f8ff354ca670 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -1069,18 +1069,28 @@ config ARM64_ERRATUM_3117295 If unsure, say Y. config ARM64_ERRATUM_3194386 - bool "Cortex-{A720,X4,X925}/Neoverse-V3: workaround for MSR SSBS not self-synchronizing" + bool "Cortex-*/Neoverse-*: workaround for MSR SSBS not self-synchronizing" default y help This option adds the workaround for the following errata: + * ARM Cortex-A76 erratum 3324349 + * ARM Cortex-A77 erratum 3324348 + * ARM Cortex-A78 erratum 3324344 + * ARM Cortex-A78C erratum 3324346 + * ARM Cortex-A78C erratum 3324347 * ARM Cortex-A710 erratam 3324338 * ARM Cortex-A720 erratum 3456091 + * ARM Cortex-A725 erratum 3456106 + * ARM Cortex-X1 erratum 3324344 + * ARM Cortex-X1C erratum 3324346 * ARM Cortex-X2 erratum 3324338 * ARM Cortex-X3 erratum 3324335 * ARM Cortex-X4 erratum 3194386 * ARM Cortex-X925 erratum 3324334 + * ARM Neoverse-N1 erratum 3324349 * ARM Neoverse N2 erratum 3324339 + * ARM Neoverse-V1 erratum 3324341 * ARM Neoverse V2 erratum 3324336 * ARM Neoverse-V3 erratum 3312417 @@ -1088,11 +1098,11 @@ config ARM64_ERRATUM_3194386 subsequent speculative instructions, which may permit unexepected speculative store bypassing. - Work around this problem by placing a speculation barrier after - kernel changes to SSBS. The presence of the SSBS special-purpose - register is hidden from hwcaps and EL0 reads of ID_AA64PFR1_EL1, such - that userspace will use the PR_SPEC_STORE_BYPASS prctl to change - SSBS. + Work around this problem by placing a Speculation Barrier (SB) or + Instruction Synchronization Barrier (ISB) after kernel changes to + SSBS. The presence of the SSBS special-purpose register is hidden + from hwcaps and EL0 reads of ID_AA64PFR1_EL1, such that userspace + will use the PR_SPEC_STORE_BYPASS prctl to change SSBS. If unsure, say Y. diff --git a/arch/arm64/boot/dts/ti/k3-am62-verdin-dahlia.dtsi b/arch/arm64/boot/dts/ti/k3-am62-verdin-dahlia.dtsi index e8f4d136e5dfb4..9202181fbd6528 100644 --- a/arch/arm64/boot/dts/ti/k3-am62-verdin-dahlia.dtsi +++ b/arch/arm64/boot/dts/ti/k3-am62-verdin-dahlia.dtsi @@ -43,15 +43,6 @@ sound-dai = <&mcasp0>; }; }; - - reg_usb_hub: regulator-usb-hub { - compatible = "regulator-fixed"; - enable-active-high; - /* Verdin CTRL_SLEEP_MOCI# (SODIMM 256) */ - gpio = <&main_gpio0 31 GPIO_ACTIVE_HIGH>; - regulator-boot-on; - regulator-name = "HUB_PWR_EN"; - }; }; /* Verdin ETHs */ @@ -193,11 +184,6 @@ status = "okay"; }; -/* Do not force CTRL_SLEEP_MOCI# always enabled */ -®_force_sleep_moci { - status = "disabled"; -}; - /* Verdin SD_1 */ &sdhci1 { status = "okay"; @@ -218,15 +204,7 @@ }; &usb1 { - #address-cells = <1>; - #size-cells = <0>; status = "okay"; - - usb-hub@1 { - compatible = "usb424,2744"; - reg = <1>; - vdd-supply = <®_usb_hub>; - }; }; /* Verdin CTRL_WAKE1_MICO# */ diff --git a/arch/arm64/boot/dts/ti/k3-am62-verdin.dtsi b/arch/arm64/boot/dts/ti/k3-am62-verdin.dtsi index 359f53f3e019b1..5bef31b8577be5 100644 --- a/arch/arm64/boot/dts/ti/k3-am62-verdin.dtsi +++ b/arch/arm64/boot/dts/ti/k3-am62-verdin.dtsi @@ -138,12 +138,6 @@ vin-supply = <®_1v8>; }; - /* - * By default we enable CTRL_SLEEP_MOCI#, this is required to have - * peripherals on the carrier board powered. - * If more granularity or power saving is required this can be disabled - * in the carrier board device tree files. - */ reg_force_sleep_moci: regulator-force-sleep-moci { compatible = "regulator-fixed"; enable-active-high; diff --git a/arch/arm64/boot/dts/ti/k3-am62p-j722s-common-mcu.dtsi b/arch/arm64/boot/dts/ti/k3-am62p-j722s-common-mcu.dtsi index e65db6ce02bf66..df7945156397b1 100644 --- a/arch/arm64/boot/dts/ti/k3-am62p-j722s-common-mcu.dtsi +++ b/arch/arm64/boot/dts/ti/k3-am62p-j722s-common-mcu.dtsi @@ -146,6 +146,8 @@ power-domains = <&k3_pds 79 TI_SCI_PD_EXCLUSIVE>; clocks = <&k3_clks 79 0>; clock-names = "gpio"; + gpio-ranges = <&mcu_pmx0 0 0 21>, <&mcu_pmx0 21 23 1>, + <&mcu_pmx0 22 32 2>; }; mcu_rti0: watchdog@4880000 { diff --git a/arch/arm64/boot/dts/ti/k3-am62p-main.dtsi b/arch/arm64/boot/dts/ti/k3-am62p-main.dtsi index 57383bd2eaeb41..0ce9721b417653 100644 --- a/arch/arm64/boot/dts/ti/k3-am62p-main.dtsi +++ b/arch/arm64/boot/dts/ti/k3-am62p-main.dtsi @@ -45,7 +45,8 @@ &main_pmx0 { pinctrl-single,gpio-range = <&main_pmx0_range 0 32 PIN_GPIO_RANGE_IOPAD>, - <&main_pmx0_range 33 92 PIN_GPIO_RANGE_IOPAD>, + <&main_pmx0_range 33 38 PIN_GPIO_RANGE_IOPAD>, + <&main_pmx0_range 72 22 PIN_GPIO_RANGE_IOPAD>, <&main_pmx0_range 137 5 PIN_GPIO_RANGE_IOPAD>, <&main_pmx0_range 143 3 PIN_GPIO_RANGE_IOPAD>, <&main_pmx0_range 149 2 PIN_GPIO_RANGE_IOPAD>; diff --git a/arch/arm64/boot/dts/ti/k3-j722s-main.dtsi b/arch/arm64/boot/dts/ti/k3-j722s-main.dtsi index c797980528ec7c..dde4bd5c664539 100644 --- a/arch/arm64/boot/dts/ti/k3-j722s-main.dtsi +++ b/arch/arm64/boot/dts/ti/k3-j722s-main.dtsi @@ -193,7 +193,8 @@ &main_pmx0 { pinctrl-single,gpio-range = <&main_pmx0_range 0 32 PIN_GPIO_RANGE_IOPAD>, - <&main_pmx0_range 33 55 PIN_GPIO_RANGE_IOPAD>, + <&main_pmx0_range 33 38 PIN_GPIO_RANGE_IOPAD>, + <&main_pmx0_range 72 17 PIN_GPIO_RANGE_IOPAD>, <&main_pmx0_range 101 25 PIN_GPIO_RANGE_IOPAD>, <&main_pmx0_range 137 5 PIN_GPIO_RANGE_IOPAD>, <&main_pmx0_range 143 3 PIN_GPIO_RANGE_IOPAD>, diff --git a/arch/arm64/boot/dts/ti/k3-j784s4-evm.dts b/arch/arm64/boot/dts/ti/k3-j784s4-evm.dts index 9338d987180d75..ffa38f41679d84 100644 --- a/arch/arm64/boot/dts/ti/k3-j784s4-evm.dts +++ b/arch/arm64/boot/dts/ti/k3-j784s4-evm.dts @@ -1262,6 +1262,14 @@ &serdes0 { status = "okay"; + serdes0_pcie1_link: phy@0 { + reg = <0>; + cdns,num-lanes = <2>; + #phy-cells = <0>; + cdns,phy-type = ; + resets = <&serdes_wiz0 1>, <&serdes_wiz0 2>; + }; + serdes0_usb_link: phy@3 { reg = <3>; cdns,num-lanes = <1>; @@ -1386,23 +1394,6 @@ phys = <&transceiver3>; }; -&serdes0 { - status = "okay"; - - serdes0_pcie1_link: phy@0 { - reg = <0>; - cdns,num-lanes = <4>; - #phy-cells = <0>; - cdns,phy-type = ; - resets = <&serdes_wiz0 1>, <&serdes_wiz0 2>, - <&serdes_wiz0 3>, <&serdes_wiz0 4>; - }; -}; - -&serdes_wiz0 { - status = "okay"; -}; - &pcie1_rc { status = "okay"; num-lanes = <2>; diff --git a/arch/arm64/boot/dts/ti/k3-j784s4-main.dtsi b/arch/arm64/boot/dts/ti/k3-j784s4-main.dtsi index f170f80f00c1b8..d4ac1c9872a5e7 100644 --- a/arch/arm64/boot/dts/ti/k3-j784s4-main.dtsi +++ b/arch/arm64/boot/dts/ti/k3-j784s4-main.dtsi @@ -2755,7 +2755,7 @@ interrupts = , ; interrupt-names = "tx", "rx"; - dmas = <&main_udmap 0xc500>, <&main_udmap 0x4500>; + dmas = <&main_udmap 0xc403>, <&main_udmap 0x4403>; dma-names = "tx", "rx"; clocks = <&k3_clks 268 0>; clock-names = "fck"; @@ -2773,7 +2773,7 @@ interrupts = , ; interrupt-names = "tx", "rx"; - dmas = <&main_udmap 0xc501>, <&main_udmap 0x4501>; + dmas = <&main_udmap 0xc404>, <&main_udmap 0x4404>; dma-names = "tx", "rx"; clocks = <&k3_clks 269 0>; clock-names = "fck"; diff --git a/arch/arm64/include/asm/cputype.h b/arch/arm64/include/asm/cputype.h index 1cb0704c6163f8..5fd7caea441936 100644 --- a/arch/arm64/include/asm/cputype.h +++ b/arch/arm64/include/asm/cputype.h @@ -86,12 +86,14 @@ #define ARM_CPU_PART_CORTEX_X2 0xD48 #define ARM_CPU_PART_NEOVERSE_N2 0xD49 #define ARM_CPU_PART_CORTEX_A78C 0xD4B +#define ARM_CPU_PART_CORTEX_X1C 0xD4C #define ARM_CPU_PART_CORTEX_X3 0xD4E #define ARM_CPU_PART_NEOVERSE_V2 0xD4F #define ARM_CPU_PART_CORTEX_A720 0xD81 #define ARM_CPU_PART_CORTEX_X4 0xD82 #define ARM_CPU_PART_NEOVERSE_V3 0xD84 #define ARM_CPU_PART_CORTEX_X925 0xD85 +#define ARM_CPU_PART_CORTEX_A725 0xD87 #define APM_CPU_PART_XGENE 0x000 #define APM_CPU_VAR_POTENZA 0x00 @@ -165,12 +167,14 @@ #define MIDR_CORTEX_X2 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X2) #define MIDR_NEOVERSE_N2 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_N2) #define MIDR_CORTEX_A78C MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A78C) +#define MIDR_CORTEX_X1C MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X1C) #define MIDR_CORTEX_X3 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X3) #define MIDR_NEOVERSE_V2 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_V2) #define MIDR_CORTEX_A720 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A720) #define MIDR_CORTEX_X4 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X4) #define MIDR_NEOVERSE_V3 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_V3) #define MIDR_CORTEX_X925 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X925) +#define MIDR_CORTEX_A725 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A725) #define MIDR_THUNDERX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX) #define MIDR_THUNDERX_81XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_81XX) #define MIDR_THUNDERX_83XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_83XX) diff --git a/arch/arm64/include/asm/jump_label.h b/arch/arm64/include/asm/jump_label.h index 4e753908b80188..a0a5bbae7229e8 100644 --- a/arch/arm64/include/asm/jump_label.h +++ b/arch/arm64/include/asm/jump_label.h @@ -13,6 +13,7 @@ #include #include +#define HAVE_JUMP_LABEL_BATCH #define JUMP_LABEL_NOP_SIZE AARCH64_INSN_SIZE #define JUMP_TABLE_ENTRY(key, label) \ diff --git a/arch/arm64/include/asm/kvm_ptrauth.h b/arch/arm64/include/asm/kvm_ptrauth.h index d81bac256abc35..6199c9f7ec6eda 100644 --- a/arch/arm64/include/asm/kvm_ptrauth.h +++ b/arch/arm64/include/asm/kvm_ptrauth.h @@ -104,7 +104,7 @@ alternative_else_nop_endif #define __ptrauth_save_key(ctxt, key) \ do { \ - u64 __val; \ + u64 __val; \ __val = read_sysreg_s(SYS_ ## key ## KEYLO_EL1); \ ctxt_sys_reg(ctxt, key ## KEYLO_EL1) = __val; \ __val = read_sysreg_s(SYS_ ## key ## KEYHI_EL1); \ diff --git a/arch/arm64/include/asm/uaccess.h b/arch/arm64/include/asm/uaccess.h index 28f665e0975a28..1aa4ecb73429fe 100644 --- a/arch/arm64/include/asm/uaccess.h +++ b/arch/arm64/include/asm/uaccess.h @@ -188,7 +188,7 @@ static inline void __user *__uaccess_mask_ptr(const void __user *ptr) #define __get_mem_asm(load, reg, x, addr, label, type) \ asm_goto_output( \ "1: " load " " reg "0, [%1]\n" \ - _ASM_EXTABLE_##type##ACCESS_ERR(1b, %l2, %w0) \ + _ASM_EXTABLE_##type##ACCESS(1b, %l2) \ : "=r" (x) \ : "r" (addr) : : label) #else diff --git a/arch/arm64/kernel/Makefile.syscalls b/arch/arm64/kernel/Makefile.syscalls index 3cfafd003b2db6..0542a718871afa 100644 --- a/arch/arm64/kernel/Makefile.syscalls +++ b/arch/arm64/kernel/Makefile.syscalls @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 syscall_abis_32 += -syscall_abis_64 += renameat newstat rlimit memfd_secret +syscall_abis_64 += renameat rlimit memfd_secret syscalltbl = arch/arm64/tools/syscall_%.tbl diff --git a/arch/arm64/kernel/acpi_numa.c b/arch/arm64/kernel/acpi_numa.c index 0c036a9a3c338a..2465f291c7e17c 100644 --- a/arch/arm64/kernel/acpi_numa.c +++ b/arch/arm64/kernel/acpi_numa.c @@ -27,7 +27,7 @@ #include -static int acpi_early_node_map[NR_CPUS] __initdata = { NUMA_NO_NODE }; +static int acpi_early_node_map[NR_CPUS] __initdata = { [0 ... NR_CPUS - 1] = NUMA_NO_NODE }; int __init acpi_numa_get_nid(unsigned int cpu) { diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c index 617424b73f8c32..f6b6b450735715 100644 --- a/arch/arm64/kernel/cpu_errata.c +++ b/arch/arm64/kernel/cpu_errata.c @@ -434,15 +434,24 @@ static const struct midr_range erratum_spec_unpriv_load_list[] = { #ifdef CONFIG_ARM64_ERRATUM_3194386 static const struct midr_range erratum_spec_ssbs_list[] = { + MIDR_ALL_VERSIONS(MIDR_CORTEX_A76), + MIDR_ALL_VERSIONS(MIDR_CORTEX_A77), + MIDR_ALL_VERSIONS(MIDR_CORTEX_A78), + MIDR_ALL_VERSIONS(MIDR_CORTEX_A78C), MIDR_ALL_VERSIONS(MIDR_CORTEX_A710), MIDR_ALL_VERSIONS(MIDR_CORTEX_A720), + MIDR_ALL_VERSIONS(MIDR_CORTEX_A725), + MIDR_ALL_VERSIONS(MIDR_CORTEX_X1), + MIDR_ALL_VERSIONS(MIDR_CORTEX_X1C), MIDR_ALL_VERSIONS(MIDR_CORTEX_X2), MIDR_ALL_VERSIONS(MIDR_CORTEX_X3), MIDR_ALL_VERSIONS(MIDR_CORTEX_X4), MIDR_ALL_VERSIONS(MIDR_CORTEX_X925), + MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N1), MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N2), - MIDR_ALL_VERSIONS(MIDR_NEOVERSE_V3), + MIDR_ALL_VERSIONS(MIDR_NEOVERSE_V1), MIDR_ALL_VERSIONS(MIDR_NEOVERSE_V2), + MIDR_ALL_VERSIONS(MIDR_NEOVERSE_V3), {} }; #endif diff --git a/arch/arm64/kernel/jump_label.c b/arch/arm64/kernel/jump_label.c index faf88ec9c48e8a..f63ea915d6ad25 100644 --- a/arch/arm64/kernel/jump_label.c +++ b/arch/arm64/kernel/jump_label.c @@ -7,11 +7,12 @@ */ #include #include +#include #include #include -void arch_jump_label_transform(struct jump_entry *entry, - enum jump_label_type type) +bool arch_jump_label_transform_queue(struct jump_entry *entry, + enum jump_label_type type) { void *addr = (void *)jump_entry_code(entry); u32 insn; @@ -25,4 +26,10 @@ void arch_jump_label_transform(struct jump_entry *entry, } aarch64_insn_patch_text_nosync(addr, insn); + return true; +} + +void arch_jump_label_transform_apply(void) +{ + kick_all_cpus_sync(); } diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c index a096e2451044d3..b22d28ec80284b 100644 --- a/arch/arm64/kernel/setup.c +++ b/arch/arm64/kernel/setup.c @@ -355,9 +355,6 @@ void __init __no_sanitize_address setup_arch(char **cmdline_p) smp_init_cpus(); smp_build_mpidr_hash(); - /* Init percpu seeds for random tags after cpus are set up. */ - kasan_init_sw_tags(); - #ifdef CONFIG_ARM64_SW_TTBR0_PAN /* * Make sure init_thread_info.ttbr0 always generates translation diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c index 5e18fbcee9a20c..f01f0fd7b7feb4 100644 --- a/arch/arm64/kernel/smp.c +++ b/arch/arm64/kernel/smp.c @@ -467,6 +467,8 @@ void __init smp_prepare_boot_cpu(void) init_gic_priority_masking(); kasan_init_hw_tags(); + /* Init percpu seeds for random tags after cpus are set up. */ + kasan_init_sw_tags(); } /* diff --git a/arch/arm64/kvm/Kconfig b/arch/arm64/kvm/Kconfig index 58f09370d17e01..8304eb342be9d9 100644 --- a/arch/arm64/kvm/Kconfig +++ b/arch/arm64/kvm/Kconfig @@ -19,6 +19,7 @@ if VIRTUALIZATION menuconfig KVM bool "Kernel-based Virtual Machine (KVM) support" + depends on AS_HAS_ARMV8_4 select KVM_COMMON select KVM_GENERIC_HARDWARE_ENABLING select KVM_GENERIC_MMU_NOTIFIER diff --git a/arch/arm64/kvm/Makefile b/arch/arm64/kvm/Makefile index a6497228c5a8c3..86a629aaf0a13f 100644 --- a/arch/arm64/kvm/Makefile +++ b/arch/arm64/kvm/Makefile @@ -10,6 +10,9 @@ include $(srctree)/virt/kvm/Makefile.kvm obj-$(CONFIG_KVM) += kvm.o obj-$(CONFIG_KVM) += hyp/ +CFLAGS_sys_regs.o += -Wno-override-init +CFLAGS_handle_exit.o += -Wno-override-init + kvm-y += arm.o mmu.o mmio.o psci.o hypercalls.o pvtime.o \ inject_fault.o va_layout.o handle_exit.o \ guest.o debug.o reset.o sys_regs.o stacktrace.o \ diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c index a7ca776b51ec8a..9bef7638342ef7 100644 --- a/arch/arm64/kvm/arm.c +++ b/arch/arm64/kvm/arm.c @@ -164,6 +164,7 @@ static int kvm_arm_default_max_vcpus(void) /** * kvm_arch_init_vm - initializes a VM data structure * @kvm: pointer to the KVM struct + * @type: kvm device type */ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) { @@ -521,10 +522,10 @@ void kvm_arch_vcpu_unblocking(struct kvm_vcpu *vcpu) static void vcpu_set_pauth_traps(struct kvm_vcpu *vcpu) { - if (vcpu_has_ptrauth(vcpu)) { + if (vcpu_has_ptrauth(vcpu) && !is_protected_kvm_enabled()) { /* - * Either we're running running an L2 guest, and the API/APK - * bits come from L1's HCR_EL2, or API/APK are both set. + * Either we're running an L2 guest, and the API/APK bits come + * from L1's HCR_EL2, or API/APK are both set. */ if (unlikely(vcpu_has_nv(vcpu) && !is_hyp_ctxt(vcpu))) { u64 val; @@ -541,16 +542,10 @@ static void vcpu_set_pauth_traps(struct kvm_vcpu *vcpu) * Save the host keys if there is any chance for the guest * to use pauth, as the entry code will reload the guest * keys in that case. - * Protected mode is the exception to that rule, as the - * entry into the EL2 code eagerly switch back and forth - * between host and hyp keys (and kvm_hyp_ctxt is out of - * reach anyway). */ - if (is_protected_kvm_enabled()) - return; - if (vcpu->arch.hcr_el2 & (HCR_API | HCR_APK)) { struct kvm_cpu_context *ctxt; + ctxt = this_cpu_ptr_hyp_sym(kvm_hyp_ctxt); ptrauth_save_keys(ctxt); } diff --git a/arch/arm64/kvm/hyp/include/hyp/switch.h b/arch/arm64/kvm/hyp/include/hyp/switch.h index f59ccfe11ab9ad..37ff87d782b62b 100644 --- a/arch/arm64/kvm/hyp/include/hyp/switch.h +++ b/arch/arm64/kvm/hyp/include/hyp/switch.h @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/arm64/kvm/hyp/nvhe/Makefile b/arch/arm64/kvm/hyp/nvhe/Makefile index 782b34b004be3c..b43426a493df5a 100644 --- a/arch/arm64/kvm/hyp/nvhe/Makefile +++ b/arch/arm64/kvm/hyp/nvhe/Makefile @@ -20,6 +20,8 @@ HOST_EXTRACFLAGS += -I$(objtree)/include lib-objs := clear_page.o copy_page.o memcpy.o memset.o lib-objs := $(addprefix ../../../lib/, $(lib-objs)) +CFLAGS_switch.nvhe.o += -Wno-override-init + hyp-obj-y := timer-sr.o sysreg-sr.o debug-sr.o switch.o tlb.o hyp-init.o host.o \ hyp-main.o hyp-smp.o psci-relay.o early_alloc.o page_alloc.o \ cache.o setup.o mm.o mem_protect.o sys_regs.o pkvm.o stacktrace.o ffa.o diff --git a/arch/arm64/kvm/hyp/nvhe/switch.c b/arch/arm64/kvm/hyp/nvhe/switch.c index 6af179c6356d66..8f5c56d5b1cdf5 100644 --- a/arch/arm64/kvm/hyp/nvhe/switch.c +++ b/arch/arm64/kvm/hyp/nvhe/switch.c @@ -173,9 +173,8 @@ static void __pmu_switch_to_host(struct kvm_vcpu *vcpu) static bool kvm_handle_pvm_sys64(struct kvm_vcpu *vcpu, u64 *exit_code) { /* - * Make sure we handle the exit for workarounds and ptrauth - * before the pKVM handling, as the latter could decide to - * UNDEF. + * Make sure we handle the exit for workarounds before the pKVM + * handling, as the latter could decide to UNDEF. */ return (kvm_hyp_handle_sysreg(vcpu, exit_code) || kvm_handle_pvm_sysreg(vcpu, exit_code)); diff --git a/arch/arm64/kvm/hyp/vhe/Makefile b/arch/arm64/kvm/hyp/vhe/Makefile index 3b9e5464b5b39c..afc4aed9231ac0 100644 --- a/arch/arm64/kvm/hyp/vhe/Makefile +++ b/arch/arm64/kvm/hyp/vhe/Makefile @@ -6,6 +6,8 @@ asflags-y := -D__KVM_VHE_HYPERVISOR__ ccflags-y := -D__KVM_VHE_HYPERVISOR__ +CFLAGS_switch.o += -Wno-override-init + obj-y := timer-sr.o sysreg-sr.o debug-sr.o switch.o tlb.o obj-y += ../vgic-v3-sr.o ../aarch32.o ../vgic-v2-cpuif-proxy.o ../entry.o \ ../fpsimd.o ../hyp-entry.o ../exception.o diff --git a/arch/arm64/kvm/nested.c b/arch/arm64/kvm/nested.c index de789e0f1ae9cb..bab27f9d8cc659 100644 --- a/arch/arm64/kvm/nested.c +++ b/arch/arm64/kvm/nested.c @@ -786,7 +786,7 @@ void kvm_arch_flush_shadow_all(struct kvm *kvm) if (!WARN_ON(atomic_read(&mmu->refcnt))) kvm_free_stage2_pgd(mmu); } - kfree(kvm->arch.nested_mmus); + kvfree(kvm->arch.nested_mmus); kvm->arch.nested_mmus = NULL; kvm->arch.nested_mmus_size = 0; kvm_uninit_stage2_mmu(kvm); diff --git a/arch/arm64/kvm/vgic/vgic-debug.c b/arch/arm64/kvm/vgic/vgic-debug.c index bcbc8c986b1d63..bc74d06398ef16 100644 --- a/arch/arm64/kvm/vgic/vgic-debug.c +++ b/arch/arm64/kvm/vgic/vgic-debug.c @@ -45,7 +45,8 @@ static void iter_next(struct kvm *kvm, struct vgic_state_iter *iter) * Let the xarray drive the iterator after the last SPI, as the iterator * has exhausted the sequentially-allocated INTID space. */ - if (iter->intid >= (iter->nr_spis + VGIC_NR_PRIVATE_IRQS - 1)) { + if (iter->intid >= (iter->nr_spis + VGIC_NR_PRIVATE_IRQS - 1) && + iter->nr_lpis) { if (iter->lpi_idx < iter->nr_lpis) xa_find_after(&dist->lpi_xa, &iter->intid, VGIC_LPI_MAX_INTID, @@ -112,7 +113,7 @@ static bool end_of_vgic(struct vgic_state_iter *iter) return iter->dist_id > 0 && iter->vcpu_id == iter->nr_cpus && iter->intid >= (iter->nr_spis + VGIC_NR_PRIVATE_IRQS) && - iter->lpi_idx > iter->nr_lpis; + (!iter->nr_lpis || iter->lpi_idx > iter->nr_lpis); } static void *vgic_debug_start(struct seq_file *s, loff_t *pos) diff --git a/arch/arm64/kvm/vgic/vgic-init.c b/arch/arm64/kvm/vgic/vgic-init.c index 7f68cf58b978fb..41feb858ff9a5e 100644 --- a/arch/arm64/kvm/vgic/vgic-init.c +++ b/arch/arm64/kvm/vgic/vgic-init.c @@ -438,14 +438,13 @@ void kvm_vgic_destroy(struct kvm *kvm) unsigned long i; mutex_lock(&kvm->slots_lock); + mutex_lock(&kvm->arch.config_lock); vgic_debug_destroy(kvm); kvm_for_each_vcpu(i, vcpu, kvm) __kvm_vgic_vcpu_destroy(vcpu); - mutex_lock(&kvm->arch.config_lock); - kvm_vgic_dist_destroy(kvm); mutex_unlock(&kvm->arch.config_lock); diff --git a/arch/arm64/kvm/vgic/vgic-irqfd.c b/arch/arm64/kvm/vgic/vgic-irqfd.c index 8c711deb25aa00..c314c016659abe 100644 --- a/arch/arm64/kvm/vgic/vgic-irqfd.c +++ b/arch/arm64/kvm/vgic/vgic-irqfd.c @@ -9,7 +9,7 @@ #include #include "vgic.h" -/** +/* * vgic_irqfd_set_irq: inject the IRQ corresponding to the * irqchip routing entry * @@ -75,7 +75,8 @@ static void kvm_populate_msi(struct kvm_kernel_irq_routing_entry *e, msi->flags = e->msi.flags; msi->devid = e->msi.devid; } -/** + +/* * kvm_set_msi: inject the MSI corresponding to the * MSI routing entry * @@ -98,7 +99,7 @@ int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e, return vgic_its_inject_msi(kvm, &msi); } -/** +/* * kvm_arch_set_irq_inatomic: fast-path for irqfd injection */ int kvm_arch_set_irq_inatomic(struct kvm_kernel_irq_routing_entry *e, diff --git a/arch/arm64/kvm/vgic/vgic-its.c b/arch/arm64/kvm/vgic/vgic-its.c index 40bb43f20bf347..ba945ba78cc7d7 100644 --- a/arch/arm64/kvm/vgic/vgic-its.c +++ b/arch/arm64/kvm/vgic/vgic-its.c @@ -2040,6 +2040,7 @@ typedef int (*entry_fn_t)(struct vgic_its *its, u32 id, void *entry, * @start_id: the ID of the first entry in the table * (non zero for 2d level tables) * @fn: function to apply on each entry + * @opaque: pointer to opaque data * * Return: < 0 on error, 0 if last element was identified, 1 otherwise * (the last element may not be found on second level tables) @@ -2079,7 +2080,7 @@ static int scan_its_table(struct vgic_its *its, gpa_t base, int size, u32 esz, return 1; } -/** +/* * vgic_its_save_ite - Save an interrupt translation entry at @gpa */ static int vgic_its_save_ite(struct vgic_its *its, struct its_device *dev, @@ -2099,6 +2100,8 @@ static int vgic_its_save_ite(struct vgic_its *its, struct its_device *dev, /** * vgic_its_restore_ite - restore an interrupt translation entry + * + * @its: its handle * @event_id: id used for indexing * @ptr: pointer to the ITE entry * @opaque: pointer to the its_device @@ -2231,6 +2234,7 @@ static int vgic_its_restore_itt(struct vgic_its *its, struct its_device *dev) * @its: ITS handle * @dev: ITS device * @ptr: GPA + * @dte_esz: device table entry size */ static int vgic_its_save_dte(struct vgic_its *its, struct its_device *dev, gpa_t ptr, int dte_esz) @@ -2313,7 +2317,7 @@ static int vgic_its_device_cmp(void *priv, const struct list_head *a, return 1; } -/** +/* * vgic_its_save_device_tables - Save the device table and all ITT * into guest RAM * @@ -2386,7 +2390,7 @@ static int handle_l1_dte(struct vgic_its *its, u32 id, void *addr, return ret; } -/** +/* * vgic_its_restore_device_tables - Restore the device table and all ITT * from guest RAM to internal data structs */ @@ -2478,7 +2482,7 @@ static int vgic_its_restore_cte(struct vgic_its *its, gpa_t gpa, int esz) return 1; } -/** +/* * vgic_its_save_collection_table - Save the collection table into * guest RAM */ @@ -2518,7 +2522,7 @@ static int vgic_its_save_collection_table(struct vgic_its *its) return ret; } -/** +/* * vgic_its_restore_collection_table - reads the collection table * in guest memory and restores the ITS internal state. Requires the * BASER registers to be restored before. @@ -2556,7 +2560,7 @@ static int vgic_its_restore_collection_table(struct vgic_its *its) return ret; } -/** +/* * vgic_its_save_tables_v0 - Save the ITS tables into guest ARM * according to v0 ABI */ @@ -2571,7 +2575,7 @@ static int vgic_its_save_tables_v0(struct vgic_its *its) return vgic_its_save_collection_table(its); } -/** +/* * vgic_its_restore_tables_v0 - Restore the ITS tables from guest RAM * to internal data structs according to V0 ABI * diff --git a/arch/arm64/kvm/vgic/vgic-v3.c b/arch/arm64/kvm/vgic/vgic-v3.c index ed6e412cd74bac..3eecdd2f4b8f55 100644 --- a/arch/arm64/kvm/vgic/vgic-v3.c +++ b/arch/arm64/kvm/vgic/vgic-v3.c @@ -370,7 +370,7 @@ static void map_all_vpes(struct kvm *kvm) dist->its_vm.vpes[i]->irq)); } -/** +/* * vgic_v3_save_pending_tables - Save the pending tables into guest RAM * kvm lock and all vcpu lock must be held */ diff --git a/arch/arm64/kvm/vgic/vgic.c b/arch/arm64/kvm/vgic/vgic.c index f07b3ddff7d442..974849ea7101c6 100644 --- a/arch/arm64/kvm/vgic/vgic.c +++ b/arch/arm64/kvm/vgic/vgic.c @@ -313,7 +313,7 @@ static bool vgic_validate_injection(struct vgic_irq *irq, bool level, void *owne * with all locks dropped. */ bool vgic_queue_irq_unlock(struct kvm *kvm, struct vgic_irq *irq, - unsigned long flags) + unsigned long flags) __releases(&irq->irq_lock) { struct kvm_vcpu *vcpu; diff --git a/arch/arm64/kvm/vgic/vgic.h b/arch/arm64/kvm/vgic/vgic.h index 03d356a123771f..ba8f790431bd3a 100644 --- a/arch/arm64/kvm/vgic/vgic.h +++ b/arch/arm64/kvm/vgic/vgic.h @@ -186,7 +186,7 @@ bool vgic_get_phys_line_level(struct vgic_irq *irq); void vgic_irq_set_phys_pending(struct vgic_irq *irq, bool pending); void vgic_irq_set_phys_active(struct vgic_irq *irq, bool active); bool vgic_queue_irq_unlock(struct kvm *kvm, struct vgic_irq *irq, - unsigned long flags); + unsigned long flags) __releases(&irq->irq_lock); void vgic_kick_vcpus(struct kvm *kvm); void vgic_irq_handle_resampling(struct vgic_irq *irq, bool lr_deactivated, bool lr_pending); diff --git a/arch/loongarch/include/asm/hugetlb.h b/arch/loongarch/include/asm/hugetlb.h index aa44b3fe43dde7..5da32c00d483fb 100644 --- a/arch/loongarch/include/asm/hugetlb.h +++ b/arch/loongarch/include/asm/hugetlb.h @@ -34,7 +34,7 @@ static inline pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) { pte_t clear; - pte_t pte = *ptep; + pte_t pte = ptep_get(ptep); pte_val(clear) = (unsigned long)invalid_pte_table; set_pte_at(mm, addr, ptep, clear); @@ -65,7 +65,7 @@ static inline int huge_ptep_set_access_flags(struct vm_area_struct *vma, pte_t *ptep, pte_t pte, int dirty) { - int changed = !pte_same(*ptep, pte); + int changed = !pte_same(ptep_get(ptep), pte); if (changed) { set_pte_at(vma->vm_mm, addr, ptep, pte); diff --git a/arch/loongarch/include/asm/kfence.h b/arch/loongarch/include/asm/kfence.h index 92636e82957c7e..da9e93024626c5 100644 --- a/arch/loongarch/include/asm/kfence.h +++ b/arch/loongarch/include/asm/kfence.h @@ -53,13 +53,13 @@ static inline bool kfence_protect_page(unsigned long addr, bool protect) { pte_t *pte = virt_to_kpte(addr); - if (WARN_ON(!pte) || pte_none(*pte)) + if (WARN_ON(!pte) || pte_none(ptep_get(pte))) return false; if (protect) - set_pte(pte, __pte(pte_val(*pte) & ~(_PAGE_VALID | _PAGE_PRESENT))); + set_pte(pte, __pte(pte_val(ptep_get(pte)) & ~(_PAGE_VALID | _PAGE_PRESENT))); else - set_pte(pte, __pte(pte_val(*pte) | (_PAGE_VALID | _PAGE_PRESENT))); + set_pte(pte, __pte(pte_val(ptep_get(pte)) | (_PAGE_VALID | _PAGE_PRESENT))); preempt_disable(); local_flush_tlb_one(addr); diff --git a/arch/loongarch/include/asm/kvm_host.h b/arch/loongarch/include/asm/kvm_host.h index 44b54965f5b4f8..5f0677e03817ba 100644 --- a/arch/loongarch/include/asm/kvm_host.h +++ b/arch/loongarch/include/asm/kvm_host.h @@ -26,8 +26,6 @@ #define KVM_MAX_VCPUS 256 #define KVM_MAX_CPUCFG_REGS 21 -/* memory slots that does not exposed to userspace */ -#define KVM_PRIVATE_MEM_SLOTS 0 #define KVM_HALT_POLL_NS_DEFAULT 500000 #define KVM_REQ_TLB_FLUSH_GPA KVM_ARCH_REQ(0) diff --git a/arch/loongarch/include/asm/kvm_para.h b/arch/loongarch/include/asm/kvm_para.h index 335fb86778e2bc..43ec61589e6cde 100644 --- a/arch/loongarch/include/asm/kvm_para.h +++ b/arch/loongarch/include/asm/kvm_para.h @@ -39,9 +39,9 @@ struct kvm_steal_time { * Hypercall interface for KVM hypervisor * * a0: function identifier - * a1-a6: args + * a1-a5: args * Return value will be placed in a0. - * Up to 6 arguments are passed in a1, a2, a3, a4, a5, a6. + * Up to 5 arguments are passed in a1, a2, a3, a4, a5. */ static __always_inline long kvm_hypercall0(u64 fid) { diff --git a/arch/loongarch/include/asm/pgtable.h b/arch/loongarch/include/asm/pgtable.h index 3fbf1f37c58ecf..85431f20a14db7 100644 --- a/arch/loongarch/include/asm/pgtable.h +++ b/arch/loongarch/include/asm/pgtable.h @@ -106,6 +106,9 @@ extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)]; #define KFENCE_AREA_START (VMEMMAP_END + 1) #define KFENCE_AREA_END (KFENCE_AREA_START + KFENCE_AREA_SIZE - 1) +#define ptep_get(ptep) READ_ONCE(*(ptep)) +#define pmdp_get(pmdp) READ_ONCE(*(pmdp)) + #define pte_ERROR(e) \ pr_err("%s:%d: bad pte %016lx.\n", __FILE__, __LINE__, pte_val(e)) #ifndef __PAGETABLE_PMD_FOLDED @@ -147,11 +150,6 @@ static inline int p4d_present(p4d_t p4d) return p4d_val(p4d) != (unsigned long)invalid_pud_table; } -static inline void p4d_clear(p4d_t *p4dp) -{ - p4d_val(*p4dp) = (unsigned long)invalid_pud_table; -} - static inline pud_t *p4d_pgtable(p4d_t p4d) { return (pud_t *)p4d_val(p4d); @@ -159,7 +157,12 @@ static inline pud_t *p4d_pgtable(p4d_t p4d) static inline void set_p4d(p4d_t *p4d, p4d_t p4dval) { - *p4d = p4dval; + WRITE_ONCE(*p4d, p4dval); +} + +static inline void p4d_clear(p4d_t *p4dp) +{ + set_p4d(p4dp, __p4d((unsigned long)invalid_pud_table)); } #define p4d_phys(p4d) PHYSADDR(p4d_val(p4d)) @@ -193,17 +196,20 @@ static inline int pud_present(pud_t pud) return pud_val(pud) != (unsigned long)invalid_pmd_table; } -static inline void pud_clear(pud_t *pudp) +static inline pmd_t *pud_pgtable(pud_t pud) { - pud_val(*pudp) = ((unsigned long)invalid_pmd_table); + return (pmd_t *)pud_val(pud); } -static inline pmd_t *pud_pgtable(pud_t pud) +static inline void set_pud(pud_t *pud, pud_t pudval) { - return (pmd_t *)pud_val(pud); + WRITE_ONCE(*pud, pudval); } -#define set_pud(pudptr, pudval) do { *(pudptr) = (pudval); } while (0) +static inline void pud_clear(pud_t *pudp) +{ + set_pud(pudp, __pud((unsigned long)invalid_pmd_table)); +} #define pud_phys(pud) PHYSADDR(pud_val(pud)) #define pud_page(pud) (pfn_to_page(pud_phys(pud) >> PAGE_SHIFT)) @@ -231,12 +237,15 @@ static inline int pmd_present(pmd_t pmd) return pmd_val(pmd) != (unsigned long)invalid_pte_table; } -static inline void pmd_clear(pmd_t *pmdp) +static inline void set_pmd(pmd_t *pmd, pmd_t pmdval) { - pmd_val(*pmdp) = ((unsigned long)invalid_pte_table); + WRITE_ONCE(*pmd, pmdval); } -#define set_pmd(pmdptr, pmdval) do { *(pmdptr) = (pmdval); } while (0) +static inline void pmd_clear(pmd_t *pmdp) +{ + set_pmd(pmdp, __pmd((unsigned long)invalid_pte_table)); +} #define pmd_phys(pmd) PHYSADDR(pmd_val(pmd)) @@ -314,7 +323,8 @@ extern void paging_init(void); static inline void set_pte(pte_t *ptep, pte_t pteval) { - *ptep = pteval; + WRITE_ONCE(*ptep, pteval); + if (pte_val(pteval) & _PAGE_GLOBAL) { pte_t *buddy = ptep_buddy(ptep); /* @@ -341,8 +351,8 @@ static inline void set_pte(pte_t *ptep, pte_t pteval) : [buddy] "+m" (buddy->pte), [tmp] "=&r" (tmp) : [global] "r" (page_global)); #else /* !CONFIG_SMP */ - if (pte_none(*buddy)) - pte_val(*buddy) = pte_val(*buddy) | _PAGE_GLOBAL; + if (pte_none(ptep_get(buddy))) + WRITE_ONCE(*buddy, __pte(pte_val(ptep_get(buddy)) | _PAGE_GLOBAL)); #endif /* CONFIG_SMP */ } } @@ -350,7 +360,7 @@ static inline void set_pte(pte_t *ptep, pte_t pteval) static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) { /* Preserve global status for the pair */ - if (pte_val(*ptep_buddy(ptep)) & _PAGE_GLOBAL) + if (pte_val(ptep_get(ptep_buddy(ptep))) & _PAGE_GLOBAL) set_pte(ptep, __pte(_PAGE_GLOBAL)); else set_pte(ptep, __pte(0)); @@ -603,7 +613,7 @@ static inline pmd_t pmd_mkinvalid(pmd_t pmd) static inline pmd_t pmdp_huge_get_and_clear(struct mm_struct *mm, unsigned long address, pmd_t *pmdp) { - pmd_t old = *pmdp; + pmd_t old = pmdp_get(pmdp); pmd_clear(pmdp); diff --git a/arch/loongarch/kernel/Makefile.syscalls b/arch/loongarch/kernel/Makefile.syscalls index 523bb411a3bca5..ab7d9baa29152d 100644 --- a/arch/loongarch/kernel/Makefile.syscalls +++ b/arch/loongarch/kernel/Makefile.syscalls @@ -1,3 +1,4 @@ # SPDX-License-Identifier: GPL-2.0 -syscall_abis_64 += newstat +# No special ABIs on loongarch so far +syscall_abis_64 += diff --git a/arch/loongarch/kernel/efi.c b/arch/loongarch/kernel/efi.c index 000825406c1f62..2bf86aeda874c7 100644 --- a/arch/loongarch/kernel/efi.c +++ b/arch/loongarch/kernel/efi.c @@ -66,6 +66,12 @@ void __init efi_runtime_init(void) set_bit(EFI_RUNTIME_SERVICES, &efi.flags); } +bool efi_poweroff_required(void) +{ + return efi_enabled(EFI_RUNTIME_SERVICES) && + (acpi_gbl_reduced_hardware || acpi_no_s5); +} + unsigned long __initdata screen_info_table = EFI_INVALID_TABLE_ADDR; #if defined(CONFIG_SYSFB) || defined(CONFIG_EFI_EARLYCON) diff --git a/arch/loongarch/kvm/mmu.c b/arch/loongarch/kvm/mmu.c index 2634a9e8d82cc5..28681dfb4b8597 100644 --- a/arch/loongarch/kvm/mmu.c +++ b/arch/loongarch/kvm/mmu.c @@ -714,19 +714,19 @@ static int host_pfn_mapping_level(struct kvm *kvm, gfn_t gfn, * value) and then p*d_offset() walks into the target huge page instead * of the old page table (sees the new value). */ - pgd = READ_ONCE(*pgd_offset(kvm->mm, hva)); + pgd = pgdp_get(pgd_offset(kvm->mm, hva)); if (pgd_none(pgd)) goto out; - p4d = READ_ONCE(*p4d_offset(&pgd, hva)); + p4d = p4dp_get(p4d_offset(&pgd, hva)); if (p4d_none(p4d) || !p4d_present(p4d)) goto out; - pud = READ_ONCE(*pud_offset(&p4d, hva)); + pud = pudp_get(pud_offset(&p4d, hva)); if (pud_none(pud) || !pud_present(pud)) goto out; - pmd = READ_ONCE(*pmd_offset(&pud, hva)); + pmd = pmdp_get(pmd_offset(&pud, hva)); if (pmd_none(pmd) || !pmd_present(pmd)) goto out; diff --git a/arch/loongarch/mm/hugetlbpage.c b/arch/loongarch/mm/hugetlbpage.c index 12222c56cb5948..e4068906143b33 100644 --- a/arch/loongarch/mm/hugetlbpage.c +++ b/arch/loongarch/mm/hugetlbpage.c @@ -39,11 +39,11 @@ pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr, pmd_t *pmd = NULL; pgd = pgd_offset(mm, addr); - if (pgd_present(*pgd)) { + if (pgd_present(pgdp_get(pgd))) { p4d = p4d_offset(pgd, addr); - if (p4d_present(*p4d)) { + if (p4d_present(p4dp_get(p4d))) { pud = pud_offset(p4d, addr); - if (pud_present(*pud)) + if (pud_present(pudp_get(pud))) pmd = pmd_offset(pud, addr); } } diff --git a/arch/loongarch/mm/init.c b/arch/loongarch/mm/init.c index bf789d114c2d79..8a87a482c8f44b 100644 --- a/arch/loongarch/mm/init.c +++ b/arch/loongarch/mm/init.c @@ -141,7 +141,7 @@ void __meminit vmemmap_set_pmd(pmd_t *pmd, void *p, int node, int __meminit vmemmap_check_pmd(pmd_t *pmd, int node, unsigned long addr, unsigned long next) { - int huge = pmd_val(*pmd) & _PAGE_HUGE; + int huge = pmd_val(pmdp_get(pmd)) & _PAGE_HUGE; if (huge) vmemmap_verify((pte_t *)pmd, node, addr, next); @@ -173,7 +173,7 @@ pte_t * __init populate_kernel_pte(unsigned long addr) pud_t *pud; pmd_t *pmd; - if (p4d_none(*p4d)) { + if (p4d_none(p4dp_get(p4d))) { pud = memblock_alloc(PAGE_SIZE, PAGE_SIZE); if (!pud) panic("%s: Failed to allocate memory\n", __func__); @@ -184,7 +184,7 @@ pte_t * __init populate_kernel_pte(unsigned long addr) } pud = pud_offset(p4d, addr); - if (pud_none(*pud)) { + if (pud_none(pudp_get(pud))) { pmd = memblock_alloc(PAGE_SIZE, PAGE_SIZE); if (!pmd) panic("%s: Failed to allocate memory\n", __func__); @@ -195,7 +195,7 @@ pte_t * __init populate_kernel_pte(unsigned long addr) } pmd = pmd_offset(pud, addr); - if (!pmd_present(*pmd)) { + if (!pmd_present(pmdp_get(pmd))) { pte_t *pte; pte = memblock_alloc(PAGE_SIZE, PAGE_SIZE); @@ -216,7 +216,7 @@ void __init __set_fixmap(enum fixed_addresses idx, BUG_ON(idx <= FIX_HOLE || idx >= __end_of_fixed_addresses); ptep = populate_kernel_pte(addr); - if (!pte_none(*ptep)) { + if (!pte_none(ptep_get(ptep))) { pte_ERROR(*ptep); return; } diff --git a/arch/loongarch/mm/kasan_init.c b/arch/loongarch/mm/kasan_init.c index c608adc9984581..427d6b1aec09e7 100644 --- a/arch/loongarch/mm/kasan_init.c +++ b/arch/loongarch/mm/kasan_init.c @@ -105,7 +105,7 @@ static phys_addr_t __init kasan_alloc_zeroed_page(int node) static pte_t *__init kasan_pte_offset(pmd_t *pmdp, unsigned long addr, int node, bool early) { - if (__pmd_none(early, READ_ONCE(*pmdp))) { + if (__pmd_none(early, pmdp_get(pmdp))) { phys_addr_t pte_phys = early ? __pa_symbol(kasan_early_shadow_pte) : kasan_alloc_zeroed_page(node); if (!early) @@ -118,7 +118,7 @@ static pte_t *__init kasan_pte_offset(pmd_t *pmdp, unsigned long addr, int node, static pmd_t *__init kasan_pmd_offset(pud_t *pudp, unsigned long addr, int node, bool early) { - if (__pud_none(early, READ_ONCE(*pudp))) { + if (__pud_none(early, pudp_get(pudp))) { phys_addr_t pmd_phys = early ? __pa_symbol(kasan_early_shadow_pmd) : kasan_alloc_zeroed_page(node); if (!early) @@ -131,7 +131,7 @@ static pmd_t *__init kasan_pmd_offset(pud_t *pudp, unsigned long addr, int node, static pud_t *__init kasan_pud_offset(p4d_t *p4dp, unsigned long addr, int node, bool early) { - if (__p4d_none(early, READ_ONCE(*p4dp))) { + if (__p4d_none(early, p4dp_get(p4dp))) { phys_addr_t pud_phys = early ? __pa_symbol(kasan_early_shadow_pud) : kasan_alloc_zeroed_page(node); if (!early) @@ -154,7 +154,7 @@ static void __init kasan_pte_populate(pmd_t *pmdp, unsigned long addr, : kasan_alloc_zeroed_page(node); next = addr + PAGE_SIZE; set_pte(ptep, pfn_pte(__phys_to_pfn(page_phys), PAGE_KERNEL)); - } while (ptep++, addr = next, addr != end && __pte_none(early, READ_ONCE(*ptep))); + } while (ptep++, addr = next, addr != end && __pte_none(early, ptep_get(ptep))); } static void __init kasan_pmd_populate(pud_t *pudp, unsigned long addr, @@ -166,7 +166,7 @@ static void __init kasan_pmd_populate(pud_t *pudp, unsigned long addr, do { next = pmd_addr_end(addr, end); kasan_pte_populate(pmdp, addr, next, node, early); - } while (pmdp++, addr = next, addr != end && __pmd_none(early, READ_ONCE(*pmdp))); + } while (pmdp++, addr = next, addr != end && __pmd_none(early, pmdp_get(pmdp))); } static void __init kasan_pud_populate(p4d_t *p4dp, unsigned long addr, diff --git a/arch/loongarch/mm/pgtable.c b/arch/loongarch/mm/pgtable.c index bda018150000e6..eb6a29b491a72b 100644 --- a/arch/loongarch/mm/pgtable.c +++ b/arch/loongarch/mm/pgtable.c @@ -128,7 +128,7 @@ pmd_t mk_pmd(struct page *page, pgprot_t prot) void set_pmd_at(struct mm_struct *mm, unsigned long addr, pmd_t *pmdp, pmd_t pmd) { - *pmdp = pmd; + WRITE_ONCE(*pmdp, pmd); flush_tlb_all(); } diff --git a/arch/mips/sgi-ip22/ip22-gio.c b/arch/mips/sgi-ip22/ip22-gio.c index 2738325e98dd09..d20eec742bfaab 100644 --- a/arch/mips/sgi-ip22/ip22-gio.c +++ b/arch/mips/sgi-ip22/ip22-gio.c @@ -111,7 +111,7 @@ void gio_device_unregister(struct gio_device *giodev) } EXPORT_SYMBOL_GPL(gio_device_unregister); -static int gio_bus_match(struct device *dev, struct device_driver *drv) +static int gio_bus_match(struct device *dev, const struct device_driver *drv) { struct gio_device *gio_dev = to_gio_device(dev); struct gio_driver *gio_drv = to_gio_driver(drv); diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig index 5d650e02cbf4a3..b0a2ac3ba91610 100644 --- a/arch/parisc/Kconfig +++ b/arch/parisc/Kconfig @@ -20,6 +20,7 @@ config PARISC select ARCH_SUPPORTS_HUGETLBFS if PA20 select ARCH_SUPPORTS_MEMORY_FAILURE select ARCH_STACKWALK + select ARCH_HAS_CACHE_LINE_SIZE select ARCH_HAS_DEBUG_VM_PGTABLE select HAVE_RELIABLE_STACKTRACE select DMA_OPS diff --git a/arch/parisc/include/asm/cache.h b/arch/parisc/include/asm/cache.h index 2a60d7a72f1fa8..a3f0f100f21949 100644 --- a/arch/parisc/include/asm/cache.h +++ b/arch/parisc/include/asm/cache.h @@ -20,7 +20,16 @@ #define SMP_CACHE_BYTES L1_CACHE_BYTES -#define ARCH_DMA_MINALIGN L1_CACHE_BYTES +#ifdef CONFIG_PA20 +#define ARCH_DMA_MINALIGN 128 +#else +#define ARCH_DMA_MINALIGN 32 +#endif +#define ARCH_KMALLOC_MINALIGN 16 /* ldcw requires 16-byte alignment */ + +#define arch_slab_minalign() ((unsigned)dcache_stride) +#define cache_line_size() dcache_stride +#define dma_get_cache_alignment cache_line_size #define __read_mostly __section(".data..read_mostly") diff --git a/arch/parisc/net/bpf_jit_core.c b/arch/parisc/net/bpf_jit_core.c index 979f45d4d1fbea..06cbcd6fe87b80 100644 --- a/arch/parisc/net/bpf_jit_core.c +++ b/arch/parisc/net/bpf_jit_core.c @@ -114,7 +114,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog) jit_data->header = bpf_jit_binary_alloc(prog_size + extable_size, &jit_data->image, - sizeof(u32), + sizeof(long), bpf_fill_ill_insns); if (!jit_data->header) { prog = orig_prog; diff --git a/arch/powerpc/include/asm/topology.h b/arch/powerpc/include/asm/topology.h index f4e6f2dd04b731..16bacfe8c7a2ca 100644 --- a/arch/powerpc/include/asm/topology.h +++ b/arch/powerpc/include/asm/topology.h @@ -145,6 +145,7 @@ static inline int cpu_to_coregroup_id(int cpu) #ifdef CONFIG_HOTPLUG_SMT #include +#include #include static inline bool topology_is_primary_thread(unsigned int cpu) @@ -156,6 +157,18 @@ static inline bool topology_smt_thread_allowed(unsigned int cpu) { return cpu_thread_in_core(cpu) < cpu_smt_num_threads; } + +#define topology_is_core_online topology_is_core_online +static inline bool topology_is_core_online(unsigned int cpu) +{ + int i, first_cpu = cpu_first_thread_sibling(cpu); + + for (i = first_cpu; i < first_cpu + threads_per_core; ++i) { + if (cpu_online(i)) + return true; + } + return false; +} #endif #endif /* __KERNEL__ */ diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c index 4bd2f87616baa9..943430077375a4 100644 --- a/arch/powerpc/kernel/setup-common.c +++ b/arch/powerpc/kernel/setup-common.c @@ -959,6 +959,7 @@ void __init setup_arch(char **cmdline_p) mem_topology_setup(); /* Set max_mapnr before paging_init() */ set_max_mapnr(max_pfn); + high_memory = (void *)__va(max_low_pfn * PAGE_SIZE); /* * Release secondary cpus out of their spinloops at 0x60 now that diff --git a/arch/powerpc/mm/init-common.c b/arch/powerpc/mm/init-common.c index 9b4a675eb8f877..2978fcbe307eab 100644 --- a/arch/powerpc/mm/init-common.c +++ b/arch/powerpc/mm/init-common.c @@ -73,7 +73,7 @@ void setup_kup(void) #define CTOR(shift) static void ctor_##shift(void *addr) \ { \ - memset(addr, 0, sizeof(void *) << (shift)); \ + memset(addr, 0, sizeof(pgd_t) << (shift)); \ } CTOR(0); CTOR(1); CTOR(2); CTOR(3); CTOR(4); CTOR(5); CTOR(6); CTOR(7); @@ -117,7 +117,7 @@ EXPORT_SYMBOL_GPL(pgtable_cache); /* used by kvm_hv module */ void pgtable_cache_add(unsigned int shift) { char *name; - unsigned long table_size = sizeof(void *) << shift; + unsigned long table_size = sizeof(pgd_t) << shift; unsigned long align = table_size; /* When batching pgtable pointers for RCU freeing, we store diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c index d325217ab20121..da21cb018984eb 100644 --- a/arch/powerpc/mm/mem.c +++ b/arch/powerpc/mm/mem.c @@ -290,8 +290,6 @@ void __init mem_init(void) swiotlb_init(ppc_swiotlb_enable, ppc_swiotlb_flags); #endif - high_memory = (void *) __va(max_low_pfn * PAGE_SIZE); - kasan_late_init(); memblock_free_all(); diff --git a/arch/riscv/include/asm/hwprobe.h b/arch/riscv/include/asm/hwprobe.h index ef01c182af2b05..ffb9484531af7e 100644 --- a/arch/riscv/include/asm/hwprobe.h +++ b/arch/riscv/include/asm/hwprobe.h @@ -8,7 +8,7 @@ #include -#define RISCV_HWPROBE_MAX_KEY 8 +#define RISCV_HWPROBE_MAX_KEY 9 static inline bool riscv_hwprobe_key_is_valid(__s64 key) { diff --git a/arch/riscv/include/uapi/asm/hwprobe.h b/arch/riscv/include/uapi/asm/hwprobe.h index b706c8e47b027b..1e153cda57db85 100644 --- a/arch/riscv/include/uapi/asm/hwprobe.h +++ b/arch/riscv/include/uapi/asm/hwprobe.h @@ -82,6 +82,12 @@ struct riscv_hwprobe { #define RISCV_HWPROBE_KEY_ZICBOZ_BLOCK_SIZE 6 #define RISCV_HWPROBE_KEY_HIGHEST_VIRT_ADDRESS 7 #define RISCV_HWPROBE_KEY_TIME_CSR_FREQ 8 +#define RISCV_HWPROBE_KEY_MISALIGNED_SCALAR_PERF 9 +#define RISCV_HWPROBE_MISALIGNED_SCALAR_UNKNOWN 0 +#define RISCV_HWPROBE_MISALIGNED_SCALAR_EMULATED 1 +#define RISCV_HWPROBE_MISALIGNED_SCALAR_SLOW 2 +#define RISCV_HWPROBE_MISALIGNED_SCALAR_FAST 3 +#define RISCV_HWPROBE_MISALIGNED_SCALAR_UNSUPPORTED 4 /* Increase RISCV_HWPROBE_MAX_KEY when adding items. */ /* Flags */ diff --git a/arch/riscv/kernel/Makefile.syscalls b/arch/riscv/kernel/Makefile.syscalls index 52087a023b3df3..9668fd1faf60e8 100644 --- a/arch/riscv/kernel/Makefile.syscalls +++ b/arch/riscv/kernel/Makefile.syscalls @@ -1,4 +1,4 @@ # SPDX-License-Identifier: GPL-2.0 syscall_abis_32 += riscv memfd_secret -syscall_abis_64 += riscv newstat rlimit memfd_secret +syscall_abis_64 += riscv rlimit memfd_secret diff --git a/arch/riscv/kernel/acpi_numa.c b/arch/riscv/kernel/acpi_numa.c index 0231482d6946aa..ff95aeebee3ebc 100644 --- a/arch/riscv/kernel/acpi_numa.c +++ b/arch/riscv/kernel/acpi_numa.c @@ -28,7 +28,7 @@ #include -static int acpi_early_node_map[NR_CPUS] __initdata = { NUMA_NO_NODE }; +static int acpi_early_node_map[NR_CPUS] __initdata = { [0 ... NR_CPUS - 1] = NUMA_NO_NODE }; int __init acpi_numa_get_nid(unsigned int cpu) { diff --git a/arch/riscv/kernel/cpufeature.c b/arch/riscv/kernel/cpufeature.c index 8f20607adb406d..b427188b28fc16 100644 --- a/arch/riscv/kernel/cpufeature.c +++ b/arch/riscv/kernel/cpufeature.c @@ -432,28 +432,26 @@ static void __init riscv_resolve_isa(unsigned long *source_isa, bitmap_copy(prev_resolved_isa, resolved_isa, RISCV_ISA_EXT_MAX); for_each_set_bit(bit, source_isa, RISCV_ISA_EXT_MAX) { ext = riscv_get_isa_ext_data(bit); - if (!ext) - continue; - if (ext->validate) { + if (ext && ext->validate) { ret = ext->validate(ext, resolved_isa); if (ret == -EPROBE_DEFER) { loop = true; continue; } else if (ret) { /* Disable the extension entirely */ - clear_bit(ext->id, source_isa); + clear_bit(bit, source_isa); continue; } } - set_bit(ext->id, resolved_isa); + set_bit(bit, resolved_isa); /* No need to keep it in source isa now that it is enabled */ - clear_bit(ext->id, source_isa); + clear_bit(bit, source_isa); /* Single letter extensions get set in hwcap */ - if (ext->id < RISCV_ISA_EXT_BASE) - *this_hwcap |= isa2hwcap[ext->id]; + if (bit < RISCV_ISA_EXT_BASE) + *this_hwcap |= isa2hwcap[bit]; } } while (loop && memcmp(prev_resolved_isa, resolved_isa, sizeof(prev_resolved_isa))); } diff --git a/arch/riscv/kernel/patch.c b/arch/riscv/kernel/patch.c index 69e5796fc51fde..34ef522f07a8c2 100644 --- a/arch/riscv/kernel/patch.c +++ b/arch/riscv/kernel/patch.c @@ -205,6 +205,8 @@ int patch_text_set_nosync(void *addr, u8 c, size_t len) int ret; ret = patch_insn_set(addr, c, len); + if (!ret) + flush_icache_range((uintptr_t)addr, (uintptr_t)addr + len); return ret; } @@ -239,6 +241,8 @@ int patch_text_nosync(void *addr, const void *insns, size_t len) int ret; ret = patch_insn_write(addr, insns, len); + if (!ret) + flush_icache_range((uintptr_t)addr, (uintptr_t)addr + len); return ret; } diff --git a/arch/riscv/kernel/sbi-ipi.c b/arch/riscv/kernel/sbi-ipi.c index 1026e22955ccc3..0cc5559c08d8ff 100644 --- a/arch/riscv/kernel/sbi-ipi.c +++ b/arch/riscv/kernel/sbi-ipi.c @@ -71,7 +71,7 @@ void __init sbi_ipi_init(void) * the masking/unmasking of virtual IPIs is done * via generic IPI-Mux */ - cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, + cpuhp_setup_state(CPUHP_AP_IRQ_RISCV_SBI_IPI_STARTING, "irqchip/sbi-ipi:starting", sbi_ipi_starting_cpu, NULL); diff --git a/arch/riscv/kernel/sys_hwprobe.c b/arch/riscv/kernel/sys_hwprobe.c index 8d1b5c35d2a731..cea0ca2bf2a25e 100644 --- a/arch/riscv/kernel/sys_hwprobe.c +++ b/arch/riscv/kernel/sys_hwprobe.c @@ -178,13 +178,13 @@ static u64 hwprobe_misaligned(const struct cpumask *cpus) perf = this_perf; if (perf != this_perf) { - perf = RISCV_HWPROBE_MISALIGNED_UNKNOWN; + perf = RISCV_HWPROBE_MISALIGNED_SCALAR_UNKNOWN; break; } } if (perf == -1ULL) - return RISCV_HWPROBE_MISALIGNED_UNKNOWN; + return RISCV_HWPROBE_MISALIGNED_SCALAR_UNKNOWN; return perf; } @@ -192,12 +192,12 @@ static u64 hwprobe_misaligned(const struct cpumask *cpus) static u64 hwprobe_misaligned(const struct cpumask *cpus) { if (IS_ENABLED(CONFIG_RISCV_EFFICIENT_UNALIGNED_ACCESS)) - return RISCV_HWPROBE_MISALIGNED_FAST; + return RISCV_HWPROBE_MISALIGNED_SCALAR_FAST; if (IS_ENABLED(CONFIG_RISCV_EMULATED_UNALIGNED_ACCESS) && unaligned_ctl_available()) - return RISCV_HWPROBE_MISALIGNED_EMULATED; + return RISCV_HWPROBE_MISALIGNED_SCALAR_EMULATED; - return RISCV_HWPROBE_MISALIGNED_SLOW; + return RISCV_HWPROBE_MISALIGNED_SCALAR_SLOW; } #endif @@ -225,6 +225,7 @@ static void hwprobe_one_pair(struct riscv_hwprobe *pair, break; case RISCV_HWPROBE_KEY_CPUPERF_0: + case RISCV_HWPROBE_KEY_MISALIGNED_SCALAR_PERF: pair->value = hwprobe_misaligned(cpus); break; diff --git a/arch/riscv/kernel/traps.c b/arch/riscv/kernel/traps.c index 05a16b1f0aee85..51ebfd23e00764 100644 --- a/arch/riscv/kernel/traps.c +++ b/arch/riscv/kernel/traps.c @@ -319,6 +319,7 @@ void do_trap_ecall_u(struct pt_regs *regs) regs->epc += 4; regs->orig_a0 = regs->a0; + regs->a0 = -ENOSYS; riscv_v_vstate_discard(regs); @@ -328,8 +329,7 @@ void do_trap_ecall_u(struct pt_regs *regs) if (syscall >= 0 && syscall < NR_syscalls) syscall_handler(regs, syscall); - else if (syscall != -1) - regs->a0 = -ENOSYS; + /* * Ultimately, this value will get limited by KSTACK_OFFSET_MAX(), * so the maximum stack offset is 1k bytes (10 bits). diff --git a/arch/riscv/kernel/traps_misaligned.c b/arch/riscv/kernel/traps_misaligned.c index b62d5a2f4541e7..192cd5603e95f9 100644 --- a/arch/riscv/kernel/traps_misaligned.c +++ b/arch/riscv/kernel/traps_misaligned.c @@ -338,7 +338,7 @@ int handle_misaligned_load(struct pt_regs *regs) perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, regs, addr); #ifdef CONFIG_RISCV_PROBE_UNALIGNED_ACCESS - *this_cpu_ptr(&misaligned_access_speed) = RISCV_HWPROBE_MISALIGNED_EMULATED; + *this_cpu_ptr(&misaligned_access_speed) = RISCV_HWPROBE_MISALIGNED_SCALAR_EMULATED; #endif if (!unaligned_enabled) @@ -532,13 +532,13 @@ static bool check_unaligned_access_emulated(int cpu) unsigned long tmp_var, tmp_val; bool misaligned_emu_detected; - *mas_ptr = RISCV_HWPROBE_MISALIGNED_UNKNOWN; + *mas_ptr = RISCV_HWPROBE_MISALIGNED_SCALAR_UNKNOWN; __asm__ __volatile__ ( " "REG_L" %[tmp], 1(%[ptr])\n" : [tmp] "=r" (tmp_val) : [ptr] "r" (&tmp_var) : "memory"); - misaligned_emu_detected = (*mas_ptr == RISCV_HWPROBE_MISALIGNED_EMULATED); + misaligned_emu_detected = (*mas_ptr == RISCV_HWPROBE_MISALIGNED_SCALAR_EMULATED); /* * If unaligned_ctl is already set, this means that we detected that all * CPUS uses emulated misaligned access at boot time. If that changed diff --git a/arch/riscv/kernel/unaligned_access_speed.c b/arch/riscv/kernel/unaligned_access_speed.c index a9a6bcb02acf11..160628a2116de4 100644 --- a/arch/riscv/kernel/unaligned_access_speed.c +++ b/arch/riscv/kernel/unaligned_access_speed.c @@ -34,9 +34,9 @@ static int check_unaligned_access(void *param) struct page *page = param; void *dst; void *src; - long speed = RISCV_HWPROBE_MISALIGNED_SLOW; + long speed = RISCV_HWPROBE_MISALIGNED_SCALAR_SLOW; - if (per_cpu(misaligned_access_speed, cpu) != RISCV_HWPROBE_MISALIGNED_UNKNOWN) + if (per_cpu(misaligned_access_speed, cpu) != RISCV_HWPROBE_MISALIGNED_SCALAR_UNKNOWN) return 0; /* Make an unaligned destination buffer. */ @@ -95,14 +95,14 @@ static int check_unaligned_access(void *param) } if (word_cycles < byte_cycles) - speed = RISCV_HWPROBE_MISALIGNED_FAST; + speed = RISCV_HWPROBE_MISALIGNED_SCALAR_FAST; ratio = div_u64((byte_cycles * 100), word_cycles); pr_info("cpu%d: Ratio of byte access time to unaligned word access is %d.%02d, unaligned accesses are %s\n", cpu, ratio / 100, ratio % 100, - (speed == RISCV_HWPROBE_MISALIGNED_FAST) ? "fast" : "slow"); + (speed == RISCV_HWPROBE_MISALIGNED_SCALAR_FAST) ? "fast" : "slow"); per_cpu(misaligned_access_speed, cpu) = speed; @@ -110,7 +110,7 @@ static int check_unaligned_access(void *param) * Set the value of fast_misaligned_access of a CPU. These operations * are atomic to avoid race conditions. */ - if (speed == RISCV_HWPROBE_MISALIGNED_FAST) + if (speed == RISCV_HWPROBE_MISALIGNED_SCALAR_FAST) cpumask_set_cpu(cpu, &fast_misaligned_access); else cpumask_clear_cpu(cpu, &fast_misaligned_access); @@ -188,7 +188,7 @@ 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_UNKNOWN) + if (per_cpu(misaligned_access_speed, cpu) != RISCV_HWPROBE_MISALIGNED_SCALAR_UNKNOWN) goto exit; buf = alloc_pages(GFP_KERNEL, MISALIGNED_BUFFER_ORDER); diff --git a/arch/riscv/kernel/vendor_extensions.c b/arch/riscv/kernel/vendor_extensions.c index b6c1e7b5d34b36..a8126d1183412f 100644 --- a/arch/riscv/kernel/vendor_extensions.c +++ b/arch/riscv/kernel/vendor_extensions.c @@ -38,7 +38,7 @@ bool __riscv_isa_vendor_extension_available(int cpu, unsigned long vendor, unsig #ifdef CONFIG_RISCV_ISA_VENDOR_EXT_ANDES case ANDES_VENDOR_ID: bmap = &riscv_isa_vendor_ext_list_andes.all_harts_isa_bitmap; - cpu_bmap = &riscv_isa_vendor_ext_list_andes.per_hart_isa_bitmap[cpu]; + cpu_bmap = riscv_isa_vendor_ext_list_andes.per_hart_isa_bitmap; break; #endif default: diff --git a/arch/riscv/mm/fault.c b/arch/riscv/mm/fault.c index 5224f373380225..a9f2b4af8f3f18 100644 --- a/arch/riscv/mm/fault.c +++ b/arch/riscv/mm/fault.c @@ -61,26 +61,27 @@ static inline void no_context(struct pt_regs *regs, unsigned long addr) static inline void mm_fault_error(struct pt_regs *regs, unsigned long addr, vm_fault_t fault) { + if (!user_mode(regs)) { + no_context(regs, addr); + return; + } + if (fault & VM_FAULT_OOM) { /* * We ran out of memory, call the OOM killer, and return the userspace * (which will retry the fault, or kill us if we got oom-killed). */ - if (!user_mode(regs)) { - no_context(regs, addr); - return; - } pagefault_out_of_memory(); return; } else if (fault & (VM_FAULT_SIGBUS | VM_FAULT_HWPOISON | VM_FAULT_HWPOISON_LARGE)) { /* Kernel mode? Handle exceptions or die */ - if (!user_mode(regs)) { - no_context(regs, addr); - return; - } do_trap(regs, SIGBUS, BUS_ADRERR, addr); return; + } else if (fault & VM_FAULT_SIGSEGV) { + do_trap(regs, SIGSEGV, SEGV_MAPERR, addr); + return; } + BUG(); } diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c index bfa2dea95354ff..eb0649a61b4c1f 100644 --- a/arch/riscv/mm/init.c +++ b/arch/riscv/mm/init.c @@ -234,8 +234,6 @@ static void __init setup_bootmem(void) */ memblock_reserve(vmlinux_start, vmlinux_end - vmlinux_start); - phys_ram_end = memblock_end_of_DRAM(); - /* * Make sure we align the start of the memory on a PMD boundary so that * at worst, we map the linear mapping with PMD mappings. @@ -250,6 +248,16 @@ static void __init setup_bootmem(void) if (IS_ENABLED(CONFIG_64BIT) && IS_ENABLED(CONFIG_MMU)) kernel_map.va_pa_offset = PAGE_OFFSET - phys_ram_base; + /* + * The size of the linear page mapping may restrict the amount of + * usable RAM. + */ + if (IS_ENABLED(CONFIG_64BIT)) { + max_mapped_addr = __pa(PAGE_OFFSET) + KERN_VIRT_SIZE; + memblock_cap_memory_range(phys_ram_base, + max_mapped_addr - phys_ram_base); + } + /* * Reserve physical address space that would be mapped to virtual * addresses greater than (void *)(-PAGE_SIZE) because: @@ -266,6 +274,7 @@ static void __init setup_bootmem(void) memblock_reserve(max_mapped_addr, (phys_addr_t)-max_mapped_addr); } + phys_ram_end = memblock_end_of_DRAM(); min_low_pfn = PFN_UP(phys_ram_base); max_low_pfn = max_pfn = PFN_DOWN(phys_ram_end); high_memory = (void *)(__va(PFN_PHYS(max_low_pfn))); @@ -918,7 +927,7 @@ static void __init create_kernel_page_table(pgd_t *pgdir, PMD_SIZE, PAGE_KERNEL_EXEC); /* Map the data in RAM */ - end_va = kernel_map.virt_addr + XIP_OFFSET + kernel_map.size; + end_va = kernel_map.virt_addr + kernel_map.size; for (va = kernel_map.virt_addr + XIP_OFFSET; va < end_va; va += PMD_SIZE) create_pgd_mapping(pgdir, va, kernel_map.phys_addr + (va - (kernel_map.virt_addr + XIP_OFFSET)), @@ -1087,7 +1096,7 @@ asmlinkage void __init setup_vm(uintptr_t dtb_pa) phys_ram_base = CONFIG_PHYS_RAM_BASE; kernel_map.phys_addr = (uintptr_t)CONFIG_PHYS_RAM_BASE; - kernel_map.size = (uintptr_t)(&_end) - (uintptr_t)(&_sdata); + kernel_map.size = (uintptr_t)(&_end) - (uintptr_t)(&_start); kernel_map.va_kernel_xip_pa_offset = kernel_map.virt_addr - kernel_map.xiprom; #else @@ -1284,8 +1293,6 @@ static void __init create_linear_mapping_page_table(void) if (start <= __pa(PAGE_OFFSET) && __pa(PAGE_OFFSET) < end) start = __pa(PAGE_OFFSET); - if (end >= __pa(PAGE_OFFSET) + memory_limit) - end = __pa(PAGE_OFFSET) + memory_limit; create_linear_mapping_range(start, end, 0, NULL); } diff --git a/arch/riscv/purgatory/entry.S b/arch/riscv/purgatory/entry.S index 5bcf3af903daa2..0e6ca6d5ae4b41 100644 --- a/arch/riscv/purgatory/entry.S +++ b/arch/riscv/purgatory/entry.S @@ -7,6 +7,7 @@ * Author: Li Zhengyu (lizhengyu3@huawei.com) * */ +#include #include .text @@ -34,6 +35,7 @@ SYM_CODE_END(purgatory_start) .data +.align LGREG SYM_DATA(riscv_kernel_entry, .quad 0) .end diff --git a/arch/s390/include/asm/uv.h b/arch/s390/include/asm/uv.h index 0b5f8f3e84f126..153d93468b77c0 100644 --- a/arch/s390/include/asm/uv.h +++ b/arch/s390/include/asm/uv.h @@ -441,7 +441,10 @@ static inline int share(unsigned long addr, u16 cmd) if (!uv_call(0, (u64)&uvcb)) return 0; - return -EINVAL; + pr_err("%s UVC failed (rc: 0x%x, rrc: 0x%x), possible hypervisor bug.\n", + uvcb.header.cmd == UVC_CMD_SET_SHARED_ACCESS ? "Share" : "Unshare", + uvcb.header.rc, uvcb.header.rrc); + panic("System security cannot be guaranteed unless the system panics now.\n"); } /* diff --git a/arch/s390/kernel/alternative.h b/arch/s390/kernel/alternative.h deleted file mode 100644 index e69de29bb2d1d6..00000000000000 diff --git a/arch/s390/kernel/fpu.c b/arch/s390/kernel/fpu.c index fa90bbdc5ef946..6f2e87920288ac 100644 --- a/arch/s390/kernel/fpu.c +++ b/arch/s390/kernel/fpu.c @@ -113,7 +113,7 @@ void load_fpu_state(struct fpu *state, int flags) int mask; if (flags & KERNEL_FPC) - fpu_lfpc(&state->fpc); + fpu_lfpc_safe(&state->fpc); if (!cpu_has_vx()) { if (flags & KERNEL_VXR_V0V7) load_fp_regs_vx(state->vxrs); diff --git a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S index 975c654cf5a51f..e67cd409b85871 100644 --- a/arch/s390/kernel/vmlinux.lds.S +++ b/arch/s390/kernel/vmlinux.lds.S @@ -59,14 +59,6 @@ SECTIONS } :text = 0x0700 RO_DATA(PAGE_SIZE) - .data.rel.ro : { - *(.data.rel.ro .data.rel.ro.*) - } - .got : { - __got_start = .; - *(.got) - __got_end = .; - } . = ALIGN(PAGE_SIZE); _sdata = .; /* Start of data section */ @@ -80,6 +72,15 @@ SECTIONS . = ALIGN(PAGE_SIZE); __end_ro_after_init = .; + .data.rel.ro : { + *(.data.rel.ro .data.rel.ro.*) + } + .got : { + __got_start = .; + *(.got) + __got_end = .; + } + RW_DATA(0x100, PAGE_SIZE, THREAD_SIZE) .data.rel : { *(.data.rel*) diff --git a/arch/s390/kvm/kvm-s390.h b/arch/s390/kvm/kvm-s390.h index bf8534218af3dc..e680c6bf0c9d94 100644 --- a/arch/s390/kvm/kvm-s390.h +++ b/arch/s390/kvm/kvm-s390.h @@ -267,7 +267,12 @@ static inline unsigned long kvm_s390_get_gfn_end(struct kvm_memslots *slots) static inline u32 kvm_s390_get_gisa_desc(struct kvm *kvm) { - u32 gd = virt_to_phys(kvm->arch.gisa_int.origin); + u32 gd; + + if (!kvm->arch.gisa_int.origin) + return 0; + + gd = virt_to_phys(kvm->arch.gisa_int.origin); if (gd && sclp.has_gisaf) gd |= GISA_FORMAT1; diff --git a/arch/s390/mm/dump_pagetables.c b/arch/s390/mm/dump_pagetables.c index 98dab3e049de2a..0a67fcee44141e 100644 --- a/arch/s390/mm/dump_pagetables.c +++ b/arch/s390/mm/dump_pagetables.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -15,13 +16,15 @@ static unsigned long max_addr; struct addr_marker { + int is_start; unsigned long start_address; const char *name; }; enum address_markers_idx { - IDENTITY_BEFORE_NR = 0, - IDENTITY_BEFORE_END_NR, + KVA_NR = 0, + LOWCORE_START_NR, + LOWCORE_END_NR, AMODE31_START_NR, AMODE31_END_NR, KERNEL_START_NR, @@ -30,8 +33,8 @@ enum address_markers_idx { KFENCE_START_NR, KFENCE_END_NR, #endif - IDENTITY_AFTER_NR, - IDENTITY_AFTER_END_NR, + IDENTITY_START_NR, + IDENTITY_END_NR, VMEMMAP_NR, VMEMMAP_END_NR, VMALLOC_NR, @@ -59,43 +62,44 @@ enum address_markers_idx { }; static struct addr_marker address_markers[] = { - [IDENTITY_BEFORE_NR] = {0, "Identity Mapping Start"}, - [IDENTITY_BEFORE_END_NR] = {(unsigned long)_stext, "Identity Mapping End"}, - [AMODE31_START_NR] = {0, "Amode31 Area Start"}, - [AMODE31_END_NR] = {0, "Amode31 Area End"}, - [KERNEL_START_NR] = {(unsigned long)_stext, "Kernel Image Start"}, - [KERNEL_END_NR] = {(unsigned long)_end, "Kernel Image End"}, + [KVA_NR] = {0, 0, "Kernel Virtual Address Space"}, + [LOWCORE_START_NR] = {1, 0, "Lowcore Start"}, + [LOWCORE_END_NR] = {0, 0, "Lowcore End"}, + [IDENTITY_START_NR] = {1, 0, "Identity Mapping Start"}, + [IDENTITY_END_NR] = {0, 0, "Identity Mapping End"}, + [AMODE31_START_NR] = {1, 0, "Amode31 Area Start"}, + [AMODE31_END_NR] = {0, 0, "Amode31 Area End"}, + [KERNEL_START_NR] = {1, (unsigned long)_stext, "Kernel Image Start"}, + [KERNEL_END_NR] = {0, (unsigned long)_end, "Kernel Image End"}, #ifdef CONFIG_KFENCE - [KFENCE_START_NR] = {0, "KFence Pool Start"}, - [KFENCE_END_NR] = {0, "KFence Pool End"}, + [KFENCE_START_NR] = {1, 0, "KFence Pool Start"}, + [KFENCE_END_NR] = {0, 0, "KFence Pool End"}, #endif - [IDENTITY_AFTER_NR] = {(unsigned long)_end, "Identity Mapping Start"}, - [IDENTITY_AFTER_END_NR] = {0, "Identity Mapping End"}, - [VMEMMAP_NR] = {0, "vmemmap Area Start"}, - [VMEMMAP_END_NR] = {0, "vmemmap Area End"}, - [VMALLOC_NR] = {0, "vmalloc Area Start"}, - [VMALLOC_END_NR] = {0, "vmalloc Area End"}, + [VMEMMAP_NR] = {1, 0, "vmemmap Area Start"}, + [VMEMMAP_END_NR] = {0, 0, "vmemmap Area End"}, + [VMALLOC_NR] = {1, 0, "vmalloc Area Start"}, + [VMALLOC_END_NR] = {0, 0, "vmalloc Area End"}, #ifdef CONFIG_KMSAN - [KMSAN_VMALLOC_SHADOW_START_NR] = {0, "Kmsan vmalloc Shadow Start"}, - [KMSAN_VMALLOC_SHADOW_END_NR] = {0, "Kmsan vmalloc Shadow End"}, - [KMSAN_VMALLOC_ORIGIN_START_NR] = {0, "Kmsan vmalloc Origins Start"}, - [KMSAN_VMALLOC_ORIGIN_END_NR] = {0, "Kmsan vmalloc Origins End"}, - [KMSAN_MODULES_SHADOW_START_NR] = {0, "Kmsan Modules Shadow Start"}, - [KMSAN_MODULES_SHADOW_END_NR] = {0, "Kmsan Modules Shadow End"}, - [KMSAN_MODULES_ORIGIN_START_NR] = {0, "Kmsan Modules Origins Start"}, - [KMSAN_MODULES_ORIGIN_END_NR] = {0, "Kmsan Modules Origins End"}, + [KMSAN_VMALLOC_SHADOW_START_NR] = {1, 0, "Kmsan vmalloc Shadow Start"}, + [KMSAN_VMALLOC_SHADOW_END_NR] = {0, 0, "Kmsan vmalloc Shadow End"}, + [KMSAN_VMALLOC_ORIGIN_START_NR] = {1, 0, "Kmsan vmalloc Origins Start"}, + [KMSAN_VMALLOC_ORIGIN_END_NR] = {0, 0, "Kmsan vmalloc Origins End"}, + [KMSAN_MODULES_SHADOW_START_NR] = {1, 0, "Kmsan Modules Shadow Start"}, + [KMSAN_MODULES_SHADOW_END_NR] = {0, 0, "Kmsan Modules Shadow End"}, + [KMSAN_MODULES_ORIGIN_START_NR] = {1, 0, "Kmsan Modules Origins Start"}, + [KMSAN_MODULES_ORIGIN_END_NR] = {0, 0, "Kmsan Modules Origins End"}, #endif - [MODULES_NR] = {0, "Modules Area Start"}, - [MODULES_END_NR] = {0, "Modules Area End"}, - [ABS_LOWCORE_NR] = {0, "Lowcore Area Start"}, - [ABS_LOWCORE_END_NR] = {0, "Lowcore Area End"}, - [MEMCPY_REAL_NR] = {0, "Real Memory Copy Area Start"}, - [MEMCPY_REAL_END_NR] = {0, "Real Memory Copy Area End"}, + [MODULES_NR] = {1, 0, "Modules Area Start"}, + [MODULES_END_NR] = {0, 0, "Modules Area End"}, + [ABS_LOWCORE_NR] = {1, 0, "Lowcore Area Start"}, + [ABS_LOWCORE_END_NR] = {0, 0, "Lowcore Area End"}, + [MEMCPY_REAL_NR] = {1, 0, "Real Memory Copy Area Start"}, + [MEMCPY_REAL_END_NR] = {0, 0, "Real Memory Copy Area End"}, #ifdef CONFIG_KASAN - [KASAN_SHADOW_START_NR] = {KASAN_SHADOW_START, "Kasan Shadow Start"}, - [KASAN_SHADOW_END_NR] = {KASAN_SHADOW_END, "Kasan Shadow End"}, + [KASAN_SHADOW_START_NR] = {1, KASAN_SHADOW_START, "Kasan Shadow Start"}, + [KASAN_SHADOW_END_NR] = {0, KASAN_SHADOW_END, "Kasan Shadow End"}, #endif - { -1, NULL } + {1, -1UL, NULL} }; struct pg_state { @@ -163,6 +167,19 @@ static void note_prot_wx(struct pg_state *st, unsigned long addr) st->wx_pages += (addr - st->start_address) / PAGE_SIZE; } +static void note_page_update_state(struct pg_state *st, unsigned long addr, unsigned int prot, int level) +{ + struct seq_file *m = st->seq; + + while (addr >= st->marker[1].start_address) { + st->marker++; + pt_dump_seq_printf(m, "---[ %s ]---\n", st->marker->name); + } + st->start_address = addr; + st->current_prot = prot; + st->level = level; +} + static void note_page(struct ptdump_state *pt_st, unsigned long addr, int level, u64 val) { int width = sizeof(unsigned long) * 2; @@ -186,9 +203,7 @@ static void note_page(struct ptdump_state *pt_st, unsigned long addr, int level, addr = max_addr; if (st->level == -1) { pt_dump_seq_printf(m, "---[ %s ]---\n", st->marker->name); - st->start_address = addr; - st->current_prot = prot; - st->level = level; + note_page_update_state(st, addr, prot, level); } else if (prot != st->current_prot || level != st->level || addr >= st->marker[1].start_address) { note_prot_wx(st, addr); @@ -202,13 +217,7 @@ static void note_page(struct ptdump_state *pt_st, unsigned long addr, int level, } pt_dump_seq_printf(m, "%9lu%c ", delta, *unit); print_prot(m, st->current_prot, st->level); - while (addr >= st->marker[1].start_address) { - st->marker++; - pt_dump_seq_printf(m, "---[ %s ]---\n", st->marker->name); - } - st->start_address = addr; - st->current_prot = prot; - st->level = level; + note_page_update_state(st, addr, prot, level); } } @@ -280,22 +289,25 @@ static int ptdump_show(struct seq_file *m, void *v) DEFINE_SHOW_ATTRIBUTE(ptdump); #endif /* CONFIG_PTDUMP_DEBUGFS */ -/* - * Heapsort from lib/sort.c is not a stable sorting algorithm, do a simple - * insertion sort to preserve the original order of markers with the same - * start address. - */ -static void sort_address_markers(void) +static int ptdump_cmp(const void *a, const void *b) { - struct addr_marker tmp; - int i, j; + const struct addr_marker *ama = a; + const struct addr_marker *amb = b; - for (i = 1; i < ARRAY_SIZE(address_markers) - 1; i++) { - tmp = address_markers[i]; - for (j = i - 1; j >= 0 && address_markers[j].start_address > tmp.start_address; j--) - address_markers[j + 1] = address_markers[j]; - address_markers[j + 1] = tmp; - } + if (ama->start_address > amb->start_address) + return 1; + if (ama->start_address < amb->start_address) + return -1; + /* + * If the start addresses of two markers are identical consider the + * marker which defines the start of an area higher than the one which + * defines the end of an area. This keeps pairs of markers sorted. + */ + if (ama->is_start) + return 1; + if (amb->is_start) + return -1; + return 0; } static int pt_dump_init(void) @@ -303,6 +315,8 @@ static int pt_dump_init(void) #ifdef CONFIG_KFENCE unsigned long kfence_start = (unsigned long)__kfence_pool; #endif + unsigned long lowcore = (unsigned long)get_lowcore(); + /* * Figure out the maximum virtual address being accessible with the * kernel ASCE. We need this to keep the page table walker functions @@ -310,7 +324,10 @@ static int pt_dump_init(void) */ max_addr = (get_lowcore()->kernel_asce.val & _REGION_ENTRY_TYPE_MASK) >> 2; max_addr = 1UL << (max_addr * 11 + 31); - address_markers[IDENTITY_AFTER_END_NR].start_address = ident_map_size; + address_markers[LOWCORE_START_NR].start_address = lowcore; + address_markers[LOWCORE_END_NR].start_address = lowcore + sizeof(struct lowcore); + address_markers[IDENTITY_START_NR].start_address = __identity_base; + address_markers[IDENTITY_END_NR].start_address = __identity_base + ident_map_size; address_markers[AMODE31_START_NR].start_address = (unsigned long)__samode31; address_markers[AMODE31_END_NR].start_address = (unsigned long)__eamode31; address_markers[MODULES_NR].start_address = MODULES_VADDR; @@ -337,7 +354,8 @@ static int pt_dump_init(void) address_markers[KMSAN_MODULES_ORIGIN_START_NR].start_address = KMSAN_MODULES_ORIGIN_START; address_markers[KMSAN_MODULES_ORIGIN_END_NR].start_address = KMSAN_MODULES_ORIGIN_END; #endif - sort_address_markers(); + sort(address_markers, ARRAY_SIZE(address_markers) - 1, + sizeof(address_markers[0]), ptdump_cmp, NULL); #ifdef CONFIG_PTDUMP_DEBUGFS debugfs_create_file("kernel_page_tables", 0400, NULL, NULL, &ptdump_fops); #endif /* CONFIG_PTDUMP_DEBUGFS */ diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c index ddcd39ef43463a..e3d258f9e72610 100644 --- a/arch/s390/mm/init.c +++ b/arch/s390/mm/init.c @@ -108,6 +108,8 @@ void mark_rodata_ro(void) { unsigned long size = __end_ro_after_init - __start_ro_after_init; + if (MACHINE_HAS_NX) + system_ctl_set_bit(0, CR0_INSTRUCTION_EXEC_PROTECTION_BIT); __set_memory_ro(__start_ro_after_init, __end_ro_after_init); pr_info("Write protected read-only-after-init data: %luk\n", size >> 10); } @@ -170,13 +172,6 @@ void __init mem_init(void) setup_zero_pages(); /* Setup zeroed pages. */ } -void free_initmem(void) -{ - set_memory_rwnx((unsigned long)_sinittext, - (unsigned long)(_einittext - _sinittext) >> PAGE_SHIFT); - free_initmem_default(POISON_FREE_INITMEM); -} - unsigned long memory_block_size_bytes(void) { /* diff --git a/arch/s390/mm/vmem.c b/arch/s390/mm/vmem.c index 41c714e212927b..665b8228afebcd 100644 --- a/arch/s390/mm/vmem.c +++ b/arch/s390/mm/vmem.c @@ -661,7 +661,6 @@ void __init vmem_map_init(void) { __set_memory_rox(_stext, _etext); __set_memory_ro(_etext, __end_rodata); - __set_memory_rox(_sinittext, _einittext); __set_memory_rox(__stext_amode31, __etext_amode31); /* * If the BEAR-enhancement facility is not installed the first @@ -670,16 +669,8 @@ void __init vmem_map_init(void) */ if (!static_key_enabled(&cpu_has_bear)) set_memory_x(0, 1); - if (debug_pagealloc_enabled()) { - /* - * Use RELOC_HIDE() as long as __va(0) translates to NULL, - * since performing pointer arithmetic on a NULL pointer - * has undefined behavior and generates compiler warnings. - */ - __set_memory_4k(__va(0), RELOC_HIDE(__va(0), ident_map_size)); - } - if (MACHINE_HAS_NX) - system_ctl_set_bit(0, CR0_INSTRUCTION_EXEC_PROTECTION_BIT); + if (debug_pagealloc_enabled()) + __set_memory_4k(__va(0), __va(0) + ident_map_size); pr_info("Write protected kernel read-only data: %luk\n", (unsigned long)(__end_rodata - _stext) >> 10); } diff --git a/arch/um/drivers/mconsole_user.c b/arch/um/drivers/mconsole_user.c index e24298a734befd..a04cd13c6315a2 100644 --- a/arch/um/drivers/mconsole_user.c +++ b/arch/um/drivers/mconsole_user.c @@ -71,7 +71,9 @@ static struct mconsole_command *mconsole_parse(struct mc_request *req) return NULL; } +#ifndef MIN #define MIN(a,b) ((a)<(b) ? (a):(b)) +#endif #define STRINGX(x) #x #define STRING(x) STRINGX(x) diff --git a/arch/x86/coco/sev/core.c b/arch/x86/coco/sev/core.c index 082d61d85dfc10..de1df0cb45dab2 100644 --- a/arch/x86/coco/sev/core.c +++ b/arch/x86/coco/sev/core.c @@ -163,7 +163,7 @@ struct sev_config { */ use_cas : 1, - __reserved : 62; + __reserved : 61; }; static struct sev_config sev_cfg __read_mostly; diff --git a/arch/x86/entry/syscalls/syscall_64.tbl b/arch/x86/entry/syscalls/syscall_64.tbl index 83073fa3c9891e..7093ee21c0d1c0 100644 --- a/arch/x86/entry/syscalls/syscall_64.tbl +++ b/arch/x86/entry/syscalls/syscall_64.tbl @@ -344,6 +344,7 @@ 332 common statx sys_statx 333 common io_pgetevents sys_io_pgetevents 334 common rseq sys_rseq +335 common uretprobe sys_uretprobe # don't use numbers 387 through 423, add new calls after the last # 'common' entry 424 common pidfd_send_signal sys_pidfd_send_signal @@ -385,7 +386,6 @@ 460 common lsm_set_self_attr sys_lsm_set_self_attr 461 common lsm_list_modules sys_lsm_list_modules 462 common mseal sys_mseal -467 common uretprobe sys_uretprobe # # Due to a historical design error, certain syscalls are numbered differently diff --git a/arch/x86/events/core.c b/arch/x86/events/core.c index 12f2a0c14d33b4..be01823b1bb453 100644 --- a/arch/x86/events/core.c +++ b/arch/x86/events/core.c @@ -1520,20 +1520,23 @@ static void x86_pmu_start(struct perf_event *event, int flags) void perf_event_print_debug(void) { u64 ctrl, status, overflow, pmc_ctrl, pmc_count, prev_left, fixed; + unsigned long *cntr_mask, *fixed_cntr_mask; + struct event_constraint *pebs_constraints; + struct cpu_hw_events *cpuc; u64 pebs, debugctl; - int cpu = smp_processor_id(); - struct cpu_hw_events *cpuc = &per_cpu(cpu_hw_events, cpu); - unsigned long *cntr_mask = hybrid(cpuc->pmu, cntr_mask); - unsigned long *fixed_cntr_mask = hybrid(cpuc->pmu, fixed_cntr_mask); - struct event_constraint *pebs_constraints = hybrid(cpuc->pmu, pebs_constraints); - unsigned long flags; - int idx; + int cpu, idx; + + guard(irqsave)(); + + cpu = smp_processor_id(); + cpuc = &per_cpu(cpu_hw_events, cpu); + cntr_mask = hybrid(cpuc->pmu, cntr_mask); + fixed_cntr_mask = hybrid(cpuc->pmu, fixed_cntr_mask); + pebs_constraints = hybrid(cpuc->pmu, pebs_constraints); if (!*(u64 *)cntr_mask) return; - local_irq_save(flags); - if (x86_pmu.version >= 2) { rdmsrl(MSR_CORE_PERF_GLOBAL_CTRL, ctrl); rdmsrl(MSR_CORE_PERF_GLOBAL_STATUS, status); @@ -1577,7 +1580,6 @@ void perf_event_print_debug(void) pr_info("CPU#%d: fixed-PMC%d count: %016llx\n", cpu, idx, pmc_count); } - local_irq_restore(flags); } void x86_pmu_stop(struct perf_event *event, int flags) diff --git a/arch/x86/events/intel/cstate.c b/arch/x86/events/intel/cstate.c index be58cfb012dd16..9f116dfc472845 100644 --- a/arch/x86/events/intel/cstate.c +++ b/arch/x86/events/intel/cstate.c @@ -64,7 +64,7 @@ * perf code: 0x00 * Available model: SNB,IVB,HSW,BDW,SKL,KNL,GLM,CNL, * KBL,CML,ICL,ICX,TGL,TNT,RKL,ADL, - * RPL,SPR,MTL,ARL,LNL + * RPL,SPR,MTL,ARL,LNL,SRF * Scope: Package (physical package) * MSR_PKG_C3_RESIDENCY: Package C3 Residency Counter. * perf code: 0x01 @@ -693,7 +693,8 @@ static const struct cstate_model srf_cstates __initconst = { .core_events = BIT(PERF_CSTATE_CORE_C1_RES) | BIT(PERF_CSTATE_CORE_C6_RES), - .pkg_events = BIT(PERF_CSTATE_PKG_C6_RES), + .pkg_events = BIT(PERF_CSTATE_PKG_C2_RES) | + BIT(PERF_CSTATE_PKG_C6_RES), .module_events = BIT(PERF_CSTATE_MODULE_C6_RES), }; diff --git a/arch/x86/include/asm/cmdline.h b/arch/x86/include/asm/cmdline.h index 6faaf27e889989..6cbd9ae58b21b3 100644 --- a/arch/x86/include/asm/cmdline.h +++ b/arch/x86/include/asm/cmdline.h @@ -2,6 +2,10 @@ #ifndef _ASM_X86_CMDLINE_H #define _ASM_X86_CMDLINE_H +#include + +extern char builtin_cmdline[COMMAND_LINE_SIZE]; + int cmdline_find_option_bool(const char *cmdline_ptr, const char *option); int cmdline_find_option(const char *cmdline_ptr, const char *option, char *buffer, int bufsize); diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 950a03e0181ec3..4a68cb3eba78f8 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -1305,6 +1305,7 @@ struct kvm_arch { u8 vm_type; bool has_private_mem; bool has_protected_state; + bool pre_fault_allowed; struct hlist_head mmu_page_hash[KVM_NUM_MMU_PAGES]; struct list_head active_mmu_pages; struct list_head zapped_obsolete_pages; @@ -2191,6 +2192,8 @@ void kvm_configure_mmu(bool enable_tdp, int tdp_forced_root_level, #define kvm_arch_has_private_mem(kvm) false #endif +#define kvm_arch_has_readonly_mem(kvm) (!(kvm)->arch.has_protected_state) + static inline u16 kvm_read_ldt(void) { u16 ldt; diff --git a/arch/x86/include/asm/qspinlock.h b/arch/x86/include/asm/qspinlock.h index a053c12939751f..68da67df304d5d 100644 --- a/arch/x86/include/asm/qspinlock.h +++ b/arch/x86/include/asm/qspinlock.h @@ -66,13 +66,15 @@ static inline bool vcpu_is_preempted(long cpu) #ifdef CONFIG_PARAVIRT /* - * virt_spin_lock_key - enables (by default) the virt_spin_lock() hijack. + * virt_spin_lock_key - disables by default the virt_spin_lock() hijack. * - * Native (and PV wanting native due to vCPU pinning) should disable this key. - * It is done in this backwards fashion to only have a single direction change, - * which removes ordering between native_pv_spin_init() and HV setup. + * Native (and PV wanting native due to vCPU pinning) should keep this key + * disabled. Native does not touch the key. + * + * When in a guest then native_pv_lock_init() enables the key first and + * KVM/XEN might conditionally disable it later in the boot process again. */ -DECLARE_STATIC_KEY_TRUE(virt_spin_lock_key); +DECLARE_STATIC_KEY_FALSE(virt_spin_lock_key); /* * Shortcut for the queued_spin_lock_slowpath() function that allows diff --git a/arch/x86/kernel/acpi/madt_wakeup.c b/arch/x86/kernel/acpi/madt_wakeup.c index 6cfe762be28bbc..d5ef6215583bcf 100644 --- a/arch/x86/kernel/acpi/madt_wakeup.c +++ b/arch/x86/kernel/acpi/madt_wakeup.c @@ -19,7 +19,7 @@ static u64 acpi_mp_wake_mailbox_paddr __ro_after_init; /* Virtual address of the Multiprocessor Wakeup Structure mailbox */ -static struct acpi_madt_multiproc_wakeup_mailbox *acpi_mp_wake_mailbox __ro_after_init; +static struct acpi_madt_multiproc_wakeup_mailbox *acpi_mp_wake_mailbox; static u64 acpi_mp_pgd __ro_after_init; static u64 acpi_mp_reset_vector_paddr __ro_after_init; diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index be5889bded4984..1e0fe5f8ab84e4 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c @@ -462,7 +462,7 @@ static void bsp_init_amd(struct cpuinfo_x86 *c) switch (c->x86_model) { case 0x00 ... 0x2f: case 0x40 ... 0x4f: - case 0x70 ... 0x7f: + case 0x60 ... 0x7f: setup_force_cpu_cap(X86_FEATURE_ZEN5); break; default: diff --git a/arch/x86/kernel/cpu/aperfmperf.c b/arch/x86/kernel/cpu/aperfmperf.c index b3fa61d45352e7..0b69bfbf345d0d 100644 --- a/arch/x86/kernel/cpu/aperfmperf.c +++ b/arch/x86/kernel/cpu/aperfmperf.c @@ -306,7 +306,7 @@ static void freq_invariance_enable(void) WARN_ON_ONCE(1); return; } - static_branch_enable(&arch_scale_freq_key); + static_branch_enable_cpuslocked(&arch_scale_freq_key); register_freq_invariance_syscore_ops(); pr_info("Estimated ratio of average max frequency by base frequency (times 1024): %llu\n", arch_max_freq_ratio); } @@ -323,8 +323,10 @@ static void __init bp_init_freq_invariance(void) if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL) return; - if (intel_set_max_freq_ratio()) + if (intel_set_max_freq_ratio()) { + guard(cpus_read_lock)(); freq_invariance_enable(); + } } static void disable_freq_invariance_workfn(struct work_struct *work) diff --git a/arch/x86/kernel/cpu/mtrr/mtrr.c b/arch/x86/kernel/cpu/mtrr/mtrr.c index 767bf1c71aadda..2a2fc14955cd3b 100644 --- a/arch/x86/kernel/cpu/mtrr/mtrr.c +++ b/arch/x86/kernel/cpu/mtrr/mtrr.c @@ -609,7 +609,7 @@ void mtrr_save_state(void) { int first_cpu; - if (!mtrr_enabled()) + if (!mtrr_enabled() || !mtrr_state.have_fixed) return; first_cpu = cpumask_first(cpu_online_mask); diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c index 5358d43886adc5..fec38153355581 100644 --- a/arch/x86/kernel/paravirt.c +++ b/arch/x86/kernel/paravirt.c @@ -51,13 +51,12 @@ DEFINE_ASM_FUNC(pv_native_irq_enable, "sti", .noinstr.text); DEFINE_ASM_FUNC(pv_native_read_cr2, "mov %cr2, %rax", .noinstr.text); #endif -DEFINE_STATIC_KEY_TRUE(virt_spin_lock_key); +DEFINE_STATIC_KEY_FALSE(virt_spin_lock_key); void __init native_pv_lock_init(void) { - if (IS_ENABLED(CONFIG_PARAVIRT_SPINLOCKS) && - !boot_cpu_has(X86_FEATURE_HYPERVISOR)) - static_branch_disable(&virt_spin_lock_key); + if (boot_cpu_has(X86_FEATURE_HYPERVISOR)) + static_branch_enable(&virt_spin_lock_key); } static void native_tlb_remove_table(struct mmu_gather *tlb, void *table) diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 5d34cad9b7b180..6129dc2ba784cb 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -164,7 +164,7 @@ unsigned long saved_video_mode; static char __initdata command_line[COMMAND_LINE_SIZE]; #ifdef CONFIG_CMDLINE_BOOL -static char __initdata builtin_cmdline[COMMAND_LINE_SIZE] = CONFIG_CMDLINE; +char builtin_cmdline[COMMAND_LINE_SIZE] = CONFIG_CMDLINE; bool builtin_cmdline_added __ro_after_init; #endif diff --git a/arch/x86/kvm/Kconfig b/arch/x86/kvm/Kconfig index 4287a8071a3ab6..472a1537b7a977 100644 --- a/arch/x86/kvm/Kconfig +++ b/arch/x86/kvm/Kconfig @@ -141,8 +141,8 @@ config KVM_AMD_SEV depends on CRYPTO_DEV_SP_PSP && !(KVM_AMD=y && CRYPTO_DEV_CCP_DD=m) select ARCH_HAS_CC_PLATFORM select KVM_GENERIC_PRIVATE_MEM - select HAVE_KVM_GMEM_PREPARE - select HAVE_KVM_GMEM_INVALIDATE + select HAVE_KVM_ARCH_GMEM_PREPARE + select HAVE_KVM_ARCH_GMEM_INVALIDATE help Provides support for launching Encrypted VMs (SEV) and Encrypted VMs with Encrypted State (SEV-ES) on AMD processors. diff --git a/arch/x86/kvm/hyperv.h b/arch/x86/kvm/hyperv.h index 923e64903da9af..913bfc96959cbf 100644 --- a/arch/x86/kvm/hyperv.h +++ b/arch/x86/kvm/hyperv.h @@ -286,7 +286,6 @@ static inline int kvm_hv_hypercall(struct kvm_vcpu *vcpu) return HV_STATUS_ACCESS_DENIED; } static inline void kvm_hv_vcpu_purge_flush_tlb(struct kvm_vcpu *vcpu) {} -static inline void kvm_hv_free_pa_page(struct kvm *kvm) {} static inline bool kvm_hv_synic_has_vector(struct kvm_vcpu *vcpu, int vector) { return false; diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c index a7172ba59ad2e7..5bb481aefcbcdc 100644 --- a/arch/x86/kvm/lapic.c +++ b/arch/x86/kvm/lapic.c @@ -351,10 +351,8 @@ static void kvm_recalculate_logical_map(struct kvm_apic_map *new, * reversing the LDR calculation to get cluster of APICs, i.e. no * additional work is required. */ - if (apic_x2apic_mode(apic)) { - WARN_ON_ONCE(ldr != kvm_apic_calc_x2apic_ldr(kvm_x2apic_id(apic))); + if (apic_x2apic_mode(apic)) return; - } if (WARN_ON_ONCE(!kvm_apic_map_get_logical_dest(new, ldr, &cluster, &mask))) { @@ -1743,7 +1741,7 @@ static void limit_periodic_timer_frequency(struct kvm_lapic *apic) s64 min_period = min_timer_period_us * 1000LL; if (apic->lapic_timer.period < min_period) { - pr_info_ratelimited( + pr_info_once( "vcpu %i: requested %lld ns " "lapic timer period limited to %lld ns\n", apic->vcpu->vcpu_id, @@ -2966,18 +2964,28 @@ static int kvm_apic_state_fixup(struct kvm_vcpu *vcpu, struct kvm_lapic_state *s, bool set) { if (apic_x2apic_mode(vcpu->arch.apic)) { + u32 x2apic_id = kvm_x2apic_id(vcpu->arch.apic); u32 *id = (u32 *)(s->regs + APIC_ID); u32 *ldr = (u32 *)(s->regs + APIC_LDR); u64 icr; if (vcpu->kvm->arch.x2apic_format) { - if (*id != vcpu->vcpu_id) + if (*id != x2apic_id) return -EINVAL; } else { + /* + * Ignore the userspace value when setting APIC state. + * KVM's model is that the x2APIC ID is readonly, e.g. + * KVM only supports delivering interrupts to KVM's + * version of the x2APIC ID. However, for backwards + * compatibility, don't reject attempts to set a + * mismatched ID for userspace that hasn't opted into + * x2apic_format. + */ if (set) - *id >>= 24; + *id = x2apic_id; else - *id <<= 24; + *id = x2apic_id << 24; } /* @@ -2986,7 +2994,7 @@ static int kvm_apic_state_fixup(struct kvm_vcpu *vcpu, * split to ICR+ICR2 in userspace for backwards compatibility. */ if (set) { - *ldr = kvm_apic_calc_x2apic_ldr(*id); + *ldr = kvm_apic_calc_x2apic_ldr(x2apic_id); icr = __kvm_lapic_get_reg(s->regs, APIC_ICR) | (u64)__kvm_lapic_get_reg(s->regs, APIC_ICR2) << 32; diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c index 901be9e420a4c5..928cf84778b0c5 100644 --- a/arch/x86/kvm/mmu/mmu.c +++ b/arch/x86/kvm/mmu/mmu.c @@ -4335,7 +4335,7 @@ static u8 kvm_max_private_mapping_level(struct kvm *kvm, kvm_pfn_t pfn, if (req_max_level) max_level = min(max_level, req_max_level); - return req_max_level; + return max_level; } static int kvm_faultin_pfn_private(struct kvm_vcpu *vcpu, @@ -4743,6 +4743,9 @@ long kvm_arch_vcpu_pre_fault_memory(struct kvm_vcpu *vcpu, u64 end; int r; + if (!vcpu->kvm->arch.pre_fault_allowed) + return -EOPNOTSUPP; + /* * reload is efficient when called repeatedly, so we can do it on * every iteration. @@ -7510,7 +7513,7 @@ static bool hugepage_has_attrs(struct kvm *kvm, struct kvm_memory_slot *slot, const unsigned long end = start + KVM_PAGES_PER_HPAGE(level); if (level == PG_LEVEL_2M) - return kvm_range_has_memory_attributes(kvm, start, end, attrs); + return kvm_range_has_memory_attributes(kvm, start, end, ~0, attrs); for (gfn = start; gfn < end; gfn += KVM_PAGES_PER_HPAGE(level - 1)) { if (hugepage_test_mixed(slot, gfn, level - 1) || diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c index a16c873b323218..714c517dd4b72b 100644 --- a/arch/x86/kvm/svm/sev.c +++ b/arch/x86/kvm/svm/sev.c @@ -2276,30 +2276,24 @@ static int sev_gmem_post_populate(struct kvm *kvm, gfn_t gfn_start, kvm_pfn_t pf for (gfn = gfn_start, i = 0; gfn < gfn_start + npages; gfn++, i++) { struct sev_data_snp_launch_update fw_args = {0}; - bool assigned; + bool assigned = false; int level; - if (!kvm_mem_is_private(kvm, gfn)) { - pr_debug("%s: Failed to ensure GFN 0x%llx has private memory attribute set\n", - __func__, gfn); - ret = -EINVAL; - goto err; - } - ret = snp_lookup_rmpentry((u64)pfn + i, &assigned, &level); if (ret || assigned) { pr_debug("%s: Failed to ensure GFN 0x%llx RMP entry is initial shared state, ret: %d assigned: %d\n", __func__, gfn, ret, assigned); - ret = -EINVAL; + ret = ret ? -EINVAL : -EEXIST; goto err; } if (src) { void *vaddr = kmap_local_pfn(pfn + i); - ret = copy_from_user(vaddr, src + i * PAGE_SIZE, PAGE_SIZE); - if (ret) + if (copy_from_user(vaddr, src + i * PAGE_SIZE, PAGE_SIZE)) { + ret = -EFAULT; goto err; + } kunmap_local(vaddr); } @@ -2549,6 +2543,14 @@ static int snp_launch_finish(struct kvm *kvm, struct kvm_sev_cmd *argp) data->gctx_paddr = __psp_pa(sev->snp_context); ret = sev_issue_cmd(kvm, SEV_CMD_SNP_LAUNCH_FINISH, data, &argp->error); + /* + * Now that there will be no more SNP_LAUNCH_UPDATE ioctls, private pages + * can be given to the guest simply by marking the RMP entry as private. + * This can happen on first access and also with KVM_PRE_FAULT_MEMORY. + */ + if (!ret) + kvm->arch.pre_fault_allowed = true; + kfree(id_auth); e_free_id_block: diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c index c115d26844f7f6..d6f252555ab3ff 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -4949,6 +4949,7 @@ static int svm_vm_init(struct kvm *kvm) to_kvm_sev_info(kvm)->need_init = true; kvm->arch.has_private_mem = (type == KVM_X86_SNP_VM); + kvm->arch.pre_fault_allowed = !kvm->arch.has_private_mem; } if (!pause_filter_count || !pause_filter_thresh) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index af6c8cf6a37a35..70219e4069874a 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -427,8 +427,7 @@ static void kvm_user_return_msr_cpu_online(void) int kvm_set_user_return_msr(unsigned slot, u64 value, u64 mask) { - unsigned int cpu = smp_processor_id(); - struct kvm_user_return_msrs *msrs = per_cpu_ptr(user_return_msrs, cpu); + struct kvm_user_return_msrs *msrs = this_cpu_ptr(user_return_msrs); int err; value = (value & mask) | (msrs->values[slot].host & ~mask); @@ -450,8 +449,7 @@ EXPORT_SYMBOL_GPL(kvm_set_user_return_msr); static void drop_user_return_notifiers(void) { - unsigned int cpu = smp_processor_id(); - struct kvm_user_return_msrs *msrs = per_cpu_ptr(user_return_msrs, cpu); + struct kvm_user_return_msrs *msrs = this_cpu_ptr(user_return_msrs); if (msrs->registered) kvm_on_user_return(&msrs->urn); @@ -12646,6 +12644,9 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) kvm->arch.vm_type = type; kvm->arch.has_private_mem = (type == KVM_X86_SW_PROTECTED_VM); + /* Decided by the vendor code for other VM types. */ + kvm->arch.pre_fault_allowed = + type == KVM_X86_DEFAULT_VM || type == KVM_X86_SW_PROTECTED_VM; ret = kvm_page_track_init(kvm); if (ret) @@ -13641,19 +13642,14 @@ bool kvm_arch_no_poll(struct kvm_vcpu *vcpu) } EXPORT_SYMBOL_GPL(kvm_arch_no_poll); -#ifdef CONFIG_HAVE_KVM_GMEM_PREPARE -bool kvm_arch_gmem_prepare_needed(struct kvm *kvm) -{ - return kvm->arch.vm_type == KVM_X86_SNP_VM; -} - +#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_PREPARE int kvm_arch_gmem_prepare(struct kvm *kvm, gfn_t gfn, kvm_pfn_t pfn, int max_order) { return kvm_x86_call(gmem_prepare)(kvm, pfn, gfn, max_order); } #endif -#ifdef CONFIG_HAVE_KVM_GMEM_INVALIDATE +#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_INVALIDATE void kvm_arch_gmem_invalidate(kvm_pfn_t start, kvm_pfn_t end) { kvm_x86_call(gmem_invalidate)(start, end); diff --git a/arch/x86/lib/cmdline.c b/arch/x86/lib/cmdline.c index 384da1fdd5c6f7..c65cd55504549a 100644 --- a/arch/x86/lib/cmdline.c +++ b/arch/x86/lib/cmdline.c @@ -207,18 +207,29 @@ __cmdline_find_option(const char *cmdline, int max_cmdline_size, int cmdline_find_option_bool(const char *cmdline, const char *option) { - if (IS_ENABLED(CONFIG_CMDLINE_BOOL)) - WARN_ON_ONCE(!builtin_cmdline_added); + int ret; - return __cmdline_find_option_bool(cmdline, COMMAND_LINE_SIZE, option); + ret = __cmdline_find_option_bool(cmdline, COMMAND_LINE_SIZE, option); + if (ret > 0) + return ret; + + if (IS_ENABLED(CONFIG_CMDLINE_BOOL) && !builtin_cmdline_added) + return __cmdline_find_option_bool(builtin_cmdline, COMMAND_LINE_SIZE, option); + + return ret; } int cmdline_find_option(const char *cmdline, const char *option, char *buffer, int bufsize) { - if (IS_ENABLED(CONFIG_CMDLINE_BOOL)) - WARN_ON_ONCE(!builtin_cmdline_added); + int ret; + + ret = __cmdline_find_option(cmdline, COMMAND_LINE_SIZE, option, buffer, bufsize); + if (ret > 0) + return ret; + + if (IS_ENABLED(CONFIG_CMDLINE_BOOL) && !builtin_cmdline_added) + return __cmdline_find_option(builtin_cmdline, COMMAND_LINE_SIZE, option, buffer, bufsize); - return __cmdline_find_option(cmdline, COMMAND_LINE_SIZE, option, - buffer, bufsize); + return ret; } diff --git a/arch/x86/lib/getuser.S b/arch/x86/lib/getuser.S index a314622aa09346..d066aecf8aeb22 100644 --- a/arch/x86/lib/getuser.S +++ b/arch/x86/lib/getuser.S @@ -88,12 +88,14 @@ SYM_FUNC_END(__get_user_4) EXPORT_SYMBOL(__get_user_4) SYM_FUNC_START(__get_user_8) +#ifndef CONFIG_X86_64 + xor %ecx,%ecx +#endif check_range size=8 ASM_STAC #ifdef CONFIG_X86_64 UACCESS movq (%_ASM_AX),%rdx #else - xor %ecx,%ecx UACCESS movl (%_ASM_AX),%edx UACCESS movl 4(%_ASM_AX),%ecx #endif diff --git a/arch/x86/mm/pti.c b/arch/x86/mm/pti.c index 2e69abf4f852ab..851ec8f1363a8b 100644 --- a/arch/x86/mm/pti.c +++ b/arch/x86/mm/pti.c @@ -241,7 +241,7 @@ static pmd_t *pti_user_pagetable_walk_pmd(unsigned long address) * * Returns a pointer to a PTE on success, or NULL on failure. */ -static pte_t *pti_user_pagetable_walk_pte(unsigned long address) +static pte_t *pti_user_pagetable_walk_pte(unsigned long address, bool late_text) { gfp_t gfp = (GFP_KERNEL | __GFP_NOTRACK | __GFP_ZERO); pmd_t *pmd; @@ -251,10 +251,15 @@ static pte_t *pti_user_pagetable_walk_pte(unsigned long address) if (!pmd) return NULL; - /* We can't do anything sensible if we hit a large mapping. */ + /* Large PMD mapping found */ if (pmd_leaf(*pmd)) { - WARN_ON(1); - return NULL; + /* Clear the PMD if we hit a large mapping from the first round */ + if (late_text) { + set_pmd(pmd, __pmd(0)); + } else { + WARN_ON_ONCE(1); + return NULL; + } } if (pmd_none(*pmd)) { @@ -283,7 +288,7 @@ static void __init pti_setup_vsyscall(void) if (!pte || WARN_ON(level != PG_LEVEL_4K) || pte_none(*pte)) return; - target_pte = pti_user_pagetable_walk_pte(VSYSCALL_ADDR); + target_pte = pti_user_pagetable_walk_pte(VSYSCALL_ADDR, false); if (WARN_ON(!target_pte)) return; @@ -301,7 +306,7 @@ enum pti_clone_level { static void pti_clone_pgtable(unsigned long start, unsigned long end, - enum pti_clone_level level) + enum pti_clone_level level, bool late_text) { unsigned long addr; @@ -374,14 +379,14 @@ pti_clone_pgtable(unsigned long start, unsigned long end, */ *target_pmd = *pmd; - addr += PMD_SIZE; + addr = round_up(addr + 1, PMD_SIZE); } else if (level == PTI_CLONE_PTE) { /* Walk the page-table down to the pte level */ pte = pte_offset_kernel(pmd, addr); if (pte_none(*pte)) { - addr += PAGE_SIZE; + addr = round_up(addr + 1, PAGE_SIZE); continue; } @@ -390,7 +395,7 @@ pti_clone_pgtable(unsigned long start, unsigned long end, return; /* Allocate PTE in the user page-table */ - target_pte = pti_user_pagetable_walk_pte(addr); + target_pte = pti_user_pagetable_walk_pte(addr, late_text); if (WARN_ON(!target_pte)) return; @@ -401,7 +406,7 @@ pti_clone_pgtable(unsigned long start, unsigned long end, /* Clone the PTE */ *target_pte = *pte; - addr += PAGE_SIZE; + addr = round_up(addr + 1, PAGE_SIZE); } else { BUG(); @@ -452,7 +457,7 @@ static void __init pti_clone_user_shared(void) phys_addr_t pa = per_cpu_ptr_to_phys((void *)va); pte_t *target_pte; - target_pte = pti_user_pagetable_walk_pte(va); + target_pte = pti_user_pagetable_walk_pte(va, false); if (WARN_ON(!target_pte)) return; @@ -475,7 +480,7 @@ static void __init pti_clone_user_shared(void) start = CPU_ENTRY_AREA_BASE; end = start + (PAGE_SIZE * CPU_ENTRY_AREA_PAGES); - pti_clone_pgtable(start, end, PTI_CLONE_PMD); + pti_clone_pgtable(start, end, PTI_CLONE_PMD, false); } #endif /* CONFIG_X86_64 */ @@ -492,11 +497,11 @@ static void __init pti_setup_espfix64(void) /* * Clone the populated PMDs of the entry text and force it RO. */ -static void pti_clone_entry_text(void) +static void pti_clone_entry_text(bool late) { pti_clone_pgtable((unsigned long) __entry_text_start, (unsigned long) __entry_text_end, - PTI_CLONE_PMD); + PTI_LEVEL_KERNEL_IMAGE, late); } /* @@ -571,7 +576,7 @@ static void pti_clone_kernel_text(void) * pti_set_kernel_image_nonglobal() did to clear the * global bit. */ - pti_clone_pgtable(start, end_clone, PTI_LEVEL_KERNEL_IMAGE); + pti_clone_pgtable(start, end_clone, PTI_LEVEL_KERNEL_IMAGE, false); /* * pti_clone_pgtable() will set the global bit in any PMDs @@ -638,8 +643,15 @@ void __init pti_init(void) /* Undo all global bits from the init pagetables in head_64.S: */ pti_set_kernel_image_nonglobal(); + /* Replace some of the global bits just for shared entry text: */ - pti_clone_entry_text(); + /* + * This is very early in boot. Device and Late initcalls can do + * modprobe before free_initmem() and mark_readonly(). This + * pti_clone_entry_text() allows those user-mode-helpers to function, + * but notably the text is still RW. + */ + pti_clone_entry_text(false); pti_setup_espfix64(); pti_setup_vsyscall(); } @@ -656,10 +668,11 @@ void pti_finalize(void) if (!boot_cpu_has(X86_FEATURE_PTI)) return; /* - * We need to clone everything (again) that maps parts of the - * kernel image. + * This is after free_initmem() (all initcalls are done) and we've done + * mark_readonly(). Text is now NX which might've split some PMDs + * relative to the early clone. */ - pti_clone_entry_text(); + pti_clone_entry_text(true); pti_clone_kernel_text(); debug_checkwx_user(); diff --git a/block/blk-mq-tag.c b/block/blk-mq-tag.c index cc57e2dd9a0bb3..2cafcf11ee8bee 100644 --- a/block/blk-mq-tag.c +++ b/block/blk-mq-tag.c @@ -38,6 +38,7 @@ static void blk_mq_update_wake_batch(struct blk_mq_tags *tags, void __blk_mq_tag_busy(struct blk_mq_hw_ctx *hctx) { unsigned int users; + unsigned long flags; struct blk_mq_tags *tags = hctx->tags; /* @@ -56,11 +57,11 @@ void __blk_mq_tag_busy(struct blk_mq_hw_ctx *hctx) return; } - spin_lock_irq(&tags->lock); + spin_lock_irqsave(&tags->lock, flags); users = tags->active_queues + 1; WRITE_ONCE(tags->active_queues, users); blk_mq_update_wake_batch(tags, users); - spin_unlock_irq(&tags->lock); + spin_unlock_irqrestore(&tags->lock, flags); } /* diff --git a/block/blk-throttle.c b/block/blk-throttle.c index dc6140fa3de061..6943ec720f39ff 100644 --- a/block/blk-throttle.c +++ b/block/blk-throttle.c @@ -31,14 +31,6 @@ static struct workqueue_struct *kthrotld_workqueue; #define rb_entry_tg(node) rb_entry((node), struct throtl_grp, rb_node) -/* We measure latency for request size from <= 4k to >= 1M */ -#define LATENCY_BUCKET_SIZE 9 - -struct latency_bucket { - unsigned long total_latency; /* ns / 1024 */ - int samples; -}; - struct throtl_data { /* service tree for active throtl groups */ @@ -116,9 +108,6 @@ static unsigned int tg_iops_limit(struct throtl_grp *tg, int rw) return tg->iops[rw]; } -#define request_bucket_index(sectors) \ - clamp_t(int, order_base_2(sectors) - 3, 0, LATENCY_BUCKET_SIZE - 1) - /** * throtl_log - log debug message via blktrace * @sq: the service_queue being reported diff --git a/drivers/acpi/acpica/acevents.h b/drivers/acpi/acpica/acevents.h index 2133085deda77f..1c5218b79fc2ac 100644 --- a/drivers/acpi/acpica/acevents.h +++ b/drivers/acpi/acpica/acevents.h @@ -188,13 +188,9 @@ acpi_ev_detach_region(union acpi_operand_object *region_obj, u8 acpi_ns_is_locked); void -acpi_ev_execute_reg_methods(struct acpi_namespace_node *node, +acpi_ev_execute_reg_methods(struct acpi_namespace_node *node, u32 max_depth, acpi_adr_space_type space_id, u32 function); -void -acpi_ev_execute_orphan_reg_method(struct acpi_namespace_node *node, - acpi_adr_space_type space_id); - acpi_status acpi_ev_execute_reg_method(union acpi_operand_object *region_obj, u32 function); diff --git a/drivers/acpi/acpica/evregion.c b/drivers/acpi/acpica/evregion.c index dc6004daf624b6..cf53b9535f18e0 100644 --- a/drivers/acpi/acpica/evregion.c +++ b/drivers/acpi/acpica/evregion.c @@ -20,6 +20,10 @@ extern u8 acpi_gbl_default_address_spaces[]; /* Local prototypes */ +static void +acpi_ev_execute_orphan_reg_method(struct acpi_namespace_node *device_node, + acpi_adr_space_type space_id); + static acpi_status acpi_ev_reg_run(acpi_handle obj_handle, u32 level, void *context, void **return_value); @@ -61,6 +65,7 @@ acpi_status acpi_ev_initialize_op_regions(void) acpi_gbl_default_address_spaces [i])) { acpi_ev_execute_reg_methods(acpi_gbl_root_node, + ACPI_UINT32_MAX, acpi_gbl_default_address_spaces [i], ACPI_REG_CONNECT); } @@ -668,6 +673,7 @@ acpi_ev_execute_reg_method(union acpi_operand_object *region_obj, u32 function) * FUNCTION: acpi_ev_execute_reg_methods * * PARAMETERS: node - Namespace node for the device + * max_depth - Depth to which search for _REG * space_id - The address space ID * function - Passed to _REG: On (1) or Off (0) * @@ -679,7 +685,7 @@ acpi_ev_execute_reg_method(union acpi_operand_object *region_obj, u32 function) ******************************************************************************/ void -acpi_ev_execute_reg_methods(struct acpi_namespace_node *node, +acpi_ev_execute_reg_methods(struct acpi_namespace_node *node, u32 max_depth, acpi_adr_space_type space_id, u32 function) { struct acpi_reg_walk_info info; @@ -713,7 +719,7 @@ acpi_ev_execute_reg_methods(struct acpi_namespace_node *node, * regions and _REG methods. (i.e. handlers must be installed for all * regions of this Space ID before we can run any _REG methods) */ - (void)acpi_ns_walk_namespace(ACPI_TYPE_ANY, node, ACPI_UINT32_MAX, + (void)acpi_ns_walk_namespace(ACPI_TYPE_ANY, node, max_depth, ACPI_NS_WALK_UNLOCK, acpi_ev_reg_run, NULL, &info, NULL); @@ -814,7 +820,7 @@ acpi_ev_reg_run(acpi_handle obj_handle, * ******************************************************************************/ -void +static void acpi_ev_execute_orphan_reg_method(struct acpi_namespace_node *device_node, acpi_adr_space_type space_id) { diff --git a/drivers/acpi/acpica/evxfregn.c b/drivers/acpi/acpica/evxfregn.c index 624361a5f34d86..95f78383bbdba1 100644 --- a/drivers/acpi/acpica/evxfregn.c +++ b/drivers/acpi/acpica/evxfregn.c @@ -85,7 +85,8 @@ acpi_install_address_space_handler_internal(acpi_handle device, /* Run all _REG methods for this address space */ if (run_reg) { - acpi_ev_execute_reg_methods(node, space_id, ACPI_REG_CONNECT); + acpi_ev_execute_reg_methods(node, ACPI_UINT32_MAX, space_id, + ACPI_REG_CONNECT); } unlock_and_exit: @@ -263,6 +264,7 @@ ACPI_EXPORT_SYMBOL(acpi_remove_address_space_handler) * FUNCTION: acpi_execute_reg_methods * * PARAMETERS: device - Handle for the device + * max_depth - Depth to which search for _REG * space_id - The address space ID * * RETURN: Status @@ -271,7 +273,8 @@ ACPI_EXPORT_SYMBOL(acpi_remove_address_space_handler) * ******************************************************************************/ acpi_status -acpi_execute_reg_methods(acpi_handle device, acpi_adr_space_type space_id) +acpi_execute_reg_methods(acpi_handle device, u32 max_depth, + acpi_adr_space_type space_id) { struct acpi_namespace_node *node; acpi_status status; @@ -296,7 +299,8 @@ acpi_execute_reg_methods(acpi_handle device, acpi_adr_space_type space_id) /* Run all _REG methods for this address space */ - acpi_ev_execute_reg_methods(node, space_id, ACPI_REG_CONNECT); + acpi_ev_execute_reg_methods(node, max_depth, space_id, + ACPI_REG_CONNECT); } else { status = AE_BAD_PARAMETER; } @@ -306,57 +310,3 @@ acpi_execute_reg_methods(acpi_handle device, acpi_adr_space_type space_id) } ACPI_EXPORT_SYMBOL(acpi_execute_reg_methods) - -/******************************************************************************* - * - * FUNCTION: acpi_execute_orphan_reg_method - * - * PARAMETERS: device - Handle for the device - * space_id - The address space ID - * - * RETURN: Status - * - * DESCRIPTION: Execute an "orphan" _REG method that appears under an ACPI - * device. This is a _REG method that has no corresponding region - * within the device's scope. - * - ******************************************************************************/ -acpi_status -acpi_execute_orphan_reg_method(acpi_handle device, acpi_adr_space_type space_id) -{ - struct acpi_namespace_node *node; - acpi_status status; - - ACPI_FUNCTION_TRACE(acpi_execute_orphan_reg_method); - - /* Parameter validation */ - - if (!device) { - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Convert and validate the device handle */ - - node = acpi_ns_validate_handle(device); - if (node) { - - /* - * If an "orphan" _REG method is present in the device's scope - * for the given address space ID, run it. - */ - - acpi_ev_execute_orphan_reg_method(node, space_id); - } else { - status = AE_BAD_PARAMETER; - } - - (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); - return_ACPI_STATUS(status); -} - -ACPI_EXPORT_SYMBOL(acpi_execute_orphan_reg_method) diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 299ec653388ceb..38d2f6e6b12b4f 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -1487,12 +1487,13 @@ static bool install_gpio_irq_event_handler(struct acpi_ec *ec) static int ec_install_handlers(struct acpi_ec *ec, struct acpi_device *device, bool call_reg) { - acpi_handle scope_handle = ec == first_ec ? ACPI_ROOT_OBJECT : ec->handle; acpi_status status; acpi_ec_start(ec, false); if (!test_bit(EC_FLAGS_EC_HANDLER_INSTALLED, &ec->flags)) { + acpi_handle scope_handle = ec == first_ec ? ACPI_ROOT_OBJECT : ec->handle; + acpi_ec_enter_noirq(ec); status = acpi_install_address_space_handler_no_reg(scope_handle, ACPI_ADR_SPACE_EC, @@ -1506,10 +1507,7 @@ static int ec_install_handlers(struct acpi_ec *ec, struct acpi_device *device, } if (call_reg && !test_bit(EC_FLAGS_EC_REG_CALLED, &ec->flags)) { - acpi_execute_reg_methods(scope_handle, ACPI_ADR_SPACE_EC); - if (scope_handle != ec->handle) - acpi_execute_orphan_reg_method(ec->handle, ACPI_ADR_SPACE_EC); - + acpi_execute_reg_methods(ec->handle, ACPI_UINT32_MAX, ACPI_ADR_SPACE_EC); set_bit(EC_FLAGS_EC_REG_CALLED, &ec->flags); } @@ -1724,6 +1722,12 @@ static void acpi_ec_remove(struct acpi_device *device) } } +void acpi_ec_register_opregions(struct acpi_device *adev) +{ + if (first_ec && first_ec->handle != adev->handle) + acpi_execute_reg_methods(adev->handle, 1, ACPI_ADR_SPACE_EC); +} + static acpi_status ec_parse_io_ports(struct acpi_resource *resource, void *context) { diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 601b670356e50e..aadd4c218b320e 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -223,6 +223,7 @@ int acpi_ec_add_query_handler(struct acpi_ec *ec, u8 query_bit, acpi_handle handle, acpi_ec_query_func func, void *data); void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit); +void acpi_ec_register_opregions(struct acpi_device *adev); #ifdef CONFIG_PM_SLEEP void acpi_ec_flush_work(void); diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 59771412686ba3..22ae7829a9155d 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -2273,6 +2273,8 @@ static int acpi_bus_attach(struct acpi_device *device, void *first_pass) if (device->handler) goto ok; + acpi_ec_register_opregions(device); + if (!device->flags.initialized) { device->flags.power_manageable = device->power.states[ACPI_STATE_D0].flags.valid; diff --git a/drivers/android/binder.c b/drivers/android/binder.c index f26286e3713ec7..905290c98c3cdb 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -1044,13 +1044,13 @@ static struct binder_ref *binder_get_ref_olocked(struct binder_proc *proc, } /* Find the smallest unused descriptor the "slow way" */ -static u32 slow_desc_lookup_olocked(struct binder_proc *proc) +static u32 slow_desc_lookup_olocked(struct binder_proc *proc, u32 offset) { struct binder_ref *ref; struct rb_node *n; u32 desc; - desc = 1; + desc = offset; for (n = rb_first(&proc->refs_by_desc); n; n = rb_next(n)) { ref = rb_entry(n, struct binder_ref, rb_node_desc); if (ref->data.desc > desc) @@ -1071,21 +1071,18 @@ static int get_ref_desc_olocked(struct binder_proc *proc, u32 *desc) { struct dbitmap *dmap = &proc->dmap; + unsigned int nbits, offset; unsigned long *new, bit; - unsigned int nbits; /* 0 is reserved for the context manager */ - if (node == proc->context->binder_context_mgr_node) { - *desc = 0; - return 0; - } + offset = (node == proc->context->binder_context_mgr_node) ? 0 : 1; if (!dbitmap_enabled(dmap)) { - *desc = slow_desc_lookup_olocked(proc); + *desc = slow_desc_lookup_olocked(proc, offset); return 0; } - if (dbitmap_acquire_first_zero_bit(dmap, &bit) == 0) { + if (dbitmap_acquire_next_zero_bit(dmap, offset, &bit) == 0) { *desc = bit; return 0; } diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c index b00961944ab1d2..b3acbc4174fb1f 100644 --- a/drivers/android/binder_alloc.c +++ b/drivers/android/binder_alloc.c @@ -939,9 +939,9 @@ void binder_alloc_deferred_release(struct binder_alloc *alloc) __free_page(alloc->pages[i].page_ptr); page_count++; } - kvfree(alloc->pages); } spin_unlock(&alloc->lock); + kvfree(alloc->pages); if (alloc->mm) mmdrop(alloc->mm); diff --git a/drivers/android/dbitmap.h b/drivers/android/dbitmap.h index b8ac7b4764fd8d..956f1bd087d1c5 100644 --- a/drivers/android/dbitmap.h +++ b/drivers/android/dbitmap.h @@ -6,8 +6,7 @@ * * Used by the binder driver to optimize the allocation of the smallest * available descriptor ID. Each bit in the bitmap represents the state - * of an ID, with the exception of BIT(0) which is used exclusively to - * reference binder's context manager. + * of an ID. * * A dbitmap can grow or shrink as needed. This part has been designed * considering that users might need to briefly release their locks in @@ -58,11 +57,7 @@ static inline unsigned int dbitmap_shrink_nbits(struct dbitmap *dmap) if (bit < (dmap->nbits >> 2)) return dmap->nbits >> 1; - /* - * Note that find_last_bit() returns dmap->nbits when no bits - * are set. While this is technically not possible here since - * BIT(0) is always set, this check is left for extra safety. - */ + /* find_last_bit() returns dmap->nbits when no bits are set. */ if (bit == dmap->nbits) return NBITS_MIN; @@ -132,16 +127,17 @@ dbitmap_grow(struct dbitmap *dmap, unsigned long *new, unsigned int nbits) } /* - * Finds and sets the first zero bit in the bitmap. Upon success @bit + * Finds and sets the next zero bit in the bitmap. Upon success @bit * is populated with the index and 0 is returned. Otherwise, -ENOSPC * is returned to indicate that a dbitmap_grow() is needed. */ static inline int -dbitmap_acquire_first_zero_bit(struct dbitmap *dmap, unsigned long *bit) +dbitmap_acquire_next_zero_bit(struct dbitmap *dmap, unsigned long offset, + unsigned long *bit) { unsigned long n; - n = find_first_zero_bit(dmap->map, dmap->nbits); + n = find_next_zero_bit(dmap->map, dmap->nbits, offset); if (n == dmap->nbits) return -ENOSPC; @@ -154,9 +150,7 @@ dbitmap_acquire_first_zero_bit(struct dbitmap *dmap, unsigned long *bit) static inline void dbitmap_clear_bit(struct dbitmap *dmap, unsigned long bit) { - /* BIT(0) should always set for the context manager */ - if (bit) - clear_bit(bit, dmap->map); + clear_bit(bit, dmap->map); } static inline int dbitmap_init(struct dbitmap *dmap) @@ -168,8 +162,6 @@ static inline int dbitmap_init(struct dbitmap *dmap) } dmap->nbits = NBITS_MIN; - /* BIT(0) is reserved for the context manager */ - set_bit(0, dmap->map); return 0; } diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index d6f5e25e1ed894..473e00a58a8b0c 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -951,8 +951,19 @@ static void ata_gen_passthru_sense(struct ata_queued_cmd *qc) &sense_key, &asc, &ascq); ata_scsi_set_sense(qc->dev, cmd, sense_key, asc, ascq); } else { - /* ATA PASS-THROUGH INFORMATION AVAILABLE */ - ata_scsi_set_sense(qc->dev, cmd, RECOVERED_ERROR, 0, 0x1D); + /* + * ATA PASS-THROUGH INFORMATION AVAILABLE + * + * Note: we are supposed to call ata_scsi_set_sense(), which + * respects the D_SENSE bit, instead of unconditionally + * generating the sense data in descriptor format. However, + * because hdparm, hddtemp, and udisks incorrectly assume sense + * data in descriptor format, without even looking at the + * RESPONSE CODE field in the returned sense data (to see which + * format the returned sense data is in), we are stuck with + * being bug compatible with older kernels. + */ + scsi_build_sense(cmd, 1, RECOVERED_ERROR, 0, 0x1D); } } diff --git a/drivers/atm/idt77252.c b/drivers/atm/idt77252.c index e7f713cd70d3fd..a876024d8a05f9 100644 --- a/drivers/atm/idt77252.c +++ b/drivers/atm/idt77252.c @@ -1118,8 +1118,8 @@ dequeue_rx(struct idt77252_dev *card, struct rsq_entry *rsqe) rpp->len += skb->len; if (stat & SAR_RSQE_EPDU) { + unsigned int len, truesize; unsigned char *l1l2; - unsigned int len; l1l2 = (unsigned char *) ((unsigned long) skb->data + skb->len - 6); @@ -1189,14 +1189,15 @@ dequeue_rx(struct idt77252_dev *card, struct rsq_entry *rsqe) ATM_SKB(skb)->vcc = vcc; __net_timestamp(skb); + truesize = skb->truesize; vcc->push(vcc, skb); atomic_inc(&vcc->stats->rx); - if (skb->truesize > SAR_FB_SIZE_3) + if (truesize > SAR_FB_SIZE_3) add_rx_skb(card, 3, SAR_FB_SIZE_3, 1); - else if (skb->truesize > SAR_FB_SIZE_2) + else if (truesize > SAR_FB_SIZE_2) add_rx_skb(card, 2, SAR_FB_SIZE_2, 1); - else if (skb->truesize > SAR_FB_SIZE_1) + else if (truesize > SAR_FB_SIZE_1) add_rx_skb(card, 1, SAR_FB_SIZE_1, 1); else add_rx_skb(card, 0, SAR_FB_SIZE_0, 1); diff --git a/drivers/base/core.c b/drivers/base/core.c index 730cae66607c02..8c0733d3aad8e9 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -2640,6 +2641,7 @@ static const char *dev_uevent_name(const struct kobject *kobj) static int dev_uevent(const struct kobject *kobj, struct kobj_uevent_env *env) { const struct device *dev = kobj_to_dev(kobj); + struct device_driver *driver; int retval = 0; /* add device node properties if present */ @@ -2668,8 +2670,12 @@ static int dev_uevent(const struct kobject *kobj, struct kobj_uevent_env *env) if (dev->type && dev->type->name) add_uevent_var(env, "DEVTYPE=%s", dev->type->name); - if (dev->driver) - add_uevent_var(env, "DRIVER=%s", dev->driver->name); + /* Synchronize with module_remove_driver() */ + rcu_read_lock(); + driver = READ_ONCE(dev->driver); + if (driver) + add_uevent_var(env, "DRIVER=%s", driver->name); + rcu_read_unlock(); /* Add common DT information about the device */ of_device_uevent(dev, env); @@ -2739,11 +2745,8 @@ static ssize_t uevent_show(struct device *dev, struct device_attribute *attr, if (!env) return -ENOMEM; - /* Synchronize with really_probe() */ - device_lock(dev); /* let the kset specific function add its keys */ retval = kset->uevent_ops->uevent(&dev->kobj, env); - device_unlock(dev); if (retval) goto out; diff --git a/drivers/base/module.c b/drivers/base/module.c index 7af224e6914a10..f742ad2a21da02 100644 --- a/drivers/base/module.c +++ b/drivers/base/module.c @@ -7,6 +7,7 @@ #include #include #include +#include #include "base.h" static char *make_driver_name(const struct device_driver *drv) @@ -97,6 +98,9 @@ void module_remove_driver(const struct device_driver *drv) if (!drv) return; + /* Synchronize with dev_uevent() */ + synchronize_rcu(); + sysfs_remove_link(&drv->p->kobj, "module"); if (drv->owner) diff --git a/drivers/base/regmap/regmap-irq.c b/drivers/base/regmap/regmap-irq.c index d3ec1345b5b53a..a750e48a26b87c 100644 --- a/drivers/base/regmap/regmap-irq.c +++ b/drivers/base/regmap/regmap-irq.c @@ -608,6 +608,30 @@ int regmap_irq_set_type_config_simple(unsigned int **buf, unsigned int type, } EXPORT_SYMBOL_GPL(regmap_irq_set_type_config_simple); +static int regmap_irq_create_domain(struct fwnode_handle *fwnode, int irq_base, + const struct regmap_irq_chip *chip, + struct regmap_irq_chip_data *d) +{ + struct irq_domain_info info = { + .fwnode = fwnode, + .size = chip->num_irqs, + .hwirq_max = chip->num_irqs, + .virq_base = irq_base, + .ops = ®map_domain_ops, + .host_data = d, + .name_suffix = chip->domain_suffix, + }; + + d->domain = irq_domain_instantiate(&info); + if (IS_ERR(d->domain)) { + dev_err(d->map->dev, "Failed to create IRQ domain\n"); + return PTR_ERR(d->domain); + } + + return 0; +} + + /** * regmap_add_irq_chip_fwnode() - Use standard regmap IRQ controller handling * @@ -856,18 +880,9 @@ int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode, } } - if (irq_base) - d->domain = irq_domain_create_legacy(fwnode, chip->num_irqs, - irq_base, 0, - ®map_domain_ops, d); - else - d->domain = irq_domain_create_linear(fwnode, chip->num_irqs, - ®map_domain_ops, d); - if (!d->domain) { - dev_err(map->dev, "Failed to create IRQ domain\n"); - ret = -ENOMEM; + ret = regmap_irq_create_domain(fwnode, irq_base, chip, d); + if (ret) goto err_alloc; - } ret = request_threaded_irq(irq, NULL, regmap_irq_thread, irq_flags | IRQF_ONESHOT, diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig index 90a94a111e67e1..769fa288179d39 100644 --- a/drivers/bluetooth/Kconfig +++ b/drivers/bluetooth/Kconfig @@ -413,6 +413,7 @@ config BT_ATH3K config BT_MTKSDIO tristate "MediaTek HCI SDIO driver" depends on MMC + depends on USB || !BT_HCIBTUSB_MTK select BT_MTK help MediaTek Bluetooth HCI SDIO driver. @@ -425,6 +426,7 @@ config BT_MTKSDIO config BT_MTKUART tristate "MediaTek HCI UART driver" depends on SERIAL_DEV_BUS + depends on USB || !BT_HCIBTUSB_MTK select BT_MTK help MediaTek Bluetooth HCI UART driver. diff --git a/drivers/bluetooth/btintel.c b/drivers/bluetooth/btintel.c index e7a612504ab1d3..2ebc970e6573fb 100644 --- a/drivers/bluetooth/btintel.c +++ b/drivers/bluetooth/btintel.c @@ -3085,6 +3085,9 @@ static int btintel_setup_combined(struct hci_dev *hdev) btintel_set_dsm_reset_method(hdev, &ver_tlv); err = btintel_bootloader_setup_tlv(hdev, &ver_tlv); + if (err) + goto exit_error; + btintel_register_devcoredump_support(hdev); btintel_print_fseq_info(hdev); break; diff --git a/drivers/bluetooth/btmtk.c b/drivers/bluetooth/btmtk.c index b7c348687a773f..2b7c80043aa2eb 100644 --- a/drivers/bluetooth/btmtk.c +++ b/drivers/bluetooth/btmtk.c @@ -437,6 +437,7 @@ int btmtk_process_coredump(struct hci_dev *hdev, struct sk_buff *skb) } EXPORT_SYMBOL_GPL(btmtk_process_coredump); +#if IS_ENABLED(CONFIG_BT_HCIBTUSB_MTK) static void btmtk_usb_wmt_recv(struct urb *urb) { struct hci_dev *hdev = urb->context; @@ -1262,7 +1263,8 @@ int btmtk_usb_suspend(struct hci_dev *hdev) struct btmtk_data *btmtk_data = hci_get_priv(hdev); /* Stop urb anchor for iso data transmission */ - usb_kill_anchored_urbs(&btmtk_data->isopkt_anchor); + if (test_bit(BTMTK_ISOPKT_RUNNING, &btmtk_data->flags)) + usb_kill_anchored_urbs(&btmtk_data->isopkt_anchor); return 0; } @@ -1487,6 +1489,7 @@ int btmtk_usb_shutdown(struct hci_dev *hdev) return 0; } EXPORT_SYMBOL_GPL(btmtk_usb_shutdown); +#endif MODULE_AUTHOR("Sean Wang "); MODULE_AUTHOR("Mark Chen "); diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index ca64666769027a..45adc1560d949a 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c @@ -2160,7 +2160,7 @@ static void qca_power_shutdown(struct hci_uart *hu) qcadev = serdev_device_get_drvdata(hu->serdev); power = qcadev->bt_power; - if (power->pwrseq) { + if (power && power->pwrseq) { pwrseq_power_off(power->pwrseq); set_bit(QCA_BT_OFF, &qca->flags); return; @@ -2187,10 +2187,6 @@ static void qca_power_shutdown(struct hci_uart *hu) } break; - case QCA_QCA6390: - pwrseq_power_off(qcadev->bt_power->pwrseq); - break; - default: gpiod_set_value_cansleep(qcadev->bt_en, 0); } @@ -2416,11 +2412,14 @@ static int qca_serdev_probe(struct serdev_device *serdev) break; case QCA_QCA6390: - qcadev->bt_power->pwrseq = devm_pwrseq_get(&serdev->dev, - "bluetooth"); - if (IS_ERR(qcadev->bt_power->pwrseq)) - return PTR_ERR(qcadev->bt_power->pwrseq); - break; + if (dev_of_node(&serdev->dev)) { + qcadev->bt_power->pwrseq = devm_pwrseq_get(&serdev->dev, + "bluetooth"); + if (IS_ERR(qcadev->bt_power->pwrseq)) + return PTR_ERR(qcadev->bt_power->pwrseq); + break; + } + fallthrough; default: qcadev->bt_en = devm_gpiod_get_optional(&serdev->dev, "enable", diff --git a/drivers/cache/Kconfig b/drivers/cache/Kconfig index 94abd8f632a7b3..db51386c663a66 100644 --- a/drivers/cache/Kconfig +++ b/drivers/cache/Kconfig @@ -18,6 +18,7 @@ config STARFIVE_STARLINK_CACHE bool "StarFive StarLink Cache controller" depends on RISCV depends on ARCH_STARFIVE + depends on 64BIT select RISCV_DMA_NONCOHERENT select RISCV_NONSTANDARD_CACHE_OPS help diff --git a/drivers/char/ds1620.c b/drivers/char/ds1620.c index cf89a9631107db..a4f4291b4492cb 100644 --- a/drivers/char/ds1620.c +++ b/drivers/char/ds1620.c @@ -421,4 +421,5 @@ static void __exit ds1620_exit(void) module_init(ds1620_init); module_exit(ds1620_exit); +MODULE_DESCRIPTION("Dallas Semiconductor DS1620 thermometer driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/char/nwbutton.c b/drivers/char/nwbutton.c index ea378c0ed54986..92cee5717237b7 100644 --- a/drivers/char/nwbutton.c +++ b/drivers/char/nwbutton.c @@ -241,6 +241,7 @@ static void __exit nwbutton_exit (void) MODULE_AUTHOR("Alex Holden"); +MODULE_DESCRIPTION("NetWinder button driver"); MODULE_LICENSE("GPL"); module_init(nwbutton_init); diff --git a/drivers/char/nwflash.c b/drivers/char/nwflash.c index 0973c2c2b01a48..9f52f0306ef71f 100644 --- a/drivers/char/nwflash.c +++ b/drivers/char/nwflash.c @@ -618,6 +618,7 @@ static void __exit nwflash_exit(void) iounmap((void *)FLASH_BASE); } +MODULE_DESCRIPTION("NetWinder flash memory driver"); MODULE_LICENSE("GPL"); module_param(flashdebug, bool, 0644); diff --git a/drivers/char/xillybus/xillyusb.c b/drivers/char/xillybus/xillyusb.c index 5a5afa14ca8cb8..45771b1a3716a2 100644 --- a/drivers/char/xillybus/xillyusb.c +++ b/drivers/char/xillybus/xillyusb.c @@ -50,6 +50,7 @@ MODULE_LICENSE("GPL v2"); static const char xillyname[] = "xillyusb"; static unsigned int fifo_buf_order; +static struct workqueue_struct *wakeup_wq; #define USB_VENDOR_ID_XILINX 0x03fd #define USB_VENDOR_ID_ALTERA 0x09fb @@ -569,10 +570,6 @@ static void cleanup_dev(struct kref *kref) * errors if executed. The mechanism relies on that xdev->error is assigned * a non-zero value by report_io_error() prior to queueing wakeup_all(), * which prevents bulk_in_work() from calling process_bulk_in(). - * - * The fact that wakeup_all() and bulk_in_work() are queued on the same - * workqueue makes their concurrent execution very unlikely, however the - * kernel's API doesn't seem to ensure this strictly. */ static void wakeup_all(struct work_struct *work) @@ -627,7 +624,7 @@ static void report_io_error(struct xillyusb_dev *xdev, if (do_once) { kref_get(&xdev->kref); /* xdev is used by work item */ - queue_work(xdev->workq, &xdev->wakeup_workitem); + queue_work(wakeup_wq, &xdev->wakeup_workitem); } } @@ -1906,6 +1903,13 @@ static const struct file_operations xillyusb_fops = { static int xillyusb_setup_base_eps(struct xillyusb_dev *xdev) { + struct usb_device *udev = xdev->udev; + + /* Verify that device has the two fundamental bulk in/out endpoints */ + if (usb_pipe_type_check(udev, usb_sndbulkpipe(udev, MSG_EP_NUM)) || + usb_pipe_type_check(udev, usb_rcvbulkpipe(udev, IN_EP_NUM))) + return -ENODEV; + xdev->msg_ep = endpoint_alloc(xdev, MSG_EP_NUM | USB_DIR_OUT, bulk_out_work, 1, 2); if (!xdev->msg_ep) @@ -1935,14 +1939,15 @@ static int setup_channels(struct xillyusb_dev *xdev, __le16 *chandesc, int num_channels) { - struct xillyusb_channel *chan; + struct usb_device *udev = xdev->udev; + struct xillyusb_channel *chan, *new_channels; int i; chan = kcalloc(num_channels, sizeof(*chan), GFP_KERNEL); if (!chan) return -ENOMEM; - xdev->channels = chan; + new_channels = chan; for (i = 0; i < num_channels; i++, chan++) { unsigned int in_desc = le16_to_cpu(*chandesc++); @@ -1971,6 +1976,15 @@ static int setup_channels(struct xillyusb_dev *xdev, */ if ((out_desc & 0x80) && i < 14) { /* Entry is valid */ + if (usb_pipe_type_check(udev, + usb_sndbulkpipe(udev, i + 2))) { + dev_err(xdev->dev, + "Missing BULK OUT endpoint %d\n", + i + 2); + kfree(new_channels); + return -ENODEV; + } + chan->writable = 1; chan->out_synchronous = !!(out_desc & 0x40); chan->out_seekable = !!(out_desc & 0x20); @@ -1980,6 +1994,7 @@ static int setup_channels(struct xillyusb_dev *xdev, } } + xdev->channels = new_channels; return 0; } @@ -2096,9 +2111,11 @@ static int xillyusb_discovery(struct usb_interface *interface) * just after responding with the IDT, there is no reason for any * work item to be running now. To be sure that xdev->channels * is updated on anything that might run in parallel, flush the - * workqueue, which rarely does anything. + * device's workqueue and the wakeup work item. This rarely + * does anything. */ flush_workqueue(xdev->workq); + flush_work(&xdev->wakeup_workitem); xdev->num_channels = num_channels; @@ -2258,6 +2275,10 @@ static int __init xillyusb_init(void) { int rc = 0; + wakeup_wq = alloc_workqueue(xillyname, 0, 0); + if (!wakeup_wq) + return -ENOMEM; + if (LOG2_INITIAL_FIFO_BUF_SIZE > PAGE_SHIFT) fifo_buf_order = LOG2_INITIAL_FIFO_BUF_SIZE - PAGE_SHIFT; else @@ -2265,12 +2286,17 @@ static int __init xillyusb_init(void) rc = usb_register(&xillyusb_driver); + if (rc) + destroy_workqueue(wakeup_wq); + return rc; } static void __exit xillyusb_exit(void) { usb_deregister(&xillyusb_driver); + + destroy_workqueue(wakeup_wq); } module_init(xillyusb_init); diff --git a/drivers/clk/thead/clk-th1520-ap.c b/drivers/clk/thead/clk-th1520-ap.c index cbc176b27c091e..17e32ae08720cb 100644 --- a/drivers/clk/thead/clk-th1520-ap.c +++ b/drivers/clk/thead/clk-th1520-ap.c @@ -738,7 +738,7 @@ static struct ccu_div vp_axi_clk = { .hw.init = CLK_HW_INIT_PARENTS_HW("vp-axi", video_pll_clk_parent, &ccu_div_ops, - 0), + CLK_IGNORE_UNUSED), }, }; diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index 392a8000b238b5..c0278d023cfce5 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c @@ -3405,6 +3405,7 @@ static const struct x86_cpu_id intel_epp_default[] = { */ X86_MATCH_VFM(INTEL_ALDERLAKE_L, HWP_SET_DEF_BALANCE_PERF_EPP(102)), X86_MATCH_VFM(INTEL_SAPPHIRERAPIDS_X, HWP_SET_DEF_BALANCE_PERF_EPP(32)), + X86_MATCH_VFM(INTEL_EMERALDRAPIDS_X, HWP_SET_DEF_BALANCE_PERF_EPP(32)), X86_MATCH_VFM(INTEL_METEORLAKE_L, HWP_SET_EPP_VALUES(HWP_EPP_POWERSAVE, 179, 64, 16)), X86_MATCH_VFM(INTEL_ARROWLAKE, HWP_SET_EPP_VALUES(HWP_EPP_POWERSAVE, diff --git a/drivers/edac/skx_common.h b/drivers/edac/skx_common.h index 11faf1db4fa482..473421ba7a18a5 100644 --- a/drivers/edac/skx_common.h +++ b/drivers/edac/skx_common.h @@ -45,7 +45,6 @@ #define I10NM_NUM_CHANNELS MAX(I10NM_NUM_DDR_CHANNELS, I10NM_NUM_HBM_CHANNELS) #define I10NM_NUM_DIMMS MAX(I10NM_NUM_DDR_DIMMS, I10NM_NUM_HBM_DIMMS) -#define MAX(a, b) ((a) > (b) ? (a) : (b)) #define NUM_IMC MAX(SKX_NUM_IMC, I10NM_NUM_IMC) #define NUM_CHANNELS MAX(SKX_NUM_CHANNELS, I10NM_NUM_CHANNELS) #define NUM_DIMMS MAX(SKX_NUM_DIMMS, I10NM_NUM_DIMMS) diff --git a/drivers/firmware/efi/libstub/Makefile b/drivers/firmware/efi/libstub/Makefile index f23ba62ce127b4..ed4e8ddbe76a50 100644 --- a/drivers/firmware/efi/libstub/Makefile +++ b/drivers/firmware/efi/libstub/Makefile @@ -27,7 +27,8 @@ cflags-$(CONFIG_ARM64) += -fpie $(DISABLE_STACKLEAK_PLUGIN) \ cflags-$(CONFIG_ARM) += -DEFI_HAVE_STRLEN -DEFI_HAVE_STRNLEN \ -DEFI_HAVE_MEMCHR -DEFI_HAVE_STRRCHR \ -DEFI_HAVE_STRCMP -fno-builtin -fpic \ - $(call cc-option,-mno-single-pic-base) + $(call cc-option,-mno-single-pic-base) \ + $(DISABLE_STACKLEAK_PLUGIN) cflags-$(CONFIG_RISCV) += -fpic -DNO_ALTERNATIVE -mno-relax \ $(DISABLE_STACKLEAK_PLUGIN) cflags-$(CONFIG_LOONGARCH) += -fpie @@ -57,6 +58,10 @@ KBUILD_CFLAGS := $(filter-out $(CC_FLAGS_CFI), $(KBUILD_CFLAGS)) # disable LTO KBUILD_CFLAGS := $(filter-out $(CC_FLAGS_LTO), $(KBUILD_CFLAGS)) +# The .data section would be renamed to .data.efistub, therefore, remove +# `-fdata-sections` flag from KBUILD_CFLAGS_KERNEL +KBUILD_CFLAGS_KERNEL := $(filter-out -fdata-sections, $(KBUILD_CFLAGS_KERNEL)) + lib-y := efi-stub-helper.o gop.o secureboot.o tpm.o \ file.o mem.o random.o randomalloc.o pci.o \ skip_spaces.o lib-cmdline.o lib-ctype.o \ diff --git a/drivers/fsi/fsi-core.c b/drivers/fsi/fsi-core.c index 46ac5a8beab72a..e2e1e9df611543 100644 --- a/drivers/fsi/fsi-core.c +++ b/drivers/fsi/fsi-core.c @@ -1444,5 +1444,6 @@ static void fsi_exit(void) } module_exit(fsi_exit); module_param(discard_errors, int, 0664); +MODULE_DESCRIPTION("FSI core driver"); MODULE_LICENSE("GPL"); MODULE_PARM_DESC(discard_errors, "Don't invoke error handling on bus accesses"); diff --git a/drivers/fsi/fsi-master-aspeed.c b/drivers/fsi/fsi-master-aspeed.c index b0b624c3717bac..6f5e1bdf7e40e4 100644 --- a/drivers/fsi/fsi-master-aspeed.c +++ b/drivers/fsi/fsi-master-aspeed.c @@ -670,4 +670,5 @@ static struct platform_driver fsi_master_aspeed_driver = { }; module_platform_driver(fsi_master_aspeed_driver); +MODULE_DESCRIPTION("FSI master driver for AST2600"); MODULE_LICENSE("GPL"); diff --git a/drivers/fsi/fsi-master-ast-cf.c b/drivers/fsi/fsi-master-ast-cf.c index f8c776ce1b5609..a4c37ff8edd69d 100644 --- a/drivers/fsi/fsi-master-ast-cf.c +++ b/drivers/fsi/fsi-master-ast-cf.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0+ // Copyright 2018 IBM Corp /* - * A FSI master controller, using a simple GPIO bit-banging interface + * A FSI master based on Aspeed ColdFire coprocessor */ #include @@ -1438,5 +1438,6 @@ static struct platform_driver fsi_master_acf = { }; module_platform_driver(fsi_master_acf); +MODULE_DESCRIPTION("A FSI master based on Aspeed ColdFire coprocessor"); MODULE_LICENSE("GPL"); MODULE_FIRMWARE(FW_FILE_NAME); diff --git a/drivers/fsi/fsi-master-gpio.c b/drivers/fsi/fsi-master-gpio.c index 10fc344b6b221e..f761344f487329 100644 --- a/drivers/fsi/fsi-master-gpio.c +++ b/drivers/fsi/fsi-master-gpio.c @@ -892,4 +892,5 @@ static struct platform_driver fsi_master_gpio_driver = { }; module_platform_driver(fsi_master_gpio_driver); +MODULE_DESCRIPTION("A FSI master controller, using a simple GPIO bit-banging interface"); MODULE_LICENSE("GPL"); diff --git a/drivers/fsi/fsi-master-hub.c b/drivers/fsi/fsi-master-hub.c index 6d8b6e8854e563..6568fed7db3cf5 100644 --- a/drivers/fsi/fsi-master-hub.c +++ b/drivers/fsi/fsi-master-hub.c @@ -295,4 +295,5 @@ static struct fsi_driver hub_master_driver = { }; module_fsi_driver(hub_master_driver); +MODULE_DESCRIPTION("FSI hub master driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/fsi/fsi-scom.c b/drivers/fsi/fsi-scom.c index 61dbda9dbe2b0d..411ddc018cd86a 100644 --- a/drivers/fsi/fsi-scom.c +++ b/drivers/fsi/fsi-scom.c @@ -625,4 +625,5 @@ static void scom_exit(void) module_init(scom_init); module_exit(scom_exit); +MODULE_DESCRIPTION("SCOM FSI Client device driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/gpio/gpio-mlxbf3.c b/drivers/gpio/gpio-mlxbf3.c index d5906d419b0ab9..10ea71273c8915 100644 --- a/drivers/gpio/gpio-mlxbf3.c +++ b/drivers/gpio/gpio-mlxbf3.c @@ -39,6 +39,8 @@ #define MLXBF_GPIO_CAUSE_OR_EVTEN0 0x14 #define MLXBF_GPIO_CAUSE_OR_CLRCAUSE 0x18 +#define MLXBF_GPIO_CLR_ALL_INTS GENMASK(31, 0) + struct mlxbf3_gpio_context { struct gpio_chip gc; @@ -82,6 +84,8 @@ static void mlxbf3_gpio_irq_disable(struct irq_data *irqd) val = readl(gs->gpio_cause_io + MLXBF_GPIO_CAUSE_OR_EVTEN0); val &= ~BIT(offset); writel(val, gs->gpio_cause_io + MLXBF_GPIO_CAUSE_OR_EVTEN0); + + writel(BIT(offset), gs->gpio_cause_io + MLXBF_GPIO_CAUSE_OR_CLRCAUSE); raw_spin_unlock_irqrestore(&gs->gc.bgpio_lock, flags); gpiochip_disable_irq(gc, offset); @@ -253,6 +257,15 @@ static int mlxbf3_gpio_probe(struct platform_device *pdev) return 0; } +static void mlxbf3_gpio_shutdown(struct platform_device *pdev) +{ + struct mlxbf3_gpio_context *gs = platform_get_drvdata(pdev); + + /* Disable and clear all interrupts */ + writel(0, gs->gpio_cause_io + MLXBF_GPIO_CAUSE_OR_EVTEN0); + writel(MLXBF_GPIO_CLR_ALL_INTS, gs->gpio_cause_io + MLXBF_GPIO_CAUSE_OR_CLRCAUSE); +} + static const struct acpi_device_id mlxbf3_gpio_acpi_match[] = { { "MLNXBF33", 0 }, {} @@ -265,6 +278,7 @@ static struct platform_driver mlxbf3_gpio_driver = { .acpi_match_table = mlxbf3_gpio_acpi_match, }, .probe = mlxbf3_gpio_probe, + .shutdown = mlxbf3_gpio_shutdown, }; module_platform_driver(mlxbf3_gpio_driver); diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index fd0749c0c630f6..6b2c6b91f96250 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -268,6 +268,7 @@ config DRM_EXEC config DRM_GPUVM tristate depends on DRM + select DRM_EXEC help GPU-VM representation providing helpers to manage a GPUs virtual address space diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index 916b6b8cf7d9a6..6dfdff58bffd1f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -1057,6 +1057,9 @@ static int amdgpu_cs_patch_ibs(struct amdgpu_cs_parser *p, r = amdgpu_ring_parse_cs(ring, p, job, ib); if (r) return r; + + if (ib->sa_bo) + ib->gpu_addr = amdgpu_sa_bo_gpu_addr(ib->sa_bo); } else { ib->ptr = (uint32_t *)kptr; r = amdgpu_ring_patch_cs_in_place(ring, p, job, ib); @@ -1778,7 +1781,7 @@ int amdgpu_cs_find_mapping(struct amdgpu_cs_parser *parser, struct ttm_operation_ctx ctx = { false, false }; struct amdgpu_vm *vm = &fpriv->vm; struct amdgpu_bo_va_mapping *mapping; - int r; + int i, r; addr /= AMDGPU_GPU_PAGE_SIZE; @@ -1793,13 +1796,13 @@ int amdgpu_cs_find_mapping(struct amdgpu_cs_parser *parser, if (dma_resv_locking_ctx((*bo)->tbo.base.resv) != &parser->exec.ticket) return -EINVAL; - if (!((*bo)->flags & AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS)) { - (*bo)->flags |= AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS; - amdgpu_bo_placement_from_domain(*bo, (*bo)->allowed_domains); - r = ttm_bo_validate(&(*bo)->tbo, &(*bo)->placement, &ctx); - if (r) - return r; - } + (*bo)->flags |= AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS; + amdgpu_bo_placement_from_domain(*bo, (*bo)->allowed_domains); + for (i = 0; i < (*bo)->placement.num_placement; i++) + (*bo)->placements[i].flags |= TTM_PL_FLAG_CONTIGUOUS; + r = ttm_bo_validate(&(*bo)->tbo, &(*bo)->placement, &ctx); + if (r) + return r; return amdgpu_ttm_alloc_gart(&(*bo)->tbo); } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c index 5cb33ac99f7089..c43d1b6e5d66b2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c @@ -685,16 +685,24 @@ int amdgpu_ctx_ioctl(struct drm_device *dev, void *data, switch (args->in.op) { case AMDGPU_CTX_OP_ALLOC_CTX: + if (args->in.flags) + return -EINVAL; r = amdgpu_ctx_alloc(adev, fpriv, filp, priority, &id); args->out.alloc.ctx_id = id; break; case AMDGPU_CTX_OP_FREE_CTX: + if (args->in.flags) + return -EINVAL; r = amdgpu_ctx_free(fpriv, id); break; case AMDGPU_CTX_OP_QUERY_STATE: + if (args->in.flags) + return -EINVAL; r = amdgpu_ctx_query(adev, fpriv, id, &args->out); break; case AMDGPU_CTX_OP_QUERY_STATE2: + if (args->in.flags) + return -EINVAL; r = amdgpu_ctx_query2(adev, fpriv, id, &args->out); break; case AMDGPU_CTX_OP_GET_STABLE_PSTATE: diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c index 82452606ae6ca8..c770cb201e64bc 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c @@ -509,6 +509,16 @@ int amdgpu_gfx_disable_kcq(struct amdgpu_device *adev, int xcc_id) int i, r = 0; int j; + if (adev->enable_mes) { + for (i = 0; i < adev->gfx.num_compute_rings; i++) { + j = i + xcc_id * adev->gfx.num_compute_rings; + amdgpu_mes_unmap_legacy_queue(adev, + &adev->gfx.compute_ring[j], + RESET_QUEUES, 0, 0); + } + return 0; + } + if (!kiq->pmf || !kiq->pmf->kiq_unmap_queues) return -EINVAL; @@ -551,6 +561,18 @@ int amdgpu_gfx_disable_kgq(struct amdgpu_device *adev, int xcc_id) int i, r = 0; int j; + if (adev->enable_mes) { + if (amdgpu_gfx_is_master_xcc(adev, xcc_id)) { + for (i = 0; i < adev->gfx.num_gfx_rings; i++) { + j = i + xcc_id * adev->gfx.num_gfx_rings; + amdgpu_mes_unmap_legacy_queue(adev, + &adev->gfx.gfx_ring[j], + PREEMPT_QUEUES, 0, 0); + } + } + return 0; + } + if (!kiq->pmf || !kiq->pmf->kiq_unmap_queues) return -EINVAL; @@ -995,7 +1017,7 @@ uint32_t amdgpu_kiq_rreg(struct amdgpu_device *adev, uint32_t reg, uint32_t xcc_ if (amdgpu_device_skip_hw_access(adev)) return 0; - if (adev->mes.ring.sched.ready) + if (adev->mes.ring[0].sched.ready) return amdgpu_mes_rreg(adev, reg); BUG_ON(!ring->funcs->emit_rreg); @@ -1065,7 +1087,7 @@ void amdgpu_kiq_wreg(struct amdgpu_device *adev, uint32_t reg, uint32_t v, uint3 if (amdgpu_device_skip_hw_access(adev)) return; - if (adev->mes.ring.sched.ready) { + if (adev->mes.ring[0].sched.ready) { amdgpu_mes_wreg(adev, reg, v); return; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c index c0265902565670..b49b3650fd6217 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c @@ -589,7 +589,8 @@ int amdgpu_gmc_allocate_vm_inv_eng(struct amdgpu_device *adev) ring = adev->rings[i]; vmhub = ring->vm_hub; - if (ring == &adev->mes.ring || + if (ring == &adev->mes.ring[0] || + ring == &adev->mes.ring[1] || ring == &adev->umsch_mm.ring) continue; @@ -761,7 +762,7 @@ void amdgpu_gmc_fw_reg_write_reg_wait(struct amdgpu_device *adev, unsigned long flags; uint32_t seq; - if (adev->mes.ring.sched.ready) { + if (adev->mes.ring[0].sched.ready) { amdgpu_mes_reg_write_reg_wait(adev, reg0, reg1, ref, mask); return; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h index febca3130497ea..4d951a1baefab7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h @@ -156,6 +156,8 @@ struct amdgpu_gmc_funcs { uint64_t addr, uint64_t *flags); /* get the amount of memory used by the vbios for pre-OS console */ unsigned int (*get_vbios_fb_size)(struct amdgpu_device *adev); + /* get the DCC buffer alignment */ + unsigned int (*get_dcc_alignment)(struct amdgpu_device *adev); enum amdgpu_memory_partition (*query_mem_partition_mode)( struct amdgpu_device *adev); @@ -363,6 +365,10 @@ struct amdgpu_gmc { (adev)->gmc.gmc_funcs->override_vm_pte_flags \ ((adev), (vm), (addr), (pte_flags)) #define amdgpu_gmc_get_vbios_fb_size(adev) (adev)->gmc.gmc_funcs->get_vbios_fb_size((adev)) +#define amdgpu_gmc_get_dcc_alignment(adev) ({ \ + typeof(adev) _adev = (adev); \ + _adev->gmc.gmc_funcs->get_dcc_alignment(_adev); \ +}) /** * amdgpu_gmc_vram_full_visible - Check if full VRAM is visible through the BAR diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c index e238f2832f65b4..908e1345515233 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c @@ -264,9 +264,8 @@ amdgpu_job_prepare_job(struct drm_sched_job *sched_job, struct dma_fence *fence = NULL; int r; - /* Ignore soft recovered fences here */ r = drm_sched_entity_error(s_entity); - if (r && r != -ENODATA) + if (r) goto error; if (!fence && job->gang_submit) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c index e499d6ba306b73..1cb1ec7beefed3 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c @@ -103,7 +103,7 @@ static int amdgpu_mes_event_log_init(struct amdgpu_device *adev) if (!amdgpu_mes_log_enable) return 0; - r = amdgpu_bo_create_kernel(adev, AMDGPU_MES_LOG_BUFFER_SIZE, PAGE_SIZE, + r = amdgpu_bo_create_kernel(adev, adev->mes.event_log_size, PAGE_SIZE, AMDGPU_GEM_DOMAIN_GTT, &adev->mes.event_log_gpu_obj, &adev->mes.event_log_gpu_addr, @@ -113,7 +113,7 @@ static int amdgpu_mes_event_log_init(struct amdgpu_device *adev) return r; } - memset(adev->mes.event_log_cpu_addr, 0, PAGE_SIZE); + memset(adev->mes.event_log_cpu_addr, 0, adev->mes.event_log_size); return 0; @@ -135,9 +135,11 @@ int amdgpu_mes_init(struct amdgpu_device *adev) idr_init(&adev->mes.queue_id_idr); ida_init(&adev->mes.doorbell_ida); spin_lock_init(&adev->mes.queue_id_lock); - spin_lock_init(&adev->mes.ring_lock); mutex_init(&adev->mes.mutex_hidden); + for (i = 0; i < AMDGPU_MAX_MES_PIPES; i++) + spin_lock_init(&adev->mes.ring_lock[i]); + adev->mes.total_max_queue = AMDGPU_FENCE_MES_QUEUE_ID_MASK; adev->mes.vmid_mask_mmhub = 0xffffff00; adev->mes.vmid_mask_gfxhub = 0xffffff00; @@ -163,36 +165,38 @@ int amdgpu_mes_init(struct amdgpu_device *adev) adev->mes.sdma_hqd_mask[i] = 0xfc; } - r = amdgpu_device_wb_get(adev, &adev->mes.sch_ctx_offs); - if (r) { - dev_err(adev->dev, - "(%d) ring trail_fence_offs wb alloc failed\n", r); - goto error_ids; - } - adev->mes.sch_ctx_gpu_addr = - adev->wb.gpu_addr + (adev->mes.sch_ctx_offs * 4); - adev->mes.sch_ctx_ptr = - (uint64_t *)&adev->wb.wb[adev->mes.sch_ctx_offs]; + for (i = 0; i < AMDGPU_MAX_MES_PIPES; i++) { + r = amdgpu_device_wb_get(adev, &adev->mes.sch_ctx_offs[i]); + if (r) { + dev_err(adev->dev, + "(%d) ring trail_fence_offs wb alloc failed\n", + r); + goto error; + } + adev->mes.sch_ctx_gpu_addr[i] = + adev->wb.gpu_addr + (adev->mes.sch_ctx_offs[i] * 4); + adev->mes.sch_ctx_ptr[i] = + (uint64_t *)&adev->wb.wb[adev->mes.sch_ctx_offs[i]]; - r = amdgpu_device_wb_get(adev, &adev->mes.query_status_fence_offs); - if (r) { - amdgpu_device_wb_free(adev, adev->mes.sch_ctx_offs); - dev_err(adev->dev, - "(%d) query_status_fence_offs wb alloc failed\n", r); - goto error_ids; + r = amdgpu_device_wb_get(adev, + &adev->mes.query_status_fence_offs[i]); + if (r) { + dev_err(adev->dev, + "(%d) query_status_fence_offs wb alloc failed\n", + r); + goto error; + } + adev->mes.query_status_fence_gpu_addr[i] = adev->wb.gpu_addr + + (adev->mes.query_status_fence_offs[i] * 4); + adev->mes.query_status_fence_ptr[i] = + (uint64_t *)&adev->wb.wb[adev->mes.query_status_fence_offs[i]]; } - adev->mes.query_status_fence_gpu_addr = - adev->wb.gpu_addr + (adev->mes.query_status_fence_offs * 4); - adev->mes.query_status_fence_ptr = - (uint64_t *)&adev->wb.wb[adev->mes.query_status_fence_offs]; r = amdgpu_device_wb_get(adev, &adev->mes.read_val_offs); if (r) { - amdgpu_device_wb_free(adev, adev->mes.sch_ctx_offs); - amdgpu_device_wb_free(adev, adev->mes.query_status_fence_offs); dev_err(adev->dev, "(%d) read_val_offs alloc failed\n", r); - goto error_ids; + goto error; } adev->mes.read_val_gpu_addr = adev->wb.gpu_addr + (adev->mes.read_val_offs * 4); @@ -212,10 +216,16 @@ int amdgpu_mes_init(struct amdgpu_device *adev) error_doorbell: amdgpu_mes_doorbell_free(adev); error: - amdgpu_device_wb_free(adev, adev->mes.sch_ctx_offs); - amdgpu_device_wb_free(adev, adev->mes.query_status_fence_offs); - amdgpu_device_wb_free(adev, adev->mes.read_val_offs); -error_ids: + for (i = 0; i < AMDGPU_MAX_MES_PIPES; i++) { + if (adev->mes.sch_ctx_ptr[i]) + amdgpu_device_wb_free(adev, adev->mes.sch_ctx_offs[i]); + if (adev->mes.query_status_fence_ptr[i]) + amdgpu_device_wb_free(adev, + adev->mes.query_status_fence_offs[i]); + } + if (adev->mes.read_val_ptr) + amdgpu_device_wb_free(adev, adev->mes.read_val_offs); + idr_destroy(&adev->mes.pasid_idr); idr_destroy(&adev->mes.gang_id_idr); idr_destroy(&adev->mes.queue_id_idr); @@ -226,13 +236,22 @@ int amdgpu_mes_init(struct amdgpu_device *adev) void amdgpu_mes_fini(struct amdgpu_device *adev) { + int i; + amdgpu_bo_free_kernel(&adev->mes.event_log_gpu_obj, &adev->mes.event_log_gpu_addr, &adev->mes.event_log_cpu_addr); - amdgpu_device_wb_free(adev, adev->mes.sch_ctx_offs); - amdgpu_device_wb_free(adev, adev->mes.query_status_fence_offs); - amdgpu_device_wb_free(adev, adev->mes.read_val_offs); + for (i = 0; i < AMDGPU_MAX_MES_PIPES; i++) { + if (adev->mes.sch_ctx_ptr[i]) + amdgpu_device_wb_free(adev, adev->mes.sch_ctx_offs[i]); + if (adev->mes.query_status_fence_ptr[i]) + amdgpu_device_wb_free(adev, + adev->mes.query_status_fence_offs[i]); + } + if (adev->mes.read_val_ptr) + amdgpu_device_wb_free(adev, adev->mes.read_val_offs); + amdgpu_mes_doorbell_free(adev); idr_destroy(&adev->mes.pasid_idr); @@ -1499,7 +1518,7 @@ int amdgpu_mes_init_microcode(struct amdgpu_device *adev, int pipe) amdgpu_ucode_ip_version_decode(adev, GC_HWIP, ucode_prefix, sizeof(ucode_prefix)); - if (adev->enable_uni_mes && pipe == AMDGPU_MES_SCHED_PIPE) { + if (adev->enable_uni_mes) { snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_uni_mes.bin", ucode_prefix); } else if (amdgpu_ip_version(adev, GC_HWIP, 0) >= IP_VERSION(11, 0, 0) && @@ -1573,7 +1592,7 @@ static int amdgpu_debugfs_mes_event_log_show(struct seq_file *m, void *unused) uint32_t *mem = (uint32_t *)(adev->mes.event_log_cpu_addr); seq_hex_dump(m, "", DUMP_PREFIX_OFFSET, 32, 4, - mem, AMDGPU_MES_LOG_BUFFER_SIZE, false); + mem, adev->mes.event_log_size, false); return 0; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.h index e11051271f71db..0bc837dab578f9 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.h @@ -52,7 +52,6 @@ enum amdgpu_mes_priority_level { #define AMDGPU_MES_PROC_CTX_SIZE 0x1000 /* one page area */ #define AMDGPU_MES_GANG_CTX_SIZE 0x1000 /* one page area */ -#define AMDGPU_MES_LOG_BUFFER_SIZE 0x4000 /* Maximu log buffer size for MES */ struct amdgpu_mes_funcs; @@ -83,8 +82,8 @@ struct amdgpu_mes { uint64_t default_process_quantum; uint64_t default_gang_quantum; - struct amdgpu_ring ring; - spinlock_t ring_lock; + struct amdgpu_ring ring[AMDGPU_MAX_MES_PIPES]; + spinlock_t ring_lock[AMDGPU_MAX_MES_PIPES]; const struct firmware *fw[AMDGPU_MAX_MES_PIPES]; @@ -113,12 +112,12 @@ struct amdgpu_mes { uint32_t gfx_hqd_mask[AMDGPU_MES_MAX_GFX_PIPES]; uint32_t sdma_hqd_mask[AMDGPU_MES_MAX_SDMA_PIPES]; uint32_t aggregated_doorbells[AMDGPU_MES_PRIORITY_NUM_LEVELS]; - uint32_t sch_ctx_offs; - uint64_t sch_ctx_gpu_addr; - uint64_t *sch_ctx_ptr; - uint32_t query_status_fence_offs; - uint64_t query_status_fence_gpu_addr; - uint64_t *query_status_fence_ptr; + uint32_t sch_ctx_offs[AMDGPU_MAX_MES_PIPES]; + uint64_t sch_ctx_gpu_addr[AMDGPU_MAX_MES_PIPES]; + uint64_t *sch_ctx_ptr[AMDGPU_MAX_MES_PIPES]; + uint32_t query_status_fence_offs[AMDGPU_MAX_MES_PIPES]; + uint64_t query_status_fence_gpu_addr[AMDGPU_MAX_MES_PIPES]; + uint64_t *query_status_fence_ptr[AMDGPU_MAX_MES_PIPES]; uint32_t read_val_offs; uint64_t read_val_gpu_addr; uint32_t *read_val_ptr; @@ -135,8 +134,9 @@ struct amdgpu_mes { unsigned long *doorbell_bitmap; /* MES event log buffer */ - struct amdgpu_bo *event_log_gpu_obj; - uint64_t event_log_gpu_addr; + uint32_t event_log_size; + struct amdgpu_bo *event_log_gpu_obj; + uint64_t event_log_gpu_addr; void *event_log_cpu_addr; /* ip specific functions */ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c index ad49cecb20b8b2..e6344a6b0a9f6a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c @@ -212,6 +212,8 @@ int amdgpu_ring_init(struct amdgpu_device *adev, struct amdgpu_ring *ring, */ if (ring->funcs->type == AMDGPU_RING_TYPE_KIQ) sched_hw_submission = max(sched_hw_submission, 256); + if (ring->funcs->type == AMDGPU_RING_TYPE_MES) + sched_hw_submission = 8; else if (ring == &adev->sdma.instance[0].page) sched_hw_submission = 256; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h index 1a5439abd1a043..c87d68d4be5365 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h @@ -461,8 +461,11 @@ struct amdgpu_vcn5_fw_shared { struct amdgpu_fw_shared_unified_queue_struct sq; uint8_t pad1[8]; struct amdgpu_fw_shared_fw_logging fw_log; + uint8_t pad2[20]; struct amdgpu_fw_shared_rb_setup rb_setup; - uint8_t pad2[4]; + struct amdgpu_fw_shared_smu_interface_info smu_dpm_interface; + struct amdgpu_fw_shared_drm_key_wa drm_key_wa; + uint8_t pad3[9]; }; #define VCN_BLOCK_ENCODE_DISABLE_MASK 0x80 diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c index 111c380f929b59..b287a82e6177e9 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c @@ -858,7 +858,7 @@ void amdgpu_virt_post_reset(struct amdgpu_device *adev) adev->gfx.is_poweron = false; } - adev->mes.ring.sched.ready = false; + adev->mes.ring[0].sched.ready = false; } bool amdgpu_virt_fw_load_skip_check(struct amdgpu_device *adev, uint32_t ucode_id) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c index f91cc149d06c88..7d26a962f811cf 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c @@ -456,6 +456,7 @@ static int amdgpu_vram_mgr_new(struct ttm_resource_manager *man, u64 vis_usage = 0, max_bytes, min_block_size; struct amdgpu_vram_mgr_resource *vres; u64 size, remaining_size, lpfn, fpfn; + unsigned int adjust_dcc_size = 0; struct drm_buddy *mm = &mgr->mm; struct drm_buddy_block *block; unsigned long pages_per_block; @@ -511,7 +512,19 @@ static int amdgpu_vram_mgr_new(struct ttm_resource_manager *man, /* Allocate blocks in desired range */ vres->flags |= DRM_BUDDY_RANGE_ALLOCATION; + if (bo->flags & AMDGPU_GEM_CREATE_GFX12_DCC && + adev->gmc.gmc_funcs->get_dcc_alignment) + adjust_dcc_size = amdgpu_gmc_get_dcc_alignment(adev); + remaining_size = (u64)vres->base.size; + if (bo->flags & AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS && adjust_dcc_size) { + unsigned int dcc_size; + + dcc_size = roundup_pow_of_two(vres->base.size + adjust_dcc_size); + remaining_size = (u64)dcc_size; + + vres->flags |= DRM_BUDDY_TRIM_DISABLE; + } mutex_lock(&mgr->lock); while (remaining_size) { @@ -521,8 +534,11 @@ static int amdgpu_vram_mgr_new(struct ttm_resource_manager *man, min_block_size = mgr->default_page_size; size = remaining_size; - if ((size >= (u64)pages_per_block << PAGE_SHIFT) && - !(size & (((u64)pages_per_block << PAGE_SHIFT) - 1))) + + if (bo->flags & AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS && adjust_dcc_size) + min_block_size = size; + else if ((size >= (u64)pages_per_block << PAGE_SHIFT) && + !(size & (((u64)pages_per_block << PAGE_SHIFT) - 1))) min_block_size = (u64)pages_per_block << PAGE_SHIFT; BUG_ON(min_block_size < mm->chunk_size); @@ -553,6 +569,22 @@ static int amdgpu_vram_mgr_new(struct ttm_resource_manager *man, } mutex_unlock(&mgr->lock); + if (bo->flags & AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS && adjust_dcc_size) { + struct drm_buddy_block *dcc_block; + unsigned long dcc_start; + u64 trim_start; + + dcc_block = amdgpu_vram_mgr_first_block(&vres->blocks); + /* Adjust the start address for DCC buffers only */ + dcc_start = + roundup((unsigned long)amdgpu_vram_mgr_block_start(dcc_block), + adjust_dcc_size); + trim_start = (u64)dcc_start; + drm_buddy_block_trim(mm, &trim_start, + (u64)vres->base.size, + &vres->blocks); + } + vres->base.start = 0; size = max_t(u64, amdgpu_vram_mgr_blocks_size(&vres->blocks), vres->base.size); diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c index f384be0d1800c2..2c611b8577a7ec 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c @@ -202,6 +202,12 @@ static const struct amdgpu_hwip_reg_entry gc_gfx_queue_reg_list_12[] = { SOC15_REG_ENTRY_STR(GC, 0, regCP_IB1_BUFSZ) }; +static const struct soc15_reg_golden golden_settings_gc_12_0[] = { + SOC15_REG_GOLDEN_VALUE(GC, 0, regDB_MEM_CONFIG, 0x0000000f, 0x0000000f), + SOC15_REG_GOLDEN_VALUE(GC, 0, regCB_HW_CONTROL_1, 0x03000000, 0x03000000), + SOC15_REG_GOLDEN_VALUE(GC, 0, regGL2C_CTRL5, 0x00000070, 0x00000020) +}; + #define DEFAULT_SH_MEM_CONFIG \ ((SH_MEM_ADDRESS_MODE_64 << SH_MEM_CONFIG__ADDRESS_MODE__SHIFT) | \ (SH_MEM_ALIGNMENT_MODE_UNALIGNED << SH_MEM_CONFIG__ALIGNMENT_MODE__SHIFT) | \ @@ -3432,6 +3438,24 @@ static void gfx_v12_0_disable_gpa_mode(struct amdgpu_device *adev) WREG32_SOC15(GC, 0, regCPG_PSP_DEBUG, data); } +static void gfx_v12_0_init_golden_registers(struct amdgpu_device *adev) +{ + if (amdgpu_sriov_vf(adev)) + return; + + switch (amdgpu_ip_version(adev, GC_HWIP, 0)) { + case IP_VERSION(12, 0, 0): + case IP_VERSION(12, 0, 1): + if (adev->rev_id == 0) + soc15_program_register_sequence(adev, + golden_settings_gc_12_0, + (const u32)ARRAY_SIZE(golden_settings_gc_12_0)); + break; + default: + break; + } +} + static int gfx_v12_0_hw_init(void *handle) { int r; @@ -3472,6 +3496,9 @@ static int gfx_v12_0_hw_init(void *handle) } } + if (!amdgpu_emu_mode) + gfx_v12_0_init_golden_registers(adev); + adev->gfx.is_poweron = true; if (get_gb_addr_config(adev)) @@ -3519,33 +3546,9 @@ static int gfx_v12_0_hw_init(void *handle) return r; } -static int gfx_v12_0_kiq_disable_kgq(struct amdgpu_device *adev) -{ - struct amdgpu_kiq *kiq = &adev->gfx.kiq[0]; - struct amdgpu_ring *kiq_ring = &kiq->ring; - int i, r = 0; - - if (!kiq->pmf || !kiq->pmf->kiq_unmap_queues) - return -EINVAL; - - if (amdgpu_ring_alloc(kiq_ring, kiq->pmf->unmap_queues_size * - adev->gfx.num_gfx_rings)) - return -ENOMEM; - - for (i = 0; i < adev->gfx.num_gfx_rings; i++) - kiq->pmf->kiq_unmap_queues(kiq_ring, &adev->gfx.gfx_ring[i], - PREEMPT_QUEUES, 0, 0); - - if (adev->gfx.kiq[0].ring.sched.ready) - r = amdgpu_ring_test_helper(kiq_ring); - - return r; -} - static int gfx_v12_0_hw_fini(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; - int r; uint32_t tmp; amdgpu_irq_put(adev, &adev->gfx.priv_reg_irq, 0); @@ -3553,8 +3556,7 @@ static int gfx_v12_0_hw_fini(void *handle) if (!adev->no_hw_access) { if (amdgpu_async_gfx_ring) { - r = gfx_v12_0_kiq_disable_kgq(adev); - if (r) + if (amdgpu_gfx_disable_kgq(adev, 0)) DRM_ERROR("KGQ disable failed\n"); } diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c index b88a6fa173b362..2797fd84432b22 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c @@ -231,7 +231,7 @@ static void gmc_v11_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid, /* This is necessary for SRIOV as well as for GFXOFF to function * properly under bare metal */ - if ((adev->gfx.kiq[0].ring.sched.ready || adev->mes.ring.sched.ready) && + if ((adev->gfx.kiq[0].ring.sched.ready || adev->mes.ring[0].sched.ready) && (amdgpu_sriov_runtime(adev) || !amdgpu_sriov_vf(adev))) { amdgpu_gmc_fw_reg_write_reg_wait(adev, req, ack, inv_req, 1 << vmid, GET_INST(GC, 0)); diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v12_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v12_0.c index fd3ac483760e6d..edcb5351f8cca7 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v12_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v12_0.c @@ -299,7 +299,7 @@ static void gmc_v12_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid, /* This is necessary for SRIOV as well as for GFXOFF to function * properly under bare metal */ - if ((adev->gfx.kiq[0].ring.sched.ready || adev->mes.ring.sched.ready) && + if ((adev->gfx.kiq[0].ring.sched.ready || adev->mes.ring[0].sched.ready) && (amdgpu_sriov_runtime(adev) || !amdgpu_sriov_vf(adev))) { struct amdgpu_vmhub *hub = &adev->vmhub[vmhub]; const unsigned eng = 17; @@ -542,6 +542,23 @@ static unsigned gmc_v12_0_get_vbios_fb_size(struct amdgpu_device *adev) return 0; } +static unsigned int gmc_v12_0_get_dcc_alignment(struct amdgpu_device *adev) +{ + unsigned int max_tex_channel_caches, alignment; + + if (amdgpu_ip_version(adev, GC_HWIP, 0) != IP_VERSION(12, 0, 0) && + amdgpu_ip_version(adev, GC_HWIP, 0) != IP_VERSION(12, 0, 1)) + return 0; + + max_tex_channel_caches = adev->gfx.config.max_texture_channel_caches; + if (is_power_of_2(max_tex_channel_caches)) + alignment = (unsigned int)(max_tex_channel_caches / SZ_4); + else + alignment = roundup_pow_of_two(max_tex_channel_caches); + + return (unsigned int)(alignment * max_tex_channel_caches * SZ_1K); +} + static const struct amdgpu_gmc_funcs gmc_v12_0_gmc_funcs = { .flush_gpu_tlb = gmc_v12_0_flush_gpu_tlb, .flush_gpu_tlb_pasid = gmc_v12_0_flush_gpu_tlb_pasid, @@ -551,6 +568,7 @@ static const struct amdgpu_gmc_funcs gmc_v12_0_gmc_funcs = { .get_vm_pde = gmc_v12_0_get_vm_pde, .get_vm_pte = gmc_v12_0_get_vm_pte, .get_vbios_fb_size = gmc_v12_0_get_vbios_fb_size, + .get_dcc_alignment = gmc_v12_0_get_dcc_alignment, }; static void gmc_v12_0_set_gmc_funcs(struct amdgpu_device *adev) diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c index 99adf3625657e9..98aa3ccd0d2024 100644 --- a/drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c +++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c @@ -538,11 +538,11 @@ void jpeg_v2_0_dec_ring_emit_ib(struct amdgpu_ring *ring, amdgpu_ring_write(ring, PACKETJ(mmUVD_LMI_JRBC_IB_VMID_INTERNAL_OFFSET, 0, 0, PACKETJ_TYPE0)); - amdgpu_ring_write(ring, (vmid | (vmid << 4))); + amdgpu_ring_write(ring, (vmid | (vmid << 4) | (vmid << 8))); amdgpu_ring_write(ring, PACKETJ(mmUVD_LMI_JPEG_VMID_INTERNAL_OFFSET, 0, 0, PACKETJ_TYPE0)); - amdgpu_ring_write(ring, (vmid | (vmid << 4))); + amdgpu_ring_write(ring, (vmid | (vmid << 4) | (vmid << 8))); amdgpu_ring_write(ring, PACKETJ(mmUVD_LMI_JRBC_IB_64BIT_BAR_LOW_INTERNAL_OFFSET, 0, 0, PACKETJ_TYPE0)); 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 ad524ddc9760a8..6ae5a784e18746 100644 --- a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c +++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c @@ -23,6 +23,7 @@ #include "amdgpu.h" #include "amdgpu_jpeg.h" +#include "amdgpu_cs.h" #include "soc15.h" #include "soc15d.h" #include "jpeg_v4_0_3.h" @@ -782,11 +783,15 @@ void jpeg_v4_0_3_dec_ring_emit_ib(struct amdgpu_ring *ring, amdgpu_ring_write(ring, PACKETJ(regUVD_LMI_JRBC_IB_VMID_INTERNAL_OFFSET, 0, 0, PACKETJ_TYPE0)); - amdgpu_ring_write(ring, (vmid | (vmid << 4))); + + if (ring->funcs->parse_cs) + amdgpu_ring_write(ring, 0); + else + amdgpu_ring_write(ring, (vmid | (vmid << 4) | (vmid << 8))); amdgpu_ring_write(ring, PACKETJ(regUVD_LMI_JPEG_VMID_INTERNAL_OFFSET, 0, 0, PACKETJ_TYPE0)); - amdgpu_ring_write(ring, (vmid | (vmid << 4))); + amdgpu_ring_write(ring, (vmid | (vmid << 4) | (vmid << 8))); amdgpu_ring_write(ring, PACKETJ(regUVD_LMI_JRBC_IB_64BIT_BAR_LOW_INTERNAL_OFFSET, 0, 0, PACKETJ_TYPE0)); @@ -1084,6 +1089,7 @@ static const struct amdgpu_ring_funcs jpeg_v4_0_3_dec_ring_vm_funcs = { .get_rptr = jpeg_v4_0_3_dec_ring_get_rptr, .get_wptr = jpeg_v4_0_3_dec_ring_get_wptr, .set_wptr = jpeg_v4_0_3_dec_ring_set_wptr, + .parse_cs = jpeg_v4_0_3_dec_ring_parse_cs, .emit_frame_size = SOC15_FLUSH_GPU_TLB_NUM_WREG * 6 + SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 8 + @@ -1248,3 +1254,56 @@ static void jpeg_v4_0_3_set_ras_funcs(struct amdgpu_device *adev) { adev->jpeg.ras = &jpeg_v4_0_3_ras; } + +/** + * jpeg_v4_0_3_dec_ring_parse_cs - command submission parser + * + * @parser: Command submission parser context + * @job: the job to parse + * @ib: the IB to parse + * + * Parse the command stream, return -EINVAL for invalid packet, + * 0 otherwise + */ +int jpeg_v4_0_3_dec_ring_parse_cs(struct amdgpu_cs_parser *parser, + struct amdgpu_job *job, + struct amdgpu_ib *ib) +{ + uint32_t i, reg, res, cond, type; + struct amdgpu_device *adev = parser->adev; + + for (i = 0; i < ib->length_dw ; i += 2) { + reg = CP_PACKETJ_GET_REG(ib->ptr[i]); + res = CP_PACKETJ_GET_RES(ib->ptr[i]); + cond = CP_PACKETJ_GET_COND(ib->ptr[i]); + type = CP_PACKETJ_GET_TYPE(ib->ptr[i]); + + if (res) /* only support 0 at the moment */ + return -EINVAL; + + switch (type) { + case PACKETJ_TYPE0: + if (cond != PACKETJ_CONDITION_CHECK0 || reg < JPEG_REG_RANGE_START || reg > JPEG_REG_RANGE_END) { + dev_err(adev->dev, "Invalid packet [0x%08x]!\n", ib->ptr[i]); + return -EINVAL; + } + break; + case PACKETJ_TYPE3: + if (cond != PACKETJ_CONDITION_CHECK3 || reg < JPEG_REG_RANGE_START || reg > JPEG_REG_RANGE_END) { + dev_err(adev->dev, "Invalid packet [0x%08x]!\n", ib->ptr[i]); + return -EINVAL; + } + break; + case PACKETJ_TYPE6: + if (ib->ptr[i] == CP_PACKETJ_NOP) + continue; + dev_err(adev->dev, "Invalid packet [0x%08x]!\n", ib->ptr[i]); + return -EINVAL; + default: + dev_err(adev->dev, "Unknown packet type %d !\n", type); + return -EINVAL; + } + } + + return 0; +} diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.h b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.h index 747a3e5f68564c..71c54b294e157e 100644 --- a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.h +++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.h @@ -46,6 +46,9 @@ #define JRBC_DEC_EXTERNAL_REG_WRITE_ADDR 0x18000 +#define JPEG_REG_RANGE_START 0x4000 +#define JPEG_REG_RANGE_END 0x41c2 + extern const struct amdgpu_ip_block_version jpeg_v4_0_3_ip_block; void jpeg_v4_0_3_dec_ring_emit_ib(struct amdgpu_ring *ring, @@ -62,5 +65,7 @@ void jpeg_v4_0_3_dec_ring_insert_end(struct amdgpu_ring *ring); void jpeg_v4_0_3_dec_ring_emit_wreg(struct amdgpu_ring *ring, uint32_t reg, uint32_t val); void jpeg_v4_0_3_dec_ring_emit_reg_wait(struct amdgpu_ring *ring, uint32_t reg, uint32_t val, uint32_t mask); - +int jpeg_v4_0_3_dec_ring_parse_cs(struct amdgpu_cs_parser *parser, + struct amdgpu_job *job, + struct amdgpu_ib *ib); #endif /* __JPEG_V4_0_3_H__ */ diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_0.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_0.c index d694a276498a1e..f4daff90c7709d 100644 --- a/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_0.c +++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_0.c @@ -646,6 +646,7 @@ static const struct amdgpu_ring_funcs jpeg_v5_0_0_dec_ring_vm_funcs = { .get_rptr = jpeg_v5_0_0_dec_ring_get_rptr, .get_wptr = jpeg_v5_0_0_dec_ring_get_wptr, .set_wptr = jpeg_v5_0_0_dec_ring_set_wptr, + .parse_cs = jpeg_v4_0_3_dec_ring_parse_cs, .emit_frame_size = SOC15_FLUSH_GPU_TLB_NUM_WREG * 6 + SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 8 + diff --git a/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c b/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c index 8ce51b9236c1ae..2ea8223eb969ae 100644 --- a/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c @@ -162,13 +162,13 @@ static int mes_v11_0_submit_pkt_and_poll_completion(struct amdgpu_mes *mes, union MESAPI__QUERY_MES_STATUS mes_status_pkt; signed long timeout = 3000000; /* 3000 ms */ struct amdgpu_device *adev = mes->adev; - struct amdgpu_ring *ring = &mes->ring; + struct amdgpu_ring *ring = &mes->ring[0]; struct MES_API_STATUS *api_status; union MESAPI__MISC *x_pkt = pkt; const char *op_str, *misc_op_str; unsigned long flags; u64 status_gpu_addr; - u32 status_offset; + u32 seq, status_offset; u64 *status_ptr; signed long r; int ret; @@ -191,11 +191,18 @@ static int mes_v11_0_submit_pkt_and_poll_completion(struct amdgpu_mes *mes, status_ptr = (u64 *)&adev->wb.wb[status_offset]; *status_ptr = 0; - spin_lock_irqsave(&mes->ring_lock, flags); + spin_lock_irqsave(&mes->ring_lock[0], flags); r = amdgpu_ring_alloc(ring, (size + sizeof(mes_status_pkt)) / 4); if (r) goto error_unlock_free; + seq = ++ring->fence_drv.sync_seq; + r = amdgpu_fence_wait_polling(ring, + seq - ring->fence_drv.num_fences_mask, + timeout); + if (r < 1) + goto error_undo; + api_status = (struct MES_API_STATUS *)((char *)pkt + api_status_off); api_status->api_completion_fence_addr = status_gpu_addr; api_status->api_completion_fence_value = 1; @@ -208,14 +215,13 @@ static int mes_v11_0_submit_pkt_and_poll_completion(struct amdgpu_mes *mes, mes_status_pkt.header.dwsize = API_FRAME_SIZE_IN_DWORDS; mes_status_pkt.api_status.api_completion_fence_addr = ring->fence_drv.gpu_addr; - mes_status_pkt.api_status.api_completion_fence_value = - ++ring->fence_drv.sync_seq; + mes_status_pkt.api_status.api_completion_fence_value = seq; amdgpu_ring_write_multiple(ring, &mes_status_pkt, sizeof(mes_status_pkt) / 4); amdgpu_ring_commit(ring); - spin_unlock_irqrestore(&mes->ring_lock, flags); + spin_unlock_irqrestore(&mes->ring_lock[0], flags); op_str = mes_v11_0_get_op_string(x_pkt); misc_op_str = mes_v11_0_get_misc_op_string(x_pkt); @@ -229,7 +235,7 @@ static int mes_v11_0_submit_pkt_and_poll_completion(struct amdgpu_mes *mes, dev_dbg(adev->dev, "MES msg=%d was emitted\n", x_pkt->header.opcode); - r = amdgpu_fence_wait_polling(ring, ring->fence_drv.sync_seq, timeout); + r = amdgpu_fence_wait_polling(ring, seq, timeout); if (r < 1 || !*status_ptr) { if (misc_op_str) @@ -252,8 +258,12 @@ static int mes_v11_0_submit_pkt_and_poll_completion(struct amdgpu_mes *mes, amdgpu_device_wb_free(adev, status_offset); return 0; +error_undo: + dev_err(adev->dev, "MES ring buffer is full.\n"); + amdgpu_ring_undo(ring); + error_unlock_free: - spin_unlock_irqrestore(&mes->ring_lock, flags); + spin_unlock_irqrestore(&mes->ring_lock[0], flags); error_wb_free: amdgpu_device_wb_free(adev, status_offset); @@ -512,9 +522,9 @@ static int mes_v11_0_set_hw_resources(struct amdgpu_mes *mes) mes_set_hw_res_pkt.vmid_mask_gfxhub = mes->vmid_mask_gfxhub; mes_set_hw_res_pkt.gds_size = adev->gds.gds_size; mes_set_hw_res_pkt.paging_vmid = 0; - mes_set_hw_res_pkt.g_sch_ctx_gpu_mc_ptr = mes->sch_ctx_gpu_addr; + mes_set_hw_res_pkt.g_sch_ctx_gpu_mc_ptr = mes->sch_ctx_gpu_addr[0]; mes_set_hw_res_pkt.query_status_fence_gpu_mc_ptr = - mes->query_status_fence_gpu_addr; + mes->query_status_fence_gpu_addr[0]; for (i = 0; i < MAX_COMPUTE_PIPES; i++) mes_set_hw_res_pkt.compute_hqd_mask[i] = @@ -1015,7 +1025,7 @@ static int mes_v11_0_kiq_enable_queue(struct amdgpu_device *adev) return r; } - kiq->pmf->kiq_map_queues(kiq_ring, &adev->mes.ring); + kiq->pmf->kiq_map_queues(kiq_ring, &adev->mes.ring[0]); return amdgpu_ring_test_helper(kiq_ring); } @@ -1029,7 +1039,7 @@ static int mes_v11_0_queue_init(struct amdgpu_device *adev, if (pipe == AMDGPU_MES_KIQ_PIPE) ring = &adev->gfx.kiq[0].ring; else if (pipe == AMDGPU_MES_SCHED_PIPE) - ring = &adev->mes.ring; + ring = &adev->mes.ring[0]; else BUG(); @@ -1071,7 +1081,7 @@ static int mes_v11_0_ring_init(struct amdgpu_device *adev) { struct amdgpu_ring *ring; - ring = &adev->mes.ring; + ring = &adev->mes.ring[0]; ring->funcs = &mes_v11_0_ring_funcs; @@ -1124,7 +1134,7 @@ static int mes_v11_0_mqd_sw_init(struct amdgpu_device *adev, if (pipe == AMDGPU_MES_KIQ_PIPE) ring = &adev->gfx.kiq[0].ring; else if (pipe == AMDGPU_MES_SCHED_PIPE) - ring = &adev->mes.ring; + ring = &adev->mes.ring[0]; else BUG(); @@ -1163,6 +1173,8 @@ static int mes_v11_0_sw_init(void *handle) adev->mes.kiq_hw_init = &mes_v11_0_kiq_hw_init; adev->mes.kiq_hw_fini = &mes_v11_0_kiq_hw_fini; + adev->mes.event_log_size = AMDGPU_MES_LOG_BUFFER_SIZE; + r = amdgpu_mes_init(adev); if (r) return r; @@ -1198,9 +1210,6 @@ static int mes_v11_0_sw_fini(void *handle) struct amdgpu_device *adev = (struct amdgpu_device *)handle; int pipe; - amdgpu_device_wb_free(adev, adev->mes.sch_ctx_offs); - amdgpu_device_wb_free(adev, adev->mes.query_status_fence_offs); - for (pipe = 0; pipe < AMDGPU_MAX_MES_PIPES; pipe++) { kfree(adev->mes.mqd_backup[pipe]); @@ -1214,12 +1223,12 @@ static int mes_v11_0_sw_fini(void *handle) &adev->gfx.kiq[0].ring.mqd_gpu_addr, &adev->gfx.kiq[0].ring.mqd_ptr); - amdgpu_bo_free_kernel(&adev->mes.ring.mqd_obj, - &adev->mes.ring.mqd_gpu_addr, - &adev->mes.ring.mqd_ptr); + amdgpu_bo_free_kernel(&adev->mes.ring[0].mqd_obj, + &adev->mes.ring[0].mqd_gpu_addr, + &adev->mes.ring[0].mqd_ptr); amdgpu_ring_fini(&adev->gfx.kiq[0].ring); - amdgpu_ring_fini(&adev->mes.ring); + amdgpu_ring_fini(&adev->mes.ring[0]); if (adev->firmware.load_type == AMDGPU_FW_LOAD_DIRECT) { mes_v11_0_free_ucode_buffers(adev, AMDGPU_MES_KIQ_PIPE); @@ -1330,9 +1339,9 @@ static int mes_v11_0_kiq_hw_init(struct amdgpu_device *adev) static int mes_v11_0_kiq_hw_fini(struct amdgpu_device *adev) { - if (adev->mes.ring.sched.ready) { - mes_v11_0_kiq_dequeue(&adev->mes.ring); - adev->mes.ring.sched.ready = false; + if (adev->mes.ring[0].sched.ready) { + mes_v11_0_kiq_dequeue(&adev->mes.ring[0]); + adev->mes.ring[0].sched.ready = false; } if (amdgpu_sriov_vf(adev)) { @@ -1350,7 +1359,7 @@ static int mes_v11_0_hw_init(void *handle) int r; struct amdgpu_device *adev = (struct amdgpu_device *)handle; - if (adev->mes.ring.sched.ready) + if (adev->mes.ring[0].sched.ready) goto out; if (!adev->enable_mes_kiq) { @@ -1395,7 +1404,7 @@ static int mes_v11_0_hw_init(void *handle) * with MES enabled. */ adev->gfx.kiq[0].ring.sched.ready = false; - adev->mes.ring.sched.ready = true; + adev->mes.ring[0].sched.ready = true; return 0; diff --git a/drivers/gpu/drm/amd/amdgpu/mes_v12_0.c b/drivers/gpu/drm/amd/amdgpu/mes_v12_0.c index c9f74231ad5951..e39a58d262c94e 100644 --- a/drivers/gpu/drm/amd/amdgpu/mes_v12_0.c +++ b/drivers/gpu/drm/amd/amdgpu/mes_v12_0.c @@ -142,19 +142,20 @@ static const char *mes_v12_0_get_misc_op_string(union MESAPI__MISC *x_pkt) } static int mes_v12_0_submit_pkt_and_poll_completion(struct amdgpu_mes *mes, - void *pkt, int size, - int api_status_off) + int pipe, void *pkt, int size, + int api_status_off) { union MESAPI__QUERY_MES_STATUS mes_status_pkt; signed long timeout = 3000000; /* 3000 ms */ struct amdgpu_device *adev = mes->adev; - struct amdgpu_ring *ring = &mes->ring; + struct amdgpu_ring *ring = &mes->ring[pipe]; + spinlock_t *ring_lock = &mes->ring_lock[pipe]; struct MES_API_STATUS *api_status; union MESAPI__MISC *x_pkt = pkt; const char *op_str, *misc_op_str; unsigned long flags; u64 status_gpu_addr; - u32 status_offset; + u32 seq, status_offset; u64 *status_ptr; signed long r; int ret; @@ -177,11 +178,18 @@ static int mes_v12_0_submit_pkt_and_poll_completion(struct amdgpu_mes *mes, status_ptr = (u64 *)&adev->wb.wb[status_offset]; *status_ptr = 0; - spin_lock_irqsave(&mes->ring_lock, flags); + spin_lock_irqsave(ring_lock, flags); r = amdgpu_ring_alloc(ring, (size + sizeof(mes_status_pkt)) / 4); if (r) goto error_unlock_free; + seq = ++ring->fence_drv.sync_seq; + r = amdgpu_fence_wait_polling(ring, + seq - ring->fence_drv.num_fences_mask, + timeout); + if (r < 1) + goto error_undo; + api_status = (struct MES_API_STATUS *)((char *)pkt + api_status_off); api_status->api_completion_fence_addr = status_gpu_addr; api_status->api_completion_fence_value = 1; @@ -194,39 +202,39 @@ static int mes_v12_0_submit_pkt_and_poll_completion(struct amdgpu_mes *mes, mes_status_pkt.header.dwsize = API_FRAME_SIZE_IN_DWORDS; mes_status_pkt.api_status.api_completion_fence_addr = ring->fence_drv.gpu_addr; - mes_status_pkt.api_status.api_completion_fence_value = - ++ring->fence_drv.sync_seq; + mes_status_pkt.api_status.api_completion_fence_value = seq; amdgpu_ring_write_multiple(ring, &mes_status_pkt, sizeof(mes_status_pkt) / 4); amdgpu_ring_commit(ring); - spin_unlock_irqrestore(&mes->ring_lock, flags); + spin_unlock_irqrestore(ring_lock, flags); op_str = mes_v12_0_get_op_string(x_pkt); misc_op_str = mes_v12_0_get_misc_op_string(x_pkt); if (misc_op_str) - dev_dbg(adev->dev, "MES msg=%s (%s) was emitted\n", op_str, - misc_op_str); + dev_dbg(adev->dev, "MES(%d) msg=%s (%s) was emitted\n", + pipe, op_str, misc_op_str); else if (op_str) - dev_dbg(adev->dev, "MES msg=%s was emitted\n", op_str); + dev_dbg(adev->dev, "MES(%d) msg=%s was emitted\n", + pipe, op_str); else - dev_dbg(adev->dev, "MES msg=%d was emitted\n", - x_pkt->header.opcode); + dev_dbg(adev->dev, "MES(%d) msg=%d was emitted\n", + pipe, x_pkt->header.opcode); - r = amdgpu_fence_wait_polling(ring, ring->fence_drv.sync_seq, timeout); + r = amdgpu_fence_wait_polling(ring, seq, timeout); if (r < 1 || !*status_ptr) { if (misc_op_str) - dev_err(adev->dev, "MES failed to respond to msg=%s (%s)\n", - op_str, misc_op_str); + dev_err(adev->dev, "MES(%d) failed to respond to msg=%s (%s)\n", + pipe, op_str, misc_op_str); else if (op_str) - dev_err(adev->dev, "MES failed to respond to msg=%s\n", - op_str); + dev_err(adev->dev, "MES(%d) failed to respond to msg=%s\n", + pipe, op_str); else - dev_err(adev->dev, "MES failed to respond to msg=%d\n", - x_pkt->header.opcode); + dev_err(adev->dev, "MES(%d) failed to respond to msg=%d\n", + pipe, x_pkt->header.opcode); while (halt_if_hws_hang) schedule(); @@ -238,8 +246,12 @@ static int mes_v12_0_submit_pkt_and_poll_completion(struct amdgpu_mes *mes, amdgpu_device_wb_free(adev, status_offset); return 0; +error_undo: + dev_err(adev->dev, "MES ring buffer is full.\n"); + amdgpu_ring_undo(ring); + error_unlock_free: - spin_unlock_irqrestore(&mes->ring_lock, flags); + spin_unlock_irqrestore(ring_lock, flags); error_wb_free: amdgpu_device_wb_free(adev, status_offset); @@ -254,6 +266,8 @@ static int convert_to_mes_queue_type(int queue_type) return MES_QUEUE_TYPE_COMPUTE; else if (queue_type == AMDGPU_RING_TYPE_SDMA) return MES_QUEUE_TYPE_SDMA; + else if (queue_type == AMDGPU_RING_TYPE_MES) + return MES_QUEUE_TYPE_SCHQ; else BUG(); return -1; @@ -311,6 +325,7 @@ static int mes_v12_0_add_hw_queue(struct amdgpu_mes *mes, mes_add_queue_pkt.gds_size = input->queue_size; return mes_v12_0_submit_pkt_and_poll_completion(mes, + AMDGPU_MES_SCHED_PIPE, &mes_add_queue_pkt, sizeof(mes_add_queue_pkt), offsetof(union MESAPI__ADD_QUEUE, api_status)); } @@ -330,6 +345,7 @@ static int mes_v12_0_remove_hw_queue(struct amdgpu_mes *mes, mes_remove_queue_pkt.gang_context_addr = input->gang_context_addr; return mes_v12_0_submit_pkt_and_poll_completion(mes, + AMDGPU_MES_SCHED_PIPE, &mes_remove_queue_pkt, sizeof(mes_remove_queue_pkt), offsetof(union MESAPI__REMOVE_QUEUE, api_status)); } @@ -338,6 +354,7 @@ static int mes_v12_0_map_legacy_queue(struct amdgpu_mes *mes, struct mes_map_legacy_queue_input *input) { union MESAPI__ADD_QUEUE mes_add_queue_pkt; + int pipe; memset(&mes_add_queue_pkt, 0, sizeof(mes_add_queue_pkt)); @@ -354,7 +371,12 @@ static int mes_v12_0_map_legacy_queue(struct amdgpu_mes *mes, convert_to_mes_queue_type(input->queue_type); mes_add_queue_pkt.map_legacy_kq = 1; - return mes_v12_0_submit_pkt_and_poll_completion(mes, + if (mes->adev->enable_uni_mes) + pipe = AMDGPU_MES_KIQ_PIPE; + else + pipe = AMDGPU_MES_SCHED_PIPE; + + return mes_v12_0_submit_pkt_and_poll_completion(mes, pipe, &mes_add_queue_pkt, sizeof(mes_add_queue_pkt), offsetof(union MESAPI__ADD_QUEUE, api_status)); } @@ -363,6 +385,7 @@ static int mes_v12_0_unmap_legacy_queue(struct amdgpu_mes *mes, struct mes_unmap_legacy_queue_input *input) { union MESAPI__REMOVE_QUEUE mes_remove_queue_pkt; + int pipe; memset(&mes_remove_queue_pkt, 0, sizeof(mes_remove_queue_pkt)); @@ -387,7 +410,12 @@ static int mes_v12_0_unmap_legacy_queue(struct amdgpu_mes *mes, convert_to_mes_queue_type(input->queue_type); } - return mes_v12_0_submit_pkt_and_poll_completion(mes, + if (mes->adev->enable_uni_mes) + pipe = AMDGPU_MES_KIQ_PIPE; + else + pipe = AMDGPU_MES_SCHED_PIPE; + + return mes_v12_0_submit_pkt_and_poll_completion(mes, pipe, &mes_remove_queue_pkt, sizeof(mes_remove_queue_pkt), offsetof(union MESAPI__REMOVE_QUEUE, api_status)); } @@ -404,7 +432,7 @@ static int mes_v12_0_resume_gang(struct amdgpu_mes *mes, return 0; } -static int mes_v12_0_query_sched_status(struct amdgpu_mes *mes) +static int mes_v12_0_query_sched_status(struct amdgpu_mes *mes, int pipe) { union MESAPI__QUERY_MES_STATUS mes_status_pkt; @@ -414,7 +442,7 @@ static int mes_v12_0_query_sched_status(struct amdgpu_mes *mes) mes_status_pkt.header.opcode = MES_SCH_API_QUERY_SCHEDULER_STATUS; mes_status_pkt.header.dwsize = API_FRAME_SIZE_IN_DWORDS; - return mes_v12_0_submit_pkt_and_poll_completion(mes, + return mes_v12_0_submit_pkt_and_poll_completion(mes, pipe, &mes_status_pkt, sizeof(mes_status_pkt), offsetof(union MESAPI__QUERY_MES_STATUS, api_status)); } @@ -423,6 +451,7 @@ static int mes_v12_0_misc_op(struct amdgpu_mes *mes, struct mes_misc_op_input *input) { union MESAPI__MISC misc_pkt; + int pipe; memset(&misc_pkt, 0, sizeof(misc_pkt)); @@ -475,12 +504,17 @@ static int mes_v12_0_misc_op(struct amdgpu_mes *mes, return -EINVAL; } - return mes_v12_0_submit_pkt_and_poll_completion(mes, + if (mes->adev->enable_uni_mes) + pipe = AMDGPU_MES_KIQ_PIPE; + else + pipe = AMDGPU_MES_SCHED_PIPE; + + return mes_v12_0_submit_pkt_and_poll_completion(mes, pipe, &misc_pkt, sizeof(misc_pkt), offsetof(union MESAPI__MISC, api_status)); } -static int mes_v12_0_set_hw_resources_1(struct amdgpu_mes *mes) +static int mes_v12_0_set_hw_resources_1(struct amdgpu_mes *mes, int pipe) { union MESAPI_SET_HW_RESOURCES_1 mes_set_hw_res_1_pkt; @@ -491,12 +525,12 @@ static int mes_v12_0_set_hw_resources_1(struct amdgpu_mes *mes) mes_set_hw_res_1_pkt.header.dwsize = API_FRAME_SIZE_IN_DWORDS; mes_set_hw_res_1_pkt.mes_kiq_unmap_timeout = 100; - return mes_v12_0_submit_pkt_and_poll_completion(mes, + return mes_v12_0_submit_pkt_and_poll_completion(mes, pipe, &mes_set_hw_res_1_pkt, sizeof(mes_set_hw_res_1_pkt), offsetof(union MESAPI_SET_HW_RESOURCES_1, api_status)); } -static int mes_v12_0_set_hw_resources(struct amdgpu_mes *mes) +static int mes_v12_0_set_hw_resources(struct amdgpu_mes *mes, int pipe) { int i; struct amdgpu_device *adev = mes->adev; @@ -508,27 +542,33 @@ static int mes_v12_0_set_hw_resources(struct amdgpu_mes *mes) mes_set_hw_res_pkt.header.opcode = MES_SCH_API_SET_HW_RSRC; mes_set_hw_res_pkt.header.dwsize = API_FRAME_SIZE_IN_DWORDS; - mes_set_hw_res_pkt.vmid_mask_mmhub = mes->vmid_mask_mmhub; - mes_set_hw_res_pkt.vmid_mask_gfxhub = mes->vmid_mask_gfxhub; - mes_set_hw_res_pkt.gds_size = adev->gds.gds_size; - mes_set_hw_res_pkt.paging_vmid = 0; - mes_set_hw_res_pkt.g_sch_ctx_gpu_mc_ptr = mes->sch_ctx_gpu_addr; - mes_set_hw_res_pkt.query_status_fence_gpu_mc_ptr = - mes->query_status_fence_gpu_addr; - - for (i = 0; i < MAX_COMPUTE_PIPES; i++) - mes_set_hw_res_pkt.compute_hqd_mask[i] = - mes->compute_hqd_mask[i]; - - for (i = 0; i < MAX_GFX_PIPES; i++) - mes_set_hw_res_pkt.gfx_hqd_mask[i] = mes->gfx_hqd_mask[i]; - - for (i = 0; i < MAX_SDMA_PIPES; i++) - mes_set_hw_res_pkt.sdma_hqd_mask[i] = mes->sdma_hqd_mask[i]; + if (pipe == AMDGPU_MES_SCHED_PIPE) { + mes_set_hw_res_pkt.vmid_mask_mmhub = mes->vmid_mask_mmhub; + mes_set_hw_res_pkt.vmid_mask_gfxhub = mes->vmid_mask_gfxhub; + mes_set_hw_res_pkt.gds_size = adev->gds.gds_size; + mes_set_hw_res_pkt.paging_vmid = 0; + + for (i = 0; i < MAX_COMPUTE_PIPES; i++) + mes_set_hw_res_pkt.compute_hqd_mask[i] = + mes->compute_hqd_mask[i]; + + for (i = 0; i < MAX_GFX_PIPES; i++) + mes_set_hw_res_pkt.gfx_hqd_mask[i] = + mes->gfx_hqd_mask[i]; + + for (i = 0; i < MAX_SDMA_PIPES; i++) + mes_set_hw_res_pkt.sdma_hqd_mask[i] = + mes->sdma_hqd_mask[i]; + + for (i = 0; i < AMD_PRIORITY_NUM_LEVELS; i++) + mes_set_hw_res_pkt.aggregated_doorbells[i] = + mes->aggregated_doorbells[i]; + } - for (i = 0; i < AMD_PRIORITY_NUM_LEVELS; i++) - mes_set_hw_res_pkt.aggregated_doorbells[i] = - mes->aggregated_doorbells[i]; + mes_set_hw_res_pkt.g_sch_ctx_gpu_mc_ptr = + mes->sch_ctx_gpu_addr[pipe]; + mes_set_hw_res_pkt.query_status_fence_gpu_mc_ptr = + mes->query_status_fence_gpu_addr[pipe]; for (i = 0; i < 5; i++) { mes_set_hw_res_pkt.gc_base[i] = adev->reg_offset[GC_HWIP][0][i]; @@ -551,10 +591,12 @@ static int mes_v12_0_set_hw_resources(struct amdgpu_mes *mes) mes_set_hw_res_pkt.oversubscription_timer = 50; mes_set_hw_res_pkt.unmapped_doorbell_handling = 1; - mes_set_hw_res_pkt.enable_mes_event_int_logging = 0; - mes_set_hw_res_pkt.event_intr_history_gpu_mc_ptr = mes->event_log_gpu_addr; + if (amdgpu_mes_log_enable) { + mes_set_hw_res_pkt.enable_mes_event_int_logging = 1; + mes_set_hw_res_pkt.event_intr_history_gpu_mc_ptr = mes->event_log_gpu_addr; + } - return mes_v12_0_submit_pkt_and_poll_completion(mes, + return mes_v12_0_submit_pkt_and_poll_completion(mes, pipe, &mes_set_hw_res_pkt, sizeof(mes_set_hw_res_pkt), offsetof(union MESAPI_SET_HW_RESOURCES, api_status)); } @@ -732,16 +774,11 @@ static void mes_v12_0_enable(struct amdgpu_device *adev, bool enable) if (enable) { data = RREG32_SOC15(GC, 0, regCP_MES_CNTL); data = REG_SET_FIELD(data, CP_MES_CNTL, MES_PIPE0_RESET, 1); - data = REG_SET_FIELD(data, CP_MES_CNTL, MES_PIPE1_RESET, - (!adev->enable_uni_mes && adev->enable_mes_kiq) ? 1 : 0); + data = REG_SET_FIELD(data, CP_MES_CNTL, MES_PIPE1_RESET, 1); WREG32_SOC15(GC, 0, regCP_MES_CNTL, data); mutex_lock(&adev->srbm_mutex); for (pipe = 0; pipe < AMDGPU_MAX_MES_PIPES; pipe++) { - if ((!adev->enable_mes_kiq || adev->enable_uni_mes) && - pipe == AMDGPU_MES_KIQ_PIPE) - continue; - soc21_grbm_select(adev, 3, pipe, 0, 0); ucode_addr = adev->mes.uc_start_addr[pipe] >> 2; @@ -755,8 +792,7 @@ static void mes_v12_0_enable(struct amdgpu_device *adev, bool enable) /* unhalt MES and activate pipe0 */ data = REG_SET_FIELD(0, CP_MES_CNTL, MES_PIPE0_ACTIVE, 1); - data = REG_SET_FIELD(data, CP_MES_CNTL, MES_PIPE1_ACTIVE, - (!adev->enable_uni_mes && adev->enable_mes_kiq) ? 1 : 0); + data = REG_SET_FIELD(data, CP_MES_CNTL, MES_PIPE1_ACTIVE, 1); WREG32_SOC15(GC, 0, regCP_MES_CNTL, data); if (amdgpu_emu_mode) @@ -772,8 +808,7 @@ static void mes_v12_0_enable(struct amdgpu_device *adev, bool enable) data = REG_SET_FIELD(data, CP_MES_CNTL, MES_INVALIDATE_ICACHE, 1); data = REG_SET_FIELD(data, CP_MES_CNTL, MES_PIPE0_RESET, 1); - data = REG_SET_FIELD(data, CP_MES_CNTL, MES_PIPE1_RESET, - (!adev->enable_uni_mes && adev->enable_mes_kiq) ? 1 : 0); + data = REG_SET_FIELD(data, CP_MES_CNTL, MES_PIPE1_RESET, 1); data = REG_SET_FIELD(data, CP_MES_CNTL, MES_HALT, 1); WREG32_SOC15(GC, 0, regCP_MES_CNTL, data); } @@ -788,10 +823,6 @@ static void mes_v12_0_set_ucode_start_addr(struct amdgpu_device *adev) mutex_lock(&adev->srbm_mutex); for (pipe = 0; pipe < AMDGPU_MAX_MES_PIPES; pipe++) { - if ((!adev->enable_mes_kiq || adev->enable_uni_mes) && - pipe == AMDGPU_MES_KIQ_PIPE) - continue; - /* me=3, queue=0 */ soc21_grbm_select(adev, 3, pipe, 0, 0); @@ -1083,7 +1114,7 @@ static int mes_v12_0_kiq_enable_queue(struct amdgpu_device *adev) return r; } - kiq->pmf->kiq_map_queues(kiq_ring, &adev->mes.ring); + kiq->pmf->kiq_map_queues(kiq_ring, &adev->mes.ring[0]); r = amdgpu_ring_test_ring(kiq_ring); if (r) { @@ -1099,14 +1130,12 @@ static int mes_v12_0_queue_init(struct amdgpu_device *adev, struct amdgpu_ring *ring; int r; - if (pipe == AMDGPU_MES_KIQ_PIPE) + if (!adev->enable_uni_mes && pipe == AMDGPU_MES_KIQ_PIPE) ring = &adev->gfx.kiq[0].ring; - else if (pipe == AMDGPU_MES_SCHED_PIPE) - ring = &adev->mes.ring; else - BUG(); + ring = &adev->mes.ring[pipe]; - if ((pipe == AMDGPU_MES_SCHED_PIPE) && + if ((adev->enable_uni_mes || pipe == AMDGPU_MES_SCHED_PIPE) && (amdgpu_in_reset(adev) || adev->in_suspend)) { *(ring->wptr_cpu_addr) = 0; *(ring->rptr_cpu_addr) = 0; @@ -1118,13 +1147,12 @@ static int mes_v12_0_queue_init(struct amdgpu_device *adev, return r; if (pipe == AMDGPU_MES_SCHED_PIPE) { - if (adev->enable_uni_mes) { - mes_v12_0_queue_init_register(ring); - } else { + if (adev->enable_uni_mes) + r = amdgpu_mes_map_legacy_queue(adev, ring); + else r = mes_v12_0_kiq_enable_queue(adev); - if (r) - return r; - } + if (r) + return r; } else { mes_v12_0_queue_init_register(ring); } @@ -1144,25 +1172,29 @@ static int mes_v12_0_queue_init(struct amdgpu_device *adev, return 0; } -static int mes_v12_0_ring_init(struct amdgpu_device *adev) +static int mes_v12_0_ring_init(struct amdgpu_device *adev, int pipe) { struct amdgpu_ring *ring; - ring = &adev->mes.ring; + ring = &adev->mes.ring[pipe]; ring->funcs = &mes_v12_0_ring_funcs; ring->me = 3; - ring->pipe = 0; + ring->pipe = pipe; ring->queue = 0; ring->ring_obj = NULL; ring->use_doorbell = true; - ring->doorbell_index = adev->doorbell_index.mes_ring0 << 1; - ring->eop_gpu_addr = adev->mes.eop_gpu_addr[AMDGPU_MES_SCHED_PIPE]; + ring->eop_gpu_addr = adev->mes.eop_gpu_addr[pipe]; ring->no_scheduler = true; sprintf(ring->name, "mes_%d.%d.%d", ring->me, ring->pipe, ring->queue); + if (pipe == AMDGPU_MES_SCHED_PIPE) + ring->doorbell_index = adev->doorbell_index.mes_ring0 << 1; + else + ring->doorbell_index = adev->doorbell_index.mes_ring1 << 1; + return amdgpu_ring_init(adev, ring, 1024, NULL, 0, AMDGPU_RING_PRIO_DEFAULT, NULL); } @@ -1176,7 +1208,7 @@ static int mes_v12_0_kiq_ring_init(struct amdgpu_device *adev) ring = &adev->gfx.kiq[0].ring; ring->me = 3; - ring->pipe = adev->enable_uni_mes ? 0 : 1; + ring->pipe = 1; ring->queue = 0; ring->adev = NULL; @@ -1198,12 +1230,10 @@ static int mes_v12_0_mqd_sw_init(struct amdgpu_device *adev, int r, mqd_size = sizeof(struct v12_compute_mqd); struct amdgpu_ring *ring; - if (pipe == AMDGPU_MES_KIQ_PIPE) + if (!adev->enable_uni_mes && pipe == AMDGPU_MES_KIQ_PIPE) ring = &adev->gfx.kiq[0].ring; - else if (pipe == AMDGPU_MES_SCHED_PIPE) - ring = &adev->mes.ring; else - BUG(); + ring = &adev->mes.ring[pipe]; if (ring->mqd_obj) return 0; @@ -1237,14 +1267,13 @@ static int mes_v12_0_sw_init(void *handle) adev->mes.kiq_hw_init = &mes_v12_0_kiq_hw_init; adev->mes.kiq_hw_fini = &mes_v12_0_kiq_hw_fini; + adev->mes.event_log_size = AMDGPU_MES_LOG_BUFFER_SIZE; + r = amdgpu_mes_init(adev); if (r) return r; for (pipe = 0; pipe < AMDGPU_MAX_MES_PIPES; pipe++) { - if (!adev->enable_mes_kiq && pipe == AMDGPU_MES_KIQ_PIPE) - continue; - r = mes_v12_0_allocate_eop_buf(adev, pipe); if (r) return r; @@ -1252,18 +1281,15 @@ static int mes_v12_0_sw_init(void *handle) r = mes_v12_0_mqd_sw_init(adev, pipe); if (r) return r; - } - if (adev->enable_mes_kiq) { - r = mes_v12_0_kiq_ring_init(adev); + if (!adev->enable_uni_mes && pipe == AMDGPU_MES_KIQ_PIPE) + r = mes_v12_0_kiq_ring_init(adev); + else + r = mes_v12_0_ring_init(adev, pipe); if (r) return r; } - r = mes_v12_0_ring_init(adev); - if (r) - return r; - return 0; } @@ -1272,9 +1298,6 @@ static int mes_v12_0_sw_fini(void *handle) struct amdgpu_device *adev = (struct amdgpu_device *)handle; int pipe; - amdgpu_device_wb_free(adev, adev->mes.sch_ctx_offs); - amdgpu_device_wb_free(adev, adev->mes.query_status_fence_offs); - for (pipe = 0; pipe < AMDGPU_MAX_MES_PIPES; pipe++) { kfree(adev->mes.mqd_backup[pipe]); @@ -1282,18 +1305,21 @@ static int mes_v12_0_sw_fini(void *handle) &adev->mes.eop_gpu_addr[pipe], NULL); amdgpu_ucode_release(&adev->mes.fw[pipe]); - } - amdgpu_bo_free_kernel(&adev->gfx.kiq[0].ring.mqd_obj, - &adev->gfx.kiq[0].ring.mqd_gpu_addr, - &adev->gfx.kiq[0].ring.mqd_ptr); - - amdgpu_bo_free_kernel(&adev->mes.ring.mqd_obj, - &adev->mes.ring.mqd_gpu_addr, - &adev->mes.ring.mqd_ptr); + if (adev->enable_uni_mes || pipe == AMDGPU_MES_SCHED_PIPE) { + amdgpu_bo_free_kernel(&adev->mes.ring[pipe].mqd_obj, + &adev->mes.ring[pipe].mqd_gpu_addr, + &adev->mes.ring[pipe].mqd_ptr); + amdgpu_ring_fini(&adev->mes.ring[pipe]); + } + } - amdgpu_ring_fini(&adev->gfx.kiq[0].ring); - amdgpu_ring_fini(&adev->mes.ring); + if (!adev->enable_uni_mes) { + amdgpu_bo_free_kernel(&adev->gfx.kiq[0].ring.mqd_obj, + &adev->gfx.kiq[0].ring.mqd_gpu_addr, + &adev->gfx.kiq[0].ring.mqd_ptr); + amdgpu_ring_fini(&adev->gfx.kiq[0].ring); + } if (adev->firmware.load_type == AMDGPU_FW_LOAD_DIRECT) { mes_v12_0_free_ucode_buffers(adev, AMDGPU_MES_KIQ_PIPE); @@ -1337,7 +1363,7 @@ static void mes_v12_0_kiq_dequeue_sched(struct amdgpu_device *adev) soc21_grbm_select(adev, 0, 0, 0, 0); mutex_unlock(&adev->srbm_mutex); - adev->mes.ring.sched.ready = false; + adev->mes.ring[0].sched.ready = false; } static void mes_v12_0_kiq_setting(struct amdgpu_ring *ring) @@ -1358,10 +1384,10 @@ static int mes_v12_0_kiq_hw_init(struct amdgpu_device *adev) { int r = 0; - mes_v12_0_kiq_setting(&adev->gfx.kiq[0].ring); - if (adev->enable_uni_mes) - return mes_v12_0_hw_init(adev); + mes_v12_0_kiq_setting(&adev->mes.ring[AMDGPU_MES_KIQ_PIPE]); + else + mes_v12_0_kiq_setting(&adev->gfx.kiq[0].ring); if (adev->firmware.load_type == AMDGPU_FW_LOAD_DIRECT) { @@ -1388,6 +1414,14 @@ static int mes_v12_0_kiq_hw_init(struct amdgpu_device *adev) if (r) goto failure; + if (adev->enable_uni_mes) { + r = mes_v12_0_set_hw_resources(&adev->mes, AMDGPU_MES_KIQ_PIPE); + if (r) + goto failure; + + mes_v12_0_set_hw_resources_1(&adev->mes, AMDGPU_MES_KIQ_PIPE); + } + r = mes_v12_0_hw_init(adev); if (r) goto failure; @@ -1401,9 +1435,15 @@ static int mes_v12_0_kiq_hw_init(struct amdgpu_device *adev) static int mes_v12_0_kiq_hw_fini(struct amdgpu_device *adev) { - if (adev->mes.ring.sched.ready) { - mes_v12_0_kiq_dequeue_sched(adev); - adev->mes.ring.sched.ready = false; + if (adev->mes.ring[0].sched.ready) { + if (adev->enable_uni_mes) + amdgpu_mes_unmap_legacy_queue(adev, + &adev->mes.ring[AMDGPU_MES_SCHED_PIPE], + RESET_QUEUES, 0, 0); + else + mes_v12_0_kiq_dequeue_sched(adev); + + adev->mes.ring[0].sched.ready = false; } mes_v12_0_enable(adev, false); @@ -1416,10 +1456,10 @@ static int mes_v12_0_hw_init(void *handle) int r; struct amdgpu_device *adev = (struct amdgpu_device *)handle; - if (adev->mes.ring.sched.ready) + if (adev->mes.ring[0].sched.ready) goto out; - if (!adev->enable_mes_kiq || adev->enable_uni_mes) { + if (!adev->enable_mes_kiq) { if (adev->firmware.load_type == AMDGPU_FW_LOAD_DIRECT) { r = mes_v12_0_load_microcode(adev, AMDGPU_MES_SCHED_PIPE, true); @@ -1439,23 +1479,23 @@ static int mes_v12_0_hw_init(void *handle) mes_v12_0_enable(adev, true); } + /* Enable the MES to handle doorbell ring on unmapped queue */ + mes_v12_0_enable_unmapped_doorbell_handling(&adev->mes, true); + r = mes_v12_0_queue_init(adev, AMDGPU_MES_SCHED_PIPE); if (r) goto failure; - r = mes_v12_0_set_hw_resources(&adev->mes); + r = mes_v12_0_set_hw_resources(&adev->mes, AMDGPU_MES_SCHED_PIPE); if (r) goto failure; if (adev->enable_uni_mes) - mes_v12_0_set_hw_resources_1(&adev->mes); + mes_v12_0_set_hw_resources_1(&adev->mes, AMDGPU_MES_SCHED_PIPE); mes_v12_0_init_aggregated_doorbell(&adev->mes); - /* Enable the MES to handle doorbell ring on unmapped queue */ - mes_v12_0_enable_unmapped_doorbell_handling(&adev->mes, true); - - r = mes_v12_0_query_sched_status(&adev->mes); + r = mes_v12_0_query_sched_status(&adev->mes, AMDGPU_MES_SCHED_PIPE); if (r) { DRM_ERROR("MES is busy\n"); goto failure; @@ -1468,7 +1508,7 @@ static int mes_v12_0_hw_init(void *handle) * with MES enabled. */ adev->gfx.kiq[0].ring.sched.ready = false; - adev->mes.ring.sched.ready = true; + adev->mes.ring[0].sched.ready = true; return 0; @@ -1511,17 +1551,7 @@ static int mes_v12_0_early_init(void *handle) struct amdgpu_device *adev = (struct amdgpu_device *)handle; int pipe, r; - if (adev->enable_uni_mes) { - r = amdgpu_mes_init_microcode(adev, AMDGPU_MES_SCHED_PIPE); - if (!r) - return 0; - - adev->enable_uni_mes = false; - } - for (pipe = 0; pipe < AMDGPU_MAX_MES_PIPES; pipe++) { - if (!adev->enable_mes_kiq && pipe == AMDGPU_MES_KIQ_PIPE) - continue; r = amdgpu_mes_init_microcode(adev, pipe); if (r) return r; diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v4_1_0.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v4_1_0.c index 5bbaa2b2caaba4..0fbc3be81f140f 100644 --- a/drivers/gpu/drm/amd/amdgpu/mmhub_v4_1_0.c +++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v4_1_0.c @@ -80,7 +80,8 @@ static uint32_t mmhub_v4_1_0_get_invalidate_req(unsigned int vmid, /* invalidate using legacy mode on vmid*/ req = REG_SET_FIELD(req, MMVM_INVALIDATE_ENG0_REQ, PER_VMID_INVALIDATE_REQ, 1 << vmid); - req = REG_SET_FIELD(req, MMVM_INVALIDATE_ENG0_REQ, FLUSH_TYPE, flush_type); + /* Only use legacy inv on mmhub side */ + req = REG_SET_FIELD(req, MMVM_INVALIDATE_ENG0_REQ, FLUSH_TYPE, 0); req = REG_SET_FIELD(req, MMVM_INVALIDATE_ENG0_REQ, INVALIDATE_L2_PTES, 1); req = REG_SET_FIELD(req, MMVM_INVALIDATE_ENG0_REQ, INVALIDATE_L2_PDE0, 1); req = REG_SET_FIELD(req, MMVM_INVALIDATE_ENG0_REQ, INVALIDATE_L2_PDE1, 1); diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v7_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v7_0.c index 41b5e45697dcde..ecee9e7d7e4c6b 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v7_0.c @@ -1575,8 +1575,7 @@ static void sdma_v7_0_emit_copy_buffer(struct amdgpu_ib *ib, ib->ptr[ib->length_dw++] = SDMA_PKT_COPY_LINEAR_HEADER_OP(SDMA_OP_COPY) | SDMA_PKT_COPY_LINEAR_HEADER_SUB_OP(SDMA_SUBOP_COPY_LINEAR) | SDMA_PKT_COPY_LINEAR_HEADER_TMZ((copy_flags & AMDGPU_COPY_FLAGS_TMZ) ? 1 : 0) | - SDMA_PKT_COPY_LINEAR_HEADER_CPV((copy_flags & - (AMDGPU_COPY_FLAGS_READ_DECOMPRESSED | AMDGPU_COPY_FLAGS_WRITE_COMPRESSED)) ? 1 : 0); + SDMA_PKT_COPY_LINEAR_HEADER_CPV(1); ib->ptr[ib->length_dw++] = byte_count - 1; ib->ptr[ib->length_dw++] = 0; /* src/dst endian swap */ @@ -1590,6 +1589,8 @@ static void sdma_v7_0_emit_copy_buffer(struct amdgpu_ib *ib, ((copy_flags & AMDGPU_COPY_FLAGS_READ_DECOMPRESSED) ? SDMA_DCC_READ_CM(2) : 0) | ((copy_flags & AMDGPU_COPY_FLAGS_WRITE_COMPRESSED) ? SDMA_DCC_WRITE_CM(1) : 0) | SDMA_DCC_MAX_COM(max_com) | SDMA_DCC_MAX_UCOM(1); + else + ib->ptr[ib->length_dw++] = 0; } /** @@ -1616,7 +1617,7 @@ static void sdma_v7_0_emit_fill_buffer(struct amdgpu_ib *ib, static const struct amdgpu_buffer_funcs sdma_v7_0_buffer_funcs = { .copy_max_bytes = 0x400000, - .copy_num_dw = 7, + .copy_num_dw = 8, .emit_copy_buffer = sdma_v7_0_emit_copy_buffer, .fill_max_bytes = 0x400000, .fill_num_dw = 5, diff --git a/drivers/gpu/drm/amd/amdgpu/soc15d.h b/drivers/gpu/drm/amd/amdgpu/soc15d.h index 2357ff39323f05..e74e1983da53aa 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc15d.h +++ b/drivers/gpu/drm/amd/amdgpu/soc15d.h @@ -76,6 +76,12 @@ ((cond & 0xF) << 24) | \ ((type & 0xF) << 28)) +#define CP_PACKETJ_NOP 0x60000000 +#define CP_PACKETJ_GET_REG(x) ((x) & 0x3FFFF) +#define CP_PACKETJ_GET_RES(x) (((x) >> 18) & 0x3F) +#define CP_PACKETJ_GET_COND(x) (((x) >> 24) & 0xF) +#define CP_PACKETJ_GET_TYPE(x) (((x) >> 28) & 0xF) + /* Packet 3 types */ #define PACKET3_NOP 0x10 #define PACKET3_SET_BASE 0x11 diff --git a/drivers/gpu/drm/amd/amdgpu/soc24.c b/drivers/gpu/drm/amd/amdgpu/soc24.c index 7d641d0dadba4d..b0c3678cfb31d8 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc24.c +++ b/drivers/gpu/drm/amd/amdgpu/soc24.c @@ -406,6 +406,7 @@ static int soc24_common_early_init(void *handle) AMD_CG_SUPPORT_ATHUB_MGCG | AMD_CG_SUPPORT_ATHUB_LS | AMD_CG_SUPPORT_MC_MGCG | + AMD_CG_SUPPORT_HDP_SD | AMD_CG_SUPPORT_MC_LS; adev->pg_flags = AMD_PG_SUPPORT_VCN | AMD_PG_SUPPORT_JPEG | @@ -424,6 +425,7 @@ static int soc24_common_early_init(void *handle) AMD_CG_SUPPORT_ATHUB_MGCG | AMD_CG_SUPPORT_ATHUB_LS | AMD_CG_SUPPORT_MC_MGCG | + AMD_CG_SUPPORT_HDP_SD | AMD_CG_SUPPORT_MC_LS; adev->pg_flags = AMD_PG_SUPPORT_VCN | 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 7e7929f24ae447..983a977632ff4e 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -2893,6 +2893,9 @@ static int dm_suspend(void *handle) hpd_rx_irq_work_suspend(dm); + if (adev->dm.dc->caps.ips_support) + dc_allow_idle_optimizations(adev->dm.dc, true); + dc_set_power_state(dm->dc, DC_ACPI_CM_POWER_STATE_D3); dc_dmub_srv_set_power_state(dm->dc->ctx->dmub_srv, DC_ACPI_CM_POWER_STATE_D3); diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index 5442da90f508f6..2e9f6da1acdcad 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -804,12 +804,25 @@ struct dsc_mst_fairness_params { }; #if defined(CONFIG_DRM_AMD_DC_FP) -static int kbps_to_peak_pbn(int kbps) +static uint16_t get_fec_overhead_multiplier(struct dc_link *dc_link) +{ + u8 link_coding_cap; + uint16_t fec_overhead_multiplier_x1000 = PBN_FEC_OVERHEAD_MULTIPLIER_8B_10B; + + link_coding_cap = dc_link_dp_mst_decide_link_encoding_format(dc_link); + if (link_coding_cap == DP_128b_132b_ENCODING) + fec_overhead_multiplier_x1000 = PBN_FEC_OVERHEAD_MULTIPLIER_128B_132B; + + return fec_overhead_multiplier_x1000; +} + +static int kbps_to_peak_pbn(int kbps, uint16_t fec_overhead_multiplier_x1000) { u64 peak_kbps = kbps; peak_kbps *= 1006; - peak_kbps = div_u64(peak_kbps, 1000); + peak_kbps *= fec_overhead_multiplier_x1000; + peak_kbps = div_u64(peak_kbps, 1000 * 1000); return (int) DIV64_U64_ROUND_UP(peak_kbps * 64, (54 * 8 * 1000)); } @@ -910,11 +923,12 @@ static int increase_dsc_bpp(struct drm_atomic_state *state, int link_timeslots_used; int fair_pbn_alloc; int ret = 0; + uint16_t fec_overhead_multiplier_x1000 = get_fec_overhead_multiplier(dc_link); for (i = 0; i < count; i++) { if (vars[i + k].dsc_enabled) { initial_slack[i] = - kbps_to_peak_pbn(params[i].bw_range.max_kbps) - vars[i + k].pbn; + kbps_to_peak_pbn(params[i].bw_range.max_kbps, fec_overhead_multiplier_x1000) - vars[i + k].pbn; bpp_increased[i] = false; remaining_to_increase += 1; } else { @@ -1010,6 +1024,7 @@ static int try_disable_dsc(struct drm_atomic_state *state, int next_index; int remaining_to_try = 0; int ret; + uint16_t fec_overhead_multiplier_x1000 = get_fec_overhead_multiplier(dc_link); for (i = 0; i < count; i++) { if (vars[i + k].dsc_enabled @@ -1039,7 +1054,7 @@ static int try_disable_dsc(struct drm_atomic_state *state, if (next_index == -1) break; - vars[next_index].pbn = kbps_to_peak_pbn(params[next_index].bw_range.stream_kbps); + vars[next_index].pbn = kbps_to_peak_pbn(params[next_index].bw_range.stream_kbps, fec_overhead_multiplier_x1000); ret = drm_dp_atomic_find_time_slots(state, params[next_index].port->mgr, params[next_index].port, @@ -1052,8 +1067,7 @@ static int try_disable_dsc(struct drm_atomic_state *state, vars[next_index].dsc_enabled = false; vars[next_index].bpp_x16 = 0; } else { - vars[next_index].pbn = kbps_to_peak_pbn( - params[next_index].bw_range.max_kbps); + vars[next_index].pbn = kbps_to_peak_pbn(params[next_index].bw_range.stream_kbps, fec_overhead_multiplier_x1000); ret = drm_dp_atomic_find_time_slots(state, params[next_index].port->mgr, params[next_index].port, @@ -1082,6 +1096,7 @@ static int compute_mst_dsc_configs_for_link(struct drm_atomic_state *state, int count = 0; int i, k, ret; bool debugfs_overwrite = false; + uint16_t fec_overhead_multiplier_x1000 = get_fec_overhead_multiplier(dc_link); memset(params, 0, sizeof(params)); @@ -1146,7 +1161,7 @@ static int compute_mst_dsc_configs_for_link(struct drm_atomic_state *state, /* Try no compression */ for (i = 0; i < count; i++) { vars[i + k].aconnector = params[i].aconnector; - vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.stream_kbps); + vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.stream_kbps, fec_overhead_multiplier_x1000); vars[i + k].dsc_enabled = false; vars[i + k].bpp_x16 = 0; ret = drm_dp_atomic_find_time_slots(state, params[i].port->mgr, params[i].port, @@ -1165,7 +1180,7 @@ static int compute_mst_dsc_configs_for_link(struct drm_atomic_state *state, /* Try max compression */ for (i = 0; i < count; i++) { if (params[i].compression_possible && params[i].clock_force_enable != DSC_CLK_FORCE_DISABLE) { - vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.min_kbps); + vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.min_kbps, fec_overhead_multiplier_x1000); vars[i + k].dsc_enabled = true; vars[i + k].bpp_x16 = params[i].bw_range.min_target_bpp_x16; ret = drm_dp_atomic_find_time_slots(state, params[i].port->mgr, @@ -1173,7 +1188,7 @@ static int compute_mst_dsc_configs_for_link(struct drm_atomic_state *state, if (ret < 0) return ret; } else { - vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.stream_kbps); + vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.stream_kbps, fec_overhead_multiplier_x1000); vars[i + k].dsc_enabled = false; vars[i + k].bpp_x16 = 0; ret = drm_dp_atomic_find_time_slots(state, params[i].port->mgr, @@ -1270,6 +1285,9 @@ static bool is_dsc_need_re_compute( } } + if (new_stream_on_link_num == 0) + return false; + /* check current_state if there stream on link but it is not in * new request state */ diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h index fa84d34b737367..600d6e22101112 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h @@ -46,6 +46,9 @@ #define SYNAPTICS_CASCADED_HUB_ID 0x5A #define IS_SYNAPTICS_CASCADED_PANAMERA(devName, data) ((IS_SYNAPTICS_PANAMERA(devName) && ((int)data[2] == SYNAPTICS_CASCADED_HUB_ID)) ? 1 : 0) +#define PBN_FEC_OVERHEAD_MULTIPLIER_8B_10B 1031 +#define PBN_FEC_OVERHEAD_MULTIPLIER_128B_132B 1000 + enum mst_msg_ready_type { NONE_MSG_RDY_EVENT = 0, DOWN_REP_MSG_RDY_EVENT = 1, diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index be2638c763d789..9a406d74c0dd76 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -35,8 +35,10 @@ #include "dc_stream_priv.h" #define DC_LOGGER dc->ctx->logger +#ifndef MIN #define MIN(X, Y) ((X) < (Y) ? (X) : (Y)) #define MAX(x, y) ((x > y) ? x : y) +#endif /******************************************************************************* * Private functions diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.c b/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.c index 2a21bcf5224f45..4d960dc5ce8935 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.c @@ -185,8 +185,7 @@ static bool dmub_replay_copy_settings(struct dmub_replay *dmub, else copy_settings_data->flags.bitfields.force_wakeup_by_tps3 = 0; - - dm_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT); + dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT); return true; } diff --git a/drivers/gpu/drm/amd/display/dc/dml/Makefile b/drivers/gpu/drm/amd/display/dc/dml/Makefile index 3c0222aa4df1d8..46f9c05de16e8c 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dml/Makefile @@ -83,6 +83,8 @@ CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn31/display_rq_dlg_calc_31.o := $(dml_rcfla CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn32/display_mode_vba_32.o := $(dml_rcflags) CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn32/display_rq_dlg_calc_32.o := $(dml_rcflags) CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn32/display_mode_vba_util_32.o := $(dml_rcflags) +CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn314/display_mode_vba_314.o := $(dml_rcflags) +CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn314/display_rq_dlg_calc_314.o := $(dml_rcflags) CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn301/dcn301_fpu.o := $(dml_rcflags) CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/display_mode_lib.o := $(dml_rcflags) CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dsc/rc_calc_fpu.o := $(dml_rcflags) diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c index e06fc370267bea..14a902ff3b8ac9 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c @@ -1402,6 +1402,8 @@ void dcn10_init_pipes(struct dc *dc, struct dc_state *context) if (hubbub && hubp) { if (hubbub->funcs->program_det_size) hubbub->funcs->program_det_size(hubbub, hubp->inst, 0); + if (hubbub->funcs->program_det_segments) + hubbub->funcs->program_det_segments(hubbub, hubp->inst, 0); } } @@ -3587,7 +3589,7 @@ void dcn10_set_cursor_position(struct pipe_ctx *pipe_ctx) (int)hubp->curs_attr.width || pos_cpy.x <= (int)hubp->curs_attr.width + pipe_ctx->plane_state->src_rect.x) { - pos_cpy.x = temp_x + viewport_width; + pos_cpy.x = 2 * viewport_width - temp_x; } } } else { @@ -3680,7 +3682,7 @@ void dcn10_set_cursor_position(struct pipe_ctx *pipe_ctx) (int)hubp->curs_attr.width || pos_cpy.x <= (int)hubp->curs_attr.width + pipe_ctx->plane_state->src_rect.x) { - pos_cpy.x = 2 * viewport_width - temp_x; + pos_cpy.x = temp_x + viewport_width; } } } else { diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c index e4f7078c10269f..f115c7a285e776 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c @@ -771,6 +771,8 @@ void dcn35_init_pipes(struct dc *dc, struct dc_state *context) if (hubbub && hubp) { if (hubbub->funcs->program_det_size) hubbub->funcs->program_det_size(hubbub, hubp->inst, 0); + if (hubbub->funcs->program_det_segments) + hubbub->funcs->program_det_segments(hubbub, hubp->inst, 0); } } diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c index 9a3cc0514a36ed..8e0588b1cf3054 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c @@ -1778,6 +1778,9 @@ static bool dcn321_resource_construct( dc->caps.color.mpc.ogam_rom_caps.hlg = 0; dc->caps.color.mpc.ocsc = 1; + /* Use pipe context based otg sync logic */ + dc->config.use_pipe_ctx_sync_logic = true; + dc->config.dc_mode_clk_limit_support = true; dc->config.enable_windowed_mpo_odm = true; /* read VBIOS LTTPR caps */ diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c index a05a2209a44e67..34b02147881ddb 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c @@ -723,6 +723,7 @@ static const struct dc_debug_options debug_defaults_drv = { .min_prefetch_in_strobe_ns = 60000, // 60us .disable_unbounded_requesting = false, .enable_legacy_fast_update = false, + .dcc_meta_propagation_delay_us = 10, .fams2_config = { .bits = { .enable = true, diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.h b/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.h index 26efeada4f41fd..bb46f30d11d0a1 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.h +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.h @@ -138,7 +138,9 @@ void dcn401_prepare_mcache_programming(struct dc *dc, struct dc_state *context); SRI_ARR(DCHUBP_MALL_CONFIG, HUBP, id), \ SRI_ARR(DCHUBP_VMPG_CONFIG, HUBP, id), \ SRI_ARR(UCLK_PSTATE_FORCE, HUBPREQ, id), \ - HUBP_3DLUT_FL_REG_LIST_DCN401(id) + HUBP_3DLUT_FL_REG_LIST_DCN401(id), \ + SRI_ARR(DCSURF_VIEWPORT_MCACHE_SPLIT_COORDINATE, HUBP, id), \ + SRI_ARR(DCHUBP_MCACHEID_CONFIG, HUBP, id) /* ABM */ #define ABM_DCN401_REG_LIST_RI(id) \ diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_ddc.c b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_ddc.c index 7ecf76aea95051..6e064e6ae949f3 100644 --- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_ddc.c +++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_ddc.c @@ -25,7 +25,9 @@ #include "hdcp.h" +#ifndef MIN #define MIN(a, b) ((a) < (b) ? (a) : (b)) +#endif #define HDCP_I2C_ADDR 0x3a /* 0x74 >> 1*/ #define KSV_READ_SIZE 0xf /* 0x6803b - 0x6802c */ #define HDCP_MAX_AUX_TRANSACTION_SIZE 16 diff --git a/drivers/gpu/drm/amd/include/mes_v11_api_def.h b/drivers/gpu/drm/amd/include/mes_v11_api_def.h index b72d5d36225123..21ceafce1f9b27 100644 --- a/drivers/gpu/drm/amd/include/mes_v11_api_def.h +++ b/drivers/gpu/drm/amd/include/mes_v11_api_def.h @@ -28,6 +28,9 @@ #define MES_API_VERSION 1 +/* Maximum log buffer size for MES. Needs to be updated if MES expands MES_EVT_INTR_HIST_LOG */ +#define AMDGPU_MES_LOG_BUFFER_SIZE 0x4000 + /* Driver submits one API(cmd) as a single Frame and this command size is same * for all API to ease the debugging and parsing of ring buffer. */ diff --git a/drivers/gpu/drm/amd/include/mes_v12_api_def.h b/drivers/gpu/drm/amd/include/mes_v12_api_def.h index ffd67c6ed9b370..101e2fe962c6a6 100644 --- a/drivers/gpu/drm/amd/include/mes_v12_api_def.h +++ b/drivers/gpu/drm/amd/include/mes_v12_api_def.h @@ -28,6 +28,9 @@ #define MES_API_VERSION 0x14 +/* Maximum log buffer size for MES. Needs to be updated if MES expands MES_EVT_INTR_HIST_LOG_12 */ +#define AMDGPU_MES_LOG_BUFFER_SIZE 0xC000 + /* Driver submits one API(cmd) as a single Frame and this command size is same for all API * to ease the debugging and parsing of ring buffer. */ @@ -94,6 +97,7 @@ enum MES_QUEUE_TYPE { MES_QUEUE_TYPE_SDMA, MES_QUEUE_TYPE_MAX, + MES_QUEUE_TYPE_SCHQ = MES_QUEUE_TYPE_MAX, }; struct MES_API_STATUS { @@ -239,8 +243,12 @@ union MESAPI_SET_HW_RESOURCES { uint32_t send_write_data : 1; uint32_t os_tdr_timeout_override : 1; uint32_t use_rs64mem_for_proc_gang_ctx : 1; + uint32_t halt_on_misaligned_access : 1; + uint32_t use_add_queue_unmap_flag_addr : 1; + uint32_t enable_mes_sch_stb_log : 1; + uint32_t limit_single_process : 1; uint32_t unmapped_doorbell_handling: 2; - uint32_t reserved : 15; + uint32_t reserved : 11; }; uint32_t uint32_all; }; diff --git a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c index a1b8a82d77cf9a..8b7d6ed7e2ed23 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c @@ -618,7 +618,8 @@ int amdgpu_pm_load_smu_firmware(struct amdgpu_device *adev, uint32_t *smu_versio const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; int r = 0; - if (!pp_funcs || !pp_funcs->load_firmware || adev->flags & AMD_IS_APU) + if (!pp_funcs || !pp_funcs->load_firmware || + (is_support_sw_smu(adev) && (adev->flags & AMD_IS_APU))) return 0; mutex_lock(&adev->pm.mutex); diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/ppevvmath.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/ppevvmath.h index 6f54c410c2f985..409aeec6baa921 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/ppevvmath.h +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/ppevvmath.h @@ -22,12 +22,18 @@ */ #include -#define SHIFT_AMOUNT 16 /* We multiply all original integers with 2^SHIFT_AMOUNT to get the fInt representation */ +enum ppevvmath_constants { + /* We multiply all original integers with 2^SHIFT_AMOUNT to get the fInt representation */ + SHIFT_AMOUNT = 16, -#define PRECISION 5 /* Change this value to change the number of decimal places in the final output - 5 is a good default */ + /* Change this value to change the number of decimal places in the final output - 5 is a good default */ + PRECISION = 5, -#define SHIFTED_2 (2 << SHIFT_AMOUNT) -#define MAX (1 << (SHIFT_AMOUNT - 1)) - 1 /* 32767 - Might change in the future */ + SHIFTED_2 = (2 << SHIFT_AMOUNT), + + /* 32767 - Might change in the future */ + MAX = (1 << (SHIFT_AMOUNT - 1)) - 1, +}; /* ------------------------------------------------------------------------------- * NEW TYPE - fINT diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v14_0_2_pptable.h b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v14_0_2_pptable.h index 4a3fde89aed731..75c921e87360eb 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v14_0_2_pptable.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v14_0_2_pptable.h @@ -27,7 +27,8 @@ #pragma pack(push, 1) -#define SMU_14_0_2_TABLE_FORMAT_REVISION 3 +#define SMU_14_0_2_TABLE_FORMAT_REVISION 23 +#define SMU_14_0_2_CUSTOM_TABLE_FORMAT_REVISION 1 // POWERPLAYTABLE::ulPlatformCaps #define SMU_14_0_2_PP_PLATFORM_CAP_POWERPLAY 0x1 // This cap indicates whether CCC need to show Powerplay page. @@ -43,6 +44,7 @@ #define SMU_14_0_2_PP_THERMALCONTROLLER_NONE 0 #define SMU_14_0_2_PP_OVERDRIVE_VERSION 0x1 // TODO: FIX OverDrive Version TBD +#define SMU_14_0_2_PP_CUSTOM_OVERDRIVE_VERSION 0x1 #define SMU_14_0_2_PP_POWERSAVINGCLOCK_VERSION 0x01 // Power Saving Clock Table Version 1.00 enum SMU_14_0_2_OD_SW_FEATURE_CAP @@ -107,6 +109,7 @@ enum SMU_14_0_2_PWRMODE_SETTING SMU_14_0_2_PMSETTING_ACOUSTIC_LIMIT_RPM_BALANCE, SMU_14_0_2_PMSETTING_ACOUSTIC_LIMIT_RPM_TURBO, SMU_14_0_2_PMSETTING_ACOUSTIC_LIMIT_RPM_RAGE, + SMU_14_0_2_PMSETTING_COUNT }; #define SMU_14_0_2_MAX_PMSETTING 32 // Maximum Number of PowerMode Settings @@ -127,17 +130,24 @@ struct smu_14_0_2_overdrive_table int16_t pm_setting[SMU_14_0_2_MAX_PMSETTING]; // Optimized power mode feature settings }; +enum smu_14_0_3_pptable_source { + PPTABLE_SOURCE_IFWI = 0, + PPTABLE_SOURCE_DRIVER_HARDCODED = 1, + PPTABLE_SOURCE_PPGEN_REGISTRY = 2, + PPTABLE_SOURCE_MAX = PPTABLE_SOURCE_PPGEN_REGISTRY, +}; + struct smu_14_0_2_powerplay_table { struct atom_common_table_header header; // header.format_revision = 3 (HAS TO MATCH SMU_14_0_2_TABLE_FORMAT_REVISION), header.content_revision = ? structuresize is calculated by PPGen. uint8_t table_revision; // PPGen use only: table_revision = 3 - uint8_t padding; // Padding 1 byte to align table_size offset to 6 bytes (pmfw_start_offset, for PMFW to know the starting offset of PPTable_t). + uint8_t pptable_source; // PPGen UI dropdown box uint16_t pmfw_pptable_start_offset; // The start offset of the pmfw portion. i.e. start of PPTable_t (start of SkuTable_t) uint16_t pmfw_pptable_size; // The total size of pmfw_pptable, i.e PPTable_t. - uint16_t pmfw_pfe_table_start_offset; // The start offset of the PFE_Settings_t within pmfw_pptable. - uint16_t pmfw_pfe_table_size; // The size of PFE_Settings_t. - uint16_t pmfw_board_table_start_offset; // The start offset of the BoardTable_t within pmfw_pptable. - uint16_t pmfw_board_table_size; // The size of BoardTable_t. + uint16_t pmfw_sku_table_start_offset; // DO NOT CHANGE ORDER; The absolute start offset of the SkuTable_t (within smu_14_0_3_powerplay_table). + uint16_t pmfw_sku_table_size; // DO NOT CHANGE ORDER; The size of SkuTable_t. + uint16_t pmfw_board_table_start_offset; // The start offset of the BoardTable_t + uint16_t pmfw_board_table_size; // The size of BoardTable_t. uint16_t pmfw_custom_sku_table_start_offset; // The start offset of the CustomSkuTable_t within pmfw_pptable. uint16_t pmfw_custom_sku_table_size; // The size of the CustomSkuTable_t. uint32_t golden_pp_id; // PPGen use only: PP Table ID on the Golden Data Base @@ -159,6 +169,36 @@ struct smu_14_0_2_powerplay_table PPTable_t smc_pptable; // PPTable_t in driver_if.h -- as requested by PMFW, this offset should start at a 32-byte boundary, and the table_size above should remain at offset=6 bytes }; +enum SMU_14_0_2_CUSTOM_OD_SW_FEATURE_CAP { + SMU_14_0_2_CUSTOM_ODCAP_POWER_MODE = 0, + SMU_14_0_2_CUSTOM_ODCAP_COUNT +}; + +enum SMU_14_0_2_CUSTOM_OD_FEATURE_SETTING_ID { + SMU_14_0_2_CUSTOM_ODSETTING_POWER_MODE = 0, + SMU_14_0_2_CUSTOM_ODSETTING_COUNT, +}; + +struct smu_14_0_2_custom_overdrive_table { + uint8_t revision; + uint8_t reserve[3]; + uint8_t cap[SMU_14_0_2_CUSTOM_ODCAP_COUNT]; + int32_t max[SMU_14_0_2_CUSTOM_ODSETTING_COUNT]; + int32_t min[SMU_14_0_2_CUSTOM_ODSETTING_COUNT]; + int16_t pm_setting[SMU_14_0_2_PMSETTING_COUNT]; +}; + +struct smu_14_0_3_custom_powerplay_table { + uint8_t custom_table_revision; + uint16_t custom_table_size; + uint16_t custom_sku_table_offset; + uint32_t custom_platform_caps; + uint16_t software_shutdown_temp; + struct smu_14_0_2_custom_overdrive_table custom_overdrive_table; + uint32_t reserve[8]; + CustomSkuTable_t custom_sku_table_pmfw; +}; + #pragma pack(pop) #endif 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 98ea58d792ca18..e1a27903c80a14 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 @@ -66,6 +66,7 @@ #define MP0_MP1_DATA_REGION_SIZE_COMBOPPTABLE 0x4000 #define DEBUGSMC_MSG_Mode1Reset 2 +#define LINK_SPEED_MAX 3 static struct cmn2asic_msg_mapping smu_v14_0_2_message_map[SMU_MSG_MAX_COUNT] = { MSG_MAP(TestMessage, PPSMC_MSG_TestMessage, 1), @@ -221,7 +222,6 @@ static struct cmn2asic_mapping smu_v14_0_2_workload_map[PP_SMC_POWER_PROFILE_COU WORKLOAD_MAP(PP_SMC_POWER_PROFILE_WINDOW3D, WORKLOAD_PPLIB_WINDOW_3D_BIT), }; -#if 0 static const uint8_t smu_v14_0_2_throttler_map[] = { [THROTTLER_PPT0_BIT] = (SMU_THROTTLER_PPT0_BIT), [THROTTLER_PPT1_BIT] = (SMU_THROTTLER_PPT1_BIT), @@ -241,7 +241,6 @@ static const uint8_t smu_v14_0_2_throttler_map[] = { [THROTTLER_GFX_APCC_PLUS_BIT] = (SMU_THROTTLER_APCC_BIT), [THROTTLER_FIT_BIT] = (SMU_THROTTLER_FIT_BIT), }; -#endif static int smu_v14_0_2_get_allowed_feature_mask(struct smu_context *smu, @@ -1869,6 +1868,88 @@ static ssize_t smu_v14_0_2_get_ecc_info(struct smu_context *smu, return ret; } +static ssize_t smu_v14_0_2_get_gpu_metrics(struct smu_context *smu, + void **table) +{ + struct smu_table_context *smu_table = &smu->smu_table; + struct gpu_metrics_v1_3 *gpu_metrics = + (struct gpu_metrics_v1_3 *)smu_table->gpu_metrics_table; + SmuMetricsExternal_t metrics_ext; + SmuMetrics_t *metrics = &metrics_ext.SmuMetrics; + int ret = 0; + + ret = smu_cmn_get_metrics_table(smu, + &metrics_ext, + true); + if (ret) + return ret; + + smu_cmn_init_soft_gpu_metrics(gpu_metrics, 1, 3); + + gpu_metrics->temperature_edge = metrics->AvgTemperature[TEMP_EDGE]; + gpu_metrics->temperature_hotspot = metrics->AvgTemperature[TEMP_HOTSPOT]; + gpu_metrics->temperature_mem = metrics->AvgTemperature[TEMP_MEM]; + gpu_metrics->temperature_vrgfx = metrics->AvgTemperature[TEMP_VR_GFX]; + gpu_metrics->temperature_vrsoc = metrics->AvgTemperature[TEMP_VR_SOC]; + gpu_metrics->temperature_vrmem = max(metrics->AvgTemperature[TEMP_VR_MEM0], + metrics->AvgTemperature[TEMP_VR_MEM1]); + + gpu_metrics->average_gfx_activity = metrics->AverageGfxActivity; + gpu_metrics->average_umc_activity = metrics->AverageUclkActivity; + gpu_metrics->average_mm_activity = max(metrics->Vcn0ActivityPercentage, + metrics->Vcn1ActivityPercentage); + + gpu_metrics->average_socket_power = metrics->AverageSocketPower; + gpu_metrics->energy_accumulator = metrics->EnergyAccumulator; + + if (metrics->AverageGfxActivity <= SMU_14_0_2_BUSY_THRESHOLD) + gpu_metrics->average_gfxclk_frequency = metrics->AverageGfxclkFrequencyPostDs; + else + gpu_metrics->average_gfxclk_frequency = metrics->AverageGfxclkFrequencyPreDs; + + if (metrics->AverageUclkActivity <= SMU_14_0_2_BUSY_THRESHOLD) + gpu_metrics->average_uclk_frequency = metrics->AverageMemclkFrequencyPostDs; + else + gpu_metrics->average_uclk_frequency = metrics->AverageMemclkFrequencyPreDs; + + gpu_metrics->average_vclk0_frequency = metrics->AverageVclk0Frequency; + gpu_metrics->average_dclk0_frequency = metrics->AverageDclk0Frequency; + gpu_metrics->average_vclk1_frequency = metrics->AverageVclk1Frequency; + gpu_metrics->average_dclk1_frequency = metrics->AverageDclk1Frequency; + + gpu_metrics->current_gfxclk = gpu_metrics->average_gfxclk_frequency; + gpu_metrics->current_socclk = metrics->CurrClock[PPCLK_SOCCLK]; + gpu_metrics->current_uclk = metrics->CurrClock[PPCLK_UCLK]; + gpu_metrics->current_vclk0 = metrics->CurrClock[PPCLK_VCLK_0]; + gpu_metrics->current_dclk0 = metrics->CurrClock[PPCLK_DCLK_0]; + gpu_metrics->current_vclk1 = metrics->CurrClock[PPCLK_VCLK_0]; + gpu_metrics->current_dclk1 = metrics->CurrClock[PPCLK_DCLK_0]; + + gpu_metrics->throttle_status = + smu_v14_0_2_get_throttler_status(metrics); + gpu_metrics->indep_throttle_status = + smu_cmn_get_indep_throttler_status(gpu_metrics->throttle_status, + smu_v14_0_2_throttler_map); + + gpu_metrics->current_fan_speed = metrics->AvgFanRpm; + + gpu_metrics->pcie_link_width = metrics->PcieWidth; + if ((metrics->PcieRate - 1) > LINK_SPEED_MAX) + gpu_metrics->pcie_link_speed = pcie_gen_to_speed(1); + else + gpu_metrics->pcie_link_speed = pcie_gen_to_speed(metrics->PcieRate); + + gpu_metrics->system_clock_counter = ktime_get_boottime_ns(); + + gpu_metrics->voltage_gfx = metrics->AvgVoltage[SVI_PLANE_VDD_GFX]; + gpu_metrics->voltage_soc = metrics->AvgVoltage[SVI_PLANE_VDD_SOC]; + gpu_metrics->voltage_mem = metrics->AvgVoltage[SVI_PLANE_VDDIO_MEM]; + + *table = (void *)gpu_metrics; + + return sizeof(struct gpu_metrics_v1_3); +} + static const struct pptable_funcs smu_v14_0_2_ppt_funcs = { .get_allowed_feature_mask = smu_v14_0_2_get_allowed_feature_mask, .set_default_dpm_table = smu_v14_0_2_set_default_dpm_table, @@ -1905,6 +1986,7 @@ static const struct pptable_funcs smu_v14_0_2_ppt_funcs = { .enable_thermal_alert = smu_v14_0_enable_thermal_alert, .disable_thermal_alert = smu_v14_0_disable_thermal_alert, .notify_memory_pool_location = smu_v14_0_notify_memory_pool_location, + .get_gpu_metrics = smu_v14_0_2_get_gpu_metrics, .set_soft_freq_limited_range = smu_v14_0_set_soft_freq_limited_range, .init_pptable_microcode = smu_v14_0_init_pptable_microcode, .populate_umd_state_clk = smu_v14_0_2_populate_umd_state_clk, diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c index 88eefef05faedc..91ad434bcdaeb4 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c @@ -794,7 +794,7 @@ static const char *smu_get_feature_name(struct smu_context *smu, size_t smu_cmn_get_pp_feature_mask(struct smu_context *smu, char *buf) { - int8_t sort_feature[max(SMU_FEATURE_COUNT, SMU_FEATURE_MAX)]; + int8_t sort_feature[MAX(SMU_FEATURE_COUNT, SMU_FEATURE_MAX)]; uint64_t feature_mask; int i, feature_index; uint32_t count = 0; diff --git a/drivers/gpu/drm/ast/ast_dp.c b/drivers/gpu/drm/ast/ast_dp.c index 1e9259416980ec..e6c7f0d64e9959 100644 --- a/drivers/gpu/drm/ast/ast_dp.c +++ b/drivers/gpu/drm/ast/ast_dp.c @@ -158,7 +158,14 @@ void ast_dp_launch(struct drm_device *dev) ASTDP_HOST_EDID_READ_DONE); } +bool ast_dp_power_is_on(struct ast_device *ast) +{ + u8 vgacre3; + + vgacre3 = ast_get_index_reg(ast, AST_IO_VGACRI, 0xe3); + return !(vgacre3 & AST_DP_PHY_SLEEP); +} void ast_dp_power_on_off(struct drm_device *dev, bool on) { diff --git a/drivers/gpu/drm/ast/ast_drv.c b/drivers/gpu/drm/ast/ast_drv.c index aae019e79bda88..225817087b4d2f 100644 --- a/drivers/gpu/drm/ast/ast_drv.c +++ b/drivers/gpu/drm/ast/ast_drv.c @@ -391,6 +391,11 @@ static int ast_drm_freeze(struct drm_device *dev) static int ast_drm_thaw(struct drm_device *dev) { + struct ast_device *ast = to_ast_device(dev); + + ast_enable_vga(ast->ioregs); + ast_open_key(ast->ioregs); + ast_enable_mmio(dev->dev, ast->ioregs); ast_post_gpu(dev); return drm_mode_config_helper_resume(dev); diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h index ba3d86973995fd..47bab5596c16ed 100644 --- a/drivers/gpu/drm/ast/ast_drv.h +++ b/drivers/gpu/drm/ast/ast_drv.h @@ -472,6 +472,7 @@ void ast_init_3rdtx(struct drm_device *dev); bool ast_astdp_is_connected(struct ast_device *ast); int ast_astdp_read_edid(struct drm_device *dev, u8 *ediddata); void ast_dp_launch(struct drm_device *dev); +bool ast_dp_power_is_on(struct ast_device *ast); void ast_dp_power_on_off(struct drm_device *dev, bool no); void ast_dp_set_on_off(struct drm_device *dev, bool no); void ast_dp_set_mode(struct drm_crtc *crtc, struct ast_vbios_mode_info *vbios_mode); diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index dc8f639e82fdf5..049ee1477c3375 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -28,6 +28,7 @@ * Authors: Dave Airlie */ +#include #include #include @@ -1687,11 +1688,35 @@ static int ast_astdp_connector_helper_detect_ctx(struct drm_connector *connector struct drm_modeset_acquire_ctx *ctx, bool force) { + struct drm_device *dev = connector->dev; struct ast_device *ast = to_ast_device(connector->dev); + enum drm_connector_status status = connector_status_disconnected; + struct drm_connector_state *connector_state = connector->state; + bool is_active = false; + + mutex_lock(&ast->modeset_lock); + + if (connector_state && connector_state->crtc) { + struct drm_crtc_state *crtc_state = connector_state->crtc->state; + + if (crtc_state && crtc_state->active) + is_active = true; + } + + if (!is_active && !ast_dp_power_is_on(ast)) { + ast_dp_power_on_off(dev, true); + msleep(50); + } if (ast_astdp_is_connected(ast)) - return connector_status_connected; - return connector_status_disconnected; + status = connector_status_connected; + + if (!is_active && status == connector_status_disconnected) + ast_dp_power_on_off(dev, false); + + mutex_unlock(&ast->modeset_lock); + + return status; } static const struct drm_connector_helper_funcs ast_astdp_connector_helper_funcs = { diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c index 22bbb2d83e3073..7936c202395518 100644 --- a/drivers/gpu/drm/drm_atomic_uapi.c +++ b/drivers/gpu/drm/drm_atomic_uapi.c @@ -1070,21 +1070,17 @@ int drm_atomic_set_property(struct drm_atomic_state *state, break; } - if (async_flip && prop != config->prop_fb_id) { + if (async_flip && + (plane_state->plane->type != DRM_PLANE_TYPE_PRIMARY || + (prop != config->prop_fb_id && + prop != config->prop_in_fence_fd && + prop != config->prop_fb_damage_clips))) { ret = drm_atomic_plane_get_property(plane, plane_state, prop, &old_val); ret = drm_atomic_check_prop_changes(ret, old_val, prop_value, prop); break; } - if (async_flip && plane_state->plane->type != DRM_PLANE_TYPE_PRIMARY) { - drm_dbg_atomic(prop->dev, - "[OBJECT:%d] Only primary planes can be changed during async flip\n", - obj->id); - ret = -EINVAL; - break; - } - ret = drm_atomic_plane_set_property(plane, plane_state, file_priv, prop, prop_value); diff --git a/drivers/gpu/drm/drm_bridge_connector.c b/drivers/gpu/drm/drm_bridge_connector.c index 0869b663f17e4d..a4fbf1eb7ac5a8 100644 --- a/drivers/gpu/drm/drm_bridge_connector.c +++ b/drivers/gpu/drm/drm_bridge_connector.c @@ -443,10 +443,8 @@ struct drm_connector *drm_bridge_connector_init(struct drm_device *drm, panel_bridge = bridge; } - if (connector_type == DRM_MODE_CONNECTOR_Unknown) { - kfree(bridge_connector); + if (connector_type == DRM_MODE_CONNECTOR_Unknown) return ERR_PTR(-EINVAL); - } if (bridge_connector->bridge_hdmi) ret = drmm_connector_hdmi_init(drm, connector, @@ -461,10 +459,8 @@ struct drm_connector *drm_bridge_connector_init(struct drm_device *drm, ret = drmm_connector_init(drm, connector, &drm_bridge_connector_funcs, connector_type, ddc); - if (ret) { - kfree(bridge_connector); + if (ret) return ERR_PTR(ret); - } drm_connector_helper_add(connector, &drm_bridge_connector_helper_funcs); diff --git a/drivers/gpu/drm/drm_buddy.c b/drivers/gpu/drm/drm_buddy.c index 6a8e45e9d0ecc1..103c185bb1c8a7 100644 --- a/drivers/gpu/drm/drm_buddy.c +++ b/drivers/gpu/drm/drm_buddy.c @@ -851,6 +851,7 @@ static int __alloc_contig_try_harder(struct drm_buddy *mm, * drm_buddy_block_trim - free unused pages * * @mm: DRM buddy manager + * @start: start address to begin the trimming. * @new_size: original size requested * @blocks: Input and output list of allocated blocks. * MUST contain single block as input to be trimmed. @@ -866,11 +867,13 @@ static int __alloc_contig_try_harder(struct drm_buddy *mm, * 0 on success, error code on failure. */ int drm_buddy_block_trim(struct drm_buddy *mm, + u64 *start, u64 new_size, struct list_head *blocks) { struct drm_buddy_block *parent; struct drm_buddy_block *block; + u64 block_start, block_end; LIST_HEAD(dfs); u64 new_start; int err; @@ -882,6 +885,9 @@ int drm_buddy_block_trim(struct drm_buddy *mm, struct drm_buddy_block, link); + block_start = drm_buddy_block_offset(block); + block_end = block_start + drm_buddy_block_size(mm, block); + if (WARN_ON(!drm_buddy_block_is_allocated(block))) return -EINVAL; @@ -894,6 +900,20 @@ int drm_buddy_block_trim(struct drm_buddy *mm, if (new_size == drm_buddy_block_size(mm, block)) return 0; + new_start = block_start; + if (start) { + new_start = *start; + + if (new_start < block_start) + return -EINVAL; + + if (!IS_ALIGNED(new_start, mm->chunk_size)) + return -EINVAL; + + if (range_overflows(new_start, new_size, block_end)) + return -EINVAL; + } + list_del(&block->link); mark_free(mm, block); mm->avail += drm_buddy_block_size(mm, block); @@ -904,7 +924,6 @@ int drm_buddy_block_trim(struct drm_buddy *mm, parent = block->parent; block->parent = NULL; - new_start = drm_buddy_block_offset(block); list_add(&block->tmp_link, &dfs); err = __alloc_range(mm, &dfs, new_start, new_size, blocks, NULL); if (err) { @@ -1066,7 +1085,8 @@ int drm_buddy_alloc_blocks(struct drm_buddy *mm, } while (1); /* Trim the allocated block to the required size */ - if (original_size != size) { + if (!(flags & DRM_BUDDY_TRIM_DISABLE) && + original_size != size) { struct list_head *trim_list; LIST_HEAD(temp); u64 trim_size; @@ -1083,6 +1103,7 @@ int drm_buddy_alloc_blocks(struct drm_buddy *mm, } drm_buddy_block_trim(mm, + NULL, trim_size, trim_list); diff --git a/drivers/gpu/drm/drm_client.c b/drivers/gpu/drm/drm_client.c index 2803ac111bbd8a..bfedcbf516dbe2 100644 --- a/drivers/gpu/drm/drm_client.c +++ b/drivers/gpu/drm/drm_client.c @@ -355,7 +355,7 @@ int drm_client_buffer_vmap_local(struct drm_client_buffer *buffer, err_drm_gem_vmap_unlocked: drm_gem_unlock(gem); - return 0; + return ret; } EXPORT_SYMBOL(drm_client_buffer_vmap_local); diff --git a/drivers/gpu/drm/drm_client_modeset.c b/drivers/gpu/drm/drm_client_modeset.c index 31af5cf37a0998..cee5eafbfb81a8 100644 --- a/drivers/gpu/drm/drm_client_modeset.c +++ b/drivers/gpu/drm/drm_client_modeset.c @@ -880,6 +880,11 @@ int drm_client_modeset_probe(struct drm_client_dev *client, unsigned int width, kfree(modeset->mode); modeset->mode = drm_mode_duplicate(dev, mode); + if (!modeset->mode) { + ret = -ENOMEM; + break; + } + drm_connector_get(connector); modeset->connectors[modeset->num_connectors++] = connector; modeset->x = offset->x; diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 18565ec6845173..56ac37ea2f2748 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -624,6 +624,17 @@ static void drm_fb_helper_add_damage_clip(struct drm_fb_helper *helper, u32 x, u static void drm_fb_helper_damage(struct drm_fb_helper *helper, u32 x, u32 y, u32 width, u32 height) { + /* + * This function may be invoked by panic() to flush the frame + * buffer, where all CPUs except the panic CPU are stopped. + * During the following schedule_work(), the panic CPU needs + * the worker_pool lock, which might be held by a stopped CPU, + * causing schedule_work() and panic() to block. Return early on + * oops_in_progress to prevent this blocking. + */ + if (oops_in_progress) + return; + drm_fb_helper_add_damage_clip(helper, x, y, width, height); schedule_work(&helper->damage_work); diff --git a/drivers/gpu/drm/drm_panel_orientation_quirks.c b/drivers/gpu/drm/drm_panel_orientation_quirks.c index 3f84d7527793ef..0830cae9a4d0f5 100644 --- a/drivers/gpu/drm/drm_panel_orientation_quirks.c +++ b/drivers/gpu/drm/drm_panel_orientation_quirks.c @@ -208,6 +208,18 @@ static const struct dmi_system_id orientation_data[] = { DMI_MATCH(DMI_BOARD_NAME, "KUN"), }, .driver_data = (void *)&lcd1600x2560_rightside_up, + }, { /* AYN Loki Max */ + .matches = { + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ayn"), + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Loki Max"), + }, + .driver_data = (void *)&lcd1080x1920_leftside_up, + }, { /* AYN Loki Zero */ + .matches = { + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ayn"), + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Loki Zero"), + }, + .driver_data = (void *)&lcd1080x1920_leftside_up, }, { /* Chuwi HiBook (CWI514) */ .matches = { DMI_MATCH(DMI_BOARD_VENDOR, "Hampoo"), @@ -414,6 +426,12 @@ static const struct dmi_system_id orientation_data[] = { DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "ONE XPLAYER"), }, .driver_data = (void *)&lcd1600x2560_leftside_up, + }, { /* OrangePi Neo */ + .matches = { + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "OrangePi"), + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "NEO-01"), + }, + .driver_data = (void *)&lcd1200x1920_rightside_up, }, { /* Samsung GalaxyBook 10.6 */ .matches = { DMI_EXACT_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."), diff --git a/drivers/gpu/drm/i915/display/intel_backlight.c b/drivers/gpu/drm/i915/display/intel_backlight.c index 071668bfe5d14e..6c3333136737e7 100644 --- a/drivers/gpu/drm/i915/display/intel_backlight.c +++ b/drivers/gpu/drm/i915/display/intel_backlight.c @@ -1449,6 +1449,9 @@ bxt_setup_backlight(struct intel_connector *connector, enum pipe unused) static int cnp_num_backlight_controllers(struct drm_i915_private *i915) { + if (INTEL_PCH_TYPE(i915) >= PCH_MTL) + return 2; + if (INTEL_PCH_TYPE(i915) >= PCH_DG1) return 1; diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index 90998b037349d3..292d163036b12a 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -1658,7 +1658,7 @@ static void skl_wrpll_params_populate(struct skl_wrpll_params *params, } static int -skl_ddi_calculate_wrpll(int clock /* in Hz */, +skl_ddi_calculate_wrpll(int clock, int ref_clock, struct skl_wrpll_params *wrpll_params) { @@ -1683,7 +1683,7 @@ skl_ddi_calculate_wrpll(int clock /* in Hz */, }; unsigned int dco, d, i; unsigned int p0, p1, p2; - u64 afe_clock = clock * 5; /* AFE Clock is 5x Pixel clock */ + u64 afe_clock = (u64)clock * 1000 * 5; /* AFE Clock is 5x Pixel clock, in Hz */ for (d = 0; d < ARRAY_SIZE(dividers); d++) { for (dco = 0; dco < ARRAY_SIZE(dco_central_freq); dco++) { @@ -1808,7 +1808,7 @@ static int skl_ddi_hdmi_pll_dividers(struct intel_crtc_state *crtc_state) struct skl_wrpll_params wrpll_params = {}; int ret; - ret = skl_ddi_calculate_wrpll(crtc_state->port_clock * 1000, + ret = skl_ddi_calculate_wrpll(crtc_state->port_clock, i915->display.dpll.ref_clks.nssc, &wrpll_params); if (ret) return ret; diff --git a/drivers/gpu/drm/i915/display/intel_hdcp_regs.h b/drivers/gpu/drm/i915/display/intel_hdcp_regs.h index a568a457e53268..f590d7f48ba74f 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp_regs.h +++ b/drivers/gpu/drm/i915/display/intel_hdcp_regs.h @@ -251,7 +251,7 @@ #define HDCP2_STREAM_STATUS(dev_priv, trans, port) \ (TRANS_HDCP(dev_priv) ? \ TRANS_HDCP2_STREAM_STATUS(trans) : \ - PIPE_HDCP2_STREAM_STATUS(pipe)) + PIPE_HDCP2_STREAM_STATUS(port)) #define _PORTA_HDCP2_AUTH_STREAM 0x66F00 #define _PORTB_HDCP2_AUTH_STREAM 0x66F04 diff --git a/drivers/gpu/drm/i915/display/intel_pps.c b/drivers/gpu/drm/i915/display/intel_pps.c index 42306bc4ba864a..7ce926241e83a2 100644 --- a/drivers/gpu/drm/i915/display/intel_pps.c +++ b/drivers/gpu/drm/i915/display/intel_pps.c @@ -351,6 +351,9 @@ static int intel_num_pps(struct drm_i915_private *i915) if (IS_GEMINILAKE(i915) || IS_BROXTON(i915)) return 2; + if (INTEL_PCH_TYPE(i915) >= PCH_MTL) + return 2; + if (INTEL_PCH_TYPE(i915) >= PCH_DG1) return 1; diff --git a/drivers/gpu/drm/i915/gem/i915_gem_mman.c b/drivers/gpu/drm/i915/gem/i915_gem_mman.c index a2195e28b625fe..cac6d4184506cc 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_mman.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_mman.c @@ -290,6 +290,41 @@ static vm_fault_t vm_fault_cpu(struct vm_fault *vmf) return i915_error_to_vmf_fault(err); } +static void set_address_limits(struct vm_area_struct *area, + struct i915_vma *vma, + unsigned long obj_offset, + unsigned long *start_vaddr, + unsigned long *end_vaddr) +{ + unsigned long vm_start, vm_end, vma_size; /* user's memory parameters */ + long start, end; /* memory boundaries */ + + /* + * Let's move into the ">> PAGE_SHIFT" + * domain to be sure not to lose bits + */ + vm_start = area->vm_start >> PAGE_SHIFT; + vm_end = area->vm_end >> PAGE_SHIFT; + vma_size = vma->size >> PAGE_SHIFT; + + /* + * Calculate the memory boundaries by considering the offset + * provided by the user during memory mapping and the offset + * provided for the partial mapping. + */ + start = vm_start; + start -= obj_offset; + start += vma->gtt_view.partial.offset; + end = start + vma_size; + + start = max_t(long, start, vm_start); + end = min_t(long, end, vm_end); + + /* Let's move back into the "<< PAGE_SHIFT" domain */ + *start_vaddr = (unsigned long)start << PAGE_SHIFT; + *end_vaddr = (unsigned long)end << PAGE_SHIFT; +} + static vm_fault_t vm_fault_gtt(struct vm_fault *vmf) { #define MIN_CHUNK_PAGES (SZ_1M >> PAGE_SHIFT) @@ -302,14 +337,18 @@ static vm_fault_t vm_fault_gtt(struct vm_fault *vmf) struct i915_ggtt *ggtt = to_gt(i915)->ggtt; bool write = area->vm_flags & VM_WRITE; struct i915_gem_ww_ctx ww; + unsigned long obj_offset; + unsigned long start, end; /* memory boundaries */ intel_wakeref_t wakeref; struct i915_vma *vma; pgoff_t page_offset; + unsigned long pfn; int srcu; int ret; - /* We don't use vmf->pgoff since that has the fake offset */ + obj_offset = area->vm_pgoff - drm_vma_node_start(&mmo->vma_node); page_offset = (vmf->address - area->vm_start) >> PAGE_SHIFT; + page_offset += obj_offset; trace_i915_gem_object_fault(obj, page_offset, true, write); @@ -402,12 +441,14 @@ static vm_fault_t vm_fault_gtt(struct vm_fault *vmf) if (ret) goto err_unpin; + set_address_limits(area, vma, obj_offset, &start, &end); + + pfn = (ggtt->gmadr.start + i915_ggtt_offset(vma)) >> PAGE_SHIFT; + pfn += (start - area->vm_start) >> PAGE_SHIFT; + pfn += obj_offset - vma->gtt_view.partial.offset; + /* Finally, remap it using the new GTT offset */ - ret = remap_io_mapping(area, - area->vm_start + (vma->gtt_view.partial.offset << PAGE_SHIFT), - (ggtt->gmadr.start + i915_ggtt_offset(vma)) >> PAGE_SHIFT, - min_t(u64, vma->size, area->vm_end - area->vm_start), - &ggtt->iomap); + ret = remap_io_mapping(area, start, pfn, end - start, &ggtt->iomap); if (ret) goto err_fence; @@ -1084,6 +1125,8 @@ int i915_gem_fb_mmap(struct drm_i915_gem_object *obj, struct vm_area_struct *vma mmo = mmap_offset_attach(obj, mmap_type, NULL); if (IS_ERR(mmo)) return PTR_ERR(mmo); + + vma->vm_pgoff += drm_vma_node_start(&mmo->vma_node); } /* diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c index e6f177183c0fa7..5c72462d1f57e3 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c @@ -165,7 +165,6 @@ i915_ttm_placement_from_obj(const struct drm_i915_gem_object *obj, i915_ttm_place_from_region(num_allowed ? obj->mm.placements[0] : obj->mm.region, &places[0], obj->bo_offset, obj->base.size, flags); - places[0].flags |= TTM_PL_FLAG_DESIRED; /* Cache this on object? */ for (i = 0; i < num_allowed; ++i) { @@ -779,13 +778,16 @@ static int __i915_ttm_get_pages(struct drm_i915_gem_object *obj, .interruptible = true, .no_wait_gpu = false, }; - int real_num_busy; + struct ttm_placement initial_placement; + struct ttm_place initial_place; int ret; /* First try only the requested placement. No eviction. */ - real_num_busy = placement->num_placement; - placement->num_placement = 1; - ret = ttm_bo_validate(bo, placement, &ctx); + initial_placement.num_placement = 1; + memcpy(&initial_place, placement->placement, sizeof(struct ttm_place)); + initial_place.flags |= TTM_PL_FLAG_DESIRED; + initial_placement.placement = &initial_place; + ret = ttm_bo_validate(bo, &initial_placement, &ctx); if (ret) { ret = i915_ttm_err_to_gem(ret); /* @@ -800,7 +802,6 @@ static int __i915_ttm_get_pages(struct drm_i915_gem_object *obj, * If the initial attempt fails, allow all accepted placements, * evicting if necessary. */ - placement->num_placement = real_num_busy; ret = ttm_bo_validate(bo, placement, &ctx); if (ret) return i915_ttm_err_to_gem(ret); diff --git a/drivers/gpu/drm/i915/i915_perf.c b/drivers/gpu/drm/i915/i915_perf.c index 0b1cd4c7a525f4..025a79fe5920e4 100644 --- a/drivers/gpu/drm/i915/i915_perf.c +++ b/drivers/gpu/drm/i915/i915_perf.c @@ -2748,26 +2748,6 @@ oa_configure_all_contexts(struct i915_perf_stream *stream, return 0; } -static int -gen12_configure_all_contexts(struct i915_perf_stream *stream, - const struct i915_oa_config *oa_config, - struct i915_active *active) -{ - struct flex regs[] = { - { - GEN8_R_PWR_CLK_STATE(RENDER_RING_BASE), - CTX_R_PWR_CLK_STATE, - }, - }; - - if (stream->engine->class != RENDER_CLASS) - return 0; - - return oa_configure_all_contexts(stream, - regs, ARRAY_SIZE(regs), - active); -} - static int lrc_configure_all_contexts(struct i915_perf_stream *stream, const struct i915_oa_config *oa_config, @@ -2874,7 +2854,6 @@ gen12_enable_metric_set(struct i915_perf_stream *stream, { struct drm_i915_private *i915 = stream->perf->i915; struct intel_uncore *uncore = stream->uncore; - struct i915_oa_config *oa_config = stream->oa_config; bool periodic = stream->periodic; u32 period_exponent = stream->period_exponent; u32 sqcnt1; @@ -2918,15 +2897,6 @@ gen12_enable_metric_set(struct i915_perf_stream *stream, intel_uncore_rmw(uncore, GEN12_SQCNT1, 0, sqcnt1); - /* - * Update all contexts prior writing the mux configurations as we need - * to make sure all slices/subslices are ON before writing to NOA - * registers. - */ - ret = gen12_configure_all_contexts(stream, oa_config, active); - if (ret) - return ret; - /* * For Gen12, performance counters are context * saved/restored. Only enable it for the context that @@ -2980,9 +2950,6 @@ static void gen12_disable_metric_set(struct i915_perf_stream *stream) _MASKED_BIT_DISABLE(GEN12_DISABLE_DOP_GATING)); } - /* Reset all contexts' slices/subslices configurations. */ - gen12_configure_all_contexts(stream, NULL, NULL); - /* disable the context save/restore or OAR counters */ if (stream->ctx) gen12_configure_oar_context(stream, NULL); diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c index ae5c6ec24a1e61..77b50c56c124ce 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c @@ -539,8 +539,8 @@ static int mtk_drm_kms_init(struct drm_device *drm) } /* IGT will check if the cursor size is configured */ - drm->mode_config.cursor_width = drm->mode_config.max_width; - drm->mode_config.cursor_height = drm->mode_config.max_height; + drm->mode_config.cursor_width = 512; + drm->mode_config.cursor_height = 512; /* Use OVL device for all DMA memory allocations */ crtc = drm_crtc_from_index(drm, 0); diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 0712d0b1517026..70fb003a66669a 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -898,7 +898,7 @@ nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict, * Without this the operation can timeout and we'll fallback to a * software copy, which might take several minutes to finish. */ - nouveau_fence_wait(fence, false); + nouveau_fence_wait(fence, false, false); ret = ttm_bo_move_accel_cleanup(bo, &fence->base, evict, false, new_reg); nouveau_fence_unref(&fence); diff --git a/drivers/gpu/drm/nouveau/nouveau_chan.c b/drivers/gpu/drm/nouveau/nouveau_chan.c index 66fca95c10c761..7c97b288680760 100644 --- a/drivers/gpu/drm/nouveau/nouveau_chan.c +++ b/drivers/gpu/drm/nouveau/nouveau_chan.c @@ -72,7 +72,7 @@ nouveau_channel_idle(struct nouveau_channel *chan) ret = nouveau_fence_new(&fence, chan); if (!ret) { - ret = nouveau_fence_wait(fence, false); + ret = nouveau_fence_wait(fence, false, false); nouveau_fence_unref(&fence); } diff --git a/drivers/gpu/drm/nouveau/nouveau_dmem.c b/drivers/gpu/drm/nouveau/nouveau_dmem.c index 6719353e2e13f9..6fb65b01d77804 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dmem.c +++ b/drivers/gpu/drm/nouveau/nouveau_dmem.c @@ -128,7 +128,7 @@ static void nouveau_dmem_page_free(struct page *page) static void nouveau_dmem_fence_done(struct nouveau_fence **fence) { if (fence) { - nouveau_fence_wait(*fence, false); + nouveau_fence_wait(*fence, true, false); nouveau_fence_unref(fence); } else { /* diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c index ba469767a20fd9..93f08f9479d89b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fence.c +++ b/drivers/gpu/drm/nouveau/nouveau_fence.c @@ -311,11 +311,39 @@ nouveau_fence_wait_legacy(struct dma_fence *f, bool intr, long wait) return timeout - t; } +static int +nouveau_fence_wait_busy(struct nouveau_fence *fence, bool intr) +{ + int ret = 0; + + while (!nouveau_fence_done(fence)) { + if (time_after_eq(jiffies, fence->timeout)) { + ret = -EBUSY; + break; + } + + __set_current_state(intr ? + TASK_INTERRUPTIBLE : + TASK_UNINTERRUPTIBLE); + + if (intr && signal_pending(current)) { + ret = -ERESTARTSYS; + break; + } + } + + __set_current_state(TASK_RUNNING); + return ret; +} + int -nouveau_fence_wait(struct nouveau_fence *fence, bool intr) +nouveau_fence_wait(struct nouveau_fence *fence, bool lazy, bool intr) { long ret; + if (!lazy) + return nouveau_fence_wait_busy(fence, intr); + ret = dma_fence_wait_timeout(&fence->base, intr, 15 * HZ); if (ret < 0) return ret; diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.h b/drivers/gpu/drm/nouveau/nouveau_fence.h index 1b63197b744a20..8bc065acfe3587 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fence.h +++ b/drivers/gpu/drm/nouveau/nouveau_fence.h @@ -23,7 +23,7 @@ void nouveau_fence_unref(struct nouveau_fence **); int nouveau_fence_emit(struct nouveau_fence *); bool nouveau_fence_done(struct nouveau_fence *); -int nouveau_fence_wait(struct nouveau_fence *, bool intr); +int nouveau_fence_wait(struct nouveau_fence *, bool lazy, bool intr); int nouveau_fence_sync(struct nouveau_bo *, struct nouveau_channel *, bool exclusive, bool intr); struct nouveau_fence_chan { diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index 2e535caa7d6ea2..5a887d67dc0e8c 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c @@ -928,7 +928,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, } if (sync) { - if (!(ret = nouveau_fence_wait(fence, false))) { + if (!(ret = nouveau_fence_wait(fence, false, false))) { if ((ret = dma_fence_get_status(&fence->base)) == 1) ret = 0; } diff --git a/drivers/gpu/drm/nouveau/nouveau_prime.c b/drivers/gpu/drm/nouveau/nouveau_prime.c index b58ab595faf827..cd95446d685111 100644 --- a/drivers/gpu/drm/nouveau/nouveau_prime.c +++ b/drivers/gpu/drm/nouveau/nouveau_prime.c @@ -64,7 +64,8 @@ struct drm_gem_object *nouveau_gem_prime_import_sg_table(struct drm_device *dev, * to the caller, instead of a normal nouveau_bo ttm reference. */ ret = drm_gem_object_init(dev, &nvbo->bo.base, size); if (ret) { - nouveau_bo_ref(NULL, &nvbo); + drm_gem_object_release(&nvbo->bo.base); + kfree(nvbo); obj = ERR_PTR(-ENOMEM); goto unlock; } diff --git a/drivers/gpu/drm/nouveau/nouveau_uvmm.c b/drivers/gpu/drm/nouveau/nouveau_uvmm.c index 9402fa320a7e9d..48f105239f42d8 100644 --- a/drivers/gpu/drm/nouveau/nouveau_uvmm.c +++ b/drivers/gpu/drm/nouveau/nouveau_uvmm.c @@ -1803,6 +1803,7 @@ nouveau_uvmm_bo_validate(struct drm_gpuvm_bo *vm_bo, struct drm_exec *exec) { struct nouveau_bo *nvbo = nouveau_gem_object(vm_bo->obj); + nouveau_bo_placement_set(nvbo, nvbo->valid_domains, 0); return nouveau_bo_validate(nvbo, true, false); } diff --git a/drivers/gpu/drm/omapdrm/Kconfig b/drivers/gpu/drm/omapdrm/Kconfig index 3f7139e211d21b..64e440a2649b01 100644 --- a/drivers/gpu/drm/omapdrm/Kconfig +++ b/drivers/gpu/drm/omapdrm/Kconfig @@ -1,6 +1,7 @@ # SPDX-License-Identifier: GPL-2.0-only config DRM_OMAP tristate "OMAP DRM" + depends on MMU depends on DRM && OF depends on ARCH_OMAP2PLUS || (COMPILE_TEST && PAGE_SIZE_LESS_THAN_64KB) select DRM_KMS_HELPER diff --git a/drivers/gpu/drm/radeon/evergreen_cs.c b/drivers/gpu/drm/radeon/evergreen_cs.c index 1fe6e0d883c79b..e5577d2a19ef49 100644 --- a/drivers/gpu/drm/radeon/evergreen_cs.c +++ b/drivers/gpu/drm/radeon/evergreen_cs.c @@ -33,8 +33,10 @@ #include "evergreen_reg_safe.h" #include "cayman_reg_safe.h" +#ifndef MIN #define MAX(a, b) (((a) > (b)) ? (a) : (b)) #define MIN(a, b) (((a) < (b)) ? (a) : (b)) +#endif #define REG_SAFE_BM_SIZE ARRAY_SIZE(evergreen_reg_safe_bm) diff --git a/drivers/gpu/drm/rockchip/inno_hdmi.c b/drivers/gpu/drm/rockchip/inno_hdmi.c index 2241e53a294690..dec6913cec5b59 100644 --- a/drivers/gpu/drm/rockchip/inno_hdmi.c +++ b/drivers/gpu/drm/rockchip/inno_hdmi.c @@ -279,7 +279,6 @@ static int inno_hdmi_upload_frame(struct drm_connector *connector, const u8 *buffer, size_t len) { struct inno_hdmi *hdmi = connector_to_inno_hdmi(connector); - u8 packed_frame[HDMI_MAXIMUM_INFO_FRAME_SIZE]; ssize_t i; if (type != HDMI_INFOFRAME_TYPE_AVI) { @@ -291,8 +290,7 @@ static int inno_hdmi_upload_frame(struct drm_connector *connector, inno_hdmi_disable_frame(connector, type); for (i = 0; i < len; i++) - hdmi_writeb(hdmi, HDMI_CONTROL_PACKET_ADDR + i, - packed_frame[i]); + hdmi_writeb(hdmi, HDMI_CONTROL_PACKET_ADDR + i, buffer[i]); return 0; } diff --git a/drivers/gpu/drm/tests/drm_gem_shmem_test.c b/drivers/gpu/drm/tests/drm_gem_shmem_test.c index c3758faa1b83a3..d8d0e4d1682fca 100644 --- a/drivers/gpu/drm/tests/drm_gem_shmem_test.c +++ b/drivers/gpu/drm/tests/drm_gem_shmem_test.c @@ -102,6 +102,17 @@ static void drm_gem_shmem_test_obj_create_private(struct kunit *test) sg_init_one(sgt->sgl, buf, TEST_SIZE); + /* + * Set the DMA mask to 64-bits and map the sgtables + * otherwise drm_gem_shmem_free will cause a warning + * on debug kernels. + */ + ret = dma_set_mask(drm_dev->dev, DMA_BIT_MASK(64)); + KUNIT_ASSERT_EQ(test, ret, 0); + + ret = dma_map_sgtable(drm_dev->dev, sgt, DMA_BIDIRECTIONAL, 0); + KUNIT_ASSERT_EQ(test, ret, 0); + /* Init a mock DMA-BUF */ buf_mock.size = TEST_SIZE; attach_mock.dmabuf = &buf_mock; diff --git a/drivers/gpu/drm/v3d/v3d_drv.h b/drivers/gpu/drm/v3d/v3d_drv.h index 49089eefb7c7d1..a0febdb6f21452 100644 --- a/drivers/gpu/drm/v3d/v3d_drv.h +++ b/drivers/gpu/drm/v3d/v3d_drv.h @@ -565,6 +565,10 @@ void v3d_mmu_insert_ptes(struct v3d_bo *bo); void v3d_mmu_remove_ptes(struct v3d_bo *bo); /* v3d_sched.c */ +void v3d_timestamp_query_info_free(struct v3d_timestamp_query_info *query_info, + unsigned int count); +void v3d_performance_query_info_free(struct v3d_performance_query_info *query_info, + unsigned int count); void v3d_job_update_stats(struct v3d_job *job, enum v3d_queue queue); int v3d_sched_init(struct v3d_dev *v3d); void v3d_sched_fini(struct v3d_dev *v3d); diff --git a/drivers/gpu/drm/v3d/v3d_sched.c b/drivers/gpu/drm/v3d/v3d_sched.c index 271a6d0f5aca78..b8682818bafa6c 100644 --- a/drivers/gpu/drm/v3d/v3d_sched.c +++ b/drivers/gpu/drm/v3d/v3d_sched.c @@ -73,24 +73,44 @@ v3d_sched_job_free(struct drm_sched_job *sched_job) v3d_job_cleanup(job); } +void +v3d_timestamp_query_info_free(struct v3d_timestamp_query_info *query_info, + unsigned int count) +{ + if (query_info->queries) { + unsigned int i; + + for (i = 0; i < count; i++) + drm_syncobj_put(query_info->queries[i].syncobj); + + kvfree(query_info->queries); + } +} + +void +v3d_performance_query_info_free(struct v3d_performance_query_info *query_info, + unsigned int count) +{ + if (query_info->queries) { + unsigned int i; + + for (i = 0; i < count; i++) + drm_syncobj_put(query_info->queries[i].syncobj); + + kvfree(query_info->queries); + } +} + static void v3d_cpu_job_free(struct drm_sched_job *sched_job) { struct v3d_cpu_job *job = to_cpu_job(sched_job); - struct v3d_timestamp_query_info *timestamp_query = &job->timestamp_query; - struct v3d_performance_query_info *performance_query = &job->performance_query; - if (timestamp_query->queries) { - for (int i = 0; i < timestamp_query->count; i++) - drm_syncobj_put(timestamp_query->queries[i].syncobj); - kvfree(timestamp_query->queries); - } + v3d_timestamp_query_info_free(&job->timestamp_query, + job->timestamp_query.count); - if (performance_query->queries) { - for (int i = 0; i < performance_query->count; i++) - drm_syncobj_put(performance_query->queries[i].syncobj); - kvfree(performance_query->queries); - } + v3d_performance_query_info_free(&job->performance_query, + job->performance_query.count); v3d_job_cleanup(&job->base); } @@ -295,7 +315,7 @@ v3d_csd_job_run(struct drm_sched_job *sched_job) struct v3d_dev *v3d = job->base.v3d; struct drm_device *dev = &v3d->drm; struct dma_fence *fence; - int i, csd_cfg0_reg, csd_cfg_reg_count; + int i, csd_cfg0_reg; v3d->csd_job = job; @@ -315,9 +335,17 @@ v3d_csd_job_run(struct drm_sched_job *sched_job) v3d_switch_perfmon(v3d, &job->base); csd_cfg0_reg = V3D_CSD_QUEUED_CFG0(v3d->ver); - csd_cfg_reg_count = v3d->ver < 71 ? 6 : 7; - for (i = 1; i <= csd_cfg_reg_count; i++) + for (i = 1; i <= 6; i++) V3D_CORE_WRITE(0, csd_cfg0_reg + 4 * i, job->args.cfg[i]); + + /* Although V3D 7.1 has an eighth configuration register, we are not + * using it. Therefore, make sure it remains unused. + * + * XXX: Set the CFG7 register + */ + if (v3d->ver >= 71) + V3D_CORE_WRITE(0, V3D_V7_CSD_QUEUED_CFG7, 0); + /* CFG0 write kicks off the job. */ V3D_CORE_WRITE(0, csd_cfg0_reg, job->args.cfg[0]); diff --git a/drivers/gpu/drm/v3d/v3d_submit.c b/drivers/gpu/drm/v3d/v3d_submit.c index 88f63d526b2236..4cdfabbf4964f9 100644 --- a/drivers/gpu/drm/v3d/v3d_submit.c +++ b/drivers/gpu/drm/v3d/v3d_submit.c @@ -452,6 +452,8 @@ v3d_get_cpu_timestamp_query_params(struct drm_file *file_priv, { u32 __user *offsets, *syncs; struct drm_v3d_timestamp_query timestamp; + unsigned int i; + int err; if (!job) { DRM_DEBUG("CPU job extension was attached to a GPU job.\n"); @@ -480,26 +482,34 @@ v3d_get_cpu_timestamp_query_params(struct drm_file *file_priv, offsets = u64_to_user_ptr(timestamp.offsets); syncs = u64_to_user_ptr(timestamp.syncs); - for (int i = 0; i < timestamp.count; i++) { + for (i = 0; i < timestamp.count; i++) { u32 offset, sync; if (copy_from_user(&offset, offsets++, sizeof(offset))) { - kvfree(job->timestamp_query.queries); - return -EFAULT; + err = -EFAULT; + goto error; } job->timestamp_query.queries[i].offset = offset; if (copy_from_user(&sync, syncs++, sizeof(sync))) { - kvfree(job->timestamp_query.queries); - return -EFAULT; + err = -EFAULT; + goto error; } job->timestamp_query.queries[i].syncobj = drm_syncobj_find(file_priv, sync); + if (!job->timestamp_query.queries[i].syncobj) { + err = -ENOENT; + goto error; + } } job->timestamp_query.count = timestamp.count; return 0; + +error: + v3d_timestamp_query_info_free(&job->timestamp_query, i); + return err; } static int @@ -509,6 +519,8 @@ v3d_get_cpu_reset_timestamp_params(struct drm_file *file_priv, { u32 __user *syncs; struct drm_v3d_reset_timestamp_query reset; + unsigned int i; + int err; if (!job) { DRM_DEBUG("CPU job extension was attached to a GPU job.\n"); @@ -533,21 +545,29 @@ v3d_get_cpu_reset_timestamp_params(struct drm_file *file_priv, syncs = u64_to_user_ptr(reset.syncs); - for (int i = 0; i < reset.count; i++) { + for (i = 0; i < reset.count; i++) { u32 sync; job->timestamp_query.queries[i].offset = reset.offset + 8 * i; if (copy_from_user(&sync, syncs++, sizeof(sync))) { - kvfree(job->timestamp_query.queries); - return -EFAULT; + err = -EFAULT; + goto error; } job->timestamp_query.queries[i].syncobj = drm_syncobj_find(file_priv, sync); + if (!job->timestamp_query.queries[i].syncobj) { + err = -ENOENT; + goto error; + } } job->timestamp_query.count = reset.count; return 0; + +error: + v3d_timestamp_query_info_free(&job->timestamp_query, i); + return err; } /* Get data for the copy timestamp query results job submission. */ @@ -558,7 +578,8 @@ v3d_get_cpu_copy_query_results_params(struct drm_file *file_priv, { u32 __user *offsets, *syncs; struct drm_v3d_copy_timestamp_query copy; - int i; + unsigned int i; + int err; if (!job) { DRM_DEBUG("CPU job extension was attached to a GPU job.\n"); @@ -591,18 +612,22 @@ v3d_get_cpu_copy_query_results_params(struct drm_file *file_priv, u32 offset, sync; if (copy_from_user(&offset, offsets++, sizeof(offset))) { - kvfree(job->timestamp_query.queries); - return -EFAULT; + err = -EFAULT; + goto error; } job->timestamp_query.queries[i].offset = offset; if (copy_from_user(&sync, syncs++, sizeof(sync))) { - kvfree(job->timestamp_query.queries); - return -EFAULT; + err = -EFAULT; + goto error; } job->timestamp_query.queries[i].syncobj = drm_syncobj_find(file_priv, sync); + if (!job->timestamp_query.queries[i].syncobj) { + err = -ENOENT; + goto error; + } } job->timestamp_query.count = copy.count; @@ -613,6 +638,10 @@ v3d_get_cpu_copy_query_results_params(struct drm_file *file_priv, job->copy.stride = copy.stride; return 0; + +error: + v3d_timestamp_query_info_free(&job->timestamp_query, i); + return err; } static int @@ -623,6 +652,8 @@ v3d_get_cpu_reset_performance_params(struct drm_file *file_priv, u32 __user *syncs; u64 __user *kperfmon_ids; struct drm_v3d_reset_performance_query reset; + unsigned int i, j; + int err; if (!job) { DRM_DEBUG("CPU job extension was attached to a GPU job.\n"); @@ -637,6 +668,9 @@ v3d_get_cpu_reset_performance_params(struct drm_file *file_priv, if (copy_from_user(&reset, ext, sizeof(reset))) return -EFAULT; + if (reset.nperfmons > V3D_MAX_PERFMONS) + return -EINVAL; + job->job_type = V3D_CPU_JOB_TYPE_RESET_PERFORMANCE_QUERY; job->performance_query.queries = kvmalloc_array(reset.count, @@ -648,39 +682,47 @@ v3d_get_cpu_reset_performance_params(struct drm_file *file_priv, syncs = u64_to_user_ptr(reset.syncs); kperfmon_ids = u64_to_user_ptr(reset.kperfmon_ids); - for (int i = 0; i < reset.count; i++) { + for (i = 0; i < reset.count; i++) { u32 sync; u64 ids; u32 __user *ids_pointer; u32 id; if (copy_from_user(&sync, syncs++, sizeof(sync))) { - kvfree(job->performance_query.queries); - return -EFAULT; + err = -EFAULT; + goto error; } - job->performance_query.queries[i].syncobj = drm_syncobj_find(file_priv, sync); - if (copy_from_user(&ids, kperfmon_ids++, sizeof(ids))) { - kvfree(job->performance_query.queries); - return -EFAULT; + err = -EFAULT; + goto error; } ids_pointer = u64_to_user_ptr(ids); - for (int j = 0; j < reset.nperfmons; j++) { + for (j = 0; j < reset.nperfmons; j++) { if (copy_from_user(&id, ids_pointer++, sizeof(id))) { - kvfree(job->performance_query.queries); - return -EFAULT; + err = -EFAULT; + goto error; } job->performance_query.queries[i].kperfmon_ids[j] = id; } + + job->performance_query.queries[i].syncobj = drm_syncobj_find(file_priv, sync); + if (!job->performance_query.queries[i].syncobj) { + err = -ENOENT; + goto error; + } } job->performance_query.count = reset.count; job->performance_query.nperfmons = reset.nperfmons; return 0; + +error: + v3d_performance_query_info_free(&job->performance_query, i); + return err; } static int @@ -691,6 +733,8 @@ v3d_get_cpu_copy_performance_query_params(struct drm_file *file_priv, u32 __user *syncs; u64 __user *kperfmon_ids; struct drm_v3d_copy_performance_query copy; + unsigned int i, j; + int err; if (!job) { DRM_DEBUG("CPU job extension was attached to a GPU job.\n"); @@ -708,6 +752,9 @@ v3d_get_cpu_copy_performance_query_params(struct drm_file *file_priv, if (copy.pad) return -EINVAL; + if (copy.nperfmons > V3D_MAX_PERFMONS) + return -EINVAL; + job->job_type = V3D_CPU_JOB_TYPE_COPY_PERFORMANCE_QUERY; job->performance_query.queries = kvmalloc_array(copy.count, @@ -719,34 +766,38 @@ v3d_get_cpu_copy_performance_query_params(struct drm_file *file_priv, syncs = u64_to_user_ptr(copy.syncs); kperfmon_ids = u64_to_user_ptr(copy.kperfmon_ids); - for (int i = 0; i < copy.count; i++) { + for (i = 0; i < copy.count; i++) { u32 sync; u64 ids; u32 __user *ids_pointer; u32 id; if (copy_from_user(&sync, syncs++, sizeof(sync))) { - kvfree(job->performance_query.queries); - return -EFAULT; + err = -EFAULT; + goto error; } - job->performance_query.queries[i].syncobj = drm_syncobj_find(file_priv, sync); - if (copy_from_user(&ids, kperfmon_ids++, sizeof(ids))) { - kvfree(job->performance_query.queries); - return -EFAULT; + err = -EFAULT; + goto error; } ids_pointer = u64_to_user_ptr(ids); - for (int j = 0; j < copy.nperfmons; j++) { + for (j = 0; j < copy.nperfmons; j++) { if (copy_from_user(&id, ids_pointer++, sizeof(id))) { - kvfree(job->performance_query.queries); - return -EFAULT; + err = -EFAULT; + goto error; } job->performance_query.queries[i].kperfmon_ids[j] = id; } + + job->performance_query.queries[i].syncobj = drm_syncobj_find(file_priv, sync); + if (!job->performance_query.queries[i].syncobj) { + err = -ENOENT; + goto error; + } } job->performance_query.count = copy.count; job->performance_query.nperfmons = copy.nperfmons; @@ -759,6 +810,10 @@ v3d_get_cpu_copy_performance_query_params(struct drm_file *file_priv, job->copy.stride = copy.stride; return 0; + +error: + v3d_performance_query_info_free(&job->performance_query, i); + return err; } /* Whenever userspace sets ioctl extensions, v3d_get_extensions parses data diff --git a/drivers/gpu/drm/virtio/virtgpu_submit.c b/drivers/gpu/drm/virtio/virtgpu_submit.c index 1c7c7f61a22289..7d34cf83f5f2bb 100644 --- a/drivers/gpu/drm/virtio/virtgpu_submit.c +++ b/drivers/gpu/drm/virtio/virtgpu_submit.c @@ -48,7 +48,7 @@ struct virtio_gpu_submit { static int virtio_gpu_do_fence_wait(struct virtio_gpu_submit *submit, struct dma_fence *in_fence) { - u32 context = submit->fence_ctx + submit->ring_idx; + u64 context = submit->fence_ctx + submit->ring_idx; if (dma_fence_match_context(in_fence, context)) return 0; diff --git a/drivers/gpu/drm/vmwgfx/vmw_surface_cache.h b/drivers/gpu/drm/vmwgfx/vmw_surface_cache.h index b0d87c5f58d8ed..1ac3cb151b117e 100644 --- a/drivers/gpu/drm/vmwgfx/vmw_surface_cache.h +++ b/drivers/gpu/drm/vmwgfx/vmw_surface_cache.h @@ -1,6 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0 OR MIT */ /********************************************************** - * Copyright 2021 VMware, Inc. - * SPDX-License-Identifier: GPL-2.0 OR MIT + * + * Copyright (c) 2021-2024 Broadcom. All Rights Reserved. The term + * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -31,6 +33,10 @@ #include +#define SVGA3D_FLAGS_UPPER_32(svga3d_flags) ((svga3d_flags) >> 32) +#define SVGA3D_FLAGS_LOWER_32(svga3d_flags) \ + ((svga3d_flags) & ((uint64_t)U32_MAX)) + static inline u32 clamped_umul32(u32 a, u32 b) { uint64_t tmp = (uint64_t) a*b; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c index 00144632c600eb..f42ebc4a7c2255 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c @@ -1,8 +1,8 @@ // SPDX-License-Identifier: GPL-2.0 OR MIT /************************************************************************** * - * Copyright © 2011-2023 VMware, Inc., Palo Alto, CA., USA - * All Rights Reserved. + * Copyright (c) 2011-2024 Broadcom. All Rights Reserved. The term + * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the @@ -28,15 +28,39 @@ #include "vmwgfx_bo.h" #include "vmwgfx_drv.h" - +#include "vmwgfx_resource_priv.h" #include static void vmw_bo_release(struct vmw_bo *vbo) { + struct vmw_resource *res; + WARN_ON(vbo->tbo.base.funcs && kref_read(&vbo->tbo.base.refcount) != 0); vmw_bo_unmap(vbo); + + xa_destroy(&vbo->detached_resources); + WARN_ON(vbo->is_dumb && !vbo->dumb_surface); + if (vbo->is_dumb && vbo->dumb_surface) { + res = &vbo->dumb_surface->res; + WARN_ON(vbo != res->guest_memory_bo); + WARN_ON(!res->guest_memory_bo); + if (res->guest_memory_bo) { + /* Reserve and switch the backing mob. */ + mutex_lock(&res->dev_priv->cmdbuf_mutex); + (void)vmw_resource_reserve(res, false, true); + vmw_resource_mob_detach(res); + if (res->coherent) + vmw_bo_dirty_release(res->guest_memory_bo); + res->guest_memory_bo = NULL; + res->guest_memory_offset = 0; + vmw_resource_unreserve(res, false, false, false, NULL, + 0); + mutex_unlock(&res->dev_priv->cmdbuf_mutex); + } + vmw_surface_unreference(&vbo->dumb_surface); + } drm_gem_object_release(&vbo->tbo.base); } @@ -325,6 +349,11 @@ void vmw_bo_pin_reserved(struct vmw_bo *vbo, bool pin) * */ void *vmw_bo_map_and_cache(struct vmw_bo *vbo) +{ + return vmw_bo_map_and_cache_size(vbo, vbo->tbo.base.size); +} + +void *vmw_bo_map_and_cache_size(struct vmw_bo *vbo, size_t size) { struct ttm_buffer_object *bo = &vbo->tbo; bool not_used; @@ -335,9 +364,10 @@ void *vmw_bo_map_and_cache(struct vmw_bo *vbo) if (virtual) return virtual; - ret = ttm_bo_kmap(bo, 0, PFN_UP(bo->base.size), &vbo->map); + ret = ttm_bo_kmap(bo, 0, PFN_UP(size), &vbo->map); if (ret) - DRM_ERROR("Buffer object map failed: %d.\n", ret); + DRM_ERROR("Buffer object map failed: %d (size: bo = %zu, map = %zu).\n", + ret, bo->base.size, size); return ttm_kmap_obj_virtual(&vbo->map, ¬_used); } @@ -390,6 +420,7 @@ static int vmw_bo_init(struct vmw_private *dev_priv, BUILD_BUG_ON(TTM_MAX_BO_PRIORITY <= 3); vmw_bo->tbo.priority = 3; vmw_bo->res_tree = RB_ROOT; + xa_init(&vmw_bo->detached_resources); params->size = ALIGN(params->size, PAGE_SIZE); drm_gem_private_object_init(vdev, &vmw_bo->tbo.base, params->size); @@ -654,52 +685,6 @@ void vmw_bo_fence_single(struct ttm_buffer_object *bo, dma_fence_put(&fence->base); } - -/** - * vmw_dumb_create - Create a dumb kms buffer - * - * @file_priv: Pointer to a struct drm_file identifying the caller. - * @dev: Pointer to the drm device. - * @args: Pointer to a struct drm_mode_create_dumb structure - * Return: Zero on success, negative error code on failure. - * - * This is a driver callback for the core drm create_dumb functionality. - * Note that this is very similar to the vmw_bo_alloc ioctl, except - * that the arguments have a different format. - */ -int vmw_dumb_create(struct drm_file *file_priv, - struct drm_device *dev, - struct drm_mode_create_dumb *args) -{ - struct vmw_private *dev_priv = vmw_priv(dev); - struct vmw_bo *vbo; - int cpp = DIV_ROUND_UP(args->bpp, 8); - int ret; - - switch (cpp) { - case 1: /* DRM_FORMAT_C8 */ - case 2: /* DRM_FORMAT_RGB565 */ - case 4: /* DRM_FORMAT_XRGB8888 */ - break; - default: - /* - * Dumb buffers don't allow anything else. - * This is tested via IGT's dumb_buffers - */ - return -EINVAL; - } - - args->pitch = args->width * cpp; - args->size = ALIGN(args->pitch * args->height, PAGE_SIZE); - - ret = vmw_gem_object_create_with_handle(dev_priv, file_priv, - args->size, &args->handle, - &vbo); - /* drop reference from allocate - handle holds it now */ - drm_gem_object_put(&vbo->tbo.base); - return ret; -} - /** * vmw_bo_swap_notify - swapout notify callback. * @@ -853,3 +838,43 @@ void vmw_bo_placement_set_default_accelerated(struct vmw_bo *bo) vmw_bo_placement_set(bo, domain, domain); } + +void vmw_bo_add_detached_resource(struct vmw_bo *vbo, struct vmw_resource *res) +{ + xa_store(&vbo->detached_resources, (unsigned long)res, res, GFP_KERNEL); +} + +void vmw_bo_del_detached_resource(struct vmw_bo *vbo, struct vmw_resource *res) +{ + xa_erase(&vbo->detached_resources, (unsigned long)res); +} + +struct vmw_surface *vmw_bo_surface(struct vmw_bo *vbo) +{ + unsigned long index; + struct vmw_resource *res = NULL; + struct vmw_surface *surf = NULL; + struct rb_node *rb_itr = vbo->res_tree.rb_node; + + if (vbo->is_dumb && vbo->dumb_surface) { + res = &vbo->dumb_surface->res; + goto out; + } + + xa_for_each(&vbo->detached_resources, index, res) { + if (res->func->res_type == vmw_res_surface) + goto out; + } + + for (rb_itr = rb_first(&vbo->res_tree); rb_itr; + rb_itr = rb_next(rb_itr)) { + res = rb_entry(rb_itr, struct vmw_resource, mob_node); + if (res->func->res_type == vmw_res_surface) + goto out; + } + +out: + if (res) + surf = vmw_res_to_srf(res); + return surf; +} diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.h b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.h index f349642e6190d6..62b4342d5f7c50 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.h @@ -1,7 +1,8 @@ /* SPDX-License-Identifier: GPL-2.0 OR MIT */ /************************************************************************** * - * Copyright 2023 VMware, Inc., Palo Alto, CA., USA + * Copyright (c) 2023-2024 Broadcom. All Rights Reserved. The term + * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the @@ -35,11 +36,13 @@ #include #include +#include struct vmw_bo_dirty; struct vmw_fence_obj; struct vmw_private; struct vmw_resource; +struct vmw_surface; enum vmw_bo_domain { VMW_BO_DOMAIN_SYS = BIT(0), @@ -85,11 +88,15 @@ struct vmw_bo { struct rb_root res_tree; u32 res_prios[TTM_MAX_BO_PRIORITY]; + struct xarray detached_resources; atomic_t cpu_writers; /* Not ref-counted. Protected by binding_mutex */ struct vmw_resource *dx_query_ctx; struct vmw_bo_dirty *dirty; + + bool is_dumb; + struct vmw_surface *dumb_surface; }; void vmw_bo_placement_set(struct vmw_bo *bo, u32 domain, u32 busy_domain); @@ -124,15 +131,21 @@ void vmw_bo_fence_single(struct ttm_buffer_object *bo, struct vmw_fence_obj *fence); void *vmw_bo_map_and_cache(struct vmw_bo *vbo); +void *vmw_bo_map_and_cache_size(struct vmw_bo *vbo, size_t size); void vmw_bo_unmap(struct vmw_bo *vbo); void vmw_bo_move_notify(struct ttm_buffer_object *bo, struct ttm_resource *mem); void vmw_bo_swap_notify(struct ttm_buffer_object *bo); +void vmw_bo_add_detached_resource(struct vmw_bo *vbo, struct vmw_resource *res); +void vmw_bo_del_detached_resource(struct vmw_bo *vbo, struct vmw_resource *res); +struct vmw_surface *vmw_bo_surface(struct vmw_bo *vbo); + int vmw_user_bo_lookup(struct drm_file *filp, u32 handle, struct vmw_bo **out); + /** * vmw_bo_adjust_prio - Adjust the buffer object eviction priority * according to attached resources diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index a1ce41e1c4684e..32f50e59580972 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h @@ -1,7 +1,8 @@ /* SPDX-License-Identifier: GPL-2.0 OR MIT */ /************************************************************************** * - * Copyright 2009-2023 VMware, Inc., Palo Alto, CA., USA + * Copyright (c) 2009-2024 Broadcom. All Rights Reserved. The term + * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the @@ -762,6 +763,26 @@ extern int vmw_gmr_bind(struct vmw_private *dev_priv, int gmr_id); extern void vmw_gmr_unbind(struct vmw_private *dev_priv, int gmr_id); +/** + * User handles + */ +struct vmw_user_object { + struct vmw_surface *surface; + struct vmw_bo *buffer; +}; + +int vmw_user_object_lookup(struct vmw_private *dev_priv, struct drm_file *filp, + u32 handle, struct vmw_user_object *uo); +struct vmw_user_object *vmw_user_object_ref(struct vmw_user_object *uo); +void vmw_user_object_unref(struct vmw_user_object *uo); +bool vmw_user_object_is_null(struct vmw_user_object *uo); +struct vmw_surface *vmw_user_object_surface(struct vmw_user_object *uo); +struct vmw_bo *vmw_user_object_buffer(struct vmw_user_object *uo); +void *vmw_user_object_map(struct vmw_user_object *uo); +void *vmw_user_object_map_size(struct vmw_user_object *uo, size_t size); +void vmw_user_object_unmap(struct vmw_user_object *uo); +bool vmw_user_object_is_mapped(struct vmw_user_object *uo); + /** * Resource utilities - vmwgfx_resource.c */ @@ -776,11 +797,6 @@ extern int vmw_resource_validate(struct vmw_resource *res, bool intr, extern int vmw_resource_reserve(struct vmw_resource *res, bool interruptible, bool no_backup); extern bool vmw_resource_needs_backup(const struct vmw_resource *res); -extern int vmw_user_lookup_handle(struct vmw_private *dev_priv, - struct drm_file *filp, - uint32_t handle, - struct vmw_surface **out_surf, - struct vmw_bo **out_buf); extern int vmw_user_resource_lookup_handle( struct vmw_private *dev_priv, struct ttm_object_file *tfile, @@ -1057,9 +1073,6 @@ int vmw_kms_suspend(struct drm_device *dev); int vmw_kms_resume(struct drm_device *dev); void vmw_kms_lost_device(struct drm_device *dev); -int vmw_dumb_create(struct drm_file *file_priv, - struct drm_device *dev, - struct drm_mode_create_dumb *args); extern int vmw_resource_pin(struct vmw_resource *res, bool interruptible); extern void vmw_resource_unpin(struct vmw_resource *res); extern enum vmw_res_type vmw_res_type(const struct vmw_resource *res); @@ -1176,6 +1189,15 @@ extern int vmw_gb_surface_reference_ext_ioctl(struct drm_device *dev, int vmw_gb_surface_define(struct vmw_private *dev_priv, const struct vmw_surface_metadata *req, struct vmw_surface **srf_out); +struct vmw_surface *vmw_lookup_surface_for_buffer(struct vmw_private *vmw, + struct vmw_bo *bo, + u32 handle); +u32 vmw_lookup_surface_handle_for_buffer(struct vmw_private *vmw, + struct vmw_bo *bo, + u32 handle); +int vmw_dumb_create(struct drm_file *file_priv, + struct drm_device *dev, + struct drm_mode_create_dumb *args); /* * Shader management - vmwgfx_shader.c diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c index 5efc6a766f64e4..588d50ababf604 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c @@ -32,7 +32,6 @@ #define VMW_FENCE_WRAP (1 << 31) struct vmw_fence_manager { - int num_fence_objects; struct vmw_private *dev_priv; spinlock_t lock; struct list_head fence_list; @@ -124,13 +123,13 @@ static void vmw_fence_obj_destroy(struct dma_fence *f) { struct vmw_fence_obj *fence = container_of(f, struct vmw_fence_obj, base); - struct vmw_fence_manager *fman = fman_from_fence(fence); - spin_lock(&fman->lock); - list_del_init(&fence->head); - --fman->num_fence_objects; - spin_unlock(&fman->lock); + if (!list_empty(&fence->head)) { + spin_lock(&fman->lock); + list_del_init(&fence->head); + spin_unlock(&fman->lock); + } fence->destroy(fence); } @@ -257,7 +256,6 @@ static const struct dma_fence_ops vmw_fence_ops = { .release = vmw_fence_obj_destroy, }; - /* * Execute signal actions on fences recently signaled. * This is done from a workqueue so we don't have to execute @@ -355,7 +353,6 @@ static int vmw_fence_obj_init(struct vmw_fence_manager *fman, goto out_unlock; } list_add_tail(&fence->head, &fman->fence_list); - ++fman->num_fence_objects; out_unlock: spin_unlock(&fman->lock); @@ -403,7 +400,7 @@ static bool vmw_fence_goal_new_locked(struct vmw_fence_manager *fman, u32 passed_seqno) { u32 goal_seqno; - struct vmw_fence_obj *fence; + struct vmw_fence_obj *fence, *next_fence; if (likely(!fman->seqno_valid)) return false; @@ -413,7 +410,7 @@ static bool vmw_fence_goal_new_locked(struct vmw_fence_manager *fman, return false; fman->seqno_valid = false; - list_for_each_entry(fence, &fman->fence_list, head) { + list_for_each_entry_safe(fence, next_fence, &fman->fence_list, head) { if (!list_empty(&fence->seq_passed_actions)) { fman->seqno_valid = true; vmw_fence_goal_write(fman->dev_priv, diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_gem.c b/drivers/gpu/drm/vmwgfx/vmwgfx_gem.c index 07185c108218fc..b9857f37ca1ac6 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_gem.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_gem.c @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 OR MIT */ /* - * Copyright 2021-2023 VMware, Inc. + * Copyright (c) 2021-2024 Broadcom. All Rights Reserved. The term + * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -78,6 +79,59 @@ static struct sg_table *vmw_gem_object_get_sg_table(struct drm_gem_object *obj) return drm_prime_pages_to_sg(obj->dev, vmw_tt->dma_ttm.pages, vmw_tt->dma_ttm.num_pages); } +static int vmw_gem_vmap(struct drm_gem_object *obj, struct iosys_map *map) +{ + struct ttm_buffer_object *bo = drm_gem_ttm_of_gem(obj); + int ret; + + if (obj->import_attach) { + ret = dma_buf_vmap(obj->import_attach->dmabuf, map); + if (!ret) { + if (drm_WARN_ON(obj->dev, map->is_iomem)) { + dma_buf_vunmap(obj->import_attach->dmabuf, map); + return -EIO; + } + } + } else { + ret = ttm_bo_vmap(bo, map); + } + + return ret; +} + +static void vmw_gem_vunmap(struct drm_gem_object *obj, struct iosys_map *map) +{ + if (obj->import_attach) + dma_buf_vunmap(obj->import_attach->dmabuf, map); + else + drm_gem_ttm_vunmap(obj, map); +} + +static int vmw_gem_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma) +{ + int ret; + + if (obj->import_attach) { + /* + * Reset both vm_ops and vm_private_data, so we don't end up with + * vm_ops pointing to our implementation if the dma-buf backend + * doesn't set those fields. + */ + vma->vm_private_data = NULL; + vma->vm_ops = NULL; + + ret = dma_buf_mmap(obj->dma_buf, vma, 0); + + /* Drop the reference drm_gem_mmap_obj() acquired.*/ + if (!ret) + drm_gem_object_put(obj); + + return ret; + } + + return drm_gem_ttm_mmap(obj, vma); +} + static const struct vm_operations_struct vmw_vm_ops = { .pfn_mkwrite = vmw_bo_vm_mkwrite, .page_mkwrite = vmw_bo_vm_mkwrite, @@ -94,9 +148,9 @@ static const struct drm_gem_object_funcs vmw_gem_object_funcs = { .pin = vmw_gem_object_pin, .unpin = vmw_gem_object_unpin, .get_sg_table = vmw_gem_object_get_sg_table, - .vmap = drm_gem_ttm_vmap, - .vunmap = drm_gem_ttm_vunmap, - .mmap = drm_gem_ttm_mmap, + .vmap = vmw_gem_vmap, + .vunmap = vmw_gem_vunmap, + .mmap = vmw_gem_mmap, .vm_ops = &vmw_vm_ops, }; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index 00c4ff68413012..288ed0bb75cb98 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -1,7 +1,8 @@ // SPDX-License-Identifier: GPL-2.0 OR MIT /************************************************************************** * - * Copyright 2009-2023 VMware, Inc., Palo Alto, CA., USA + * Copyright (c) 2009-2024 Broadcom. All Rights Reserved. The term + * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the @@ -193,13 +194,16 @@ static u32 vmw_du_cursor_mob_size(u32 w, u32 h) */ static u32 *vmw_du_cursor_plane_acquire_image(struct vmw_plane_state *vps) { - if (vps->surf) { - if (vps->surf_mapped) - return vmw_bo_map_and_cache(vps->surf->res.guest_memory_bo); - return vps->surf->snooper.image; - } else if (vps->bo) - return vmw_bo_map_and_cache(vps->bo); - return NULL; + struct vmw_surface *surf; + + if (vmw_user_object_is_null(&vps->uo)) + return NULL; + + surf = vmw_user_object_surface(&vps->uo); + if (surf && !vmw_user_object_is_mapped(&vps->uo)) + return surf->snooper.image; + + return vmw_user_object_map(&vps->uo); } static bool vmw_du_cursor_plane_has_changed(struct vmw_plane_state *old_vps, @@ -536,22 +540,16 @@ void vmw_du_primary_plane_destroy(struct drm_plane *plane) * vmw_du_plane_unpin_surf - unpins resource associated with a framebuffer surface * * @vps: plane state associated with the display surface - * @unreference: true if we also want to unreference the display. */ -void vmw_du_plane_unpin_surf(struct vmw_plane_state *vps, - bool unreference) +void vmw_du_plane_unpin_surf(struct vmw_plane_state *vps) { - if (vps->surf) { + struct vmw_surface *surf = vmw_user_object_surface(&vps->uo); + + if (surf) { if (vps->pinned) { - vmw_resource_unpin(&vps->surf->res); + vmw_resource_unpin(&surf->res); vps->pinned--; } - - if (unreference) { - if (vps->pinned) - DRM_ERROR("Surface still pinned\n"); - vmw_surface_unreference(&vps->surf); - } } } @@ -572,7 +570,7 @@ vmw_du_plane_cleanup_fb(struct drm_plane *plane, { struct vmw_plane_state *vps = vmw_plane_state_to_vps(old_state); - vmw_du_plane_unpin_surf(vps, false); + vmw_du_plane_unpin_surf(vps); } @@ -661,25 +659,14 @@ vmw_du_cursor_plane_cleanup_fb(struct drm_plane *plane, struct vmw_cursor_plane *vcp = vmw_plane_to_vcp(plane); struct vmw_plane_state *vps = vmw_plane_state_to_vps(old_state); - if (vps->surf_mapped) { - vmw_bo_unmap(vps->surf->res.guest_memory_bo); - vps->surf_mapped = false; - } + if (!vmw_user_object_is_null(&vps->uo)) + vmw_user_object_unmap(&vps->uo); vmw_du_cursor_plane_unmap_cm(vps); vmw_du_put_cursor_mob(vcp, vps); - vmw_du_plane_unpin_surf(vps, false); - - if (vps->surf) { - vmw_surface_unreference(&vps->surf); - vps->surf = NULL; - } - - if (vps->bo) { - vmw_bo_unreference(&vps->bo); - vps->bo = NULL; - } + vmw_du_plane_unpin_surf(vps); + vmw_user_object_unref(&vps->uo); } @@ -698,64 +685,48 @@ vmw_du_cursor_plane_prepare_fb(struct drm_plane *plane, struct drm_framebuffer *fb = new_state->fb; struct vmw_cursor_plane *vcp = vmw_plane_to_vcp(plane); struct vmw_plane_state *vps = vmw_plane_state_to_vps(new_state); + struct vmw_bo *bo = NULL; int ret = 0; - if (vps->surf) { - if (vps->surf_mapped) { - vmw_bo_unmap(vps->surf->res.guest_memory_bo); - vps->surf_mapped = false; - } - vmw_surface_unreference(&vps->surf); - vps->surf = NULL; - } - - if (vps->bo) { - vmw_bo_unreference(&vps->bo); - vps->bo = NULL; + if (!vmw_user_object_is_null(&vps->uo)) { + vmw_user_object_unmap(&vps->uo); + vmw_user_object_unref(&vps->uo); } if (fb) { if (vmw_framebuffer_to_vfb(fb)->bo) { - vps->bo = vmw_framebuffer_to_vfbd(fb)->buffer; - vmw_bo_reference(vps->bo); + vps->uo.buffer = vmw_framebuffer_to_vfbd(fb)->buffer; + vps->uo.surface = NULL; } else { - vps->surf = vmw_framebuffer_to_vfbs(fb)->surface; - vmw_surface_reference(vps->surf); + memcpy(&vps->uo, &vmw_framebuffer_to_vfbs(fb)->uo, sizeof(vps->uo)); } + vmw_user_object_ref(&vps->uo); } - if (!vps->surf && vps->bo) { - const u32 size = new_state->crtc_w * new_state->crtc_h * sizeof(u32); + bo = vmw_user_object_buffer(&vps->uo); + if (bo) { + struct ttm_operation_ctx ctx = {false, false}; - /* - * Not using vmw_bo_map_and_cache() helper here as we need to - * reserve the ttm_buffer_object first which - * vmw_bo_map_and_cache() omits. - */ - ret = ttm_bo_reserve(&vps->bo->tbo, true, false, NULL); - - if (unlikely(ret != 0)) + ret = ttm_bo_reserve(&bo->tbo, true, false, NULL); + if (ret != 0) return -ENOMEM; - ret = ttm_bo_kmap(&vps->bo->tbo, 0, PFN_UP(size), &vps->bo->map); - - ttm_bo_unreserve(&vps->bo->tbo); - - if (unlikely(ret != 0)) + ret = ttm_bo_validate(&bo->tbo, &bo->placement, &ctx); + if (ret != 0) return -ENOMEM; - } else if (vps->surf && !vps->bo && vps->surf->res.guest_memory_bo) { - WARN_ON(vps->surf->snooper.image); - ret = ttm_bo_reserve(&vps->surf->res.guest_memory_bo->tbo, true, false, - NULL); - if (unlikely(ret != 0)) - return -ENOMEM; - vmw_bo_map_and_cache(vps->surf->res.guest_memory_bo); - ttm_bo_unreserve(&vps->surf->res.guest_memory_bo->tbo); - vps->surf_mapped = true; + vmw_bo_pin_reserved(bo, true); + if (vmw_framebuffer_to_vfb(fb)->bo) { + const u32 size = new_state->crtc_w * new_state->crtc_h * sizeof(u32); + + (void)vmw_bo_map_and_cache_size(bo, size); + } else { + vmw_bo_map_and_cache(bo); + } + ttm_bo_unreserve(&bo->tbo); } - if (vps->surf || vps->bo) { + if (!vmw_user_object_is_null(&vps->uo)) { vmw_du_get_cursor_mob(vcp, vps); vmw_du_cursor_plane_map_cm(vps); } @@ -777,14 +748,17 @@ vmw_du_cursor_plane_atomic_update(struct drm_plane *plane, struct vmw_display_unit *du = vmw_crtc_to_du(crtc); struct vmw_plane_state *vps = vmw_plane_state_to_vps(new_state); struct vmw_plane_state *old_vps = vmw_plane_state_to_vps(old_state); + struct vmw_bo *old_bo = NULL; + struct vmw_bo *new_bo = NULL; s32 hotspot_x, hotspot_y; + int ret; hotspot_x = du->hotspot_x + new_state->hotspot_x; hotspot_y = du->hotspot_y + new_state->hotspot_y; - du->cursor_surface = vps->surf; + du->cursor_surface = vmw_user_object_surface(&vps->uo); - if (!vps->surf && !vps->bo) { + if (vmw_user_object_is_null(&vps->uo)) { vmw_cursor_update_position(dev_priv, false, 0, 0); return; } @@ -792,10 +766,26 @@ vmw_du_cursor_plane_atomic_update(struct drm_plane *plane, vps->cursor.hotspot_x = hotspot_x; vps->cursor.hotspot_y = hotspot_y; - if (vps->surf) { + if (du->cursor_surface) du->cursor_age = du->cursor_surface->snooper.age; + + if (!vmw_user_object_is_null(&old_vps->uo)) { + old_bo = vmw_user_object_buffer(&old_vps->uo); + ret = ttm_bo_reserve(&old_bo->tbo, false, false, NULL); + if (ret != 0) + return; } + if (!vmw_user_object_is_null(&vps->uo)) { + new_bo = vmw_user_object_buffer(&vps->uo); + if (old_bo != new_bo) { + ret = ttm_bo_reserve(&new_bo->tbo, false, false, NULL); + if (ret != 0) + return; + } else { + new_bo = NULL; + } + } if (!vmw_du_cursor_plane_has_changed(old_vps, vps)) { /* * If it hasn't changed, avoid making the device do extra @@ -813,6 +803,11 @@ vmw_du_cursor_plane_atomic_update(struct drm_plane *plane, hotspot_x, hotspot_y); } + if (old_bo) + ttm_bo_unreserve(&old_bo->tbo); + if (new_bo) + ttm_bo_unreserve(&new_bo->tbo); + du->cursor_x = new_state->crtc_x + du->set_gui_x; du->cursor_y = new_state->crtc_y + du->set_gui_y; @@ -913,7 +908,7 @@ int vmw_du_cursor_plane_atomic_check(struct drm_plane *plane, } if (!vmw_framebuffer_to_vfb(fb)->bo) { - surface = vmw_framebuffer_to_vfbs(fb)->surface; + surface = vmw_user_object_surface(&vmw_framebuffer_to_vfbs(fb)->uo); WARN_ON(!surface); @@ -1074,12 +1069,7 @@ vmw_du_plane_duplicate_state(struct drm_plane *plane) memset(&vps->cursor, 0, sizeof(vps->cursor)); /* Each ref counted resource needs to be acquired again */ - if (vps->surf) - (void) vmw_surface_reference(vps->surf); - - if (vps->bo) - (void) vmw_bo_reference(vps->bo); - + vmw_user_object_ref(&vps->uo); state = &vps->base; __drm_atomic_helper_plane_duplicate_state(plane, state); @@ -1128,11 +1118,7 @@ vmw_du_plane_destroy_state(struct drm_plane *plane, struct vmw_plane_state *vps = vmw_plane_state_to_vps(state); /* Should have been freed by cleanup_fb */ - if (vps->surf) - vmw_surface_unreference(&vps->surf); - - if (vps->bo) - vmw_bo_unreference(&vps->bo); + vmw_user_object_unref(&vps->uo); drm_atomic_helper_plane_destroy_state(plane, state); } @@ -1227,7 +1213,7 @@ static void vmw_framebuffer_surface_destroy(struct drm_framebuffer *framebuffer) vmw_framebuffer_to_vfbs(framebuffer); drm_framebuffer_cleanup(framebuffer); - vmw_surface_unreference(&vfbs->surface); + vmw_user_object_unref(&vfbs->uo); kfree(vfbs); } @@ -1272,29 +1258,41 @@ int vmw_kms_readback(struct vmw_private *dev_priv, return -ENOSYS; } +static int vmw_framebuffer_surface_create_handle(struct drm_framebuffer *fb, + struct drm_file *file_priv, + unsigned int *handle) +{ + struct vmw_framebuffer_surface *vfbs = vmw_framebuffer_to_vfbs(fb); + struct vmw_bo *bo = vmw_user_object_buffer(&vfbs->uo); + + return drm_gem_handle_create(file_priv, &bo->tbo.base, handle); +} static const struct drm_framebuffer_funcs vmw_framebuffer_surface_funcs = { + .create_handle = vmw_framebuffer_surface_create_handle, .destroy = vmw_framebuffer_surface_destroy, .dirty = drm_atomic_helper_dirtyfb, }; static int vmw_kms_new_framebuffer_surface(struct vmw_private *dev_priv, - struct vmw_surface *surface, + struct vmw_user_object *uo, struct vmw_framebuffer **out, const struct drm_mode_fb_cmd2 - *mode_cmd, - bool is_bo_proxy) + *mode_cmd) { struct drm_device *dev = &dev_priv->drm; struct vmw_framebuffer_surface *vfbs; enum SVGA3dSurfaceFormat format; + struct vmw_surface *surface; int ret; /* 3D is only supported on HWv8 and newer hosts */ if (dev_priv->active_display_unit == vmw_du_legacy) return -ENOSYS; + surface = vmw_user_object_surface(uo); + /* * Sanity checks. */ @@ -1357,8 +1355,8 @@ static int vmw_kms_new_framebuffer_surface(struct vmw_private *dev_priv, } drm_helper_mode_fill_fb_struct(dev, &vfbs->base.base, mode_cmd); - vfbs->surface = vmw_surface_reference(surface); - vfbs->is_bo_proxy = is_bo_proxy; + memcpy(&vfbs->uo, uo, sizeof(vfbs->uo)); + vmw_user_object_ref(&vfbs->uo); *out = &vfbs->base; @@ -1370,7 +1368,7 @@ static int vmw_kms_new_framebuffer_surface(struct vmw_private *dev_priv, return 0; out_err2: - vmw_surface_unreference(&surface); + vmw_user_object_unref(&vfbs->uo); kfree(vfbs); out_err1: return ret; @@ -1386,7 +1384,6 @@ static int vmw_framebuffer_bo_create_handle(struct drm_framebuffer *fb, { struct vmw_framebuffer_bo *vfbd = vmw_framebuffer_to_vfbd(fb); - return drm_gem_handle_create(file_priv, &vfbd->buffer->tbo.base, handle); } @@ -1407,86 +1404,6 @@ static const struct drm_framebuffer_funcs vmw_framebuffer_bo_funcs = { .dirty = drm_atomic_helper_dirtyfb, }; -/** - * vmw_create_bo_proxy - create a proxy surface for the buffer object - * - * @dev: DRM device - * @mode_cmd: parameters for the new surface - * @bo_mob: MOB backing the buffer object - * @srf_out: newly created surface - * - * When the content FB is a buffer object, we create a surface as a proxy to the - * same buffer. This way we can do a surface copy rather than a surface DMA. - * This is a more efficient approach - * - * RETURNS: - * 0 on success, error code otherwise - */ -static int vmw_create_bo_proxy(struct drm_device *dev, - const struct drm_mode_fb_cmd2 *mode_cmd, - struct vmw_bo *bo_mob, - struct vmw_surface **srf_out) -{ - struct vmw_surface_metadata metadata = {0}; - uint32_t format; - struct vmw_resource *res; - unsigned int bytes_pp; - int ret; - - switch (mode_cmd->pixel_format) { - case DRM_FORMAT_ARGB8888: - case DRM_FORMAT_XRGB8888: - format = SVGA3D_X8R8G8B8; - bytes_pp = 4; - break; - - case DRM_FORMAT_RGB565: - case DRM_FORMAT_XRGB1555: - format = SVGA3D_R5G6B5; - bytes_pp = 2; - break; - - case 8: - format = SVGA3D_P8; - bytes_pp = 1; - break; - - default: - DRM_ERROR("Invalid framebuffer format %p4cc\n", - &mode_cmd->pixel_format); - return -EINVAL; - } - - metadata.format = format; - metadata.mip_levels[0] = 1; - metadata.num_sizes = 1; - metadata.base_size.width = mode_cmd->pitches[0] / bytes_pp; - metadata.base_size.height = mode_cmd->height; - metadata.base_size.depth = 1; - metadata.scanout = true; - - ret = vmw_gb_surface_define(vmw_priv(dev), &metadata, srf_out); - if (ret) { - DRM_ERROR("Failed to allocate proxy content buffer\n"); - return ret; - } - - res = &(*srf_out)->res; - - /* Reserve and switch the backing mob. */ - mutex_lock(&res->dev_priv->cmdbuf_mutex); - (void) vmw_resource_reserve(res, false, true); - vmw_user_bo_unref(&res->guest_memory_bo); - res->guest_memory_bo = vmw_user_bo_ref(bo_mob); - res->guest_memory_offset = 0; - vmw_resource_unreserve(res, false, false, false, NULL, 0); - mutex_unlock(&res->dev_priv->cmdbuf_mutex); - - return 0; -} - - - static int vmw_kms_new_framebuffer_bo(struct vmw_private *dev_priv, struct vmw_bo *bo, struct vmw_framebuffer **out, @@ -1565,55 +1482,24 @@ vmw_kms_srf_ok(struct vmw_private *dev_priv, uint32_t width, uint32_t height) * vmw_kms_new_framebuffer - Create a new framebuffer. * * @dev_priv: Pointer to device private struct. - * @bo: Pointer to buffer object to wrap the kms framebuffer around. - * Either @bo or @surface must be NULL. - * @surface: Pointer to a surface to wrap the kms framebuffer around. - * Either @bo or @surface must be NULL. - * @only_2d: No presents will occur to this buffer object based framebuffer. - * This helps the code to do some important optimizations. + * @uo: Pointer to user object to wrap the kms framebuffer around. + * Either the buffer or surface inside the user object must be NULL. * @mode_cmd: Frame-buffer metadata. */ struct vmw_framebuffer * vmw_kms_new_framebuffer(struct vmw_private *dev_priv, - struct vmw_bo *bo, - struct vmw_surface *surface, - bool only_2d, + struct vmw_user_object *uo, const struct drm_mode_fb_cmd2 *mode_cmd) { struct vmw_framebuffer *vfb = NULL; - bool is_bo_proxy = false; int ret; - /* - * We cannot use the SurfaceDMA command in an non-accelerated VM, - * therefore, wrap the buffer object in a surface so we can use the - * SurfaceCopy command. - */ - if (vmw_kms_srf_ok(dev_priv, mode_cmd->width, mode_cmd->height) && - bo && only_2d && - mode_cmd->width > 64 && /* Don't create a proxy for cursor */ - dev_priv->active_display_unit == vmw_du_screen_target) { - ret = vmw_create_bo_proxy(&dev_priv->drm, mode_cmd, - bo, &surface); - if (ret) - return ERR_PTR(ret); - - is_bo_proxy = true; - } - /* Create the new framebuffer depending one what we have */ - if (surface) { - ret = vmw_kms_new_framebuffer_surface(dev_priv, surface, &vfb, - mode_cmd, - is_bo_proxy); - /* - * vmw_create_bo_proxy() adds a reference that is no longer - * needed - */ - if (is_bo_proxy) - vmw_surface_unreference(&surface); - } else if (bo) { - ret = vmw_kms_new_framebuffer_bo(dev_priv, bo, &vfb, + if (vmw_user_object_surface(uo)) { + ret = vmw_kms_new_framebuffer_surface(dev_priv, uo, &vfb, + mode_cmd); + } else if (uo->buffer) { + ret = vmw_kms_new_framebuffer_bo(dev_priv, uo->buffer, &vfb, mode_cmd); } else { BUG(); @@ -1635,14 +1521,12 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev, { struct vmw_private *dev_priv = vmw_priv(dev); struct vmw_framebuffer *vfb = NULL; - struct vmw_surface *surface = NULL; - struct vmw_bo *bo = NULL; + struct vmw_user_object uo = {0}; int ret; /* returns either a bo or surface */ - ret = vmw_user_lookup_handle(dev_priv, file_priv, - mode_cmd->handles[0], - &surface, &bo); + ret = vmw_user_object_lookup(dev_priv, file_priv, mode_cmd->handles[0], + &uo); if (ret) { DRM_ERROR("Invalid buffer object handle %u (0x%x).\n", mode_cmd->handles[0], mode_cmd->handles[0]); @@ -1650,7 +1534,7 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev, } - if (!bo && + if (vmw_user_object_surface(&uo) && !vmw_kms_srf_ok(dev_priv, mode_cmd->width, mode_cmd->height)) { DRM_ERROR("Surface size cannot exceed %dx%d\n", dev_priv->texture_max_width, @@ -1659,20 +1543,15 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev, } - vfb = vmw_kms_new_framebuffer(dev_priv, bo, surface, - !(dev_priv->capabilities & SVGA_CAP_3D), - mode_cmd); + vfb = vmw_kms_new_framebuffer(dev_priv, &uo, mode_cmd); if (IS_ERR(vfb)) { ret = PTR_ERR(vfb); goto err_out; } err_out: - /* vmw_user_lookup_handle takes one ref so does new_fb */ - if (bo) - vmw_user_bo_unref(&bo); - if (surface) - vmw_surface_unreference(&surface); + /* vmw_user_object_lookup takes one ref so does new_fb */ + vmw_user_object_unref(&uo); if (ret) { DRM_ERROR("failed to create vmw_framebuffer: %i\n", ret); @@ -2584,72 +2463,6 @@ void vmw_kms_helper_validation_finish(struct vmw_private *dev_priv, vmw_fence_obj_unreference(&fence); } -/** - * vmw_kms_update_proxy - Helper function to update a proxy surface from - * its backing MOB. - * - * @res: Pointer to the surface resource - * @clips: Clip rects in framebuffer (surface) space. - * @num_clips: Number of clips in @clips. - * @increment: Integer with which to increment the clip counter when looping. - * Used to skip a predetermined number of clip rects. - * - * This function makes sure the proxy surface is updated from its backing MOB - * using the region given by @clips. The surface resource @res and its backing - * MOB needs to be reserved and validated on call. - */ -int vmw_kms_update_proxy(struct vmw_resource *res, - const struct drm_clip_rect *clips, - unsigned num_clips, - int increment) -{ - struct vmw_private *dev_priv = res->dev_priv; - struct drm_vmw_size *size = &vmw_res_to_srf(res)->metadata.base_size; - struct { - SVGA3dCmdHeader header; - SVGA3dCmdUpdateGBImage body; - } *cmd; - SVGA3dBox *box; - size_t copy_size = 0; - int i; - - if (!clips) - return 0; - - cmd = VMW_CMD_RESERVE(dev_priv, sizeof(*cmd) * num_clips); - if (!cmd) - return -ENOMEM; - - for (i = 0; i < num_clips; ++i, clips += increment, ++cmd) { - box = &cmd->body.box; - - cmd->header.id = SVGA_3D_CMD_UPDATE_GB_IMAGE; - cmd->header.size = sizeof(cmd->body); - cmd->body.image.sid = res->id; - cmd->body.image.face = 0; - cmd->body.image.mipmap = 0; - - if (clips->x1 > size->width || clips->x2 > size->width || - clips->y1 > size->height || clips->y2 > size->height) { - DRM_ERROR("Invalid clips outsize of framebuffer.\n"); - return -EINVAL; - } - - box->x = clips->x1; - box->y = clips->y1; - box->z = 0; - box->w = clips->x2 - clips->x1; - box->h = clips->y2 - clips->y1; - box->d = 1; - - copy_size += sizeof(*cmd); - } - - vmw_cmd_commit(dev_priv, copy_size); - - return 0; -} - /** * vmw_kms_create_implicit_placement_property - Set up the implicit placement * property. @@ -2784,8 +2597,9 @@ int vmw_du_helper_plane_update(struct vmw_du_update_plane *update) } else { struct vmw_framebuffer_surface *vfbs = container_of(update->vfb, typeof(*vfbs), base); + struct vmw_surface *surf = vmw_user_object_surface(&vfbs->uo); - ret = vmw_validation_add_resource(&val_ctx, &vfbs->surface->res, + ret = vmw_validation_add_resource(&val_ctx, &surf->res, 0, VMW_RES_DIRTY_NONE, NULL, NULL); } @@ -2941,3 +2755,93 @@ int vmw_connector_get_modes(struct drm_connector *connector) return num_modes; } + +struct vmw_user_object *vmw_user_object_ref(struct vmw_user_object *uo) +{ + if (uo->buffer) + vmw_user_bo_ref(uo->buffer); + else if (uo->surface) + vmw_surface_reference(uo->surface); + return uo; +} + +void vmw_user_object_unref(struct vmw_user_object *uo) +{ + if (uo->buffer) + vmw_user_bo_unref(&uo->buffer); + else if (uo->surface) + vmw_surface_unreference(&uo->surface); +} + +struct vmw_bo * +vmw_user_object_buffer(struct vmw_user_object *uo) +{ + if (uo->buffer) + return uo->buffer; + else if (uo->surface) + return uo->surface->res.guest_memory_bo; + return NULL; +} + +struct vmw_surface * +vmw_user_object_surface(struct vmw_user_object *uo) +{ + if (uo->buffer) + return uo->buffer->dumb_surface; + return uo->surface; +} + +void *vmw_user_object_map(struct vmw_user_object *uo) +{ + struct vmw_bo *bo = vmw_user_object_buffer(uo); + + WARN_ON(!bo); + return vmw_bo_map_and_cache(bo); +} + +void *vmw_user_object_map_size(struct vmw_user_object *uo, size_t size) +{ + struct vmw_bo *bo = vmw_user_object_buffer(uo); + + WARN_ON(!bo); + return vmw_bo_map_and_cache_size(bo, size); +} + +void vmw_user_object_unmap(struct vmw_user_object *uo) +{ + struct vmw_bo *bo = vmw_user_object_buffer(uo); + int ret; + + WARN_ON(!bo); + + /* Fence the mob creation so we are guarateed to have the mob */ + ret = ttm_bo_reserve(&bo->tbo, false, false, NULL); + if (ret != 0) + return; + + vmw_bo_unmap(bo); + vmw_bo_pin_reserved(bo, false); + + ttm_bo_unreserve(&bo->tbo); +} + +bool vmw_user_object_is_mapped(struct vmw_user_object *uo) +{ + struct vmw_bo *bo; + + if (!uo || vmw_user_object_is_null(uo)) + return false; + + bo = vmw_user_object_buffer(uo); + + if (WARN_ON(!bo)) + return false; + + WARN_ON(bo->map.bo && !bo->map.virtual); + return bo->map.virtual; +} + +bool vmw_user_object_is_null(struct vmw_user_object *uo) +{ + return !uo->buffer && !uo->surface; +} diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h index bf24f2f0dcfc93..6141fadf81efeb 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h @@ -1,7 +1,8 @@ /* SPDX-License-Identifier: GPL-2.0 OR MIT */ /************************************************************************** * - * Copyright 2009-2023 VMware, Inc., Palo Alto, CA., USA + * Copyright (c) 2009-2024 Broadcom. All Rights Reserved. The term + * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the @@ -221,11 +222,9 @@ struct vmw_framebuffer { struct vmw_framebuffer_surface { struct vmw_framebuffer base; - struct vmw_surface *surface; - bool is_bo_proxy; /* true if this is proxy surface for DMA buf */ + struct vmw_user_object uo; }; - struct vmw_framebuffer_bo { struct vmw_framebuffer base; struct vmw_bo *buffer; @@ -277,8 +276,7 @@ struct vmw_cursor_plane_state { */ struct vmw_plane_state { struct drm_plane_state base; - struct vmw_surface *surf; - struct vmw_bo *bo; + struct vmw_user_object uo; int content_fb_type; unsigned long bo_size; @@ -457,9 +455,7 @@ int vmw_kms_readback(struct vmw_private *dev_priv, uint32_t num_clips); struct vmw_framebuffer * vmw_kms_new_framebuffer(struct vmw_private *dev_priv, - struct vmw_bo *bo, - struct vmw_surface *surface, - bool only_2d, + struct vmw_user_object *uo, const struct drm_mode_fb_cmd2 *mode_cmd); void vmw_guess_mode_timing(struct drm_display_mode *mode); void vmw_kms_update_implicit_fb(struct vmw_private *dev_priv); @@ -486,8 +482,7 @@ void vmw_du_plane_reset(struct drm_plane *plane); struct drm_plane_state *vmw_du_plane_duplicate_state(struct drm_plane *plane); void vmw_du_plane_destroy_state(struct drm_plane *plane, struct drm_plane_state *state); -void vmw_du_plane_unpin_surf(struct vmw_plane_state *vps, - bool unreference); +void vmw_du_plane_unpin_surf(struct vmw_plane_state *vps); int vmw_du_crtc_atomic_check(struct drm_crtc *crtc, struct drm_atomic_state *state); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c index 5befc2719a4984..39949e0a493f3d 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c @@ -1,7 +1,8 @@ // SPDX-License-Identifier: GPL-2.0 OR MIT /************************************************************************** * - * Copyright 2009-2023 VMware, Inc., Palo Alto, CA., USA + * Copyright (c) 2009-2024 Broadcom. All Rights Reserved. The term + * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the @@ -147,8 +148,9 @@ static int vmw_ldu_fb_pin(struct vmw_framebuffer *vfb) struct vmw_bo *buf; int ret; - buf = vfb->bo ? vmw_framebuffer_to_vfbd(&vfb->base)->buffer : - vmw_framebuffer_to_vfbs(&vfb->base)->surface->res.guest_memory_bo; + buf = vfb->bo ? + vmw_framebuffer_to_vfbd(&vfb->base)->buffer : + vmw_user_object_buffer(&vmw_framebuffer_to_vfbs(&vfb->base)->uo); if (!buf) return 0; @@ -169,8 +171,10 @@ static int vmw_ldu_fb_unpin(struct vmw_framebuffer *vfb) struct vmw_private *dev_priv = vmw_priv(vfb->base.dev); struct vmw_bo *buf; - buf = vfb->bo ? vmw_framebuffer_to_vfbd(&vfb->base)->buffer : - vmw_framebuffer_to_vfbs(&vfb->base)->surface->res.guest_memory_bo; + buf = vfb->bo ? + vmw_framebuffer_to_vfbd(&vfb->base)->buffer : + vmw_user_object_buffer(&vmw_framebuffer_to_vfbs(&vfb->base)->uo); + if (WARN_ON(!buf)) return 0; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c b/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c index c45b4724e4141d..e20f64b67b2669 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c @@ -92,7 +92,7 @@ static int vmw_overlay_send_put(struct vmw_private *dev_priv, { struct vmw_escape_video_flush *flush; size_t fifo_size; - bool have_so = (dev_priv->active_display_unit == vmw_du_screen_object); + bool have_so = (dev_priv->active_display_unit != vmw_du_legacy); int i, num_items; SVGAGuestPtr ptr; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_prime.c b/drivers/gpu/drm/vmwgfx/vmwgfx_prime.c index c99cad44499157..598b90ac7590b5 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_prime.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_prime.c @@ -1,7 +1,8 @@ // SPDX-License-Identifier: GPL-2.0 OR MIT /************************************************************************** * - * Copyright 2013 VMware, Inc., Palo Alto, CA., USA + * Copyright (c) 2013-2024 Broadcom. All Rights Reserved. The term + * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the @@ -31,6 +32,7 @@ */ #include "vmwgfx_drv.h" +#include "vmwgfx_bo.h" #include "ttm_object.h" #include @@ -88,13 +90,35 @@ int vmw_prime_handle_to_fd(struct drm_device *dev, uint32_t handle, uint32_t flags, int *prime_fd) { + struct vmw_private *vmw = vmw_priv(dev); struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; + struct vmw_bo *vbo; int ret; + int surf_handle; - if (handle > VMWGFX_NUM_MOB) + if (handle > VMWGFX_NUM_MOB) { ret = ttm_prime_handle_to_fd(tfile, handle, flags, prime_fd); - else - ret = drm_gem_prime_handle_to_fd(dev, file_priv, handle, flags, prime_fd); + } else { + ret = vmw_user_bo_lookup(file_priv, handle, &vbo); + if (ret) + return ret; + if (vbo && vbo->is_dumb) { + ret = drm_gem_prime_handle_to_fd(dev, file_priv, handle, + flags, prime_fd); + } else { + surf_handle = vmw_lookup_surface_handle_for_buffer(vmw, + vbo, + handle); + if (surf_handle > 0) + ret = ttm_prime_handle_to_fd(tfile, surf_handle, + flags, prime_fd); + else + ret = drm_gem_prime_handle_to_fd(dev, file_priv, + handle, flags, + prime_fd); + } + vmw_user_bo_unref(&vbo); + } return ret; } diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c index 848dba09981b0d..a73af8a355fbf5 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c @@ -1,7 +1,8 @@ // SPDX-License-Identifier: GPL-2.0 OR MIT /************************************************************************** * - * Copyright 2009-2023 VMware, Inc., Palo Alto, CA., USA + * Copyright (c) 2009-2024 Broadcom. All Rights Reserved. The term + * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the @@ -58,6 +59,7 @@ void vmw_resource_mob_attach(struct vmw_resource *res) rb_link_node(&res->mob_node, parent, new); rb_insert_color(&res->mob_node, &gbo->res_tree); + vmw_bo_del_detached_resource(gbo, res); vmw_bo_prio_add(gbo, res->used_prio); } @@ -287,28 +289,35 @@ int vmw_user_resource_lookup_handle(struct vmw_private *dev_priv, * * The pointer this pointed at by out_surf and out_buf needs to be null. */ -int vmw_user_lookup_handle(struct vmw_private *dev_priv, +int vmw_user_object_lookup(struct vmw_private *dev_priv, struct drm_file *filp, - uint32_t handle, - struct vmw_surface **out_surf, - struct vmw_bo **out_buf) + u32 handle, + struct vmw_user_object *uo) { struct ttm_object_file *tfile = vmw_fpriv(filp)->tfile; struct vmw_resource *res; int ret; - BUG_ON(*out_surf || *out_buf); + WARN_ON(uo->surface || uo->buffer); ret = vmw_user_resource_lookup_handle(dev_priv, tfile, handle, user_surface_converter, &res); if (!ret) { - *out_surf = vmw_res_to_srf(res); + uo->surface = vmw_res_to_srf(res); return 0; } - *out_surf = NULL; - ret = vmw_user_bo_lookup(filp, handle, out_buf); + uo->surface = NULL; + ret = vmw_user_bo_lookup(filp, handle, &uo->buffer); + if (!ret && !uo->buffer->is_dumb) { + uo->surface = vmw_lookup_surface_for_buffer(dev_priv, + uo->buffer, + handle); + if (uo->surface) + vmw_user_bo_unref(&uo->buffer); + } + return ret; } diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c index df0039a8ef29a2..0f4bfd98480afe 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c @@ -1,7 +1,8 @@ // SPDX-License-Identifier: GPL-2.0 OR MIT /************************************************************************** * - * Copyright 2011-2023 VMware, Inc., Palo Alto, CA., USA + * Copyright (c) 2011-2024 Broadcom. All Rights Reserved. The term + * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the @@ -240,7 +241,7 @@ static void vmw_sou_crtc_mode_set_nofb(struct drm_crtc *crtc) struct vmw_connector_state *vmw_conn_state; int x, y; - sou->buffer = vps->bo; + sou->buffer = vmw_user_object_buffer(&vps->uo); conn_state = sou->base.connector.state; vmw_conn_state = vmw_connector_state_to_vcs(conn_state); @@ -376,10 +377,11 @@ vmw_sou_primary_plane_cleanup_fb(struct drm_plane *plane, struct vmw_plane_state *vps = vmw_plane_state_to_vps(old_state); struct drm_crtc *crtc = plane->state->crtc ? plane->state->crtc : old_state->crtc; + struct vmw_bo *bo = vmw_user_object_buffer(&vps->uo); - if (vps->bo) - vmw_bo_unpin(vmw_priv(crtc->dev), vps->bo, false); - vmw_bo_unreference(&vps->bo); + if (bo) + vmw_bo_unpin(vmw_priv(crtc->dev), bo, false); + vmw_user_object_unref(&vps->uo); vps->bo_size = 0; vmw_du_plane_cleanup_fb(plane, old_state); @@ -411,9 +413,10 @@ vmw_sou_primary_plane_prepare_fb(struct drm_plane *plane, .bo_type = ttm_bo_type_device, .pin = true }; + struct vmw_bo *bo = NULL; if (!new_fb) { - vmw_bo_unreference(&vps->bo); + vmw_user_object_unref(&vps->uo); vps->bo_size = 0; return 0; @@ -422,17 +425,17 @@ vmw_sou_primary_plane_prepare_fb(struct drm_plane *plane, bo_params.size = new_state->crtc_w * new_state->crtc_h * 4; dev_priv = vmw_priv(crtc->dev); - if (vps->bo) { + bo = vmw_user_object_buffer(&vps->uo); + if (bo) { if (vps->bo_size == bo_params.size) { /* * Note that this might temporarily up the pin-count * to 2, until cleanup_fb() is called. */ - return vmw_bo_pin_in_vram(dev_priv, vps->bo, - true); + return vmw_bo_pin_in_vram(dev_priv, bo, true); } - vmw_bo_unreference(&vps->bo); + vmw_user_object_unref(&vps->uo); vps->bo_size = 0; } @@ -442,7 +445,7 @@ vmw_sou_primary_plane_prepare_fb(struct drm_plane *plane, * resume the overlays, this is preferred to failing to alloc. */ vmw_overlay_pause_all(dev_priv); - ret = vmw_bo_create(dev_priv, &bo_params, &vps->bo); + ret = vmw_gem_object_create(dev_priv, &bo_params, &vps->uo.buffer); vmw_overlay_resume_all(dev_priv); if (ret) return ret; @@ -453,7 +456,7 @@ vmw_sou_primary_plane_prepare_fb(struct drm_plane *plane, * TTM already thinks the buffer is pinned, but make sure the * pin_count is upped. */ - return vmw_bo_pin_in_vram(dev_priv, vps->bo, true); + return vmw_bo_pin_in_vram(dev_priv, vps->uo.buffer, true); } static uint32_t vmw_sou_bo_fifo_size(struct vmw_du_update_plane *update, @@ -580,6 +583,7 @@ static uint32_t vmw_sou_surface_pre_clip(struct vmw_du_update_plane *update, { struct vmw_kms_sou_dirty_cmd *blit = cmd; struct vmw_framebuffer_surface *vfbs; + struct vmw_surface *surf = NULL; vfbs = container_of(update->vfb, typeof(*vfbs), base); @@ -587,7 +591,8 @@ static uint32_t vmw_sou_surface_pre_clip(struct vmw_du_update_plane *update, blit->header.size = sizeof(blit->body) + sizeof(SVGASignedRect) * num_hits; - blit->body.srcImage.sid = vfbs->surface->res.id; + surf = vmw_user_object_surface(&vfbs->uo); + blit->body.srcImage.sid = surf->res.id; blit->body.destScreenId = update->du->unit; /* Update the source and destination bounding box later in post_clip */ @@ -1104,7 +1109,7 @@ int vmw_kms_sou_do_surface_dirty(struct vmw_private *dev_priv, int ret; if (!srf) - srf = &vfbs->surface->res; + srf = &vmw_user_object_surface(&vfbs->uo)->res; ret = vmw_validation_add_resource(&val_ctx, srf, 0, VMW_RES_DIRTY_NONE, NULL, NULL); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c index a04e0736318da6..5453f7cf0e2d7b 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c @@ -1,7 +1,8 @@ // SPDX-License-Identifier: GPL-2.0 OR MIT /****************************************************************************** * - * COPYRIGHT (C) 2014-2023 VMware, Inc., Palo Alto, CA., USA + * Copyright (c) 2014-2024 Broadcom. All Rights Reserved. The term + * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the @@ -29,6 +30,7 @@ #include "vmwgfx_kms.h" #include "vmwgfx_vkms.h" #include "vmw_surface_cache.h" +#include #include #include @@ -735,7 +737,7 @@ int vmw_kms_stdu_surface_dirty(struct vmw_private *dev_priv, int ret; if (!srf) - srf = &vfbs->surface->res; + srf = &vmw_user_object_surface(&vfbs->uo)->res; ret = vmw_validation_add_resource(&val_ctx, srf, 0, VMW_RES_DIRTY_NONE, NULL, NULL); @@ -746,12 +748,6 @@ int vmw_kms_stdu_surface_dirty(struct vmw_private *dev_priv, if (ret) goto out_unref; - if (vfbs->is_bo_proxy) { - ret = vmw_kms_update_proxy(srf, clips, num_clips, inc); - if (ret) - goto out_finish; - } - sdirty.base.fifo_commit = vmw_kms_stdu_surface_fifo_commit; sdirty.base.clip = vmw_kms_stdu_surface_clip; sdirty.base.fifo_reserve_size = sizeof(struct vmw_stdu_surface_copy) + @@ -765,7 +761,7 @@ int vmw_kms_stdu_surface_dirty(struct vmw_private *dev_priv, ret = vmw_kms_helper_dirty(dev_priv, framebuffer, clips, vclips, dest_x, dest_y, num_clips, inc, &sdirty.base); -out_finish: + vmw_kms_helper_validation_finish(dev_priv, NULL, &val_ctx, out_fence, NULL); @@ -877,6 +873,32 @@ vmw_stdu_connector_mode_valid(struct drm_connector *connector, return MODE_OK; } +/* + * Trigger a modeset if the X,Y position of the Screen Target changes. + * This is needed when multi-mon is cycled. The original Screen Target will have + * the same mode but its relative X,Y position in the topology will change. + */ +static int vmw_stdu_connector_atomic_check(struct drm_connector *conn, + struct drm_atomic_state *state) +{ + struct drm_connector_state *conn_state; + struct vmw_screen_target_display_unit *du; + struct drm_crtc_state *new_crtc_state; + + conn_state = drm_atomic_get_connector_state(state, conn); + du = vmw_connector_to_stdu(conn); + + if (!conn_state->crtc) + return 0; + + new_crtc_state = drm_atomic_get_new_crtc_state(state, conn_state->crtc); + if (du->base.gui_x != du->base.set_gui_x || + du->base.gui_y != du->base.set_gui_y) + new_crtc_state->mode_changed = true; + + return 0; +} + static const struct drm_connector_funcs vmw_stdu_connector_funcs = { .dpms = vmw_du_connector_dpms, .detect = vmw_du_connector_detect, @@ -891,7 +913,8 @@ static const struct drm_connector_funcs vmw_stdu_connector_funcs = { static const struct drm_connector_helper_funcs vmw_stdu_connector_helper_funcs = { .get_modes = vmw_connector_get_modes, - .mode_valid = vmw_stdu_connector_mode_valid + .mode_valid = vmw_stdu_connector_mode_valid, + .atomic_check = vmw_stdu_connector_atomic_check, }; @@ -918,9 +941,8 @@ vmw_stdu_primary_plane_cleanup_fb(struct drm_plane *plane, { struct vmw_plane_state *vps = vmw_plane_state_to_vps(old_state); - if (vps->surf) + if (vmw_user_object_surface(&vps->uo)) WARN_ON(!vps->pinned); - vmw_du_plane_cleanup_fb(plane, old_state); vps->content_fb_type = SAME_AS_DISPLAY; @@ -928,7 +950,6 @@ vmw_stdu_primary_plane_cleanup_fb(struct drm_plane *plane, } - /** * vmw_stdu_primary_plane_prepare_fb - Readies the display surface * @@ -952,13 +973,15 @@ vmw_stdu_primary_plane_prepare_fb(struct drm_plane *plane, enum stdu_content_type new_content_type; struct vmw_framebuffer_surface *new_vfbs; uint32_t hdisplay = new_state->crtc_w, vdisplay = new_state->crtc_h; + struct drm_plane_state *old_state = plane->state; + struct drm_rect rect; int ret; /* No FB to prepare */ if (!new_fb) { - if (vps->surf) { + if (vmw_user_object_surface(&vps->uo)) { WARN_ON(vps->pinned != 0); - vmw_surface_unreference(&vps->surf); + vmw_user_object_unref(&vps->uo); } return 0; @@ -968,8 +991,8 @@ vmw_stdu_primary_plane_prepare_fb(struct drm_plane *plane, new_vfbs = (vfb->bo) ? NULL : vmw_framebuffer_to_vfbs(new_fb); if (new_vfbs && - new_vfbs->surface->metadata.base_size.width == hdisplay && - new_vfbs->surface->metadata.base_size.height == vdisplay) + vmw_user_object_surface(&new_vfbs->uo)->metadata.base_size.width == hdisplay && + vmw_user_object_surface(&new_vfbs->uo)->metadata.base_size.height == vdisplay) new_content_type = SAME_AS_DISPLAY; else if (vfb->bo) new_content_type = SEPARATE_BO; @@ -1007,29 +1030,29 @@ vmw_stdu_primary_plane_prepare_fb(struct drm_plane *plane, metadata.num_sizes = 1; metadata.scanout = true; } else { - metadata = new_vfbs->surface->metadata; + metadata = vmw_user_object_surface(&new_vfbs->uo)->metadata; } metadata.base_size.width = hdisplay; metadata.base_size.height = vdisplay; metadata.base_size.depth = 1; - if (vps->surf) { + if (vmw_user_object_surface(&vps->uo)) { struct drm_vmw_size cur_base_size = - vps->surf->metadata.base_size; + vmw_user_object_surface(&vps->uo)->metadata.base_size; if (cur_base_size.width != metadata.base_size.width || cur_base_size.height != metadata.base_size.height || - vps->surf->metadata.format != metadata.format) { + vmw_user_object_surface(&vps->uo)->metadata.format != metadata.format) { WARN_ON(vps->pinned != 0); - vmw_surface_unreference(&vps->surf); + vmw_user_object_unref(&vps->uo); } } - if (!vps->surf) { + if (!vmw_user_object_surface(&vps->uo)) { ret = vmw_gb_surface_define(dev_priv, &metadata, - &vps->surf); + &vps->uo.surface); if (ret != 0) { DRM_ERROR("Couldn't allocate STDU surface.\n"); return ret; @@ -1042,18 +1065,19 @@ vmw_stdu_primary_plane_prepare_fb(struct drm_plane *plane, * The only time we add a reference in prepare_fb is if the * state object doesn't have a reference to begin with */ - if (vps->surf) { + if (vmw_user_object_surface(&vps->uo)) { WARN_ON(vps->pinned != 0); - vmw_surface_unreference(&vps->surf); + vmw_user_object_unref(&vps->uo); } - vps->surf = vmw_surface_reference(new_vfbs->surface); + memcpy(&vps->uo, &new_vfbs->uo, sizeof(vps->uo)); + vmw_user_object_ref(&vps->uo); } - if (vps->surf) { + if (vmw_user_object_surface(&vps->uo)) { /* Pin new surface before flipping */ - ret = vmw_resource_pin(&vps->surf->res, false); + ret = vmw_resource_pin(&vmw_user_object_surface(&vps->uo)->res, false); if (ret) goto out_srf_unref; @@ -1062,6 +1086,34 @@ vmw_stdu_primary_plane_prepare_fb(struct drm_plane *plane, vps->content_fb_type = new_content_type; + /* + * The drm fb code will do blit's via the vmap interface, which doesn't + * trigger vmw_bo page dirty tracking due to being kernel side (and thus + * doesn't require mmap'ing) so we have to update the surface's dirty + * regions by hand but we want to be careful to not overwrite the + * resource if it has been written to by the gpu (res_dirty). + */ + if (vps->uo.buffer && vps->uo.buffer->is_dumb) { + struct vmw_surface *surf = vmw_user_object_surface(&vps->uo); + struct vmw_resource *res = &surf->res; + + if (!res->res_dirty && drm_atomic_helper_damage_merged(old_state, + new_state, + &rect)) { + /* + * At some point it might be useful to actually translate + * (rect.x1, rect.y1) => start, and (rect.x2, rect.y2) => end, + * but currently the fb code will just report the entire fb + * dirty so in practice it doesn't matter. + */ + pgoff_t start = res->guest_memory_offset >> PAGE_SHIFT; + pgoff_t end = __KERNEL_DIV_ROUND_UP(res->guest_memory_offset + + res->guest_memory_size, + PAGE_SIZE); + vmw_resource_dirty_update(res, start, end); + } + } + /* * This should only happen if the buffer object is too large to create a * proxy surface for. @@ -1072,7 +1124,7 @@ vmw_stdu_primary_plane_prepare_fb(struct drm_plane *plane, return 0; out_srf_unref: - vmw_surface_unreference(&vps->surf); + vmw_user_object_unref(&vps->uo); return ret; } @@ -1214,14 +1266,8 @@ static uint32_t vmw_stdu_surface_fifo_size_same_display(struct vmw_du_update_plane *update, uint32_t num_hits) { - struct vmw_framebuffer_surface *vfbs; uint32_t size = 0; - vfbs = container_of(update->vfb, typeof(*vfbs), base); - - if (vfbs->is_bo_proxy) - size += sizeof(struct vmw_stdu_update_gb_image) * num_hits; - size += sizeof(struct vmw_stdu_update); return size; @@ -1230,61 +1276,14 @@ vmw_stdu_surface_fifo_size_same_display(struct vmw_du_update_plane *update, static uint32_t vmw_stdu_surface_fifo_size(struct vmw_du_update_plane *update, uint32_t num_hits) { - struct vmw_framebuffer_surface *vfbs; uint32_t size = 0; - vfbs = container_of(update->vfb, typeof(*vfbs), base); - - if (vfbs->is_bo_proxy) - size += sizeof(struct vmw_stdu_update_gb_image) * num_hits; - size += sizeof(struct vmw_stdu_surface_copy) + sizeof(SVGA3dCopyBox) * num_hits + sizeof(struct vmw_stdu_update); return size; } -static uint32_t -vmw_stdu_surface_update_proxy(struct vmw_du_update_plane *update, void *cmd) -{ - struct vmw_framebuffer_surface *vfbs; - struct drm_plane_state *state = update->plane->state; - struct drm_plane_state *old_state = update->old_state; - struct vmw_stdu_update_gb_image *cmd_update = cmd; - struct drm_atomic_helper_damage_iter iter; - struct drm_rect clip; - uint32_t copy_size = 0; - - vfbs = container_of(update->vfb, typeof(*vfbs), base); - - /* - * proxy surface is special where a buffer object type fb is wrapped - * in a surface and need an update gb image command to sync with device. - */ - drm_atomic_helper_damage_iter_init(&iter, old_state, state); - drm_atomic_for_each_plane_damage(&iter, &clip) { - SVGA3dBox *box = &cmd_update->body.box; - - cmd_update->header.id = SVGA_3D_CMD_UPDATE_GB_IMAGE; - cmd_update->header.size = sizeof(cmd_update->body); - cmd_update->body.image.sid = vfbs->surface->res.id; - cmd_update->body.image.face = 0; - cmd_update->body.image.mipmap = 0; - - box->x = clip.x1; - box->y = clip.y1; - box->z = 0; - box->w = drm_rect_width(&clip); - box->h = drm_rect_height(&clip); - box->d = 1; - - copy_size += sizeof(*cmd_update); - cmd_update++; - } - - return copy_size; -} - static uint32_t vmw_stdu_surface_populate_copy(struct vmw_du_update_plane *update, void *cmd, uint32_t num_hits) @@ -1299,7 +1298,7 @@ vmw_stdu_surface_populate_copy(struct vmw_du_update_plane *update, void *cmd, cmd_copy->header.id = SVGA_3D_CMD_SURFACE_COPY; cmd_copy->header.size = sizeof(cmd_copy->body) + sizeof(SVGA3dCopyBox) * num_hits; - cmd_copy->body.src.sid = vfbs->surface->res.id; + cmd_copy->body.src.sid = vmw_user_object_surface(&vfbs->uo)->res.id; cmd_copy->body.dest.sid = stdu->display_srf->res.id; return sizeof(*cmd_copy); @@ -1370,10 +1369,7 @@ static int vmw_stdu_plane_update_surface(struct vmw_private *dev_priv, srf_update.mutex = &dev_priv->cmdbuf_mutex; srf_update.intr = true; - if (vfbs->is_bo_proxy) - srf_update.post_prepare = vmw_stdu_surface_update_proxy; - - if (vfbs->surface->res.id != stdu->display_srf->res.id) { + if (vmw_user_object_surface(&vfbs->uo)->res.id != stdu->display_srf->res.id) { srf_update.calc_fifo_size = vmw_stdu_surface_fifo_size; srf_update.pre_clip = vmw_stdu_surface_populate_copy; srf_update.clip = vmw_stdu_surface_populate_clip; @@ -1417,7 +1413,7 @@ vmw_stdu_primary_plane_atomic_update(struct drm_plane *plane, stdu = vmw_crtc_to_stdu(crtc); dev_priv = vmw_priv(crtc->dev); - stdu->display_srf = vps->surf; + stdu->display_srf = vmw_user_object_surface(&vps->uo); stdu->content_fb_type = vps->content_fb_type; stdu->cpp = vps->cpp; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c index e7a744dfcecfd4..8ae6a761c90034 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c @@ -1,7 +1,8 @@ // SPDX-License-Identifier: GPL-2.0 OR MIT /************************************************************************** * - * Copyright 2009-2023 VMware, Inc., Palo Alto, CA., USA + * Copyright (c) 2009-2024 Broadcom. All Rights Reserved. The term + * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the @@ -36,9 +37,6 @@ #include #define SVGA3D_FLAGS_64(upper32, lower32) (((uint64_t)upper32 << 32) | lower32) -#define SVGA3D_FLAGS_UPPER_32(svga3d_flags) (svga3d_flags >> 32) -#define SVGA3D_FLAGS_LOWER_32(svga3d_flags) \ - (svga3d_flags & ((uint64_t)U32_MAX)) /** * struct vmw_user_surface - User-space visible surface resource @@ -686,6 +684,14 @@ static void vmw_user_surface_base_release(struct ttm_base_object **p_base) struct vmw_resource *res = &user_srf->srf.res; *p_base = NULL; + + /* + * Dumb buffers own the resource and they'll unref the + * resource themselves + */ + if (res && res->guest_memory_bo && res->guest_memory_bo->is_dumb) + return; + vmw_resource_unreference(&res); } @@ -812,7 +818,8 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data, } } res->guest_memory_size = cur_bo_offset; - if (metadata->scanout && + if (!file_priv->atomic && + metadata->scanout && metadata->num_sizes == 1 && metadata->sizes[0].width == VMW_CURSOR_SNOOP_WIDTH && metadata->sizes[0].height == VMW_CURSOR_SNOOP_HEIGHT && @@ -864,6 +871,7 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data, vmw_resource_unreference(&res); goto out_unlock; } + vmw_bo_add_detached_resource(res->guest_memory_bo, res); } tmp = vmw_resource_reference(&srf->res); @@ -892,6 +900,113 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data, return ret; } +static struct vmw_user_surface * +vmw_lookup_user_surface_for_buffer(struct vmw_private *vmw, struct vmw_bo *bo, + u32 handle) +{ + struct vmw_user_surface *user_srf = NULL; + struct vmw_surface *surf; + struct ttm_base_object *base; + + surf = vmw_bo_surface(bo); + if (surf) { + rcu_read_lock(); + user_srf = container_of(surf, struct vmw_user_surface, srf); + base = &user_srf->prime.base; + if (base && !kref_get_unless_zero(&base->refcount)) { + drm_dbg_driver(&vmw->drm, + "%s: referencing a stale surface handle %d\n", + __func__, handle); + base = NULL; + user_srf = NULL; + } + rcu_read_unlock(); + } + + return user_srf; +} + +struct vmw_surface *vmw_lookup_surface_for_buffer(struct vmw_private *vmw, + struct vmw_bo *bo, + u32 handle) +{ + struct vmw_user_surface *user_srf = + vmw_lookup_user_surface_for_buffer(vmw, bo, handle); + struct vmw_surface *surf = NULL; + struct ttm_base_object *base; + + if (user_srf) { + surf = vmw_surface_reference(&user_srf->srf); + base = &user_srf->prime.base; + ttm_base_object_unref(&base); + } + return surf; +} + +u32 vmw_lookup_surface_handle_for_buffer(struct vmw_private *vmw, + struct vmw_bo *bo, + u32 handle) +{ + struct vmw_user_surface *user_srf = + vmw_lookup_user_surface_for_buffer(vmw, bo, handle); + int surf_handle = 0; + struct ttm_base_object *base; + + if (user_srf) { + base = &user_srf->prime.base; + surf_handle = (u32)base->handle; + ttm_base_object_unref(&base); + } + return surf_handle; +} + +static int vmw_buffer_prime_to_surface_base(struct vmw_private *dev_priv, + struct drm_file *file_priv, + u32 fd, u32 *handle, + struct ttm_base_object **base_p) +{ + struct ttm_base_object *base; + struct vmw_bo *bo; + struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; + struct vmw_user_surface *user_srf; + int ret; + + ret = drm_gem_prime_fd_to_handle(&dev_priv->drm, file_priv, fd, handle); + if (ret) { + drm_warn(&dev_priv->drm, + "Wasn't able to find user buffer for fd = %u.\n", fd); + return ret; + } + + ret = vmw_user_bo_lookup(file_priv, *handle, &bo); + if (ret) { + drm_warn(&dev_priv->drm, + "Wasn't able to lookup user buffer for handle = %u.\n", *handle); + return ret; + } + + user_srf = vmw_lookup_user_surface_for_buffer(dev_priv, bo, *handle); + if (WARN_ON(!user_srf)) { + drm_warn(&dev_priv->drm, + "User surface fd %d (handle %d) is null.\n", fd, *handle); + ret = -EINVAL; + goto out; + } + + base = &user_srf->prime.base; + ret = ttm_ref_object_add(tfile, base, NULL, false); + if (ret) { + drm_warn(&dev_priv->drm, + "Couldn't add an object ref for the buffer (%d).\n", *handle); + goto out; + } + + *base_p = base; +out: + vmw_user_bo_unref(&bo); + + return ret; +} static int vmw_surface_handle_reference(struct vmw_private *dev_priv, @@ -901,15 +1016,19 @@ vmw_surface_handle_reference(struct vmw_private *dev_priv, struct ttm_base_object **base_p) { struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; - struct vmw_user_surface *user_srf; + struct vmw_user_surface *user_srf = NULL; uint32_t handle; struct ttm_base_object *base; int ret; if (handle_type == DRM_VMW_HANDLE_PRIME) { ret = ttm_prime_fd_to_handle(tfile, u_handle, &handle); - if (unlikely(ret != 0)) - return ret; + if (ret) + return vmw_buffer_prime_to_surface_base(dev_priv, + file_priv, + u_handle, + &handle, + base_p); } else { handle = u_handle; } @@ -1503,7 +1622,12 @@ vmw_gb_surface_define_internal(struct drm_device *dev, ret = vmw_user_bo_lookup(file_priv, req->base.buffer_handle, &res->guest_memory_bo); if (ret == 0) { - if (res->guest_memory_bo->tbo.base.size < res->guest_memory_size) { + if (res->guest_memory_bo->is_dumb) { + VMW_DEBUG_USER("Can't backup surface with a dumb buffer.\n"); + vmw_user_bo_unref(&res->guest_memory_bo); + ret = -EINVAL; + goto out_unlock; + } else if (res->guest_memory_bo->tbo.base.size < res->guest_memory_size) { VMW_DEBUG_USER("Surface backup buffer too small.\n"); vmw_user_bo_unref(&res->guest_memory_bo); ret = -EINVAL; @@ -1560,6 +1684,7 @@ vmw_gb_surface_define_internal(struct drm_device *dev, rep->handle = user_srf->prime.base.handle; rep->backup_size = res->guest_memory_size; if (res->guest_memory_bo) { + vmw_bo_add_detached_resource(res->guest_memory_bo, res); rep->buffer_map_handle = drm_vma_node_offset_addr(&res->guest_memory_bo->tbo.base.vma_node); rep->buffer_size = res->guest_memory_bo->tbo.base.size; @@ -2100,3 +2225,140 @@ int vmw_gb_surface_define(struct vmw_private *dev_priv, out_unlock: return ret; } + +static SVGA3dSurfaceFormat vmw_format_bpp_to_svga(struct vmw_private *vmw, + int bpp) +{ + switch (bpp) { + case 8: /* DRM_FORMAT_C8 */ + return SVGA3D_P8; + case 16: /* DRM_FORMAT_RGB565 */ + return SVGA3D_R5G6B5; + case 32: /* DRM_FORMAT_XRGB8888 */ + if (has_sm4_context(vmw)) + return SVGA3D_B8G8R8X8_UNORM; + return SVGA3D_X8R8G8B8; + default: + drm_warn(&vmw->drm, "Unsupported format bpp: %d\n", bpp); + return SVGA3D_X8R8G8B8; + } +} + +/** + * vmw_dumb_create - Create a dumb kms buffer + * + * @file_priv: Pointer to a struct drm_file identifying the caller. + * @dev: Pointer to the drm device. + * @args: Pointer to a struct drm_mode_create_dumb structure + * Return: Zero on success, negative error code on failure. + * + * This is a driver callback for the core drm create_dumb functionality. + * Note that this is very similar to the vmw_bo_alloc ioctl, except + * that the arguments have a different format. + */ +int vmw_dumb_create(struct drm_file *file_priv, + struct drm_device *dev, + struct drm_mode_create_dumb *args) +{ + struct vmw_private *dev_priv = vmw_priv(dev); + struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; + struct vmw_bo *vbo = NULL; + struct vmw_resource *res = NULL; + union drm_vmw_gb_surface_create_ext_arg arg = { 0 }; + struct drm_vmw_gb_surface_create_ext_req *req = &arg.req; + int ret; + struct drm_vmw_size drm_size = { + .width = args->width, + .height = args->height, + .depth = 1, + }; + SVGA3dSurfaceFormat format = vmw_format_bpp_to_svga(dev_priv, args->bpp); + const struct SVGA3dSurfaceDesc *desc = vmw_surface_get_desc(format); + SVGA3dSurfaceAllFlags flags = SVGA3D_SURFACE_HINT_TEXTURE | + SVGA3D_SURFACE_HINT_RENDERTARGET | + SVGA3D_SURFACE_SCREENTARGET | + SVGA3D_SURFACE_BIND_SHADER_RESOURCE | + SVGA3D_SURFACE_BIND_RENDER_TARGET; + + /* + * Without mob support we're just going to use raw memory buffer + * because we wouldn't be able to support full surface coherency + * without mobs + */ + if (!dev_priv->has_mob) { + int cpp = DIV_ROUND_UP(args->bpp, 8); + + switch (cpp) { + case 1: /* DRM_FORMAT_C8 */ + case 2: /* DRM_FORMAT_RGB565 */ + case 4: /* DRM_FORMAT_XRGB8888 */ + break; + default: + /* + * Dumb buffers don't allow anything else. + * This is tested via IGT's dumb_buffers + */ + return -EINVAL; + } + + args->pitch = args->width * cpp; + args->size = ALIGN(args->pitch * args->height, PAGE_SIZE); + + ret = vmw_gem_object_create_with_handle(dev_priv, file_priv, + args->size, &args->handle, + &vbo); + /* drop reference from allocate - handle holds it now */ + drm_gem_object_put(&vbo->tbo.base); + return ret; + } + + req->version = drm_vmw_gb_surface_v1; + req->multisample_pattern = SVGA3D_MS_PATTERN_NONE; + req->quality_level = SVGA3D_MS_QUALITY_NONE; + req->buffer_byte_stride = 0; + req->must_be_zero = 0; + req->base.svga3d_flags = SVGA3D_FLAGS_LOWER_32(flags); + req->svga3d_flags_upper_32_bits = SVGA3D_FLAGS_UPPER_32(flags); + req->base.format = (uint32_t)format; + req->base.drm_surface_flags = drm_vmw_surface_flag_scanout; + req->base.drm_surface_flags |= drm_vmw_surface_flag_shareable; + req->base.drm_surface_flags |= drm_vmw_surface_flag_create_buffer; + req->base.drm_surface_flags |= drm_vmw_surface_flag_coherent; + req->base.base_size.width = args->width; + req->base.base_size.height = args->height; + req->base.base_size.depth = 1; + req->base.array_size = 0; + req->base.mip_levels = 1; + req->base.multisample_count = 0; + req->base.buffer_handle = SVGA3D_INVALID_ID; + req->base.autogen_filter = SVGA3D_TEX_FILTER_NONE; + ret = vmw_gb_surface_define_ext_ioctl(dev, &arg, file_priv); + if (ret) { + drm_warn(dev, "Unable to create a dumb buffer\n"); + return ret; + } + + args->handle = arg.rep.buffer_handle; + args->size = arg.rep.buffer_size; + args->pitch = vmw_surface_calculate_pitch(desc, &drm_size); + + ret = vmw_user_resource_lookup_handle(dev_priv, tfile, arg.rep.handle, + user_surface_converter, + &res); + if (ret) { + drm_err(dev, "Created resource handle doesn't exist!\n"); + goto err; + } + + vbo = res->guest_memory_bo; + vbo->is_dumb = true; + vbo->dumb_surface = vmw_res_to_srf(res); + +err: + if (res) + vmw_resource_unreference(&res); + if (ret) + ttm_ref_object_base_unref(tfile, arg.rep.handle); + + return ret; +} diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_vkms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_vkms.c index 3bfcf671fcd583..8651b788e98bc4 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_vkms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_vkms.c @@ -75,7 +75,7 @@ vmw_surface_sync(struct vmw_private *vmw, return ret; } -static int +static void compute_crc(struct drm_crtc *crtc, struct vmw_surface *surf, u32 *crc) @@ -101,8 +101,6 @@ compute_crc(struct drm_crtc *crtc, } vmw_bo_unmap(bo); - - return 0; } static void @@ -116,7 +114,6 @@ crc_generate_worker(struct work_struct *work) u64 frame_start, frame_end; u32 crc32 = 0; struct vmw_surface *surf = 0; - int ret; spin_lock_irq(&du->vkms.crc_state_lock); crc_pending = du->vkms.crc_pending; @@ -130,22 +127,24 @@ crc_generate_worker(struct work_struct *work) return; spin_lock_irq(&du->vkms.crc_state_lock); - surf = du->vkms.surface; + surf = vmw_surface_reference(du->vkms.surface); spin_unlock_irq(&du->vkms.crc_state_lock); - if (vmw_surface_sync(vmw, surf)) { - drm_warn(crtc->dev, "CRC worker wasn't able to sync the crc surface!\n"); - return; - } + if (surf) { + if (vmw_surface_sync(vmw, surf)) { + drm_warn( + crtc->dev, + "CRC worker wasn't able to sync the crc surface!\n"); + return; + } - ret = compute_crc(crtc, surf, &crc32); - if (ret) - return; + compute_crc(crtc, surf, &crc32); + vmw_surface_unreference(&surf); + } spin_lock_irq(&du->vkms.crc_state_lock); frame_start = du->vkms.frame_start; frame_end = du->vkms.frame_end; - crc_pending = du->vkms.crc_pending; du->vkms.frame_start = 0; du->vkms.frame_end = 0; du->vkms.crc_pending = false; @@ -164,7 +163,7 @@ vmw_vkms_vblank_simulate(struct hrtimer *timer) struct vmw_display_unit *du = container_of(timer, struct vmw_display_unit, vkms.timer); struct drm_crtc *crtc = &du->crtc; struct vmw_private *vmw = vmw_priv(crtc->dev); - struct vmw_surface *surf = NULL; + bool has_surface = false; u64 ret_overrun; bool locked, ret; @@ -179,10 +178,10 @@ vmw_vkms_vblank_simulate(struct hrtimer *timer) WARN_ON(!ret); if (!locked) return HRTIMER_RESTART; - surf = du->vkms.surface; + has_surface = du->vkms.surface != NULL; vmw_vkms_unlock(crtc); - if (du->vkms.crc_enabled && surf) { + if (du->vkms.crc_enabled && has_surface) { u64 frame = drm_crtc_accurate_vblank_count(crtc); spin_lock(&du->vkms.crc_state_lock); @@ -336,6 +335,8 @@ vmw_vkms_crtc_cleanup(struct drm_crtc *crtc) { struct vmw_display_unit *du = vmw_crtc_to_du(crtc); + if (du->vkms.surface) + vmw_surface_unreference(&du->vkms.surface); WARN_ON(work_pending(&du->vkms.crc_generator_work)); hrtimer_cancel(&du->vkms.timer); } @@ -497,9 +498,12 @@ vmw_vkms_set_crc_surface(struct drm_crtc *crtc, struct vmw_display_unit *du = vmw_crtc_to_du(crtc); struct vmw_private *vmw = vmw_priv(crtc->dev); - if (vmw->vkms_enabled) { + if (vmw->vkms_enabled && du->vkms.surface != surf) { WARN_ON(atomic_read(&du->vkms.atomic_lock) != VMW_VKMS_LOCK_MODESET); - du->vkms.surface = surf; + if (du->vkms.surface) + vmw_surface_unreference(&du->vkms.surface); + if (surf) + du->vkms.surface = vmw_surface_reference(surf); } } diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c index 76109415eba61e..f2f1d8ddb22138 100644 --- a/drivers/gpu/drm/xe/xe_device.c +++ b/drivers/gpu/drm/xe/xe_device.c @@ -87,9 +87,55 @@ static int xe_file_open(struct drm_device *dev, struct drm_file *file) spin_unlock(&xe->clients.lock); file->driver_priv = xef; + kref_init(&xef->refcount); + return 0; } +static void xe_file_destroy(struct kref *ref) +{ + struct xe_file *xef = container_of(ref, struct xe_file, refcount); + struct xe_device *xe = xef->xe; + + xa_destroy(&xef->exec_queue.xa); + mutex_destroy(&xef->exec_queue.lock); + xa_destroy(&xef->vm.xa); + mutex_destroy(&xef->vm.lock); + + spin_lock(&xe->clients.lock); + xe->clients.count--; + spin_unlock(&xe->clients.lock); + + xe_drm_client_put(xef->client); + kfree(xef); +} + +/** + * xe_file_get() - Take a reference to the xe file object + * @xef: Pointer to the xe file + * + * Anyone with a pointer to xef must take a reference to the xe file + * object using this call. + * + * Return: xe file pointer + */ +struct xe_file *xe_file_get(struct xe_file *xef) +{ + kref_get(&xef->refcount); + return xef; +} + +/** + * xe_file_put() - Drop a reference to the xe file object + * @xef: Pointer to the xe file + * + * Used to drop reference to the xef object + */ +void xe_file_put(struct xe_file *xef) +{ + kref_put(&xef->refcount, xe_file_destroy); +} + static void xe_file_close(struct drm_device *dev, struct drm_file *file) { struct xe_device *xe = to_xe_device(dev); @@ -98,6 +144,8 @@ static void xe_file_close(struct drm_device *dev, struct drm_file *file) struct xe_exec_queue *q; unsigned long idx; + xe_pm_runtime_get(xe); + /* * No need for exec_queue.lock here as there is no contention for it * when FD is closing as IOCTLs presumably can't be modifying the @@ -108,21 +156,14 @@ static void xe_file_close(struct drm_device *dev, struct drm_file *file) xe_exec_queue_kill(q); xe_exec_queue_put(q); } - xa_destroy(&xef->exec_queue.xa); - mutex_destroy(&xef->exec_queue.lock); mutex_lock(&xef->vm.lock); xa_for_each(&xef->vm.xa, idx, vm) xe_vm_close_and_put(vm); mutex_unlock(&xef->vm.lock); - xa_destroy(&xef->vm.xa); - mutex_destroy(&xef->vm.lock); - spin_lock(&xe->clients.lock); - xe->clients.count--; - spin_unlock(&xe->clients.lock); + xe_file_put(xef); - xe_drm_client_put(xef->client); - kfree(xef); + xe_pm_runtime_put(xe); } static const struct drm_ioctl_desc xe_ioctls[] = { diff --git a/drivers/gpu/drm/xe/xe_device.h b/drivers/gpu/drm/xe/xe_device.h index bb07f5669dbb35..b3952718b3c1cb 100644 --- a/drivers/gpu/drm/xe/xe_device.h +++ b/drivers/gpu/drm/xe/xe_device.h @@ -170,4 +170,7 @@ static inline bool xe_device_wedged(struct xe_device *xe) void xe_device_declare_wedged(struct xe_device *xe); +struct xe_file *xe_file_get(struct xe_file *xef); +void xe_file_put(struct xe_file *xef); + #endif diff --git a/drivers/gpu/drm/xe/xe_device_types.h b/drivers/gpu/drm/xe/xe_device_types.h index 3bca6d344744ac..cbc582bcc90a5f 100644 --- a/drivers/gpu/drm/xe/xe_device_types.h +++ b/drivers/gpu/drm/xe/xe_device_types.h @@ -566,6 +566,9 @@ struct xe_file { /** @client: drm client */ struct xe_drm_client *client; + + /** @refcount: ref count of this xe file */ + struct kref refcount; }; #endif diff --git a/drivers/gpu/drm/xe/xe_drm_client.c b/drivers/gpu/drm/xe/xe_drm_client.c index 6a26923fa10e0f..7ddd59908334c5 100644 --- a/drivers/gpu/drm/xe/xe_drm_client.c +++ b/drivers/gpu/drm/xe/xe_drm_client.c @@ -251,11 +251,8 @@ static void show_run_ticks(struct drm_printer *p, struct drm_file *file) /* Accumulate all the exec queues from this client */ mutex_lock(&xef->exec_queue.lock); - xa_for_each(&xef->exec_queue.xa, i, q) { + xa_for_each(&xef->exec_queue.xa, i, q) xe_exec_queue_update_run_ticks(q); - xef->run_ticks[q->class] += q->run_ticks - q->old_run_ticks; - q->old_run_ticks = q->run_ticks; - } mutex_unlock(&xef->exec_queue.lock); /* Get the total GPU cycles */ diff --git a/drivers/gpu/drm/xe/xe_exec_queue.c b/drivers/gpu/drm/xe/xe_exec_queue.c index 0ba37835849b01..a39384bb9553ff 100644 --- a/drivers/gpu/drm/xe/xe_exec_queue.c +++ b/drivers/gpu/drm/xe/xe_exec_queue.c @@ -37,6 +37,10 @@ static void __xe_exec_queue_free(struct xe_exec_queue *q) { if (q->vm) xe_vm_put(q->vm); + + if (q->xef) + xe_file_put(q->xef); + kfree(q); } @@ -649,6 +653,7 @@ int xe_exec_queue_create_ioctl(struct drm_device *dev, void *data, goto kill_exec_queue; args->exec_queue_id = id; + q->xef = xe_file_get(xef); return 0; @@ -762,6 +767,7 @@ bool xe_exec_queue_is_idle(struct xe_exec_queue *q) */ void xe_exec_queue_update_run_ticks(struct xe_exec_queue *q) { + struct xe_file *xef; struct xe_lrc *lrc; u32 old_ts, new_ts; @@ -773,6 +779,8 @@ void xe_exec_queue_update_run_ticks(struct xe_exec_queue *q) if (!q->vm || !q->vm->xef) return; + xef = q->vm->xef; + /* * Only sample the first LRC. For parallel submission, all of them are * scheduled together and we compensate that below by multiplying by @@ -783,7 +791,7 @@ void xe_exec_queue_update_run_ticks(struct xe_exec_queue *q) */ lrc = q->lrc[0]; new_ts = xe_lrc_update_timestamp(lrc, &old_ts); - q->run_ticks += (new_ts - old_ts) * q->width; + xef->run_ticks[q->class] += (new_ts - old_ts) * q->width; } void xe_exec_queue_kill(struct xe_exec_queue *q) diff --git a/drivers/gpu/drm/xe/xe_exec_queue_types.h b/drivers/gpu/drm/xe/xe_exec_queue_types.h index 201588ec33c359..a35ce24c97982c 100644 --- a/drivers/gpu/drm/xe/xe_exec_queue_types.h +++ b/drivers/gpu/drm/xe/xe_exec_queue_types.h @@ -38,6 +38,9 @@ enum xe_exec_queue_priority { * a kernel object. */ struct xe_exec_queue { + /** @xef: Back pointer to xe file if this is user created exec queue */ + struct xe_file *xef; + /** @gt: graphics tile this exec queue can submit to */ struct xe_gt *gt; /** @@ -139,10 +142,6 @@ struct xe_exec_queue { * Protected by @vm's resv. Unused if @vm == NULL. */ u64 tlb_flush_seqno; - /** @old_run_ticks: prior hw engine class run time in ticks for this exec queue */ - u64 old_run_ticks; - /** @run_ticks: hw engine class run time in ticks for this exec queue */ - u64 run_ticks; /** @lrc: logical ring context for this exec queue */ struct xe_lrc *lrc[]; }; diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c b/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c index 4699b78360013c..b6f0a7299c0309 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c +++ b/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c @@ -1927,6 +1927,7 @@ static int pf_validate_vf_config(struct xe_gt *gt, unsigned int vfid) { struct xe_gt *primary_gt = gt_to_tile(gt)->primary_gt; struct xe_device *xe = gt_to_xe(gt); + bool is_primary = !xe_gt_is_media_type(gt); bool valid_ggtt, valid_ctxs, valid_dbs; bool valid_any, valid_all; @@ -1935,13 +1936,17 @@ static int pf_validate_vf_config(struct xe_gt *gt, unsigned int vfid) valid_dbs = pf_get_vf_config_dbs(gt, vfid); /* note that GuC doorbells are optional */ - valid_any = valid_ggtt || valid_ctxs || valid_dbs; - valid_all = valid_ggtt && valid_ctxs; + valid_any = valid_ctxs || valid_dbs; + valid_all = valid_ctxs; + + /* and GGTT/LMEM is configured on primary GT only */ + valid_all = valid_all && valid_ggtt; + valid_any = valid_any || (valid_ggtt && is_primary); if (IS_DGFX(xe)) { bool valid_lmem = pf_get_vf_config_ggtt(primary_gt, vfid); - valid_any = valid_any || valid_lmem; + valid_any = valid_any || (valid_lmem && is_primary); valid_all = valid_all && valid_lmem; } diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_vf.c b/drivers/gpu/drm/xe/xe_gt_sriov_vf.c index 41e46a00c01e89..8892d6c2291ebb 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_vf.c +++ b/drivers/gpu/drm/xe/xe_gt_sriov_vf.c @@ -850,7 +850,7 @@ static struct vf_runtime_reg *vf_lookup_reg(struct xe_gt *gt, u32 addr) xe_gt_assert(gt, IS_SRIOV_VF(gt_to_xe(gt))); - return bsearch(&key, runtime->regs, runtime->regs_size, sizeof(key), + return bsearch(&key, runtime->regs, runtime->num_regs, sizeof(key), vf_runtime_reg_cmp); } diff --git a/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.c b/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.c index d9359976ab8bb6..481d83d07367d2 100644 --- a/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.c +++ b/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.c @@ -13,10 +13,13 @@ #include "xe_guc.h" #include "xe_guc_ct.h" #include "xe_mmio.h" +#include "xe_pm.h" #include "xe_sriov.h" #include "xe_trace.h" #include "regs/xe_guc_regs.h" +#define FENCE_STACK_BIT DMA_FENCE_FLAG_USER_BITS + /* * TLB inval depends on pending commands in the CT queue and then the real * invalidation time. Double up the time to process full CT queue @@ -33,6 +36,24 @@ static long tlb_timeout_jiffies(struct xe_gt *gt) return hw_tlb_timeout + 2 * delay; } +static void +__invalidation_fence_signal(struct xe_device *xe, struct xe_gt_tlb_invalidation_fence *fence) +{ + bool stack = test_bit(FENCE_STACK_BIT, &fence->base.flags); + + trace_xe_gt_tlb_invalidation_fence_signal(xe, fence); + xe_gt_tlb_invalidation_fence_fini(fence); + dma_fence_signal(&fence->base); + if (!stack) + dma_fence_put(&fence->base); +} + +static void +invalidation_fence_signal(struct xe_device *xe, struct xe_gt_tlb_invalidation_fence *fence) +{ + list_del(&fence->link); + __invalidation_fence_signal(xe, fence); +} static void xe_gt_tlb_fence_timeout(struct work_struct *work) { @@ -54,10 +75,8 @@ static void xe_gt_tlb_fence_timeout(struct work_struct *work) xe_gt_err(gt, "TLB invalidation fence timeout, seqno=%d recv=%d", fence->seqno, gt->tlb_invalidation.seqno_recv); - list_del(&fence->link); fence->base.error = -ETIME; - dma_fence_signal(&fence->base); - dma_fence_put(&fence->base); + invalidation_fence_signal(xe, fence); } if (!list_empty(>->tlb_invalidation.pending_fences)) queue_delayed_work(system_wq, @@ -87,21 +106,6 @@ int xe_gt_tlb_invalidation_init(struct xe_gt *gt) return 0; } -static void -__invalidation_fence_signal(struct xe_device *xe, struct xe_gt_tlb_invalidation_fence *fence) -{ - trace_xe_gt_tlb_invalidation_fence_signal(xe, fence); - dma_fence_signal(&fence->base); - dma_fence_put(&fence->base); -} - -static void -invalidation_fence_signal(struct xe_device *xe, struct xe_gt_tlb_invalidation_fence *fence) -{ - list_del(&fence->link); - __invalidation_fence_signal(xe, fence); -} - /** * xe_gt_tlb_invalidation_reset - Initialize GT TLB invalidation reset * @gt: graphics tile @@ -111,7 +115,6 @@ invalidation_fence_signal(struct xe_device *xe, struct xe_gt_tlb_invalidation_fe void xe_gt_tlb_invalidation_reset(struct xe_gt *gt) { struct xe_gt_tlb_invalidation_fence *fence, *next; - struct xe_guc *guc = >->uc.guc; int pending_seqno; /* @@ -134,7 +137,6 @@ void xe_gt_tlb_invalidation_reset(struct xe_gt *gt) else pending_seqno = gt->tlb_invalidation.seqno - 1; WRITE_ONCE(gt->tlb_invalidation.seqno_recv, pending_seqno); - wake_up_all(&guc->ct.wq); list_for_each_entry_safe(fence, next, >->tlb_invalidation.pending_fences, link) @@ -165,6 +167,8 @@ static int send_tlb_invalidation(struct xe_guc *guc, int seqno; int ret; + xe_gt_assert(gt, fence); + /* * XXX: The seqno algorithm relies on TLB invalidation being processed * in order which they currently are, if that changes the algorithm will @@ -173,10 +177,8 @@ static int send_tlb_invalidation(struct xe_guc *guc, mutex_lock(&guc->ct.lock); seqno = gt->tlb_invalidation.seqno; - if (fence) { - fence->seqno = seqno; - trace_xe_gt_tlb_invalidation_fence_send(xe, fence); - } + fence->seqno = seqno; + trace_xe_gt_tlb_invalidation_fence_send(xe, fence); action[1] = seqno; ret = xe_guc_ct_send_locked(&guc->ct, action, len, G2H_LEN_DW_TLB_INVALIDATE, 1); @@ -209,7 +211,6 @@ static int send_tlb_invalidation(struct xe_guc *guc, TLB_INVALIDATION_SEQNO_MAX; if (!gt->tlb_invalidation.seqno) gt->tlb_invalidation.seqno = 1; - ret = seqno; } mutex_unlock(&guc->ct.lock); @@ -223,14 +224,16 @@ static int send_tlb_invalidation(struct xe_guc *guc, /** * xe_gt_tlb_invalidation_guc - Issue a TLB invalidation on this GT for the GuC * @gt: graphics tile + * @fence: invalidation fence which will be signal on TLB invalidation + * completion * * Issue a TLB invalidation for the GuC. Completion of TLB is asynchronous and - * caller can use seqno + xe_gt_tlb_invalidation_wait to wait for completion. + * caller can use the invalidation fence to wait for completion. * - * Return: Seqno which can be passed to xe_gt_tlb_invalidation_wait on success, - * negative error code on error. + * Return: 0 on success, negative error code on error */ -static int xe_gt_tlb_invalidation_guc(struct xe_gt *gt) +static int xe_gt_tlb_invalidation_guc(struct xe_gt *gt, + struct xe_gt_tlb_invalidation_fence *fence) { u32 action[] = { XE_GUC_ACTION_TLB_INVALIDATION, @@ -238,7 +241,7 @@ static int xe_gt_tlb_invalidation_guc(struct xe_gt *gt) MAKE_INVAL_OP(XE_GUC_TLB_INVAL_GUC), }; - return send_tlb_invalidation(>->uc.guc, NULL, action, + return send_tlb_invalidation(>->uc.guc, fence, action, ARRAY_SIZE(action)); } @@ -257,13 +260,17 @@ int xe_gt_tlb_invalidation_ggtt(struct xe_gt *gt) if (xe_guc_ct_enabled(>->uc.guc.ct) && gt->uc.guc.submission_state.enabled) { - int seqno; - - seqno = xe_gt_tlb_invalidation_guc(gt); - if (seqno <= 0) - return seqno; + struct xe_gt_tlb_invalidation_fence fence; + int ret; + + xe_gt_tlb_invalidation_fence_init(gt, &fence, true); + ret = xe_gt_tlb_invalidation_guc(gt, &fence); + if (ret < 0) { + xe_gt_tlb_invalidation_fence_fini(&fence); + return ret; + } - xe_gt_tlb_invalidation_wait(gt, seqno); + xe_gt_tlb_invalidation_fence_wait(&fence); } else if (xe_device_uc_enabled(xe) && !xe_device_wedged(xe)) { if (IS_SRIOV_VF(xe)) return 0; @@ -290,18 +297,16 @@ int xe_gt_tlb_invalidation_ggtt(struct xe_gt *gt) * * @gt: graphics tile * @fence: invalidation fence which will be signal on TLB invalidation - * completion, can be NULL + * completion * @start: start address * @end: end address * @asid: address space id * * Issue a range based TLB invalidation if supported, if not fallback to a full - * TLB invalidation. Completion of TLB is asynchronous and caller can either use - * the invalidation fence or seqno + xe_gt_tlb_invalidation_wait to wait for - * completion. + * TLB invalidation. Completion of TLB is asynchronous and caller can use + * the invalidation fence to wait for completion. * - * Return: Seqno which can be passed to xe_gt_tlb_invalidation_wait on success, - * negative error code on error. + * Return: Negative error code on error, 0 on success */ int xe_gt_tlb_invalidation_range(struct xe_gt *gt, struct xe_gt_tlb_invalidation_fence *fence, @@ -312,11 +317,11 @@ int xe_gt_tlb_invalidation_range(struct xe_gt *gt, u32 action[MAX_TLB_INVALIDATION_LEN]; int len = 0; + xe_gt_assert(gt, fence); + /* Execlists not supported */ if (gt_to_xe(gt)->info.force_execlist) { - if (fence) - __invalidation_fence_signal(xe, fence); - + __invalidation_fence_signal(xe, fence); return 0; } @@ -382,12 +387,10 @@ int xe_gt_tlb_invalidation_range(struct xe_gt *gt, * @vma: VMA to invalidate * * Issue a range based TLB invalidation if supported, if not fallback to a full - * TLB invalidation. Completion of TLB is asynchronous and caller can either use - * the invalidation fence or seqno + xe_gt_tlb_invalidation_wait to wait for - * completion. + * TLB invalidation. Completion of TLB is asynchronous and caller can use + * the invalidation fence to wait for completion. * - * Return: Seqno which can be passed to xe_gt_tlb_invalidation_wait on success, - * negative error code on error. + * Return: Negative error code on error, 0 on success */ int xe_gt_tlb_invalidation_vma(struct xe_gt *gt, struct xe_gt_tlb_invalidation_fence *fence, @@ -400,43 +403,6 @@ int xe_gt_tlb_invalidation_vma(struct xe_gt *gt, xe_vma_vm(vma)->usm.asid); } -/** - * xe_gt_tlb_invalidation_wait - Wait for TLB to complete - * @gt: graphics tile - * @seqno: seqno to wait which was returned from xe_gt_tlb_invalidation - * - * Wait for tlb_timeout_jiffies() for a TLB invalidation to complete. - * - * Return: 0 on success, -ETIME on TLB invalidation timeout - */ -int xe_gt_tlb_invalidation_wait(struct xe_gt *gt, int seqno) -{ - struct xe_guc *guc = >->uc.guc; - int ret; - - /* Execlists not supported */ - if (gt_to_xe(gt)->info.force_execlist) - return 0; - - /* - * XXX: See above, this algorithm only works if seqno are always in - * order - */ - ret = wait_event_timeout(guc->ct.wq, - tlb_invalidation_seqno_past(gt, seqno), - tlb_timeout_jiffies(gt)); - if (!ret) { - struct drm_printer p = xe_gt_err_printer(gt); - - xe_gt_err(gt, "TLB invalidation time'd out, seqno=%d, recv=%d\n", - seqno, gt->tlb_invalidation.seqno_recv); - xe_guc_ct_print(&guc->ct, &p, true); - return -ETIME; - } - - return 0; -} - /** * xe_guc_tlb_invalidation_done_handler - TLB invalidation done handler * @guc: guc @@ -480,12 +446,7 @@ int xe_guc_tlb_invalidation_done_handler(struct xe_guc *guc, u32 *msg, u32 len) return 0; } - /* - * wake_up_all() and wait_event_timeout() already have the correct - * barriers. - */ WRITE_ONCE(gt->tlb_invalidation.seqno_recv, msg[0]); - wake_up_all(&guc->ct.wq); list_for_each_entry_safe(fence, next, >->tlb_invalidation.pending_fences, link) { @@ -508,3 +469,59 @@ int xe_guc_tlb_invalidation_done_handler(struct xe_guc *guc, u32 *msg, u32 len) return 0; } + +static const char * +invalidation_fence_get_driver_name(struct dma_fence *dma_fence) +{ + return "xe"; +} + +static const char * +invalidation_fence_get_timeline_name(struct dma_fence *dma_fence) +{ + return "invalidation_fence"; +} + +static const struct dma_fence_ops invalidation_fence_ops = { + .get_driver_name = invalidation_fence_get_driver_name, + .get_timeline_name = invalidation_fence_get_timeline_name, +}; + +/** + * xe_gt_tlb_invalidation_fence_init - Initialize TLB invalidation fence + * @gt: GT + * @fence: TLB invalidation fence to initialize + * @stack: fence is stack variable + * + * Initialize TLB invalidation fence for use. xe_gt_tlb_invalidation_fence_fini + * must be called if fence is not signaled. + */ +void xe_gt_tlb_invalidation_fence_init(struct xe_gt *gt, + struct xe_gt_tlb_invalidation_fence *fence, + bool stack) +{ + xe_pm_runtime_get_noresume(gt_to_xe(gt)); + + spin_lock_irq(>->tlb_invalidation.lock); + dma_fence_init(&fence->base, &invalidation_fence_ops, + >->tlb_invalidation.lock, + dma_fence_context_alloc(1), 1); + spin_unlock_irq(>->tlb_invalidation.lock); + INIT_LIST_HEAD(&fence->link); + if (stack) + set_bit(FENCE_STACK_BIT, &fence->base.flags); + else + dma_fence_get(&fence->base); + fence->gt = gt; +} + +/** + * xe_gt_tlb_invalidation_fence_fini - Finalize TLB invalidation fence + * @fence: TLB invalidation fence to finalize + * + * Drop PM ref which fence took durinig init. + */ +void xe_gt_tlb_invalidation_fence_fini(struct xe_gt_tlb_invalidation_fence *fence) +{ + xe_pm_runtime_put(gt_to_xe(fence->gt)); +} diff --git a/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.h b/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.h index bf3bebd9f985ba..a84065fa324c76 100644 --- a/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.h +++ b/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.h @@ -23,7 +23,17 @@ int xe_gt_tlb_invalidation_vma(struct xe_gt *gt, int xe_gt_tlb_invalidation_range(struct xe_gt *gt, struct xe_gt_tlb_invalidation_fence *fence, u64 start, u64 end, u32 asid); -int xe_gt_tlb_invalidation_wait(struct xe_gt *gt, int seqno); int xe_guc_tlb_invalidation_done_handler(struct xe_guc *guc, u32 *msg, u32 len); +void xe_gt_tlb_invalidation_fence_init(struct xe_gt *gt, + struct xe_gt_tlb_invalidation_fence *fence, + bool stack); +void xe_gt_tlb_invalidation_fence_fini(struct xe_gt_tlb_invalidation_fence *fence); + +static inline void +xe_gt_tlb_invalidation_fence_wait(struct xe_gt_tlb_invalidation_fence *fence) +{ + dma_fence_wait(&fence->base, false); +} + #endif /* _XE_GT_TLB_INVALIDATION_ */ diff --git a/drivers/gpu/drm/xe/xe_gt_tlb_invalidation_types.h b/drivers/gpu/drm/xe/xe_gt_tlb_invalidation_types.h index 934c828efe31cb..de6e825e0851e5 100644 --- a/drivers/gpu/drm/xe/xe_gt_tlb_invalidation_types.h +++ b/drivers/gpu/drm/xe/xe_gt_tlb_invalidation_types.h @@ -8,6 +8,8 @@ #include +struct xe_gt; + /** * struct xe_gt_tlb_invalidation_fence - XE GT TLB invalidation fence * @@ -17,6 +19,8 @@ struct xe_gt_tlb_invalidation_fence { /** @base: dma fence base */ struct dma_fence base; + /** @gt: GT which fence belong to */ + struct xe_gt *gt; /** @link: link into list of pending tlb fences */ struct list_head link; /** @seqno: seqno of TLB invalidation to signal fence one */ diff --git a/drivers/gpu/drm/xe/xe_guc_ct.c b/drivers/gpu/drm/xe/xe_guc_ct.c index 7d2e937da1d83d..64afc90ad2c519 100644 --- a/drivers/gpu/drm/xe/xe_guc_ct.c +++ b/drivers/gpu/drm/xe/xe_guc_ct.c @@ -327,6 +327,8 @@ static void xe_guc_ct_set_state(struct xe_guc_ct *ct, xe_gt_assert(ct_to_gt(ct), ct->g2h_outstanding == 0 || state == XE_GUC_CT_STATE_STOPPED); + if (ct->g2h_outstanding) + xe_pm_runtime_put(ct_to_xe(ct)); ct->g2h_outstanding = 0; ct->state = state; @@ -495,10 +497,15 @@ static void h2g_reserve_space(struct xe_guc_ct *ct, u32 cmd_len) static void __g2h_reserve_space(struct xe_guc_ct *ct, u32 g2h_len, u32 num_g2h) { xe_gt_assert(ct_to_gt(ct), g2h_len <= ct->ctbs.g2h.info.space); + xe_gt_assert(ct_to_gt(ct), (!g2h_len && !num_g2h) || + (g2h_len && num_g2h)); if (g2h_len) { lockdep_assert_held(&ct->fast_lock); + if (!ct->g2h_outstanding) + xe_pm_runtime_get_noresume(ct_to_xe(ct)); + ct->ctbs.g2h.info.space -= g2h_len; ct->g2h_outstanding += num_g2h; } @@ -511,7 +518,8 @@ static void __g2h_release_space(struct xe_guc_ct *ct, u32 g2h_len) ct->ctbs.g2h.info.size - ct->ctbs.g2h.info.resv_space); ct->ctbs.g2h.info.space += g2h_len; - --ct->g2h_outstanding; + if (!--ct->g2h_outstanding) + xe_pm_runtime_put(ct_to_xe(ct)); } static void g2h_release_space(struct xe_guc_ct *ct, u32 g2h_len) diff --git a/drivers/gpu/drm/xe/xe_guc_submit.c b/drivers/gpu/drm/xe/xe_guc_submit.c index 8d7e7f4bbff716..6398629e6b4ecd 100644 --- a/drivers/gpu/drm/xe/xe_guc_submit.c +++ b/drivers/gpu/drm/xe/xe_guc_submit.c @@ -1393,6 +1393,8 @@ static void guc_exec_queue_process_msg(struct xe_sched_msg *msg) default: XE_WARN_ON("Unknown message type"); } + + xe_pm_runtime_put(guc_to_xe(exec_queue_to_guc(msg->private_data))); } static const struct drm_sched_backend_ops drm_sched_ops = { @@ -1482,6 +1484,8 @@ static void guc_exec_queue_kill(struct xe_exec_queue *q) static void guc_exec_queue_add_msg(struct xe_exec_queue *q, struct xe_sched_msg *msg, u32 opcode) { + xe_pm_runtime_get_noresume(guc_to_xe(exec_queue_to_guc(q))); + INIT_LIST_HEAD(&msg->link); msg->opcode = opcode; msg->private_data = q; diff --git a/drivers/gpu/drm/xe/xe_hwmon.c b/drivers/gpu/drm/xe/xe_hwmon.c index 0c8ce09e502505..832ea81faeee50 100644 --- a/drivers/gpu/drm/xe/xe_hwmon.c +++ b/drivers/gpu/drm/xe/xe_hwmon.c @@ -203,9 +203,10 @@ static int xe_hwmon_power_max_write(struct xe_hwmon *hwmon, int channel, long va reg_val = xe_mmio_rmw32(hwmon->gt, rapl_limit, PKG_PWR_LIM_1_EN, 0); reg_val = xe_mmio_read32(hwmon->gt, rapl_limit); if (reg_val & PKG_PWR_LIM_1_EN) { + drm_warn(>_to_xe(hwmon->gt)->drm, "PL1 disable is not supported!\n"); ret = -EOPNOTSUPP; - goto unlock; } + goto unlock; } /* Computation in 64-bits to avoid overflow. Round to nearest. */ diff --git a/drivers/gpu/drm/xe/xe_lrc.c b/drivers/gpu/drm/xe/xe_lrc.c index 94ff62e1d95eb1..58121821f0814a 100644 --- a/drivers/gpu/drm/xe/xe_lrc.c +++ b/drivers/gpu/drm/xe/xe_lrc.c @@ -1634,6 +1634,9 @@ struct xe_lrc_snapshot *xe_lrc_snapshot_capture(struct xe_lrc *lrc) if (!snapshot) return NULL; + if (lrc->bo && lrc->bo->vm) + xe_vm_get(lrc->bo->vm); + snapshot->context_desc = xe_lrc_ggtt_addr(lrc); snapshot->indirect_context_desc = xe_lrc_indirect_ring_ggtt_addr(lrc); snapshot->head = xe_lrc_ring_head(lrc); @@ -1653,12 +1656,14 @@ struct xe_lrc_snapshot *xe_lrc_snapshot_capture(struct xe_lrc *lrc) void xe_lrc_snapshot_capture_delayed(struct xe_lrc_snapshot *snapshot) { struct xe_bo *bo; + struct xe_vm *vm; struct iosys_map src; if (!snapshot) return; bo = snapshot->lrc_bo; + vm = bo->vm; snapshot->lrc_bo = NULL; snapshot->lrc_snapshot = kvmalloc(snapshot->lrc_size, GFP_KERNEL); @@ -1678,6 +1683,8 @@ void xe_lrc_snapshot_capture_delayed(struct xe_lrc_snapshot *snapshot) xe_bo_unlock(bo); put_bo: xe_bo_put(bo); + if (vm) + xe_vm_put(vm); } void xe_lrc_snapshot_print(struct xe_lrc_snapshot *snapshot, struct drm_printer *p) @@ -1727,8 +1734,14 @@ void xe_lrc_snapshot_free(struct xe_lrc_snapshot *snapshot) return; kvfree(snapshot->lrc_snapshot); - if (snapshot->lrc_bo) + if (snapshot->lrc_bo) { + struct xe_vm *vm; + + vm = snapshot->lrc_bo->vm; xe_bo_put(snapshot->lrc_bo); + if (vm) + xe_vm_put(vm); + } kfree(snapshot); } diff --git a/drivers/gpu/drm/xe/xe_pt.c b/drivers/gpu/drm/xe/xe_pt.c index ade9e7a3a0adb4..31a751a5de3f1f 100644 --- a/drivers/gpu/drm/xe/xe_pt.c +++ b/drivers/gpu/drm/xe/xe_pt.c @@ -1115,23 +1115,6 @@ struct invalidation_fence { u32 asid; }; -static const char * -invalidation_fence_get_driver_name(struct dma_fence *dma_fence) -{ - return "xe"; -} - -static const char * -invalidation_fence_get_timeline_name(struct dma_fence *dma_fence) -{ - return "invalidation_fence"; -} - -static const struct dma_fence_ops invalidation_fence_ops = { - .get_driver_name = invalidation_fence_get_driver_name, - .get_timeline_name = invalidation_fence_get_timeline_name, -}; - static void invalidation_fence_cb(struct dma_fence *fence, struct dma_fence_cb *cb) { @@ -1170,15 +1153,8 @@ static int invalidation_fence_init(struct xe_gt *gt, trace_xe_gt_tlb_invalidation_fence_create(gt_to_xe(gt), &ifence->base); - spin_lock_irq(>->tlb_invalidation.lock); - dma_fence_init(&ifence->base.base, &invalidation_fence_ops, - >->tlb_invalidation.lock, - dma_fence_context_alloc(1), 1); - spin_unlock_irq(>->tlb_invalidation.lock); - - INIT_LIST_HEAD(&ifence->base.link); + xe_gt_tlb_invalidation_fence_init(gt, &ifence->base, false); - dma_fence_get(&ifence->base.base); /* Ref for caller */ ifence->fence = fence; ifence->gt = gt; ifence->start = start; diff --git a/drivers/gpu/drm/xe/xe_rtp.c b/drivers/gpu/drm/xe/xe_rtp.c index 02e28274282f93..5efe83cc82ab5e 100644 --- a/drivers/gpu/drm/xe/xe_rtp.c +++ b/drivers/gpu/drm/xe/xe_rtp.c @@ -231,7 +231,7 @@ static void rtp_mark_active(struct xe_device *xe, if (first == last) bitmap_set(ctx->active_entries, first, 1); else - bitmap_set(ctx->active_entries, first, last - first + 2); + bitmap_set(ctx->active_entries, first, last - first + 1); } /** diff --git a/drivers/gpu/drm/xe/xe_sync.c b/drivers/gpu/drm/xe/xe_sync.c index 2883d9aca404e6..e8d31e01086019 100644 --- a/drivers/gpu/drm/xe/xe_sync.c +++ b/drivers/gpu/drm/xe/xe_sync.c @@ -53,14 +53,18 @@ static struct xe_user_fence *user_fence_create(struct xe_device *xe, u64 addr, u64 value) { struct xe_user_fence *ufence; + u64 __user *ptr = u64_to_user_ptr(addr); + + if (!access_ok(ptr, sizeof(ptr))) + return ERR_PTR(-EFAULT); ufence = kmalloc(sizeof(*ufence), GFP_KERNEL); if (!ufence) - return NULL; + return ERR_PTR(-ENOMEM); ufence->xe = xe; kref_init(&ufence->refcount); - ufence->addr = u64_to_user_ptr(addr); + ufence->addr = ptr; ufence->value = value; ufence->mm = current->mm; mmgrab(ufence->mm); @@ -183,8 +187,8 @@ int xe_sync_entry_parse(struct xe_device *xe, struct xe_file *xef, } else { sync->ufence = user_fence_create(xe, sync_in.addr, sync_in.timeline_value); - if (XE_IOCTL_DBG(xe, !sync->ufence)) - return -ENOMEM; + if (XE_IOCTL_DBG(xe, IS_ERR(sync->ufence))) + return PTR_ERR(sync->ufence); } break; @@ -263,7 +267,7 @@ void xe_sync_entry_cleanup(struct xe_sync_entry *sync) if (sync->fence) dma_fence_put(sync->fence); if (sync->chain_fence) - dma_fence_put(&sync->chain_fence->base); + dma_fence_chain_free(sync->chain_fence); if (sync->ufence) user_fence_put(sync->ufence); } diff --git a/drivers/gpu/drm/xe/xe_ttm_vram_mgr.c b/drivers/gpu/drm/xe/xe_ttm_vram_mgr.c index fe3779fdba2c86..423b261ea74305 100644 --- a/drivers/gpu/drm/xe/xe_ttm_vram_mgr.c +++ b/drivers/gpu/drm/xe/xe_ttm_vram_mgr.c @@ -150,7 +150,7 @@ static int xe_ttm_vram_mgr_new(struct ttm_resource_manager *man, } while (remaining_size); if (place->flags & TTM_PL_FLAG_CONTIGUOUS) { - if (!drm_buddy_block_trim(mm, vres->base.size, &vres->blocks)) + if (!drm_buddy_block_trim(mm, NULL, vres->base.size, &vres->blocks)) size = vres->base.size; } diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c index 5b166fa03684e2..c7561a56abaf20 100644 --- a/drivers/gpu/drm/xe/xe_vm.c +++ b/drivers/gpu/drm/xe/xe_vm.c @@ -1601,6 +1601,10 @@ static void vm_destroy_work_func(struct work_struct *w) XE_WARN_ON(vm->pt_root[id]); trace_xe_vm_free(vm); + + if (vm->xef) + xe_file_put(vm->xef); + kfree(vm); } @@ -1916,7 +1920,7 @@ int xe_vm_create_ioctl(struct drm_device *dev, void *data, } args->vm_id = id; - vm->xef = xef; + vm->xef = xe_file_get(xef); /* Record BO memory for VM pagetable created against client */ for_each_tile(tile, xe, id) @@ -3337,10 +3341,10 @@ int xe_vm_invalidate_vma(struct xe_vma *vma) { struct xe_device *xe = xe_vma_vm(vma)->xe; struct xe_tile *tile; + struct xe_gt_tlb_invalidation_fence fence[XE_MAX_TILES_PER_DEVICE]; u32 tile_needs_invalidate = 0; - int seqno[XE_MAX_TILES_PER_DEVICE]; u8 id; - int ret; + int ret = 0; xe_assert(xe, !xe_vma_is_null(vma)); trace_xe_vma_invalidate(vma); @@ -3365,29 +3369,33 @@ int xe_vm_invalidate_vma(struct xe_vma *vma) for_each_tile(tile, xe, id) { if (xe_pt_zap_ptes(tile, vma)) { - tile_needs_invalidate |= BIT(id); xe_device_wmb(xe); + xe_gt_tlb_invalidation_fence_init(tile->primary_gt, + &fence[id], true); + /* * FIXME: We potentially need to invalidate multiple * GTs within the tile */ - seqno[id] = xe_gt_tlb_invalidation_vma(tile->primary_gt, NULL, vma); - if (seqno[id] < 0) - return seqno[id]; - } - } + ret = xe_gt_tlb_invalidation_vma(tile->primary_gt, + &fence[id], vma); + if (ret < 0) { + xe_gt_tlb_invalidation_fence_fini(&fence[id]); + goto wait; + } - for_each_tile(tile, xe, id) { - if (tile_needs_invalidate & BIT(id)) { - ret = xe_gt_tlb_invalidation_wait(tile->primary_gt, seqno[id]); - if (ret < 0) - return ret; + tile_needs_invalidate |= BIT(id); } } +wait: + for_each_tile(tile, xe, id) + if (tile_needs_invalidate & BIT(id)) + xe_gt_tlb_invalidation_fence_wait(&fence[id]); + vma->tile_invalidated = vma->tile_mask; - return 0; + return ret; } struct xe_vm_snapshot { diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_client.c b/drivers/hid/amd-sfh-hid/amd_sfh_client.c index bdb578e0899f55..4b59687ff5d821 100644 --- a/drivers/hid/amd-sfh-hid/amd_sfh_client.c +++ b/drivers/hid/amd-sfh-hid/amd_sfh_client.c @@ -288,12 +288,22 @@ int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata) mp2_ops->start(privdata, info); cl_data->sensor_sts[i] = amd_sfh_wait_for_response (privdata, cl_data->sensor_idx[i], SENSOR_ENABLED); + + if (cl_data->sensor_sts[i] == SENSOR_ENABLED) + cl_data->is_any_sensor_enabled = true; + } + + if (!cl_data->is_any_sensor_enabled || + (mp2_ops->discovery_status && mp2_ops->discovery_status(privdata) == 0)) { + dev_warn(dev, "Failed to discover, sensors not enabled is %d\n", + cl_data->is_any_sensor_enabled); + rc = -EOPNOTSUPP; + goto cleanup; } for (i = 0; i < cl_data->num_hid_devices; i++) { cl_data->cur_hid_dev = i; if (cl_data->sensor_sts[i] == SENSOR_ENABLED) { - cl_data->is_any_sensor_enabled = true; rc = amdtp_hid_probe(i, cl_data); if (rc) goto cleanup; @@ -305,12 +315,6 @@ int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata) cl_data->sensor_sts[i]); } - if (!cl_data->is_any_sensor_enabled || - (mp2_ops->discovery_status && mp2_ops->discovery_status(privdata) == 0)) { - dev_warn(dev, "Failed to discover, sensors not enabled is %d\n", cl_data->is_any_sensor_enabled); - rc = -EOPNOTSUPP; - goto cleanup; - } schedule_delayed_work(&cl_data->work_buffer, msecs_to_jiffies(AMD_SFH_IDLE_LOOP)); return 0; diff --git a/drivers/hid/bpf/Kconfig b/drivers/hid/bpf/Kconfig index 83214bae67687a..d65482e02a6c27 100644 --- a/drivers/hid/bpf/Kconfig +++ b/drivers/hid/bpf/Kconfig @@ -3,7 +3,7 @@ menu "HID-BPF support" config HID_BPF bool "HID-BPF support" - depends on BPF + depends on BPF_JIT depends on BPF_SYSCALL depends on DYNAMIC_FTRACE_WITH_DIRECT_CALLS help diff --git a/drivers/hid/bpf/hid_bpf_struct_ops.c b/drivers/hid/bpf/hid_bpf_struct_ops.c index f59cce6e437f77..cd696c59ba0f4f 100644 --- a/drivers/hid/bpf/hid_bpf_struct_ops.c +++ b/drivers/hid/bpf/hid_bpf_struct_ops.c @@ -183,6 +183,10 @@ static int hid_bpf_reg(void *kdata, struct bpf_link *link) struct hid_device *hdev; int count, err = 0; + /* prevent multiple attach of the same struct_ops */ + if (ops->hdev) + return -EINVAL; + hdev = hid_get_device(ops->hid_id); if (IS_ERR(hdev)) return PTR_ERR(hdev); @@ -248,6 +252,7 @@ static void hid_bpf_unreg(void *kdata, struct bpf_link *link) list_del_rcu(&ops->list); synchronize_srcu(&hdev->bpf.srcu); + ops->hdev = NULL; reconnect = hdev->bpf.rdesc_ops == ops; if (reconnect) diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index a44367aef62164..1f4564982b9584 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -692,78 +692,28 @@ static bool wacom_is_art_pen(int tool_id) static int wacom_intuos_get_tool_type(int tool_id) { - int tool_type = BTN_TOOL_PEN; - - if (wacom_is_art_pen(tool_id)) - return tool_type; - switch (tool_id) { case 0x812: /* Inking pen */ case 0x801: /* Intuos3 Inking pen */ case 0x12802: /* Intuos4/5 Inking Pen */ case 0x012: - tool_type = BTN_TOOL_PENCIL; - break; - - case 0x822: /* Pen */ - case 0x842: - case 0x852: - case 0x823: /* Intuos3 Grip Pen */ - case 0x813: /* Intuos3 Classic Pen */ - case 0x802: /* Intuos4/5 13HD/24HD General Pen */ - case 0x8e2: /* IntuosHT2 pen */ - case 0x022: - case 0x200: /* Pro Pen 3 */ - case 0x04200: /* Pro Pen 3 */ - case 0x10842: /* MobileStudio Pro Pro Pen slim */ - case 0x14802: /* Intuos4/5 13HD/24HD Classic Pen */ - case 0x16802: /* Cintiq 13HD Pro Pen */ - case 0x18802: /* DTH2242 Pen */ - case 0x10802: /* Intuos4/5 13HD/24HD General Pen */ - case 0x80842: /* Intuos Pro and Cintiq Pro 3D Pen */ - tool_type = BTN_TOOL_PEN; - break; + return BTN_TOOL_PENCIL; case 0x832: /* Stroke pen */ case 0x032: - tool_type = BTN_TOOL_BRUSH; - break; + return BTN_TOOL_BRUSH; case 0x007: /* Mouse 4D and 2D */ case 0x09c: case 0x094: case 0x017: /* Intuos3 2D Mouse */ case 0x806: /* Intuos4 Mouse */ - tool_type = BTN_TOOL_MOUSE; - break; + return BTN_TOOL_MOUSE; case 0x096: /* Lens cursor */ case 0x097: /* Intuos3 Lens cursor */ case 0x006: /* Intuos4 Lens cursor */ - tool_type = BTN_TOOL_LENS; - break; - - case 0x82a: /* Eraser */ - case 0x84a: - case 0x85a: - case 0x91a: - case 0xd1a: - case 0x0fa: - case 0x82b: /* Intuos3 Grip Pen Eraser */ - case 0x81b: /* Intuos3 Classic Pen Eraser */ - case 0x91b: /* Intuos3 Airbrush Eraser */ - case 0x80c: /* Intuos4/5 13HD/24HD Marker Pen Eraser */ - case 0x80a: /* Intuos4/5 13HD/24HD General Pen Eraser */ - case 0x90a: /* Intuos4/5 13HD/24HD Airbrush Eraser */ - case 0x1480a: /* Intuos4/5 13HD/24HD Classic Pen Eraser */ - case 0x1090a: /* Intuos4/5 13HD/24HD Airbrush Eraser */ - case 0x1080c: /* Intuos4/5 13HD/24HD Art Pen Eraser */ - case 0x1084a: /* MobileStudio Pro Pro Pen slim Eraser */ - case 0x1680a: /* Cintiq 13HD Pro Pen Eraser */ - case 0x1880a: /* DTH2242 Eraser */ - case 0x1080a: /* Intuos4/5 13HD/24HD General Pen Eraser */ - tool_type = BTN_TOOL_RUBBER; - break; + return BTN_TOOL_LENS; case 0xd12: case 0x912: @@ -771,10 +721,13 @@ static int wacom_intuos_get_tool_type(int tool_id) case 0x913: /* Intuos3 Airbrush */ case 0x902: /* Intuos4/5 13HD/24HD Airbrush */ case 0x10902: /* Intuos4/5 13HD/24HD Airbrush */ - tool_type = BTN_TOOL_AIRBRUSH; - break; + return BTN_TOOL_AIRBRUSH; + + default: + if (tool_id & 0x0008) + return BTN_TOOL_RUBBER; + return BTN_TOOL_PEN; } - return tool_type; } static void wacom_exit_report(struct wacom_wac *wacom) diff --git a/drivers/hwmon/adt7475.c b/drivers/hwmon/adt7475.c index bc186c61a2c0a5..382a2bb9168a50 100644 --- a/drivers/hwmon/adt7475.c +++ b/drivers/hwmon/adt7475.c @@ -22,23 +22,23 @@ #include /* Indexes for the sysfs hooks */ - -#define INPUT 0 -#define MIN 1 -#define MAX 2 -#define CONTROL 3 -#define OFFSET 3 -#define AUTOMIN 4 -#define THERM 5 -#define HYSTERSIS 6 - +enum adt_sysfs_id { + INPUT = 0, + MIN = 1, + MAX = 2, + CONTROL = 3, + OFFSET = 3, // Dup + AUTOMIN = 4, + THERM = 5, + HYSTERSIS = 6, /* * These are unique identifiers for the sysfs functions - unlike the * numbers above, these are not also indexes into an array */ + ALARM = 9, + FAULT = 10, +}; -#define ALARM 9 -#define FAULT 10 /* 7475 Common Registers */ diff --git a/drivers/i2c/busses/i2c-qcom-geni.c b/drivers/i2c/busses/i2c-qcom-geni.c index 0a8b95ce35f793..06e836e3e87733 100644 --- a/drivers/i2c/busses/i2c-qcom-geni.c +++ b/drivers/i2c/busses/i2c-qcom-geni.c @@ -986,12 +986,17 @@ static int __maybe_unused geni_i2c_runtime_resume(struct device *dev) return ret; ret = clk_prepare_enable(gi2c->core_clk); - if (ret) + if (ret) { + geni_icc_disable(&gi2c->se); return ret; + } ret = geni_se_resources_on(&gi2c->se); - if (ret) + if (ret) { + clk_disable_unprepare(gi2c->core_clk); + geni_icc_disable(&gi2c->se); return ret; + } enable_irq(gi2c->irq); gi2c->suspended = 0; diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index 85b31edc558dff..1df5b42041427c 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -1802,9 +1802,9 @@ static int tegra_i2c_probe(struct platform_device *pdev) * domain. * * VI I2C device shouldn't be marked as IRQ-safe because VI I2C won't - * be used for atomic transfers. + * be used for atomic transfers. ACPI device is not IRQ safe also. */ - if (!IS_VI(i2c_dev)) + if (!IS_VI(i2c_dev) && !has_acpi_companion(i2c_dev->dev)) pm_runtime_irq_safe(i2c_dev->dev); pm_runtime_enable(i2c_dev->dev); diff --git a/drivers/i2c/i2c-slave-testunit.c b/drivers/i2c/i2c-slave-testunit.c index 4e03b75f9ad772..4c550306f3ec59 100644 --- a/drivers/i2c/i2c-slave-testunit.c +++ b/drivers/i2c/i2c-slave-testunit.c @@ -18,7 +18,7 @@ enum testunit_cmds { TU_CMD_READ_BYTES = 1, /* save 0 for ABORT, RESET or similar */ - TU_CMD_HOST_NOTIFY, + TU_CMD_SMBUS_HOST_NOTIFY, TU_CMD_SMBUS_BLOCK_PROC_CALL, TU_NUM_CMDS }; @@ -60,7 +60,7 @@ static void i2c_slave_testunit_work(struct work_struct *work) msg.len = tu->regs[TU_REG_DATAH]; break; - case TU_CMD_HOST_NOTIFY: + case TU_CMD_SMBUS_HOST_NOTIFY: msg.addr = 0x08; msg.flags = 0; msg.len = 3; diff --git a/drivers/i2c/i2c-smbus.c b/drivers/i2c/i2c-smbus.c index 7e4203df83edb5..8256f7aed0cf86 100644 --- a/drivers/i2c/i2c-smbus.c +++ b/drivers/i2c/i2c-smbus.c @@ -34,6 +34,7 @@ static int smbus_do_alert(struct device *dev, void *addrp) struct i2c_client *client = i2c_verify_client(dev); struct alert_data *data = addrp; struct i2c_driver *driver; + int ret; if (!client || client->addr != data->addr) return 0; @@ -47,16 +48,47 @@ static int smbus_do_alert(struct device *dev, void *addrp) device_lock(dev); if (client->dev.driver) { driver = to_i2c_driver(client->dev.driver); - if (driver->alert) + if (driver->alert) { + /* Stop iterating after we find the device */ driver->alert(client, data->type, data->data); - else + ret = -EBUSY; + } else { dev_warn(&client->dev, "no driver alert()!\n"); - } else + ret = -EOPNOTSUPP; + } + } else { dev_dbg(&client->dev, "alert with no driver\n"); + ret = -ENODEV; + } + device_unlock(dev); + + return ret; +} + +/* Same as above, but call back all drivers with alert handler */ + +static int smbus_do_alert_force(struct device *dev, void *addrp) +{ + struct i2c_client *client = i2c_verify_client(dev); + struct alert_data *data = addrp; + struct i2c_driver *driver; + + if (!client || (client->flags & I2C_CLIENT_TEN)) + return 0; + + /* + * Drivers should either disable alerts, or provide at least + * a minimal handler. Lock so the driver won't change. + */ + device_lock(dev); + if (client->dev.driver) { + driver = to_i2c_driver(client->dev.driver); + if (driver->alert) + driver->alert(client, data->type, data->data); + } device_unlock(dev); - /* Stop iterating after we find the device */ - return -EBUSY; + return 0; } /* @@ -67,6 +99,7 @@ static irqreturn_t smbus_alert(int irq, void *d) { struct i2c_smbus_alert *alert = d; struct i2c_client *ara; + unsigned short prev_addr = I2C_CLIENT_END; /* Not a valid address */ ara = alert->ara; @@ -94,8 +127,25 @@ static irqreturn_t smbus_alert(int irq, void *d) data.addr, data.data); /* Notify driver for the device which issued the alert */ - device_for_each_child(&ara->adapter->dev, &data, - smbus_do_alert); + status = device_for_each_child(&ara->adapter->dev, &data, + smbus_do_alert); + /* + * If we read the same address more than once, and the alert + * was not handled by a driver, it won't do any good to repeat + * the loop because it will never terminate. Try again, this + * time calling the alert handlers of all devices connected to + * the bus, and abort the loop afterwards. If this helps, we + * are all set. If it doesn't, there is nothing else we can do, + * so we might as well abort the loop. + * Note: This assumes that a driver with alert handler handles + * the alert properly and clears it if necessary. + */ + if (data.addr == prev_addr && status != -EBUSY) { + device_for_each_child(&ara->adapter->dev, &data, + smbus_do_alert_force); + break; + } + prev_addr = data.addr; } return IRQ_HANDLED; diff --git a/drivers/input/input-mt.c b/drivers/input/input-mt.c index 14b53dac1253bf..6b04a674f832a0 100644 --- a/drivers/input/input-mt.c +++ b/drivers/input/input-mt.c @@ -46,6 +46,9 @@ int input_mt_init_slots(struct input_dev *dev, unsigned int num_slots, return 0; if (mt) return mt->num_slots != num_slots ? -EINVAL : 0; + /* Arbitrary limit for avoiding too large memory allocation. */ + if (num_slots > 1024) + return -EINVAL; mt = kzalloc(struct_size(mt, slots, num_slots), GFP_KERNEL); if (!mt) diff --git a/drivers/input/touchscreen/cyttsp4_core.c b/drivers/input/touchscreen/cyttsp4_core.c index 7cb26929dc7328..9dc25eb2be445f 100644 --- a/drivers/input/touchscreen/cyttsp4_core.c +++ b/drivers/input/touchscreen/cyttsp4_core.c @@ -871,7 +871,7 @@ static void cyttsp4_get_mt_touches(struct cyttsp4_mt_data *md, int num_cur_tch) struct cyttsp4_touch tch; int sig; int i, j, t = 0; - int ids[max(CY_TMA1036_MAX_TCH, CY_TMA4XX_MAX_TCH)]; + int ids[MAX(CY_TMA1036_MAX_TCH, CY_TMA4XX_MAX_TCH)]; memset(ids, 0, si->si_ofs.tch_abs[CY_TCH_T].max * sizeof(int)); for (i = 0; i < num_cur_tch; i++) { diff --git a/drivers/iommu/io-pgfault.c b/drivers/iommu/io-pgfault.c index cd679c13752e00..81e9cc6e3164a4 100644 --- a/drivers/iommu/io-pgfault.c +++ b/drivers/iommu/io-pgfault.c @@ -170,6 +170,7 @@ void iommu_report_device_fault(struct device *dev, struct iopf_fault *evt) report_partial_fault(iopf_param, fault); iopf_put_dev_fault_param(iopf_param); /* A request that is not the last does not need to be ack'd */ + return; } /* diff --git a/drivers/irqchip/irq-loongarch-cpu.c b/drivers/irqchip/irq-loongarch-cpu.c index 9d8f2c40604310..b35903a06902f7 100644 --- a/drivers/irqchip/irq-loongarch-cpu.c +++ b/drivers/irqchip/irq-loongarch-cpu.c @@ -18,11 +18,13 @@ struct fwnode_handle *cpuintc_handle; static u32 lpic_gsi_to_irq(u32 gsi) { + int irq = 0; + /* Only pch irqdomain transferring is required for LoongArch. */ if (gsi >= GSI_MIN_PCH_IRQ && gsi <= GSI_MAX_PCH_IRQ) - return acpi_register_gsi(NULL, gsi, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_HIGH); + irq = acpi_register_gsi(NULL, gsi, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_HIGH); - return 0; + return (irq > 0) ? irq : 0; } static struct fwnode_handle *lpic_get_gsi_domain_id(u32 gsi) diff --git a/drivers/irqchip/irq-mbigen.c b/drivers/irqchip/irq-mbigen.c index 093fd42893a7aa..53cc08387588f1 100644 --- a/drivers/irqchip/irq-mbigen.c +++ b/drivers/irqchip/irq-mbigen.c @@ -64,6 +64,20 @@ struct mbigen_device { void __iomem *base; }; +static inline unsigned int get_mbigen_node_offset(unsigned int nid) +{ + unsigned int offset = nid * MBIGEN_NODE_OFFSET; + + /* + * To avoid touched clear register in unexpected way, we need to directly + * skip clear register when access to more than 10 mbigen nodes. + */ + if (nid >= (REG_MBIGEN_CLEAR_OFFSET / MBIGEN_NODE_OFFSET)) + offset += MBIGEN_NODE_OFFSET; + + return offset; +} + static inline unsigned int get_mbigen_vec_reg(irq_hw_number_t hwirq) { unsigned int nid, pin; @@ -72,8 +86,7 @@ static inline unsigned int get_mbigen_vec_reg(irq_hw_number_t hwirq) nid = hwirq / IRQS_PER_MBIGEN_NODE + 1; pin = hwirq % IRQS_PER_MBIGEN_NODE; - return pin * 4 + nid * MBIGEN_NODE_OFFSET - + REG_MBIGEN_VEC_OFFSET; + return pin * 4 + get_mbigen_node_offset(nid) + REG_MBIGEN_VEC_OFFSET; } static inline void get_mbigen_type_reg(irq_hw_number_t hwirq, @@ -88,8 +101,7 @@ static inline void get_mbigen_type_reg(irq_hw_number_t hwirq, *mask = 1 << (irq_ofst % 32); ofst = irq_ofst / 32 * 4; - *addr = ofst + nid * MBIGEN_NODE_OFFSET - + REG_MBIGEN_TYPE_OFFSET; + *addr = ofst + get_mbigen_node_offset(nid) + REG_MBIGEN_TYPE_OFFSET; } static inline void get_mbigen_clear_reg(irq_hw_number_t hwirq, diff --git a/drivers/irqchip/irq-meson-gpio.c b/drivers/irqchip/irq-meson-gpio.c index 27e30ce41db3a7..cd789fa5151909 100644 --- a/drivers/irqchip/irq-meson-gpio.c +++ b/drivers/irqchip/irq-meson-gpio.c @@ -178,7 +178,7 @@ struct meson_gpio_irq_controller { void __iomem *base; u32 channel_irqs[MAX_NUM_CHANNEL]; DECLARE_BITMAP(channel_map, MAX_NUM_CHANNEL); - spinlock_t lock; + raw_spinlock_t lock; }; static void meson_gpio_irq_update_bits(struct meson_gpio_irq_controller *ctl, @@ -187,14 +187,14 @@ static void meson_gpio_irq_update_bits(struct meson_gpio_irq_controller *ctl, unsigned long flags; u32 tmp; - spin_lock_irqsave(&ctl->lock, flags); + raw_spin_lock_irqsave(&ctl->lock, flags); tmp = readl_relaxed(ctl->base + reg); tmp &= ~mask; tmp |= val; writel_relaxed(tmp, ctl->base + reg); - spin_unlock_irqrestore(&ctl->lock, flags); + raw_spin_unlock_irqrestore(&ctl->lock, flags); } static void meson_gpio_irq_init_dummy(struct meson_gpio_irq_controller *ctl) @@ -244,12 +244,12 @@ meson_gpio_irq_request_channel(struct meson_gpio_irq_controller *ctl, unsigned long flags; unsigned int idx; - spin_lock_irqsave(&ctl->lock, flags); + raw_spin_lock_irqsave(&ctl->lock, flags); /* Find a free channel */ idx = find_first_zero_bit(ctl->channel_map, ctl->params->nr_channels); if (idx >= ctl->params->nr_channels) { - spin_unlock_irqrestore(&ctl->lock, flags); + raw_spin_unlock_irqrestore(&ctl->lock, flags); pr_err("No channel available\n"); return -ENOSPC; } @@ -257,7 +257,7 @@ meson_gpio_irq_request_channel(struct meson_gpio_irq_controller *ctl, /* Mark the channel as used */ set_bit(idx, ctl->channel_map); - spin_unlock_irqrestore(&ctl->lock, flags); + raw_spin_unlock_irqrestore(&ctl->lock, flags); /* * Setup the mux of the channel to route the signal of the pad @@ -567,7 +567,7 @@ static int meson_gpio_irq_of_init(struct device_node *node, struct device_node * if (!ctl) return -ENOMEM; - spin_lock_init(&ctl->lock); + raw_spin_lock_init(&ctl->lock); ctl->base = of_iomap(node, 0); if (!ctl->base) { diff --git a/drivers/irqchip/irq-pic32-evic.c b/drivers/irqchip/irq-pic32-evic.c index 5d6b8e025bb876..eb6ca516a16645 100644 --- a/drivers/irqchip/irq-pic32-evic.c +++ b/drivers/irqchip/irq-pic32-evic.c @@ -161,9 +161,9 @@ static int pic32_irq_domain_map(struct irq_domain *d, unsigned int virq, return ret; } -int pic32_irq_domain_xlate(struct irq_domain *d, struct device_node *ctrlr, - const u32 *intspec, unsigned int intsize, - irq_hw_number_t *out_hwirq, unsigned int *out_type) +static int pic32_irq_domain_xlate(struct irq_domain *d, struct device_node *ctrlr, + const u32 *intspec, unsigned int intsize, + irq_hw_number_t *out_hwirq, unsigned int *out_type) { struct evic_chip_data *priv = d->host_data; diff --git a/drivers/irqchip/irq-riscv-aplic-msi.c b/drivers/irqchip/irq-riscv-aplic-msi.c index 028444af48bd57..d7773f76e5d0a5 100644 --- a/drivers/irqchip/irq-riscv-aplic-msi.c +++ b/drivers/irqchip/irq-riscv-aplic-msi.c @@ -32,15 +32,10 @@ static void aplic_msi_irq_unmask(struct irq_data *d) aplic_irq_unmask(d); } -static void aplic_msi_irq_eoi(struct irq_data *d) +static void aplic_msi_irq_retrigger_level(struct irq_data *d) { struct aplic_priv *priv = irq_data_get_irq_chip_data(d); - /* - * EOI handling is required only for level-triggered interrupts - * when APLIC is in MSI mode. - */ - switch (irqd_get_trigger_type(d)) { case IRQ_TYPE_LEVEL_LOW: case IRQ_TYPE_LEVEL_HIGH: @@ -59,6 +54,29 @@ static void aplic_msi_irq_eoi(struct irq_data *d) } } +static void aplic_msi_irq_eoi(struct irq_data *d) +{ + /* + * EOI handling is required only for level-triggered interrupts + * when APLIC is in MSI mode. + */ + aplic_msi_irq_retrigger_level(d); +} + +static int aplic_msi_irq_set_type(struct irq_data *d, unsigned int type) +{ + int rc = aplic_irq_set_type(d, type); + + if (rc) + return rc; + /* + * Updating sourcecfg register for level-triggered interrupts + * requires interrupt retriggering when APLIC is in MSI mode. + */ + aplic_msi_irq_retrigger_level(d); + return 0; +} + static void aplic_msi_write_msg(struct irq_data *d, struct msi_msg *msg) { unsigned int group_index, hart_index, guest_index, val; @@ -130,7 +148,7 @@ static const struct msi_domain_template aplic_msi_template = { .name = "APLIC-MSI", .irq_mask = aplic_msi_irq_mask, .irq_unmask = aplic_msi_irq_unmask, - .irq_set_type = aplic_irq_set_type, + .irq_set_type = aplic_msi_irq_set_type, .irq_eoi = aplic_msi_irq_eoi, #ifdef CONFIG_SMP .irq_set_affinity = irq_chip_set_affinity_parent, diff --git a/drivers/irqchip/irq-sun6i-r.c b/drivers/irqchip/irq-sun6i-r.c index a01e440494154e..99958d470d6268 100644 --- a/drivers/irqchip/irq-sun6i-r.c +++ b/drivers/irqchip/irq-sun6i-r.c @@ -270,7 +270,7 @@ static const struct irq_domain_ops sun6i_r_intc_domain_ops = { static int sun6i_r_intc_suspend(void) { - u32 buf[BITS_TO_U32(max(SUN6I_NR_TOP_LEVEL_IRQS, SUN6I_NR_MUX_BITS))]; + u32 buf[BITS_TO_U32(MAX(SUN6I_NR_TOP_LEVEL_IRQS, SUN6I_NR_MUX_BITS))]; int i; /* Wake IRQs are enabled during system sleep and shutdown. */ diff --git a/drivers/irqchip/irq-xilinx-intc.c b/drivers/irqchip/irq-xilinx-intc.c index 238d3d34494969..7e08714d507f47 100644 --- a/drivers/irqchip/irq-xilinx-intc.c +++ b/drivers/irqchip/irq-xilinx-intc.c @@ -189,7 +189,7 @@ static int __init xilinx_intc_of_init(struct device_node *intc, irqc->intr_mask = 0; } - if (irqc->intr_mask >> irqc->nr_irq) + if ((u64)irqc->intr_mask >> irqc->nr_irq) pr_warn("irq-xilinx: mismatch in kind-of-intr param\n"); pr_info("irq-xilinx: %pOF: num_irq=%d, edge=0x%x\n", diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c index c2c07bfa647199..f299ff393a6a2c 100644 --- a/drivers/md/dm-ioctl.c +++ b/drivers/md/dm-ioctl.c @@ -1181,8 +1181,26 @@ static int do_resume(struct dm_ioctl *param) suspend_flags &= ~DM_SUSPEND_LOCKFS_FLAG; if (param->flags & DM_NOFLUSH_FLAG) suspend_flags |= DM_SUSPEND_NOFLUSH_FLAG; - if (!dm_suspended_md(md)) - dm_suspend(md, suspend_flags); + if (!dm_suspended_md(md)) { + r = dm_suspend(md, suspend_flags); + if (r) { + down_write(&_hash_lock); + hc = dm_get_mdptr(md); + if (hc && !hc->new_map) { + hc->new_map = new_map; + new_map = NULL; + } else { + r = -ENXIO; + } + up_write(&_hash_lock); + if (new_map) { + dm_sync_table(md); + dm_table_destroy(new_map); + } + dm_put(md); + return r; + } + } old_size = dm_get_size(md); old_map = dm_swap_table(md, new_map); diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 97fab2087df86d..87bb9030343582 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -2737,7 +2737,7 @@ static int dm_wait_for_bios_completion(struct mapped_device *md, unsigned int ta break; if (signal_pending_state(task_state, current)) { - r = -EINTR; + r = -ERESTARTSYS; break; } @@ -2762,7 +2762,7 @@ static int dm_wait_for_completion(struct mapped_device *md, unsigned int task_st break; if (signal_pending_state(task_state, current)) { - r = -EINTR; + r = -ERESTARTSYS; break; } diff --git a/drivers/md/persistent-data/dm-space-map-metadata.c b/drivers/md/persistent-data/dm-space-map-metadata.c index 04698fd03e6069..d48c4fafc77989 100644 --- a/drivers/md/persistent-data/dm-space-map-metadata.c +++ b/drivers/md/persistent-data/dm-space-map-metadata.c @@ -277,7 +277,7 @@ static void sm_metadata_destroy(struct dm_space_map *sm) { struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm); - kfree(smm); + kvfree(smm); } static int sm_metadata_get_nr_blocks(struct dm_space_map *sm, dm_block_t *count) @@ -772,7 +772,7 @@ struct dm_space_map *dm_sm_metadata_init(void) { struct sm_metadata *smm; - smm = kmalloc(sizeof(*smm), GFP_KERNEL); + smm = kvmalloc(sizeof(*smm), GFP_KERNEL); if (!smm) return ERR_PTR(-ENOMEM); diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 7acfe7c9dc8daa..761989d6790683 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -617,6 +617,12 @@ static int choose_first_rdev(struct r1conf *conf, struct r1bio *r1_bio, return -1; } +static bool rdev_in_recovery(struct md_rdev *rdev, struct r1bio *r1_bio) +{ + return !test_bit(In_sync, &rdev->flags) && + rdev->recovery_offset < r1_bio->sector + r1_bio->sectors; +} + static int choose_bb_rdev(struct r1conf *conf, struct r1bio *r1_bio, int *max_sectors) { @@ -635,6 +641,7 @@ static int choose_bb_rdev(struct r1conf *conf, struct r1bio *r1_bio, rdev = conf->mirrors[disk].rdev; if (!rdev || test_bit(Faulty, &rdev->flags) || + rdev_in_recovery(rdev, r1_bio) || test_bit(WriteMostly, &rdev->flags)) continue; @@ -673,7 +680,8 @@ static int choose_slow_rdev(struct r1conf *conf, struct r1bio *r1_bio, rdev = conf->mirrors[disk].rdev; if (!rdev || test_bit(Faulty, &rdev->flags) || - !test_bit(WriteMostly, &rdev->flags)) + !test_bit(WriteMostly, &rdev->flags) || + rdev_in_recovery(rdev, r1_bio)) continue; /* there are no bad blocks, we can use this disk */ @@ -733,9 +741,7 @@ static bool rdev_readable(struct md_rdev *rdev, struct r1bio *r1_bio) if (!rdev || test_bit(Faulty, &rdev->flags)) return false; - /* still in recovery */ - if (!test_bit(In_sync, &rdev->flags) && - rdev->recovery_offset < r1_bio->sector + r1_bio->sectors) + if (rdev_in_recovery(rdev, r1_bio)) return false; /* don't read from slow disk unless have to */ diff --git a/drivers/media/dvb-frontends/stv0367_priv.h b/drivers/media/dvb-frontends/stv0367_priv.h index 617f605947b2c4..7f056d1cce8228 100644 --- a/drivers/media/dvb-frontends/stv0367_priv.h +++ b/drivers/media/dvb-frontends/stv0367_priv.h @@ -25,8 +25,11 @@ #endif /* MACRO definitions */ +#ifndef MIN #define MAX(X, Y) ((X) >= (Y) ? (X) : (Y)) #define MIN(X, Y) ((X) <= (Y) ? (X) : (Y)) +#endif + #define INRANGE(X, Y, Z) \ ((((X) <= (Y)) && ((Y) <= (Z))) || \ (((Z) <= (Y)) && ((Y) <= (X))) ? 1 : 0) diff --git a/drivers/media/pci/intel/ipu6/Kconfig b/drivers/media/pci/intel/ipu6/Kconfig index 154343080c82a6..40e20f0aa5ae5d 100644 --- a/drivers/media/pci/intel/ipu6/Kconfig +++ b/drivers/media/pci/intel/ipu6/Kconfig @@ -3,13 +3,14 @@ config VIDEO_INTEL_IPU6 depends on ACPI || COMPILE_TEST depends on VIDEO_DEV depends on X86 && X86_64 && HAS_DMA + depends on IPU_BRIDGE || !IPU_BRIDGE + select AUXILIARY_BUS select DMA_OPS select IOMMU_IOVA select VIDEO_V4L2_SUBDEV_API select MEDIA_CONTROLLER select VIDEOBUF2_DMA_CONTIG select V4L2_FWNODE - select IPU_BRIDGE help This is the 6th Gen Intel Image Processing Unit, found in Intel SoCs and used for capturing images and video from camera sensors. diff --git a/drivers/media/usb/dvb-usb/dvb-usb-init.c b/drivers/media/usb/dvb-usb/dvb-usb-init.c index 22d83ac18eb735..fbf58012becdf2 100644 --- a/drivers/media/usb/dvb-usb/dvb-usb-init.c +++ b/drivers/media/usb/dvb-usb/dvb-usb-init.c @@ -23,40 +23,11 @@ static int dvb_usb_force_pid_filter_usage; module_param_named(force_pid_filter_usage, dvb_usb_force_pid_filter_usage, int, 0444); MODULE_PARM_DESC(force_pid_filter_usage, "force all dvb-usb-devices to use a PID filter, if any (default: 0)."); -static int dvb_usb_check_bulk_endpoint(struct dvb_usb_device *d, u8 endpoint) -{ - if (endpoint) { - int ret; - - ret = usb_pipe_type_check(d->udev, usb_sndbulkpipe(d->udev, endpoint)); - if (ret) - return ret; - ret = usb_pipe_type_check(d->udev, usb_rcvbulkpipe(d->udev, endpoint)); - if (ret) - return ret; - } - return 0; -} - -static void dvb_usb_clear_halt(struct dvb_usb_device *d, u8 endpoint) -{ - if (endpoint) { - usb_clear_halt(d->udev, usb_sndbulkpipe(d->udev, endpoint)); - usb_clear_halt(d->udev, usb_rcvbulkpipe(d->udev, endpoint)); - } -} - static int dvb_usb_adapter_init(struct dvb_usb_device *d, short *adapter_nrs) { struct dvb_usb_adapter *adap; int ret, n, o; - ret = dvb_usb_check_bulk_endpoint(d, d->props.generic_bulk_ctrl_endpoint); - if (ret) - return ret; - ret = dvb_usb_check_bulk_endpoint(d, d->props.generic_bulk_ctrl_endpoint_response); - if (ret) - return ret; for (n = 0; n < d->props.num_adapters; n++) { adap = &d->adapter[n]; adap->dev = d; @@ -132,8 +103,10 @@ static int dvb_usb_adapter_init(struct dvb_usb_device *d, short *adapter_nrs) * when reloading the driver w/o replugging the device * sometimes a timeout occurs, this helps */ - dvb_usb_clear_halt(d, d->props.generic_bulk_ctrl_endpoint); - dvb_usb_clear_halt(d, d->props.generic_bulk_ctrl_endpoint_response); + if (d->props.generic_bulk_ctrl_endpoint != 0) { + usb_clear_halt(d->udev, usb_sndbulkpipe(d->udev, d->props.generic_bulk_ctrl_endpoint)); + usb_clear_halt(d->udev, usb_rcvbulkpipe(d->udev, d->props.generic_bulk_ctrl_endpoint)); + } return 0; diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c index 0136df5732bac5..4fe26e82e3d1c1 100644 --- a/drivers/media/usb/uvc/uvc_ctrl.c +++ b/drivers/media/usb/uvc/uvc_ctrl.c @@ -2680,6 +2680,10 @@ static void uvc_ctrl_init_ctrl(struct uvc_video_chain *chain, for (i = 0; i < ARRAY_SIZE(uvc_ctrl_mappings); ++i) { const struct uvc_control_mapping *mapping = &uvc_ctrl_mappings[i]; + if (!uvc_entity_match_guid(ctrl->entity, mapping->entity) || + ctrl->info.selector != mapping->selector) + continue; + /* Let the device provide a custom mapping. */ if (mapping->filter_mapping) { mapping = mapping->filter_mapping(chain, ctrl); @@ -2687,9 +2691,7 @@ static void uvc_ctrl_init_ctrl(struct uvc_video_chain *chain, continue; } - if (uvc_entity_match_guid(ctrl->entity, mapping->entity) && - ctrl->info.selector == mapping->selector) - __uvc_ctrl_add_mapping(chain, ctrl, mapping); + __uvc_ctrl_add_mapping(chain, ctrl, mapping); } } diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 41c3d2821a7850..41c54051347ab7 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -587,7 +587,7 @@ config NSM config MARVELL_CN10K_DPI tristate "Octeon CN10K DPI driver" - depends on PCI + depends on PCI && PCI_IOV depends on ARCH_THUNDER || (COMPILE_TEST && 64BIT) help Enables Octeon CN10K DMA packet interface (DPI) driver which diff --git a/drivers/misc/eeprom/ee1004.c b/drivers/misc/eeprom/ee1004.c index d4aeeb2b216920..89224d4af4a201 100644 --- a/drivers/misc/eeprom/ee1004.c +++ b/drivers/misc/eeprom/ee1004.c @@ -233,6 +233,49 @@ static void ee1004_cleanup_bus_data(void *data) mutex_unlock(&ee1004_bus_lock); } +static int ee1004_init_bus_data(struct i2c_client *client) +{ + struct ee1004_bus_data *bd; + int err, cnr = 0; + + bd = ee1004_get_bus_data(client->adapter); + if (!bd) + return dev_err_probe(&client->dev, -ENOSPC, "Only %d busses supported", + EE1004_MAX_BUSSES); + + i2c_set_clientdata(client, bd); + + if (++bd->dev_count == 1) { + /* Use 2 dummy devices for page select command */ + for (cnr = 0; cnr < EE1004_NUM_PAGES; cnr++) { + struct i2c_client *cl; + + cl = i2c_new_dummy_device(client->adapter, EE1004_ADDR_SET_PAGE + cnr); + if (IS_ERR(cl)) { + err = PTR_ERR(cl); + goto err_out; + } + + bd->set_page[cnr] = cl; + } + + /* Remember current page to avoid unneeded page select */ + err = ee1004_get_current_page(bd); + if (err < 0) + goto err_out; + + dev_dbg(&client->dev, "Currently selected page: %d\n", err); + bd->current_page = err; + } + + return 0; + +err_out: + ee1004_cleanup(cnr, bd); + + return err; +} + static int ee1004_probe(struct i2c_client *client) { struct nvmem_config config = { @@ -251,9 +294,8 @@ static int ee1004_probe(struct i2c_client *client) .compat = true, .base_dev = &client->dev, }; - struct ee1004_bus_data *bd; struct nvmem_device *ndev; - int err, cnr = 0; + int err; /* Make sure we can operate on this adapter */ if (!i2c_check_functionality(client->adapter, @@ -264,46 +306,21 @@ static int ee1004_probe(struct i2c_client *client) mutex_lock(&ee1004_bus_lock); - bd = ee1004_get_bus_data(client->adapter); - if (!bd) { + err = ee1004_init_bus_data(client); + if (err < 0) { mutex_unlock(&ee1004_bus_lock); - return dev_err_probe(&client->dev, -ENOSPC, - "Only %d busses supported", EE1004_MAX_BUSSES); - } - - err = devm_add_action_or_reset(&client->dev, ee1004_cleanup_bus_data, bd); - if (err < 0) return err; - - i2c_set_clientdata(client, bd); - - if (++bd->dev_count == 1) { - /* Use 2 dummy devices for page select command */ - for (cnr = 0; cnr < EE1004_NUM_PAGES; cnr++) { - struct i2c_client *cl; - - cl = i2c_new_dummy_device(client->adapter, EE1004_ADDR_SET_PAGE + cnr); - if (IS_ERR(cl)) { - mutex_unlock(&ee1004_bus_lock); - return PTR_ERR(cl); - } - bd->set_page[cnr] = cl; - } - - /* Remember current page to avoid unneeded page select */ - err = ee1004_get_current_page(bd); - if (err < 0) { - mutex_unlock(&ee1004_bus_lock); - return err; - } - dev_dbg(&client->dev, "Currently selected page: %d\n", err); - bd->current_page = err; } ee1004_probe_temp_sensor(client); mutex_unlock(&ee1004_bus_lock); + err = devm_add_action_or_reset(&client->dev, ee1004_cleanup_bus_data, + i2c_get_clientdata(client)); + if (err < 0) + return err; + ndev = devm_nvmem_register(&client->dev, &config); if (IS_ERR(ndev)) return PTR_ERR(ndev); diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c index 5204fda51da3fc..339d126414d4bf 100644 --- a/drivers/misc/fastrpc.c +++ b/drivers/misc/fastrpc.c @@ -2085,16 +2085,6 @@ static int fastrpc_req_mem_map(struct fastrpc_user *fl, char __user *argp) return err; } -static int is_attach_rejected(struct fastrpc_user *fl) -{ - /* Check if the device node is non-secure */ - if (!fl->is_secure_dev) { - dev_dbg(&fl->cctx->rpdev->dev, "untrusted app trying to attach to privileged DSP PD\n"); - return -EACCES; - } - return 0; -} - static long fastrpc_device_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { @@ -2107,19 +2097,13 @@ static long fastrpc_device_ioctl(struct file *file, unsigned int cmd, err = fastrpc_invoke(fl, argp); break; case FASTRPC_IOCTL_INIT_ATTACH: - err = is_attach_rejected(fl); - if (!err) - err = fastrpc_init_attach(fl, ROOT_PD); + err = fastrpc_init_attach(fl, ROOT_PD); break; case FASTRPC_IOCTL_INIT_ATTACH_SNS: - err = is_attach_rejected(fl); - if (!err) - err = fastrpc_init_attach(fl, SENSORS_PD); + err = fastrpc_init_attach(fl, SENSORS_PD); break; case FASTRPC_IOCTL_INIT_CREATE_STATIC: - err = is_attach_rejected(fl); - if (!err) - err = fastrpc_init_create_static_process(fl, argp); + err = fastrpc_init_create_static_process(fl, argp); break; case FASTRPC_IOCTL_INIT_CREATE: err = fastrpc_init_create_process(fl, argp); diff --git a/drivers/misc/lkdtm/refcount.c b/drivers/misc/lkdtm/refcount.c index 5cd488f54cfa54..8f744bee6fbde8 100644 --- a/drivers/misc/lkdtm/refcount.c +++ b/drivers/misc/lkdtm/refcount.c @@ -182,6 +182,21 @@ static void lkdtm_REFCOUNT_SUB_AND_TEST_NEGATIVE(void) check_negative(&neg, 3); } +/* + * A refcount_sub_and_test() by zero when the counter is at zero should act like + * refcount_sub_and_test() above when going negative. + */ +static void lkdtm_REFCOUNT_SUB_AND_TEST_ZERO(void) +{ + refcount_t neg = REFCOUNT_INIT(0); + + pr_info("attempting bad refcount_sub_and_test() at zero\n"); + if (refcount_sub_and_test(0, &neg)) + pr_warn("Weird: refcount_sub_and_test() reported zero\n"); + + check_negative(&neg, 0); +} + static void check_from_zero(refcount_t *ref) { switch (refcount_read(ref)) { @@ -400,6 +415,7 @@ static struct crashtype crashtypes[] = { CRASHTYPE(REFCOUNT_DEC_NEGATIVE), CRASHTYPE(REFCOUNT_DEC_AND_TEST_NEGATIVE), CRASHTYPE(REFCOUNT_SUB_AND_TEST_NEGATIVE), + CRASHTYPE(REFCOUNT_SUB_AND_TEST_ZERO), CRASHTYPE(REFCOUNT_INC_ZERO), CRASHTYPE(REFCOUNT_ADD_ZERO), CRASHTYPE(REFCOUNT_INC_SATURATED), diff --git a/drivers/net/can/usb/etas_es58x/es58x_devlink.c b/drivers/net/can/usb/etas_es58x/es58x_devlink.c index 635edeb8f68cdf..eee20839d96fd4 100644 --- a/drivers/net/can/usb/etas_es58x/es58x_devlink.c +++ b/drivers/net/can/usb/etas_es58x/es58x_devlink.c @@ -215,7 +215,7 @@ static int es58x_devlink_info_get(struct devlink *devlink, struct es58x_sw_version *fw_ver = &es58x_dev->firmware_version; struct es58x_sw_version *bl_ver = &es58x_dev->bootloader_version; struct es58x_hw_revision *hw_rev = &es58x_dev->hardware_revision; - char buf[max(sizeof("xx.xx.xx"), sizeof("axxx/xxx"))]; + char buf[MAX(sizeof("xx.xx.xx"), sizeof("axxx/xxx"))]; int ret = 0; if (es58x_sw_version_is_valid(fw_ver)) { diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c index ed1e6560df25ec..0e663ec0c12a3b 100644 --- a/drivers/net/dsa/bcm_sf2.c +++ b/drivers/net/dsa/bcm_sf2.c @@ -675,8 +675,10 @@ static int bcm_sf2_mdio_register(struct dsa_switch *ds) of_remove_property(child, prop); phydev = of_phy_find_device(child); - if (phydev) + if (phydev) { phy_device_remove(phydev); + phy_device_free(phydev); + } } err = mdiobus_register(priv->user_mii_bus); diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c index b074b4bb062964..1491099528be8d 100644 --- a/drivers/net/dsa/microchip/ksz_common.c +++ b/drivers/net/dsa/microchip/ksz_common.c @@ -2578,7 +2578,11 @@ static u32 ksz_get_phy_flags(struct dsa_switch *ds, int port) if (!port) return MICREL_KSZ8_P1_ERRATA; break; + case KSZ8567_CHIP_ID: case KSZ9477_CHIP_ID: + case KSZ9567_CHIP_ID: + case KSZ9896_CHIP_ID: + case KSZ9897_CHIP_ID: /* KSZ9477 Errata DS80000754C * * Module 4: Energy Efficient Ethernet (EEE) feature select must @@ -2588,6 +2592,13 @@ static u32 ksz_get_phy_flags(struct dsa_switch *ds, int port) * controls. If not disabled, the PHY ports can auto-negotiate * to enable EEE, and this feature can cause link drops when * linked to another device supporting EEE. + * + * The same item appears in the errata for the KSZ9567, KSZ9896, + * and KSZ9897. + * + * A similar item appears in the errata for the KSZ8567, but + * provides an alternative workaround. For now, use the simple + * workaround of disabling the EEE feature for this device too. */ return MICREL_NO_EEE; } @@ -3764,6 +3775,11 @@ static int ksz_port_set_mac_address(struct dsa_switch *ds, int port, return -EBUSY; } + /* Need to initialize variable as the code to fill in settings may + * not be executed. + */ + wol.wolopts = 0; + ksz_get_wol(ds, dp->index, &wol); if (wol.wolopts & WAKE_MAGIC) { dev_err(ds->dev, diff --git a/drivers/net/dsa/vitesse-vsc73xx-core.c b/drivers/net/dsa/vitesse-vsc73xx-core.c index d9d3e30fd47ad4..e3f95d2cc2c168 100644 --- a/drivers/net/dsa/vitesse-vsc73xx-core.c +++ b/drivers/net/dsa/vitesse-vsc73xx-core.c @@ -40,6 +40,10 @@ #define VSC73XX_BLOCK_ARBITER 0x5 /* Only subblock 0 */ #define VSC73XX_BLOCK_SYSTEM 0x7 /* Only subblock 0 */ +/* MII Block subblock */ +#define VSC73XX_BLOCK_MII_INTERNAL 0x0 /* Internal MDIO subblock */ +#define VSC73XX_BLOCK_MII_EXTERNAL 0x1 /* External MDIO subblock */ + #define CPU_PORT 6 /* CPU port */ /* MAC Block registers */ @@ -225,6 +229,8 @@ #define VSC73XX_MII_CMD 0x1 #define VSC73XX_MII_DATA 0x2 +#define VSC73XX_MII_STAT_BUSY BIT(3) + /* Arbiter block 5 registers */ #define VSC73XX_ARBEMPTY 0x0c #define VSC73XX_ARBDISC 0x0e @@ -299,6 +305,7 @@ #define IS_739X(a) (IS_7395(a) || IS_7398(a)) #define VSC73XX_POLL_SLEEP_US 1000 +#define VSC73XX_MDIO_POLL_SLEEP_US 5 #define VSC73XX_POLL_TIMEOUT_US 10000 struct vsc73xx_counter { @@ -527,6 +534,22 @@ static int vsc73xx_detect(struct vsc73xx *vsc) return 0; } +static int vsc73xx_mdio_busy_check(struct vsc73xx *vsc) +{ + int ret, err; + u32 val; + + ret = read_poll_timeout(vsc73xx_read, err, + err < 0 || !(val & VSC73XX_MII_STAT_BUSY), + VSC73XX_MDIO_POLL_SLEEP_US, + VSC73XX_POLL_TIMEOUT_US, false, vsc, + VSC73XX_BLOCK_MII, VSC73XX_BLOCK_MII_INTERNAL, + VSC73XX_MII_STAT, &val); + if (ret) + return ret; + return err; +} + static int vsc73xx_phy_read(struct dsa_switch *ds, int phy, int regnum) { struct vsc73xx *vsc = ds->priv; @@ -534,12 +557,20 @@ static int vsc73xx_phy_read(struct dsa_switch *ds, int phy, int regnum) u32 val; int ret; + ret = vsc73xx_mdio_busy_check(vsc); + if (ret) + return ret; + /* Setting bit 26 means "read" */ cmd = BIT(26) | (phy << 21) | (regnum << 16); ret = vsc73xx_write(vsc, VSC73XX_BLOCK_MII, 0, 1, cmd); if (ret) return ret; - msleep(2); + + ret = vsc73xx_mdio_busy_check(vsc); + if (ret) + return ret; + ret = vsc73xx_read(vsc, VSC73XX_BLOCK_MII, 0, 2, &val); if (ret) return ret; @@ -563,18 +594,11 @@ static int vsc73xx_phy_write(struct dsa_switch *ds, int phy, int regnum, u32 cmd; int ret; - /* It was found through tedious experiments that this router - * chip really hates to have it's PHYs reset. They - * never recover if that happens: autonegotiation stops - * working after a reset. Just filter out this command. - * (Resetting the whole chip is OK.) - */ - if (regnum == 0 && (val & BIT(15))) { - dev_info(vsc->dev, "reset PHY - disallowed\n"); - return 0; - } + ret = vsc73xx_mdio_busy_check(vsc); + if (ret) + return ret; - cmd = (phy << 21) | (regnum << 16); + cmd = (phy << 21) | (regnum << 16) | val; ret = vsc73xx_write(vsc, VSC73XX_BLOCK_MII, 0, 1, cmd); if (ret) return ret; @@ -957,6 +981,11 @@ static void vsc73xx_mac_link_up(struct phylink_config *config, if (duplex == DUPLEX_FULL) val |= VSC73XX_MAC_CFG_FDX; + else + /* In datasheet description ("Port Mode Procedure" in 5.6.2) + * this bit is configured only for half duplex. + */ + val |= VSC73XX_MAC_CFG_WEXC_DIS; /* This routine is described in the datasheet (below ARBDISC register * description) @@ -967,7 +996,6 @@ static void vsc73xx_mac_link_up(struct phylink_config *config, get_random_bytes(&seed, 1); val |= seed << VSC73XX_MAC_CFG_SEED_OFFSET; val |= VSC73XX_MAC_CFG_SEED_LOAD; - val |= VSC73XX_MAC_CFG_WEXC_DIS; /* Those bits are responsible for MTU only. Kernel takes care about MTU, * let's enable +8 bytes frame length unconditionally. diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index ffa74c26ee5325..e27e1082ee33ae 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -7591,19 +7591,20 @@ static bool bnxt_need_reserve_rings(struct bnxt *bp) int rx = bp->rx_nr_rings, stat; int vnic, grp = rx; - if (hw_resc->resv_tx_rings != bp->tx_nr_rings && - bp->hwrm_spec_code >= 0x10601) - return true; - /* Old firmware does not need RX ring reservations but we still * need to setup a default RSS map when needed. With new firmware * we go through RX ring reservations first and then set up the * RSS map for the successfully reserved RX rings when needed. */ - if (!BNXT_NEW_RM(bp)) { + if (!BNXT_NEW_RM(bp)) bnxt_check_rss_tbl_no_rmgr(bp); + + if (hw_resc->resv_tx_rings != bp->tx_nr_rings && + bp->hwrm_spec_code >= 0x10601) + return true; + + if (!BNXT_NEW_RM(bp)) return false; - } vnic = bnxt_get_total_vnics(bp, rx); @@ -7649,8 +7650,8 @@ static int bnxt_get_avail_msix(struct bnxt *bp, int num); static int __bnxt_reserve_rings(struct bnxt *bp) { struct bnxt_hw_rings hwr = {0}; + int rx_rings, old_rx_rings, rc; int cp = bp->cp_nr_rings; - int rx_rings, rc; int ulp_msix = 0; bool sh = false; int tx_cp; @@ -7684,6 +7685,7 @@ static int __bnxt_reserve_rings(struct bnxt *bp) hwr.grp = bp->rx_nr_rings; hwr.rss_ctx = bnxt_get_total_rss_ctxs(bp, &hwr); hwr.stat = bnxt_get_func_stat_ctxs(bp); + old_rx_rings = bp->hw_resc.resv_rx_rings; rc = bnxt_hwrm_reserve_rings(bp, &hwr); if (rc) @@ -7738,7 +7740,8 @@ static int __bnxt_reserve_rings(struct bnxt *bp) if (!bnxt_rings_ok(bp, &hwr)) return -ENOMEM; - if (!netif_is_rxfh_configured(bp->dev)) + if (old_rx_rings != bp->hw_resc.resv_rx_rings && + !netif_is_rxfh_configured(bp->dev)) bnxt_set_dflt_rss_indir_tbl(bp, NULL); if (!bnxt_ulp_registered(bp->edev) && BNXT_NEW_RM(bp)) { diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c index d00ef0063820d7..9dadc89378f02e 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c @@ -1863,8 +1863,14 @@ static void bnxt_modify_rss(struct bnxt *bp, struct ethtool_rxfh_context *ctx, } static int bnxt_rxfh_context_check(struct bnxt *bp, + const struct ethtool_rxfh_param *rxfh, struct netlink_ext_ack *extack) { + if (rxfh->hfunc && rxfh->hfunc != ETH_RSS_HASH_TOP) { + NL_SET_ERR_MSG_MOD(extack, "RSS hash function not supported"); + return -EOPNOTSUPP; + } + if (!BNXT_SUPPORTS_MULTI_RSS_CTX(bp)) { NL_SET_ERR_MSG_MOD(extack, "RSS contexts not supported"); return -EOPNOTSUPP; @@ -1888,7 +1894,7 @@ static int bnxt_create_rxfh_context(struct net_device *dev, struct bnxt_vnic_info *vnic; int rc; - rc = bnxt_rxfh_context_check(bp, extack); + rc = bnxt_rxfh_context_check(bp, rxfh, extack); if (rc) return rc; @@ -1915,8 +1921,12 @@ static int bnxt_create_rxfh_context(struct net_device *dev, if (rc) goto out; + /* Populate defaults in the context */ bnxt_set_dflt_rss_indir_tbl(bp, ctx); + ctx->hfunc = ETH_RSS_HASH_TOP; memcpy(vnic->rss_hash_key, bp->rss_hash_key, HW_HASH_KEY_SIZE); + memcpy(ethtool_rxfh_context_key(ctx), + bp->rss_hash_key, HW_HASH_KEY_SIZE); rc = bnxt_hwrm_vnic_alloc(bp, vnic, 0, bp->rx_nr_rings); if (rc) { @@ -1953,7 +1963,7 @@ static int bnxt_modify_rxfh_context(struct net_device *dev, struct bnxt_rss_ctx *rss_ctx; int rc; - rc = bnxt_rxfh_context_check(bp, extack); + rc = bnxt_rxfh_context_check(bp, rxfh, extack); if (rc) return rc; @@ -5280,7 +5290,7 @@ void bnxt_ethtool_free(struct bnxt *bp) const struct ethtool_ops bnxt_ethtool_ops = { .cap_link_lanes_supported = 1, .cap_rss_ctx_supported = 1, - .rxfh_max_context_id = BNXT_MAX_ETH_RSS_CTX, + .rxfh_max_num_contexts = BNXT_MAX_ETH_RSS_CTX + 1, .rxfh_indir_space = BNXT_MAX_RSS_TABLE_ENTRIES_P5, .rxfh_priv_size = sizeof(struct bnxt_rss_ctx), .supported_coalesce_params = ETHTOOL_COALESCE_USECS | diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c b/drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c index 1248792d7fd4d2..0715ea5bf13ed9 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c @@ -42,19 +42,15 @@ void bcmgenet_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) struct bcmgenet_priv *priv = netdev_priv(dev); struct device *kdev = &priv->pdev->dev; - if (dev->phydev) { + if (dev->phydev) phy_ethtool_get_wol(dev->phydev, wol); - if (wol->supported) - return; - } - if (!device_can_wakeup(kdev)) { - wol->supported = 0; - wol->wolopts = 0; + /* MAC is not wake-up capable, return what the PHY does */ + if (!device_can_wakeup(kdev)) return; - } - wol->supported = WAKE_MAGIC | WAKE_MAGICSECURE | WAKE_FILTER; + /* Overlay MAC capabilities with that of the PHY queried before */ + wol->supported |= WAKE_MAGIC | WAKE_MAGICSECURE | WAKE_FILTER; wol->wolopts = priv->wolopts; memset(wol->sopass, 0, sizeof(wol->sopass)); diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c index 11665be3a22c7a..dcd3f54ed0cf00 100644 --- a/drivers/net/ethernet/cadence/macb_main.c +++ b/drivers/net/ethernet/cadence/macb_main.c @@ -5250,8 +5250,8 @@ static int __maybe_unused macb_suspend(struct device *dev) if (bp->wol & MACB_WOL_ENABLED) { /* Check for IP address in WOL ARP mode */ idev = __in_dev_get_rcu(bp->dev); - if (idev && idev->ifa_list) - ifa = rcu_access_pointer(idev->ifa_list); + if (idev) + ifa = rcu_dereference(idev->ifa_list); if ((bp->wolopts & WAKE_ARP) && !ifa) { netdev_err(netdev, "IP address not assigned as required by WoL walk ARP\n"); return -EOPNOTSUPP; diff --git a/drivers/net/ethernet/cavium/thunder/thunder_bgx.c b/drivers/net/ethernet/cavium/thunder/thunder_bgx.c index a40c266c37f207..608cc6af5af1c7 100644 --- a/drivers/net/ethernet/cavium/thunder/thunder_bgx.c +++ b/drivers/net/ethernet/cavium/thunder/thunder_bgx.c @@ -1054,18 +1054,12 @@ static int phy_interface_mode(u8 lmac_type) static int bgx_lmac_enable(struct bgx *bgx, u8 lmacid) { - struct lmac *lmac, **priv; + struct lmac *lmac; u64 cfg; lmac = &bgx->lmac[lmacid]; lmac->bgx = bgx; - lmac->netdev = alloc_netdev_dummy(sizeof(struct lmac *)); - if (!lmac->netdev) - return -ENOMEM; - priv = netdev_priv(lmac->netdev); - *priv = lmac; - if ((lmac->lmac_type == BGX_MODE_SGMII) || (lmac->lmac_type == BGX_MODE_QSGMII) || (lmac->lmac_type == BGX_MODE_RGMII)) { @@ -1191,7 +1185,6 @@ static void bgx_lmac_disable(struct bgx *bgx, u8 lmacid) (lmac->lmac_type != BGX_MODE_10G_KR) && lmac->phydev) phy_disconnect(lmac->phydev); - free_netdev(lmac->netdev); lmac->phydev = NULL; } @@ -1653,6 +1646,23 @@ static int bgx_probe(struct pci_dev *pdev, const struct pci_device_id *ent) bgx_get_qlm_mode(bgx); + for (lmac = 0; lmac < bgx->lmac_count; lmac++) { + struct lmac *lmacp, **priv; + + lmacp = &bgx->lmac[lmac]; + lmacp->netdev = alloc_netdev_dummy(sizeof(struct lmac *)); + + if (!lmacp->netdev) { + for (int i = 0; i < lmac; i++) + free_netdev(bgx->lmac[i].netdev); + err = -ENOMEM; + goto err_enable; + } + + priv = netdev_priv(lmacp->netdev); + *priv = lmacp; + } + err = bgx_init_phy(bgx); if (err) goto err_enable; @@ -1692,8 +1702,10 @@ static void bgx_remove(struct pci_dev *pdev) u8 lmac; /* Disable all LMACs */ - for (lmac = 0; lmac < bgx->lmac_count; lmac++) + for (lmac = 0; lmac < bgx->lmac_count; lmac++) { bgx_lmac_disable(bgx, lmac); + free_netdev(bgx->lmac[lmac].netdev); + } pci_free_irq(pdev, GMPX_GMI_TX_INT, bgx); diff --git a/drivers/net/ethernet/freescale/fec_ptp.c b/drivers/net/ethernet/freescale/fec_ptp.c index e32f6724f56816..2e4f3e1782a252 100644 --- a/drivers/net/ethernet/freescale/fec_ptp.c +++ b/drivers/net/ethernet/freescale/fec_ptp.c @@ -775,6 +775,9 @@ void fec_ptp_stop(struct platform_device *pdev) struct net_device *ndev = platform_get_drvdata(pdev); struct fec_enet_private *fep = netdev_priv(ndev); + if (fep->pps_enable) + fec_ptp_enable_pps(fep, 0); + cancel_delayed_work_sync(&fep->time_keep); hrtimer_cancel(&fep->perout_timer); if (fep->ptp_clock) diff --git a/drivers/net/ethernet/google/gve/gve_ethtool.c b/drivers/net/ethernet/google/gve/gve_ethtool.c index 3480ff5c7ed6a7..5a8b490ab3ad08 100644 --- a/drivers/net/ethernet/google/gve/gve_ethtool.c +++ b/drivers/net/ethernet/google/gve/gve_ethtool.c @@ -495,7 +495,7 @@ static int gve_set_channels(struct net_device *netdev, return -EINVAL; } - if (!netif_carrier_ok(netdev)) { + if (!netif_running(netdev)) { priv->tx_cfg.num_queues = new_tx; priv->rx_cfg.num_queues = new_rx; return 0; diff --git a/drivers/net/ethernet/google/gve/gve_main.c b/drivers/net/ethernet/google/gve/gve_main.c index 9744b426940e46..661566db68c860 100644 --- a/drivers/net/ethernet/google/gve/gve_main.c +++ b/drivers/net/ethernet/google/gve/gve_main.c @@ -1566,7 +1566,7 @@ static int gve_set_xdp(struct gve_priv *priv, struct bpf_prog *prog, u32 status; old_prog = READ_ONCE(priv->xdp_prog); - if (!netif_carrier_ok(priv->dev)) { + if (!netif_running(priv->dev)) { WRITE_ONCE(priv->xdp_prog, prog); if (old_prog) bpf_prog_put(old_prog); @@ -1847,7 +1847,7 @@ int gve_adjust_queues(struct gve_priv *priv, rx_alloc_cfg.qcfg = &new_rx_config; tx_alloc_cfg.num_rings = new_tx_config.num_queues; - if (netif_carrier_ok(priv->dev)) { + if (netif_running(priv->dev)) { err = gve_adjust_config(priv, &tx_alloc_cfg, &rx_alloc_cfg); return err; } @@ -2064,7 +2064,7 @@ static int gve_set_features(struct net_device *netdev, if ((netdev->features & NETIF_F_LRO) != (features & NETIF_F_LRO)) { netdev->features ^= NETIF_F_LRO; - if (netif_carrier_ok(netdev)) { + if (netif_running(netdev)) { err = gve_adjust_config(priv, &tx_alloc_cfg, &rx_alloc_cfg); if (err) goto revert_features; @@ -2359,7 +2359,7 @@ static int gve_reset_recovery(struct gve_priv *priv, bool was_up) int gve_reset(struct gve_priv *priv, bool attempt_teardown) { - bool was_up = netif_carrier_ok(priv->dev); + bool was_up = netif_running(priv->dev); int err; dev_info(&priv->pdev->dev, "Performing reset\n"); @@ -2700,7 +2700,7 @@ static void gve_shutdown(struct pci_dev *pdev) { struct net_device *netdev = pci_get_drvdata(pdev); struct gve_priv *priv = netdev_priv(netdev); - bool was_up = netif_carrier_ok(priv->dev); + bool was_up = netif_running(priv->dev); rtnl_lock(); if (was_up && gve_close(priv->dev)) { @@ -2718,7 +2718,7 @@ static int gve_suspend(struct pci_dev *pdev, pm_message_t state) { struct net_device *netdev = pci_get_drvdata(pdev); struct gve_priv *priv = netdev_priv(netdev); - bool was_up = netif_carrier_ok(priv->dev); + bool was_up = netif_running(priv->dev); priv->suspend_cnt++; rtnl_lock(); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index a5fc0209d628eb..4cbc4d069a1f36 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -5724,6 +5724,9 @@ static int hns3_reset_notify_uninit_enet(struct hnae3_handle *handle) struct net_device *netdev = handle->kinfo.netdev; struct hns3_nic_priv *priv = netdev_priv(netdev); + if (!test_bit(HNS3_NIC_STATE_DOWN, &priv->state)) + hns3_nic_net_stop(netdev); + if (!test_and_clear_bit(HNS3_NIC_STATE_INITED, &priv->state)) { netdev_warn(netdev, "already uninitialized\n"); return 0; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c index e132c2f0956098..cc7f46c0b35ff6 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c @@ -1598,8 +1598,7 @@ static void hclge_query_reg_info_of_ssu(struct hclge_dev *hdev) { u32 loop_para[HCLGE_MOD_MSG_PARA_ARRAY_MAX_SIZE] = {0}; struct hclge_mod_reg_common_msg msg; - u8 i, j, num; - u32 loop_time; + u8 i, j, num, loop_time; num = ARRAY_SIZE(hclge_ssu_reg_common_msg); for (i = 0; i < num; i++) { @@ -1609,7 +1608,8 @@ static void hclge_query_reg_info_of_ssu(struct hclge_dev *hdev) loop_time = 1; loop_para[0] = 0; if (msg.need_para) { - loop_time = hdev->ae_dev->dev_specs.tnl_num; + loop_time = min(hdev->ae_dev->dev_specs.tnl_num, + HCLGE_MOD_MSG_PARA_ARRAY_MAX_SIZE); for (j = 0; j < loop_time; j++) loop_para[j] = j + 1; } diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 82574ce0194fba..6c33195a1168f8 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -2653,8 +2653,17 @@ static int hclge_cfg_mac_speed_dup_h(struct hnae3_handle *handle, int speed, { struct hclge_vport *vport = hclge_get_vport(handle); struct hclge_dev *hdev = vport->back; + int ret; + + ret = hclge_cfg_mac_speed_dup(hdev, speed, duplex, lane_num); + + if (ret) + return ret; - return hclge_cfg_mac_speed_dup(hdev, speed, duplex, lane_num); + hdev->hw.mac.req_speed = speed; + hdev->hw.mac.req_duplex = duplex; + + return 0; } static int hclge_set_autoneg_en(struct hclge_dev *hdev, bool enable) @@ -2956,17 +2965,20 @@ static int hclge_mac_init(struct hclge_dev *hdev) if (!test_bit(HCLGE_STATE_RST_HANDLING, &hdev->state)) hdev->hw.mac.duplex = HCLGE_MAC_FULL; - ret = hclge_cfg_mac_speed_dup_hw(hdev, hdev->hw.mac.speed, - hdev->hw.mac.duplex, hdev->hw.mac.lane_num); - if (ret) - return ret; - if (hdev->hw.mac.support_autoneg) { ret = hclge_set_autoneg_en(hdev, hdev->hw.mac.autoneg); if (ret) return ret; } + if (!hdev->hw.mac.autoneg) { + ret = hclge_cfg_mac_speed_dup_hw(hdev, hdev->hw.mac.req_speed, + hdev->hw.mac.req_duplex, + hdev->hw.mac.lane_num); + if (ret) + return ret; + } + mac->link = 0; if (mac->user_fec_mode & BIT(HNAE3_FEC_USER_DEF)) { @@ -11444,7 +11456,7 @@ static void hclge_pci_uninit(struct hclge_dev *hdev) pcim_iounmap(pdev, hdev->hw.hw.io_base); pci_free_irq_vectors(pdev); - pci_release_mem_regions(pdev); + pci_release_regions(pdev); pci_disable_device(pdev); } @@ -11516,8 +11528,8 @@ static void hclge_reset_done(struct hnae3_ae_dev *ae_dev) dev_err(&hdev->pdev->dev, "fail to rebuild, ret=%d\n", ret); hdev->reset_type = HNAE3_NONE_RESET; - clear_bit(HCLGE_STATE_RST_HANDLING, &hdev->state); - up(&hdev->reset_sem); + if (test_and_clear_bit(HCLGE_STATE_RST_HANDLING, &hdev->state)) + up(&hdev->reset_sem); } static void hclge_clear_resetting_state(struct hclge_dev *hdev) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c index 85fb11de43a124..80079657afebe0 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c @@ -191,6 +191,9 @@ static void hclge_mac_adjust_link(struct net_device *netdev) if (ret) netdev_err(netdev, "failed to adjust link.\n"); + hdev->hw.mac.req_speed = (u32)speed; + hdev->hw.mac.req_duplex = (u8)duplex; + ret = hclge_cfg_flowctrl(hdev); if (ret) netdev_err(netdev, "failed to configure flow control.\n"); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c index 3735d2fed11f75..094a7c7b55921f 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c @@ -1747,8 +1747,8 @@ static void hclgevf_reset_done(struct hnae3_ae_dev *ae_dev) ret); hdev->reset_type = HNAE3_NONE_RESET; - clear_bit(HCLGEVF_STATE_RST_HANDLING, &hdev->state); - up(&hdev->reset_sem); + if (test_and_clear_bit(HCLGEVF_STATE_RST_HANDLING, &hdev->state)) + up(&hdev->reset_sem); } static u32 hclgevf_get_fw_version(struct hnae3_handle *handle) diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h index 99a75a59078ef3..caaa10157909ee 100644 --- a/drivers/net/ethernet/intel/ice/ice.h +++ b/drivers/net/ethernet/intel/ice/ice.h @@ -765,18 +765,17 @@ static inline struct xsk_buff_pool *ice_get_xp_from_qid(struct ice_vsi *vsi, } /** - * ice_xsk_pool - get XSK buffer pool bound to a ring + * ice_rx_xsk_pool - assign XSK buff pool to Rx ring * @ring: Rx ring to use * - * Returns a pointer to xsk_buff_pool structure if there is a buffer pool - * present, NULL otherwise. + * Sets XSK buff pool pointer on Rx ring. */ -static inline struct xsk_buff_pool *ice_xsk_pool(struct ice_rx_ring *ring) +static inline void ice_rx_xsk_pool(struct ice_rx_ring *ring) { struct ice_vsi *vsi = ring->vsi; u16 qid = ring->q_index; - return ice_get_xp_from_qid(vsi, qid); + WRITE_ONCE(ring->xsk_pool, ice_get_xp_from_qid(vsi, qid)); } /** @@ -801,7 +800,7 @@ static inline void ice_tx_xsk_pool(struct ice_vsi *vsi, u16 qid) if (!ring) return; - ring->xsk_pool = ice_get_xp_from_qid(vsi, qid); + WRITE_ONCE(ring->xsk_pool, ice_get_xp_from_qid(vsi, qid)); } /** diff --git a/drivers/net/ethernet/intel/ice/ice_base.c b/drivers/net/ethernet/intel/ice/ice_base.c index 5d396c1a773148..1facf179a96fd6 100644 --- a/drivers/net/ethernet/intel/ice/ice_base.c +++ b/drivers/net/ethernet/intel/ice/ice_base.c @@ -536,7 +536,7 @@ static int ice_vsi_cfg_rxq(struct ice_rx_ring *ring) return err; } - ring->xsk_pool = ice_xsk_pool(ring); + ice_rx_xsk_pool(ring); if (ring->xsk_pool) { xdp_rxq_info_unreg(&ring->xdp_rxq); @@ -597,7 +597,7 @@ static int ice_vsi_cfg_rxq(struct ice_rx_ring *ring) return 0; } - ok = ice_alloc_rx_bufs_zc(ring, num_bufs); + ok = ice_alloc_rx_bufs_zc(ring, ring->xsk_pool, num_bufs); if (!ok) { u16 pf_q = ring->vsi->rxq_map[ring->q_index]; diff --git a/drivers/net/ethernet/intel/ice/ice_ethtool.c b/drivers/net/ethernet/intel/ice/ice_ethtool.c index 8c990c97613299..bc79ba974e4958 100644 --- a/drivers/net/ethernet/intel/ice/ice_ethtool.c +++ b/drivers/net/ethernet/intel/ice/ice_ethtool.c @@ -4673,10 +4673,10 @@ static int ice_get_port_fec_stats(struct ice_hw *hw, u16 pcs_quad, u16 pcs_port, if (err) return err; - fec_stats->uncorrectable_blocks.total = (fec_corr_high_val << 16) + - fec_corr_low_val; - fec_stats->corrected_blocks.total = (fec_uncorr_high_val << 16) + - fec_uncorr_low_val; + fec_stats->corrected_blocks.total = (fec_corr_high_val << 16) + + fec_corr_low_val; + fec_stats->uncorrectable_blocks.total = (fec_uncorr_high_val << 16) + + fec_uncorr_low_val; return 0; } diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c index ec636be4d17d1e..6f97ed471fe9a1 100644 --- a/drivers/net/ethernet/intel/ice/ice_main.c +++ b/drivers/net/ethernet/intel/ice/ice_main.c @@ -559,6 +559,8 @@ ice_prepare_for_reset(struct ice_pf *pf, enum ice_reset_req reset_type) if (test_bit(ICE_PREPARED_FOR_RESET, pf->state)) return; + synchronize_irq(pf->oicr_irq.virq); + ice_unplug_aux_dev(pf); /* Notify VFs of impending reset */ @@ -2948,7 +2950,7 @@ static void ice_vsi_rx_napi_schedule(struct ice_vsi *vsi) ice_for_each_rxq(vsi, i) { struct ice_rx_ring *rx_ring = vsi->rx_rings[i]; - if (rx_ring->xsk_pool) + if (READ_ONCE(rx_ring->xsk_pool)) napi_schedule(&rx_ring->q_vector->napi); } } diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c index e2786cc1328611..ef2e858f49bb0e 100644 --- a/drivers/net/ethernet/intel/ice/ice_ptp.c +++ b/drivers/net/ethernet/intel/ice/ice_ptp.c @@ -1477,6 +1477,10 @@ void ice_ptp_link_change(struct ice_pf *pf, u8 port, bool linkup) /* Update cached link status for this port immediately */ ptp_port->link_up = linkup; + /* Skip HW writes if reset is in progress */ + if (pf->hw.reset_ongoing) + return; + switch (hw->ptp.phy_model) { case ICE_PHY_E810: /* Do not reconfigure E810 PHY */ diff --git a/drivers/net/ethernet/intel/ice/ice_txrx.c b/drivers/net/ethernet/intel/ice/ice_txrx.c index 8bb743f78fcb47..8d25b698126982 100644 --- a/drivers/net/ethernet/intel/ice/ice_txrx.c +++ b/drivers/net/ethernet/intel/ice/ice_txrx.c @@ -456,7 +456,7 @@ void ice_free_rx_ring(struct ice_rx_ring *rx_ring) if (rx_ring->vsi->type == ICE_VSI_PF) if (xdp_rxq_info_is_reg(&rx_ring->xdp_rxq)) xdp_rxq_info_unreg(&rx_ring->xdp_rxq); - rx_ring->xdp_prog = NULL; + WRITE_ONCE(rx_ring->xdp_prog, NULL); if (rx_ring->xsk_pool) { kfree(rx_ring->xdp_buf); rx_ring->xdp_buf = NULL; @@ -1521,10 +1521,11 @@ int ice_napi_poll(struct napi_struct *napi, int budget) * budget and be more aggressive about cleaning up the Tx descriptors. */ ice_for_each_tx_ring(tx_ring, q_vector->tx) { + struct xsk_buff_pool *xsk_pool = READ_ONCE(tx_ring->xsk_pool); bool wd; - if (tx_ring->xsk_pool) - wd = ice_xmit_zc(tx_ring); + if (xsk_pool) + wd = ice_xmit_zc(tx_ring, xsk_pool); else if (ice_ring_is_xdp(tx_ring)) wd = true; else @@ -1550,6 +1551,7 @@ int ice_napi_poll(struct napi_struct *napi, int budget) budget_per_ring = budget; ice_for_each_rx_ring(rx_ring, q_vector->rx) { + struct xsk_buff_pool *xsk_pool = READ_ONCE(rx_ring->xsk_pool); int cleaned; /* A dedicated path for zero-copy allows making a single @@ -1557,7 +1559,7 @@ int ice_napi_poll(struct napi_struct *napi, int budget) * ice_clean_rx_irq function and makes the codebase cleaner. */ cleaned = rx_ring->xsk_pool ? - ice_clean_rx_irq_zc(rx_ring, budget_per_ring) : + ice_clean_rx_irq_zc(rx_ring, xsk_pool, budget_per_ring) : ice_clean_rx_irq(rx_ring, budget_per_ring); work_done += cleaned; /* if we clean as many as budgeted, we must not be done */ diff --git a/drivers/net/ethernet/intel/ice/ice_xsk.c b/drivers/net/ethernet/intel/ice/ice_xsk.c index a65955eb23c0bd..240a7bec242be3 100644 --- a/drivers/net/ethernet/intel/ice/ice_xsk.c +++ b/drivers/net/ethernet/intel/ice/ice_xsk.c @@ -52,10 +52,8 @@ static void ice_qp_reset_stats(struct ice_vsi *vsi, u16 q_idx) static void ice_qp_clean_rings(struct ice_vsi *vsi, u16 q_idx) { ice_clean_tx_ring(vsi->tx_rings[q_idx]); - if (ice_is_xdp_ena_vsi(vsi)) { - synchronize_rcu(); + if (ice_is_xdp_ena_vsi(vsi)) ice_clean_tx_ring(vsi->xdp_rings[q_idx]); - } ice_clean_rx_ring(vsi->rx_rings[q_idx]); } @@ -112,25 +110,29 @@ ice_qvec_dis_irq(struct ice_vsi *vsi, struct ice_rx_ring *rx_ring, * ice_qvec_cfg_msix - Enable IRQ for given queue vector * @vsi: the VSI that contains queue vector * @q_vector: queue vector + * @qid: queue index */ static void -ice_qvec_cfg_msix(struct ice_vsi *vsi, struct ice_q_vector *q_vector) +ice_qvec_cfg_msix(struct ice_vsi *vsi, struct ice_q_vector *q_vector, u16 qid) { u16 reg_idx = q_vector->reg_idx; struct ice_pf *pf = vsi->back; struct ice_hw *hw = &pf->hw; - struct ice_tx_ring *tx_ring; - struct ice_rx_ring *rx_ring; + int q, _qid = qid; ice_cfg_itr(hw, q_vector); - ice_for_each_tx_ring(tx_ring, q_vector->tx) - ice_cfg_txq_interrupt(vsi, tx_ring->reg_idx, reg_idx, - q_vector->tx.itr_idx); + for (q = 0; q < q_vector->num_ring_tx; q++) { + ice_cfg_txq_interrupt(vsi, _qid, reg_idx, q_vector->tx.itr_idx); + _qid++; + } + + _qid = qid; - ice_for_each_rx_ring(rx_ring, q_vector->rx) - ice_cfg_rxq_interrupt(vsi, rx_ring->reg_idx, reg_idx, - q_vector->rx.itr_idx); + for (q = 0; q < q_vector->num_ring_rx; q++) { + ice_cfg_rxq_interrupt(vsi, _qid, reg_idx, q_vector->rx.itr_idx); + _qid++; + } ice_flush(hw); } @@ -164,6 +166,7 @@ static int ice_qp_dis(struct ice_vsi *vsi, u16 q_idx) struct ice_tx_ring *tx_ring; struct ice_rx_ring *rx_ring; int timeout = 50; + int fail = 0; int err; if (q_idx >= vsi->num_rxq || q_idx >= vsi->num_txq) @@ -180,15 +183,17 @@ static int ice_qp_dis(struct ice_vsi *vsi, u16 q_idx) usleep_range(1000, 2000); } + synchronize_net(); + netif_carrier_off(vsi->netdev); + netif_tx_stop_queue(netdev_get_tx_queue(vsi->netdev, q_idx)); + ice_qvec_dis_irq(vsi, rx_ring, q_vector); ice_qvec_toggle_napi(vsi, q_vector, false); - netif_tx_stop_queue(netdev_get_tx_queue(vsi->netdev, q_idx)); - ice_fill_txq_meta(vsi, tx_ring, &txq_meta); err = ice_vsi_stop_tx_ring(vsi, ICE_NO_RESET, 0, tx_ring, &txq_meta); - if (err) - return err; + if (!fail) + fail = err; if (ice_is_xdp_ena_vsi(vsi)) { struct ice_tx_ring *xdp_ring = vsi->xdp_rings[q_idx]; @@ -196,17 +201,15 @@ static int ice_qp_dis(struct ice_vsi *vsi, u16 q_idx) ice_fill_txq_meta(vsi, xdp_ring, &txq_meta); err = ice_vsi_stop_tx_ring(vsi, ICE_NO_RESET, 0, xdp_ring, &txq_meta); - if (err) - return err; + if (!fail) + fail = err; } - err = ice_vsi_ctrl_one_rx_ring(vsi, false, q_idx, true); - if (err) - return err; + ice_vsi_ctrl_one_rx_ring(vsi, false, q_idx, false); ice_qp_clean_rings(vsi, q_idx); ice_qp_reset_stats(vsi, q_idx); - return 0; + return fail; } /** @@ -219,40 +222,48 @@ static int ice_qp_dis(struct ice_vsi *vsi, u16 q_idx) static int ice_qp_ena(struct ice_vsi *vsi, u16 q_idx) { struct ice_q_vector *q_vector; + int fail = 0; + bool link_up; int err; err = ice_vsi_cfg_single_txq(vsi, vsi->tx_rings, q_idx); - if (err) - return err; + if (!fail) + fail = err; if (ice_is_xdp_ena_vsi(vsi)) { struct ice_tx_ring *xdp_ring = vsi->xdp_rings[q_idx]; err = ice_vsi_cfg_single_txq(vsi, vsi->xdp_rings, q_idx); - if (err) - return err; + if (!fail) + fail = err; ice_set_ring_xdp(xdp_ring); ice_tx_xsk_pool(vsi, q_idx); } err = ice_vsi_cfg_single_rxq(vsi, q_idx); - if (err) - return err; + if (!fail) + fail = err; q_vector = vsi->rx_rings[q_idx]->q_vector; - ice_qvec_cfg_msix(vsi, q_vector); + ice_qvec_cfg_msix(vsi, q_vector, q_idx); err = ice_vsi_ctrl_one_rx_ring(vsi, true, q_idx, true); - if (err) - return err; + if (!fail) + fail = err; ice_qvec_toggle_napi(vsi, q_vector, true); ice_qvec_ena_irq(vsi, q_vector); - netif_tx_start_queue(netdev_get_tx_queue(vsi->netdev, q_idx)); + /* make sure NAPI sees updated ice_{t,x}_ring::xsk_pool */ + synchronize_net(); + ice_get_link_status(vsi->port_info, &link_up); + if (link_up) { + netif_tx_start_queue(netdev_get_tx_queue(vsi->netdev, q_idx)); + netif_carrier_on(vsi->netdev); + } clear_bit(ICE_CFG_BUSY, vsi->state); - return 0; + return fail; } /** @@ -459,6 +470,7 @@ static u16 ice_fill_rx_descs(struct xsk_buff_pool *pool, struct xdp_buff **xdp, /** * __ice_alloc_rx_bufs_zc - allocate a number of Rx buffers * @rx_ring: Rx ring + * @xsk_pool: XSK buffer pool to pick buffers to be filled by HW * @count: The number of buffers to allocate * * Place the @count of descriptors onto Rx ring. Handle the ring wrap @@ -467,7 +479,8 @@ static u16 ice_fill_rx_descs(struct xsk_buff_pool *pool, struct xdp_buff **xdp, * * Returns true if all allocations were successful, false if any fail. */ -static bool __ice_alloc_rx_bufs_zc(struct ice_rx_ring *rx_ring, u16 count) +static bool __ice_alloc_rx_bufs_zc(struct ice_rx_ring *rx_ring, + struct xsk_buff_pool *xsk_pool, u16 count) { u32 nb_buffs_extra = 0, nb_buffs = 0; union ice_32b_rx_flex_desc *rx_desc; @@ -479,8 +492,7 @@ static bool __ice_alloc_rx_bufs_zc(struct ice_rx_ring *rx_ring, u16 count) xdp = ice_xdp_buf(rx_ring, ntu); if (ntu + count >= rx_ring->count) { - nb_buffs_extra = ice_fill_rx_descs(rx_ring->xsk_pool, xdp, - rx_desc, + nb_buffs_extra = ice_fill_rx_descs(xsk_pool, xdp, rx_desc, rx_ring->count - ntu); if (nb_buffs_extra != rx_ring->count - ntu) { ntu += nb_buffs_extra; @@ -493,7 +505,7 @@ static bool __ice_alloc_rx_bufs_zc(struct ice_rx_ring *rx_ring, u16 count) ice_release_rx_desc(rx_ring, 0); } - nb_buffs = ice_fill_rx_descs(rx_ring->xsk_pool, xdp, rx_desc, count); + nb_buffs = ice_fill_rx_descs(xsk_pool, xdp, rx_desc, count); ntu += nb_buffs; if (ntu == rx_ring->count) @@ -509,6 +521,7 @@ static bool __ice_alloc_rx_bufs_zc(struct ice_rx_ring *rx_ring, u16 count) /** * ice_alloc_rx_bufs_zc - allocate a number of Rx buffers * @rx_ring: Rx ring + * @xsk_pool: XSK buffer pool to pick buffers to be filled by HW * @count: The number of buffers to allocate * * Wrapper for internal allocation routine; figure out how many tail @@ -516,7 +529,8 @@ static bool __ice_alloc_rx_bufs_zc(struct ice_rx_ring *rx_ring, u16 count) * * Returns true if all calls to internal alloc routine succeeded */ -bool ice_alloc_rx_bufs_zc(struct ice_rx_ring *rx_ring, u16 count) +bool ice_alloc_rx_bufs_zc(struct ice_rx_ring *rx_ring, + struct xsk_buff_pool *xsk_pool, u16 count) { u16 rx_thresh = ICE_RING_QUARTER(rx_ring); u16 leftover, i, tail_bumps; @@ -525,9 +539,9 @@ bool ice_alloc_rx_bufs_zc(struct ice_rx_ring *rx_ring, u16 count) leftover = count - (tail_bumps * rx_thresh); for (i = 0; i < tail_bumps; i++) - if (!__ice_alloc_rx_bufs_zc(rx_ring, rx_thresh)) + if (!__ice_alloc_rx_bufs_zc(rx_ring, xsk_pool, rx_thresh)) return false; - return __ice_alloc_rx_bufs_zc(rx_ring, leftover); + return __ice_alloc_rx_bufs_zc(rx_ring, xsk_pool, leftover); } /** @@ -596,8 +610,10 @@ ice_construct_skb_zc(struct ice_rx_ring *rx_ring, struct xdp_buff *xdp) /** * ice_clean_xdp_irq_zc - produce AF_XDP descriptors to CQ * @xdp_ring: XDP Tx ring + * @xsk_pool: AF_XDP buffer pool pointer */ -static u32 ice_clean_xdp_irq_zc(struct ice_tx_ring *xdp_ring) +static u32 ice_clean_xdp_irq_zc(struct ice_tx_ring *xdp_ring, + struct xsk_buff_pool *xsk_pool) { u16 ntc = xdp_ring->next_to_clean; struct ice_tx_desc *tx_desc; @@ -648,7 +664,7 @@ static u32 ice_clean_xdp_irq_zc(struct ice_tx_ring *xdp_ring) if (xdp_ring->next_to_clean >= cnt) xdp_ring->next_to_clean -= cnt; if (xsk_frames) - xsk_tx_completed(xdp_ring->xsk_pool, xsk_frames); + xsk_tx_completed(xsk_pool, xsk_frames); return completed_frames; } @@ -657,6 +673,7 @@ static u32 ice_clean_xdp_irq_zc(struct ice_tx_ring *xdp_ring) * ice_xmit_xdp_tx_zc - AF_XDP ZC handler for XDP_TX * @xdp: XDP buffer to xmit * @xdp_ring: XDP ring to produce descriptor onto + * @xsk_pool: AF_XDP buffer pool pointer * * note that this function works directly on xdp_buff, no need to convert * it to xdp_frame. xdp_buff pointer is stored to ice_tx_buf so that cleaning @@ -666,7 +683,8 @@ static u32 ice_clean_xdp_irq_zc(struct ice_tx_ring *xdp_ring) * was not enough space on XDP ring */ static int ice_xmit_xdp_tx_zc(struct xdp_buff *xdp, - struct ice_tx_ring *xdp_ring) + struct ice_tx_ring *xdp_ring, + struct xsk_buff_pool *xsk_pool) { struct skb_shared_info *sinfo = NULL; u32 size = xdp->data_end - xdp->data; @@ -680,7 +698,7 @@ static int ice_xmit_xdp_tx_zc(struct xdp_buff *xdp, free_space = ICE_DESC_UNUSED(xdp_ring); if (free_space < ICE_RING_QUARTER(xdp_ring)) - free_space += ice_clean_xdp_irq_zc(xdp_ring); + free_space += ice_clean_xdp_irq_zc(xdp_ring, xsk_pool); if (unlikely(!free_space)) goto busy; @@ -700,7 +718,7 @@ static int ice_xmit_xdp_tx_zc(struct xdp_buff *xdp, dma_addr_t dma; dma = xsk_buff_xdp_get_dma(xdp); - xsk_buff_raw_dma_sync_for_device(xdp_ring->xsk_pool, dma, size); + xsk_buff_raw_dma_sync_for_device(xsk_pool, dma, size); tx_buf->xdp = xdp; tx_buf->type = ICE_TX_BUF_XSK_TX; @@ -742,12 +760,14 @@ static int ice_xmit_xdp_tx_zc(struct xdp_buff *xdp, * @xdp: xdp_buff used as input to the XDP program * @xdp_prog: XDP program to run * @xdp_ring: ring to be used for XDP_TX action + * @xsk_pool: AF_XDP buffer pool pointer * * Returns any of ICE_XDP_{PASS, CONSUMED, TX, REDIR} */ static int ice_run_xdp_zc(struct ice_rx_ring *rx_ring, struct xdp_buff *xdp, - struct bpf_prog *xdp_prog, struct ice_tx_ring *xdp_ring) + struct bpf_prog *xdp_prog, struct ice_tx_ring *xdp_ring, + struct xsk_buff_pool *xsk_pool) { int err, result = ICE_XDP_PASS; u32 act; @@ -758,7 +778,7 @@ ice_run_xdp_zc(struct ice_rx_ring *rx_ring, struct xdp_buff *xdp, err = xdp_do_redirect(rx_ring->netdev, xdp, xdp_prog); if (!err) return ICE_XDP_REDIR; - if (xsk_uses_need_wakeup(rx_ring->xsk_pool) && err == -ENOBUFS) + if (xsk_uses_need_wakeup(xsk_pool) && err == -ENOBUFS) result = ICE_XDP_EXIT; else result = ICE_XDP_CONSUMED; @@ -769,7 +789,7 @@ ice_run_xdp_zc(struct ice_rx_ring *rx_ring, struct xdp_buff *xdp, case XDP_PASS: break; case XDP_TX: - result = ice_xmit_xdp_tx_zc(xdp, xdp_ring); + result = ice_xmit_xdp_tx_zc(xdp, xdp_ring, xsk_pool); if (result == ICE_XDP_CONSUMED) goto out_failure; break; @@ -821,14 +841,16 @@ ice_add_xsk_frag(struct ice_rx_ring *rx_ring, struct xdp_buff *first, /** * ice_clean_rx_irq_zc - consumes packets from the hardware ring * @rx_ring: AF_XDP Rx ring + * @xsk_pool: AF_XDP buffer pool pointer * @budget: NAPI budget * * Returns number of processed packets on success, remaining budget on failure. */ -int ice_clean_rx_irq_zc(struct ice_rx_ring *rx_ring, int budget) +int ice_clean_rx_irq_zc(struct ice_rx_ring *rx_ring, + struct xsk_buff_pool *xsk_pool, + int budget) { unsigned int total_rx_bytes = 0, total_rx_packets = 0; - struct xsk_buff_pool *xsk_pool = rx_ring->xsk_pool; u32 ntc = rx_ring->next_to_clean; u32 ntu = rx_ring->next_to_use; struct xdp_buff *first = NULL; @@ -891,7 +913,8 @@ int ice_clean_rx_irq_zc(struct ice_rx_ring *rx_ring, int budget) if (ice_is_non_eop(rx_ring, rx_desc)) continue; - xdp_res = ice_run_xdp_zc(rx_ring, first, xdp_prog, xdp_ring); + xdp_res = ice_run_xdp_zc(rx_ring, first, xdp_prog, xdp_ring, + xsk_pool); if (likely(xdp_res & (ICE_XDP_TX | ICE_XDP_REDIR))) { xdp_xmit |= xdp_res; } else if (xdp_res == ICE_XDP_EXIT) { @@ -940,7 +963,8 @@ int ice_clean_rx_irq_zc(struct ice_rx_ring *rx_ring, int budget) rx_ring->next_to_clean = ntc; entries_to_alloc = ICE_RX_DESC_UNUSED(rx_ring); if (entries_to_alloc > ICE_RING_QUARTER(rx_ring)) - failure |= !ice_alloc_rx_bufs_zc(rx_ring, entries_to_alloc); + failure |= !ice_alloc_rx_bufs_zc(rx_ring, xsk_pool, + entries_to_alloc); ice_finalize_xdp_rx(xdp_ring, xdp_xmit, 0); ice_update_rx_ring_stats(rx_ring, total_rx_packets, total_rx_bytes); @@ -963,17 +987,19 @@ int ice_clean_rx_irq_zc(struct ice_rx_ring *rx_ring, int budget) /** * ice_xmit_pkt - produce a single HW Tx descriptor out of AF_XDP descriptor * @xdp_ring: XDP ring to produce the HW Tx descriptor on + * @xsk_pool: XSK buffer pool to pick buffers to be consumed by HW * @desc: AF_XDP descriptor to pull the DMA address and length from * @total_bytes: bytes accumulator that will be used for stats update */ -static void ice_xmit_pkt(struct ice_tx_ring *xdp_ring, struct xdp_desc *desc, +static void ice_xmit_pkt(struct ice_tx_ring *xdp_ring, + struct xsk_buff_pool *xsk_pool, struct xdp_desc *desc, unsigned int *total_bytes) { struct ice_tx_desc *tx_desc; dma_addr_t dma; - dma = xsk_buff_raw_get_dma(xdp_ring->xsk_pool, desc->addr); - xsk_buff_raw_dma_sync_for_device(xdp_ring->xsk_pool, dma, desc->len); + dma = xsk_buff_raw_get_dma(xsk_pool, desc->addr); + xsk_buff_raw_dma_sync_for_device(xsk_pool, dma, desc->len); tx_desc = ICE_TX_DESC(xdp_ring, xdp_ring->next_to_use++); tx_desc->buf_addr = cpu_to_le64(dma); @@ -986,10 +1012,13 @@ static void ice_xmit_pkt(struct ice_tx_ring *xdp_ring, struct xdp_desc *desc, /** * ice_xmit_pkt_batch - produce a batch of HW Tx descriptors out of AF_XDP descriptors * @xdp_ring: XDP ring to produce the HW Tx descriptors on + * @xsk_pool: XSK buffer pool to pick buffers to be consumed by HW * @descs: AF_XDP descriptors to pull the DMA addresses and lengths from * @total_bytes: bytes accumulator that will be used for stats update */ -static void ice_xmit_pkt_batch(struct ice_tx_ring *xdp_ring, struct xdp_desc *descs, +static void ice_xmit_pkt_batch(struct ice_tx_ring *xdp_ring, + struct xsk_buff_pool *xsk_pool, + struct xdp_desc *descs, unsigned int *total_bytes) { u16 ntu = xdp_ring->next_to_use; @@ -999,8 +1028,8 @@ static void ice_xmit_pkt_batch(struct ice_tx_ring *xdp_ring, struct xdp_desc *de loop_unrolled_for(i = 0; i < PKTS_PER_BATCH; i++) { dma_addr_t dma; - dma = xsk_buff_raw_get_dma(xdp_ring->xsk_pool, descs[i].addr); - xsk_buff_raw_dma_sync_for_device(xdp_ring->xsk_pool, dma, descs[i].len); + dma = xsk_buff_raw_get_dma(xsk_pool, descs[i].addr); + xsk_buff_raw_dma_sync_for_device(xsk_pool, dma, descs[i].len); tx_desc = ICE_TX_DESC(xdp_ring, ntu++); tx_desc->buf_addr = cpu_to_le64(dma); @@ -1016,60 +1045,69 @@ static void ice_xmit_pkt_batch(struct ice_tx_ring *xdp_ring, struct xdp_desc *de /** * ice_fill_tx_hw_ring - produce the number of Tx descriptors onto ring * @xdp_ring: XDP ring to produce the HW Tx descriptors on + * @xsk_pool: XSK buffer pool to pick buffers to be consumed by HW * @descs: AF_XDP descriptors to pull the DMA addresses and lengths from * @nb_pkts: count of packets to be send * @total_bytes: bytes accumulator that will be used for stats update */ -static void ice_fill_tx_hw_ring(struct ice_tx_ring *xdp_ring, struct xdp_desc *descs, - u32 nb_pkts, unsigned int *total_bytes) +static void ice_fill_tx_hw_ring(struct ice_tx_ring *xdp_ring, + struct xsk_buff_pool *xsk_pool, + struct xdp_desc *descs, u32 nb_pkts, + unsigned int *total_bytes) { u32 batched, leftover, i; batched = ALIGN_DOWN(nb_pkts, PKTS_PER_BATCH); leftover = nb_pkts & (PKTS_PER_BATCH - 1); for (i = 0; i < batched; i += PKTS_PER_BATCH) - ice_xmit_pkt_batch(xdp_ring, &descs[i], total_bytes); + ice_xmit_pkt_batch(xdp_ring, xsk_pool, &descs[i], total_bytes); for (; i < batched + leftover; i++) - ice_xmit_pkt(xdp_ring, &descs[i], total_bytes); + ice_xmit_pkt(xdp_ring, xsk_pool, &descs[i], total_bytes); } /** * ice_xmit_zc - take entries from XSK Tx ring and place them onto HW Tx ring * @xdp_ring: XDP ring to produce the HW Tx descriptors on + * @xsk_pool: AF_XDP buffer pool pointer * * Returns true if there is no more work that needs to be done, false otherwise */ -bool ice_xmit_zc(struct ice_tx_ring *xdp_ring) +bool ice_xmit_zc(struct ice_tx_ring *xdp_ring, struct xsk_buff_pool *xsk_pool) { - struct xdp_desc *descs = xdp_ring->xsk_pool->tx_descs; + struct xdp_desc *descs = xsk_pool->tx_descs; u32 nb_pkts, nb_processed = 0; unsigned int total_bytes = 0; int budget; - ice_clean_xdp_irq_zc(xdp_ring); + ice_clean_xdp_irq_zc(xdp_ring, xsk_pool); + + if (!netif_carrier_ok(xdp_ring->vsi->netdev) || + !netif_running(xdp_ring->vsi->netdev)) + return true; budget = ICE_DESC_UNUSED(xdp_ring); budget = min_t(u16, budget, ICE_RING_QUARTER(xdp_ring)); - nb_pkts = xsk_tx_peek_release_desc_batch(xdp_ring->xsk_pool, budget); + nb_pkts = xsk_tx_peek_release_desc_batch(xsk_pool, budget); if (!nb_pkts) return true; if (xdp_ring->next_to_use + nb_pkts >= xdp_ring->count) { nb_processed = xdp_ring->count - xdp_ring->next_to_use; - ice_fill_tx_hw_ring(xdp_ring, descs, nb_processed, &total_bytes); + ice_fill_tx_hw_ring(xdp_ring, xsk_pool, descs, nb_processed, + &total_bytes); xdp_ring->next_to_use = 0; } - ice_fill_tx_hw_ring(xdp_ring, &descs[nb_processed], nb_pkts - nb_processed, - &total_bytes); + ice_fill_tx_hw_ring(xdp_ring, xsk_pool, &descs[nb_processed], + nb_pkts - nb_processed, &total_bytes); ice_set_rs_bit(xdp_ring); ice_xdp_ring_update_tail(xdp_ring); ice_update_tx_ring_stats(xdp_ring, nb_pkts, total_bytes); - if (xsk_uses_need_wakeup(xdp_ring->xsk_pool)) - xsk_set_tx_need_wakeup(xdp_ring->xsk_pool); + if (xsk_uses_need_wakeup(xsk_pool)) + xsk_set_tx_need_wakeup(xsk_pool); return nb_pkts < budget; } @@ -1091,7 +1129,7 @@ ice_xsk_wakeup(struct net_device *netdev, u32 queue_id, struct ice_vsi *vsi = np->vsi; struct ice_tx_ring *ring; - if (test_bit(ICE_VSI_DOWN, vsi->state)) + if (test_bit(ICE_VSI_DOWN, vsi->state) || !netif_carrier_ok(netdev)) return -ENETDOWN; if (!ice_is_xdp_ena_vsi(vsi)) @@ -1102,7 +1140,7 @@ ice_xsk_wakeup(struct net_device *netdev, u32 queue_id, ring = vsi->rx_rings[queue_id]->xdp_ring; - if (!ring->xsk_pool) + if (!READ_ONCE(ring->xsk_pool)) return -EINVAL; /* The idea here is that if NAPI is running, mark a miss, so diff --git a/drivers/net/ethernet/intel/ice/ice_xsk.h b/drivers/net/ethernet/intel/ice/ice_xsk.h index 6fa181f080ef13..45adeb513253a0 100644 --- a/drivers/net/ethernet/intel/ice/ice_xsk.h +++ b/drivers/net/ethernet/intel/ice/ice_xsk.h @@ -20,16 +20,20 @@ struct ice_vsi; #ifdef CONFIG_XDP_SOCKETS int ice_xsk_pool_setup(struct ice_vsi *vsi, struct xsk_buff_pool *pool, u16 qid); -int ice_clean_rx_irq_zc(struct ice_rx_ring *rx_ring, int budget); +int ice_clean_rx_irq_zc(struct ice_rx_ring *rx_ring, + struct xsk_buff_pool *xsk_pool, + int budget); int ice_xsk_wakeup(struct net_device *netdev, u32 queue_id, u32 flags); -bool ice_alloc_rx_bufs_zc(struct ice_rx_ring *rx_ring, u16 count); +bool ice_alloc_rx_bufs_zc(struct ice_rx_ring *rx_ring, + struct xsk_buff_pool *xsk_pool, u16 count); bool ice_xsk_any_rx_ring_ena(struct ice_vsi *vsi); void ice_xsk_clean_rx_ring(struct ice_rx_ring *rx_ring); void ice_xsk_clean_xdp_ring(struct ice_tx_ring *xdp_ring); -bool ice_xmit_zc(struct ice_tx_ring *xdp_ring); +bool ice_xmit_zc(struct ice_tx_ring *xdp_ring, struct xsk_buff_pool *xsk_pool); int ice_realloc_zc_buf(struct ice_vsi *vsi, bool zc); #else -static inline bool ice_xmit_zc(struct ice_tx_ring __always_unused *xdp_ring) +static inline bool ice_xmit_zc(struct ice_tx_ring __always_unused *xdp_ring, + struct xsk_buff_pool __always_unused *xsk_pool) { return false; } @@ -44,6 +48,7 @@ ice_xsk_pool_setup(struct ice_vsi __always_unused *vsi, static inline int ice_clean_rx_irq_zc(struct ice_rx_ring __always_unused *rx_ring, + struct xsk_buff_pool __always_unused *xsk_pool, int __always_unused budget) { return 0; @@ -51,6 +56,7 @@ ice_clean_rx_irq_zc(struct ice_rx_ring __always_unused *rx_ring, static inline bool ice_alloc_rx_bufs_zc(struct ice_rx_ring __always_unused *rx_ring, + struct xsk_buff_pool __always_unused *xsk_pool, u16 __always_unused count) { return false; diff --git a/drivers/net/ethernet/intel/idpf/idpf_lib.c b/drivers/net/ethernet/intel/idpf/idpf_lib.c index 5dbf2b4ba1b001..0b6c8fd5bc90f7 100644 --- a/drivers/net/ethernet/intel/idpf/idpf_lib.c +++ b/drivers/net/ethernet/intel/idpf/idpf_lib.c @@ -900,8 +900,8 @@ static void idpf_vport_stop(struct idpf_vport *vport) vport->link_up = false; idpf_vport_intr_deinit(vport); - idpf_vport_intr_rel(vport); idpf_vport_queues_rel(vport); + idpf_vport_intr_rel(vport); np->state = __IDPF_VPORT_DOWN; } @@ -1335,9 +1335,8 @@ static void idpf_rx_init_buf_tail(struct idpf_vport *vport) /** * idpf_vport_open - Bring up a vport * @vport: vport to bring up - * @alloc_res: allocate queue resources */ -static int idpf_vport_open(struct idpf_vport *vport, bool alloc_res) +static int idpf_vport_open(struct idpf_vport *vport) { struct idpf_netdev_priv *np = netdev_priv(vport->netdev); struct idpf_adapter *adapter = vport->adapter; @@ -1350,45 +1349,43 @@ static int idpf_vport_open(struct idpf_vport *vport, bool alloc_res) /* we do not allow interface up just yet */ netif_carrier_off(vport->netdev); - if (alloc_res) { - err = idpf_vport_queues_alloc(vport); - if (err) - return err; - } - err = idpf_vport_intr_alloc(vport); if (err) { dev_err(&adapter->pdev->dev, "Failed to allocate interrupts for vport %u: %d\n", vport->vport_id, err); - goto queues_rel; + return err; } + err = idpf_vport_queues_alloc(vport); + if (err) + goto intr_rel; + err = idpf_vport_queue_ids_init(vport); if (err) { dev_err(&adapter->pdev->dev, "Failed to initialize queue ids for vport %u: %d\n", vport->vport_id, err); - goto intr_rel; + goto queues_rel; } err = idpf_vport_intr_init(vport); if (err) { dev_err(&adapter->pdev->dev, "Failed to initialize interrupts for vport %u: %d\n", vport->vport_id, err); - goto intr_rel; + goto queues_rel; } err = idpf_rx_bufs_init_all(vport); if (err) { dev_err(&adapter->pdev->dev, "Failed to initialize RX buffers for vport %u: %d\n", vport->vport_id, err); - goto intr_rel; + goto queues_rel; } err = idpf_queue_reg_init(vport); if (err) { dev_err(&adapter->pdev->dev, "Failed to initialize queue registers for vport %u: %d\n", vport->vport_id, err); - goto intr_rel; + goto queues_rel; } idpf_rx_init_buf_tail(vport); @@ -1455,10 +1452,10 @@ static int idpf_vport_open(struct idpf_vport *vport, bool alloc_res) idpf_send_map_unmap_queue_vector_msg(vport, false); intr_deinit: idpf_vport_intr_deinit(vport); -intr_rel: - idpf_vport_intr_rel(vport); queues_rel: idpf_vport_queues_rel(vport); +intr_rel: + idpf_vport_intr_rel(vport); return err; } @@ -1539,7 +1536,7 @@ void idpf_init_task(struct work_struct *work) np = netdev_priv(vport->netdev); np->state = __IDPF_VPORT_DOWN; if (test_and_clear_bit(IDPF_VPORT_UP_REQUESTED, vport_config->flags)) - idpf_vport_open(vport, true); + idpf_vport_open(vport); /* Spawn and return 'idpf_init_task' work queue until all the * default vports are created @@ -1898,9 +1895,6 @@ int idpf_initiate_soft_reset(struct idpf_vport *vport, goto free_vport; } - err = idpf_vport_queues_alloc(new_vport); - if (err) - goto free_vport; if (current_state <= __IDPF_VPORT_DOWN) { idpf_send_delete_queues_msg(vport); } else { @@ -1932,17 +1926,23 @@ int idpf_initiate_soft_reset(struct idpf_vport *vport, err = idpf_set_real_num_queues(vport); if (err) - goto err_reset; + goto err_open; if (current_state == __IDPF_VPORT_UP) - err = idpf_vport_open(vport, false); + err = idpf_vport_open(vport); kfree(new_vport); return err; err_reset: - idpf_vport_queues_rel(new_vport); + idpf_send_add_queues_msg(vport, vport->num_txq, vport->num_complq, + vport->num_rxq, vport->num_bufq); + +err_open: + if (current_state == __IDPF_VPORT_UP) + idpf_vport_open(vport); + free_vport: kfree(new_vport); @@ -2171,7 +2171,7 @@ static int idpf_open(struct net_device *netdev) idpf_vport_ctrl_lock(netdev); vport = idpf_netdev_to_vport(netdev); - err = idpf_vport_open(vport, true); + err = idpf_vport_open(vport); idpf_vport_ctrl_unlock(netdev); diff --git a/drivers/net/ethernet/intel/idpf/idpf_txrx.c b/drivers/net/ethernet/intel/idpf/idpf_txrx.c index af2879f03b8df7..585c3dadd9bfac 100644 --- a/drivers/net/ethernet/intel/idpf/idpf_txrx.c +++ b/drivers/net/ethernet/intel/idpf/idpf_txrx.c @@ -3576,9 +3576,7 @@ static void idpf_vport_intr_napi_dis_all(struct idpf_vport *vport) */ void idpf_vport_intr_rel(struct idpf_vport *vport) { - int i, j, v_idx; - - for (v_idx = 0; v_idx < vport->num_q_vectors; v_idx++) { + for (u32 v_idx = 0; v_idx < vport->num_q_vectors; v_idx++) { struct idpf_q_vector *q_vector = &vport->q_vectors[v_idx]; kfree(q_vector->complq); @@ -3593,26 +3591,6 @@ void idpf_vport_intr_rel(struct idpf_vport *vport) free_cpumask_var(q_vector->affinity_mask); } - /* Clean up the mapping of queues to vectors */ - for (i = 0; i < vport->num_rxq_grp; i++) { - struct idpf_rxq_group *rx_qgrp = &vport->rxq_grps[i]; - - if (idpf_is_queue_model_split(vport->rxq_model)) - for (j = 0; j < rx_qgrp->splitq.num_rxq_sets; j++) - rx_qgrp->splitq.rxq_sets[j]->rxq.q_vector = NULL; - else - for (j = 0; j < rx_qgrp->singleq.num_rxq; j++) - rx_qgrp->singleq.rxqs[j]->q_vector = NULL; - } - - if (idpf_is_queue_model_split(vport->txq_model)) - for (i = 0; i < vport->num_txq_grp; i++) - vport->txq_grps[i].complq->q_vector = NULL; - else - for (i = 0; i < vport->num_txq_grp; i++) - for (j = 0; j < vport->txq_grps[i].num_txq; j++) - vport->txq_grps[i].txqs[j]->q_vector = NULL; - kfree(vport->q_vectors); vport->q_vectors = NULL; } @@ -3780,13 +3758,15 @@ void idpf_vport_intr_update_itr_ena_irq(struct idpf_q_vector *q_vector) /** * idpf_vport_intr_req_irq - get MSI-X vectors from the OS for the vport * @vport: main vport structure - * @basename: name for the vector */ -static int idpf_vport_intr_req_irq(struct idpf_vport *vport, char *basename) +static int idpf_vport_intr_req_irq(struct idpf_vport *vport) { struct idpf_adapter *adapter = vport->adapter; + const char *drv_name, *if_name, *vec_name; int vector, err, irq_num, vidx; - const char *vec_name; + + drv_name = dev_driver_string(&adapter->pdev->dev); + if_name = netdev_name(vport->netdev); for (vector = 0; vector < vport->num_q_vectors; vector++) { struct idpf_q_vector *q_vector = &vport->q_vectors[vector]; @@ -3804,8 +3784,8 @@ static int idpf_vport_intr_req_irq(struct idpf_vport *vport, char *basename) else continue; - name = kasprintf(GFP_KERNEL, "%s-%s-%d", basename, vec_name, - vidx); + name = kasprintf(GFP_KERNEL, "%s-%s-%s-%d", drv_name, if_name, + vec_name, vidx); err = request_irq(irq_num, idpf_vport_intr_clean_queues, 0, name, q_vector); @@ -4326,7 +4306,6 @@ int idpf_vport_intr_alloc(struct idpf_vport *vport) */ int idpf_vport_intr_init(struct idpf_vport *vport) { - char *int_name; int err; err = idpf_vport_intr_init_vec_idx(vport); @@ -4340,11 +4319,7 @@ int idpf_vport_intr_init(struct idpf_vport *vport) if (err) goto unroll_vectors_alloc; - int_name = kasprintf(GFP_KERNEL, "%s-%s", - dev_driver_string(&vport->adapter->pdev->dev), - vport->netdev->name); - - err = idpf_vport_intr_req_irq(vport, int_name); + err = idpf_vport_intr_req_irq(vport); if (err) goto unroll_vectors_alloc; diff --git a/drivers/net/ethernet/intel/igc/igc_defines.h b/drivers/net/ethernet/intel/igc/igc_defines.h index 5f92b3c7c3d4a1..511384f3ec5cb5 100644 --- a/drivers/net/ethernet/intel/igc/igc_defines.h +++ b/drivers/net/ethernet/intel/igc/igc_defines.h @@ -404,6 +404,12 @@ #define IGC_DTXMXPKTSZ_TSN 0x19 /* 1600 bytes of max TX DMA packet size */ #define IGC_DTXMXPKTSZ_DEFAULT 0x98 /* 9728-byte Jumbo frames */ +/* Retry Buffer Control */ +#define IGC_RETX_CTL 0x041C +#define IGC_RETX_CTL_WATERMARK_MASK 0xF +#define IGC_RETX_CTL_QBVFULLTH_SHIFT 8 /* QBV Retry Buffer Full Threshold */ +#define IGC_RETX_CTL_QBVFULLEN 0x1000 /* Enable QBV Retry Buffer Full Threshold */ + /* Transmit Scheduling Latency */ /* Latency between transmission scheduling (LaunchTime) and the time * the packet is transmitted to the network in nanosecond. diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c index cb5c7b09e8a009..dfd6c00b4205d4 100644 --- a/drivers/net/ethernet/intel/igc/igc_main.c +++ b/drivers/net/ethernet/intel/igc/igc_main.c @@ -6306,21 +6306,6 @@ static int igc_save_qbv_schedule(struct igc_adapter *adapter, size_t n; int i; - switch (qopt->cmd) { - case TAPRIO_CMD_REPLACE: - break; - case TAPRIO_CMD_DESTROY: - return igc_tsn_clear_schedule(adapter); - case TAPRIO_CMD_STATS: - igc_taprio_stats(adapter->netdev, &qopt->stats); - return 0; - case TAPRIO_CMD_QUEUE_STATS: - igc_taprio_queue_stats(adapter->netdev, &qopt->queue_stats); - return 0; - default: - return -EOPNOTSUPP; - } - if (qopt->base_time < 0) return -ERANGE; @@ -6330,12 +6315,16 @@ static int igc_save_qbv_schedule(struct igc_adapter *adapter, if (!validate_schedule(adapter, qopt)) return -EINVAL; + igc_ptp_read(adapter, &now); + + if (igc_tsn_is_taprio_activated_by_user(adapter) && + is_base_time_past(qopt->base_time, &now)) + adapter->qbv_config_change_errors++; + adapter->cycle_time = qopt->cycle_time; adapter->base_time = qopt->base_time; adapter->taprio_offload_enable = true; - igc_ptp_read(adapter, &now); - for (n = 0; n < qopt->num_entries; n++) { struct tc_taprio_sched_entry *e = &qopt->entries[n]; @@ -6429,7 +6418,23 @@ static int igc_tsn_enable_qbv_scheduling(struct igc_adapter *adapter, if (hw->mac.type != igc_i225) return -EOPNOTSUPP; - err = igc_save_qbv_schedule(adapter, qopt); + switch (qopt->cmd) { + case TAPRIO_CMD_REPLACE: + err = igc_save_qbv_schedule(adapter, qopt); + break; + case TAPRIO_CMD_DESTROY: + err = igc_tsn_clear_schedule(adapter); + break; + case TAPRIO_CMD_STATS: + igc_taprio_stats(adapter->netdev, &qopt->stats); + return 0; + case TAPRIO_CMD_QUEUE_STATS: + igc_taprio_queue_stats(adapter->netdev, &qopt->queue_stats); + return 0; + default: + return -EOPNOTSUPP; + } + if (err) return err; diff --git a/drivers/net/ethernet/intel/igc/igc_tsn.c b/drivers/net/ethernet/intel/igc/igc_tsn.c index 22cefb1eeedfa7..d68fa7f3d5f078 100644 --- a/drivers/net/ethernet/intel/igc/igc_tsn.c +++ b/drivers/net/ethernet/intel/igc/igc_tsn.c @@ -49,12 +49,19 @@ static unsigned int igc_tsn_new_flags(struct igc_adapter *adapter) return new_flags; } +static bool igc_tsn_is_tx_mode_in_tsn(struct igc_adapter *adapter) +{ + struct igc_hw *hw = &adapter->hw; + + return !!(rd32(IGC_TQAVCTRL) & IGC_TQAVCTRL_TRANSMIT_MODE_TSN); +} + void igc_tsn_adjust_txtime_offset(struct igc_adapter *adapter) { struct igc_hw *hw = &adapter->hw; u16 txoffset; - if (!is_any_launchtime(adapter)) + if (!igc_tsn_is_tx_mode_in_tsn(adapter)) return; switch (adapter->link_speed) { @@ -78,6 +85,23 @@ void igc_tsn_adjust_txtime_offset(struct igc_adapter *adapter) wr32(IGC_GTXOFFSET, txoffset); } +static void igc_tsn_restore_retx_default(struct igc_adapter *adapter) +{ + struct igc_hw *hw = &adapter->hw; + u32 retxctl; + + retxctl = rd32(IGC_RETX_CTL) & IGC_RETX_CTL_WATERMARK_MASK; + wr32(IGC_RETX_CTL, retxctl); +} + +bool igc_tsn_is_taprio_activated_by_user(struct igc_adapter *adapter) +{ + struct igc_hw *hw = &adapter->hw; + + return (rd32(IGC_BASET_H) || rd32(IGC_BASET_L)) && + adapter->taprio_offload_enable; +} + /* Returns the TSN specific registers to their default values after * the adapter is reset. */ @@ -91,6 +115,9 @@ static int igc_tsn_disable_offload(struct igc_adapter *adapter) wr32(IGC_TXPBS, I225_TXPBSIZE_DEFAULT); wr32(IGC_DTXMXPKTSZ, IGC_DTXMXPKTSZ_DEFAULT); + if (igc_is_device_id_i226(hw)) + igc_tsn_restore_retx_default(adapter); + tqavctrl = rd32(IGC_TQAVCTRL); tqavctrl &= ~(IGC_TQAVCTRL_TRANSMIT_MODE_TSN | IGC_TQAVCTRL_ENHANCED_QAV | IGC_TQAVCTRL_FUTSCDDIS); @@ -111,6 +138,25 @@ static int igc_tsn_disable_offload(struct igc_adapter *adapter) return 0; } +/* To partially fix i226 HW errata, reduce MAC internal buffering from 192 Bytes + * to 88 Bytes by setting RETX_CTL register using the recommendation from: + * a) Ethernet Controller I225/I226 Specification Update Rev 2.1 + * Item 9: TSN: Packet Transmission Might Cross the Qbv Window + * b) I225/6 SW User Manual Rev 1.2.4: Section 8.11.5 Retry Buffer Control + */ +static void igc_tsn_set_retx_qbvfullthreshold(struct igc_adapter *adapter) +{ + struct igc_hw *hw = &adapter->hw; + u32 retxctl, watermark; + + retxctl = rd32(IGC_RETX_CTL); + watermark = retxctl & IGC_RETX_CTL_WATERMARK_MASK; + /* Set QBVFULLTH value using watermark and set QBVFULLEN */ + retxctl |= (watermark << IGC_RETX_CTL_QBVFULLTH_SHIFT) | + IGC_RETX_CTL_QBVFULLEN; + wr32(IGC_RETX_CTL, retxctl); +} + static int igc_tsn_enable_offload(struct igc_adapter *adapter) { struct igc_hw *hw = &adapter->hw; @@ -123,6 +169,9 @@ static int igc_tsn_enable_offload(struct igc_adapter *adapter) wr32(IGC_DTXMXPKTSZ, IGC_DTXMXPKTSZ_TSN); wr32(IGC_TXPBS, IGC_TXPBSIZE_TSN); + if (igc_is_device_id_i226(hw)) + igc_tsn_set_retx_qbvfullthreshold(adapter); + for (i = 0; i < adapter->num_tx_queues; i++) { struct igc_ring *ring = adapter->tx_ring[i]; u32 txqctl = 0; @@ -262,14 +311,6 @@ static int igc_tsn_enable_offload(struct igc_adapter *adapter) s64 n = div64_s64(ktime_sub_ns(systim, base_time), cycle); base_time = ktime_add_ns(base_time, (n + 1) * cycle); - - /* Increase the counter if scheduling into the past while - * Gate Control List (GCL) is running. - */ - if ((rd32(IGC_BASET_H) || rd32(IGC_BASET_L)) && - (adapter->tc_setup_type == TC_SETUP_QDISC_TAPRIO) && - (adapter->qbv_count > 1)) - adapter->qbv_config_change_errors++; } else { if (igc_is_device_id_i226(hw)) { ktime_t adjust_time, expires_time; @@ -331,15 +372,22 @@ int igc_tsn_reset(struct igc_adapter *adapter) return err; } -int igc_tsn_offload_apply(struct igc_adapter *adapter) +static bool igc_tsn_will_tx_mode_change(struct igc_adapter *adapter) { - struct igc_hw *hw = &adapter->hw; + bool any_tsn_enabled = !!(igc_tsn_new_flags(adapter) & + IGC_FLAG_TSN_ANY_ENABLED); - /* Per I225/6 HW Design Section 7.5.2.1, transmit mode - * cannot be changed dynamically. Require reset the adapter. + return (any_tsn_enabled && !igc_tsn_is_tx_mode_in_tsn(adapter)) || + (!any_tsn_enabled && igc_tsn_is_tx_mode_in_tsn(adapter)); +} + +int igc_tsn_offload_apply(struct igc_adapter *adapter) +{ + /* Per I225/6 HW Design Section 7.5.2.1 guideline, if tx mode change + * from legacy->tsn or tsn->legacy, then reset adapter is needed. */ if (netif_running(adapter->netdev) && - (igc_is_device_id_i225(hw) || !adapter->qbv_count)) { + igc_tsn_will_tx_mode_change(adapter)) { schedule_work(&adapter->reset_task); return 0; } diff --git a/drivers/net/ethernet/intel/igc/igc_tsn.h b/drivers/net/ethernet/intel/igc/igc_tsn.h index b53e6af560b738..98ec845a86bf00 100644 --- a/drivers/net/ethernet/intel/igc/igc_tsn.h +++ b/drivers/net/ethernet/intel/igc/igc_tsn.h @@ -7,5 +7,6 @@ int igc_tsn_offload_apply(struct igc_adapter *adapter); int igc_tsn_reset(struct igc_adapter *adapter); void igc_tsn_adjust_txtime_offset(struct igc_adapter *adapter); +bool igc_tsn_is_taprio_activated_by_user(struct igc_adapter *adapter); #endif /* _IGC_BASE_H */ diff --git a/drivers/net/ethernet/jme.c b/drivers/net/ethernet/jme.c index b06e245629739f..d8be0e4dcb072b 100644 --- a/drivers/net/ethernet/jme.c +++ b/drivers/net/ethernet/jme.c @@ -946,15 +946,13 @@ jme_udpsum(struct sk_buff *skb) if (skb->protocol != htons(ETH_P_IP)) return csum; skb_set_network_header(skb, ETH_HLEN); - if ((ip_hdr(skb)->protocol != IPPROTO_UDP) || - (skb->len < (ETH_HLEN + - (ip_hdr(skb)->ihl << 2) + - sizeof(struct udphdr)))) { + + if (ip_hdr(skb)->protocol != IPPROTO_UDP || + skb->len < (ETH_HLEN + ip_hdrlen(skb) + sizeof(struct udphdr))) { skb_reset_network_header(skb); return csum; } - skb_set_transport_header(skb, - ETH_HLEN + (ip_hdr(skb)->ihl << 2)); + skb_set_transport_header(skb, ETH_HLEN + ip_hdrlen(skb)); csum = udp_hdr(skb)->check; skb_reset_transport_header(skb); skb_reset_network_header(skb); diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c index 8c45ad983abc0c..0d62a33afa80ca 100644 --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c @@ -953,13 +953,13 @@ static void mvpp2_bm_pool_update_fc(struct mvpp2_port *port, static void mvpp2_bm_pool_update_priv_fc(struct mvpp2 *priv, bool en) { struct mvpp2_port *port; - int i; + int i, j; for (i = 0; i < priv->port_count; i++) { port = priv->port_list[i]; if (port->priv->percpu_pools) { - for (i = 0; i < port->nrxqs; i++) - mvpp2_bm_pool_update_fc(port, &port->priv->bm_pools[i], + for (j = 0; j < port->nrxqs; j++) + mvpp2_bm_pool_update_fc(port, &port->priv->bm_pools[j], port->tx_fc & en); } else { mvpp2_bm_pool_update_fc(port, port->pool_long, port->tx_fc & en); diff --git a/drivers/net/ethernet/mediatek/mtk_wed.c b/drivers/net/ethernet/mediatek/mtk_wed.c index 61334a71058c75..e212a4ba92751f 100644 --- a/drivers/net/ethernet/mediatek/mtk_wed.c +++ b/drivers/net/ethernet/mediatek/mtk_wed.c @@ -2666,14 +2666,15 @@ mtk_wed_setup_tc_block_cb(enum tc_setup_type type, void *type_data, void *cb_pri { struct mtk_wed_flow_block_priv *priv = cb_priv; struct flow_cls_offload *cls = type_data; - struct mtk_wed_hw *hw = priv->hw; + struct mtk_wed_hw *hw = NULL; - if (!tc_can_offload(priv->dev)) + if (!priv || !tc_can_offload(priv->dev)) return -EOPNOTSUPP; if (type != TC_SETUP_CLSFLOWER) return -EOPNOTSUPP; + hw = priv->hw; return mtk_flow_offload_cmd(hw->eth, cls, hw->index); } @@ -2729,6 +2730,7 @@ mtk_wed_setup_tc_block(struct mtk_wed_hw *hw, struct net_device *dev, flow_block_cb_remove(block_cb, f); list_del(&block_cb->driver_list); kfree(block_cb->cb_priv); + block_cb->cb_priv = NULL; } return 0; default: diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h index 5fd82c67b6ab7f..bb5da42edc23a0 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h @@ -130,7 +130,7 @@ struct page_pool; #define MLX5E_PARAMS_MINIMUM_LOG_RQ_SIZE_MPW 0x2 #define MLX5E_DEFAULT_LRO_TIMEOUT 32 -#define MLX5E_LRO_TIMEOUT_ARR_SIZE 4 +#define MLX5E_DEFAULT_SHAMPO_TIMEOUT 1024 #define MLX5E_PARAMS_DEFAULT_RX_CQ_MODERATION_USEC 0x10 #define MLX5E_PARAMS_DEFAULT_RX_CQ_MODERATION_USEC_FROM_CQE 0x3 diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/params.c b/drivers/net/ethernet/mellanox/mlx5/core/en/params.c index 6c9ccccca81e27..64b62ed17b07a7 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/params.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/params.c @@ -928,7 +928,7 @@ int mlx5e_build_rq_param(struct mlx5_core_dev *mdev, MLX5_SET(wq, wq, log_headers_entry_size, mlx5e_shampo_get_log_hd_entry_size(mdev, params)); MLX5_SET(rqc, rqc, reservation_timeout, - params->packet_merge.timeout); + mlx5e_choose_lro_timeout(mdev, MLX5E_DEFAULT_SHAMPO_TIMEOUT)); MLX5_SET(rqc, rqc, shampo_match_criteria_type, params->packet_merge.shampo.match_criteria_type); MLX5_SET(rqc, rqc, shampo_no_match_alignment_granularity, @@ -1087,6 +1087,20 @@ static u32 mlx5e_shampo_icosq_sz(struct mlx5_core_dev *mdev, return wqebbs; } +#define MLX5E_LRO_TIMEOUT_ARR_SIZE 4 + +u32 mlx5e_choose_lro_timeout(struct mlx5_core_dev *mdev, u32 wanted_timeout) +{ + int i; + + /* The supported periods are organized in ascending order */ + for (i = 0; i < MLX5E_LRO_TIMEOUT_ARR_SIZE - 1; i++) + if (MLX5_CAP_ETH(mdev, lro_timer_supported_periods[i]) >= wanted_timeout) + break; + + return MLX5_CAP_ETH(mdev, lro_timer_supported_periods[i]); +} + static u32 mlx5e_mpwrq_total_umr_wqebbs(struct mlx5_core_dev *mdev, struct mlx5e_params *params, struct mlx5e_xsk_param *xsk) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/params.h b/drivers/net/ethernet/mellanox/mlx5/core/en/params.h index 749b2ec0436eea..3f8986f9d86291 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/params.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/params.h @@ -108,6 +108,7 @@ u32 mlx5e_shampo_hd_per_wqe(struct mlx5_core_dev *mdev, u32 mlx5e_shampo_hd_per_wq(struct mlx5_core_dev *mdev, struct mlx5e_params *params, struct mlx5e_rq_param *rq_param); +u32 mlx5e_choose_lro_timeout(struct mlx5_core_dev *mdev, u32 wanted_timeout); u8 mlx5e_mpwqe_get_log_stride_size(struct mlx5_core_dev *mdev, struct mlx5e_params *params, struct mlx5e_xsk_param *xsk); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c index 22918b2ef7f128..09433b91be176f 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c @@ -146,7 +146,9 @@ static int mlx5e_tx_reporter_timeout_recover(void *ctx) return err; } + mutex_lock(&priv->state_lock); err = mlx5e_safe_reopen_channels(priv); + mutex_unlock(&priv->state_lock); if (!err) { to_ctx->status = 1; /* all channels recovered */ return err; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c index 8cf8ba2622f2bf..71a168746ebe21 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c @@ -932,6 +932,7 @@ mlx5_tc_ct_entry_replace_rule(struct mlx5_tc_ct_priv *ct_priv, mlx5_tc_ct_entry_destroy_mod_hdr(ct_priv, zone_rule->attr, mh); mlx5_put_label_mapping(ct_priv, attr->ct_attr.ct_labels_id); err_mod_hdr: + *attr = *old_attr; kfree(old_attr); err_attr: kvfree(spec); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_offload.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_offload.c index 6e00afe4671b78..797db853de3638 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_offload.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_offload.c @@ -51,9 +51,10 @@ u32 mlx5_ipsec_device_caps(struct mlx5_core_dev *mdev) MLX5_CAP_FLOWTABLE_NIC_RX(mdev, decap)) caps |= MLX5_IPSEC_CAP_PACKET_OFFLOAD; - if ((MLX5_CAP_FLOWTABLE_NIC_TX(mdev, ignore_flow_level) && - MLX5_CAP_FLOWTABLE_NIC_RX(mdev, ignore_flow_level)) || - MLX5_CAP_ESW_FLOWTABLE_FDB(mdev, ignore_flow_level)) + if (IS_ENABLED(CONFIG_MLX5_CLS_ACT) && + ((MLX5_CAP_FLOWTABLE_NIC_TX(mdev, ignore_flow_level) && + MLX5_CAP_FLOWTABLE_NIC_RX(mdev, ignore_flow_level)) || + MLX5_CAP_ESW_FLOWTABLE_FDB(mdev, ignore_flow_level))) caps |= MLX5_IPSEC_CAP_PRIO; if (MLX5_CAP_FLOWTABLE_NIC_TX(mdev, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c index 00d5661dc62e1a..36845872ae94e7 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c @@ -1409,7 +1409,12 @@ static int mlx5e_ethtool_set_link_ksettings(struct mlx5e_priv *priv, if (!an_changes && link_modes == eproto.admin) goto out; - mlx5_port_set_eth_ptys(mdev, an_disable, link_modes, ext); + err = mlx5_port_set_eth_ptys(mdev, an_disable, link_modes, ext); + if (err) { + netdev_err(priv->netdev, "%s: failed to set ptys reg: %d\n", __func__, err); + goto out; + } + mlx5_toggle_port_link(mdev); out: diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c index 3eccdadc035781..773624bb2c5d54 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c @@ -734,7 +734,7 @@ mlx5e_ethtool_flow_replace(struct mlx5e_priv *priv, if (num_tuples <= 0) { netdev_warn(priv->netdev, "%s: flow is not valid %d\n", __func__, num_tuples); - return num_tuples; + return num_tuples < 0 ? num_tuples : -EINVAL; } eth_ft = get_flow_table(priv, fs, num_tuples); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index 6f686fabed4462..5df904639b0ce6 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -5167,18 +5167,6 @@ const struct net_device_ops mlx5e_netdev_ops = { #endif }; -static u32 mlx5e_choose_lro_timeout(struct mlx5_core_dev *mdev, u32 wanted_timeout) -{ - int i; - - /* The supported periods are organized in ascending order */ - for (i = 0; i < MLX5E_LRO_TIMEOUT_ARR_SIZE - 1; i++) - if (MLX5_CAP_ETH(mdev, lro_timer_supported_periods[i]) >= wanted_timeout) - break; - - return MLX5_CAP_ETH(mdev, lro_timer_supported_periods[i]); -} - void mlx5e_build_nic_params(struct mlx5e_priv *priv, struct mlx5e_xsk *xsk, u16 mtu) { struct mlx5e_params *params = &priv->channels.params; @@ -5308,7 +5296,7 @@ static void mlx5e_get_queue_stats_rx(struct net_device *dev, int i, struct mlx5e_rq_stats *rq_stats; ASSERT_RTNL(); - if (mlx5e_is_uplink_rep(priv)) + if (mlx5e_is_uplink_rep(priv) || !priv->stats_nch) return; channel_stats = priv->channel_stats[i]; @@ -5328,6 +5316,9 @@ static void mlx5e_get_queue_stats_tx(struct net_device *dev, int i, struct mlx5e_sq_stats *sq_stats; ASSERT_RTNL(); + if (!priv->stats_nch) + return; + /* no special case needed for ptp htb etc since txq2sq_stats is kept up * to date for active sq_stats, otherwise get_base_stats takes care of * inactive sqs. diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c index 979c49ae6b5cc9..b43ca0b762c306 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c @@ -207,6 +207,7 @@ int mlx5_fw_reset_set_live_patch(struct mlx5_core_dev *dev) static void mlx5_fw_reset_complete_reload(struct mlx5_core_dev *dev, bool unloaded) { struct mlx5_fw_reset *fw_reset = dev->priv.fw_reset; + struct devlink *devlink = priv_to_devlink(dev); /* if this is the driver that initiated the fw reset, devlink completed the reload */ if (test_bit(MLX5_FW_RESET_FLAGS_PENDING_COMP, &fw_reset->reset_flags)) { @@ -218,9 +219,11 @@ static void mlx5_fw_reset_complete_reload(struct mlx5_core_dev *dev, bool unload mlx5_core_err(dev, "reset reload flow aborted, PCI reads still not working\n"); else mlx5_load_one(dev, true); - devlink_remote_reload_actions_performed(priv_to_devlink(dev), 0, + devl_lock(devlink); + devlink_remote_reload_actions_performed(devlink, 0, BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT) | BIT(DEVLINK_RELOAD_ACTION_FW_ACTIVATE)); + devl_unlock(devlink); } } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/irq_affinity.c b/drivers/net/ethernet/mellanox/mlx5/core/irq_affinity.c index f7b01b3f0cba36..1477db7f5307e0 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/irq_affinity.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/irq_affinity.c @@ -48,6 +48,7 @@ static struct mlx5_irq * irq_pool_request_irq(struct mlx5_irq_pool *pool, struct irq_affinity_desc *af_desc) { struct irq_affinity_desc auto_desc = {}; + struct mlx5_irq *irq; u32 irq_index; int err; @@ -64,9 +65,12 @@ irq_pool_request_irq(struct mlx5_irq_pool *pool, struct irq_affinity_desc *af_de else cpu_get(pool, cpumask_first(&af_desc->mask)); } - return mlx5_irq_alloc(pool, irq_index, - cpumask_empty(&auto_desc.mask) ? af_desc : &auto_desc, - NULL); + irq = mlx5_irq_alloc(pool, irq_index, + cpumask_empty(&auto_desc.mask) ? af_desc : &auto_desc, + NULL); + if (IS_ERR(irq)) + xa_erase(&pool->irqs, irq_index); + return irq; } /* Looking for the IRQ with the smallest refcount that fits req_mask. diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c index d0871c46b8c543..cf8045b926892e 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c @@ -1538,7 +1538,7 @@ u8 mlx5_lag_get_slave_port(struct mlx5_core_dev *dev, goto unlock; for (i = 0; i < ldev->ports; i++) { - if (ldev->pf[MLX5_LAG_P1].netdev == slave) { + if (ldev->pf[i].netdev == slave) { port = i; break; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/sd.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/sd.c index f6deb5a3f82024..eeb0b7ea05f126 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lib/sd.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/sd.c @@ -126,7 +126,7 @@ static bool mlx5_sd_is_supported(struct mlx5_core_dev *dev, u8 host_buses) } static int mlx5_query_sd(struct mlx5_core_dev *dev, bool *sdm, - u8 *host_buses, u8 *sd_group) + u8 *host_buses) { u32 out[MLX5_ST_SZ_DW(mpir_reg)]; int err; @@ -135,10 +135,6 @@ static int mlx5_query_sd(struct mlx5_core_dev *dev, bool *sdm, if (err) return err; - err = mlx5_query_nic_vport_sd_group(dev, sd_group); - if (err) - return err; - *sdm = MLX5_GET(mpir_reg, out, sdm); *host_buses = MLX5_GET(mpir_reg, out, host_buses); @@ -166,19 +162,23 @@ static int sd_init(struct mlx5_core_dev *dev) if (mlx5_core_is_ecpf(dev)) return 0; + err = mlx5_query_nic_vport_sd_group(dev, &sd_group); + if (err) + return err; + + if (!sd_group) + return 0; + if (!MLX5_CAP_MCAM_REG(dev, mpir)) return 0; - err = mlx5_query_sd(dev, &sdm, &host_buses, &sd_group); + err = mlx5_query_sd(dev, &sdm, &host_buses); if (err) return err; if (!sdm) return 0; - if (!sd_group) - return 0; - group_id = mlx5_sd_group_id(dev, sd_group); if (!mlx5_sd_is_supported(dev, host_buses)) { diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c index 527da58c79535b..5b7e6f4b5c7ea1 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c @@ -2142,7 +2142,6 @@ static int mlx5_try_fast_unload(struct mlx5_core_dev *dev) /* Panic tear down fw command will stop the PCI bus communication * with the HCA, so the health poll is no longer needed. */ - mlx5_drain_health_wq(dev); mlx5_stop_health_poll(dev, false); ret = mlx5_cmd_fast_teardown_hca(dev); @@ -2177,6 +2176,7 @@ static void shutdown(struct pci_dev *pdev) mlx5_core_info(dev, "Shutdown was called\n"); set_bit(MLX5_BREAK_FW_WAIT, &dev->intf_state); + mlx5_drain_health_wq(dev); err = mlx5_try_fast_unload(dev); if (err) mlx5_unload_one(dev, false); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c b/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c index b2986175d9afe8..b706f1486504a7 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c @@ -112,6 +112,7 @@ static void mlx5_sf_dev_shutdown(struct auxiliary_device *adev) struct mlx5_core_dev *mdev = sf_dev->mdev; set_bit(MLX5_BREAK_FW_WAIT, &mdev->intf_state); + mlx5_drain_health_wq(mdev); mlx5_unload_one(mdev, false); } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_rule.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_rule.c index 042ca034912433..d1db04baa1fa6f 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_rule.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_rule.c @@ -7,7 +7,7 @@ /* don't try to optimize STE allocation if the stack is too constaraining */ #define DR_RULE_MAX_STES_OPTIMIZED 0 #else -#define DR_RULE_MAX_STES_OPTIMIZED 5 +#define DR_RULE_MAX_STES_OPTIMIZED 2 #endif #define DR_RULE_MAX_STE_CHAIN_OPTIMIZED (DR_RULE_MAX_STES_OPTIMIZED + DR_ACTION_MAX_STES) diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige.h b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige.h index bc94e75a7aebd1..e7777700ee18a7 100644 --- a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige.h +++ b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige.h @@ -40,6 +40,7 @@ */ #define MLXBF_GIGE_BCAST_MAC_FILTER_IDX 0 #define MLXBF_GIGE_LOCAL_MAC_FILTER_IDX 1 +#define MLXBF_GIGE_MAX_FILTER_IDX 3 /* Define for broadcast MAC literal */ #define BCAST_MAC_ADDR 0xFFFFFFFFFFFF @@ -175,6 +176,13 @@ enum mlxbf_gige_res { int mlxbf_gige_mdio_probe(struct platform_device *pdev, struct mlxbf_gige *priv); void mlxbf_gige_mdio_remove(struct mlxbf_gige *priv); + +void mlxbf_gige_enable_multicast_rx(struct mlxbf_gige *priv); +void mlxbf_gige_disable_multicast_rx(struct mlxbf_gige *priv); +void mlxbf_gige_enable_mac_rx_filter(struct mlxbf_gige *priv, + unsigned int index); +void mlxbf_gige_disable_mac_rx_filter(struct mlxbf_gige *priv, + unsigned int index); void mlxbf_gige_set_mac_rx_filter(struct mlxbf_gige *priv, unsigned int index, u64 dmac); void mlxbf_gige_get_mac_rx_filter(struct mlxbf_gige *priv, diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c index b157f0f1c5a886..385a56ac73481a 100644 --- a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c +++ b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c @@ -168,6 +168,10 @@ static int mlxbf_gige_open(struct net_device *netdev) if (err) goto napi_deinit; + mlxbf_gige_enable_mac_rx_filter(priv, MLXBF_GIGE_BCAST_MAC_FILTER_IDX); + mlxbf_gige_enable_mac_rx_filter(priv, MLXBF_GIGE_LOCAL_MAC_FILTER_IDX); + mlxbf_gige_enable_multicast_rx(priv); + /* Set bits in INT_EN that we care about */ int_en = MLXBF_GIGE_INT_EN_HW_ACCESS_ERROR | MLXBF_GIGE_INT_EN_TX_CHECKSUM_INPUTS | @@ -379,6 +383,7 @@ static int mlxbf_gige_probe(struct platform_device *pdev) void __iomem *plu_base; void __iomem *base; int addr, phy_irq; + unsigned int i; int err; base = devm_platform_ioremap_resource(pdev, MLXBF_GIGE_RES_MAC); @@ -423,6 +428,11 @@ static int mlxbf_gige_probe(struct platform_device *pdev) priv->rx_q_entries = MLXBF_GIGE_DEFAULT_RXQ_SZ; priv->tx_q_entries = MLXBF_GIGE_DEFAULT_TXQ_SZ; + for (i = 0; i <= MLXBF_GIGE_MAX_FILTER_IDX; i++) + mlxbf_gige_disable_mac_rx_filter(priv, i); + mlxbf_gige_disable_multicast_rx(priv); + mlxbf_gige_disable_promisc(priv); + /* Write initial MAC address to hardware */ mlxbf_gige_initial_mac(priv); diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_regs.h b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_regs.h index 98a8681c21b9ca..4d14cb13fd64e1 100644 --- a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_regs.h +++ b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_regs.h @@ -62,6 +62,8 @@ #define MLXBF_GIGE_TX_STATUS_DATA_FIFO_FULL BIT(1) #define MLXBF_GIGE_RX_MAC_FILTER_DMAC_RANGE_START 0x0520 #define MLXBF_GIGE_RX_MAC_FILTER_DMAC_RANGE_END 0x0528 +#define MLXBF_GIGE_RX_MAC_FILTER_GENERAL 0x0530 +#define MLXBF_GIGE_RX_MAC_FILTER_EN_MULTICAST BIT(1) #define MLXBF_GIGE_RX_MAC_FILTER_COUNT_DISC 0x0540 #define MLXBF_GIGE_RX_MAC_FILTER_COUNT_DISC_EN BIT(0) #define MLXBF_GIGE_RX_MAC_FILTER_COUNT_PASS 0x0548 diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_rx.c b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_rx.c index 69998435849348..eb62620b63c7fc 100644 --- a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_rx.c +++ b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_rx.c @@ -11,15 +11,31 @@ #include "mlxbf_gige.h" #include "mlxbf_gige_regs.h" -void mlxbf_gige_set_mac_rx_filter(struct mlxbf_gige *priv, - unsigned int index, u64 dmac) +void mlxbf_gige_enable_multicast_rx(struct mlxbf_gige *priv) { void __iomem *base = priv->base; - u64 control; + u64 data; - /* Write destination MAC to specified MAC RX filter */ - writeq(dmac, base + MLXBF_GIGE_RX_MAC_FILTER + - (index * MLXBF_GIGE_RX_MAC_FILTER_STRIDE)); + data = readq(base + MLXBF_GIGE_RX_MAC_FILTER_GENERAL); + data |= MLXBF_GIGE_RX_MAC_FILTER_EN_MULTICAST; + writeq(data, base + MLXBF_GIGE_RX_MAC_FILTER_GENERAL); +} + +void mlxbf_gige_disable_multicast_rx(struct mlxbf_gige *priv) +{ + void __iomem *base = priv->base; + u64 data; + + data = readq(base + MLXBF_GIGE_RX_MAC_FILTER_GENERAL); + data &= ~MLXBF_GIGE_RX_MAC_FILTER_EN_MULTICAST; + writeq(data, base + MLXBF_GIGE_RX_MAC_FILTER_GENERAL); +} + +void mlxbf_gige_enable_mac_rx_filter(struct mlxbf_gige *priv, + unsigned int index) +{ + void __iomem *base = priv->base; + u64 control; /* Enable MAC receive filter mask for specified index */ control = readq(base + MLXBF_GIGE_CONTROL); @@ -27,6 +43,28 @@ void mlxbf_gige_set_mac_rx_filter(struct mlxbf_gige *priv, writeq(control, base + MLXBF_GIGE_CONTROL); } +void mlxbf_gige_disable_mac_rx_filter(struct mlxbf_gige *priv, + unsigned int index) +{ + void __iomem *base = priv->base; + u64 control; + + /* Disable MAC receive filter mask for specified index */ + control = readq(base + MLXBF_GIGE_CONTROL); + control &= ~(MLXBF_GIGE_CONTROL_EN_SPECIFIC_MAC << index); + writeq(control, base + MLXBF_GIGE_CONTROL); +} + +void mlxbf_gige_set_mac_rx_filter(struct mlxbf_gige *priv, + unsigned int index, u64 dmac) +{ + void __iomem *base = priv->base; + + /* Write destination MAC to specified MAC RX filter */ + writeq(dmac, base + MLXBF_GIGE_RX_MAC_FILTER + + (index * MLXBF_GIGE_RX_MAC_FILTER_STRIDE)); +} + void mlxbf_gige_get_mac_rx_filter(struct mlxbf_gige *priv, unsigned int index, u64 *dmac) { diff --git a/drivers/net/ethernet/meta/Kconfig b/drivers/net/ethernet/meta/Kconfig index 86034ea4ba5b61..c002ede3640202 100644 --- a/drivers/net/ethernet/meta/Kconfig +++ b/drivers/net/ethernet/meta/Kconfig @@ -20,7 +20,7 @@ if NET_VENDOR_META config FBNIC tristate "Meta Platforms Host Network Interface" depends on X86_64 || COMPILE_TEST - depends on S390=n + depends on !S390 depends on MAX_SKB_FRAGS < 22 depends on PCI_MSI select PHYLINK diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c index d2f07e179e86ba..39f56973746d7f 100644 --- a/drivers/net/ethernet/microsoft/mana/mana_en.c +++ b/drivers/net/ethernet/microsoft/mana/mana_en.c @@ -599,7 +599,11 @@ static void mana_get_rxbuf_cfg(int mtu, u32 *datasize, u32 *alloc_size, else *headroom = XDP_PACKET_HEADROOM; - *alloc_size = mtu + MANA_RXBUF_PAD + *headroom; + *alloc_size = SKB_DATA_ALIGN(mtu + MANA_RXBUF_PAD + *headroom); + + /* Using page pool in this case, so alloc_size is PAGE_SIZE */ + if (*alloc_size < PAGE_SIZE) + *alloc_size = PAGE_SIZE; *datasize = mtu + ETH_HLEN; } @@ -1788,7 +1792,6 @@ static void mana_poll_rx_cq(struct mana_cq *cq) static int mana_cq_handler(void *context, struct gdma_queue *gdma_queue) { struct mana_cq *cq = context; - u8 arm_bit; int w; WARN_ON_ONCE(cq->gdma_cq != gdma_queue); @@ -1799,16 +1802,23 @@ static int mana_cq_handler(void *context, struct gdma_queue *gdma_queue) mana_poll_tx_cq(cq); w = cq->work_done; - - if (w < cq->budget && - napi_complete_done(&cq->napi, w)) { - arm_bit = SET_ARM_BIT; - } else { - arm_bit = 0; + cq->work_done_since_doorbell += w; + + if (w < cq->budget) { + mana_gd_ring_cq(gdma_queue, SET_ARM_BIT); + cq->work_done_since_doorbell = 0; + napi_complete_done(&cq->napi, w); + } else if (cq->work_done_since_doorbell > + cq->gdma_cq->queue_size / COMP_ENTRY_SIZE * 4) { + /* MANA hardware requires at least one doorbell ring every 8 + * wraparounds of CQ even if there is no need to arm the CQ. + * This driver rings the doorbell as soon as we have exceeded + * 4 wraparounds. + */ + mana_gd_ring_cq(gdma_queue, 0); + cq->work_done_since_doorbell = 0; } - mana_gd_ring_cq(gdma_queue, arm_bit); - return w; } diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c index 714d2e80469404..3507c2e28110d2 100644 --- a/drivers/net/ethernet/realtek/r8169_main.c +++ b/drivers/net/ethernet/realtek/r8169_main.c @@ -4349,7 +4349,8 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb, if (unlikely(!rtl_tx_slots_avail(tp))) { if (net_ratelimit()) netdev_err(dev, "BUG! Tx Ring full when queue awake!\n"); - goto err_stop_0; + netif_stop_queue(dev); + return NETDEV_TX_BUSY; } opts[1] = rtl8169_tx_vlan_tag(skb); @@ -4405,11 +4406,6 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb, dev_kfree_skb_any(skb); dev->stats.tx_dropped++; return NETDEV_TX_OK; - -err_stop_0: - netif_stop_queue(dev); - dev->stats.tx_dropped++; - return NETDEV_TX_BUSY; } static unsigned int rtl_last_frag_len(struct sk_buff *skb) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4.h b/drivers/net/ethernet/stmicro/stmmac/dwmac4.h index d3c5306f1c41f7..93a78fd0737b6c 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4.h +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4.h @@ -573,8 +573,6 @@ static inline u32 mtl_low_credx_base_addr(const struct dwmac4_addrs *addrs, #define GMAC_PHYIF_CTRLSTATUS_LNKSTS BIT(19) #define GMAC_PHYIF_CTRLSTATUS_JABTO BIT(20) #define GMAC_PHYIF_CTRLSTATUS_FALSECARDET BIT(21) -/* LNKMOD */ -#define GMAC_PHYIF_CTRLSTATUS_LNKMOD_MASK 0x1 /* LNKSPEED */ #define GMAC_PHYIF_CTRLSTATUS_SPEED_125 0x2 #define GMAC_PHYIF_CTRLSTATUS_SPEED_25 0x1 diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c index f98741d2607ec4..31c387cc5f269d 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c @@ -786,7 +786,7 @@ static void dwmac4_phystatus(void __iomem *ioaddr, struct stmmac_extra_stats *x) else x->pcs_speed = SPEED_10; - x->pcs_duplex = (status & GMAC_PHYIF_CTRLSTATUS_LNKMOD_MASK); + x->pcs_duplex = (status & GMAC_PHYIF_CTRLSTATUS_LNKMOD); pr_info("Link is Up - %d/%s\n", (int)x->pcs_speed, x->pcs_duplex ? "Full" : "Half"); diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet.h b/drivers/net/ethernet/xilinx/xilinx_axienet.h index fa5500decc9602..c7d9221fafdcb1 100644 --- a/drivers/net/ethernet/xilinx/xilinx_axienet.h +++ b/drivers/net/ethernet/xilinx/xilinx_axienet.h @@ -160,16 +160,16 @@ #define XAE_RCW1_OFFSET 0x00000404 /* Rx Configuration Word 1 */ #define XAE_TC_OFFSET 0x00000408 /* Tx Configuration */ #define XAE_FCC_OFFSET 0x0000040C /* Flow Control Configuration */ -#define XAE_EMMC_OFFSET 0x00000410 /* EMAC mode configuration */ -#define XAE_PHYC_OFFSET 0x00000414 /* RGMII/SGMII configuration */ +#define XAE_EMMC_OFFSET 0x00000410 /* MAC speed configuration */ +#define XAE_PHYC_OFFSET 0x00000414 /* RX Max Frame Configuration */ #define XAE_ID_OFFSET 0x000004F8 /* Identification register */ -#define XAE_MDIO_MC_OFFSET 0x00000500 /* MII Management Config */ -#define XAE_MDIO_MCR_OFFSET 0x00000504 /* MII Management Control */ -#define XAE_MDIO_MWD_OFFSET 0x00000508 /* MII Management Write Data */ -#define XAE_MDIO_MRD_OFFSET 0x0000050C /* MII Management Read Data */ +#define XAE_MDIO_MC_OFFSET 0x00000500 /* MDIO Setup */ +#define XAE_MDIO_MCR_OFFSET 0x00000504 /* MDIO Control */ +#define XAE_MDIO_MWD_OFFSET 0x00000508 /* MDIO Write Data */ +#define XAE_MDIO_MRD_OFFSET 0x0000050C /* MDIO Read Data */ #define XAE_UAW0_OFFSET 0x00000700 /* Unicast address word 0 */ #define XAE_UAW1_OFFSET 0x00000704 /* Unicast address word 1 */ -#define XAE_FMI_OFFSET 0x00000708 /* Filter Mask Index */ +#define XAE_FMI_OFFSET 0x00000708 /* Frame Filter Control */ #define XAE_AF0_OFFSET 0x00000710 /* Address Filter 0 */ #define XAE_AF1_OFFSET 0x00000714 /* Address Filter 1 */ @@ -308,7 +308,7 @@ */ #define XAE_UAW1_UNICASTADDR_MASK 0x0000FFFF -/* Bit masks for Axi Ethernet FMI register */ +/* Bit masks for Axi Ethernet FMC register */ #define XAE_FMI_PM_MASK 0x80000000 /* Promis. mode enable */ #define XAE_FMI_IND_MASK 0x00000003 /* Index Mask */ diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c index e342f387c3dd64..02fdf66e07faa3 100644 --- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c @@ -2219,9 +2219,9 @@ static void axienet_dma_err_handler(struct work_struct *work) ~(XAE_OPTION_TXEN | XAE_OPTION_RXEN)); axienet_set_mac_address(ndev, NULL); axienet_set_multicast_list(ndev); - axienet_setoptions(ndev, lp->options); napi_enable(&lp->napi_rx); napi_enable(&lp->napi_tx); + axienet_setoptions(ndev, lp->options); } /** diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c index b3ddc9a629d9d9..fad5b65644645d 100644 --- a/drivers/net/fjes/fjes_main.c +++ b/drivers/net/fjes/fjes_main.c @@ -14,9 +14,7 @@ #include "fjes.h" #include "fjes_trace.h" -#define MAJ 1 -#define MIN 2 -#define DRV_VERSION __stringify(MAJ) "." __stringify(MIN) +#define DRV_VERSION "1.2" #define DRV_NAME "fjes" char fjes_driver_name[] = DRV_NAME; char fjes_driver_version[] = DRV_VERSION; diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c index 427b91aca50d3a..0696faf60013e0 100644 --- a/drivers/net/gtp.c +++ b/drivers/net/gtp.c @@ -1269,6 +1269,9 @@ static netdev_tx_t gtp_dev_xmit(struct sk_buff *skb, struct net_device *dev) if (skb_cow_head(skb, dev->needed_headroom)) goto tx_err; + if (!pskb_inet_may_pull(skb)) + goto tx_err; + skb_reset_inner_headers(skb); /* PDP context lookups in gtp_build_skb_*() need rcu read-side lock. */ diff --git a/drivers/net/phy/aquantia/aquantia_main.c b/drivers/net/phy/aquantia/aquantia_main.c index d12e353742318e..e982e9ce44a596 100644 --- a/drivers/net/phy/aquantia/aquantia_main.c +++ b/drivers/net/phy/aquantia/aquantia_main.c @@ -653,13 +653,7 @@ static int aqr107_fill_interface_modes(struct phy_device *phydev) unsigned long *possible = phydev->possible_interfaces; unsigned int serdes_mode, rate_adapt; phy_interface_t interface; - int i, val, ret; - - ret = phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND1, - VEND1_GLOBAL_CFG_10M, val, val != 0, - 1000, 100000, false); - if (ret) - return ret; + int i, val; /* Walk the media-speed configuration registers to determine which * host-side serdes modes may be used by the PHY depending on the @@ -708,6 +702,25 @@ static int aqr107_fill_interface_modes(struct phy_device *phydev) return 0; } +static int aqr113c_fill_interface_modes(struct phy_device *phydev) +{ + int val, ret; + + /* It's been observed on some models that - when coming out of suspend + * - the FW signals that the PHY is ready but the GLOBAL_CFG registers + * continue on returning zeroes for some time. Let's poll the 100M + * register until it returns a real value as both 113c and 115c support + * this mode. + */ + ret = phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND1, + VEND1_GLOBAL_CFG_100M, val, val != 0, + 1000, 100000, false); + if (ret) + return ret; + + return aqr107_fill_interface_modes(phydev); +} + static int aqr113c_config_init(struct phy_device *phydev) { int ret; @@ -725,7 +738,7 @@ static int aqr113c_config_init(struct phy_device *phydev) if (ret) return ret; - return aqr107_fill_interface_modes(phydev); + return aqr113c_fill_interface_modes(phydev); } static int aqr107_probe(struct phy_device *phydev) diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c index dd519805deee31..65b0a3115e14cd 100644 --- a/drivers/net/phy/micrel.c +++ b/drivers/net/phy/micrel.c @@ -1389,6 +1389,8 @@ static int ksz9131_config_init(struct phy_device *phydev) const struct device *dev_walker; int ret; + phydev->mdix_ctrl = ETH_TP_MDI_AUTO; + dev_walker = &phydev->mdio.dev; do { of_node = dev_walker->of_node; @@ -1438,28 +1440,30 @@ static int ksz9131_config_init(struct phy_device *phydev) #define MII_KSZ9131_AUTO_MDIX 0x1C #define MII_KSZ9131_AUTO_MDI_SET BIT(7) #define MII_KSZ9131_AUTO_MDIX_SWAP_OFF BIT(6) +#define MII_KSZ9131_DIG_AXAN_STS 0x14 +#define MII_KSZ9131_DIG_AXAN_STS_LINK_DET BIT(14) +#define MII_KSZ9131_DIG_AXAN_STS_A_SELECT BIT(12) static int ksz9131_mdix_update(struct phy_device *phydev) { int ret; - ret = phy_read(phydev, MII_KSZ9131_AUTO_MDIX); - if (ret < 0) - return ret; - - if (ret & MII_KSZ9131_AUTO_MDIX_SWAP_OFF) { - if (ret & MII_KSZ9131_AUTO_MDI_SET) - phydev->mdix_ctrl = ETH_TP_MDI; - else - phydev->mdix_ctrl = ETH_TP_MDI_X; + if (phydev->mdix_ctrl != ETH_TP_MDI_AUTO) { + phydev->mdix = phydev->mdix_ctrl; } else { - phydev->mdix_ctrl = ETH_TP_MDI_AUTO; - } + ret = phy_read(phydev, MII_KSZ9131_DIG_AXAN_STS); + if (ret < 0) + return ret; - if (ret & MII_KSZ9131_AUTO_MDI_SET) - phydev->mdix = ETH_TP_MDI; - else - phydev->mdix = ETH_TP_MDI_X; + if (ret & MII_KSZ9131_DIG_AXAN_STS_LINK_DET) { + if (ret & MII_KSZ9131_DIG_AXAN_STS_A_SELECT) + phydev->mdix = ETH_TP_MDI; + else + phydev->mdix = ETH_TP_MDI_X; + } else { + phydev->mdix = ETH_TP_MDI_INVALID; + } + } return 0; } diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c index bed839237fb55b..87865918dab6d0 100644 --- a/drivers/net/phy/realtek.c +++ b/drivers/net/phy/realtek.c @@ -1465,6 +1465,13 @@ static struct phy_driver realtek_drvs[] = { .handle_interrupt = genphy_handle_interrupt_no_ack, .suspend = genphy_suspend, .resume = genphy_resume, + }, { + PHY_ID_MATCH_EXACT(0x001cc960), + .name = "RTL8366S Gigabit Ethernet", + .suspend = genphy_suspend, + .resume = genphy_resume, + .read_mmd = genphy_read_mmd_unsupported, + .write_mmd = genphy_write_mmd_unsupported, }, }; diff --git a/drivers/net/phy/vitesse.c b/drivers/net/phy/vitesse.c index 897b979ec03c81..3b5fcaf0dd36db 100644 --- a/drivers/net/phy/vitesse.c +++ b/drivers/net/phy/vitesse.c @@ -237,16 +237,6 @@ static int vsc739x_config_init(struct phy_device *phydev) return 0; } -static int vsc73xx_config_aneg(struct phy_device *phydev) -{ - /* The VSC73xx switches does not like to be instructed to - * do autonegotiation in any way, it prefers that you just go - * with the power-on/reset defaults. Writing some registers will - * just make autonegotiation permanently fail. - */ - return 0; -} - /* This adds a skew for both TX and RX clocks, so the skew should only be * applied to "rgmii-id" interfaces. It may not work as expected * on "rgmii-txid", "rgmii-rxid" or "rgmii" interfaces. @@ -444,7 +434,6 @@ static struct phy_driver vsc82xx_driver[] = { .phy_id_mask = 0x000ffff0, /* PHY_GBIT_FEATURES */ .config_init = vsc738x_config_init, - .config_aneg = vsc73xx_config_aneg, .read_page = vsc73xx_read_page, .write_page = vsc73xx_write_page, }, { @@ -453,7 +442,6 @@ static struct phy_driver vsc82xx_driver[] = { .phy_id_mask = 0x000ffff0, /* PHY_GBIT_FEATURES */ .config_init = vsc738x_config_init, - .config_aneg = vsc73xx_config_aneg, .read_page = vsc73xx_read_page, .write_page = vsc73xx_write_page, }, { @@ -462,7 +450,6 @@ static struct phy_driver vsc82xx_driver[] = { .phy_id_mask = 0x000ffff0, /* PHY_GBIT_FEATURES */ .config_init = vsc739x_config_init, - .config_aneg = vsc73xx_config_aneg, .read_page = vsc73xx_read_page, .write_page = vsc73xx_write_page, }, { @@ -471,7 +458,6 @@ static struct phy_driver vsc82xx_driver[] = { .phy_id_mask = 0x000ffff0, /* PHY_GBIT_FEATURES */ .config_init = vsc739x_config_init, - .config_aneg = vsc73xx_config_aneg, .read_page = vsc73xx_read_page, .write_page = vsc73xx_write_page, }, { diff --git a/drivers/net/pse-pd/pse_core.c b/drivers/net/pse-pd/pse_core.c index ec20953e0f825c..4f032b16a8a0a6 100644 --- a/drivers/net/pse-pd/pse_core.c +++ b/drivers/net/pse-pd/pse_core.c @@ -401,9 +401,14 @@ devm_pse_pi_regulator_register(struct pse_controller_dev *pcdev, rdesc->ops = &pse_pi_ops; rdesc->owner = pcdev->owner; - rinit_data->constraints.valid_ops_mask = REGULATOR_CHANGE_STATUS | - REGULATOR_CHANGE_CURRENT; - rinit_data->constraints.max_uA = MAX_PI_CURRENT; + rinit_data->constraints.valid_ops_mask = REGULATOR_CHANGE_STATUS; + + if (pcdev->ops->pi_set_current_limit) { + rinit_data->constraints.valid_ops_mask |= + REGULATOR_CHANGE_CURRENT; + rinit_data->constraints.max_uA = MAX_PI_CURRENT; + } + rinit_data->supply_regulator = "vpwr"; rconfig.dev = pcdev->dev; diff --git a/drivers/net/pse-pd/tps23881.c b/drivers/net/pse-pd/tps23881.c index 61f6ad9c1934e1..2ea75686a31907 100644 --- a/drivers/net/pse-pd/tps23881.c +++ b/drivers/net/pse-pd/tps23881.c @@ -5,6 +5,7 @@ * Copyright (c) 2023 Bootlin, Kory Maincent */ +#include #include #include #include @@ -29,6 +30,8 @@ #define TPS23881_REG_TPON BIT(0) #define TPS23881_REG_FWREV 0x41 #define TPS23881_REG_DEVID 0x43 +#define TPS23881_REG_DEVID_MASK 0xF0 +#define TPS23881_DEVICE_ID 0x02 #define TPS23881_REG_SRAM_CTRL 0x60 #define TPS23881_REG_SRAM_DATA 0x61 @@ -750,7 +753,7 @@ static int tps23881_i2c_probe(struct i2c_client *client) if (ret < 0) return ret; - if (ret != 0x22) { + if (FIELD_GET(TPS23881_REG_DEVID_MASK, ret) != TPS23881_DEVICE_ID) { dev_err(dev, "Wrong device ID\n"); return -ENXIO; } diff --git a/drivers/net/usb/ipheth.c b/drivers/net/usb/ipheth.c index 687d70cfc55635..46afb95ffabe3b 100644 --- a/drivers/net/usb/ipheth.c +++ b/drivers/net/usb/ipheth.c @@ -286,10 +286,11 @@ static void ipheth_rcvbulk_callback(struct urb *urb) return; } - if (urb->actual_length <= IPHETH_IP_ALIGN) { - dev->net->stats.rx_length_errors++; - return; - } + /* iPhone may periodically send URBs with no payload + * on the "bulk in" endpoint. It is safe to ignore them. + */ + if (urb->actual_length == 0) + goto rx_submit; /* RX URBs starting with 0x00 0x01 do not encapsulate Ethernet frames, * but rather are control frames. Their purpose is not documented, and @@ -298,7 +299,8 @@ static void ipheth_rcvbulk_callback(struct urb *urb) * URB received from the bulk IN endpoint. */ if (unlikely - (((char *)urb->transfer_buffer)[0] == 0 && + (urb->actual_length == 4 && + ((char *)urb->transfer_buffer)[0] == 0 && ((char *)urb->transfer_buffer)[1] == 1)) goto rx_submit; @@ -306,7 +308,6 @@ static void ipheth_rcvbulk_callback(struct urb *urb) if (retval != 0) { dev_err(&dev->intf->dev, "%s: callback retval: %d\n", __func__, retval); - return; } rx_submit: @@ -354,13 +355,14 @@ static int ipheth_carrier_set(struct ipheth_device *dev) 0x02, /* index */ dev->ctrl_buf, IPHETH_CTRL_BUF_SIZE, IPHETH_CTRL_TIMEOUT); - if (retval < 0) { + if (retval <= 0) { dev_err(&dev->intf->dev, "%s: usb_control_msg: %d\n", __func__, retval); return retval; } - if (dev->ctrl_buf[0] == IPHETH_CARRIER_ON) { + if ((retval == 1 && dev->ctrl_buf[0] == IPHETH_CARRIER_ON) || + (retval >= 2 && dev->ctrl_buf[1] == IPHETH_CARRIER_ON)) { netif_carrier_on(dev->net); if (dev->tx_urb->status != -EINPROGRESS) netif_wake_queue(dev->net); @@ -475,8 +477,8 @@ static int ipheth_close(struct net_device *net) { struct ipheth_device *dev = netdev_priv(net); - cancel_delayed_work_sync(&dev->carrier_work); netif_stop_queue(net); + cancel_delayed_work_sync(&dev->carrier_work); return 0; } diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index 386d62769dedb1..4823dbdf54656f 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -201,6 +201,7 @@ static int qmimux_rx_fixup(struct usbnet *dev, struct sk_buff *skb) break; default: /* not ip - do not know what to do */ + kfree_skb(skbn); goto skip; } @@ -1431,6 +1432,7 @@ static const struct usb_device_id products[] = { {QMI_QUIRK_SET_DTR(0x1546, 0x1312, 4)}, /* u-blox LARA-R6 01B */ {QMI_QUIRK_SET_DTR(0x1546, 0x1342, 4)}, /* u-blox LARA-L6 */ {QMI_QUIRK_SET_DTR(0x33f8, 0x0104, 4)}, /* Rolling RW101 RMNET */ + {QMI_FIXED_INTF(0x2dee, 0x4d22, 5)}, /* MeiG Smart SRM825L */ /* 4. Gobi 1000 devices */ {QMI_GOBI1K_DEVICE(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */ diff --git a/drivers/net/usb/sr9700.c b/drivers/net/usb/sr9700.c index 0a662e42ed9659..cb7d2f798fb436 100644 --- a/drivers/net/usb/sr9700.c +++ b/drivers/net/usb/sr9700.c @@ -179,6 +179,7 @@ static int sr_mdio_read(struct net_device *netdev, int phy_id, int loc) struct usbnet *dev = netdev_priv(netdev); __le16 res; int rc = 0; + int err; if (phy_id) { netdev_dbg(netdev, "Only internal phy supported\n"); @@ -189,11 +190,17 @@ static int sr_mdio_read(struct net_device *netdev, int phy_id, int loc) if (loc == MII_BMSR) { u8 value; - sr_read_reg(dev, SR_NSR, &value); + err = sr_read_reg(dev, SR_NSR, &value); + if (err < 0) + return err; + if (value & NSR_LINKST) rc = 1; } - sr_share_read_word(dev, 1, loc, &res); + err = sr_share_read_word(dev, 1, loc, &res); + if (err < 0) + return err; + if (rc == 1) res = le16_to_cpu(res) | BMSR_LSTATUS; else diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 0383a3e136d6a0..3f10c72743e94d 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -3658,6 +3658,9 @@ static int virtnet_send_rx_ctrl_coal_vq_cmd(struct virtnet_info *vi, { int err; + if (!virtio_has_feature(vi->vdev, VIRTIO_NET_F_VQ_NOTF_COAL)) + return -EOPNOTSUPP; + err = virtnet_send_ctrl_coal_vq_cmd(vi, rxq2vq(queue), max_usecs, max_packets); if (err) @@ -3675,6 +3678,9 @@ static int virtnet_send_tx_ctrl_coal_vq_cmd(struct virtnet_info *vi, { int err; + if (!virtio_has_feature(vi->vdev, VIRTIO_NET_F_VQ_NOTF_COAL)) + return -EOPNOTSUPP; + err = virtnet_send_ctrl_coal_vq_cmd(vi, txq2vq(queue), max_usecs, max_packets); if (err) @@ -3743,7 +3749,11 @@ static int virtnet_set_ringparam(struct net_device *dev, err = virtnet_send_tx_ctrl_coal_vq_cmd(vi, i, vi->intr_coal_tx.max_usecs, vi->intr_coal_tx.max_packets); - if (err) + + /* Don't break the tx resize action if the vq coalescing is not + * supported. The same is true for rx resize below. + */ + if (err && err != -EOPNOTSUPP) return err; } @@ -3758,7 +3768,7 @@ static int virtnet_set_ringparam(struct net_device *dev, vi->intr_coal_rx.max_usecs, vi->intr_coal_rx.max_packets); mutex_unlock(&vi->rq[i].dim_lock); - if (err) + if (err && err != -EOPNOTSUPP) return err; } } diff --git a/drivers/net/wan/fsl_qmc_hdlc.c b/drivers/net/wan/fsl_qmc_hdlc.c index c5e7ca793c4331..8fcfbde31a1c66 100644 --- a/drivers/net/wan/fsl_qmc_hdlc.c +++ b/drivers/net/wan/fsl_qmc_hdlc.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -37,7 +38,7 @@ struct qmc_hdlc { struct qmc_chan *qmc_chan; struct net_device *netdev; struct framer *framer; - spinlock_t carrier_lock; /* Protect carrier detection */ + struct mutex carrier_lock; /* Protect carrier detection */ struct notifier_block nb; bool is_crc32; spinlock_t tx_lock; /* Protect tx descriptors */ @@ -60,7 +61,7 @@ static int qmc_hdlc_framer_set_carrier(struct qmc_hdlc *qmc_hdlc) if (!qmc_hdlc->framer) return 0; - guard(spinlock_irqsave)(&qmc_hdlc->carrier_lock); + guard(mutex)(&qmc_hdlc->carrier_lock); ret = framer_get_status(qmc_hdlc->framer, &framer_status); if (ret) { @@ -249,6 +250,7 @@ static void qmc_hcld_recv_complete(void *context, size_t length, unsigned int fl struct qmc_hdlc_desc *desc = context; struct net_device *netdev; struct qmc_hdlc *qmc_hdlc; + size_t crc_size; int ret; netdev = desc->netdev; @@ -267,15 +269,26 @@ static void qmc_hcld_recv_complete(void *context, size_t length, unsigned int fl if (flags & QMC_RX_FLAG_HDLC_CRC) /* CRC error */ netdev->stats.rx_crc_errors++; kfree_skb(desc->skb); - } else { - netdev->stats.rx_packets++; - netdev->stats.rx_bytes += length; + goto re_queue; + } - skb_put(desc->skb, length); - desc->skb->protocol = hdlc_type_trans(desc->skb, netdev); - netif_rx(desc->skb); + /* Discard the CRC */ + crc_size = qmc_hdlc->is_crc32 ? 4 : 2; + if (length < crc_size) { + netdev->stats.rx_length_errors++; + kfree_skb(desc->skb); + goto re_queue; } + length -= crc_size; + + netdev->stats.rx_packets++; + netdev->stats.rx_bytes += length; + + skb_put(desc->skb, length); + desc->skb->protocol = hdlc_type_trans(desc->skb, netdev); + netif_rx(desc->skb); +re_queue: /* Re-queue a transfer using the same descriptor */ ret = qmc_hdlc_recv_queue(qmc_hdlc, desc, desc->dma_size); if (ret) { @@ -706,7 +719,7 @@ static int qmc_hdlc_probe(struct platform_device *pdev) qmc_hdlc->dev = dev; spin_lock_init(&qmc_hdlc->tx_lock); - spin_lock_init(&qmc_hdlc->carrier_lock); + mutex_init(&qmc_hdlc->carrier_lock); qmc_hdlc->qmc_chan = devm_qmc_chan_get_bychild(dev, dev->of_node); if (IS_ERR(qmc_hdlc->qmc_chan)) diff --git a/drivers/net/wireless/ath/ath12k/dp_tx.c b/drivers/net/wireless/ath/ath12k/dp_tx.c index d08c04343e9007..44406e0b4a342f 100644 --- a/drivers/net/wireless/ath/ath12k/dp_tx.c +++ b/drivers/net/wireless/ath/ath12k/dp_tx.c @@ -162,6 +162,60 @@ static int ath12k_dp_prepare_htt_metadata(struct sk_buff *skb) return 0; } +static void ath12k_dp_tx_move_payload(struct sk_buff *skb, + unsigned long delta, + bool head) +{ + unsigned long len = skb->len; + + if (head) { + skb_push(skb, delta); + memmove(skb->data, skb->data + delta, len); + skb_trim(skb, len); + } else { + skb_put(skb, delta); + memmove(skb->data + delta, skb->data, len); + skb_pull(skb, delta); + } +} + +static int ath12k_dp_tx_align_payload(struct ath12k_base *ab, + struct sk_buff **pskb) +{ + u32 iova_mask = ab->hw_params->iova_mask; + unsigned long offset, delta1, delta2; + struct sk_buff *skb2, *skb = *pskb; + unsigned int headroom = skb_headroom(skb); + int tailroom = skb_tailroom(skb); + int ret = 0; + + offset = (unsigned long)skb->data & iova_mask; + delta1 = offset; + delta2 = iova_mask - offset + 1; + + if (headroom >= delta1) { + ath12k_dp_tx_move_payload(skb, delta1, true); + } else if (tailroom >= delta2) { + ath12k_dp_tx_move_payload(skb, delta2, false); + } else { + skb2 = skb_realloc_headroom(skb, iova_mask); + if (!skb2) { + ret = -ENOMEM; + goto out; + } + + dev_kfree_skb_any(skb); + + offset = (unsigned long)skb2->data & iova_mask; + if (offset) + ath12k_dp_tx_move_payload(skb2, offset, true); + *pskb = skb2; + } + +out: + return ret; +} + int ath12k_dp_tx(struct ath12k *ar, struct ath12k_vif *arvif, struct sk_buff *skb) { @@ -184,6 +238,7 @@ int ath12k_dp_tx(struct ath12k *ar, struct ath12k_vif *arvif, bool tcl_ring_retry; bool msdu_ext_desc = false; bool add_htt_metadata = false; + u32 iova_mask = ab->hw_params->iova_mask; if (test_bit(ATH12K_FLAG_CRASH_FLUSH, &ar->ab->dev_flags)) return -ESHUTDOWN; @@ -279,6 +334,23 @@ int ath12k_dp_tx(struct ath12k *ar, struct ath12k_vif *arvif, goto fail_remove_tx_buf; } + if (iova_mask && + (unsigned long)skb->data & iova_mask) { + ret = ath12k_dp_tx_align_payload(ab, &skb); + if (ret) { + ath12k_warn(ab, "failed to align TX buffer %d\n", ret); + /* don't bail out, give original buffer + * a chance even unaligned. + */ + goto map; + } + + /* hdr is pointing to a wrong place after alignment, + * so refresh it for later use. + */ + hdr = (void *)skb->data; + } +map: ti.paddr = dma_map_single(ab->dev, skb->data, skb->len, DMA_TO_DEVICE); if (dma_mapping_error(ab->dev, ti.paddr)) { atomic_inc(&ab->soc_stats.tx_err.misc_fail); diff --git a/drivers/net/wireless/ath/ath12k/hw.c b/drivers/net/wireless/ath/ath12k/hw.c index 2e11ea7635740c..7b0b6a7f4701ab 100644 --- a/drivers/net/wireless/ath/ath12k/hw.c +++ b/drivers/net/wireless/ath/ath12k/hw.c @@ -924,6 +924,8 @@ static const struct ath12k_hw_params ath12k_hw_params[] = { .acpi_guid = NULL, .supports_dynamic_smps_6ghz = true, + + .iova_mask = 0, }, { .name = "wcn7850 hw2.0", @@ -1000,6 +1002,8 @@ static const struct ath12k_hw_params ath12k_hw_params[] = { .acpi_guid = &wcn7850_uuid, .supports_dynamic_smps_6ghz = false, + + .iova_mask = ATH12K_PCIE_MAX_PAYLOAD_SIZE - 1, }, { .name = "qcn9274 hw2.0", @@ -1072,6 +1076,8 @@ static const struct ath12k_hw_params ath12k_hw_params[] = { .acpi_guid = NULL, .supports_dynamic_smps_6ghz = true, + + .iova_mask = 0, }, }; diff --git a/drivers/net/wireless/ath/ath12k/hw.h b/drivers/net/wireless/ath/ath12k/hw.h index e792eb6b249b41..b1d302c48326b8 100644 --- a/drivers/net/wireless/ath/ath12k/hw.h +++ b/drivers/net/wireless/ath/ath12k/hw.h @@ -96,6 +96,8 @@ #define ATH12K_M3_FILE "m3.bin" #define ATH12K_REGDB_FILE_NAME "regdb.bin" +#define ATH12K_PCIE_MAX_PAYLOAD_SIZE 128 + enum ath12k_hw_rate_cck { ATH12K_HW_RATE_CCK_LP_11M = 0, ATH12K_HW_RATE_CCK_LP_5_5M, @@ -215,6 +217,8 @@ struct ath12k_hw_params { const guid_t *acpi_guid; bool supports_dynamic_smps_6ghz; + + u32 iova_mask; }; struct ath12k_hw_ops { diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c index 8106297f0bc1c7..ce41c8153080cd 100644 --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c @@ -9193,6 +9193,7 @@ static int ath12k_mac_hw_register(struct ath12k_hw *ah) hw->vif_data_size = sizeof(struct ath12k_vif); hw->sta_data_size = sizeof(struct ath12k_sta); + hw->extra_tx_headroom = ab->hw_params->iova_mask; wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST); wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_STA_TX_PWR); diff --git a/drivers/net/wireless/ath/ath12k/pci.c b/drivers/net/wireless/ath/ath12k/pci.c index 876c029f58f62c..9e0b9e329bda32 100644 --- a/drivers/net/wireless/ath/ath12k/pci.c +++ b/drivers/net/wireless/ath/ath12k/pci.c @@ -473,7 +473,8 @@ static void __ath12k_pci_ext_irq_disable(struct ath12k_base *ab) { int i; - clear_bit(ATH12K_FLAG_EXT_IRQ_ENABLED, &ab->dev_flags); + if (!test_and_clear_bit(ATH12K_FLAG_EXT_IRQ_ENABLED, &ab->dev_flags)) + return; for (i = 0; i < ATH12K_EXT_IRQ_GRP_NUM_MAX; i++) { struct ath12k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i]; diff --git a/drivers/net/wireless/ath/ath12k/wow.c b/drivers/net/wireless/ath/ath12k/wow.c index bead19db2c9a21..9b8684abbe40ae 100644 --- a/drivers/net/wireless/ath/ath12k/wow.c +++ b/drivers/net/wireless/ath/ath12k/wow.c @@ -361,7 +361,7 @@ static int ath12k_wow_vif_set_wakeups(struct ath12k_vif *arvif, struct ath12k *ar = arvif->ar; unsigned long wow_mask = 0; int pattern_id = 0; - int ret, i; + int ret, i, j; /* Setup requested WOW features */ switch (arvif->vdev_type) { @@ -431,9 +431,9 @@ static int ath12k_wow_vif_set_wakeups(struct ath12k_vif *arvif, eth_pattern->pattern_len); /* convert bitmask to bytemask */ - for (i = 0; i < eth_pattern->pattern_len; i++) - if (eth_pattern->mask[i / 8] & BIT(i % 8)) - new_pattern.bytemask[i] = 0xff; + for (j = 0; j < eth_pattern->pattern_len; j++) + if (eth_pattern->mask[j / 8] & BIT(j % 8)) + new_pattern.bytemask[j] = 0xff; new_pattern.pattern_len = eth_pattern->pattern_len; new_pattern.pkt_offset = eth_pattern->pkt_offset; diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c index 1585a5653ee4b9..d4cc5fa92341d5 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c @@ -4320,9 +4320,16 @@ brcmf_pmksa_v3_op(struct brcmf_if *ifp, struct cfg80211_pmksa *pmksa, /* Single PMK operation */ pmk_op->count = cpu_to_le16(1); length += sizeof(struct brcmf_pmksa_v3); - memcpy(pmk_op->pmk[0].bssid, pmksa->bssid, ETH_ALEN); - memcpy(pmk_op->pmk[0].pmkid, pmksa->pmkid, WLAN_PMKID_LEN); - pmk_op->pmk[0].pmkid_len = WLAN_PMKID_LEN; + if (pmksa->bssid) + memcpy(pmk_op->pmk[0].bssid, pmksa->bssid, ETH_ALEN); + if (pmksa->pmkid) { + memcpy(pmk_op->pmk[0].pmkid, pmksa->pmkid, WLAN_PMKID_LEN); + pmk_op->pmk[0].pmkid_len = WLAN_PMKID_LEN; + } + if (pmksa->ssid && pmksa->ssid_len) { + memcpy(pmk_op->pmk[0].ssid.SSID, pmksa->ssid, pmksa->ssid_len); + pmk_op->pmk[0].ssid.SSID_len = pmksa->ssid_len; + } pmk_op->pmk[0].time_left = cpu_to_le32(alive ? BRCMF_PMKSA_NO_EXPIRY : 0); } diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h index b59de4f80b4b89..27a7e0b5b3d51e 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h +++ b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h @@ -639,7 +639,8 @@ void iwl_trans_pcie_tx_reset(struct iwl_trans *trans); int iwl_pcie_txq_alloc(struct iwl_trans *trans, struct iwl_txq *txq, int slots_num, bool cmd_queue); -dma_addr_t iwl_pcie_get_sgt_tb_phys(struct sg_table *sgt, void *addr); +dma_addr_t iwl_pcie_get_sgt_tb_phys(struct sg_table *sgt, unsigned int offset, + unsigned int len); struct sg_table *iwl_pcie_prep_tso(struct iwl_trans *trans, struct sk_buff *skb, struct iwl_cmd_meta *cmd_meta, u8 **hdr, unsigned int hdr_room); diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c index 2e780fb2da426c..b1846abb99b78f 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c @@ -168,6 +168,7 @@ static int iwl_txq_gen2_build_amsdu(struct iwl_trans *trans, struct ieee80211_hdr *hdr = (void *)skb->data; unsigned int snap_ip_tcp_hdrlen, ip_hdrlen, total_len, hdr_room; unsigned int mss = skb_shinfo(skb)->gso_size; + unsigned int data_offset = 0; dma_addr_t start_hdr_phys; u16 length, amsdu_pad; u8 *start_hdr; @@ -260,7 +261,8 @@ static int iwl_txq_gen2_build_amsdu(struct iwl_trans *trans, int ret; tb_len = min_t(unsigned int, tso.size, data_left); - tb_phys = iwl_pcie_get_sgt_tb_phys(sgt, tso.data); + tb_phys = iwl_pcie_get_sgt_tb_phys(sgt, data_offset, + tb_len); /* Not a real mapping error, use direct comparison */ if (unlikely(tb_phys == DMA_MAPPING_ERROR)) goto out_err; @@ -272,6 +274,7 @@ static int iwl_txq_gen2_build_amsdu(struct iwl_trans *trans, goto out_err; data_left -= tb_len; + data_offset += tb_len; tso_build_data(skb, &tso, tb_len); } } diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c index 22d482ae53d97a..9fe050f0ddc160 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c @@ -1814,23 +1814,31 @@ static void *iwl_pcie_get_page_hdr(struct iwl_trans *trans, /** * iwl_pcie_get_sgt_tb_phys - Find TB address in mapped SG list * @sgt: scatter gather table - * @addr: Virtual address + * @offset: Offset into the mapped memory (i.e. SKB payload data) + * @len: Length of the area * - * Find the entry that includes the address for the given address and return - * correct physical address for the TB entry. + * Find the DMA address that corresponds to the SKB payload data at the + * position given by @offset. * * Returns: Address for TB entry */ -dma_addr_t iwl_pcie_get_sgt_tb_phys(struct sg_table *sgt, void *addr) +dma_addr_t iwl_pcie_get_sgt_tb_phys(struct sg_table *sgt, unsigned int offset, + unsigned int len) { struct scatterlist *sg; + unsigned int sg_offset = 0; int i; + /* + * Search the mapped DMA areas in the SG for the area that contains the + * data at offset with the given length. + */ for_each_sgtable_dma_sg(sgt, sg, i) { - if (addr >= sg_virt(sg) && - (u8 *)addr < (u8 *)sg_virt(sg) + sg_dma_len(sg)) - return sg_dma_address(sg) + - ((unsigned long)addr - (unsigned long)sg_virt(sg)); + if (offset >= sg_offset && + offset + len <= sg_offset + sg_dma_len(sg)) + return sg_dma_address(sg) + offset - sg_offset; + + sg_offset += sg_dma_len(sg); } WARN_ON_ONCE(1); @@ -1875,7 +1883,9 @@ struct sg_table *iwl_pcie_prep_tso(struct iwl_trans *trans, struct sk_buff *skb, sg_init_table(sgt->sgl, skb_shinfo(skb)->nr_frags + 1); - sgt->orig_nents = skb_to_sgvec(skb, sgt->sgl, 0, skb->len); + /* Only map the data, not the header (it is copied to the TSO page) */ + sgt->orig_nents = skb_to_sgvec(skb, sgt->sgl, skb_headlen(skb), + skb->data_len); if (WARN_ON_ONCE(sgt->orig_nents <= 0)) return NULL; @@ -1900,6 +1910,7 @@ static int iwl_fill_data_tbs_amsdu(struct iwl_trans *trans, struct sk_buff *skb, struct ieee80211_hdr *hdr = (void *)skb->data; unsigned int snap_ip_tcp_hdrlen, ip_hdrlen, total_len, hdr_room; unsigned int mss = skb_shinfo(skb)->gso_size; + unsigned int data_offset = 0; u16 length, iv_len, amsdu_pad; dma_addr_t start_hdr_phys; u8 *start_hdr, *pos_hdr; @@ -2000,7 +2011,7 @@ static int iwl_fill_data_tbs_amsdu(struct iwl_trans *trans, struct sk_buff *skb, data_left); dma_addr_t tb_phys; - tb_phys = iwl_pcie_get_sgt_tb_phys(sgt, tso.data); + tb_phys = iwl_pcie_get_sgt_tb_phys(sgt, data_offset, size); /* Not a real mapping error, use direct comparison */ if (unlikely(tb_phys == DMA_MAPPING_ERROR)) return -EINVAL; @@ -2011,6 +2022,7 @@ static int iwl_fill_data_tbs_amsdu(struct iwl_trans *trans, struct sk_buff *skb, tb_phys, size); data_left -= size; + data_offset += size; tso_build_data(skb, &tso, size); } } diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c index 2e6268cb06c002..23b228804289be 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c @@ -303,6 +303,7 @@ mt7921_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) mvif->bss_conf.mt76.omac_idx = mvif->bss_conf.mt76.idx; mvif->phy = phy; + mvif->bss_conf.vif = mvif; mvif->bss_conf.mt76.band_idx = 0; mvif->bss_conf.mt76.wmm_idx = mvif->bss_conf.mt76.idx % MT76_CONNAC_MAX_WMM_SETS; @@ -1182,7 +1183,7 @@ static void mt7921_ipv6_addr_change(struct ieee80211_hw *hw, struct inet6_dev *idev) { struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; - struct mt792x_dev *dev = mvif->phy->dev; + struct mt792x_dev *dev = mt792x_hw_dev(hw); struct inet6_ifaddr *ifa; struct in6_addr ns_addrs[IEEE80211_BSS_ARP_ADDR_LIST_LEN]; struct sk_buff *skb; diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192du/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192du/hw.c index 700c6e2bcad194..ff458fb8514dae 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192du/hw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192du/hw.c @@ -181,11 +181,11 @@ static void _rtl92du_init_queue_reserved_page(struct ieee80211_hw *hw, struct rtl_hal *rtlhal = rtl_hal(rtlpriv); u32 txqpagenum, txqpageunit; u32 txqremainingpage; + u32 value32 = 0; u32 numhq = 0; u32 numlq = 0; u32 numnq = 0; u32 numpubq; - u32 value32; if (rtlhal->macphymode != SINGLEMAC_SINGLEPHY) { numpubq = NORMAL_PAGE_NUM_PUBQ_92D_DUAL_MAC; diff --git a/drivers/nfc/pn544/i2c.c b/drivers/nfc/pn544/i2c.c index 9fe664960b3803..e2a6575b9ff7f8 100644 --- a/drivers/nfc/pn544/i2c.c +++ b/drivers/nfc/pn544/i2c.c @@ -126,8 +126,6 @@ struct pn544_i2c_fw_secure_blob { #define PN544_FW_CMD_RESULT_COMMAND_REJECTED 0xE0 #define PN544_FW_CMD_RESULT_CHUNK_ERROR 0xE6 -#define MIN(X, Y) ((X) < (Y) ? (X) : (Y)) - #define PN544_FW_WRITE_BUFFER_MAX_LEN 0x9f7 #define PN544_FW_I2C_MAX_PAYLOAD PN544_HCI_I2C_LLC_MAX_SIZE #define PN544_FW_I2C_WRITE_FRAME_HEADER_LEN 8 diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c index 1ae8b2351654e7..210fb77f51ba02 100644 --- a/drivers/nvdimm/pmem.c +++ b/drivers/nvdimm/pmem.c @@ -498,7 +498,7 @@ static int pmem_attach_disk(struct device *dev, } if (fua) lim.features |= BLK_FEAT_FUA; - if (is_nd_pfn(dev)) + if (is_nd_pfn(dev) || pmem_should_map_pages(dev)) lim.features |= BLK_FEAT_DAX; if (!devm_request_mem_region(dev, res->start, resource_size(res), diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index 053d5b4909cda4..33fa01c599adda 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -36,6 +36,7 @@ struct nvme_ns_info { struct nvme_ns_ids ids; u32 nsid; __le32 anagrpid; + u8 pi_offset; bool is_shared; bool is_readonly; bool is_ready; @@ -1757,8 +1758,8 @@ int nvme_getgeo(struct block_device *bdev, struct hd_geometry *geo) return 0; } -static bool nvme_init_integrity(struct gendisk *disk, struct nvme_ns_head *head, - struct queue_limits *lim) +static bool nvme_init_integrity(struct nvme_ns_head *head, + struct queue_limits *lim, struct nvme_ns_info *info) { struct blk_integrity *bi = &lim->integrity; @@ -1816,7 +1817,7 @@ static bool nvme_init_integrity(struct gendisk *disk, struct nvme_ns_head *head, } bi->tuple_size = head->ms; - bi->pi_offset = head->pi_offset; + bi->pi_offset = info->pi_offset; return true; } @@ -1902,12 +1903,11 @@ static void nvme_configure_pi_elbas(struct nvme_ns_head *head, static void nvme_configure_metadata(struct nvme_ctrl *ctrl, struct nvme_ns_head *head, struct nvme_id_ns *id, - struct nvme_id_ns_nvm *nvm) + struct nvme_id_ns_nvm *nvm, struct nvme_ns_info *info) { head->features &= ~(NVME_NS_METADATA_SUPPORTED | NVME_NS_EXT_LBAS); head->pi_type = 0; head->pi_size = 0; - head->pi_offset = 0; head->ms = le16_to_cpu(id->lbaf[nvme_lbaf_index(id->flbas)].ms); if (!head->ms || !(ctrl->ops->flags & NVME_F_METADATA_SUPPORTED)) return; @@ -1922,7 +1922,7 @@ static void nvme_configure_metadata(struct nvme_ctrl *ctrl, if (head->pi_size && head->ms >= head->pi_size) head->pi_type = id->dps & NVME_NS_DPS_PI_MASK; if (!(id->dps & NVME_NS_DPS_PI_FIRST)) - head->pi_offset = head->ms - head->pi_size; + info->pi_offset = head->ms - head->pi_size; if (ctrl->ops->flags & NVME_F_FABRICS) { /* @@ -2156,7 +2156,7 @@ static int nvme_update_ns_info_block(struct nvme_ns *ns, lim = queue_limits_start_update(ns->disk->queue); nvme_set_ctrl_limits(ns->ctrl, &lim); - nvme_configure_metadata(ns->ctrl, ns->head, id, nvm); + nvme_configure_metadata(ns->ctrl, ns->head, id, nvm, info); nvme_set_chunk_sectors(ns, id, &lim); if (!nvme_update_disk_info(ns, id, &lim)) capacity = 0; @@ -2176,7 +2176,7 @@ static int nvme_update_ns_info_block(struct nvme_ns *ns, * I/O to namespaces with metadata except when the namespace supports * PI, as it can strip/insert in that case. */ - if (!nvme_init_integrity(ns->disk, ns->head, &lim)) + if (!nvme_init_integrity(ns->head, &lim, info)) capacity = 0; ret = queue_limits_commit_update(ns->disk->queue, &lim); @@ -2280,7 +2280,7 @@ static int nvme_update_ns_info(struct nvme_ns *ns, struct nvme_ns_info *info) if (unsupported) ns->head->disk->flags |= GENHD_FL_HIDDEN; else - nvme_init_integrity(ns->head->disk, ns->head, &lim); + nvme_init_integrity(ns->head, &lim, info); ret = queue_limits_commit_update(ns->head->disk->queue, &lim); set_capacity_and_notify(ns->head->disk, get_capacity(ns->disk)); diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h index f900e44243aef0..ae5314d32943e8 100644 --- a/drivers/nvme/host/nvme.h +++ b/drivers/nvme/host/nvme.h @@ -462,20 +462,19 @@ struct nvme_ns_head { struct srcu_struct srcu; struct nvme_subsystem *subsys; struct nvme_ns_ids ids; + u8 lba_shift; + u16 ms; + u16 pi_size; + u8 pi_type; + u8 guard_type; struct list_head entry; struct kref ref; bool shared; bool passthru_err_log_enabled; - int instance; struct nvme_effects_log *effects; u64 nuse; unsigned ns_id; - int lba_shift; - u16 ms; - u16 pi_size; - u8 pi_type; - u8 pi_offset; - u8 guard_type; + int instance; #ifdef CONFIG_BLK_DEV_ZONED u64 zsze; #endif diff --git a/drivers/of/irq.c b/drivers/of/irq.c index c94203ce65bb32..8fd63100ba8f08 100644 --- a/drivers/of/irq.c +++ b/drivers/of/irq.c @@ -344,7 +344,8 @@ int of_irq_parse_one(struct device_node *device, int index, struct of_phandle_ar struct device_node *p; const __be32 *addr; u32 intsize; - int i, res; + int i, res, addr_len; + __be32 addr_buf[3] = { 0 }; pr_debug("of_irq_parse_one: dev=%pOF, index=%d\n", device, index); @@ -353,13 +354,19 @@ int of_irq_parse_one(struct device_node *device, int index, struct of_phandle_ar return of_irq_parse_oldworld(device, index, out_irq); /* Get the reg property (if any) */ - addr = of_get_property(device, "reg", NULL); + addr = of_get_property(device, "reg", &addr_len); + + /* Prevent out-of-bounds read in case of longer interrupt parent address size */ + if (addr_len > (3 * sizeof(__be32))) + addr_len = 3 * sizeof(__be32); + if (addr) + memcpy(addr_buf, addr, addr_len); /* Try the new-style interrupts-extended first */ res = of_parse_phandle_with_args(device, "interrupts-extended", "#interrupt-cells", index, out_irq); if (!res) - return of_irq_parse_raw(addr, out_irq); + return of_irq_parse_raw(addr_buf, out_irq); /* Look for the interrupt parent. */ p = of_irq_find_parent(device); @@ -389,7 +396,7 @@ int of_irq_parse_one(struct device_node *device, int index, struct of_phandle_ar /* Check if there are any interrupt-map translations to process */ - res = of_irq_parse_raw(addr, out_irq); + res = of_irq_parse_raw(addr_buf, out_irq); out: of_node_put(p); return res; diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 061f01f60db4b9..736ad8baa2a555 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -485,7 +485,9 @@ int pciehp_set_raw_indicator_status(struct hotplug_slot *hotplug_slot, struct pci_dev *pdev = ctrl_dev(ctrl); pci_config_pm_runtime_get(pdev); - pcie_write_cmd_nowait(ctrl, FIELD_PREP(PCI_EXP_SLTCTL_AIC, status), + + /* Attention and Power Indicator Control bits are supported */ + pcie_write_cmd_nowait(ctrl, FIELD_PREP(PCI_EXP_SLTCTL_AIC | PCI_EXP_SLTCTL_PIC, status), PCI_EXP_SLTCTL_AIC | PCI_EXP_SLTCTL_PIC); pci_config_pm_runtime_put(pdev); return 0; diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index e3a49f66982d52..ffaaca0978cbc9 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -4477,12 +4477,6 @@ void pci_intx(struct pci_dev *pdev, int enable) { u16 pci_command, new; - /* Preserve the "hybrid" behavior for backwards compatibility */ - if (pci_is_managed(pdev)) { - WARN_ON_ONCE(pcim_intx(pdev, enable) != 0); - return; - } - pci_read_config_word(pdev, PCI_COMMAND, &pci_command); if (enable) @@ -4490,8 +4484,15 @@ void pci_intx(struct pci_dev *pdev, int enable) else new = pci_command | PCI_COMMAND_INTX_DISABLE; - if (new != pci_command) + if (new != pci_command) { + /* Preserve the "hybrid" behavior for backwards compatibility */ + if (pci_is_managed(pdev)) { + WARN_ON_ONCE(pcim_intx(pdev, enable) != 0); + return; + } + pci_write_config_word(pdev, PCI_COMMAND, new); + } } EXPORT_SYMBOL_GPL(pci_intx); diff --git a/drivers/perf/riscv_pmu_sbi.c b/drivers/perf/riscv_pmu_sbi.c index 44d3951d009fb0..31a17a56eb3bba 100644 --- a/drivers/perf/riscv_pmu_sbi.c +++ b/drivers/perf/riscv_pmu_sbi.c @@ -416,7 +416,7 @@ static int pmu_sbi_ctr_get_idx(struct perf_event *event) * but not in the user access mode as we want to use the other counters * that support sampling/filtering. */ - if (hwc->flags & PERF_EVENT_FLAG_LEGACY) { + if ((hwc->flags & PERF_EVENT_FLAG_LEGACY) && (event->attr.type == PERF_TYPE_HARDWARE)) { if (event->attr.config == PERF_COUNT_HW_CPU_CYCLES) { cflags |= SBI_PMU_CFG_FLAG_SKIP_MATCH; cmask = 1; diff --git a/drivers/platform/chrome/cros_ec_proto.c b/drivers/platform/chrome/cros_ec_proto.c index f776fd42244f4c..73f75958e15c10 100644 --- a/drivers/platform/chrome/cros_ec_proto.c +++ b/drivers/platform/chrome/cros_ec_proto.c @@ -813,9 +813,11 @@ int cros_ec_get_next_event(struct cros_ec_device *ec_dev, if (ret == -ENOPROTOOPT) { dev_dbg(ec_dev->dev, "GET_NEXT_EVENT returned invalid version error.\n"); + mutex_lock(&ec_dev->lock); ret = cros_ec_get_host_command_version_mask(ec_dev, EC_CMD_GET_NEXT_EVENT, &ver_mask); + mutex_unlock(&ec_dev->lock); if (ret < 0 || ver_mask == 0) /* * Do not change the MKBP supported version if we can't diff --git a/drivers/platform/cznic/Kconfig b/drivers/platform/cznic/Kconfig index cb0d4d686d8a51..a111eca8ff57d2 100644 --- a/drivers/platform/cznic/Kconfig +++ b/drivers/platform/cznic/Kconfig @@ -16,35 +16,65 @@ config TURRIS_OMNIA_MCU tristate "Turris Omnia MCU driver" depends on MACH_ARMADA_38X || COMPILE_TEST depends on I2C - depends on OF - depends on WATCHDOG - depends on GPIOLIB - depends on HW_RANDOM - depends on RTC_CLASS - depends on WATCHDOG_CORE - select GPIOLIB_IRQCHIP help Say Y here to add support for the features implemented by the microcontroller on the CZ.NIC's Turris Omnia SOHO router. - The features include: - - board poweroff into true low power mode (with voltage regulators - disabled) and the ability to configure wake up from this mode (via - rtcwake) - - true random number generator (if available on the MCU) - - MCU watchdog - - GPIO pins - - to get front button press events (the front button can be - configured either to generate press events to the CPU or to change - front LEDs panel brightness) - - to enable / disable USB port voltage regulators and to detect - USB overcurrent - - to detect MiniPCIe / mSATA card presence in MiniPCIe port 0 - - to configure resets of various peripherals on board revisions 32+ - - to enable / disable the VHV voltage regulator to the SOC in order - to be able to program SOC's OTP on board revisions 32+ - - to get input from the LED output pins of the WAN ethernet PHY, LAN - switch and MiniPCIe ports + This option only enables the core part of the driver. Specific + features can be enabled by subsequent config options. To compile this driver as a module, choose M here; the module will be called turris-omnia-mcu. +if TURRIS_OMNIA_MCU + +config TURRIS_OMNIA_MCU_GPIO + bool "Turris Omnia MCU GPIOs" + default y + depends on GPIOLIB + depends on OF + select GPIOLIB_IRQCHIP + help + Say Y here to add support for controlling MCU GPIO pins and receiving + MCU interrupts on CZ.NIC's Turris Omnia. + This enables you to + - get front button press events (the front button can be configured + either to generate press events to the CPU or to change front LEDs + panel brightness), + - enable / disable USB port voltage regulators and to detect USB + overcurrent, + - detect MiniPCIe / mSATA card presence in MiniPCIe port 0, + - configure resets of various peripherals on board revisions 32+, + - enable / disable the VHV voltage regulator to the SOC in order to be + able to program SOC's OTP on board revisions 32+, + - get input from the LED output pins of the WAN ethernet PHY, LAN + switch and MiniPCIe ports. + +config TURRIS_OMNIA_MCU_SYSOFF_WAKEUP + bool "Turris Omnia MCU system off and RTC wakeup" + default y + depends on RTC_CLASS + help + Say Y here to add support for CZ.NIC's Turris Omnia board poweroff + into true low power mode (with voltage regulators disabled) and the + ability to configure wake up from this mode (via rtcwake). + +config TURRIS_OMNIA_MCU_WATCHDOG + bool "Turris Omnia MCU watchdog" + default y + depends on WATCHDOG + select WATCHDOG_CORE + help + Say Y here to add support for watchdog provided by CZ.NIC's Turris + Omnia MCU. + +config TURRIS_OMNIA_MCU_TRNG + bool "Turris Omnia MCU true random number generator" + default y + depends on TURRIS_OMNIA_MCU_GPIO + depends on HW_RANDOM + help + Say Y here to add support for the true random number generator + provided by CZ.NIC's Turris Omnia MCU. + +endif # TURRIS_OMNIA_MCU + endif # CZNIC_PLATFORMS diff --git a/drivers/platform/cznic/Makefile b/drivers/platform/cznic/Makefile index eae4c6b341fff7..ce6d997f34d66e 100644 --- a/drivers/platform/cznic/Makefile +++ b/drivers/platform/cznic/Makefile @@ -2,7 +2,7 @@ obj-$(CONFIG_TURRIS_OMNIA_MCU) += turris-omnia-mcu.o turris-omnia-mcu-y := turris-omnia-mcu-base.o -turris-omnia-mcu-y += turris-omnia-mcu-gpio.o -turris-omnia-mcu-y += turris-omnia-mcu-sys-off-wakeup.o -turris-omnia-mcu-y += turris-omnia-mcu-trng.o -turris-omnia-mcu-y += turris-omnia-mcu-watchdog.o +turris-omnia-mcu-$(CONFIG_TURRIS_OMNIA_MCU_GPIO) += turris-omnia-mcu-gpio.o +turris-omnia-mcu-$(CONFIG_TURRIS_OMNIA_MCU_SYSOFF_WAKEUP) += turris-omnia-mcu-sys-off-wakeup.o +turris-omnia-mcu-$(CONFIG_TURRIS_OMNIA_MCU_TRNG) += turris-omnia-mcu-trng.o +turris-omnia-mcu-$(CONFIG_TURRIS_OMNIA_MCU_WATCHDOG) += turris-omnia-mcu-watchdog.o diff --git a/drivers/platform/cznic/turris-omnia-mcu-base.c b/drivers/platform/cznic/turris-omnia-mcu-base.c index c68a7a84a9519a..58f9afae286737 100644 --- a/drivers/platform/cznic/turris-omnia-mcu-base.c +++ b/drivers/platform/cznic/turris-omnia-mcu-base.c @@ -197,8 +197,12 @@ static const struct attribute_group omnia_mcu_base_group = { static const struct attribute_group *omnia_mcu_groups[] = { &omnia_mcu_base_group, +#ifdef CONFIG_TURRIS_OMNIA_MCU_GPIO &omnia_mcu_gpio_group, +#endif +#ifdef CONFIG_TURRIS_OMNIA_MCU_SYSOFF_WAKEUP &omnia_mcu_poweroff_group, +#endif NULL }; diff --git a/drivers/platform/cznic/turris-omnia-mcu.h b/drivers/platform/cznic/turris-omnia-mcu.h index 2ca56ae13aa908..fed0d357fea39c 100644 --- a/drivers/platform/cznic/turris-omnia-mcu.h +++ b/drivers/platform/cznic/turris-omnia-mcu.h @@ -33,6 +33,7 @@ struct omnia_mcu { u8 board_first_mac[ETH_ALEN]; u8 board_revision; +#ifdef CONFIG_TURRIS_OMNIA_MCU_GPIO /* GPIO chip */ struct gpio_chip gc; struct mutex lock; @@ -41,18 +42,25 @@ struct omnia_mcu { struct delayed_work button_release_emul_work; unsigned long last_status; bool button_pressed_emul; +#endif +#ifdef CONFIG_TURRIS_OMNIA_MCU_SYSOFF_WAKEUP /* RTC device for configuring wake-up */ struct rtc_device *rtcdev; u32 rtc_alarm; bool front_button_poweron; +#endif +#ifdef CONFIG_TURRIS_OMNIA_MCU_WATCHDOG /* MCU watchdog */ struct watchdog_device wdt; +#endif +#ifdef CONFIG_TURRIS_OMNIA_MCU_TRNG /* true random number generator */ struct hwrng trng; struct completion trng_entropy_ready; +#endif }; int omnia_cmd_write_read(const struct i2c_client *client, @@ -182,13 +190,43 @@ static inline int omnia_cmd_read_u8(const struct i2c_client *client, u8 cmd, return omnia_cmd_read(client, cmd, reply, sizeof(*reply)); } +#ifdef CONFIG_TURRIS_OMNIA_MCU_GPIO extern const u8 omnia_int_to_gpio_idx[32]; extern const struct attribute_group omnia_mcu_gpio_group; -extern const struct attribute_group omnia_mcu_poweroff_group; - int omnia_mcu_register_gpiochip(struct omnia_mcu *mcu); +#else +static inline int omnia_mcu_register_gpiochip(struct omnia_mcu *mcu) +{ + return 0; +} +#endif + +#ifdef CONFIG_TURRIS_OMNIA_MCU_SYSOFF_WAKEUP +extern const struct attribute_group omnia_mcu_poweroff_group; int omnia_mcu_register_sys_off_and_wakeup(struct omnia_mcu *mcu); +#else +static inline int omnia_mcu_register_sys_off_and_wakeup(struct omnia_mcu *mcu) +{ + return 0; +} +#endif + +#ifdef CONFIG_TURRIS_OMNIA_MCU_TRNG int omnia_mcu_register_trng(struct omnia_mcu *mcu); +#else +static inline int omnia_mcu_register_trng(struct omnia_mcu *mcu) +{ + return 0; +} +#endif + +#ifdef CONFIG_TURRIS_OMNIA_MCU_WATCHDOG int omnia_mcu_register_watchdog(struct omnia_mcu *mcu); +#else +static inline int omnia_mcu_register_watchdog(struct omnia_mcu *mcu) +{ + return 0; +} +#endif #endif /* __TURRIS_OMNIA_MCU_H */ diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index 665fa952498659..ddfccc226751f4 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -477,6 +477,7 @@ config LENOVO_YMC tristate "Lenovo Yoga Tablet Mode Control" depends on ACPI_WMI depends on INPUT + depends on IDEAPAD_LAPTOP select INPUT_SPARSEKMAP help This driver maps the Tablet Mode Control switch to SW_TABLET_MODE input diff --git a/drivers/platform/x86/amd/pmc/pmc.c b/drivers/platform/x86/amd/pmc/pmc.c index a3d881f6e5d904..c3e51f0a5c33e2 100644 --- a/drivers/platform/x86/amd/pmc/pmc.c +++ b/drivers/platform/x86/amd/pmc/pmc.c @@ -764,6 +764,7 @@ static int amd_pmc_get_os_hint(struct amd_pmc_dev *dev) case AMD_CPU_ID_CB: case AMD_CPU_ID_PS: case PCI_DEVICE_ID_AMD_1AH_M20H_ROOT: + case PCI_DEVICE_ID_AMD_1AH_M60H_ROOT: return MSG_OS_HINT_RN; } return -EINVAL; @@ -967,6 +968,7 @@ static const struct pci_device_id pmc_pci_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_AMD, AMD_CPU_ID_RV) }, { PCI_DEVICE(PCI_VENDOR_ID_AMD, AMD_CPU_ID_SP) }, { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_1AH_M20H_ROOT) }, + { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_1AH_M60H_ROOT) }, { } }; diff --git a/drivers/platform/x86/amd/pmc/pmc.h b/drivers/platform/x86/amd/pmc/pmc.h index 9e32d3128c3a2b..f1166d15c85620 100644 --- a/drivers/platform/x86/amd/pmc/pmc.h +++ b/drivers/platform/x86/amd/pmc/pmc.h @@ -67,6 +67,7 @@ void amd_mp2_stb_deinit(struct amd_pmc_dev *dev); #define AMD_CPU_ID_PS 0x14E8 #define AMD_CPU_ID_SP 0x14A4 #define PCI_DEVICE_ID_AMD_1AH_M20H_ROOT 0x1507 +#define PCI_DEVICE_ID_AMD_1AH_M60H_ROOT 0x1122 #define PCI_DEVICE_ID_AMD_MP2_STB 0x172c #endif /* PMC_H */ diff --git a/drivers/platform/x86/amd/pmf/core.c b/drivers/platform/x86/amd/pmf/core.c index 2d6e2558863c58..8f1f719befa3e7 100644 --- a/drivers/platform/x86/amd/pmf/core.c +++ b/drivers/platform/x86/amd/pmf/core.c @@ -41,6 +41,7 @@ #define AMD_CPU_ID_RMB 0x14b5 #define AMD_CPU_ID_PS 0x14e8 #define PCI_DEVICE_ID_AMD_1AH_M20H_ROOT 0x1507 +#define PCI_DEVICE_ID_AMD_1AH_M60H_ROOT 0x1122 #define PMF_MSG_DELAY_MIN_US 50 #define RESPONSE_REGISTER_LOOP_MAX 20000 @@ -249,6 +250,7 @@ static const struct pci_device_id pmf_pci_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_AMD, AMD_CPU_ID_RMB) }, { PCI_DEVICE(PCI_VENDOR_ID_AMD, AMD_CPU_ID_PS) }, { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_1AH_M20H_ROOT) }, + { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_1AH_M60H_ROOT) }, { } }; @@ -382,6 +384,7 @@ static const struct acpi_device_id amd_pmf_acpi_ids[] = { {"AMDI0102", 0}, {"AMDI0103", 0}, {"AMDI0105", 0}, + {"AMDI0107", 0}, { } }; MODULE_DEVICE_TABLE(acpi, amd_pmf_acpi_ids); diff --git a/drivers/platform/x86/amd/pmf/pmf-quirks.c b/drivers/platform/x86/amd/pmf/pmf-quirks.c index 0b2eb0ae85febd..460444cda1b295 100644 --- a/drivers/platform/x86/amd/pmf/pmf-quirks.c +++ b/drivers/platform/x86/amd/pmf/pmf-quirks.c @@ -29,6 +29,14 @@ static const struct dmi_system_id fwbug_list[] = { }, .driver_data = &quirk_no_sps_bug, }, + { + .ident = "ROG Ally X", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "RC72LA"), + }, + .driver_data = &quirk_no_sps_bug, + }, {} }; @@ -48,4 +56,3 @@ void amd_pmf_quirks_init(struct amd_pmf_dev *dev) dmi_id->ident); } } - diff --git a/drivers/platform/x86/amd/pmf/spc.c b/drivers/platform/x86/amd/pmf/spc.c index a3dec14c30043e..3c153fb1425e9f 100644 --- a/drivers/platform/x86/amd/pmf/spc.c +++ b/drivers/platform/x86/amd/pmf/spc.c @@ -150,36 +150,26 @@ static int amd_pmf_get_slider_info(struct amd_pmf_dev *dev, struct ta_pmf_enact_ return 0; } -static int amd_pmf_get_sensor_info(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *in) +static void amd_pmf_get_sensor_info(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *in) { struct amd_sfh_info sfh_info; - int ret; + + /* Get the latest information from SFH */ + in->ev_info.user_present = false; /* Get ALS data */ - ret = amd_get_sfh_info(&sfh_info, MT_ALS); - if (!ret) + if (!amd_get_sfh_info(&sfh_info, MT_ALS)) in->ev_info.ambient_light = sfh_info.ambient_light; else - return ret; + dev_dbg(dev->dev, "ALS is not enabled/detected\n"); /* get HPD data */ - ret = amd_get_sfh_info(&sfh_info, MT_HPD); - if (ret) - return ret; - - switch (sfh_info.user_present) { - case SFH_NOT_DETECTED: - in->ev_info.user_present = 0xff; /* assume no sensors connected */ - break; - case SFH_USER_PRESENT: - in->ev_info.user_present = 1; - break; - case SFH_USER_AWAY: - in->ev_info.user_present = 0; - break; + if (!amd_get_sfh_info(&sfh_info, MT_HPD)) { + if (sfh_info.user_present == SFH_USER_PRESENT) + in->ev_info.user_present = true; + } else { + dev_dbg(dev->dev, "HPD is not enabled/detected\n"); } - - return 0; } void amd_pmf_populate_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *in) diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c index 1ace711f7442e2..98ec30fce9fdd3 100644 --- a/drivers/platform/x86/ideapad-laptop.c +++ b/drivers/platform/x86/ideapad-laptop.c @@ -126,6 +126,7 @@ struct ideapad_rfk_priv { struct ideapad_private { struct acpi_device *adev; + struct mutex vpc_mutex; /* protects the VPC calls */ struct rfkill *rfk[IDEAPAD_RFKILL_DEV_NUM]; struct ideapad_rfk_priv rfk_priv[IDEAPAD_RFKILL_DEV_NUM]; struct platform_device *platform_device; @@ -146,6 +147,7 @@ struct ideapad_private { bool touchpad_ctrl_via_ec : 1; bool ctrl_ps2_aux_port : 1; bool usb_charging : 1; + bool ymc_ec_trigger : 1; } features; struct { bool initialized; @@ -194,6 +196,12 @@ MODULE_PARM_DESC(touchpad_ctrl_via_ec, "Enable registering a 'touchpad' sysfs-attribute which can be used to manually " "tell the EC to enable/disable the touchpad. This may not work on all models."); +static bool ymc_ec_trigger __read_mostly; +module_param(ymc_ec_trigger, bool, 0444); +MODULE_PARM_DESC(ymc_ec_trigger, + "Enable EC triggering work-around to force emitting tablet mode events. " + "If you need this please report this to: platform-driver-x86@vger.kernel.org"); + /* * shared data */ @@ -294,6 +302,8 @@ static int debugfs_status_show(struct seq_file *s, void *data) struct ideapad_private *priv = s->private; unsigned long value; + guard(mutex)(&priv->vpc_mutex); + if (!read_ec_data(priv->adev->handle, VPCCMD_R_BL_MAX, &value)) seq_printf(s, "Backlight max: %lu\n", value); if (!read_ec_data(priv->adev->handle, VPCCMD_R_BL, &value)) @@ -412,7 +422,8 @@ static ssize_t camera_power_show(struct device *dev, unsigned long result; int err; - err = read_ec_data(priv->adev->handle, VPCCMD_R_CAMERA, &result); + scoped_guard(mutex, &priv->vpc_mutex) + err = read_ec_data(priv->adev->handle, VPCCMD_R_CAMERA, &result); if (err) return err; @@ -431,7 +442,8 @@ static ssize_t camera_power_store(struct device *dev, if (err) return err; - err = write_ec_cmd(priv->adev->handle, VPCCMD_W_CAMERA, state); + scoped_guard(mutex, &priv->vpc_mutex) + err = write_ec_cmd(priv->adev->handle, VPCCMD_W_CAMERA, state); if (err) return err; @@ -484,7 +496,8 @@ static ssize_t fan_mode_show(struct device *dev, unsigned long result; int err; - err = read_ec_data(priv->adev->handle, VPCCMD_R_FAN, &result); + scoped_guard(mutex, &priv->vpc_mutex) + err = read_ec_data(priv->adev->handle, VPCCMD_R_FAN, &result); if (err) return err; @@ -506,7 +519,8 @@ static ssize_t fan_mode_store(struct device *dev, if (state > 4 || state == 3) return -EINVAL; - err = write_ec_cmd(priv->adev->handle, VPCCMD_W_FAN, state); + scoped_guard(mutex, &priv->vpc_mutex) + err = write_ec_cmd(priv->adev->handle, VPCCMD_W_FAN, state); if (err) return err; @@ -591,7 +605,8 @@ static ssize_t touchpad_show(struct device *dev, unsigned long result; int err; - err = read_ec_data(priv->adev->handle, VPCCMD_R_TOUCHPAD, &result); + scoped_guard(mutex, &priv->vpc_mutex) + err = read_ec_data(priv->adev->handle, VPCCMD_R_TOUCHPAD, &result); if (err) return err; @@ -612,7 +627,8 @@ static ssize_t touchpad_store(struct device *dev, if (err) return err; - err = write_ec_cmd(priv->adev->handle, VPCCMD_W_TOUCHPAD, state); + scoped_guard(mutex, &priv->vpc_mutex) + err = write_ec_cmd(priv->adev->handle, VPCCMD_W_TOUCHPAD, state); if (err) return err; @@ -1005,6 +1021,8 @@ static int ideapad_rfk_set(void *data, bool blocked) struct ideapad_rfk_priv *priv = data; int opcode = ideapad_rfk_data[priv->dev].opcode; + guard(mutex)(&priv->priv->vpc_mutex); + return write_ec_cmd(priv->priv->adev->handle, opcode, !blocked); } @@ -1018,6 +1036,8 @@ static void ideapad_sync_rfk_state(struct ideapad_private *priv) int i; if (priv->features.hw_rfkill_switch) { + guard(mutex)(&priv->vpc_mutex); + if (read_ec_data(priv->adev->handle, VPCCMD_R_RF, &hw_blocked)) return; hw_blocked = !hw_blocked; @@ -1191,8 +1211,9 @@ static void ideapad_input_novokey(struct ideapad_private *priv) { unsigned long long_pressed; - if (read_ec_data(priv->adev->handle, VPCCMD_R_NOVO, &long_pressed)) - return; + scoped_guard(mutex, &priv->vpc_mutex) + if (read_ec_data(priv->adev->handle, VPCCMD_R_NOVO, &long_pressed)) + return; if (long_pressed) ideapad_input_report(priv, 17); @@ -1204,8 +1225,9 @@ static void ideapad_check_special_buttons(struct ideapad_private *priv) { unsigned long bit, value; - if (read_ec_data(priv->adev->handle, VPCCMD_R_SPECIAL_BUTTONS, &value)) - return; + scoped_guard(mutex, &priv->vpc_mutex) + if (read_ec_data(priv->adev->handle, VPCCMD_R_SPECIAL_BUTTONS, &value)) + return; for_each_set_bit (bit, &value, 16) { switch (bit) { @@ -1238,6 +1260,8 @@ static int ideapad_backlight_get_brightness(struct backlight_device *blightdev) unsigned long now; int err; + guard(mutex)(&priv->vpc_mutex); + err = read_ec_data(priv->adev->handle, VPCCMD_R_BL, &now); if (err) return err; @@ -1250,6 +1274,8 @@ static int ideapad_backlight_update_status(struct backlight_device *blightdev) struct ideapad_private *priv = bl_get_data(blightdev); int err; + guard(mutex)(&priv->vpc_mutex); + err = write_ec_cmd(priv->adev->handle, VPCCMD_W_BL, blightdev->props.brightness); if (err) @@ -1327,6 +1353,8 @@ static void ideapad_backlight_notify_power(struct ideapad_private *priv) if (!blightdev) return; + guard(mutex)(&priv->vpc_mutex); + if (read_ec_data(priv->adev->handle, VPCCMD_R_BL_POWER, &power)) return; @@ -1339,7 +1367,8 @@ static void ideapad_backlight_notify_brightness(struct ideapad_private *priv) /* if we control brightness via acpi video driver */ if (!priv->blightdev) - read_ec_data(priv->adev->handle, VPCCMD_R_BL, &now); + scoped_guard(mutex, &priv->vpc_mutex) + read_ec_data(priv->adev->handle, VPCCMD_R_BL, &now); else backlight_force_update(priv->blightdev, BACKLIGHT_UPDATE_HOTKEY); } @@ -1564,7 +1593,8 @@ static void ideapad_sync_touchpad_state(struct ideapad_private *priv, bool send_ int ret; /* Without reading from EC touchpad LED doesn't switch state */ - ret = read_ec_data(priv->adev->handle, VPCCMD_R_TOUCHPAD, &value); + scoped_guard(mutex, &priv->vpc_mutex) + ret = read_ec_data(priv->adev->handle, VPCCMD_R_TOUCHPAD, &value); if (ret) return; @@ -1592,16 +1622,92 @@ static void ideapad_sync_touchpad_state(struct ideapad_private *priv, bool send_ priv->r_touchpad_val = value; } +static const struct dmi_system_id ymc_ec_trigger_quirk_dmi_table[] = { + { + /* Lenovo Yoga 7 14ARB7 */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "82QF"), + }, + }, + { + /* Lenovo Yoga 7 14ACN6 */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "82N7"), + }, + }, + { } +}; + +static void ideapad_laptop_trigger_ec(void) +{ + struct ideapad_private *priv; + int ret; + + guard(mutex)(&ideapad_shared_mutex); + + priv = ideapad_shared; + if (!priv) + return; + + if (!priv->features.ymc_ec_trigger) + return; + + scoped_guard(mutex, &priv->vpc_mutex) + ret = write_ec_cmd(priv->adev->handle, VPCCMD_W_YMC, 1); + if (ret) + dev_warn(&priv->platform_device->dev, "Could not write YMC: %d\n", ret); +} + +static int ideapad_laptop_nb_notify(struct notifier_block *nb, + unsigned long action, void *data) +{ + switch (action) { + case IDEAPAD_LAPTOP_YMC_EVENT: + ideapad_laptop_trigger_ec(); + break; + } + + return 0; +} + +static struct notifier_block ideapad_laptop_notifier = { + .notifier_call = ideapad_laptop_nb_notify, +}; + +static BLOCKING_NOTIFIER_HEAD(ideapad_laptop_chain_head); + +int ideapad_laptop_register_notifier(struct notifier_block *nb) +{ + return blocking_notifier_chain_register(&ideapad_laptop_chain_head, nb); +} +EXPORT_SYMBOL_NS_GPL(ideapad_laptop_register_notifier, IDEAPAD_LAPTOP); + +int ideapad_laptop_unregister_notifier(struct notifier_block *nb) +{ + return blocking_notifier_chain_unregister(&ideapad_laptop_chain_head, nb); +} +EXPORT_SYMBOL_NS_GPL(ideapad_laptop_unregister_notifier, IDEAPAD_LAPTOP); + +void ideapad_laptop_call_notifier(unsigned long action, void *data) +{ + blocking_notifier_call_chain(&ideapad_laptop_chain_head, action, data); +} +EXPORT_SYMBOL_NS_GPL(ideapad_laptop_call_notifier, IDEAPAD_LAPTOP); + static void ideapad_acpi_notify(acpi_handle handle, u32 event, void *data) { struct ideapad_private *priv = data; unsigned long vpc1, vpc2, bit; - if (read_ec_data(handle, VPCCMD_R_VPC1, &vpc1)) - return; + scoped_guard(mutex, &priv->vpc_mutex) { + if (read_ec_data(handle, VPCCMD_R_VPC1, &vpc1)) + return; - if (read_ec_data(handle, VPCCMD_R_VPC2, &vpc2)) - return; + if (read_ec_data(handle, VPCCMD_R_VPC2, &vpc2)) + return; + } vpc1 = (vpc2 << 8) | vpc1; @@ -1728,6 +1834,8 @@ static void ideapad_check_features(struct ideapad_private *priv) priv->features.ctrl_ps2_aux_port = ctrl_ps2_aux_port || dmi_check_system(ctrl_ps2_aux_port_list); priv->features.touchpad_ctrl_via_ec = touchpad_ctrl_via_ec; + priv->features.ymc_ec_trigger = + ymc_ec_trigger || dmi_check_system(ymc_ec_trigger_quirk_dmi_table); if (!read_ec_data(handle, VPCCMD_R_FAN, &val)) priv->features.fan_mode = true; @@ -1906,6 +2014,10 @@ static int ideapad_acpi_add(struct platform_device *pdev) priv->adev = adev; priv->platform_device = pdev; + err = devm_mutex_init(&pdev->dev, &priv->vpc_mutex); + if (err) + return err; + ideapad_check_features(priv); err = ideapad_sysfs_init(priv); @@ -1974,6 +2086,8 @@ static int ideapad_acpi_add(struct platform_device *pdev) if (err) goto shared_init_failed; + ideapad_laptop_register_notifier(&ideapad_laptop_notifier); + return 0; shared_init_failed: @@ -2006,6 +2120,8 @@ static void ideapad_acpi_remove(struct platform_device *pdev) struct ideapad_private *priv = dev_get_drvdata(&pdev->dev); int i; + ideapad_laptop_unregister_notifier(&ideapad_laptop_notifier); + ideapad_shared_exit(priv); acpi_remove_notify_handler(priv->adev->handle, diff --git a/drivers/platform/x86/ideapad-laptop.h b/drivers/platform/x86/ideapad-laptop.h index 4498a96de59769..948cc61800a950 100644 --- a/drivers/platform/x86/ideapad-laptop.h +++ b/drivers/platform/x86/ideapad-laptop.h @@ -12,6 +12,15 @@ #include #include #include +#include + +enum ideapad_laptop_notifier_actions { + IDEAPAD_LAPTOP_YMC_EVENT, +}; + +int ideapad_laptop_register_notifier(struct notifier_block *nb); +int ideapad_laptop_unregister_notifier(struct notifier_block *nb); +void ideapad_laptop_call_notifier(unsigned long action, void *data); enum { VPCCMD_R_VPC1 = 0x10, diff --git a/drivers/platform/x86/intel/ifs/runtest.c b/drivers/platform/x86/intel/ifs/runtest.c index 282e4bfe30da32..be3d51ed0e4740 100644 --- a/drivers/platform/x86/intel/ifs/runtest.c +++ b/drivers/platform/x86/intel/ifs/runtest.c @@ -221,8 +221,8 @@ static int doscan(void *data) */ static void ifs_test_core(int cpu, struct device *dev) { + union ifs_status status = {}; union ifs_scan activate; - union ifs_status status; unsigned long timeout; struct ifs_data *ifsd; int to_start, to_stop; diff --git a/drivers/platform/x86/intel/vbtn.c b/drivers/platform/x86/intel/vbtn.c index 9b7ce03ba085c2..a353e830b65fd1 100644 --- a/drivers/platform/x86/intel/vbtn.c +++ b/drivers/platform/x86/intel/vbtn.c @@ -7,11 +7,13 @@ */ #include +#include #include #include #include #include #include +#include #include #include #include "../dual_accel_detect.h" @@ -66,6 +68,7 @@ static const struct key_entry intel_vbtn_switchmap[] = { }; struct intel_vbtn_priv { + struct mutex mutex; /* Avoid notify_handler() racing with itself */ struct input_dev *buttons_dev; struct input_dev *switches_dev; bool dual_accel; @@ -155,6 +158,8 @@ static void notify_handler(acpi_handle handle, u32 event, void *context) bool autorelease; int ret; + guard(mutex)(&priv->mutex); + if ((ke = sparse_keymap_entry_from_scancode(priv->buttons_dev, event))) { if (!priv->has_buttons) { dev_warn(&device->dev, "Warning: received 0x%02x button event on a device without buttons, please report this.\n", @@ -290,6 +295,10 @@ static int intel_vbtn_probe(struct platform_device *device) return -ENOMEM; dev_set_drvdata(&device->dev, priv); + err = devm_mutex_init(&device->dev, &priv->mutex); + if (err) + return err; + priv->dual_accel = dual_accel; priv->has_buttons = has_buttons; priv->has_switches = has_switches; diff --git a/drivers/platform/x86/lenovo-ymc.c b/drivers/platform/x86/lenovo-ymc.c index e1fbc35504d498..e0bbd6a14a89cb 100644 --- a/drivers/platform/x86/lenovo-ymc.c +++ b/drivers/platform/x86/lenovo-ymc.c @@ -20,32 +20,10 @@ #define LENOVO_YMC_QUERY_INSTANCE 0 #define LENOVO_YMC_QUERY_METHOD 0x01 -static bool ec_trigger __read_mostly; -module_param(ec_trigger, bool, 0444); -MODULE_PARM_DESC(ec_trigger, "Enable EC triggering work-around to force emitting tablet mode events"); - static bool force; module_param(force, bool, 0444); MODULE_PARM_DESC(force, "Force loading on boards without a convertible DMI chassis-type"); -static const struct dmi_system_id ec_trigger_quirk_dmi_table[] = { - { - /* Lenovo Yoga 7 14ARB7 */ - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_NAME, "82QF"), - }, - }, - { - /* Lenovo Yoga 7 14ACN6 */ - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_NAME, "82N7"), - }, - }, - { } -}; - static const struct dmi_system_id allowed_chasis_types_dmi_table[] = { { .matches = { @@ -62,21 +40,8 @@ static const struct dmi_system_id allowed_chasis_types_dmi_table[] = { struct lenovo_ymc_private { struct input_dev *input_dev; - struct acpi_device *ec_acpi_dev; }; -static void lenovo_ymc_trigger_ec(struct wmi_device *wdev, struct lenovo_ymc_private *priv) -{ - int err; - - if (!priv->ec_acpi_dev) - return; - - err = write_ec_cmd(priv->ec_acpi_dev->handle, VPCCMD_W_YMC, 1); - if (err) - dev_warn(&wdev->dev, "Could not write YMC: %d\n", err); -} - static const struct key_entry lenovo_ymc_keymap[] = { /* Laptop */ { KE_SW, 0x01, { .sw = { SW_TABLET_MODE, 0 } } }, @@ -125,11 +90,9 @@ static void lenovo_ymc_notify(struct wmi_device *wdev, union acpi_object *data) free_obj: kfree(obj); - lenovo_ymc_trigger_ec(wdev, priv); + ideapad_laptop_call_notifier(IDEAPAD_LAPTOP_YMC_EVENT, &code); } -static void acpi_dev_put_helper(void *p) { acpi_dev_put(p); } - static int lenovo_ymc_probe(struct wmi_device *wdev, const void *ctx) { struct lenovo_ymc_private *priv; @@ -143,29 +106,10 @@ static int lenovo_ymc_probe(struct wmi_device *wdev, const void *ctx) return -ENODEV; } - ec_trigger |= dmi_check_system(ec_trigger_quirk_dmi_table); - priv = devm_kzalloc(&wdev->dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; - if (ec_trigger) { - pr_debug("Lenovo YMC enable EC triggering.\n"); - priv->ec_acpi_dev = acpi_dev_get_first_match_dev("VPC2004", NULL, -1); - - if (!priv->ec_acpi_dev) { - dev_err(&wdev->dev, "Could not find EC ACPI device.\n"); - return -ENODEV; - } - err = devm_add_action_or_reset(&wdev->dev, - acpi_dev_put_helper, priv->ec_acpi_dev); - if (err) { - dev_err(&wdev->dev, - "Could not clean up EC ACPI device: %d\n", err); - return err; - } - } - input_dev = devm_input_allocate_device(&wdev->dev); if (!input_dev) return -ENOMEM; @@ -192,7 +136,6 @@ static int lenovo_ymc_probe(struct wmi_device *wdev, const void *ctx) dev_set_drvdata(&wdev->dev, priv); /* Report the state for the first time on probe */ - lenovo_ymc_trigger_ec(wdev, priv); lenovo_ymc_notify(wdev, NULL); return 0; } @@ -217,3 +160,4 @@ module_wmi_driver(lenovo_ymc_driver); MODULE_AUTHOR("Gergo Koteles "); MODULE_DESCRIPTION("Lenovo Yoga Mode Control driver"); MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS(IDEAPAD_LAPTOP); diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index 3e94fdd1ea52e0..3197aaa69da73d 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c @@ -757,7 +757,6 @@ static union acpi_object *__call_snc_method(acpi_handle handle, char *method, return result; } -#define MIN(a, b) (a > b ? b : a) static int sony_nc_buffer_call(acpi_handle handle, char *name, u64 *value, void *buffer, size_t buflen) { diff --git a/drivers/power/supply/axp288_charger.c b/drivers/power/supply/axp288_charger.c index b5903193e2f96d..ac05942e4e6ac1 100644 --- a/drivers/power/supply/axp288_charger.c +++ b/drivers/power/supply/axp288_charger.c @@ -178,18 +178,18 @@ static inline int axp288_charger_set_cv(struct axp288_chrg_info *info, int cv) u8 reg_val; int ret; - if (cv <= CV_4100MV) { - reg_val = CHRG_CCCV_CV_4100MV; - cv = CV_4100MV; - } else if (cv <= CV_4150MV) { - reg_val = CHRG_CCCV_CV_4150MV; - cv = CV_4150MV; - } else if (cv <= CV_4200MV) { + if (cv >= CV_4350MV) { + reg_val = CHRG_CCCV_CV_4350MV; + cv = CV_4350MV; + } else if (cv >= CV_4200MV) { reg_val = CHRG_CCCV_CV_4200MV; cv = CV_4200MV; + } else if (cv >= CV_4150MV) { + reg_val = CHRG_CCCV_CV_4150MV; + cv = CV_4150MV; } else { - reg_val = CHRG_CCCV_CV_4350MV; - cv = CV_4350MV; + reg_val = CHRG_CCCV_CV_4100MV; + cv = CV_4100MV; } reg_val = reg_val << CHRG_CCCV_CV_BIT_POS; @@ -337,8 +337,8 @@ static int axp288_charger_usb_set_property(struct power_supply *psy, } break; case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE: - scaled_val = min(val->intval, info->max_cv); - scaled_val = DIV_ROUND_CLOSEST(scaled_val, 1000); + scaled_val = DIV_ROUND_CLOSEST(val->intval, 1000); + scaled_val = min(scaled_val, info->max_cv); ret = axp288_charger_set_cv(info, scaled_val); if (ret < 0) { dev_warn(&info->pdev->dev, "set charge voltage failed\n"); diff --git a/drivers/power/supply/qcom_battmgr.c b/drivers/power/supply/qcom_battmgr.c index 46f36dcb185c36..49bef4a5ac3f3e 100644 --- a/drivers/power/supply/qcom_battmgr.c +++ b/drivers/power/supply/qcom_battmgr.c @@ -486,7 +486,7 @@ static int qcom_battmgr_bat_get_property(struct power_supply *psy, int ret; if (!battmgr->service_up) - return -ENODEV; + return -EAGAIN; if (battmgr->variant == QCOM_BATTMGR_SC8280XP) ret = qcom_battmgr_bat_sc8280xp_update(battmgr, psp); @@ -683,7 +683,7 @@ static int qcom_battmgr_ac_get_property(struct power_supply *psy, int ret; if (!battmgr->service_up) - return -ENODEV; + return -EAGAIN; ret = qcom_battmgr_bat_sc8280xp_update(battmgr, psp); if (ret) @@ -748,7 +748,7 @@ static int qcom_battmgr_usb_get_property(struct power_supply *psy, int ret; if (!battmgr->service_up) - return -ENODEV; + return -EAGAIN; if (battmgr->variant == QCOM_BATTMGR_SC8280XP) ret = qcom_battmgr_bat_sc8280xp_update(battmgr, psp); @@ -867,7 +867,7 @@ static int qcom_battmgr_wls_get_property(struct power_supply *psy, int ret; if (!battmgr->service_up) - return -ENODEV; + return -EAGAIN; if (battmgr->variant == QCOM_BATTMGR_SC8280XP) ret = qcom_battmgr_bat_sc8280xp_update(battmgr, psp); @@ -1007,7 +1007,9 @@ static void qcom_battmgr_sc8280xp_callback(struct qcom_battmgr *battmgr, battmgr->error = 0; break; case BATTMGR_BAT_INFO: - if (payload_len != sizeof(resp->info)) { + /* some firmware versions report an extra __le32 at the end of the payload */ + if (payload_len != sizeof(resp->info) && + payload_len != (sizeof(resp->info) + sizeof(__le32))) { dev_warn(battmgr->dev, "invalid payload length for battery information request: %zd\n", payload_len); diff --git a/drivers/power/supply/rt5033_battery.c b/drivers/power/supply/rt5033_battery.c index 32eafe2c00af51..7a27b262fb84a7 100644 --- a/drivers/power/supply/rt5033_battery.c +++ b/drivers/power/supply/rt5033_battery.c @@ -159,6 +159,7 @@ static int rt5033_battery_probe(struct i2c_client *client) return -EINVAL; } + i2c_set_clientdata(client, battery); psy_cfg.of_node = client->dev.of_node; psy_cfg.drv_data = battery; diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index 0a97cfedd7060a..42a4a996defbe1 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -1601,9 +1601,15 @@ static int dasd_ese_needs_format(struct dasd_block *block, struct irb *irb) if (!sense) return 0; - return !!(sense[1] & SNS1_NO_REC_FOUND) || - !!(sense[1] & SNS1_FILE_PROTECTED) || - scsw_cstat(&irb->scsw) == SCHN_STAT_INCORR_LEN; + if (sense[1] & SNS1_NO_REC_FOUND) + return 1; + + if ((sense[1] & SNS1_INV_TRACK_FORMAT) && + scsw_is_tm(&irb->scsw) && + !(sense[2] & SNS2_ENV_DATA_PRESENT)) + return 1; + + return 0; } static int dasd_ese_oos_cond(u8 *sense) @@ -1624,7 +1630,7 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm, struct dasd_device *device; unsigned long now; int nrf_suppressed = 0; - int fp_suppressed = 0; + int it_suppressed = 0; struct request *req; u8 *sense = NULL; int expires; @@ -1679,8 +1685,9 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm, */ sense = dasd_get_sense(irb); if (sense) { - fp_suppressed = (sense[1] & SNS1_FILE_PROTECTED) && - test_bit(DASD_CQR_SUPPRESS_FP, &cqr->flags); + it_suppressed = (sense[1] & SNS1_INV_TRACK_FORMAT) && + !(sense[2] & SNS2_ENV_DATA_PRESENT) && + test_bit(DASD_CQR_SUPPRESS_IT, &cqr->flags); nrf_suppressed = (sense[1] & SNS1_NO_REC_FOUND) && test_bit(DASD_CQR_SUPPRESS_NRF, &cqr->flags); @@ -1695,7 +1702,7 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm, return; } } - if (!(fp_suppressed || nrf_suppressed)) + if (!(it_suppressed || nrf_suppressed)) device->discipline->dump_sense_dbf(device, irb, "int"); if (device->features & DASD_FEATURE_ERPLOG) @@ -2459,14 +2466,17 @@ static int _dasd_sleep_on_queue(struct list_head *ccw_queue, int interruptible) rc = 0; list_for_each_entry_safe(cqr, n, ccw_queue, blocklist) { /* - * In some cases the 'File Protected' or 'Incorrect Length' - * error might be expected and error recovery would be - * unnecessary in these cases. Check if the according suppress - * bit is set. + * In some cases certain errors might be expected and + * error recovery would be unnecessary in these cases. + * Check if the according suppress bit is set. */ sense = dasd_get_sense(&cqr->irb); - if (sense && sense[1] & SNS1_FILE_PROTECTED && - test_bit(DASD_CQR_SUPPRESS_FP, &cqr->flags)) + if (sense && (sense[1] & SNS1_INV_TRACK_FORMAT) && + !(sense[2] & SNS2_ENV_DATA_PRESENT) && + test_bit(DASD_CQR_SUPPRESS_IT, &cqr->flags)) + continue; + if (sense && (sense[1] & SNS1_NO_REC_FOUND) && + test_bit(DASD_CQR_SUPPRESS_NRF, &cqr->flags)) continue; if (scsw_cstat(&cqr->irb.scsw) == 0x40 && test_bit(DASD_CQR_SUPPRESS_IL, &cqr->flags)) diff --git a/drivers/s390/block/dasd_3990_erp.c b/drivers/s390/block/dasd_3990_erp.c index bbbacfc386f28d..d0aa267462c50a 100644 --- a/drivers/s390/block/dasd_3990_erp.c +++ b/drivers/s390/block/dasd_3990_erp.c @@ -1386,14 +1386,8 @@ dasd_3990_erp_file_prot(struct dasd_ccw_req * erp) struct dasd_device *device = erp->startdev; - /* - * In some cases the 'File Protected' error might be expected and - * log messages shouldn't be written then. - * Check if the according suppress bit is set. - */ - if (!test_bit(DASD_CQR_SUPPRESS_FP, &erp->flags)) - dev_err(&device->cdev->dev, - "Accessing the DASD failed because of a hardware error\n"); + dev_err(&device->cdev->dev, + "Accessing the DASD failed because of a hardware error\n"); return dasd_3990_erp_cleanup(erp, DASD_CQR_FAILED); diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index 9388b5c383cab8..90b106408992d0 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c @@ -2275,6 +2275,7 @@ dasd_eckd_analysis_ccw(struct dasd_device *device) cqr->status = DASD_CQR_FILLED; /* Set flags to suppress output for expected errors */ set_bit(DASD_CQR_SUPPRESS_NRF, &cqr->flags); + set_bit(DASD_CQR_SUPPRESS_IT, &cqr->flags); return cqr; } @@ -2556,7 +2557,6 @@ dasd_eckd_build_check_tcw(struct dasd_device *base, struct format_data_t *fdata, cqr->buildclk = get_tod_clock(); cqr->status = DASD_CQR_FILLED; /* Set flags to suppress output for expected errors */ - set_bit(DASD_CQR_SUPPRESS_FP, &cqr->flags); set_bit(DASD_CQR_SUPPRESS_IL, &cqr->flags); return cqr; @@ -4130,8 +4130,6 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_cmd_single( /* Set flags to suppress output for expected errors */ if (dasd_eckd_is_ese(basedev)) { - set_bit(DASD_CQR_SUPPRESS_FP, &cqr->flags); - set_bit(DASD_CQR_SUPPRESS_IL, &cqr->flags); set_bit(DASD_CQR_SUPPRESS_NRF, &cqr->flags); } @@ -4633,9 +4631,8 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_tpm_track( /* Set flags to suppress output for expected errors */ if (dasd_eckd_is_ese(basedev)) { - set_bit(DASD_CQR_SUPPRESS_FP, &cqr->flags); - set_bit(DASD_CQR_SUPPRESS_IL, &cqr->flags); set_bit(DASD_CQR_SUPPRESS_NRF, &cqr->flags); + set_bit(DASD_CQR_SUPPRESS_IT, &cqr->flags); } return cqr; @@ -5780,36 +5777,32 @@ static void dasd_eckd_dump_sense(struct dasd_device *device, { u8 *sense = dasd_get_sense(irb); - if (scsw_is_tm(&irb->scsw)) { - /* - * In some cases the 'File Protected' or 'Incorrect Length' - * error might be expected and log messages shouldn't be written - * then. Check if the according suppress bit is set. - */ - if (sense && (sense[1] & SNS1_FILE_PROTECTED) && - test_bit(DASD_CQR_SUPPRESS_FP, &req->flags)) - return; - if (scsw_cstat(&irb->scsw) == 0x40 && - test_bit(DASD_CQR_SUPPRESS_IL, &req->flags)) - return; + /* + * In some cases certain errors might be expected and + * log messages shouldn't be written then. + * Check if the according suppress bit is set. + */ + if (sense && (sense[1] & SNS1_INV_TRACK_FORMAT) && + !(sense[2] & SNS2_ENV_DATA_PRESENT) && + test_bit(DASD_CQR_SUPPRESS_IT, &req->flags)) + return; - dasd_eckd_dump_sense_tcw(device, req, irb); - } else { - /* - * In some cases the 'Command Reject' or 'No Record Found' - * error might be expected and log messages shouldn't be - * written then. Check if the according suppress bit is set. - */ - if (sense && sense[0] & SNS0_CMD_REJECT && - test_bit(DASD_CQR_SUPPRESS_CR, &req->flags)) - return; + if (sense && sense[0] & SNS0_CMD_REJECT && + test_bit(DASD_CQR_SUPPRESS_CR, &req->flags)) + return; - if (sense && sense[1] & SNS1_NO_REC_FOUND && - test_bit(DASD_CQR_SUPPRESS_NRF, &req->flags)) - return; + if (sense && sense[1] & SNS1_NO_REC_FOUND && + test_bit(DASD_CQR_SUPPRESS_NRF, &req->flags)) + return; + if (scsw_cstat(&irb->scsw) == 0x40 && + test_bit(DASD_CQR_SUPPRESS_IL, &req->flags)) + return; + + if (scsw_is_tm(&irb->scsw)) + dasd_eckd_dump_sense_tcw(device, req, irb); + else dasd_eckd_dump_sense_ccw(device, req, irb); - } } static int dasd_eckd_reload_device(struct dasd_device *device) diff --git a/drivers/s390/block/dasd_genhd.c b/drivers/s390/block/dasd_genhd.c index 1aa426b1deddc7..6da47a65af610f 100644 --- a/drivers/s390/block/dasd_genhd.c +++ b/drivers/s390/block/dasd_genhd.c @@ -41,7 +41,6 @@ int dasd_gendisk_alloc(struct dasd_block *block) */ .max_segment_size = PAGE_SIZE, .seg_boundary_mask = PAGE_SIZE - 1, - .dma_alignment = PAGE_SIZE - 1, .max_segments = USHRT_MAX, }; struct gendisk *gdp; diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h index e5f40536b42540..81cfb5c89681bc 100644 --- a/drivers/s390/block/dasd_int.h +++ b/drivers/s390/block/dasd_int.h @@ -196,7 +196,7 @@ struct dasd_ccw_req { * The following flags are used to suppress output of certain errors. */ #define DASD_CQR_SUPPRESS_NRF 4 /* Suppress 'No Record Found' error */ -#define DASD_CQR_SUPPRESS_FP 5 /* Suppress 'File Protected' error*/ +#define DASD_CQR_SUPPRESS_IT 5 /* Suppress 'Invalid Track' error*/ #define DASD_CQR_SUPPRESS_IL 6 /* Suppress 'Incorrect Length' error */ #define DASD_CQR_SUPPRESS_CR 7 /* Suppress 'Command Reject' error */ diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c index b72f672a7720a6..66b1bdc6328443 100644 --- a/drivers/s390/cio/ccwgroup.c +++ b/drivers/s390/cio/ccwgroup.c @@ -550,4 +550,5 @@ void ccwgroup_remove_ccwdev(struct ccw_device *cdev) put_device(&gdev->dev); } EXPORT_SYMBOL(ccwgroup_remove_ccwdev); +MODULE_DESCRIPTION("ccwgroup bus driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/s390/cio/vfio_ccw_drv.c b/drivers/s390/cio/vfio_ccw_drv.c index 8ad49030a7bf30..914dde0416753f 100644 --- a/drivers/s390/cio/vfio_ccw_drv.c +++ b/drivers/s390/cio/vfio_ccw_drv.c @@ -488,4 +488,5 @@ static void __exit vfio_ccw_sch_exit(void) module_init(vfio_ccw_sch_init); module_exit(vfio_ccw_sch_exit); +MODULE_DESCRIPTION("VFIO based Subchannel device driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c index d31884f82f2ad5..73085d2f5c4344 100644 --- a/drivers/scsi/isci/init.c +++ b/drivers/scsi/isci/init.c @@ -65,11 +65,7 @@ #include "task.h" #include "probe_roms.h" -#define MAJ 1 -#define MIN 2 -#define BUILD 0 -#define DRV_VERSION __stringify(MAJ) "." __stringify(MIN) "." \ - __stringify(BUILD) +#define DRV_VERSION "1.2.0" MODULE_VERSION(DRV_VERSION); diff --git a/drivers/scsi/mpi3mr/mpi3mr_app.c b/drivers/scsi/mpi3mr/mpi3mr_app.c index 8b0eded6ef36e5..01f035f9330e4b 100644 --- a/drivers/scsi/mpi3mr/mpi3mr_app.c +++ b/drivers/scsi/mpi3mr/mpi3mr_app.c @@ -100,7 +100,8 @@ void mpi3mr_alloc_diag_bufs(struct mpi3mr_ioc *mrioc) dprint_init(mrioc, "trying to allocate trace diag buffer of size = %dKB\n", trace_size / 1024); - if (mpi3mr_alloc_trace_buffer(mrioc, trace_size)) { + if (get_order(trace_size) > MAX_PAGE_ORDER || + mpi3mr_alloc_trace_buffer(mrioc, trace_size)) { retry = true; trace_size -= trace_dec_size; dprint_init(mrioc, "trace diag buffer allocation failed\n" @@ -118,8 +119,12 @@ void mpi3mr_alloc_diag_bufs(struct mpi3mr_ioc *mrioc) diag_buffer->type = MPI3_DIAG_BUFFER_TYPE_FW; diag_buffer->status = MPI3MR_HDB_BUFSTATUS_NOT_ALLOCATED; if ((mrioc->facts.diag_fw_sz < fw_size) && (fw_size >= fw_min_size)) { - diag_buffer->addr = dma_alloc_coherent(&mrioc->pdev->dev, - fw_size, &diag_buffer->dma_addr, GFP_KERNEL); + if (get_order(fw_size) <= MAX_PAGE_ORDER) { + diag_buffer->addr + = dma_alloc_coherent(&mrioc->pdev->dev, fw_size, + &diag_buffer->dma_addr, + GFP_KERNEL); + } if (!retry) dprint_init(mrioc, "%s:trying to allocate firmware diag buffer of size = %dKB\n", diff --git a/drivers/scsi/mpi3mr/mpi3mr_os.c b/drivers/scsi/mpi3mr/mpi3mr_os.c index 69b14918de59ea..616894571c6abe 100644 --- a/drivers/scsi/mpi3mr/mpi3mr_os.c +++ b/drivers/scsi/mpi3mr/mpi3mr_os.c @@ -3575,6 +3575,17 @@ static int mpi3mr_prepare_sg_scmd(struct mpi3mr_ioc *mrioc, scmd->sc_data_direction); priv->meta_sg_valid = 1; /* To unmap meta sg DMA */ } else { + /* + * Some firmware versions byte-swap the REPORT ZONES command + * reply from ATA-ZAC devices by directly accessing in the host + * buffer. This does not respect the default command DMA + * direction and causes IOMMU page faults on some architectures + * with an IOMMU enforcing write mappings (e.g. AMD hosts). + * Avoid such issue by making the REPORT ZONES buffer mapping + * bi-directional. + */ + if (scmd->cmnd[0] == ZBC_IN && scmd->cmnd[1] == ZI_REPORT_ZONES) + scmd->sc_data_direction = DMA_BIDIRECTIONAL; sg_scmd = scsi_sglist(scmd); sges_left = scsi_dma_map(scmd); } @@ -5223,6 +5234,7 @@ mpi3mr_probe(struct pci_dev *pdev, const struct pci_device_id *id) spin_lock_init(&mrioc->watchdog_lock); spin_lock_init(&mrioc->chain_buf_lock); spin_lock_init(&mrioc->sas_node_lock); + spin_lock_init(&mrioc->trigger_lock); INIT_LIST_HEAD(&mrioc->fwevt_list); INIT_LIST_HEAD(&mrioc->tgtdev_list); diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c index b2bcf4a27ddcde..b785a7e88b498c 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.c +++ b/drivers/scsi/mpt3sas/mpt3sas_base.c @@ -2671,6 +2671,22 @@ _base_build_zero_len_sge_ieee(struct MPT3SAS_ADAPTER *ioc, void *paddr) _base_add_sg_single_ieee(paddr, sgl_flags, 0, 0, -1); } +static inline int _base_scsi_dma_map(struct scsi_cmnd *cmd) +{ + /* + * Some firmware versions byte-swap the REPORT ZONES command reply from + * ATA-ZAC devices by directly accessing in the host buffer. This does + * not respect the default command DMA direction and causes IOMMU page + * faults on some architectures with an IOMMU enforcing write mappings + * (e.g. AMD hosts). Avoid such issue by making the report zones buffer + * mapping bi-directional. + */ + if (cmd->cmnd[0] == ZBC_IN && cmd->cmnd[1] == ZI_REPORT_ZONES) + cmd->sc_data_direction = DMA_BIDIRECTIONAL; + + return scsi_dma_map(cmd); +} + /** * _base_build_sg_scmd - main sg creation routine * pcie_device is unused here! @@ -2717,7 +2733,7 @@ _base_build_sg_scmd(struct MPT3SAS_ADAPTER *ioc, sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT; sg_scmd = scsi_sglist(scmd); - sges_left = scsi_dma_map(scmd); + sges_left = _base_scsi_dma_map(scmd); if (sges_left < 0) return -ENOMEM; @@ -2861,7 +2877,7 @@ _base_build_sg_scmd_ieee(struct MPT3SAS_ADAPTER *ioc, } sg_scmd = scsi_sglist(scmd); - sges_left = scsi_dma_map(scmd); + sges_left = _base_scsi_dma_map(scmd); if (sges_left < 0) return -ENOMEM; diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index adeaa8ab995167..699f4f9674d98f 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -2711,8 +2711,6 @@ static int read_capacity_16(struct scsi_disk *sdkp, struct scsi_device *sdp, if (buffer[14] & 0x40) /* LBPRZ */ sdkp->lbprz = 1; - - sd_config_discard(sdkp, lim, SD_LBP_WS16); } sdkp->capacity = lba + 1; @@ -3365,8 +3363,6 @@ static void sd_read_block_limits(struct scsi_disk *sdkp, sdkp->unmap_alignment = get_unaligned_be32(&vpd->data[32]) & ~(1 << 31); - sd_config_discard(sdkp, lim, sd_discard_mode(sdkp)); - config_atomic: sdkp->max_atomic = get_unaligned_be32(&vpd->data[44]); sdkp->atomic_alignment = get_unaligned_be32(&vpd->data[48]); @@ -3753,9 +3749,10 @@ static int sd_revalidate_disk(struct gendisk *disk) sd_read_block_limits_ext(sdkp); sd_read_block_characteristics(sdkp, &lim); sd_zbc_read_zones(sdkp, &lim, buffer); - sd_read_cpr(sdkp); } + sd_config_discard(sdkp, &lim, sd_discard_mode(sdkp)); + sd_print_capacity(sdkp, old_capacity); sd_read_write_protect_flag(sdkp, buffer); @@ -3808,6 +3805,14 @@ static int sd_revalidate_disk(struct gendisk *disk) if (err) return err; + /* + * Query concurrent positioning ranges after + * queue_limits_commit_update() unlocked q->limits_lock to avoid + * deadlock with q->sysfs_dir_lock and q->sysfs_lock. + */ + if (sdkp->media_present && scsi_device_supports_vpd(sdp)) + sd_read_cpr(sdkp); + /* * For a zoned drive, revalidating the zones can be done only once * the gendisk capacity is set. So if this fails, set back the gendisk @@ -4205,6 +4210,8 @@ static int sd_resume(struct device *dev) { struct scsi_disk *sdkp = dev_get_drvdata(dev); + sd_printk(KERN_NOTICE, sdkp, "Starting disk\n"); + if (opal_unlock_from_suspend(sdkp->opal_dev)) { sd_printk(KERN_NOTICE, sdkp, "OPAL unlock failed\n"); return -EIO; @@ -4221,13 +4228,12 @@ static int sd_resume_common(struct device *dev, bool runtime) if (!sdkp) /* E.g.: runtime resume at the start of sd_probe() */ return 0; - sd_printk(KERN_NOTICE, sdkp, "Starting disk\n"); - if (!sd_do_start_stop(sdkp->device, runtime)) { sdkp->suspended = false; return 0; } + sd_printk(KERN_NOTICE, sdkp, "Starting disk\n"); ret = sd_start_stop_device(sdkp, 1); if (!ret) { sd_resume(dev); diff --git a/drivers/scsi/sr_ioctl.c b/drivers/scsi/sr_ioctl.c index a0d2556a27bba3..089653018d32c1 100644 --- a/drivers/scsi/sr_ioctl.c +++ b/drivers/scsi/sr_ioctl.c @@ -431,7 +431,7 @@ int sr_select_speed(struct cdrom_device_info *cdi, unsigned long speed) struct packet_command cgc; /* avoid exceeding the max speed or overflowing integer bounds */ - speed = clamp(0, speed, 0xffff / 177); + speed = clamp(speed, 0, 0xffff / 177); if (speed == 0) speed = 0xffff; /* set to max */ diff --git a/drivers/soc/fsl/qbman/qman.c b/drivers/soc/fsl/qbman/qman.c index 7e9074519ad22d..4dc8aba33d9b70 100644 --- a/drivers/soc/fsl/qbman/qman.c +++ b/drivers/soc/fsl/qbman/qman.c @@ -2546,11 +2546,6 @@ int qman_delete_cgr(struct qman_cgr *cgr) } EXPORT_SYMBOL(qman_delete_cgr); -struct cgr_comp { - struct qman_cgr *cgr; - struct completion completion; -}; - static void qman_delete_cgr_smp_call(void *p) { qman_delete_cgr((struct qman_cgr *)p); diff --git a/drivers/spi/spi-fsl-lpspi.c b/drivers/spi/spi-fsl-lpspi.c index 32baa14dfd83e5..be261ac09df823 100644 --- a/drivers/spi/spi-fsl-lpspi.c +++ b/drivers/spi/spi-fsl-lpspi.c @@ -296,7 +296,7 @@ static void fsl_lpspi_set_watermark(struct fsl_lpspi_data *fsl_lpspi) static int fsl_lpspi_set_bitrate(struct fsl_lpspi_data *fsl_lpspi) { struct lpspi_config config = fsl_lpspi->config; - unsigned int perclk_rate, scldiv; + unsigned int perclk_rate, scldiv, div; u8 prescale; perclk_rate = clk_get_rate(fsl_lpspi->clk_per); @@ -313,8 +313,10 @@ static int fsl_lpspi_set_bitrate(struct fsl_lpspi_data *fsl_lpspi) return -EINVAL; } + div = DIV_ROUND_UP(perclk_rate, config.speed_hz); + for (prescale = 0; prescale < 8; prescale++) { - scldiv = perclk_rate / config.speed_hz / (1 << prescale) - 2; + scldiv = div / (1 << prescale) - 2; if (scldiv < 256) { fsl_lpspi->config.prescale = prescale; break; diff --git a/drivers/spi/spi-hisi-kunpeng.c b/drivers/spi/spi-hisi-kunpeng.c index 77e9738e42f60e..16054695bdb04a 100644 --- a/drivers/spi/spi-hisi-kunpeng.c +++ b/drivers/spi/spi-hisi-kunpeng.c @@ -481,6 +481,9 @@ static int hisi_spi_probe(struct platform_device *pdev) return -EINVAL; } + if (host->max_speed_hz == 0) + return dev_err_probe(dev, -EINVAL, "spi-max-frequency can't be 0\n"); + ret = device_property_read_u16(dev, "num-cs", &host->num_chipselect); if (ret) @@ -495,6 +498,7 @@ static int hisi_spi_probe(struct platform_device *pdev) host->transfer_one = hisi_spi_transfer_one; host->handle_err = hisi_spi_handle_err; host->dev.fwnode = dev->fwnode; + host->min_speed_hz = DIV_ROUND_UP(host->max_speed_hz, CLK_DIV_MAX); hisi_spi_hw_init(hs); diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c index 05e6d007f9a7f6..5304728c68c20d 100644 --- a/drivers/spi/spidev.c +++ b/drivers/spi/spidev.c @@ -700,6 +700,7 @@ static const struct class spidev_class = { }; static const struct spi_device_id spidev_spi_ids[] = { + { .name = "bh2228fv" }, { .name = "dh2228fv" }, { .name = "ltc2488" }, { .name = "sx1301" }, diff --git a/drivers/spmi/spmi-pmic-arb.c b/drivers/spmi/spmi-pmic-arb.c index f240fcc5a4e14a..9ba9495fcc4bae 100644 --- a/drivers/spmi/spmi-pmic-arb.c +++ b/drivers/spmi/spmi-pmic-arb.c @@ -398,7 +398,7 @@ static int pmic_arb_fmt_read_cmd(struct spmi_pmic_arb_bus *bus, u8 opc, u8 sid, *offset = rc; if (bc >= PMIC_ARB_MAX_TRANS_BYTES) { - dev_err(&bus->spmic->dev, "pmic-arb supports 1..%d bytes per trans, but:%zu requested", + dev_err(&bus->spmic->dev, "pmic-arb supports 1..%d bytes per trans, but:%zu requested\n", PMIC_ARB_MAX_TRANS_BYTES, len); return -EINVAL; } @@ -477,7 +477,7 @@ static int pmic_arb_fmt_write_cmd(struct spmi_pmic_arb_bus *bus, u8 opc, *offset = rc; if (bc >= PMIC_ARB_MAX_TRANS_BYTES) { - dev_err(&bus->spmic->dev, "pmic-arb supports 1..%d bytes per trans, but:%zu requested", + dev_err(&bus->spmic->dev, "pmic-arb supports 1..%d bytes per trans, but:%zu requested\n", PMIC_ARB_MAX_TRANS_BYTES, len); return -EINVAL; } @@ -1702,7 +1702,7 @@ static int spmi_pmic_arb_bus_init(struct platform_device *pdev, index = of_property_match_string(node, "reg-names", "cnfg"); if (index < 0) { - dev_err(dev, "cnfg reg region missing"); + dev_err(dev, "cnfg reg region missing\n"); return -EINVAL; } @@ -1712,7 +1712,7 @@ static int spmi_pmic_arb_bus_init(struct platform_device *pdev, index = of_property_match_string(node, "reg-names", "intr"); if (index < 0) { - dev_err(dev, "intr reg region missing"); + dev_err(dev, "intr reg region missing\n"); return -EINVAL; } @@ -1737,8 +1737,7 @@ static int spmi_pmic_arb_bus_init(struct platform_device *pdev, dev_dbg(&pdev->dev, "adding irq domain for bus %d\n", bus_index); - bus->domain = irq_domain_add_tree(dev->of_node, - &pmic_arb_irq_domain_ops, bus); + bus->domain = irq_domain_add_tree(node, &pmic_arb_irq_domain_ops, bus); if (!bus->domain) { dev_err(&pdev->dev, "unable to create irq_domain\n"); return -ENOMEM; diff --git a/drivers/staging/media/atomisp/pci/hive_isp_css_include/math_support.h b/drivers/staging/media/atomisp/pci/hive_isp_css_include/math_support.h index 7349943bba2b46..160c496784b7fc 100644 --- a/drivers/staging/media/atomisp/pci/hive_isp_css_include/math_support.h +++ b/drivers/staging/media/atomisp/pci/hive_isp_css_include/math_support.h @@ -22,11 +22,6 @@ /* force a value to a lower even value */ #define EVEN_FLOOR(x) ((x) & ~1) -/* for preprocessor and array sizing use MIN and MAX - otherwise use min and max */ -#define MAX(a, b) (((a) > (b)) ? (a) : (b)) -#define MIN(a, b) (((a) < (b)) ? (a) : (b)) - #define CEIL_DIV(a, b) (((b) != 0) ? ((a) + (b) - 1) / (b) : 0) #define CEIL_MUL(a, b) (CEIL_DIV(a, b) * (b)) #define CEIL_MUL2(a, b) (((a) + (b) - 1) & ~((b) - 1)) diff --git a/drivers/staging/media/atomisp/pci/ia_css_stream_public.h b/drivers/staging/media/atomisp/pci/ia_css_stream_public.h index 961c612880833a..aad860e54d3a71 100644 --- a/drivers/staging/media/atomisp/pci/ia_css_stream_public.h +++ b/drivers/staging/media/atomisp/pci/ia_css_stream_public.h @@ -27,12 +27,16 @@ #include "ia_css_prbs.h" #include "ia_css_input_port.h" -/* Input modes, these enumerate all supported input modes. - * Note that not all ISP modes support all input modes. +/* + * Input modes, these enumerate all supported input modes. + * This enum is part of the atomisp firmware ABI and must + * NOT be changed! + * Note that not all ISP modes support all input modes. */ enum ia_css_input_mode { IA_CSS_INPUT_MODE_SENSOR, /** data from sensor */ IA_CSS_INPUT_MODE_FIFO, /** data from input-fifo */ + IA_CSS_INPUT_MODE_TPG, /** data from test-pattern generator */ IA_CSS_INPUT_MODE_PRBS, /** data from pseudo-random bit stream */ IA_CSS_INPUT_MODE_MEMORY, /** data from a frame in memory */ IA_CSS_INPUT_MODE_BUFFERED_SENSOR /** data is sent through mipi buffer */ diff --git a/drivers/staging/media/atomisp/pci/sh_css_internal.h b/drivers/staging/media/atomisp/pci/sh_css_internal.h index a2d972ea3fa084..959e7f549641c1 100644 --- a/drivers/staging/media/atomisp/pci/sh_css_internal.h +++ b/drivers/staging/media/atomisp/pci/sh_css_internal.h @@ -344,7 +344,14 @@ struct sh_css_sp_input_formatter_set { #define IA_CSS_MIPI_SIZE_CHECK_MAX_NOF_ENTRIES_PER_PORT (3) -/* SP configuration information */ +/* + * SP configuration information + * + * This struct is part of the atomisp firmware ABI and is directly copied + * to ISP DRAM by sh_css_store_sp_group_to_ddr() + * + * Do NOT change this struct's layout or remove seemingly unused fields! + */ struct sh_css_sp_config { u8 no_isp_sync; /* Signal host immediately after start */ u8 enable_raw_pool_locking; /** Enable Raw Buffer Locking for HALv3 Support */ @@ -354,6 +361,10 @@ struct sh_css_sp_config { host (true) or when they are passed to the preview/video pipe (false). */ + /* + * Note the fields below are only used on the ISP2400 not on the ISP2401, + * sh_css_store_sp_group_to_ddr() skip copying these when run on the ISP2401. + */ struct { u8 a_changed; u8 b_changed; @@ -363,11 +374,13 @@ struct sh_css_sp_config { } input_formatter; sync_generator_cfg_t sync_gen; + tpg_cfg_t tpg; prbs_cfg_t prbs; input_system_cfg_t input_circuit; u8 input_circuit_cfg_changed; - u32 mipi_sizes_for_check[N_CSI_PORTS][IA_CSS_MIPI_SIZE_CHECK_MAX_NOF_ENTRIES_PER_PORT]; - u8 enable_isys_event_queue; + u32 mipi_sizes_for_check[N_CSI_PORTS][IA_CSS_MIPI_SIZE_CHECK_MAX_NOF_ENTRIES_PER_PORT]; + /* These last 2 fields are used on both the ISP2400 and the ISP2401 */ + u8 enable_isys_event_queue; u8 disable_cont_vf; }; diff --git a/drivers/thermal/gov_bang_bang.c b/drivers/thermal/gov_bang_bang.c index 4a2e869b9538c1..daed67d19efb81 100644 --- a/drivers/thermal/gov_bang_bang.c +++ b/drivers/thermal/gov_bang_bang.c @@ -13,6 +13,28 @@ #include "thermal_core.h" +static void bang_bang_set_instance_target(struct thermal_instance *instance, + unsigned int target) +{ + if (instance->target != 0 && instance->target != 1 && + instance->target != THERMAL_NO_TARGET) + pr_debug("Unexpected state %ld of thermal instance %s in bang-bang\n", + instance->target, instance->name); + + /* + * Enable the fan when the trip is crossed on the way up and disable it + * when the trip is crossed on the way down. + */ + instance->target = target; + instance->initialized = true; + + dev_dbg(&instance->cdev->device, "target=%ld\n", instance->target); + + mutex_lock(&instance->cdev->lock); + __thermal_cdev_update(instance->cdev); + mutex_unlock(&instance->cdev->lock); +} + /** * bang_bang_control - controls devices associated with the given zone * @tz: thermal_zone_device @@ -54,33 +76,60 @@ static void bang_bang_control(struct thermal_zone_device *tz, tz->temperature, trip->hysteresis); list_for_each_entry(instance, &tz->thermal_instances, tz_node) { - if (instance->trip != trip) - continue; + if (instance->trip == trip) + bang_bang_set_instance_target(instance, crossed_up); + } +} + +static void bang_bang_manage(struct thermal_zone_device *tz) +{ + const struct thermal_trip_desc *td; + struct thermal_instance *instance; - if (instance->target != 0 && instance->target != 1 && - instance->target != THERMAL_NO_TARGET) - pr_debug("Unexpected state %ld of thermal instance %s in bang-bang\n", - instance->target, instance->name); + /* If the code below has run already, nothing needs to be done. */ + if (tz->governor_data) + return; - /* - * Enable the fan when the trip is crossed on the way up and - * disable it when the trip is crossed on the way down. - */ - instance->target = crossed_up; + for_each_trip_desc(tz, td) { + const struct thermal_trip *trip = &td->trip; - dev_dbg(&instance->cdev->device, "target=%ld\n", instance->target); + if (tz->temperature >= td->threshold || + trip->temperature == THERMAL_TEMP_INVALID || + trip->type == THERMAL_TRIP_CRITICAL || + trip->type == THERMAL_TRIP_HOT) + continue; - mutex_lock(&instance->cdev->lock); - instance->cdev->updated = false; /* cdev needs update */ - mutex_unlock(&instance->cdev->lock); + /* + * If the initial cooling device state is "on", but the zone + * temperature is not above the trip point, the core will not + * call bang_bang_control() until the zone temperature reaches + * the trip point temperature which may be never. In those + * cases, set the initial state of the cooling device to 0. + */ + list_for_each_entry(instance, &tz->thermal_instances, tz_node) { + if (!instance->initialized && instance->trip == trip) + bang_bang_set_instance_target(instance, 0); + } } - list_for_each_entry(instance, &tz->thermal_instances, tz_node) - thermal_cdev_update(instance->cdev); + tz->governor_data = (void *)true; +} + +static void bang_bang_update_tz(struct thermal_zone_device *tz, + enum thermal_notify_event reason) +{ + /* + * Let bang_bang_manage() know that it needs to walk trips after binding + * a new cdev and after system resume. + */ + if (reason == THERMAL_TZ_BIND_CDEV || reason == THERMAL_TZ_RESUME) + tz->governor_data = NULL; } static struct thermal_governor thermal_gov_bang_bang = { .name = "bang_bang", .trip_crossed = bang_bang_control, + .manage = bang_bang_manage, + .update_tz = bang_bang_update_tz, }; THERMAL_GOVERNOR_DECLARE(thermal_gov_bang_bang); diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c b/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c index 114136893a59af..00661492187028 100644 --- a/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c +++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c @@ -278,20 +278,32 @@ static struct thermal_zone_params tzone_params = { static bool msi_irq; +static void proc_thermal_free_msi(struct pci_dev *pdev, struct proc_thermal_pci *pci_info) +{ + int i; + + for (i = 0; i < MSI_THERMAL_MAX; i++) { + if (proc_thermal_msi_map[i]) + devm_free_irq(&pdev->dev, proc_thermal_msi_map[i], pci_info); + } + + pci_free_irq_vectors(pdev); +} + static int proc_thermal_setup_msi(struct pci_dev *pdev, struct proc_thermal_pci *pci_info) { - int ret, i, irq; + int ret, i, irq, count; - ret = pci_alloc_irq_vectors(pdev, 1, MSI_THERMAL_MAX, PCI_IRQ_MSI | PCI_IRQ_MSIX); - if (ret < 0) { + count = pci_alloc_irq_vectors(pdev, 1, MSI_THERMAL_MAX, PCI_IRQ_MSI | PCI_IRQ_MSIX); + if (count < 0) { dev_err(&pdev->dev, "Failed to allocate vectors!\n"); - return ret; + return count; } dev_info(&pdev->dev, "msi enabled:%d msix enabled:%d\n", pdev->msi_enabled, pdev->msix_enabled); - for (i = 0; i < MSI_THERMAL_MAX; i++) { + for (i = 0; i < count; i++) { irq = pci_irq_vector(pdev, i); ret = devm_request_threaded_irq(&pdev->dev, irq, proc_thermal_irq_handler, @@ -310,7 +322,7 @@ static int proc_thermal_setup_msi(struct pci_dev *pdev, struct proc_thermal_pci return 0; err_free_msi_vectors: - pci_free_irq_vectors(pdev); + proc_thermal_free_msi(pdev, pci_info); return ret; } @@ -397,7 +409,7 @@ static int proc_thermal_pci_probe(struct pci_dev *pdev, const struct pci_device_ err_free_vectors: if (msi_irq) - pci_free_irq_vectors(pdev); + proc_thermal_free_msi(pdev, pci_info); err_ret_tzone: thermal_zone_device_unregister(pci_info->tzone); err_del_legacy: @@ -419,6 +431,9 @@ static void proc_thermal_pci_remove(struct pci_dev *pdev) proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_THRES_0, 0); proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_INT_ENABLE_0, 0); + if (msi_irq) + proc_thermal_free_msi(pdev, pci_info); + thermal_zone_device_unregister(pci_info->tzone); proc_thermal_mmio_remove(pdev, pci_info->proc_priv); if (!pci_info->no_legacy) diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index 95c399f9474418..e6669aeda1fff0 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -1728,7 +1728,8 @@ static void thermal_zone_device_resume(struct work_struct *work) thermal_debug_tz_resume(tz); thermal_zone_device_init(tz); - __thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED); + thermal_governor_update_tz(tz, THERMAL_TZ_RESUME); + __thermal_zone_device_update(tz, THERMAL_TZ_RESUME); complete(&tz->resume); tz->resuming = false; diff --git a/drivers/thermal/thermal_trip.c b/drivers/thermal/thermal_trip.c index c0b679b846b3b9..06a0554ddc3891 100644 --- a/drivers/thermal/thermal_trip.c +++ b/drivers/thermal/thermal_trip.c @@ -88,10 +88,10 @@ void thermal_zone_set_trips(struct thermal_zone_device *tz) return; for_each_trip_desc(tz, td) { - if (td->threshold < tz->temperature && td->threshold > low) + if (td->threshold <= tz->temperature && td->threshold > low) low = td->threshold; - if (td->threshold > tz->temperature && td->threshold < high) + if (td->threshold >= tz->temperature && td->threshold < high) high = td->threshold; } diff --git a/drivers/thunderbolt/debugfs.c b/drivers/thunderbolt/debugfs.c index 11185cc1db9299..9ed4bb2e8d05fd 100644 --- a/drivers/thunderbolt/debugfs.c +++ b/drivers/thunderbolt/debugfs.c @@ -323,16 +323,17 @@ static ssize_t port_sb_regs_write(struct file *file, const char __user *user_buf if (mutex_lock_interruptible(&tb->lock)) { ret = -ERESTARTSYS; - goto out_rpm_put; + goto out; } ret = sb_regs_write(port, port_sb_regs, ARRAY_SIZE(port_sb_regs), USB4_SB_TARGET_ROUTER, 0, buf, count, ppos); mutex_unlock(&tb->lock); -out_rpm_put: +out: pm_runtime_mark_last_busy(&sw->dev); pm_runtime_put_autosuspend(&sw->dev); + free_page((unsigned long)buf); return ret < 0 ? ret : count; } @@ -355,16 +356,17 @@ static ssize_t retimer_sb_regs_write(struct file *file, if (mutex_lock_interruptible(&tb->lock)) { ret = -ERESTARTSYS; - goto out_rpm_put; + goto out; } ret = sb_regs_write(rt->port, retimer_sb_regs, ARRAY_SIZE(retimer_sb_regs), USB4_SB_TARGET_RETIMER, rt->index, buf, count, ppos); mutex_unlock(&tb->lock); -out_rpm_put: +out: pm_runtime_mark_last_busy(&rt->dev); pm_runtime_put_autosuspend(&rt->dev); + free_page((unsigned long)buf); return ret < 0 ? ret : count; } diff --git a/drivers/thunderbolt/switch.c b/drivers/thunderbolt/switch.c index 326433df5880e2..6a2116cbb06f92 100644 --- a/drivers/thunderbolt/switch.c +++ b/drivers/thunderbolt/switch.c @@ -3392,6 +3392,7 @@ void tb_switch_remove(struct tb_switch *sw) tb_switch_remove(port->remote->sw); port->remote = NULL; } else if (port->xdomain) { + port->xdomain->is_unplugged = true; tb_xdomain_remove(port->xdomain); port->xdomain = NULL; } diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c index 1af9aed99c6512..afef1dd4ddf49c 100644 --- a/drivers/tty/serial/8250/8250_omap.c +++ b/drivers/tty/serial/8250/8250_omap.c @@ -27,7 +27,6 @@ #include #include #include -#include #include "8250.h" @@ -119,12 +118,6 @@ #define UART_OMAP_TO_L 0x26 #define UART_OMAP_TO_H 0x27 -/* - * Copy of the genpd flags for the console. - * Only used if console suspend is disabled - */ -static unsigned int genpd_flags_console; - struct omap8250_priv { void __iomem *membase; int line; @@ -1655,7 +1648,6 @@ static int omap8250_suspend(struct device *dev) { struct omap8250_priv *priv = dev_get_drvdata(dev); struct uart_8250_port *up = serial8250_get_port(priv->line); - struct generic_pm_domain *genpd = pd_to_genpd(dev->pm_domain); int err = 0; serial8250_suspend_port(priv->line); @@ -1666,19 +1658,8 @@ static int omap8250_suspend(struct device *dev) if (!device_may_wakeup(dev)) priv->wer = 0; serial_out(up, UART_OMAP_WER, priv->wer); - if (uart_console(&up->port)) { - if (console_suspend_enabled) - err = pm_runtime_force_suspend(dev); - else { - /* - * The pd shall not be powered-off (no console suspend). - * Make copy of genpd flags before to set it always on. - * The original value is restored during the resume. - */ - genpd_flags_console = genpd->flags; - genpd->flags |= GENPD_FLAG_ALWAYS_ON; - } - } + if (uart_console(&up->port) && console_suspend_enabled) + err = pm_runtime_force_suspend(dev); flush_work(&priv->qos_work); return err; @@ -1688,16 +1669,12 @@ static int omap8250_resume(struct device *dev) { struct omap8250_priv *priv = dev_get_drvdata(dev); struct uart_8250_port *up = serial8250_get_port(priv->line); - struct generic_pm_domain *genpd = pd_to_genpd(dev->pm_domain); int err; if (uart_console(&up->port) && console_suspend_enabled) { - if (console_suspend_enabled) { - err = pm_runtime_force_resume(dev); - if (err) - return err; - } else - genpd->flags = genpd_flags_console; + err = pm_runtime_force_resume(dev); + if (err) + return err; } serial8250_resume_port(priv->line); diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index 0a90964d6d107f..09b246c9e389ec 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -2514,7 +2514,7 @@ static const struct uart_ops atmel_pops = { }; static const struct serial_rs485 atmel_rs485_supported = { - .flags = SER_RS485_ENABLED | SER_RS485_RTS_AFTER_SEND | SER_RS485_RX_DURING_TX, + .flags = SER_RS485_ENABLED | SER_RS485_RTS_ON_SEND | SER_RS485_RX_DURING_TX, .delay_rts_before_send = 1, .delay_rts_after_send = 1, }; diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c index 615291ea9b5e93..77efa7ee6eda29 100644 --- a/drivers/tty/serial/fsl_lpuart.c +++ b/drivers/tty/serial/fsl_lpuart.c @@ -2923,6 +2923,7 @@ static int lpuart_probe(struct platform_device *pdev) pm_runtime_set_autosuspend_delay(&pdev->dev, UART_AUTOSUSPEND_TIMEOUT); pm_runtime_set_active(&pdev->dev); pm_runtime_enable(&pdev->dev); + pm_runtime_mark_last_busy(&pdev->dev); ret = lpuart_global_reset(sport); if (ret) diff --git a/drivers/tty/serial/sc16is7xx.c b/drivers/tty/serial/sc16is7xx.c index c79dcd7c8d1a60..b4c1798a1df2a0 100644 --- a/drivers/tty/serial/sc16is7xx.c +++ b/drivers/tty/serial/sc16is7xx.c @@ -327,6 +327,7 @@ struct sc16is7xx_one { struct kthread_work reg_work; struct kthread_delayed_work ms_work; struct sc16is7xx_one_config config; + unsigned char buf[SC16IS7XX_FIFO_SIZE]; /* Rx buffer. */ unsigned int old_mctrl; u8 old_lcr; /* Value before EFR access. */ bool irda_mode; @@ -340,7 +341,6 @@ struct sc16is7xx_port { unsigned long gpio_valid_mask; #endif u8 mctrl_mask; - unsigned char buf[SC16IS7XX_FIFO_SIZE]; struct kthread_worker kworker; struct task_struct *kworker_task; struct sc16is7xx_one p[]; @@ -592,6 +592,8 @@ static int sc16is7xx_set_baud(struct uart_port *port, int baud) SC16IS7XX_MCR_CLKSEL_BIT, prescaler == 1 ? 0 : SC16IS7XX_MCR_CLKSEL_BIT); + mutex_lock(&one->efr_lock); + /* Backup LCR and access special register set (DLL/DLH) */ lcr = sc16is7xx_port_read(port, SC16IS7XX_LCR_REG); sc16is7xx_port_write(port, SC16IS7XX_LCR_REG, @@ -606,24 +608,26 @@ static int sc16is7xx_set_baud(struct uart_port *port, int baud) /* Restore LCR and access to general register set */ sc16is7xx_port_write(port, SC16IS7XX_LCR_REG, lcr); + mutex_unlock(&one->efr_lock); + return DIV_ROUND_CLOSEST((clk / prescaler) / 16, div); } static void sc16is7xx_handle_rx(struct uart_port *port, unsigned int rxlen, unsigned int iir) { - struct sc16is7xx_port *s = dev_get_drvdata(port->dev); + struct sc16is7xx_one *one = to_sc16is7xx_one(port, port); unsigned int lsr = 0, bytes_read, i; bool read_lsr = (iir == SC16IS7XX_IIR_RLSE_SRC) ? true : false; u8 ch, flag; - if (unlikely(rxlen >= sizeof(s->buf))) { + if (unlikely(rxlen >= sizeof(one->buf))) { dev_warn_ratelimited(port->dev, "ttySC%i: Possible RX FIFO overrun: %d\n", port->line, rxlen); port->icount.buf_overrun++; /* Ensure sanity of RX level */ - rxlen = sizeof(s->buf); + rxlen = sizeof(one->buf); } while (rxlen) { @@ -636,10 +640,10 @@ static void sc16is7xx_handle_rx(struct uart_port *port, unsigned int rxlen, lsr = 0; if (read_lsr) { - s->buf[0] = sc16is7xx_port_read(port, SC16IS7XX_RHR_REG); + one->buf[0] = sc16is7xx_port_read(port, SC16IS7XX_RHR_REG); bytes_read = 1; } else { - sc16is7xx_fifo_read(port, s->buf, rxlen); + sc16is7xx_fifo_read(port, one->buf, rxlen); bytes_read = rxlen; } @@ -672,7 +676,7 @@ static void sc16is7xx_handle_rx(struct uart_port *port, unsigned int rxlen, } for (i = 0; i < bytes_read; ++i) { - ch = s->buf[i]; + ch = one->buf[i]; if (uart_handle_sysrq_char(port, ch)) continue; @@ -690,10 +694,10 @@ static void sc16is7xx_handle_rx(struct uart_port *port, unsigned int rxlen, static void sc16is7xx_handle_tx(struct uart_port *port) { - struct sc16is7xx_port *s = dev_get_drvdata(port->dev); struct tty_port *tport = &port->state->port; unsigned long flags; unsigned int txlen; + unsigned char *tail; if (unlikely(port->x_char)) { sc16is7xx_port_write(port, SC16IS7XX_THR_REG, port->x_char); @@ -718,8 +722,9 @@ static void sc16is7xx_handle_tx(struct uart_port *port) txlen = 0; } - txlen = uart_fifo_out(port, s->buf, txlen); - sc16is7xx_fifo_write(port, s->buf, txlen); + txlen = kfifo_out_linear_ptr(&tport->xmit_fifo, &tail, txlen); + sc16is7xx_fifo_write(port, tail, txlen); + uart_xmit_advance(port, txlen); uart_port_lock_irqsave(port, &flags); if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS) diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 9a18d0b95a4190..5bea3af46abcef 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -881,6 +881,14 @@ static int uart_set_info(struct tty_struct *tty, struct tty_port *port, new_flags = (__force upf_t)new_info->flags; old_custom_divisor = uport->custom_divisor; + if (!(uport->flags & UPF_FIXED_PORT)) { + unsigned int uartclk = new_info->baud_base * 16; + /* check needs to be done here before other settings made */ + if (uartclk == 0) { + retval = -EINVAL; + goto exit; + } + } if (!capable(CAP_SYS_ADMIN)) { retval = -EPERM; if (change_irq || change_port || diff --git a/drivers/tty/vt/conmakehash.c b/drivers/tty/vt/conmakehash.c index dc2177fec7156e..a931fcde7ad98d 100644 --- a/drivers/tty/vt/conmakehash.c +++ b/drivers/tty/vt/conmakehash.c @@ -76,8 +76,7 @@ static void addpair(int fp, int un) int main(int argc, char *argv[]) { FILE *ctbl; - const char *tblname, *rel_tblname; - const char *abs_srctree; + const char *tblname; char buffer[65536]; int fontlen; int i, nuni, nent; @@ -102,16 +101,6 @@ int main(int argc, char *argv[]) } } - abs_srctree = getenv("abs_srctree"); - if (abs_srctree && !strncmp(abs_srctree, tblname, strlen(abs_srctree))) - { - rel_tblname = tblname + strlen(abs_srctree); - while (*rel_tblname == '/') - ++rel_tblname; - } - else - rel_tblname = tblname; - /* For now we assume the default font is always 256 characters. */ fontlen = 256; @@ -255,16 +244,13 @@ int main(int argc, char *argv[]) printf("\ /*\n\ - * Do not edit this file; it was automatically generated by\n\ - *\n\ - * conmakehash %s > [this file]\n\ - *\n\ + * Automatically generated file; Do not edit.\n\ */\n\ \n\ #include \n\ \n\ u8 dfont_unicount[%d] = \n\ -{\n\t", rel_tblname, fontlen); +{\n\t", fontlen); for ( i = 0 ; i < fontlen ; i++ ) { diff --git a/drivers/ufs/core/ufshcd-priv.h b/drivers/ufs/core/ufshcd-priv.h index ce36154ce9638a..7aea8fbaeee882 100644 --- a/drivers/ufs/core/ufshcd-priv.h +++ b/drivers/ufs/core/ufshcd-priv.h @@ -316,6 +316,11 @@ static inline int ufshcd_rpm_get_sync(struct ufs_hba *hba) return pm_runtime_get_sync(&hba->ufs_device_wlun->sdev_gendev); } +static inline int ufshcd_rpm_get_if_active(struct ufs_hba *hba) +{ + return pm_runtime_get_if_active(&hba->ufs_device_wlun->sdev_gendev); +} + static inline int ufshcd_rpm_put_sync(struct ufs_hba *hba) { return pm_runtime_put_sync(&hba->ufs_device_wlun->sdev_gendev); diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c index dc757ba47522b0..0b3d0c8e0ddaed 100644 --- a/drivers/ufs/core/ufshcd.c +++ b/drivers/ufs/core/ufshcd.c @@ -2416,7 +2416,17 @@ static inline int ufshcd_hba_capabilities(struct ufs_hba *hba) return err; } + /* + * The UFSHCI 3.0 specification does not define MCQ_SUPPORT and + * LSDB_SUPPORT, but [31:29] as reserved bits with reset value 0s, which + * means we can simply read values regardless of version. + */ hba->mcq_sup = FIELD_GET(MASK_MCQ_SUPPORT, hba->capabilities); + /* + * 0h: legacy single doorbell support is available + * 1h: indicate that legacy single doorbell support has been removed + */ + hba->lsdb_sup = !FIELD_GET(MASK_LSDB_SUPPORT, hba->capabilities); if (!hba->mcq_sup) return 0; @@ -4090,11 +4100,16 @@ static inline void ufshcd_add_delay_before_dme_cmd(struct ufs_hba *hba) min_sleep_time_us = MIN_DELAY_BEFORE_DME_CMDS_US - delta; else - return; /* no more delay required */ + min_sleep_time_us = 0; /* no more delay required */ } - /* allow sleep for extra 50us if needed */ - usleep_range(min_sleep_time_us, min_sleep_time_us + 50); + if (min_sleep_time_us > 0) { + /* allow sleep for extra 50us if needed */ + usleep_range(min_sleep_time_us, min_sleep_time_us + 50); + } + + /* update the last_dme_cmd_tstamp */ + hba->last_dme_cmd_tstamp = ktime_get(); } /** @@ -6553,7 +6568,8 @@ static void ufshcd_err_handler(struct work_struct *work) if (ufshcd_err_handling_should_stop(hba)) goto skip_err_handling; - if (hba->dev_quirks & UFS_DEVICE_QUIRK_RECOVERY_FROM_DL_NAC_ERRORS) { + if ((hba->dev_quirks & UFS_DEVICE_QUIRK_RECOVERY_FROM_DL_NAC_ERRORS) && + !hba->force_reset) { bool ret; spin_unlock_irqrestore(hba->host->host_lock, flags); @@ -8211,7 +8227,10 @@ static void ufshcd_update_rtc(struct ufs_hba *hba) */ val = ts64.tv_sec - hba->dev_info.rtc_time_baseline; - ufshcd_rpm_get_sync(hba); + /* Skip update RTC if RPM state is not RPM_ACTIVE */ + if (ufshcd_rpm_get_if_active(hba) <= 0) + return; + err = ufshcd_query_attr(hba, UPIU_QUERY_OPCODE_WRITE_ATTR, QUERY_ATTR_IDN_SECONDS_PASSED, 0, 0, &val); ufshcd_rpm_put_sync(hba); @@ -10265,9 +10284,6 @@ int ufshcd_system_restore(struct device *dev) */ ufshcd_readl(hba, REG_UTP_TASK_REQ_LIST_BASE_H); - /* Resuming from hibernate, assume that link was OFF */ - ufshcd_set_link_off(hba); - return 0; } @@ -10496,6 +10512,12 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq) } if (!is_mcq_supported(hba)) { + if (!hba->lsdb_sup) { + dev_err(hba->dev, "%s: failed to initialize (legacy doorbell mode not supported)\n", + __func__); + err = -EINVAL; + goto out_disable; + } err = scsi_add_host(host, hba->dev); if (err) { dev_err(hba->dev, "scsi_add_host failed\n"); diff --git a/drivers/ufs/host/ufs-exynos.c b/drivers/ufs/host/ufs-exynos.c index 16ad3528d80b23..9ec318ef52bff2 100644 --- a/drivers/ufs/host/ufs-exynos.c +++ b/drivers/ufs/host/ufs-exynos.c @@ -1293,6 +1293,9 @@ static void exynos_ufs_fmp_resume(struct ufs_hba *hba) { struct arm_smccc_res res; + if (!(hba->caps & UFSHCD_CAP_CRYPTO)) + return; + arm_smccc_smc(SMC_CMD_FMP_SECURITY, 0, SMU_EMBEDDED, CFG_DESCTYPE_3, 0, 0, 0, 0, &res); if (res.a0) diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index d8b09685933795..e0ceaa72194937 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c @@ -3734,11 +3734,9 @@ static int ffs_func_set_alt(struct usb_function *f, if (alt > MAX_ALT_SETTINGS) return -EINVAL; - if (alt != (unsigned)-1) { - intf = ffs_func_revmap_intf(func, interface); - if (intf < 0) - return intf; - } + intf = ffs_func_revmap_intf(func, interface); + if (intf < 0) + return intf; if (ffs->func) ffs_func_eps_disable(ffs->func); @@ -3753,12 +3751,6 @@ static int ffs_func_set_alt(struct usb_function *f, if (ffs->state != FFS_ACTIVE) return -ENODEV; - if (alt == (unsigned)-1) { - ffs->func = NULL; - ffs_event_add(ffs, FUNCTIONFS_DISABLE); - return 0; - } - ffs->func = func; ret = ffs_func_eps_enable(func); if (ret >= 0) { @@ -3770,7 +3762,23 @@ static int ffs_func_set_alt(struct usb_function *f, static void ffs_func_disable(struct usb_function *f) { - ffs_func_set_alt(f, 0, (unsigned)-1); + struct ffs_function *func = ffs_func_from_usb(f); + struct ffs_data *ffs = func->ffs; + + if (ffs->func) + ffs_func_eps_disable(ffs->func); + + if (ffs->state == FFS_DEACTIVATED) { + ffs->state = FFS_CLOSING; + INIT_WORK(&ffs->reset_work, ffs_reset_work); + schedule_work(&ffs->reset_work); + return; + } + + if (ffs->state == FFS_ACTIVE) { + ffs->func = NULL; + ffs_event_add(ffs, FUNCTIONFS_DISABLE); + } } static int ffs_func_setup(struct usb_function *f, diff --git a/drivers/usb/gadget/function/f_midi2.c b/drivers/usb/gadget/function/f_midi2.c index 38e8ed3144f060..3f63253ad3e074 100644 --- a/drivers/usb/gadget/function/f_midi2.c +++ b/drivers/usb/gadget/function/f_midi2.c @@ -642,12 +642,21 @@ static void process_ump_stream_msg(struct f_midi2_ep *ep, const u32 *data) if (format) return; // invalid blk = (*data >> 8) & 0xff; - if (blk >= ep->num_blks) - return; - if (*data & UMP_STREAM_MSG_REQUEST_FB_INFO) - reply_ump_stream_fb_info(ep, blk); - if (*data & UMP_STREAM_MSG_REQUEST_FB_NAME) - reply_ump_stream_fb_name(ep, blk); + if (blk == 0xff) { + /* inquiry for all blocks */ + for (blk = 0; blk < ep->num_blks; blk++) { + if (*data & UMP_STREAM_MSG_REQUEST_FB_INFO) + reply_ump_stream_fb_info(ep, blk); + if (*data & UMP_STREAM_MSG_REQUEST_FB_NAME) + reply_ump_stream_fb_name(ep, blk); + } + } else if (blk < ep->num_blks) { + /* only the specified block */ + if (*data & UMP_STREAM_MSG_REQUEST_FB_INFO) + reply_ump_stream_fb_info(ep, blk); + if (*data & UMP_STREAM_MSG_REQUEST_FB_NAME) + reply_ump_stream_fb_name(ep, blk); + } return; } } diff --git a/drivers/usb/gadget/function/u_audio.c b/drivers/usb/gadget/function/u_audio.c index 89af0feb751208..24299576972fe1 100644 --- a/drivers/usb/gadget/function/u_audio.c +++ b/drivers/usb/gadget/function/u_audio.c @@ -592,16 +592,25 @@ int u_audio_start_capture(struct g_audio *audio_dev) struct usb_ep *ep, *ep_fback; struct uac_rtd_params *prm; struct uac_params *params = &audio_dev->params; - int req_len, i; + int req_len, i, ret; prm = &uac->c_prm; dev_dbg(dev, "start capture with rate %d\n", prm->srate); ep = audio_dev->out_ep; - config_ep_by_speed(gadget, &audio_dev->func, ep); + ret = config_ep_by_speed(gadget, &audio_dev->func, ep); + if (ret < 0) { + dev_err(dev, "config_ep_by_speed for out_ep failed (%d)\n", ret); + return ret; + } + req_len = ep->maxpacket; prm->ep_enabled = true; - usb_ep_enable(ep); + ret = usb_ep_enable(ep); + if (ret < 0) { + dev_err(dev, "usb_ep_enable failed for out_ep (%d)\n", ret); + return ret; + } for (i = 0; i < params->req_number; i++) { if (!prm->reqs[i]) { @@ -629,9 +638,18 @@ int u_audio_start_capture(struct g_audio *audio_dev) return 0; /* Setup feedback endpoint */ - config_ep_by_speed(gadget, &audio_dev->func, ep_fback); + ret = config_ep_by_speed(gadget, &audio_dev->func, ep_fback); + if (ret < 0) { + dev_err(dev, "config_ep_by_speed in_ep_fback failed (%d)\n", ret); + return ret; // TODO: Clean up out_ep + } + prm->fb_ep_enabled = true; - usb_ep_enable(ep_fback); + ret = usb_ep_enable(ep_fback); + if (ret < 0) { + dev_err(dev, "usb_ep_enable failed for in_ep_fback (%d)\n", ret); + return ret; // TODO: Clean up out_ep + } req_len = ep_fback->maxpacket; req_fback = usb_ep_alloc_request(ep_fback, GFP_ATOMIC); @@ -687,13 +705,17 @@ int u_audio_start_playback(struct g_audio *audio_dev) struct uac_params *params = &audio_dev->params; unsigned int factor; const struct usb_endpoint_descriptor *ep_desc; - int req_len, i; + int req_len, i, ret; unsigned int p_pktsize; prm = &uac->p_prm; dev_dbg(dev, "start playback with rate %d\n", prm->srate); ep = audio_dev->in_ep; - config_ep_by_speed(gadget, &audio_dev->func, ep); + ret = config_ep_by_speed(gadget, &audio_dev->func, ep); + if (ret < 0) { + dev_err(dev, "config_ep_by_speed for in_ep failed (%d)\n", ret); + return ret; + } ep_desc = ep->desc; /* @@ -720,7 +742,11 @@ int u_audio_start_playback(struct g_audio *audio_dev) uac->p_residue_mil = 0; prm->ep_enabled = true; - usb_ep_enable(ep); + ret = usb_ep_enable(ep); + if (ret < 0) { + dev_err(dev, "usb_ep_enable failed for in_ep (%d)\n", ret); + return ret; + } for (i = 0; i < params->req_number; i++) { if (!prm->reqs[i]) { diff --git a/drivers/usb/gadget/function/u_serial.c b/drivers/usb/gadget/function/u_serial.c index eec7f7a2e40f08..b394105e55d6cc 100644 --- a/drivers/usb/gadget/function/u_serial.c +++ b/drivers/usb/gadget/function/u_serial.c @@ -1441,6 +1441,7 @@ void gserial_suspend(struct gserial *gser) spin_lock(&port->port_lock); spin_unlock(&serial_port_lock); port->suspended = true; + port->start_delayed = true; spin_unlock_irqrestore(&port->port_lock, flags); } EXPORT_SYMBOL_GPL(gserial_suspend); diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c index b0a6137584141c..cf6478f97f4a3d 100644 --- a/drivers/usb/gadget/udc/core.c +++ b/drivers/usb/gadget/udc/core.c @@ -118,12 +118,10 @@ int usb_ep_enable(struct usb_ep *ep) goto out; /* UDC drivers can't handle endpoints with maxpacket size 0 */ - if (usb_endpoint_maxp(ep->desc) == 0) { - /* - * We should log an error message here, but we can't call - * dev_err() because there's no way to find the gadget - * given only ep. - */ + if (!ep->desc || usb_endpoint_maxp(ep->desc) == 0) { + WARN_ONCE(1, "%s: ep%d (%s) has %s\n", __func__, ep->address, ep->name, + (!ep->desc) ? "NULL descriptor" : "maxpacket 0"); + ret = -EINVAL; goto out; } diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index d7654f475dafbf..937ce5fd58095b 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -1872,7 +1872,7 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci) cancel_delayed_work_sync(&xhci->cmd_timer); - for (i = 0; i < xhci->max_interrupters; i++) { + for (i = 0; xhci->interrupters && i < xhci->max_interrupters; i++) { if (xhci->interrupters[i]) { xhci_remove_interrupter(xhci, xhci->interrupters[i]); xhci_free_interrupter(xhci, xhci->interrupters[i]); diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index b7517c3c8059f4..4ea2c3e072a9e3 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -2910,6 +2910,7 @@ static int handle_tx_event(struct xhci_hcd *xhci, process_isoc_td(xhci, ep, ep_ring, td, ep_trb, event); else process_bulk_intr_td(xhci, ep, ep_ring, td, ep_trb, event); + return 0; check_endpoint_halted: if (xhci_halted_host_endpoint(ep_ctx, trb_comp_code)) diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 0a8cf6c17f827a..efdf4c228b8c0a 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -2837,7 +2837,7 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci, xhci->num_active_eps); return -ENOMEM; } - if ((xhci->quirks & XHCI_SW_BW_CHECKING) && + if ((xhci->quirks & XHCI_SW_BW_CHECKING) && !ctx_change && xhci_reserve_bandwidth(xhci, virt_dev, command->in_ctx)) { if ((xhci->quirks & XHCI_EP_LIMIT_QUIRK)) xhci_free_host_resources(xhci, ctrl_ctx); @@ -4200,8 +4200,10 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev, mutex_unlock(&xhci->mutex); ret = xhci_disable_slot(xhci, udev->slot_id); xhci_free_virt_device(xhci, udev->slot_id); - if (!ret) - xhci_alloc_dev(hcd, udev); + if (!ret) { + if (xhci_alloc_dev(hcd, udev) == 1) + xhci_setup_addressable_virt_dev(xhci, udev); + } kfree(command->completion); kfree(command); return -EPROTO; diff --git a/drivers/usb/misc/usb-ljca.c b/drivers/usb/misc/usb-ljca.c index 2d30fc1be30669..1a8d5e80b9aec2 100644 --- a/drivers/usb/misc/usb-ljca.c +++ b/drivers/usb/misc/usb-ljca.c @@ -169,6 +169,7 @@ static const struct acpi_device_id ljca_gpio_hids[] = { { "INTC1096" }, { "INTC100B" }, { "INTC10D1" }, + { "INTC10B5" }, {}, }; diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c index 612bea504d7a87..0870c6533f8012 100644 --- a/drivers/usb/serial/ch341.c +++ b/drivers/usb/serial/ch341.c @@ -863,4 +863,5 @@ static struct usb_serial_driver * const serial_drivers[] = { module_usb_serial_driver(serial_drivers, id_table); +MODULE_DESCRIPTION("Winchiphead CH341 USB Serial driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c index 670e942fdaaa18..6d6ec7eed87c92 100644 --- a/drivers/usb/serial/garmin_gps.c +++ b/drivers/usb/serial/garmin_gps.c @@ -104,7 +104,7 @@ struct garmin_packet { int seq; /* the real size of the data array, always > 0 */ int size; - __u8 data[]; + __u8 data[] __counted_by(size); }; /* structure used to keep the current state of the driver */ @@ -267,8 +267,7 @@ static int pkt_add(struct garmin_data *garmin_data_p, /* process only packets containing data ... */ if (data_length) { - pkt = kmalloc(sizeof(struct garmin_packet)+data_length, - GFP_ATOMIC); + pkt = kmalloc(struct_size(pkt, data, data_length), GFP_ATOMIC); if (!pkt) return 0; diff --git a/drivers/usb/serial/mxuport.c b/drivers/usb/serial/mxuport.c index 1f7bb3e4fcf22d..942cb01534232e 100644 --- a/drivers/usb/serial/mxuport.c +++ b/drivers/usb/serial/mxuport.c @@ -1315,4 +1315,5 @@ module_usb_serial_driver(serial_drivers, mxuport_idtable); MODULE_AUTHOR("Andrew Lunn "); MODULE_AUTHOR(""); +MODULE_DESCRIPTION("Moxa UPORT USB Serial driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/usb/serial/navman.c b/drivers/usb/serial/navman.c index 20277c52dded6b..82791fd67c468e 100644 --- a/drivers/usb/serial/navman.c +++ b/drivers/usb/serial/navman.c @@ -112,4 +112,5 @@ static struct usb_serial_driver * const serial_drivers[] = { module_usb_serial_driver(serial_drivers, id_table); +MODULE_DESCRIPTION("Navman USB Serial driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/usb/serial/qcaux.c b/drivers/usb/serial/qcaux.c index 929ffba663f203..015bb7c5d19d3b 100644 --- a/drivers/usb/serial/qcaux.c +++ b/drivers/usb/serial/qcaux.c @@ -84,4 +84,5 @@ static struct usb_serial_driver * const serial_drivers[] = { }; module_usb_serial_driver(serial_drivers, id_table); +MODULE_DESCRIPTION("Qualcomm USB Auxiliary Serial Port driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c index 09a972a838ee4c..6b294bf8bc435f 100644 --- a/drivers/usb/serial/spcp8x5.c +++ b/drivers/usb/serial/spcp8x5.c @@ -49,16 +49,6 @@ static const struct usb_device_id id_table[] = { }; MODULE_DEVICE_TABLE(usb, id_table); -struct spcp8x5_usb_ctrl_arg { - u8 type; - u8 cmd; - u8 cmd_type; - u16 value; - u16 index; - u16 length; -}; - - /* spcp8x5 spec register define */ #define MCR_CONTROL_LINE_RTS 0x02 #define MCR_CONTROL_LINE_DTR 0x01 diff --git a/drivers/usb/serial/symbolserial.c b/drivers/usb/serial/symbolserial.c index d7f73ad6e778f9..9aabb087f733cb 100644 --- a/drivers/usb/serial/symbolserial.c +++ b/drivers/usb/serial/symbolserial.c @@ -190,4 +190,5 @@ static struct usb_serial_driver * const serial_drivers[] = { module_usb_serial_driver(serial_drivers, id_table); +MODULE_DESCRIPTION("Symbol USB barcode to serial driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/usb/serial/usb-serial-simple.c b/drivers/usb/serial/usb-serial-simple.c index 24b8772a345e2f..82f4f0b992aaa7 100644 --- a/drivers/usb/serial/usb-serial-simple.c +++ b/drivers/usb/serial/usb-serial-simple.c @@ -163,4 +163,5 @@ static const struct usb_device_id id_table[] = { MODULE_DEVICE_TABLE(usb, id_table); module_usb_serial_driver(serial_drivers, id_table); +MODULE_DESCRIPTION("USB Serial 'Simple' driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/usb/serial/usb_debug.c b/drivers/usb/serial/usb_debug.c index 6934970f180d7f..61a8425b7762a4 100644 --- a/drivers/usb/serial/usb_debug.c +++ b/drivers/usb/serial/usb_debug.c @@ -76,6 +76,11 @@ static void usb_debug_process_read_urb(struct urb *urb) usb_serial_generic_process_read_urb(urb); } +static void usb_debug_init_termios(struct tty_struct *tty) +{ + tty->termios.c_lflag &= ~(ECHO | ECHONL); +} + static struct usb_serial_driver debug_device = { .driver = { .owner = THIS_MODULE, @@ -85,6 +90,7 @@ static struct usb_serial_driver debug_device = { .num_ports = 1, .bulk_out_size = USB_DEBUG_MAX_PACKET_SIZE, .break_ctl = usb_debug_break_ctl, + .init_termios = usb_debug_init_termios, .process_read_urb = usb_debug_process_read_urb, }; @@ -96,6 +102,7 @@ static struct usb_serial_driver dbc_device = { .id_table = dbc_id_table, .num_ports = 1, .break_ctl = usb_debug_break_ctl, + .init_termios = usb_debug_init_termios, .process_read_urb = usb_debug_process_read_urb, }; @@ -104,4 +111,5 @@ static struct usb_serial_driver * const serial_drivers[] = { }; module_usb_serial_driver(serial_drivers, id_table_combined); +MODULE_DESCRIPTION("USB Debug cable driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/usb/typec/mux/fsa4480.c b/drivers/usb/typec/mux/fsa4480.c index cb7cdf90cb0aaa..cd235339834b0b 100644 --- a/drivers/usb/typec/mux/fsa4480.c +++ b/drivers/usb/typec/mux/fsa4480.c @@ -13,6 +13,10 @@ #include #include +#define FSA4480_DEVICE_ID 0x00 + #define FSA4480_DEVICE_ID_VENDOR_ID GENMASK(7, 6) + #define FSA4480_DEVICE_ID_VERSION_ID GENMASK(5, 3) + #define FSA4480_DEVICE_ID_REV_ID GENMASK(2, 0) #define FSA4480_SWITCH_ENABLE 0x04 #define FSA4480_SWITCH_SELECT 0x05 #define FSA4480_SWITCH_STATUS1 0x07 @@ -251,6 +255,7 @@ static int fsa4480_probe(struct i2c_client *client) struct typec_switch_desc sw_desc = { }; struct typec_mux_desc mux_desc = { }; struct fsa4480 *fsa; + int val = 0; int ret; fsa = devm_kzalloc(dev, sizeof(*fsa), GFP_KERNEL); @@ -268,6 +273,15 @@ static int fsa4480_probe(struct i2c_client *client) if (IS_ERR(fsa->regmap)) return dev_err_probe(dev, PTR_ERR(fsa->regmap), "failed to initialize regmap\n"); + ret = regmap_read(fsa->regmap, FSA4480_DEVICE_ID, &val); + if (ret || !val) + return dev_err_probe(dev, -ENODEV, "FSA4480 not found\n"); + + dev_dbg(dev, "Found FSA4480 v%lu.%lu (Vendor ID = %lu)\n", + FIELD_GET(FSA4480_DEVICE_ID_VERSION_ID, val), + FIELD_GET(FSA4480_DEVICE_ID_REV_ID, val), + FIELD_GET(FSA4480_DEVICE_ID_VENDOR_ID, val)); + /* Safe mode */ fsa->cur_enable = FSA4480_ENABLE_DEVICE | FSA4480_ENABLE_USB; fsa->mode = TYPEC_STATE_SAFE; diff --git a/drivers/usb/typec/tcpm/tcpci.c b/drivers/usb/typec/tcpm/tcpci.c index b862fdf3fe1d4c..3e3dcb983ddeab 100644 --- a/drivers/usb/typec/tcpm/tcpci.c +++ b/drivers/usb/typec/tcpm/tcpci.c @@ -67,7 +67,7 @@ static int tcpci_write16(struct tcpci *tcpci, unsigned int reg, u16 val) return regmap_raw_write(tcpci->regmap, reg, &val, sizeof(u16)); } -static bool tcpci_check_std_output_cap(struct regmap *regmap, u8 mask) +static int tcpci_check_std_output_cap(struct regmap *regmap, u8 mask) { unsigned int reg; int ret; diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c index 26f9006e95e169..4b02d647425910 100644 --- a/drivers/usb/typec/tcpm/tcpm.c +++ b/drivers/usb/typec/tcpm/tcpm.c @@ -4515,7 +4515,7 @@ static inline enum tcpm_state hard_reset_state(struct tcpm_port *port) return ERROR_RECOVERY; if (port->pwr_role == TYPEC_SOURCE) return SRC_UNATTACHED; - if (port->state == SNK_WAIT_CAPABILITIES) + if (port->state == SNK_WAIT_CAPABILITIES_TIMEOUT) return SNK_READY; return SNK_UNATTACHED; } @@ -5655,7 +5655,6 @@ static void run_state_machine(struct tcpm_port *port) break; case PORT_RESET: tcpm_reset_port(port); - port->pd_events = 0; if (port->self_powered) tcpm_set_cc(port, TYPEC_CC_OPEN); else diff --git a/drivers/usb/typec/tipd/core.c b/drivers/usb/typec/tipd/core.c index ea768b19a7f1ec..dd51a25480bfb9 100644 --- a/drivers/usb/typec/tipd/core.c +++ b/drivers/usb/typec/tipd/core.c @@ -1191,14 +1191,14 @@ static int tps6598x_apply_patch(struct tps6598x *tps) dev_info(tps->dev, "Firmware update succeeded\n"); release_fw: - release_firmware(fw); if (ret) { dev_err(tps->dev, "Failed to write patch %s of %zu bytes\n", firmware_name, fw->size); } + release_firmware(fw); return ret; -}; +} static int cd321x_init(struct tps6598x *tps) { diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c index dcd3765cc1f532..4039851551c1b7 100644 --- a/drivers/usb/typec/ucsi/ucsi.c +++ b/drivers/usb/typec/ucsi/ucsi.c @@ -137,7 +137,7 @@ static int ucsi_run_command(struct ucsi *ucsi, u64 command, u32 *cci, if (ret) return ret; - return err; + return err ?: UCSI_CCI_LENGTH(*cci); } static int ucsi_read_error(struct ucsi *ucsi, u8 connector_num) @@ -238,13 +238,10 @@ static int ucsi_send_command_common(struct ucsi *ucsi, u64 cmd, mutex_lock(&ucsi->ppm_lock); ret = ucsi_run_command(ucsi, cmd, &cci, data, size, conn_ack); - if (cci & UCSI_CCI_BUSY) { - ret = ucsi_run_command(ucsi, UCSI_CANCEL, &cci, NULL, 0, false); - return ret ? ret : -EBUSY; - } - - if (cci & UCSI_CCI_ERROR) - return ucsi_read_error(ucsi, connector_num); + if (cci & UCSI_CCI_BUSY) + ret = ucsi_run_command(ucsi, UCSI_CANCEL, &cci, NULL, 0, false) ?: -EBUSY; + else if (cci & UCSI_CCI_ERROR) + ret = ucsi_read_error(ucsi, connector_num); mutex_unlock(&ucsi->ppm_lock); return ret; diff --git a/drivers/usb/usbip/vhci_hcd.c b/drivers/usb/usbip/vhci_hcd.c index 82650c11e45161..302a89aeb258a5 100644 --- a/drivers/usb/usbip/vhci_hcd.c +++ b/drivers/usb/usbip/vhci_hcd.c @@ -745,6 +745,7 @@ static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flag * */ if (usb_pipedevice(urb->pipe) == 0) { + struct usb_device *old; __u8 type = usb_pipetype(urb->pipe); struct usb_ctrlrequest *ctrlreq = (struct usb_ctrlrequest *) urb->setup_packet; @@ -755,14 +756,15 @@ static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flag goto no_need_xmit; } + old = vdev->udev; switch (ctrlreq->bRequest) { case USB_REQ_SET_ADDRESS: /* set_address may come when a device is reset */ dev_info(dev, "SetAddress Request (%d) to port %d\n", ctrlreq->wValue, vdev->rhport); - usb_put_dev(vdev->udev); vdev->udev = usb_get_dev(urb->dev); + usb_put_dev(old); spin_lock(&vdev->ud.lock); vdev->ud.status = VDEV_ST_USED; @@ -781,8 +783,8 @@ static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flag usbip_dbg_vhci_hc( "Not yet?:Get_Descriptor to device 0 (get max pipe size)\n"); - usb_put_dev(vdev->udev); vdev->udev = usb_get_dev(urb->dev); + usb_put_dev(old); goto out; default: @@ -1067,6 +1069,7 @@ static void vhci_shutdown_connection(struct usbip_device *ud) static void vhci_device_reset(struct usbip_device *ud) { struct vhci_device *vdev = container_of(ud, struct vhci_device, ud); + struct usb_device *old = vdev->udev; unsigned long flags; spin_lock_irqsave(&ud->lock, flags); @@ -1074,8 +1077,8 @@ static void vhci_device_reset(struct usbip_device *ud) vdev->speed = 0; vdev->devid = 0; - usb_put_dev(vdev->udev); vdev->udev = NULL; + usb_put_dev(old); if (ud->tcp_socket) { sockfd_put(ud->tcp_socket); diff --git a/drivers/vdpa/octeon_ep/octep_vdpa_hw.c b/drivers/vdpa/octeon_ep/octep_vdpa_hw.c index 7fa0491bb201eb..11bd76ae18cf93 100644 --- a/drivers/vdpa/octeon_ep/octep_vdpa_hw.c +++ b/drivers/vdpa/octeon_ep/octep_vdpa_hw.c @@ -140,7 +140,7 @@ static int octep_process_mbox(struct octep_hw *oct_hw, u16 id, u16 qid, void *bu val = octep_read_sig(mbox); if ((val & 0xFFFF) != MBOX_RSP_SIG) { dev_warn(&pdev->dev, "Invalid Signature from mbox : %d response\n", id); - return ret; + return -EINVAL; } val = octep_read_sts(mbox); diff --git a/drivers/vhost/vdpa.c b/drivers/vhost/vdpa.c index e31ec9ebc4ce84..478cd46a49ede2 100644 --- a/drivers/vhost/vdpa.c +++ b/drivers/vhost/vdpa.c @@ -1481,13 +1481,7 @@ static vm_fault_t vhost_vdpa_fault(struct vm_fault *vmf) notify = ops->get_vq_notification(vdpa, index); - vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); - if (remap_pfn_range(vma, vmf->address & PAGE_MASK, - PFN_DOWN(notify.addr), PAGE_SIZE, - vma->vm_page_prot)) - return VM_FAULT_SIGBUS; - - return VM_FAULT_NOPAGE; + return vmf_insert_pfn(vma, vmf->address & PAGE_MASK, PFN_DOWN(notify.addr)); } static const struct vm_operations_struct vhost_vdpa_vm_ops = { diff --git a/drivers/virtio/virtio.c b/drivers/virtio/virtio.c index a9b93e99c23a41..bc1f962e483b98 100644 --- a/drivers/virtio/virtio.c +++ b/drivers/virtio/virtio.c @@ -305,15 +305,9 @@ static int virtio_dev_probe(struct device *_d) if (err) goto err; - if (dev->config->create_avq) { - err = dev->config->create_avq(dev); - if (err) - goto err; - } - err = drv->probe(dev); if (err) - goto err_probe; + goto err; /* If probe didn't do it, mark device DRIVER_OK ourselves. */ if (!(dev->config->get_status(dev) & VIRTIO_CONFIG_S_DRIVER_OK)) @@ -326,9 +320,6 @@ static int virtio_dev_probe(struct device *_d) return 0; -err_probe: - if (dev->config->destroy_avq) - dev->config->destroy_avq(dev); err: virtio_add_status(dev, VIRTIO_CONFIG_S_FAILED); return err; @@ -344,9 +335,6 @@ static void virtio_dev_remove(struct device *_d) drv->remove(dev); - if (dev->config->destroy_avq) - dev->config->destroy_avq(dev); - /* Driver should have reset device. */ WARN_ON_ONCE(dev->config->get_status(dev)); @@ -524,9 +512,6 @@ int virtio_device_freeze(struct virtio_device *dev) } } - if (dev->config->destroy_avq) - dev->config->destroy_avq(dev); - return 0; } EXPORT_SYMBOL_GPL(virtio_device_freeze); @@ -562,16 +547,10 @@ int virtio_device_restore(struct virtio_device *dev) if (ret) goto err; - if (dev->config->create_avq) { - ret = dev->config->create_avq(dev); - if (ret) - goto err; - } - if (drv->restore) { ret = drv->restore(dev); if (ret) - goto err_restore; + goto err; } /* If restore didn't do it, mark device DRIVER_OK ourselves. */ @@ -582,9 +561,6 @@ int virtio_device_restore(struct virtio_device *dev) return 0; -err_restore: - if (dev->config->destroy_avq) - dev->config->destroy_avq(dev); err: virtio_add_status(dev, VIRTIO_CONFIG_S_FAILED); return ret; diff --git a/drivers/virtio/virtio_pci_common.c b/drivers/virtio/virtio_pci_common.c index 7d82facafd75ee..c44d8ba00c02c3 100644 --- a/drivers/virtio/virtio_pci_common.c +++ b/drivers/virtio/virtio_pci_common.c @@ -46,12 +46,26 @@ bool vp_notify(struct virtqueue *vq) return true; } +/* Notify all slow path virtqueues on an interrupt. */ +static void vp_vring_slow_path_interrupt(int irq, + struct virtio_pci_device *vp_dev) +{ + struct virtio_pci_vq_info *info; + unsigned long flags; + + spin_lock_irqsave(&vp_dev->lock, flags); + list_for_each_entry(info, &vp_dev->slow_virtqueues, node) + vring_interrupt(irq, info->vq); + spin_unlock_irqrestore(&vp_dev->lock, flags); +} + /* Handle a configuration change: Tell driver if it wants to know. */ static irqreturn_t vp_config_changed(int irq, void *opaque) { struct virtio_pci_device *vp_dev = opaque; virtio_config_changed(&vp_dev->vdev); + vp_vring_slow_path_interrupt(irq, vp_dev); return IRQ_HANDLED; } @@ -125,6 +139,9 @@ static int vp_request_msix_vectors(struct virtio_device *vdev, int nvectors, GFP_KERNEL)) goto error; + if (!per_vq_vectors) + desc = NULL; + if (desc) { flags |= PCI_IRQ_AFFINITY; desc->pre_vectors++; /* virtio config vector */ @@ -171,11 +188,17 @@ static int vp_request_msix_vectors(struct virtio_device *vdev, int nvectors, return err; } +static bool vp_is_slow_path_vector(u16 msix_vec) +{ + return msix_vec == VP_MSIX_CONFIG_VECTOR; +} + static struct virtqueue *vp_setup_vq(struct virtio_device *vdev, unsigned int index, void (*callback)(struct virtqueue *vq), const char *name, bool ctx, - u16 msix_vec) + u16 msix_vec, + struct virtio_pci_vq_info **p_info) { struct virtio_pci_device *vp_dev = to_vp_device(vdev); struct virtio_pci_vq_info *info = kmalloc(sizeof *info, GFP_KERNEL); @@ -194,13 +217,16 @@ static struct virtqueue *vp_setup_vq(struct virtio_device *vdev, unsigned int in info->vq = vq; if (callback) { spin_lock_irqsave(&vp_dev->lock, flags); - list_add(&info->node, &vp_dev->virtqueues); + if (!vp_is_slow_path_vector(msix_vec)) + list_add(&info->node, &vp_dev->virtqueues); + else + list_add(&info->node, &vp_dev->slow_virtqueues); spin_unlock_irqrestore(&vp_dev->lock, flags); } else { INIT_LIST_HEAD(&info->node); } - vp_dev->vqs[index] = info; + *p_info = info; return vq; out_info: @@ -236,13 +262,11 @@ void vp_del_vqs(struct virtio_device *vdev) int i; list_for_each_entry_safe(vq, n, &vdev->vqs, list) { - if (vp_dev->is_avq && vp_dev->is_avq(vdev, vq->index)) - continue; - if (vp_dev->per_vq_vectors) { int v = vp_dev->vqs[vq->index]->msix_vector; - if (v != VIRTIO_MSI_NO_VECTOR) { + if (v != VIRTIO_MSI_NO_VECTOR && + !vp_is_slow_path_vector(v)) { int irq = pci_irq_vector(vp_dev->pci_dev, v); irq_update_affinity_hint(irq, NULL); @@ -284,21 +308,85 @@ void vp_del_vqs(struct virtio_device *vdev) vp_dev->vqs = NULL; } +enum vp_vq_vector_policy { + VP_VQ_VECTOR_POLICY_EACH, + VP_VQ_VECTOR_POLICY_SHARED_SLOW, + VP_VQ_VECTOR_POLICY_SHARED, +}; + +static struct virtqueue * +vp_find_one_vq_msix(struct virtio_device *vdev, int queue_idx, + vq_callback_t *callback, const char *name, bool ctx, + bool slow_path, int *allocated_vectors, + enum vp_vq_vector_policy vector_policy, + struct virtio_pci_vq_info **p_info) +{ + struct virtio_pci_device *vp_dev = to_vp_device(vdev); + struct virtqueue *vq; + u16 msix_vec; + int err; + + if (!callback) + msix_vec = VIRTIO_MSI_NO_VECTOR; + else if (vector_policy == VP_VQ_VECTOR_POLICY_EACH || + (vector_policy == VP_VQ_VECTOR_POLICY_SHARED_SLOW && + !slow_path)) + msix_vec = (*allocated_vectors)++; + else if (vector_policy != VP_VQ_VECTOR_POLICY_EACH && + slow_path) + msix_vec = VP_MSIX_CONFIG_VECTOR; + else + msix_vec = VP_MSIX_VQ_VECTOR; + vq = vp_setup_vq(vdev, queue_idx, callback, name, ctx, msix_vec, + p_info); + if (IS_ERR(vq)) + return vq; + + if (vector_policy == VP_VQ_VECTOR_POLICY_SHARED || + msix_vec == VIRTIO_MSI_NO_VECTOR || + vp_is_slow_path_vector(msix_vec)) + return vq; + + /* allocate per-vq irq if available and necessary */ + snprintf(vp_dev->msix_names[msix_vec], sizeof(*vp_dev->msix_names), + "%s-%s", dev_name(&vp_dev->vdev.dev), name); + err = request_irq(pci_irq_vector(vp_dev->pci_dev, msix_vec), + vring_interrupt, 0, + vp_dev->msix_names[msix_vec], vq); + if (err) { + vp_del_vq(vq); + return ERR_PTR(err); + } + + return vq; +} + static int vp_find_vqs_msix(struct virtio_device *vdev, unsigned int nvqs, struct virtqueue *vqs[], struct virtqueue_info vqs_info[], - bool per_vq_vectors, + enum vp_vq_vector_policy vector_policy, struct irq_affinity *desc) { struct virtio_pci_device *vp_dev = to_vp_device(vdev); + struct virtio_pci_admin_vq *avq = &vp_dev->admin_vq; struct virtqueue_info *vqi; - u16 msix_vec; int i, err, nvectors, allocated_vectors, queue_idx = 0; + struct virtqueue *vq; + bool per_vq_vectors; + u16 avq_num = 0; vp_dev->vqs = kcalloc(nvqs, sizeof(*vp_dev->vqs), GFP_KERNEL); if (!vp_dev->vqs) return -ENOMEM; + if (vp_dev->avq_index) { + err = vp_dev->avq_index(vdev, &avq->vq_index, &avq_num); + if (err) + goto error_find; + } + + per_vq_vectors = vector_policy != VP_VQ_VECTOR_POLICY_SHARED; + if (per_vq_vectors) { /* Best option: one for change interrupt, one per vq. */ nvectors = 1; @@ -307,13 +395,14 @@ static int vp_find_vqs_msix(struct virtio_device *vdev, unsigned int nvqs, if (vqi->name && vqi->callback) ++nvectors; } + if (avq_num && vector_policy == VP_VQ_VECTOR_POLICY_EACH) + ++nvectors; } else { /* Second best: one for change, shared for all vqs. */ nvectors = 2; } - err = vp_request_msix_vectors(vdev, nvectors, per_vq_vectors, - per_vq_vectors ? desc : NULL); + err = vp_request_msix_vectors(vdev, nvectors, per_vq_vectors, desc); if (err) goto error_find; @@ -325,37 +414,27 @@ static int vp_find_vqs_msix(struct virtio_device *vdev, unsigned int nvqs, vqs[i] = NULL; continue; } - - if (!vqi->callback) - msix_vec = VIRTIO_MSI_NO_VECTOR; - else if (vp_dev->per_vq_vectors) - msix_vec = allocated_vectors++; - else - msix_vec = VP_MSIX_VQ_VECTOR; - vqs[i] = vp_setup_vq(vdev, queue_idx++, vqi->callback, - vqi->name, vqi->ctx, msix_vec); + vqs[i] = vp_find_one_vq_msix(vdev, queue_idx++, vqi->callback, + vqi->name, vqi->ctx, false, + &allocated_vectors, vector_policy, + &vp_dev->vqs[i]); if (IS_ERR(vqs[i])) { err = PTR_ERR(vqs[i]); goto error_find; } + } - if (!vp_dev->per_vq_vectors || msix_vec == VIRTIO_MSI_NO_VECTOR) - continue; - - /* allocate per-vq irq if available and necessary */ - snprintf(vp_dev->msix_names[msix_vec], - sizeof *vp_dev->msix_names, - "%s-%s", - dev_name(&vp_dev->vdev.dev), vqi->name); - err = request_irq(pci_irq_vector(vp_dev->pci_dev, msix_vec), - vring_interrupt, 0, - vp_dev->msix_names[msix_vec], - vqs[i]); - if (err) { - vp_del_vq(vqs[i]); - goto error_find; - } + if (!avq_num) + return 0; + sprintf(avq->name, "avq.%u", avq->vq_index); + vq = vp_find_one_vq_msix(vdev, avq->vq_index, vp_modern_avq_done, + avq->name, false, true, &allocated_vectors, + vector_policy, &vp_dev->admin_vq.info); + if (IS_ERR(vq)) { + err = PTR_ERR(vq); + goto error_find; } + return 0; error_find: @@ -368,12 +447,21 @@ static int vp_find_vqs_intx(struct virtio_device *vdev, unsigned int nvqs, struct virtqueue_info vqs_info[]) { struct virtio_pci_device *vp_dev = to_vp_device(vdev); + struct virtio_pci_admin_vq *avq = &vp_dev->admin_vq; int i, err, queue_idx = 0; + struct virtqueue *vq; + u16 avq_num = 0; vp_dev->vqs = kcalloc(nvqs, sizeof(*vp_dev->vqs), GFP_KERNEL); if (!vp_dev->vqs) return -ENOMEM; + if (vp_dev->avq_index) { + err = vp_dev->avq_index(vdev, &avq->vq_index, &avq_num); + if (err) + goto out_del_vqs; + } + err = request_irq(vp_dev->pci_dev->irq, vp_interrupt, IRQF_SHARED, dev_name(&vdev->dev), vp_dev); if (err) @@ -390,13 +478,24 @@ static int vp_find_vqs_intx(struct virtio_device *vdev, unsigned int nvqs, } vqs[i] = vp_setup_vq(vdev, queue_idx++, vqi->callback, vqi->name, vqi->ctx, - VIRTIO_MSI_NO_VECTOR); + VIRTIO_MSI_NO_VECTOR, &vp_dev->vqs[i]); if (IS_ERR(vqs[i])) { err = PTR_ERR(vqs[i]); goto out_del_vqs; } } + if (!avq_num) + return 0; + sprintf(avq->name, "avq.%u", avq->vq_index); + vq = vp_setup_vq(vdev, queue_idx++, vp_modern_avq_done, avq->name, + false, VIRTIO_MSI_NO_VECTOR, + &vp_dev->admin_vq.info); + if (IS_ERR(vq)) { + err = PTR_ERR(vq); + goto out_del_vqs; + } + return 0; out_del_vqs: vp_del_vqs(vdev); @@ -411,11 +510,20 @@ int vp_find_vqs(struct virtio_device *vdev, unsigned int nvqs, int err; /* Try MSI-X with one vector per queue. */ - err = vp_find_vqs_msix(vdev, nvqs, vqs, vqs_info, true, desc); + err = vp_find_vqs_msix(vdev, nvqs, vqs, vqs_info, + VP_VQ_VECTOR_POLICY_EACH, desc); + if (!err) + return 0; + /* Fallback: MSI-X with one shared vector for config and + * slow path queues, one vector per queue for the rest. + */ + err = vp_find_vqs_msix(vdev, nvqs, vqs, vqs_info, + VP_VQ_VECTOR_POLICY_SHARED_SLOW, desc); if (!err) return 0; /* Fallback: MSI-X with one vector for config, one shared for queues. */ - err = vp_find_vqs_msix(vdev, nvqs, vqs, vqs_info, false, desc); + err = vp_find_vqs_msix(vdev, nvqs, vqs, vqs_info, + VP_VQ_VECTOR_POLICY_SHARED, desc); if (!err) return 0; /* Is there an interrupt? If not give up. */ @@ -466,7 +574,8 @@ const struct cpumask *vp_get_vq_affinity(struct virtio_device *vdev, int index) struct virtio_pci_device *vp_dev = to_vp_device(vdev); if (!vp_dev->per_vq_vectors || - vp_dev->vqs[index]->msix_vector == VIRTIO_MSI_NO_VECTOR) + vp_dev->vqs[index]->msix_vector == VIRTIO_MSI_NO_VECTOR || + vp_is_slow_path_vector(vp_dev->vqs[index]->msix_vector)) return NULL; return pci_irq_get_affinity(vp_dev->pci_dev, @@ -574,6 +683,7 @@ static int virtio_pci_probe(struct pci_dev *pci_dev, vp_dev->vdev.dev.release = virtio_pci_release_dev; vp_dev->pci_dev = pci_dev; INIT_LIST_HEAD(&vp_dev->virtqueues); + INIT_LIST_HEAD(&vp_dev->slow_virtqueues); spin_lock_init(&vp_dev->lock); /* enable the device */ diff --git a/drivers/virtio/virtio_pci_common.h b/drivers/virtio/virtio_pci_common.h index 3c4bb2d6163a92..1d9c49947f52d1 100644 --- a/drivers/virtio/virtio_pci_common.h +++ b/drivers/virtio/virtio_pci_common.h @@ -35,7 +35,7 @@ struct virtio_pci_vq_info { /* the actual virtqueue */ struct virtqueue *vq; - /* the list node for the virtqueues list */ + /* the list node for the virtqueues or slow_virtqueues list */ struct list_head node; /* MSI-X vector (or none) */ @@ -44,9 +44,9 @@ struct virtio_pci_vq_info { struct virtio_pci_admin_vq { /* Virtqueue info associated with this admin queue. */ - struct virtio_pci_vq_info info; - /* serializing admin commands execution and virtqueue deletion */ - struct mutex cmd_lock; + struct virtio_pci_vq_info *info; + /* Protects virtqueue access. */ + spinlock_t lock; u64 supported_cmds; /* Name of the admin queue: avq.$vq_index. */ char name[10]; @@ -66,9 +66,12 @@ struct virtio_pci_device { /* Where to read and clear interrupt */ u8 __iomem *isr; - /* a list of queues so we can dispatch IRQs */ + /* Lists of queues and potentially slow path queues + * so we can dispatch IRQs. + */ spinlock_t lock; struct list_head virtqueues; + struct list_head slow_virtqueues; /* Array of all virtqueues reported in the * PCI common config num_queues field @@ -102,7 +105,7 @@ struct virtio_pci_device { void (*del_vq)(struct virtio_pci_vq_info *info); u16 (*config_vector)(struct virtio_pci_device *vp_dev, u16 vector); - bool (*is_avq)(struct virtio_device *vdev, unsigned int index); + int (*avq_index)(struct virtio_device *vdev, u16 *index, u16 *num); }; /* Constants for MSI-X */ @@ -175,6 +178,7 @@ struct virtio_device *virtio_pci_vf_get_pf_dev(struct pci_dev *pdev); #define VIRTIO_ADMIN_CMD_BITMAP 0 #endif +void vp_modern_avq_done(struct virtqueue *vq); int vp_modern_admin_cmd_exec(struct virtio_device *vdev, struct virtio_admin_cmd *cmd); diff --git a/drivers/virtio/virtio_pci_modern.c b/drivers/virtio/virtio_pci_modern.c index 3b5b9499a53a65..9193c30d640aeb 100644 --- a/drivers/virtio/virtio_pci_modern.c +++ b/drivers/virtio/virtio_pci_modern.c @@ -28,6 +28,21 @@ static u64 vp_get_features(struct virtio_device *vdev) return vp_modern_get_features(&vp_dev->mdev); } +static int vp_avq_index(struct virtio_device *vdev, u16 *index, u16 *num) +{ + struct virtio_pci_device *vp_dev = to_vp_device(vdev); + + *num = 0; + if (!virtio_has_feature(vdev, VIRTIO_F_ADMIN_VQ)) + return 0; + + *num = vp_modern_avq_num(&vp_dev->mdev); + if (!(*num)) + return -EINVAL; + *index = vp_modern_avq_index(&vp_dev->mdev); + return 0; +} + static bool vp_is_avq(struct virtio_device *vdev, unsigned int index) { struct virtio_pci_device *vp_dev = to_vp_device(vdev); @@ -38,17 +53,35 @@ static bool vp_is_avq(struct virtio_device *vdev, unsigned int index) return index == vp_dev->admin_vq.vq_index; } +void vp_modern_avq_done(struct virtqueue *vq) +{ + struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev); + struct virtio_pci_admin_vq *admin_vq = &vp_dev->admin_vq; + struct virtio_admin_cmd *cmd; + unsigned long flags; + unsigned int len; + + spin_lock_irqsave(&admin_vq->lock, flags); + do { + virtqueue_disable_cb(vq); + while ((cmd = virtqueue_get_buf(vq, &len))) + complete(&cmd->completion); + } while (!virtqueue_enable_cb(vq)); + spin_unlock_irqrestore(&admin_vq->lock, flags); +} + static int virtqueue_exec_admin_cmd(struct virtio_pci_admin_vq *admin_vq, u16 opcode, struct scatterlist **sgs, unsigned int out_num, unsigned int in_num, - void *data) + struct virtio_admin_cmd *cmd) { struct virtqueue *vq; - int ret, len; + unsigned long flags; + int ret; - vq = admin_vq->info.vq; + vq = admin_vq->info->vq; if (!vq) return -EIO; @@ -57,21 +90,33 @@ static int virtqueue_exec_admin_cmd(struct virtio_pci_admin_vq *admin_vq, !((1ULL << opcode) & admin_vq->supported_cmds)) return -EOPNOTSUPP; - ret = virtqueue_add_sgs(vq, sgs, out_num, in_num, data, GFP_KERNEL); - if (ret < 0) - return -EIO; + init_completion(&cmd->completion); - if (unlikely(!virtqueue_kick(vq))) +again: + if (virtqueue_is_broken(vq)) return -EIO; - while (!virtqueue_get_buf(vq, &len) && - !virtqueue_is_broken(vq)) - cpu_relax(); + spin_lock_irqsave(&admin_vq->lock, flags); + ret = virtqueue_add_sgs(vq, sgs, out_num, in_num, cmd, GFP_KERNEL); + if (ret < 0) { + if (ret == -ENOSPC) { + spin_unlock_irqrestore(&admin_vq->lock, flags); + cpu_relax(); + goto again; + } + goto unlock_err; + } + if (!virtqueue_kick(vq)) + goto unlock_err; + spin_unlock_irqrestore(&admin_vq->lock, flags); - if (virtqueue_is_broken(vq)) - return -EIO; + wait_for_completion(&cmd->completion); - return 0; + return cmd->ret; + +unlock_err: + spin_unlock_irqrestore(&admin_vq->lock, flags); + return -EIO; } int vp_modern_admin_cmd_exec(struct virtio_device *vdev, @@ -122,12 +167,9 @@ int vp_modern_admin_cmd_exec(struct virtio_device *vdev, in_num++; } - mutex_lock(&vp_dev->admin_vq.cmd_lock); ret = virtqueue_exec_admin_cmd(&vp_dev->admin_vq, le16_to_cpu(cmd->opcode), - sgs, out_num, in_num, sgs); - mutex_unlock(&vp_dev->admin_vq.cmd_lock); - + sgs, out_num, in_num, cmd); if (ret) { dev_err(&vdev->dev, "Failed to execute command on admin vq: %d\n.", ret); @@ -188,25 +230,29 @@ static void virtio_pci_admin_cmd_list_init(struct virtio_device *virtio_dev) static void vp_modern_avq_activate(struct virtio_device *vdev) { - struct virtio_pci_device *vp_dev = to_vp_device(vdev); - struct virtio_pci_admin_vq *admin_vq = &vp_dev->admin_vq; - if (!virtio_has_feature(vdev, VIRTIO_F_ADMIN_VQ)) return; - __virtqueue_unbreak(admin_vq->info.vq); virtio_pci_admin_cmd_list_init(vdev); } -static void vp_modern_avq_deactivate(struct virtio_device *vdev) +static void vp_modern_avq_cleanup(struct virtio_device *vdev) { struct virtio_pci_device *vp_dev = to_vp_device(vdev); - struct virtio_pci_admin_vq *admin_vq = &vp_dev->admin_vq; + struct virtio_admin_cmd *cmd; + struct virtqueue *vq; if (!virtio_has_feature(vdev, VIRTIO_F_ADMIN_VQ)) return; - __virtqueue_break(admin_vq->info.vq); + vq = vp_dev->vqs[vp_dev->admin_vq.vq_index]->vq; + if (!vq) + return; + + while ((cmd = virtqueue_detach_unused_buf(vq))) { + cmd->ret = -EIO; + complete(&cmd->completion); + } } static void vp_transport_features(struct virtio_device *vdev, u64 features) @@ -403,7 +449,7 @@ static void vp_reset(struct virtio_device *vdev) while (vp_modern_get_status(mdev)) msleep(1); - vp_modern_avq_deactivate(vdev); + vp_modern_avq_cleanup(vdev); /* Flush pending VQ/configuration callbacks. */ vp_synchronize_vectors(vdev); @@ -552,8 +598,7 @@ static struct virtqueue *setup_vq(struct virtio_pci_device *vp_dev, if (index >= vp_modern_get_num_queues(mdev) && !is_avq) return ERR_PTR(-EINVAL); - num = is_avq ? - VIRTIO_AVQ_SGS_MAX : vp_modern_get_queue_size(mdev, index); + num = vp_modern_get_queue_size(mdev, index); /* Check if queue is either not available or already active. */ if (!num || vp_modern_get_queue_enable(mdev, index)) return ERR_PTR(-ENOENT); @@ -580,12 +625,6 @@ static struct virtqueue *setup_vq(struct virtio_pci_device *vp_dev, goto err; } - if (is_avq) { - mutex_lock(&vp_dev->admin_vq.cmd_lock); - vp_dev->admin_vq.info.vq = vq; - mutex_unlock(&vp_dev->admin_vq.cmd_lock); - } - return vq; err: @@ -620,12 +659,6 @@ static void del_vq(struct virtio_pci_vq_info *info) struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev); struct virtio_pci_modern_device *mdev = &vp_dev->mdev; - if (vp_is_avq(&vp_dev->vdev, vq->index)) { - mutex_lock(&vp_dev->admin_vq.cmd_lock); - vp_dev->admin_vq.info.vq = NULL; - mutex_unlock(&vp_dev->admin_vq.cmd_lock); - } - if (vp_dev->msix_enabled) vp_modern_queue_vector(mdev, vq->index, VIRTIO_MSI_NO_VECTOR); @@ -735,45 +768,6 @@ static bool vp_get_shm_region(struct virtio_device *vdev, return true; } -static int vp_modern_create_avq(struct virtio_device *vdev) -{ - struct virtio_pci_device *vp_dev = to_vp_device(vdev); - struct virtio_pci_admin_vq *avq; - struct virtqueue *vq; - u16 admin_q_num; - - if (!virtio_has_feature(vdev, VIRTIO_F_ADMIN_VQ)) - return 0; - - admin_q_num = vp_modern_avq_num(&vp_dev->mdev); - if (!admin_q_num) - return -EINVAL; - - avq = &vp_dev->admin_vq; - avq->vq_index = vp_modern_avq_index(&vp_dev->mdev); - sprintf(avq->name, "avq.%u", avq->vq_index); - vq = vp_dev->setup_vq(vp_dev, &vp_dev->admin_vq.info, avq->vq_index, NULL, - avq->name, NULL, VIRTIO_MSI_NO_VECTOR); - if (IS_ERR(vq)) { - dev_err(&vdev->dev, "failed to setup admin virtqueue, err=%ld", - PTR_ERR(vq)); - return PTR_ERR(vq); - } - - vp_modern_set_queue_enable(&vp_dev->mdev, avq->info.vq->index, true); - return 0; -} - -static void vp_modern_destroy_avq(struct virtio_device *vdev) -{ - struct virtio_pci_device *vp_dev = to_vp_device(vdev); - - if (!virtio_has_feature(vdev, VIRTIO_F_ADMIN_VQ)) - return; - - vp_dev->del_vq(&vp_dev->admin_vq.info); -} - static const struct virtio_config_ops virtio_pci_config_nodev_ops = { .get = NULL, .set = NULL, @@ -792,8 +786,6 @@ static const struct virtio_config_ops virtio_pci_config_nodev_ops = { .get_shm_region = vp_get_shm_region, .disable_vq_and_reset = vp_modern_disable_vq_and_reset, .enable_vq_after_reset = vp_modern_enable_vq_after_reset, - .create_avq = vp_modern_create_avq, - .destroy_avq = vp_modern_destroy_avq, }; static const struct virtio_config_ops virtio_pci_config_ops = { @@ -814,8 +806,6 @@ static const struct virtio_config_ops virtio_pci_config_ops = { .get_shm_region = vp_get_shm_region, .disable_vq_and_reset = vp_modern_disable_vq_and_reset, .enable_vq_after_reset = vp_modern_enable_vq_after_reset, - .create_avq = vp_modern_create_avq, - .destroy_avq = vp_modern_destroy_avq, }; /* the PCI probing function */ @@ -839,11 +829,11 @@ int virtio_pci_modern_probe(struct virtio_pci_device *vp_dev) vp_dev->config_vector = vp_config_vector; vp_dev->setup_vq = setup_vq; vp_dev->del_vq = del_vq; - vp_dev->is_avq = vp_is_avq; + vp_dev->avq_index = vp_avq_index; vp_dev->isr = mdev->isr; vp_dev->vdev.id = mdev->id; - mutex_init(&vp_dev->admin_vq.cmd_lock); + spin_lock_init(&vp_dev->admin_vq.lock); return 0; } @@ -851,6 +841,5 @@ void virtio_pci_modern_remove(struct virtio_pci_device *vp_dev) { struct virtio_pci_modern_device *mdev = &vp_dev->mdev; - mutex_destroy(&vp_dev->admin_vq.cmd_lock); vp_modern_remove(mdev); } diff --git a/fs/9p/vfs_addr.c b/fs/9p/vfs_addr.c index a97ceb105cd8dd..24fdc74caeba47 100644 --- a/fs/9p/vfs_addr.c +++ b/fs/9p/vfs_addr.c @@ -75,7 +75,8 @@ static void v9fs_issue_read(struct netfs_io_subrequest *subreq) /* if we just extended the file size, any portion not in * cache won't be on server and is zeroes */ - __set_bit(NETFS_SREQ_CLEAR_TAIL, &subreq->flags); + if (subreq->rreq->origin != NETFS_DIO_READ) + __set_bit(NETFS_SREQ_CLEAR_TAIL, &subreq->flags); netfs_subreq_terminated(subreq, err ?: total, false); } diff --git a/fs/afs/file.c b/fs/afs/file.c index c3f0c45ae9a9b6..ec1be0091fdb56 100644 --- a/fs/afs/file.c +++ b/fs/afs/file.c @@ -242,7 +242,8 @@ static void afs_fetch_data_notify(struct afs_operation *op) req->error = error; if (subreq) { - __set_bit(NETFS_SREQ_CLEAR_TAIL, &subreq->flags); + if (subreq->rreq->origin != NETFS_DIO_READ) + __set_bit(NETFS_SREQ_CLEAR_TAIL, &subreq->flags); netfs_subreq_terminated(subreq, error ?: req->actual_len, false); req->subreq = NULL; } else if (req->done) { diff --git a/fs/bcachefs/acl.c b/fs/bcachefs/acl.c index a7b425d3c8a0e4..331a17f3f113b4 100644 --- a/fs/bcachefs/acl.c +++ b/fs/bcachefs/acl.c @@ -272,16 +272,19 @@ bch2_acl_to_xattr(struct btree_trans *trans, return xattr; } -struct posix_acl *bch2_get_acl(struct mnt_idmap *idmap, - struct dentry *dentry, int type) +struct posix_acl *bch2_get_acl(struct inode *vinode, int type, bool rcu) { - struct bch_inode_info *inode = to_bch_ei(dentry->d_inode); + struct bch_inode_info *inode = to_bch_ei(vinode); 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_trans *trans = bch2_trans_get(c); struct btree_iter iter = { NULL }; struct posix_acl *acl = NULL; + + if (rcu) + return ERR_PTR(-ECHILD); + + struct btree_trans *trans = bch2_trans_get(c); retry: bch2_trans_begin(trans); diff --git a/fs/bcachefs/acl.h b/fs/bcachefs/acl.h index 27e7eec0f278c6..fe730a6bf0c18c 100644 --- a/fs/bcachefs/acl.h +++ b/fs/bcachefs/acl.h @@ -28,7 +28,7 @@ void bch2_acl_to_text(struct printbuf *, const void *, size_t); #ifdef CONFIG_BCACHEFS_POSIX_ACL -struct posix_acl *bch2_get_acl(struct mnt_idmap *, struct dentry *, int); +struct posix_acl *bch2_get_acl(struct inode *, int, bool); int bch2_set_acl_trans(struct btree_trans *, subvol_inum, struct bch_inode_unpacked *, diff --git a/fs/bcachefs/alloc_background.c b/fs/bcachefs/alloc_background.c index d9c5a92fa708fb..fd3a2522bc3ed3 100644 --- a/fs/bcachefs/alloc_background.c +++ b/fs/bcachefs/alloc_background.c @@ -196,75 +196,71 @@ static unsigned bch_alloc_v1_val_u64s(const struct bch_alloc *a) return DIV_ROUND_UP(bytes, sizeof(u64)); } -int bch2_alloc_v1_invalid(struct bch_fs *c, struct bkey_s_c k, - enum bch_validate_flags flags, - struct printbuf *err) +int bch2_alloc_v1_validate(struct bch_fs *c, struct bkey_s_c k, + enum bch_validate_flags flags) { struct bkey_s_c_alloc a = bkey_s_c_to_alloc(k); int ret = 0; /* allow for unknown fields */ - bkey_fsck_err_on(bkey_val_u64s(a.k) < bch_alloc_v1_val_u64s(a.v), c, err, - alloc_v1_val_size_bad, + bkey_fsck_err_on(bkey_val_u64s(a.k) < bch_alloc_v1_val_u64s(a.v), + c, alloc_v1_val_size_bad, "incorrect value size (%zu < %u)", bkey_val_u64s(a.k), bch_alloc_v1_val_u64s(a.v)); fsck_err: return ret; } -int bch2_alloc_v2_invalid(struct bch_fs *c, struct bkey_s_c k, - enum bch_validate_flags flags, - struct printbuf *err) +int bch2_alloc_v2_validate(struct bch_fs *c, struct bkey_s_c k, + enum bch_validate_flags flags) { struct bkey_alloc_unpacked u; int ret = 0; - bkey_fsck_err_on(bch2_alloc_unpack_v2(&u, k), c, err, - alloc_v2_unpack_error, + bkey_fsck_err_on(bch2_alloc_unpack_v2(&u, k), + c, alloc_v2_unpack_error, "unpack error"); fsck_err: return ret; } -int bch2_alloc_v3_invalid(struct bch_fs *c, struct bkey_s_c k, - enum bch_validate_flags flags, - struct printbuf *err) +int bch2_alloc_v3_validate(struct bch_fs *c, struct bkey_s_c k, + enum bch_validate_flags flags) { struct bkey_alloc_unpacked u; int ret = 0; - bkey_fsck_err_on(bch2_alloc_unpack_v3(&u, k), c, err, - alloc_v2_unpack_error, + bkey_fsck_err_on(bch2_alloc_unpack_v3(&u, k), + c, alloc_v2_unpack_error, "unpack error"); fsck_err: return ret; } -int bch2_alloc_v4_invalid(struct bch_fs *c, struct bkey_s_c k, - enum bch_validate_flags flags, struct printbuf *err) +int bch2_alloc_v4_validate(struct bch_fs *c, struct bkey_s_c k, + enum bch_validate_flags flags) { struct bkey_s_c_alloc_v4 a = bkey_s_c_to_alloc_v4(k); int ret = 0; - bkey_fsck_err_on(alloc_v4_u64s_noerror(a.v) > bkey_val_u64s(k.k), c, err, - alloc_v4_val_size_bad, + bkey_fsck_err_on(alloc_v4_u64s_noerror(a.v) > bkey_val_u64s(k.k), + c, alloc_v4_val_size_bad, "bad val size (%u > %zu)", alloc_v4_u64s_noerror(a.v), bkey_val_u64s(k.k)); bkey_fsck_err_on(!BCH_ALLOC_V4_BACKPOINTERS_START(a.v) && - BCH_ALLOC_V4_NR_BACKPOINTERS(a.v), c, err, - alloc_v4_backpointers_start_bad, + BCH_ALLOC_V4_NR_BACKPOINTERS(a.v), + c, alloc_v4_backpointers_start_bad, "invalid backpointers_start"); - bkey_fsck_err_on(alloc_data_type(*a.v, a.v->data_type) != a.v->data_type, c, err, - alloc_key_data_type_bad, + bkey_fsck_err_on(alloc_data_type(*a.v, a.v->data_type) != a.v->data_type, + c, alloc_key_data_type_bad, "invalid data type (got %u should be %u)", a.v->data_type, alloc_data_type(*a.v, a.v->data_type)); for (unsigned i = 0; i < 2; i++) bkey_fsck_err_on(a.v->io_time[i] > LRU_TIME_MAX, - c, err, - alloc_key_io_time_bad, + c, alloc_key_io_time_bad, "invalid io_time[%s]: %llu, max %llu", i == READ ? "read" : "write", a.v->io_time[i], LRU_TIME_MAX); @@ -282,7 +278,7 @@ int bch2_alloc_v4_invalid(struct bch_fs *c, struct bkey_s_c k, a.v->dirty_sectors || a.v->cached_sectors || a.v->stripe, - c, err, alloc_key_empty_but_have_data, + c, alloc_key_empty_but_have_data, "empty data type free but have data %u.%u.%u %u", stripe_sectors, a.v->dirty_sectors, @@ -296,7 +292,7 @@ int bch2_alloc_v4_invalid(struct bch_fs *c, struct bkey_s_c k, case BCH_DATA_parity: bkey_fsck_err_on(!a.v->dirty_sectors && !stripe_sectors, - c, err, alloc_key_dirty_sectors_0, + c, alloc_key_dirty_sectors_0, "data_type %s but dirty_sectors==0", bch2_data_type_str(a.v->data_type)); break; @@ -305,12 +301,12 @@ int bch2_alloc_v4_invalid(struct bch_fs *c, struct bkey_s_c k, a.v->dirty_sectors || stripe_sectors || a.v->stripe, - c, err, alloc_key_cached_inconsistency, + c, alloc_key_cached_inconsistency, "data type inconsistency"); bkey_fsck_err_on(!a.v->io_time[READ] && c->curr_recovery_pass > BCH_RECOVERY_PASS_check_alloc_to_lru_refs, - c, err, alloc_key_cached_but_read_time_zero, + c, alloc_key_cached_but_read_time_zero, "cached bucket with read_time == 0"); break; case BCH_DATA_stripe: @@ -513,14 +509,13 @@ static unsigned alloc_gen(struct bkey_s_c k, unsigned offset) : 0; } -int bch2_bucket_gens_invalid(struct bch_fs *c, struct bkey_s_c k, - enum bch_validate_flags flags, - struct printbuf *err) +int bch2_bucket_gens_validate(struct bch_fs *c, struct bkey_s_c k, + enum bch_validate_flags flags) { int ret = 0; - bkey_fsck_err_on(bkey_val_bytes(k.k) != sizeof(struct bch_bucket_gens), c, err, - bucket_gens_val_size_bad, + bkey_fsck_err_on(bkey_val_bytes(k.k) != sizeof(struct bch_bucket_gens), + c, bucket_gens_val_size_bad, "bad val size (%zu != %zu)", bkey_val_bytes(k.k), sizeof(struct bch_bucket_gens)); fsck_err: @@ -829,7 +824,19 @@ int bch2_trigger_alloc(struct btree_trans *trans, struct bch_alloc_v4 old_a_convert; const struct bch_alloc_v4 *old_a = bch2_alloc_to_v4(old, &old_a_convert); - struct bch_alloc_v4 *new_a = bkey_s_to_alloc_v4(new).v; + + struct bch_alloc_v4 *new_a; + if (likely(new.k->type == KEY_TYPE_alloc_v4)) { + new_a = bkey_s_to_alloc_v4(new).v; + } else { + BUG_ON(!(flags & BTREE_TRIGGER_gc)); + + struct bkey_i_alloc_v4 *new_ka = bch2_alloc_to_v4_mut_inlined(trans, new.s_c); + ret = PTR_ERR_OR_ZERO(new_ka); + if (unlikely(ret)) + goto err; + new_a = &new_ka->v; + } if (flags & BTREE_TRIGGER_transactional) { alloc_data_type_set(new_a, new_a->data_type); diff --git a/fs/bcachefs/alloc_background.h b/fs/bcachefs/alloc_background.h index 8d2b62c9588e73..fd790b03fbe198 100644 --- a/fs/bcachefs/alloc_background.h +++ b/fs/bcachefs/alloc_background.h @@ -82,6 +82,14 @@ static inline bool bucket_data_type_mismatch(enum bch_data_type bucket, bucket_data_type(bucket) != bucket_data_type(ptr); } +/* + * It is my general preference to use unsigned types for unsigned quantities - + * however, these helpers are used in disk accounting calculations run by + * triggers where the output will be negated and added to an s64. unsigned is + * right out even though all these quantities will fit in 32 bits, since it + * won't be sign extended correctly; u64 will negate "correctly", but s64 is the + * simpler option here. + */ static inline s64 bch2_bucket_sectors_total(struct bch_alloc_v4 a) { return a.stripe_sectors + a.dirty_sectors + a.cached_sectors; @@ -142,7 +150,9 @@ static inline void alloc_data_type_set(struct bch_alloc_v4 *a, enum bch_data_typ static inline u64 alloc_lru_idx_read(struct bch_alloc_v4 a) { - return a.data_type == BCH_DATA_cached ? a.io_time[READ] : 0; + return a.data_type == BCH_DATA_cached + ? a.io_time[READ] & LRU_TIME_MAX + : 0; } #define DATA_TYPES_MOVABLE \ @@ -166,8 +176,8 @@ static inline u64 alloc_lru_idx_fragmentation(struct bch_alloc_v4 a, * avoid overflowing LRU_TIME_BITS on a corrupted fs, when * bucket_sectors_dirty is (much) bigger than bucket_size */ - u64 d = min(bch2_bucket_sectors_dirty(a), - ca->mi.bucket_size); + u64 d = min_t(s64, bch2_bucket_sectors_dirty(a), + ca->mi.bucket_size); return div_u64(d * (1ULL << 31), ca->mi.bucket_size); } @@ -232,52 +242,48 @@ struct bkey_i_alloc_v4 *bch2_alloc_to_v4_mut(struct btree_trans *, struct bkey_s int bch2_bucket_io_time_reset(struct btree_trans *, unsigned, size_t, int); -int bch2_alloc_v1_invalid(struct bch_fs *, struct bkey_s_c, - enum bch_validate_flags, struct printbuf *); -int bch2_alloc_v2_invalid(struct bch_fs *, struct bkey_s_c, - enum bch_validate_flags, struct printbuf *); -int bch2_alloc_v3_invalid(struct bch_fs *, struct bkey_s_c, - enum bch_validate_flags, struct printbuf *); -int bch2_alloc_v4_invalid(struct bch_fs *, struct bkey_s_c, - enum bch_validate_flags, struct printbuf *); +int bch2_alloc_v1_validate(struct bch_fs *, struct bkey_s_c, enum bch_validate_flags); +int bch2_alloc_v2_validate(struct bch_fs *, struct bkey_s_c, enum bch_validate_flags); +int bch2_alloc_v3_validate(struct bch_fs *, struct bkey_s_c, enum bch_validate_flags); +int bch2_alloc_v4_validate(struct bch_fs *, struct bkey_s_c, enum bch_validate_flags); void bch2_alloc_v4_swab(struct bkey_s); void bch2_alloc_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c); #define bch2_bkey_ops_alloc ((struct bkey_ops) { \ - .key_invalid = bch2_alloc_v1_invalid, \ + .key_validate = bch2_alloc_v1_validate, \ .val_to_text = bch2_alloc_to_text, \ .trigger = bch2_trigger_alloc, \ .min_val_size = 8, \ }) #define bch2_bkey_ops_alloc_v2 ((struct bkey_ops) { \ - .key_invalid = bch2_alloc_v2_invalid, \ + .key_validate = bch2_alloc_v2_validate, \ .val_to_text = bch2_alloc_to_text, \ .trigger = bch2_trigger_alloc, \ .min_val_size = 8, \ }) #define bch2_bkey_ops_alloc_v3 ((struct bkey_ops) { \ - .key_invalid = bch2_alloc_v3_invalid, \ + .key_validate = bch2_alloc_v3_validate, \ .val_to_text = bch2_alloc_to_text, \ .trigger = bch2_trigger_alloc, \ .min_val_size = 16, \ }) #define bch2_bkey_ops_alloc_v4 ((struct bkey_ops) { \ - .key_invalid = bch2_alloc_v4_invalid, \ + .key_validate = bch2_alloc_v4_validate, \ .val_to_text = bch2_alloc_to_text, \ .swab = bch2_alloc_v4_swab, \ .trigger = bch2_trigger_alloc, \ .min_val_size = 48, \ }) -int bch2_bucket_gens_invalid(struct bch_fs *, struct bkey_s_c, - enum bch_validate_flags, struct printbuf *); +int bch2_bucket_gens_validate(struct bch_fs *, struct bkey_s_c, + enum bch_validate_flags); void bch2_bucket_gens_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c); #define bch2_bkey_ops_bucket_gens ((struct bkey_ops) { \ - .key_invalid = bch2_bucket_gens_invalid, \ + .key_validate = bch2_bucket_gens_validate, \ .val_to_text = bch2_bucket_gens_to_text, \ }) diff --git a/fs/bcachefs/alloc_foreground.c b/fs/bcachefs/alloc_foreground.c index 618d2ff0292ec3..8563c2d268476e 100644 --- a/fs/bcachefs/alloc_foreground.c +++ b/fs/bcachefs/alloc_foreground.c @@ -1603,7 +1603,8 @@ void bch2_open_bucket_to_text(struct printbuf *out, struct bch_fs *c, struct ope prt_newline(out); } -void bch2_open_buckets_to_text(struct printbuf *out, struct bch_fs *c) +void bch2_open_buckets_to_text(struct printbuf *out, struct bch_fs *c, + struct bch_dev *ca) { struct open_bucket *ob; @@ -1613,7 +1614,8 @@ void bch2_open_buckets_to_text(struct printbuf *out, struct bch_fs *c) ob < c->open_buckets + ARRAY_SIZE(c->open_buckets); ob++) { spin_lock(&ob->lock); - if (ob->valid && !ob->on_partial_list) + if (ob->valid && !ob->on_partial_list && + (!ca || ob->dev == ca->dev_idx)) bch2_open_bucket_to_text(out, c, ob); spin_unlock(&ob->lock); } @@ -1738,7 +1740,7 @@ void bch2_dev_alloc_debug_to_text(struct printbuf *out, struct bch_dev *ca) printbuf_tabstop_push(out, 16); printbuf_tabstop_push(out, 16); - bch2_dev_usage_to_text(out, &stats); + bch2_dev_usage_to_text(out, ca, &stats); prt_newline(out); @@ -1756,11 +1758,12 @@ void bch2_dev_alloc_debug_to_text(struct printbuf *out, struct bch_dev *ca) prt_printf(out, "buckets to invalidate\t%llu\r\n", should_invalidate_buckets(ca, stats)); } -void bch2_print_allocator_stuck(struct bch_fs *c) +static noinline void bch2_print_allocator_stuck(struct bch_fs *c) { struct printbuf buf = PRINTBUF; - prt_printf(&buf, "Allocator stuck? Waited for 10 seconds\n"); + prt_printf(&buf, "Allocator stuck? Waited for %u seconds\n", + c->opts.allocator_stuck_timeout); prt_printf(&buf, "Allocator debug:\n"); printbuf_indent_add(&buf, 2); @@ -1790,3 +1793,24 @@ void bch2_print_allocator_stuck(struct bch_fs *c) bch2_print_string_as_lines(KERN_ERR, buf.buf); printbuf_exit(&buf); } + +static inline unsigned allocator_wait_timeout(struct bch_fs *c) +{ + if (c->allocator_last_stuck && + time_after(c->allocator_last_stuck + HZ * 60 * 2, jiffies)) + return 0; + + return c->opts.allocator_stuck_timeout * HZ; +} + +void __bch2_wait_on_allocator(struct bch_fs *c, struct closure *cl) +{ + unsigned t = allocator_wait_timeout(c); + + if (t && closure_sync_timeout(cl, t)) { + c->allocator_last_stuck = jiffies; + bch2_print_allocator_stuck(c); + } + + closure_sync(cl); +} diff --git a/fs/bcachefs/alloc_foreground.h b/fs/bcachefs/alloc_foreground.h index 6da9e7e29026f2..386d231ceca3f6 100644 --- a/fs/bcachefs/alloc_foreground.h +++ b/fs/bcachefs/alloc_foreground.h @@ -223,7 +223,7 @@ static inline struct write_point_specifier writepoint_ptr(struct write_point *wp void bch2_fs_allocator_foreground_init(struct bch_fs *); void bch2_open_bucket_to_text(struct printbuf *, struct bch_fs *, struct open_bucket *); -void bch2_open_buckets_to_text(struct printbuf *, struct bch_fs *); +void bch2_open_buckets_to_text(struct printbuf *, struct bch_fs *, struct bch_dev *); void bch2_open_buckets_partial_to_text(struct printbuf *, struct bch_fs *); void bch2_write_points_to_text(struct printbuf *, struct bch_fs *); @@ -231,6 +231,11 @@ void bch2_write_points_to_text(struct printbuf *, struct bch_fs *); void bch2_fs_alloc_debug_to_text(struct printbuf *, struct bch_fs *); void bch2_dev_alloc_debug_to_text(struct printbuf *, struct bch_dev *); -void bch2_print_allocator_stuck(struct bch_fs *); +void __bch2_wait_on_allocator(struct bch_fs *, struct closure *); +static inline void bch2_wait_on_allocator(struct bch_fs *c, struct closure *cl) +{ + if (cl->closure_get_happened) + __bch2_wait_on_allocator(c, cl); +} #endif /* _BCACHEFS_ALLOC_FOREGROUND_H */ diff --git a/fs/bcachefs/backpointers.c b/fs/bcachefs/backpointers.c index 3cc02479a9828e..d4da6343efa9bd 100644 --- a/fs/bcachefs/backpointers.c +++ b/fs/bcachefs/backpointers.c @@ -47,9 +47,8 @@ static bool extent_matches_bp(struct bch_fs *c, return false; } -int bch2_backpointer_invalid(struct bch_fs *c, struct bkey_s_c k, - enum bch_validate_flags flags, - struct printbuf *err) +int bch2_backpointer_validate(struct bch_fs *c, struct bkey_s_c k, + enum bch_validate_flags flags) { struct bkey_s_c_backpointer bp = bkey_s_c_to_backpointer(k); @@ -68,8 +67,7 @@ int bch2_backpointer_invalid(struct bch_fs *c, struct bkey_s_c k, bkey_fsck_err_on((bp.v->bucket_offset >> MAX_EXTENT_COMPRESS_RATIO_SHIFT) >= ca->mi.bucket_size || !bpos_eq(bp.k->p, bp_pos), - c, err, - backpointer_bucket_offset_wrong, + c, backpointer_bucket_offset_wrong, "backpointer bucket_offset wrong"); fsck_err: return ret; @@ -763,27 +761,22 @@ static int bch2_get_btree_in_memory_pos(struct btree_trans *trans, btree < BTREE_ID_NR && !ret; btree++) { unsigned depth = (BIT_ULL(btree) & btree_leaf_mask) ? 0 : 1; - struct btree_iter iter; - struct btree *b; if (!(BIT_ULL(btree) & btree_leaf_mask) && !(BIT_ULL(btree) & btree_interior_mask)) continue; - bch2_trans_begin(trans); - - __for_each_btree_node(trans, iter, btree, + ret = __for_each_btree_node(trans, iter, btree, btree == start.btree ? start.pos : POS_MIN, - 0, depth, BTREE_ITER_prefetch, b, ret) { + 0, depth, BTREE_ITER_prefetch, b, ({ mem_may_pin -= btree_buf_bytes(b); if (mem_may_pin <= 0) { c->btree_cache.pinned_nodes_end = *end = BBPOS(btree, b->key.k.p); - bch2_trans_iter_exit(trans, &iter); - return 0; + break; } - } - bch2_trans_iter_exit(trans, &iter); + 0; + })); } return ret; diff --git a/fs/bcachefs/backpointers.h b/fs/bcachefs/backpointers.h index 6021de1c5e98de..7daecadb764e3e 100644 --- a/fs/bcachefs/backpointers.h +++ b/fs/bcachefs/backpointers.h @@ -18,14 +18,13 @@ static inline u64 swab40(u64 x) ((x & 0xff00000000ULL) >> 32)); } -int bch2_backpointer_invalid(struct bch_fs *, struct bkey_s_c k, - enum bch_validate_flags, struct printbuf *); +int bch2_backpointer_validate(struct bch_fs *, struct bkey_s_c k, enum bch_validate_flags); void bch2_backpointer_to_text(struct printbuf *, const struct bch_backpointer *); void bch2_backpointer_k_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c); void bch2_backpointer_swab(struct bkey_s); #define bch2_bkey_ops_backpointer ((struct bkey_ops) { \ - .key_invalid = bch2_backpointer_invalid, \ + .key_validate = bch2_backpointer_validate, \ .val_to_text = bch2_backpointer_k_to_text, \ .swab = bch2_backpointer_swab, \ .min_val_size = 32, \ diff --git a/fs/bcachefs/bcachefs.h b/fs/bcachefs/bcachefs.h index 91361a167dcd63..0c7086e00d18f5 100644 --- a/fs/bcachefs/bcachefs.h +++ b/fs/bcachefs/bcachefs.h @@ -447,6 +447,7 @@ BCH_DEBUG_PARAMS_DEBUG() x(blocked_journal_low_on_space) \ x(blocked_journal_low_on_pin) \ x(blocked_journal_max_in_flight) \ + x(blocked_key_cache_flush) \ x(blocked_allocate) \ x(blocked_allocate_open_bucket) \ x(blocked_write_buffer_full) \ @@ -893,6 +894,8 @@ struct bch_fs { struct bch_fs_usage_base __percpu *usage; u64 __percpu *online_reserved; + unsigned long allocator_last_stuck; + struct io_clock io_clock[2]; /* JOURNAL SEQ BLACKLIST */ diff --git a/fs/bcachefs/bcachefs_format.h b/fs/bcachefs/bcachefs_format.h index 74a60b1a4ddfa7..c75f2e0f32bb96 100644 --- a/fs/bcachefs/bcachefs_format.h +++ b/fs/bcachefs/bcachefs_format.h @@ -675,7 +675,9 @@ struct bch_sb_field_ext { x(btree_subvolume_children, BCH_VERSION(1, 6)) \ x(mi_btree_bitmap, BCH_VERSION(1, 7)) \ x(bucket_stripe_sectors, BCH_VERSION(1, 8)) \ - x(disk_accounting_v2, BCH_VERSION(1, 9)) + x(disk_accounting_v2, BCH_VERSION(1, 9)) \ + x(disk_accounting_v3, BCH_VERSION(1, 10)) \ + x(disk_accounting_inum, BCH_VERSION(1, 11)) enum bcachefs_metadata_version { bcachefs_metadata_version_min = 9, @@ -836,6 +838,8 @@ LE64_BITMASK(BCH_SB_BACKGROUND_COMPRESSION_TYPE_HI, LE64_BITMASK(BCH_SB_VERSION_UPGRADE_COMPLETE, struct bch_sb, flags[5], 0, 16); +LE64_BITMASK(BCH_SB_ALLOCATOR_STUCK_TIMEOUT, + struct bch_sb, flags[5], 16, 32); static inline __u64 BCH_SB_COMPRESSION_TYPE(const struct bch_sb *sb) { diff --git a/fs/bcachefs/bkey.h b/fs/bcachefs/bkey.h index 936357149cf0fb..e34cb2bf329c54 100644 --- a/fs/bcachefs/bkey.h +++ b/fs/bcachefs/bkey.h @@ -10,9 +10,10 @@ #include "vstructs.h" enum bch_validate_flags { - BCH_VALIDATE_write = (1U << 0), - BCH_VALIDATE_commit = (1U << 1), - BCH_VALIDATE_journal = (1U << 2), + BCH_VALIDATE_write = BIT(0), + BCH_VALIDATE_commit = BIT(1), + BCH_VALIDATE_journal = BIT(2), + BCH_VALIDATE_silent = BIT(3), }; #if 0 diff --git a/fs/bcachefs/bkey_methods.c b/fs/bcachefs/bkey_methods.c index 5f07cf853d0c75..88d8958281e80f 100644 --- a/fs/bcachefs/bkey_methods.c +++ b/fs/bcachefs/bkey_methods.c @@ -27,27 +27,27 @@ const char * const bch2_bkey_types[] = { NULL }; -static int deleted_key_invalid(struct bch_fs *c, struct bkey_s_c k, - enum bch_validate_flags flags, struct printbuf *err) +static int deleted_key_validate(struct bch_fs *c, struct bkey_s_c k, + enum bch_validate_flags flags) { return 0; } #define bch2_bkey_ops_deleted ((struct bkey_ops) { \ - .key_invalid = deleted_key_invalid, \ + .key_validate = deleted_key_validate, \ }) #define bch2_bkey_ops_whiteout ((struct bkey_ops) { \ - .key_invalid = deleted_key_invalid, \ + .key_validate = deleted_key_validate, \ }) -static int empty_val_key_invalid(struct bch_fs *c, struct bkey_s_c k, - enum bch_validate_flags flags, struct printbuf *err) +static int empty_val_key_validate(struct bch_fs *c, struct bkey_s_c k, + enum bch_validate_flags flags) { int ret = 0; - bkey_fsck_err_on(bkey_val_bytes(k.k), c, err, - bkey_val_size_nonzero, + bkey_fsck_err_on(bkey_val_bytes(k.k), + c, bkey_val_size_nonzero, "incorrect value size (%zu != 0)", bkey_val_bytes(k.k)); fsck_err: @@ -55,11 +55,11 @@ static int empty_val_key_invalid(struct bch_fs *c, struct bkey_s_c k, } #define bch2_bkey_ops_error ((struct bkey_ops) { \ - .key_invalid = empty_val_key_invalid, \ + .key_validate = empty_val_key_validate, \ }) -static int key_type_cookie_invalid(struct bch_fs *c, struct bkey_s_c k, - enum bch_validate_flags flags, struct printbuf *err) +static int key_type_cookie_validate(struct bch_fs *c, struct bkey_s_c k, + enum bch_validate_flags flags) { return 0; } @@ -73,17 +73,17 @@ static void key_type_cookie_to_text(struct printbuf *out, struct bch_fs *c, } #define bch2_bkey_ops_cookie ((struct bkey_ops) { \ - .key_invalid = key_type_cookie_invalid, \ + .key_validate = key_type_cookie_validate, \ .val_to_text = key_type_cookie_to_text, \ .min_val_size = 8, \ }) #define bch2_bkey_ops_hash_whiteout ((struct bkey_ops) {\ - .key_invalid = empty_val_key_invalid, \ + .key_validate = empty_val_key_validate, \ }) -static int key_type_inline_data_invalid(struct bch_fs *c, struct bkey_s_c k, - enum bch_validate_flags flags, struct printbuf *err) +static int key_type_inline_data_validate(struct bch_fs *c, struct bkey_s_c k, + enum bch_validate_flags flags) { return 0; } @@ -98,9 +98,9 @@ static void key_type_inline_data_to_text(struct printbuf *out, struct bch_fs *c, datalen, min(datalen, 32U), d.v->data); } -#define bch2_bkey_ops_inline_data ((struct bkey_ops) { \ - .key_invalid = key_type_inline_data_invalid, \ - .val_to_text = key_type_inline_data_to_text, \ +#define bch2_bkey_ops_inline_data ((struct bkey_ops) { \ + .key_validate = key_type_inline_data_validate, \ + .val_to_text = key_type_inline_data_to_text, \ }) static bool key_type_set_merge(struct bch_fs *c, struct bkey_s l, struct bkey_s_c r) @@ -110,7 +110,7 @@ static bool key_type_set_merge(struct bch_fs *c, struct bkey_s l, struct bkey_s_ } #define bch2_bkey_ops_set ((struct bkey_ops) { \ - .key_invalid = empty_val_key_invalid, \ + .key_validate = empty_val_key_validate, \ .key_merge = key_type_set_merge, \ }) @@ -123,9 +123,8 @@ const struct bkey_ops bch2_bkey_ops[] = { const struct bkey_ops bch2_bkey_null_ops = { }; -int bch2_bkey_val_invalid(struct bch_fs *c, struct bkey_s_c k, - enum bch_validate_flags flags, - struct printbuf *err) +int bch2_bkey_val_validate(struct bch_fs *c, struct bkey_s_c k, + enum bch_validate_flags flags) { if (test_bit(BCH_FS_no_invalid_checks, &c->flags)) return 0; @@ -133,15 +132,15 @@ int bch2_bkey_val_invalid(struct bch_fs *c, struct bkey_s_c k, const struct bkey_ops *ops = bch2_bkey_type_ops(k.k->type); int ret = 0; - bkey_fsck_err_on(bkey_val_bytes(k.k) < ops->min_val_size, c, err, - bkey_val_size_too_small, + bkey_fsck_err_on(bkey_val_bytes(k.k) < ops->min_val_size, + c, bkey_val_size_too_small, "bad val size (%zu < %u)", bkey_val_bytes(k.k), ops->min_val_size); - if (!ops->key_invalid) + if (!ops->key_validate) return 0; - ret = ops->key_invalid(c, k, flags, err); + ret = ops->key_validate(c, k, flags); fsck_err: return ret; } @@ -161,18 +160,17 @@ const char *bch2_btree_node_type_str(enum btree_node_type type) return type == BKEY_TYPE_btree ? "internal btree node" : bch2_btree_id_str(type - 1); } -int __bch2_bkey_invalid(struct bch_fs *c, struct bkey_s_c k, - enum btree_node_type type, - enum bch_validate_flags flags, - struct printbuf *err) +int __bch2_bkey_validate(struct bch_fs *c, struct bkey_s_c k, + enum btree_node_type type, + enum bch_validate_flags flags) { if (test_bit(BCH_FS_no_invalid_checks, &c->flags)) return 0; int ret = 0; - bkey_fsck_err_on(k.k->u64s < BKEY_U64s, c, err, - bkey_u64s_too_small, + bkey_fsck_err_on(k.k->u64s < BKEY_U64s, + c, bkey_u64s_too_small, "u64s too small (%u < %zu)", k.k->u64s, BKEY_U64s); if (type >= BKEY_TYPE_NR) @@ -180,8 +178,8 @@ int __bch2_bkey_invalid(struct bch_fs *c, struct bkey_s_c k, bkey_fsck_err_on(k.k->type < KEY_TYPE_MAX && (type == BKEY_TYPE_btree || (flags & BCH_VALIDATE_commit)) && - !(bch2_key_types_allowed[type] & BIT_ULL(k.k->type)), c, err, - bkey_invalid_type_for_btree, + !(bch2_key_types_allowed[type] & BIT_ULL(k.k->type)), + c, bkey_invalid_type_for_btree, "invalid key type for btree %s (%s)", bch2_btree_node_type_str(type), k.k->type < KEY_TYPE_MAX @@ -189,17 +187,17 @@ int __bch2_bkey_invalid(struct bch_fs *c, struct bkey_s_c k, : "(unknown)"); if (btree_node_type_is_extents(type) && !bkey_whiteout(k.k)) { - bkey_fsck_err_on(k.k->size == 0, c, err, - bkey_extent_size_zero, + bkey_fsck_err_on(k.k->size == 0, + c, bkey_extent_size_zero, "size == 0"); - bkey_fsck_err_on(k.k->size > k.k->p.offset, c, err, - bkey_extent_size_greater_than_offset, + bkey_fsck_err_on(k.k->size > k.k->p.offset, + c, bkey_extent_size_greater_than_offset, "size greater than offset (%u > %llu)", k.k->size, k.k->p.offset); } else { - bkey_fsck_err_on(k.k->size, c, err, - bkey_size_nonzero, + bkey_fsck_err_on(k.k->size, + c, bkey_size_nonzero, "size != 0"); } @@ -207,12 +205,12 @@ int __bch2_bkey_invalid(struct bch_fs *c, struct bkey_s_c k, enum btree_id btree = type - 1; if (btree_type_has_snapshots(btree)) { - bkey_fsck_err_on(!k.k->p.snapshot, c, err, - bkey_snapshot_zero, + bkey_fsck_err_on(!k.k->p.snapshot, + c, bkey_snapshot_zero, "snapshot == 0"); } else if (!btree_type_has_snapshot_field(btree)) { - bkey_fsck_err_on(k.k->p.snapshot, c, err, - bkey_snapshot_nonzero, + bkey_fsck_err_on(k.k->p.snapshot, + c, bkey_snapshot_nonzero, "nonzero snapshot"); } else { /* @@ -221,34 +219,33 @@ int __bch2_bkey_invalid(struct bch_fs *c, struct bkey_s_c k, */ } - bkey_fsck_err_on(bkey_eq(k.k->p, POS_MAX), c, err, - bkey_at_pos_max, + bkey_fsck_err_on(bkey_eq(k.k->p, POS_MAX), + c, bkey_at_pos_max, "key at POS_MAX"); } fsck_err: return ret; } -int bch2_bkey_invalid(struct bch_fs *c, struct bkey_s_c k, +int bch2_bkey_validate(struct bch_fs *c, struct bkey_s_c k, enum btree_node_type type, - enum bch_validate_flags flags, - struct printbuf *err) + enum bch_validate_flags flags) { - return __bch2_bkey_invalid(c, k, type, flags, err) ?: - bch2_bkey_val_invalid(c, k, flags, err); + return __bch2_bkey_validate(c, k, type, flags) ?: + bch2_bkey_val_validate(c, k, flags); } int bch2_bkey_in_btree_node(struct bch_fs *c, struct btree *b, - struct bkey_s_c k, struct printbuf *err) + struct bkey_s_c k, enum bch_validate_flags flags) { int ret = 0; - bkey_fsck_err_on(bpos_lt(k.k->p, b->data->min_key), c, err, - bkey_before_start_of_btree_node, + bkey_fsck_err_on(bpos_lt(k.k->p, b->data->min_key), + c, bkey_before_start_of_btree_node, "key before start of btree node"); - bkey_fsck_err_on(bpos_gt(k.k->p, b->data->max_key), c, err, - bkey_after_end_of_btree_node, + bkey_fsck_err_on(bpos_gt(k.k->p, b->data->max_key), + c, bkey_after_end_of_btree_node, "key past end of btree node"); fsck_err: return ret; diff --git a/fs/bcachefs/bkey_methods.h b/fs/bcachefs/bkey_methods.h index baef0722f5fb60..3df3dd2723a128 100644 --- a/fs/bcachefs/bkey_methods.h +++ b/fs/bcachefs/bkey_methods.h @@ -14,15 +14,15 @@ extern const char * const bch2_bkey_types[]; extern const struct bkey_ops bch2_bkey_null_ops; /* - * key_invalid: checks validity of @k, returns 0 if good or -EINVAL if bad. If + * key_validate: checks validity of @k, returns 0 if good or -EINVAL if bad. If * invalid, entire key will be deleted. * * When invalid, error string is returned via @err. @rw indicates whether key is * being read or written; more aggressive checks can be enabled when rw == WRITE. */ struct bkey_ops { - int (*key_invalid)(struct bch_fs *c, struct bkey_s_c k, - enum bch_validate_flags flags, struct printbuf *err); + int (*key_validate)(struct bch_fs *c, struct bkey_s_c k, + enum bch_validate_flags flags); void (*val_to_text)(struct printbuf *, struct bch_fs *, struct bkey_s_c); void (*swab)(struct bkey_s); @@ -48,14 +48,13 @@ static inline const struct bkey_ops *bch2_bkey_type_ops(enum bch_bkey_type type) : &bch2_bkey_null_ops; } -int bch2_bkey_val_invalid(struct bch_fs *, struct bkey_s_c, - enum bch_validate_flags, struct printbuf *); -int __bch2_bkey_invalid(struct bch_fs *, struct bkey_s_c, enum btree_node_type, - enum bch_validate_flags, struct printbuf *); -int bch2_bkey_invalid(struct bch_fs *, struct bkey_s_c, enum btree_node_type, - enum bch_validate_flags, struct printbuf *); -int bch2_bkey_in_btree_node(struct bch_fs *, struct btree *, - struct bkey_s_c, struct printbuf *); +int bch2_bkey_val_validate(struct bch_fs *, struct bkey_s_c, enum bch_validate_flags); +int __bch2_bkey_validate(struct bch_fs *, struct bkey_s_c, enum btree_node_type, + enum bch_validate_flags); +int bch2_bkey_validate(struct bch_fs *, struct bkey_s_c, enum btree_node_type, + enum bch_validate_flags); +int bch2_bkey_in_btree_node(struct bch_fs *, struct btree *, struct bkey_s_c, + enum bch_validate_flags); void bch2_bpos_to_text(struct printbuf *, struct bpos); void bch2_bkey_to_text(struct printbuf *, const struct bkey *); diff --git a/fs/bcachefs/btree_gc.c b/fs/bcachefs/btree_gc.c index 6cbf2aa6a9479b..eb3002c4eae7b1 100644 --- a/fs/bcachefs/btree_gc.c +++ b/fs/bcachefs/btree_gc.c @@ -741,12 +741,9 @@ static int bch2_gc_btrees(struct bch_fs *c) static int bch2_mark_superblocks(struct bch_fs *c) { - mutex_lock(&c->sb_lock); gc_pos_set(c, gc_phase(GC_PHASE_sb)); - int ret = bch2_trans_mark_dev_sbs_flags(c, BTREE_TRIGGER_gc); - mutex_unlock(&c->sb_lock); - return ret; + return bch2_trans_mark_dev_sbs_flags(c, BTREE_TRIGGER_gc); } static void bch2_gc_free(struct bch_fs *c) diff --git a/fs/bcachefs/btree_io.c b/fs/bcachefs/btree_io.c index 2c424435ca4aaa..56ea9a77cd4afd 100644 --- a/fs/bcachefs/btree_io.c +++ b/fs/bcachefs/btree_io.c @@ -836,14 +836,13 @@ static int validate_bset(struct bch_fs *c, struct bch_dev *ca, return ret; } -static int bset_key_invalid(struct bch_fs *c, struct btree *b, - struct bkey_s_c k, - bool updated_range, int rw, - struct printbuf *err) +static int bset_key_validate(struct bch_fs *c, struct btree *b, + struct bkey_s_c k, + bool updated_range, int rw) { - return __bch2_bkey_invalid(c, k, btree_node_type(b), READ, err) ?: - (!updated_range ? bch2_bkey_in_btree_node(c, b, k, err) : 0) ?: - (rw == WRITE ? bch2_bkey_val_invalid(c, k, READ, err) : 0); + return __bch2_bkey_validate(c, k, btree_node_type(b), 0) ?: + (!updated_range ? bch2_bkey_in_btree_node(c, b, k, 0) : 0) ?: + (rw == WRITE ? bch2_bkey_val_validate(c, k, 0) : 0); } static bool bkey_packed_valid(struct bch_fs *c, struct btree *b, @@ -858,12 +857,9 @@ static bool bkey_packed_valid(struct bch_fs *c, struct btree *b, if (!bkeyp_u64s_valid(&b->format, k)) return false; - struct printbuf buf = PRINTBUF; struct bkey tmp; struct bkey_s u = __bkey_disassemble(b, k, &tmp); - bool ret = __bch2_bkey_invalid(c, u.s_c, btree_node_type(b), READ, &buf); - printbuf_exit(&buf); - return ret; + return !__bch2_bkey_validate(c, u.s_c, btree_node_type(b), BCH_VALIDATE_silent); } static int validate_bset_keys(struct bch_fs *c, struct btree *b, @@ -915,19 +911,11 @@ static int validate_bset_keys(struct bch_fs *c, struct btree *b, u = __bkey_disassemble(b, k, &tmp); - printbuf_reset(&buf); - if (bset_key_invalid(c, b, u.s_c, updated_range, write, &buf)) { - printbuf_reset(&buf); - bset_key_invalid(c, b, u.s_c, updated_range, write, &buf); - prt_printf(&buf, "\n "); - bch2_bkey_val_to_text(&buf, c, u.s_c); - - btree_err(-BCH_ERR_btree_node_read_err_fixable, - c, NULL, b, i, k, - btree_node_bad_bkey, - "invalid bkey: %s", buf.buf); + ret = bset_key_validate(c, b, u.s_c, updated_range, write); + if (ret == -BCH_ERR_fsck_delete_bkey) goto drop_this_key; - } + if (ret) + goto fsck_err; if (write) bch2_bkey_compat(b->c.level, b->c.btree_id, version, @@ -1228,23 +1216,10 @@ int bch2_btree_node_read_done(struct bch_fs *c, struct bch_dev *ca, struct bkey tmp; struct bkey_s u = __bkey_disassemble(b, k, &tmp); - printbuf_reset(&buf); - - if (bch2_bkey_val_invalid(c, u.s_c, READ, &buf) || + ret = bch2_bkey_val_validate(c, u.s_c, READ); + if (ret == -BCH_ERR_fsck_delete_bkey || (bch2_inject_invalid_keys && !bversion_cmp(u.k->version, MAX_VERSION))) { - printbuf_reset(&buf); - - prt_printf(&buf, "invalid bkey: "); - bch2_bkey_val_invalid(c, u.s_c, READ, &buf); - prt_printf(&buf, "\n "); - bch2_bkey_val_to_text(&buf, c, u.s_c); - - btree_err(-BCH_ERR_btree_node_read_err_fixable, - c, NULL, b, i, k, - btree_node_bad_bkey, - "%s", buf.buf); - btree_keys_account_key_drop(&b->nr, 0, k); i->u64s = cpu_to_le16(le16_to_cpu(i->u64s) - k->u64s); @@ -1253,6 +1228,8 @@ int bch2_btree_node_read_done(struct bch_fs *c, struct bch_dev *ca, set_btree_bset_end(b, b->set); continue; } + if (ret) + goto fsck_err; if (u.k->type == KEY_TYPE_btree_ptr_v2) { struct bkey_s_btree_ptr_v2 bp = bkey_s_to_btree_ptr_v2(u); @@ -1767,6 +1744,8 @@ static int __bch2_btree_root_read(struct btree_trans *trans, enum btree_id id, set_btree_node_read_in_flight(b); + /* we can't pass the trans to read_done() for fsck errors, so it must be unlocked */ + bch2_trans_unlock(trans); bch2_btree_node_read(trans, b, true); if (btree_node_read_error(b)) { @@ -1952,18 +1931,14 @@ static void btree_node_write_endio(struct bio *bio) static int validate_bset_for_write(struct bch_fs *c, struct btree *b, struct bset *i, unsigned sectors) { - struct printbuf buf = PRINTBUF; bool saw_error; - int ret; - - ret = bch2_bkey_invalid(c, bkey_i_to_s_c(&b->key), - BKEY_TYPE_btree, WRITE, &buf); - if (ret) - bch2_fs_inconsistent(c, "invalid btree node key before write: %s", buf.buf); - printbuf_exit(&buf); - if (ret) + int ret = bch2_bkey_validate(c, bkey_i_to_s_c(&b->key), + BKEY_TYPE_btree, WRITE); + if (ret) { + bch2_fs_inconsistent(c, "invalid btree node key before write"); return ret; + } ret = validate_bset_keys(c, b, i, WRITE, false, &saw_error) ?: validate_bset(c, NULL, b, i, b->written, sectors, WRITE, false, &saw_error); diff --git a/fs/bcachefs/btree_iter.c b/fs/bcachefs/btree_iter.c index 36872207f09b22..2e84d22e17bdd6 100644 --- a/fs/bcachefs/btree_iter.c +++ b/fs/bcachefs/btree_iter.c @@ -1900,6 +1900,7 @@ struct btree *bch2_btree_iter_peek_node(struct btree_iter *iter) goto out; } +/* Only kept for -tools */ struct btree *bch2_btree_iter_peek_node_and_restart(struct btree_iter *iter) { struct btree *b; @@ -1921,6 +1922,11 @@ struct btree *bch2_btree_iter_next_node(struct btree_iter *iter) bch2_trans_verify_not_in_restart(trans); bch2_btree_iter_verify(iter); + ret = bch2_btree_path_traverse(trans, iter->path, iter->flags); + if (ret) + goto err; + + struct btree_path *path = btree_iter_path(trans, iter); /* already at end? */ diff --git a/fs/bcachefs/btree_iter.h b/fs/bcachefs/btree_iter.h index c7725865309c09..dca62375d7d30f 100644 --- a/fs/bcachefs/btree_iter.h +++ b/fs/bcachefs/btree_iter.h @@ -600,23 +600,35 @@ void bch2_trans_srcu_unlock(struct btree_trans *); u32 bch2_trans_begin(struct btree_trans *); -/* - * XXX - * this does not handle transaction restarts from bch2_btree_iter_next_node() - * correctly - */ -#define __for_each_btree_node(_trans, _iter, _btree_id, _start, \ - _locks_want, _depth, _flags, _b, _ret) \ - for (bch2_trans_node_iter_init((_trans), &(_iter), (_btree_id), \ - _start, _locks_want, _depth, _flags); \ - (_b) = bch2_btree_iter_peek_node_and_restart(&(_iter)), \ - !((_ret) = PTR_ERR_OR_ZERO(_b)) && (_b); \ - (_b) = bch2_btree_iter_next_node(&(_iter))) +#define __for_each_btree_node(_trans, _iter, _btree_id, _start, \ + _locks_want, _depth, _flags, _b, _do) \ +({ \ + bch2_trans_begin((_trans)); \ + \ + struct btree_iter _iter; \ + bch2_trans_node_iter_init((_trans), &_iter, (_btree_id), \ + _start, _locks_want, _depth, _flags); \ + int _ret3 = 0; \ + do { \ + _ret3 = lockrestart_do((_trans), ({ \ + struct btree *_b = bch2_btree_iter_peek_node(&_iter); \ + if (!_b) \ + break; \ + \ + PTR_ERR_OR_ZERO(_b) ?: (_do); \ + })) ?: \ + lockrestart_do((_trans), \ + PTR_ERR_OR_ZERO(bch2_btree_iter_next_node(&_iter))); \ + } while (!_ret3); \ + \ + bch2_trans_iter_exit((_trans), &(_iter)); \ + _ret3; \ +}) #define for_each_btree_node(_trans, _iter, _btree_id, _start, \ - _flags, _b, _ret) \ - __for_each_btree_node(_trans, _iter, _btree_id, _start, \ - 0, 0, _flags, _b, _ret) + _flags, _b, _do) \ + __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, unsigned flags) diff --git a/fs/bcachefs/btree_key_cache.c b/fs/bcachefs/btree_key_cache.c index f2f2e525460b57..79954490627cca 100644 --- a/fs/bcachefs/btree_key_cache.c +++ b/fs/bcachefs/btree_key_cache.c @@ -497,11 +497,6 @@ int bch2_btree_path_traverse_cached(struct btree_trans *trans, struct btree_path path->l[1].b = NULL; - if (bch2_btree_node_relock_notrace(trans, path, 0)) { - path->uptodate = BTREE_ITER_UPTODATE; - return 0; - } - int ret; do { ret = btree_path_traverse_cached_fast(trans, path); diff --git a/fs/bcachefs/btree_key_cache.h b/fs/bcachefs/btree_key_cache.h index e6b2cd0dd2c1af..51d6289b8dee32 100644 --- a/fs/bcachefs/btree_key_cache.h +++ b/fs/bcachefs/btree_key_cache.h @@ -11,13 +11,27 @@ static inline size_t bch2_nr_btree_keys_need_flush(struct bch_fs *c) return max_t(ssize_t, 0, nr_dirty - max_dirty); } -static inline bool bch2_btree_key_cache_must_wait(struct bch_fs *c) +static inline ssize_t __bch2_btree_key_cache_must_wait(struct bch_fs *c) { size_t nr_dirty = atomic_long_read(&c->btree_key_cache.nr_dirty); size_t nr_keys = atomic_long_read(&c->btree_key_cache.nr_keys); size_t max_dirty = 4096 + (nr_keys * 3) / 4; - return nr_dirty > max_dirty; + return nr_dirty - max_dirty; +} + +static inline bool bch2_btree_key_cache_must_wait(struct bch_fs *c) +{ + return __bch2_btree_key_cache_must_wait(c) > 0; +} + +static inline bool bch2_btree_key_cache_wait_done(struct bch_fs *c) +{ + size_t nr_dirty = atomic_long_read(&c->btree_key_cache.nr_dirty); + size_t nr_keys = atomic_long_read(&c->btree_key_cache.nr_keys); + size_t max_dirty = 2048 + (nr_keys * 5) / 8; + + return nr_dirty <= max_dirty; } int bch2_btree_key_cache_journal_flush(struct journal *, diff --git a/fs/bcachefs/btree_node_scan.c b/fs/bcachefs/btree_node_scan.c index 0011072263778b..b28c649c68389f 100644 --- a/fs/bcachefs/btree_node_scan.c +++ b/fs/bcachefs/btree_node_scan.c @@ -530,7 +530,7 @@ int bch2_get_scanned_nodes(struct bch_fs *c, enum btree_id btree, bch_verbose(c, "%s(): recovering %s", __func__, buf.buf); printbuf_exit(&buf); - BUG_ON(bch2_bkey_invalid(c, bkey_i_to_s_c(&tmp.k), BKEY_TYPE_btree, 0, NULL)); + BUG_ON(bch2_bkey_validate(c, bkey_i_to_s_c(&tmp.k), BKEY_TYPE_btree, 0)); ret = bch2_journal_key_insert(c, btree, level + 1, &tmp.k); if (ret) diff --git a/fs/bcachefs/btree_trans_commit.c b/fs/bcachefs/btree_trans_commit.c index cca336fe46e9b4..a0101d9c5d83f6 100644 --- a/fs/bcachefs/btree_trans_commit.c +++ b/fs/bcachefs/btree_trans_commit.c @@ -712,7 +712,7 @@ bch2_trans_commit_write_locked(struct btree_trans *trans, unsigned flags, a->k.version = journal_pos_to_bversion(&trans->journal_res, (u64 *) entry - (u64 *) trans->journal_entries); BUG_ON(bversion_zero(a->k.version)); - ret = bch2_accounting_mem_mod_locked(trans, accounting_i_to_s_c(a), false); + ret = bch2_accounting_mem_mod_locked(trans, accounting_i_to_s_c(a), false, false); if (ret) goto revert_fs_usage; } @@ -798,7 +798,7 @@ bch2_trans_commit_write_locked(struct btree_trans *trans, unsigned flags, struct bkey_s_accounting a = bkey_i_to_s_accounting(entry2->start); bch2_accounting_neg(a); - bch2_accounting_mem_mod_locked(trans, a.c, false); + bch2_accounting_mem_mod_locked(trans, a.c, false, false); bch2_accounting_neg(a); } percpu_up_read(&c->mark_lock); @@ -818,50 +818,6 @@ static noinline void bch2_drop_overwrites_from_journal(struct btree_trans *trans bch2_journal_key_overwritten(trans->c, i->btree_id, i->level, i->k->k.p); } -static noinline int bch2_trans_commit_bkey_invalid(struct btree_trans *trans, - enum bch_validate_flags flags, - struct btree_insert_entry *i, - struct printbuf *err) -{ - struct bch_fs *c = trans->c; - - printbuf_reset(err); - prt_printf(err, "invalid bkey on insert from %s -> %ps\n", - trans->fn, (void *) i->ip_allocated); - printbuf_indent_add(err, 2); - - bch2_bkey_val_to_text(err, c, bkey_i_to_s_c(i->k)); - prt_newline(err); - - bch2_bkey_invalid(c, bkey_i_to_s_c(i->k), i->bkey_type, flags, err); - bch2_print_string_as_lines(KERN_ERR, err->buf); - - bch2_inconsistent_error(c); - bch2_dump_trans_updates(trans); - - return -EINVAL; -} - -static noinline int bch2_trans_commit_journal_entry_invalid(struct btree_trans *trans, - struct jset_entry *i) -{ - struct bch_fs *c = trans->c; - struct printbuf buf = PRINTBUF; - - prt_printf(&buf, "invalid bkey on insert from %s\n", trans->fn); - printbuf_indent_add(&buf, 2); - - bch2_journal_entry_to_text(&buf, c, i); - prt_newline(&buf); - - bch2_print_string_as_lines(KERN_ERR, buf.buf); - - bch2_inconsistent_error(c); - bch2_dump_trans_updates(trans); - - return -EINVAL; -} - static int bch2_trans_commit_journal_pin_flush(struct journal *j, struct journal_entry_pin *_pin, u64 seq) { @@ -927,7 +883,7 @@ static inline int do_bch2_trans_commit(struct btree_trans *trans, unsigned flags static int journal_reclaim_wait_done(struct bch_fs *c) { int ret = bch2_journal_error(&c->journal) ?: - !bch2_btree_key_cache_must_wait(c); + bch2_btree_key_cache_wait_done(c); if (!ret) journal_reclaim_kick(&c->journal); @@ -973,9 +929,13 @@ int bch2_trans_commit_error(struct btree_trans *trans, unsigned flags, bch2_trans_unlock(trans); trace_and_count(c, trans_blocked_journal_reclaim, trans, trace_ip); + track_event_change(&c->times[BCH_TIME_blocked_key_cache_flush], true); wait_event_freezable(c->journal.reclaim_wait, (ret = journal_reclaim_wait_done(c))); + + track_event_change(&c->times[BCH_TIME_blocked_key_cache_flush], false); + if (ret < 0) break; @@ -1060,20 +1020,19 @@ int __bch2_trans_commit(struct btree_trans *trans, unsigned flags) goto out_reset; trans_for_each_update(trans, i) { - struct printbuf buf = PRINTBUF; enum bch_validate_flags invalid_flags = 0; if (!(flags & BCH_TRANS_COMMIT_no_journal_res)) invalid_flags |= BCH_VALIDATE_write|BCH_VALIDATE_commit; - if (unlikely(bch2_bkey_invalid(c, bkey_i_to_s_c(i->k), - i->bkey_type, invalid_flags, &buf))) - ret = bch2_trans_commit_bkey_invalid(trans, invalid_flags, i, &buf); - btree_insert_entry_checks(trans, i); - printbuf_exit(&buf); - - if (ret) + ret = bch2_bkey_validate(c, bkey_i_to_s_c(i->k), + i->bkey_type, invalid_flags); + if (unlikely(ret)){ + bch2_trans_inconsistent(trans, "invalid bkey on insert from %s -> %ps\n", + trans->fn, (void *) i->ip_allocated); return ret; + } + btree_insert_entry_checks(trans, i); } for (struct jset_entry *i = trans->journal_entries; @@ -1084,13 +1043,14 @@ int __bch2_trans_commit(struct btree_trans *trans, unsigned flags) if (!(flags & BCH_TRANS_COMMIT_no_journal_res)) invalid_flags |= BCH_VALIDATE_write|BCH_VALIDATE_commit; - if (unlikely(bch2_journal_entry_validate(c, NULL, i, - bcachefs_metadata_version_current, - CPU_BIG_ENDIAN, invalid_flags))) - ret = bch2_trans_commit_journal_entry_invalid(trans, i); - - if (ret) + ret = bch2_journal_entry_validate(c, NULL, i, + bcachefs_metadata_version_current, + CPU_BIG_ENDIAN, invalid_flags); + if (unlikely(ret)) { + bch2_trans_inconsistent(trans, "invalid journal entry on insert from %s\n", + trans->fn); return ret; + } } if (unlikely(!test_bit(BCH_FS_may_go_rw, &c->flags))) { diff --git a/fs/bcachefs/btree_update_interior.c b/fs/bcachefs/btree_update_interior.c index 31ee50184be236..b3454d4619e8fb 100644 --- a/fs/bcachefs/btree_update_interior.c +++ b/fs/bcachefs/btree_update_interior.c @@ -1264,7 +1264,7 @@ bch2_btree_update_start(struct btree_trans *trans, struct btree_path *path, ret = bch2_btree_reserve_get(trans, as, nr_nodes, flags, &cl); bch2_trans_unlock(trans); - closure_sync(&cl); + bch2_wait_on_allocator(c, &cl); } while (bch2_err_matches(ret, BCH_ERR_operation_blocked)); } @@ -1364,18 +1364,10 @@ static void bch2_insert_fixup_btree_ptr(struct btree_update *as, if (unlikely(!test_bit(JOURNAL_replay_done, &c->journal.flags))) bch2_journal_key_overwritten(c, b->c.btree_id, b->c.level, insert->k.p); - if (bch2_bkey_invalid(c, bkey_i_to_s_c(insert), - btree_node_type(b), WRITE, &buf) ?: - bch2_bkey_in_btree_node(c, b, bkey_i_to_s_c(insert), &buf)) { - printbuf_reset(&buf); - prt_printf(&buf, "inserting invalid bkey\n "); - bch2_bkey_val_to_text(&buf, c, bkey_i_to_s_c(insert)); - prt_printf(&buf, "\n "); - bch2_bkey_invalid(c, bkey_i_to_s_c(insert), - btree_node_type(b), WRITE, &buf); - bch2_bkey_in_btree_node(c, b, bkey_i_to_s_c(insert), &buf); - - bch2_fs_inconsistent(c, "%s", buf.buf); + if (bch2_bkey_validate(c, bkey_i_to_s_c(insert), + btree_node_type(b), BCH_VALIDATE_write) ?: + bch2_bkey_in_btree_node(c, b, bkey_i_to_s_c(insert), BCH_VALIDATE_write)) { + bch2_fs_inconsistent(c, "%s: inserting invalid bkey", __func__); dump_stack(); } diff --git a/fs/bcachefs/buckets.c b/fs/bcachefs/buckets.c index 2650a0d2466369..be2bbd2486314f 100644 --- a/fs/bcachefs/buckets.c +++ b/fs/bcachefs/buckets.c @@ -71,17 +71,21 @@ bch2_fs_usage_read_short(struct bch_fs *c) return ret; } -void bch2_dev_usage_to_text(struct printbuf *out, struct bch_dev_usage *usage) +void bch2_dev_usage_to_text(struct printbuf *out, + struct bch_dev *ca, + struct bch_dev_usage *usage) { prt_printf(out, "\tbuckets\rsectors\rfragmented\r\n"); for (unsigned i = 0; i < BCH_DATA_NR; i++) { bch2_prt_data_type(out, i); prt_printf(out, "\t%llu\r%llu\r%llu\r\n", - usage->d[i].buckets, - usage->d[i].sectors, - usage->d[i].fragmented); + usage->d[i].buckets, + usage->d[i].sectors, + usage->d[i].fragmented); } + + prt_printf(out, "capacity\t%llu\r\n", ca->mi.nbuckets); } static int bch2_check_fix_ptr(struct btree_trans *trans, @@ -806,6 +810,20 @@ static int __trigger_extent(struct btree_trans *trans, ret = bch2_disk_accounting_mod(trans, &acc_btree_key, &replicas_sectors, 1, gc); if (ret) return ret; + } else { + bool insert = !(flags & BTREE_TRIGGER_overwrite); + struct disk_accounting_pos acc_inum_key = { + .type = BCH_DISK_ACCOUNTING_inum, + .inum.inum = k.k->p.inode, + }; + s64 v[3] = { + insert ? 1 : -1, + insert ? k.k->size : -((s64) k.k->size), + replicas_sectors, + }; + ret = bch2_disk_accounting_mod(trans, &acc_inum_key, v, ARRAY_SIZE(v), gc); + if (ret) + return ret; } if (bch2_bkey_rebalance_opts(k)) { @@ -897,7 +915,6 @@ static int __bch2_trans_mark_metadata_bucket(struct btree_trans *trans, enum bch_data_type type, unsigned sectors) { - struct bch_fs *c = trans->c; struct btree_iter iter; int ret = 0; @@ -907,7 +924,7 @@ static int __bch2_trans_mark_metadata_bucket(struct btree_trans *trans, return PTR_ERR(a); if (a->v.data_type && type && a->v.data_type != type) { - bch2_fsck_err(c, FSCK_CAN_IGNORE|FSCK_NEED_FSCK, + bch2_fsck_err(trans, FSCK_CAN_IGNORE|FSCK_NEED_FSCK, bucket_metadata_type_mismatch, "bucket %llu:%llu gen %u different types of data in same bucket: %s, %s\n" "while marking %s", @@ -1028,13 +1045,18 @@ static int bch2_trans_mark_metadata_sectors(struct btree_trans *trans, static int __bch2_trans_mark_dev_sb(struct btree_trans *trans, struct bch_dev *ca, enum btree_iter_update_trigger_flags flags) { - struct bch_sb_layout *layout = &ca->disk_sb.sb->layout; + struct bch_fs *c = trans->c; + + mutex_lock(&c->sb_lock); + struct bch_sb_layout layout = ca->disk_sb.sb->layout; + mutex_unlock(&c->sb_lock); + u64 bucket = 0; unsigned i, bucket_sectors = 0; int ret; - for (i = 0; i < layout->nr_superblocks; i++) { - u64 offset = le64_to_cpu(layout->sb_offset[i]); + for (i = 0; i < layout.nr_superblocks; i++) { + u64 offset = le64_to_cpu(layout.sb_offset[i]); if (offset == BCH_SB_SECTOR) { ret = bch2_trans_mark_metadata_sectors(trans, ca, @@ -1045,7 +1067,7 @@ static int __bch2_trans_mark_dev_sb(struct btree_trans *trans, struct bch_dev *c } ret = bch2_trans_mark_metadata_sectors(trans, ca, offset, - offset + (1 << layout->sb_max_size_bits), + offset + (1 << layout.sb_max_size_bits), BCH_DATA_sb, &bucket, &bucket_sectors, flags); if (ret) return ret; diff --git a/fs/bcachefs/buckets.h b/fs/bcachefs/buckets.h index 2d35eeb24a2d69..edbdffd508fc3b 100644 --- a/fs/bcachefs/buckets.h +++ b/fs/bcachefs/buckets.h @@ -212,7 +212,7 @@ 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_usage *); +void bch2_dev_usage_to_text(struct printbuf *, struct bch_dev *, struct bch_dev_usage *); static inline u64 bch2_dev_buckets_reserved(struct bch_dev *ca, enum bch_watermark watermark) { diff --git a/fs/bcachefs/buckets_waiting_for_journal.c b/fs/bcachefs/buckets_waiting_for_journal.c index ec1b636ef78d07..f70eb2127d322c 100644 --- a/fs/bcachefs/buckets_waiting_for_journal.c +++ b/fs/bcachefs/buckets_waiting_for_journal.c @@ -93,7 +93,7 @@ int bch2_set_bucket_needs_journal_commit(struct buckets_waiting_for_journal *b, .dev_bucket = (u64) dev << 56 | bucket, .journal_seq = journal_seq, }; - size_t i, size, new_bits, nr_elements = 1, nr_rehashes = 0; + size_t i, size, new_bits, nr_elements = 1, nr_rehashes = 0, nr_rehashes_this_size = 0; int ret = 0; mutex_lock(&b->lock); @@ -106,7 +106,7 @@ int bch2_set_bucket_needs_journal_commit(struct buckets_waiting_for_journal *b, for (i = 0; i < size; i++) nr_elements += t->d[i].journal_seq > flushed_seq; - new_bits = t->bits + (nr_elements * 3 > size); + new_bits = ilog2(roundup_pow_of_two(nr_elements * 3)); n = kvmalloc(sizeof(*n) + (sizeof(n->d[0]) << new_bits), GFP_KERNEL); if (!n) { @@ -115,7 +115,14 @@ int bch2_set_bucket_needs_journal_commit(struct buckets_waiting_for_journal *b, } retry_rehash: + if (nr_rehashes_this_size == 3) { + new_bits++; + nr_rehashes_this_size = 0; + } + nr_rehashes++; + nr_rehashes_this_size++; + bucket_table_init(n, new_bits); tmp = new; diff --git a/fs/bcachefs/data_update.c b/fs/bcachefs/data_update.c index 0087b8555ead3c..6a854c9184965e 100644 --- a/fs/bcachefs/data_update.c +++ b/fs/bcachefs/data_update.c @@ -250,10 +250,8 @@ static int __bch2_data_update_index_update(struct btree_trans *trans, * it's been hard to reproduce, so this should give us some more * information when it does occur: */ - struct printbuf err = PRINTBUF; - int invalid = bch2_bkey_invalid(c, bkey_i_to_s_c(insert), __btree_node_type(0, m->btree_id), 0, &err); - printbuf_exit(&err); - + int invalid = bch2_bkey_validate(c, bkey_i_to_s_c(insert), __btree_node_type(0, m->btree_id), + BCH_VALIDATE_commit); if (invalid) { struct printbuf buf = PRINTBUF; diff --git a/fs/bcachefs/debug.c b/fs/bcachefs/debug.c index ebabab171fe5ea..45aec1afdb0e31 100644 --- a/fs/bcachefs/debug.c +++ b/fs/bcachefs/debug.c @@ -397,47 +397,27 @@ static ssize_t bch2_read_btree_formats(struct file *file, char __user *buf, size_t size, loff_t *ppos) { struct dump_iter *i = file->private_data; - struct btree_trans *trans; - struct btree_iter iter; - struct btree *b; - ssize_t ret; i->ubuf = buf; i->size = size; i->ret = 0; - ret = flush_buf(i); + ssize_t ret = flush_buf(i); if (ret) return ret; if (bpos_eq(SPOS_MAX, i->from)) return i->ret; - trans = bch2_trans_get(i->c); -retry: - bch2_trans_begin(trans); - - for_each_btree_node(trans, iter, i->id, i->from, 0, b, ret) { - bch2_btree_node_to_text(&i->buf, i->c, b); - i->from = !bpos_eq(SPOS_MAX, b->key.k.p) - ? bpos_successor(b->key.k.p) - : b->key.k.p; - - ret = drop_locks_do(trans, flush_buf(i)); - if (ret) - break; - } - bch2_trans_iter_exit(trans, &iter); - - if (bch2_err_matches(ret, BCH_ERR_transaction_restart)) - goto retry; - - bch2_trans_put(trans); - - if (!ret) - ret = flush_buf(i); + return bch2_trans_run(i->c, + for_each_btree_node(trans, iter, i->id, i->from, 0, b, ({ + bch2_btree_node_to_text(&i->buf, i->c, b); + i->from = !bpos_eq(SPOS_MAX, b->key.k.p) + ? bpos_successor(b->key.k.p) + : b->key.k.p; - return ret ?: i->ret; + drop_locks_do(trans, flush_buf(i)); + }))) ?: i->ret; } static const struct file_operations btree_format_debug_ops = { diff --git a/fs/bcachefs/dirent.c b/fs/bcachefs/dirent.c index d743da89308ef7..32bfdf19289a9d 100644 --- a/fs/bcachefs/dirent.c +++ b/fs/bcachefs/dirent.c @@ -100,20 +100,19 @@ const struct bch_hash_desc bch2_dirent_hash_desc = { .is_visible = dirent_is_visible, }; -int bch2_dirent_invalid(struct bch_fs *c, struct bkey_s_c k, - enum bch_validate_flags flags, - struct printbuf *err) +int bch2_dirent_validate(struct bch_fs *c, struct bkey_s_c k, + enum bch_validate_flags flags) { struct bkey_s_c_dirent d = bkey_s_c_to_dirent(k); struct qstr d_name = bch2_dirent_get_name(d); int ret = 0; - bkey_fsck_err_on(!d_name.len, c, err, - dirent_empty_name, + bkey_fsck_err_on(!d_name.len, + c, dirent_empty_name, "empty name"); - bkey_fsck_err_on(bkey_val_u64s(k.k) > dirent_val_u64s(d_name.len), c, err, - dirent_val_too_big, + bkey_fsck_err_on(bkey_val_u64s(k.k) > dirent_val_u64s(d_name.len), + c, dirent_val_too_big, "value too big (%zu > %u)", bkey_val_u64s(k.k), dirent_val_u64s(d_name.len)); @@ -121,27 +120,27 @@ int bch2_dirent_invalid(struct bch_fs *c, struct bkey_s_c k, * Check new keys don't exceed the max length * (older keys may be larger.) */ - bkey_fsck_err_on((flags & BCH_VALIDATE_commit) && d_name.len > BCH_NAME_MAX, c, err, - dirent_name_too_long, + bkey_fsck_err_on((flags & BCH_VALIDATE_commit) && d_name.len > BCH_NAME_MAX, + c, dirent_name_too_long, "dirent name too big (%u > %u)", d_name.len, BCH_NAME_MAX); - bkey_fsck_err_on(d_name.len != strnlen(d_name.name, d_name.len), c, err, - dirent_name_embedded_nul, + bkey_fsck_err_on(d_name.len != strnlen(d_name.name, d_name.len), + c, dirent_name_embedded_nul, "dirent has stray data after name's NUL"); bkey_fsck_err_on((d_name.len == 1 && !memcmp(d_name.name, ".", 1)) || - (d_name.len == 2 && !memcmp(d_name.name, "..", 2)), c, err, - dirent_name_dot_or_dotdot, + (d_name.len == 2 && !memcmp(d_name.name, "..", 2)), + c, dirent_name_dot_or_dotdot, "invalid name"); - bkey_fsck_err_on(memchr(d_name.name, '/', d_name.len), c, err, - dirent_name_has_slash, + bkey_fsck_err_on(memchr(d_name.name, '/', d_name.len), + c, dirent_name_has_slash, "name with /"); bkey_fsck_err_on(d.v->d_type != DT_SUBVOL && - le64_to_cpu(d.v->d_inum) == d.k->p.inode, c, err, - dirent_to_itself, + le64_to_cpu(d.v->d_inum) == d.k->p.inode, + c, dirent_to_itself, "dirent points to own directory"); fsck_err: return ret; diff --git a/fs/bcachefs/dirent.h b/fs/bcachefs/dirent.h index 24037e6e0a0948..8945145865c53b 100644 --- a/fs/bcachefs/dirent.h +++ b/fs/bcachefs/dirent.h @@ -7,12 +7,11 @@ enum bch_validate_flags; extern const struct bch_hash_desc bch2_dirent_hash_desc; -int bch2_dirent_invalid(struct bch_fs *, struct bkey_s_c, - enum bch_validate_flags, struct printbuf *); +int bch2_dirent_validate(struct bch_fs *, struct bkey_s_c, enum bch_validate_flags); void bch2_dirent_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c); #define bch2_bkey_ops_dirent ((struct bkey_ops) { \ - .key_invalid = bch2_dirent_invalid, \ + .key_validate = bch2_dirent_validate, \ .val_to_text = bch2_dirent_to_text, \ .min_val_size = 16, \ }) diff --git a/fs/bcachefs/disk_accounting.c b/fs/bcachefs/disk_accounting.c index dcdd59249c23eb..e972e2bca546a9 100644 --- a/fs/bcachefs/disk_accounting.c +++ b/fs/bcachefs/disk_accounting.c @@ -114,11 +114,73 @@ int bch2_mod_dev_cached_sectors(struct btree_trans *trans, return bch2_disk_accounting_mod(trans, &acc, §ors, 1, gc); } -int bch2_accounting_invalid(struct bch_fs *c, struct bkey_s_c k, - enum bch_validate_flags flags, - struct printbuf *err) +static inline bool is_zero(char *start, char *end) { - return 0; + BUG_ON(start > end); + + for (; start < end; start++) + if (*start) + return false; + return true; +} + +#define field_end(p, member) (((void *) (&p.member)) + sizeof(p.member)) + +int bch2_accounting_validate(struct bch_fs *c, struct bkey_s_c k, + enum bch_validate_flags flags) +{ + struct disk_accounting_pos acc_k; + bpos_to_disk_accounting_pos(&acc_k, k.k->p); + void *end = &acc_k + 1; + int ret = 0; + + switch (acc_k.type) { + case BCH_DISK_ACCOUNTING_nr_inodes: + end = field_end(acc_k, nr_inodes); + break; + case BCH_DISK_ACCOUNTING_persistent_reserved: + end = field_end(acc_k, persistent_reserved); + break; + case BCH_DISK_ACCOUNTING_replicas: + bkey_fsck_err_on(!acc_k.replicas.nr_devs, + c, accounting_key_replicas_nr_devs_0, + "accounting key replicas entry with nr_devs=0"); + + bkey_fsck_err_on(acc_k.replicas.nr_required > acc_k.replicas.nr_devs || + (acc_k.replicas.nr_required > 1 && + acc_k.replicas.nr_required == acc_k.replicas.nr_devs), + c, accounting_key_replicas_nr_required_bad, + "accounting key replicas entry with bad nr_required"); + + for (unsigned i = 0; i + 1 < acc_k.replicas.nr_devs; i++) + bkey_fsck_err_on(acc_k.replicas.devs[i] >= acc_k.replicas.devs[i + 1], + c, accounting_key_replicas_devs_unsorted, + "accounting key replicas entry with unsorted devs"); + + end = (void *) &acc_k.replicas + replicas_entry_bytes(&acc_k.replicas); + break; + case BCH_DISK_ACCOUNTING_dev_data_type: + end = field_end(acc_k, dev_data_type); + break; + case BCH_DISK_ACCOUNTING_compression: + end = field_end(acc_k, compression); + break; + case BCH_DISK_ACCOUNTING_snapshot: + end = field_end(acc_k, snapshot); + break; + case BCH_DISK_ACCOUNTING_btree: + end = field_end(acc_k, btree); + break; + case BCH_DISK_ACCOUNTING_rebalance_work: + end = field_end(acc_k, rebalance_work); + break; + } + + bkey_fsck_err_on(!is_zero(end, (void *) (&acc_k + 1)), + c, accounting_key_junk_at_end, + "junk at end of accounting key"); +fsck_err: + return ret; } void bch2_accounting_key_to_text(struct printbuf *out, struct disk_accounting_pos *k) @@ -465,6 +527,9 @@ int bch2_gc_accounting_done(struct bch_fs *c) struct disk_accounting_pos acc_k; bpos_to_disk_accounting_pos(&acc_k, e->pos); + if (acc_k.type >= BCH_DISK_ACCOUNTING_TYPE_NR) + continue; + u64 src_v[BCH_ACCOUNTING_MAX_COUNTERS]; u64 dst_v[BCH_ACCOUNTING_MAX_COUNTERS]; @@ -501,7 +566,7 @@ int bch2_gc_accounting_done(struct bch_fs *c) struct { __BKEY_PADDED(k, BCH_ACCOUNTING_MAX_COUNTERS); } k_i; accounting_key_init(&k_i.k, &acc_k, src_v, nr); - bch2_accounting_mem_mod_locked(trans, bkey_i_to_s_c_accounting(&k_i.k), false); + bch2_accounting_mem_mod_locked(trans, bkey_i_to_s_c_accounting(&k_i.k), false, false); preempt_disable(); struct bch_fs_usage_base *dst = this_cpu_ptr(c->usage); @@ -530,7 +595,7 @@ static int accounting_read_key(struct btree_trans *trans, struct bkey_s_c k) return 0; percpu_down_read(&c->mark_lock); - int ret = __bch2_accounting_mem_mod(c, bkey_s_c_to_accounting(k), false); + int ret = bch2_accounting_mem_mod_locked(trans, bkey_s_c_to_accounting(k), false, true); percpu_up_read(&c->mark_lock); if (bch2_accounting_key_is_zero(bkey_s_c_to_accounting(k)) && @@ -697,6 +762,15 @@ void bch2_verify_accounting_clean(struct bch_fs *c) struct bkey_s_c_accounting a = bkey_s_c_to_accounting(k); unsigned nr = bch2_accounting_counters(k.k); + struct disk_accounting_pos acc_k; + bpos_to_disk_accounting_pos(&acc_k, k.k->p); + + if (acc_k.type >= BCH_DISK_ACCOUNTING_TYPE_NR) + continue; + + if (acc_k.type == BCH_DISK_ACCOUNTING_inum) + continue; + bch2_accounting_mem_read(c, k.k->p, v, nr); if (memcmp(a.v->d, v, nr * sizeof(u64))) { @@ -712,9 +786,6 @@ void bch2_verify_accounting_clean(struct bch_fs *c) mismatch = true; } - struct disk_accounting_pos acc_k; - bpos_to_disk_accounting_pos(&acc_k, a.k->p); - switch (acc_k.type) { case BCH_DISK_ACCOUNTING_persistent_reserved: base.reserved += acc_k.persistent_reserved.nr_replicas * a.v->d[0]; diff --git a/fs/bcachefs/disk_accounting.h b/fs/bcachefs/disk_accounting.h index 3d3f25e08b6961..f29fd0dd9581fb 100644 --- a/fs/bcachefs/disk_accounting.h +++ b/fs/bcachefs/disk_accounting.h @@ -82,14 +82,13 @@ int bch2_disk_accounting_mod(struct btree_trans *, struct disk_accounting_pos *, s64 *, unsigned, bool); int bch2_mod_dev_cached_sectors(struct btree_trans *, unsigned, s64, bool); -int bch2_accounting_invalid(struct bch_fs *, struct bkey_s_c, - enum bch_validate_flags, struct printbuf *); +int bch2_accounting_validate(struct bch_fs *, struct bkey_s_c, enum bch_validate_flags); void bch2_accounting_key_to_text(struct printbuf *, struct disk_accounting_pos *); void bch2_accounting_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c); void bch2_accounting_swab(struct bkey_s); #define bch2_bkey_ops_accounting ((struct bkey_ops) { \ - .key_invalid = bch2_accounting_invalid, \ + .key_validate = bch2_accounting_validate, \ .val_to_text = bch2_accounting_to_text, \ .swab = bch2_accounting_swab, \ .min_val_size = 8, \ @@ -107,41 +106,20 @@ static inline int accounting_pos_cmp(const void *_l, const void *_r) int bch2_accounting_mem_insert(struct bch_fs *, struct bkey_s_c_accounting, bool); void bch2_accounting_mem_gc(struct bch_fs *); -static inline int __bch2_accounting_mem_mod(struct bch_fs *c, struct bkey_s_c_accounting a, bool gc) -{ - struct bch_accounting_mem *acc = &c->accounting; - unsigned idx; - - EBUG_ON(gc && !acc->gc_running); - - while ((idx = eytzinger0_find(acc->k.data, acc->k.nr, sizeof(acc->k.data[0]), - accounting_pos_cmp, &a.k->p)) >= acc->k.nr) { - int ret = bch2_accounting_mem_insert(c, a, gc); - if (ret) - return ret; - } - - struct accounting_mem_entry *e = &acc->k.data[idx]; - - EBUG_ON(bch2_accounting_counters(a.k) != e->nr_counters); - - for (unsigned i = 0; i < bch2_accounting_counters(a.k); i++) - this_cpu_add(e->v[gc][i], a.v->d[i]); - return 0; -} - /* * Update in memory counters so they match the btree update we're doing; called * from transaction commit path */ -static inline int bch2_accounting_mem_mod_locked(struct btree_trans *trans, struct bkey_s_c_accounting a, bool gc) +static inline int bch2_accounting_mem_mod_locked(struct btree_trans *trans, struct bkey_s_c_accounting a, bool gc, bool read) { struct bch_fs *c = trans->c; + struct disk_accounting_pos acc_k; + bpos_to_disk_accounting_pos(&acc_k, a.k->p); - if (!gc) { - struct disk_accounting_pos acc_k; - bpos_to_disk_accounting_pos(&acc_k, a.k->p); + if (acc_k.type == BCH_DISK_ACCOUNTING_inum) + return 0; + if (!gc && !read) { switch (acc_k.type) { case BCH_DISK_ACCOUNTING_persistent_reserved: trans->fs_usage_delta.reserved += acc_k.persistent_reserved.nr_replicas * a.v->d[0]; @@ -162,13 +140,31 @@ static inline int bch2_accounting_mem_mod_locked(struct btree_trans *trans, stru } } - return __bch2_accounting_mem_mod(c, a, gc); + struct bch_accounting_mem *acc = &c->accounting; + unsigned idx; + + EBUG_ON(gc && !acc->gc_running); + + while ((idx = eytzinger0_find(acc->k.data, acc->k.nr, sizeof(acc->k.data[0]), + accounting_pos_cmp, &a.k->p)) >= acc->k.nr) { + int ret = bch2_accounting_mem_insert(c, a, gc); + if (ret) + return ret; + } + + struct accounting_mem_entry *e = &acc->k.data[idx]; + + EBUG_ON(bch2_accounting_counters(a.k) != e->nr_counters); + + for (unsigned i = 0; i < bch2_accounting_counters(a.k); i++) + this_cpu_add(e->v[gc][i], a.v->d[i]); + return 0; } static inline int bch2_accounting_mem_add(struct btree_trans *trans, struct bkey_s_c_accounting a, bool gc) { percpu_down_read(&trans->c->mark_lock); - int ret = bch2_accounting_mem_mod_locked(trans, a, gc); + int ret = bch2_accounting_mem_mod_locked(trans, a, gc, false); percpu_up_read(&trans->c->mark_lock); return ret; } diff --git a/fs/bcachefs/disk_accounting_format.h b/fs/bcachefs/disk_accounting_format.h index cba417060b3331..7b6e6c97e6aa6a 100644 --- a/fs/bcachefs/disk_accounting_format.h +++ b/fs/bcachefs/disk_accounting_format.h @@ -103,7 +103,8 @@ static inline bool data_type_is_hidden(enum bch_data_type type) x(compression, 4) \ x(snapshot, 5) \ x(btree, 6) \ - x(rebalance_work, 7) + x(rebalance_work, 7) \ + x(inum, 8) enum disk_accounting_type { #define x(f, nr) BCH_DISK_ACCOUNTING_##f = nr, @@ -124,20 +125,23 @@ struct bch_dev_data_type { __u8 data_type; }; -struct bch_dev_stripe_buckets { - __u8 dev; -}; - struct bch_acct_compression { __u8 type; }; struct bch_acct_snapshot { __u32 id; -}; +} __packed; struct bch_acct_btree { __u32 id; +} __packed; + +struct bch_acct_inum { + __u64 inum; +} __packed; + +struct bch_acct_rebalance_work { }; struct disk_accounting_pos { @@ -149,12 +153,13 @@ struct disk_accounting_pos { struct bch_persistent_reserved persistent_reserved; struct bch_replicas_entry_v1 replicas; struct bch_dev_data_type dev_data_type; - struct bch_dev_stripe_buckets dev_stripe_buckets; struct bch_acct_compression compression; struct bch_acct_snapshot snapshot; struct bch_acct_btree btree; - }; - }; + struct bch_acct_rebalance_work rebalance_work; + struct bch_acct_inum inum; + } __packed; + } __packed; struct bpos _pad; }; }; diff --git a/fs/bcachefs/ec.c b/fs/bcachefs/ec.c index 9b5b5c9a6c638c..141a4c63142f5b 100644 --- a/fs/bcachefs/ec.c +++ b/fs/bcachefs/ec.c @@ -107,24 +107,23 @@ struct ec_bio { /* Stripes btree keys: */ -int bch2_stripe_invalid(struct bch_fs *c, struct bkey_s_c k, - enum bch_validate_flags flags, - struct printbuf *err) +int bch2_stripe_validate(struct bch_fs *c, struct bkey_s_c k, + enum bch_validate_flags flags) { const struct bch_stripe *s = bkey_s_c_to_stripe(k).v; int ret = 0; bkey_fsck_err_on(bkey_eq(k.k->p, POS_MIN) || - bpos_gt(k.k->p, POS(0, U32_MAX)), c, err, - stripe_pos_bad, + bpos_gt(k.k->p, POS(0, U32_MAX)), + c, stripe_pos_bad, "stripe at bad pos"); - bkey_fsck_err_on(bkey_val_u64s(k.k) < stripe_val_u64s(s), c, err, - stripe_val_size_bad, + bkey_fsck_err_on(bkey_val_u64s(k.k) < stripe_val_u64s(s), + c, stripe_val_size_bad, "incorrect value size (%zu < %u)", bkey_val_u64s(k.k), stripe_val_u64s(s)); - ret = bch2_bkey_ptrs_invalid(c, k, flags, err); + ret = bch2_bkey_ptrs_validate(c, k, flags); fsck_err: return ret; } @@ -1809,6 +1808,9 @@ static int new_stripe_alloc_buckets(struct btree_trans *trans, struct ec_stripe_ BUG_ON(v->nr_blocks != h->s->nr_data + h->s->nr_parity); BUG_ON(v->nr_redundant != h->s->nr_parity); + /* * We bypass the sector allocator which normally does this: */ + bitmap_and(devs.d, devs.d, c->rw_devs[BCH_DATA_user].d, BCH_SB_MEMBERS_MAX); + for_each_set_bit(i, h->s->blocks_gotten, v->nr_blocks) { __clear_bit(v->ptrs[i].dev, devs.d); if (i < h->s->nr_data) @@ -2235,6 +2237,23 @@ void bch2_stripes_heap_to_text(struct printbuf *out, struct bch_fs *c) mutex_unlock(&c->ec_stripes_heap_lock); } +static void bch2_new_stripe_to_text(struct printbuf *out, struct bch_fs *c, + struct ec_stripe_new *s) +{ + prt_printf(out, "\tidx %llu blocks %u+%u allocated %u ref %u %u %s obs", + s->idx, s->nr_data, s->nr_parity, + bitmap_weight(s->blocks_allocated, s->nr_data), + atomic_read(&s->ref[STRIPE_REF_io]), + atomic_read(&s->ref[STRIPE_REF_stripe]), + bch2_watermarks[s->h->watermark]); + + struct bch_stripe *v = &bkey_i_to_stripe(&s->new_stripe.key)->v; + unsigned i; + for_each_set_bit(i, s->blocks_gotten, v->nr_blocks) + prt_printf(out, " %u", s->blocks[i]); + prt_newline(out); +} + void bch2_new_stripes_to_text(struct printbuf *out, struct bch_fs *c) { struct ec_stripe_head *h; @@ -2247,23 +2266,15 @@ void bch2_new_stripes_to_text(struct printbuf *out, struct bch_fs *c) bch2_watermarks[h->watermark]); if (h->s) - prt_printf(out, "\tidx %llu blocks %u+%u allocated %u\n", - h->s->idx, h->s->nr_data, h->s->nr_parity, - bitmap_weight(h->s->blocks_allocated, - h->s->nr_data)); + bch2_new_stripe_to_text(out, c, h->s); } mutex_unlock(&c->ec_stripe_head_lock); prt_printf(out, "in flight:\n"); mutex_lock(&c->ec_stripe_new_lock); - list_for_each_entry(s, &c->ec_stripe_new_list, list) { - prt_printf(out, "\tidx %llu blocks %u+%u ref %u %u %s\n", - s->idx, s->nr_data, s->nr_parity, - atomic_read(&s->ref[STRIPE_REF_io]), - atomic_read(&s->ref[STRIPE_REF_stripe]), - bch2_watermarks[s->h->watermark]); - } + list_for_each_entry(s, &c->ec_stripe_new_list, list) + bch2_new_stripe_to_text(out, c, s); mutex_unlock(&c->ec_stripe_new_lock); } diff --git a/fs/bcachefs/ec.h b/fs/bcachefs/ec.h index 84a23eeb62495e..90962b3c013057 100644 --- a/fs/bcachefs/ec.h +++ b/fs/bcachefs/ec.h @@ -8,8 +8,7 @@ enum bch_validate_flags; -int bch2_stripe_invalid(struct bch_fs *, struct bkey_s_c, - enum bch_validate_flags, struct printbuf *); +int bch2_stripe_validate(struct bch_fs *, struct bkey_s_c, enum bch_validate_flags); void bch2_stripe_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c); int bch2_trigger_stripe(struct btree_trans *, enum btree_id, unsigned, @@ -17,7 +16,7 @@ int bch2_trigger_stripe(struct btree_trans *, enum btree_id, unsigned, enum btree_iter_update_trigger_flags); #define bch2_bkey_ops_stripe ((struct bkey_ops) { \ - .key_invalid = bch2_stripe_invalid, \ + .key_validate = bch2_stripe_validate, \ .val_to_text = bch2_stripe_to_text, \ .swab = bch2_ptr_swab, \ .trigger = bch2_trigger_stripe, \ diff --git a/fs/bcachefs/errcode.h b/fs/bcachefs/errcode.h index a268af3e52bfd8..ab5a7adece1042 100644 --- a/fs/bcachefs/errcode.h +++ b/fs/bcachefs/errcode.h @@ -166,6 +166,7 @@ x(0, journal_reclaim_would_deadlock) \ x(EINVAL, fsck) \ x(BCH_ERR_fsck, fsck_fix) \ + x(BCH_ERR_fsck, fsck_delete_bkey) \ x(BCH_ERR_fsck, fsck_ignore) \ x(BCH_ERR_fsck, fsck_errors_not_fixed) \ x(BCH_ERR_fsck, fsck_repair_unimplemented) \ diff --git a/fs/bcachefs/error.c b/fs/bcachefs/error.c index a62b6310882003..95afa7bf20205c 100644 --- a/fs/bcachefs/error.c +++ b/fs/bcachefs/error.c @@ -416,6 +416,28 @@ int __bch2_fsck_err(struct bch_fs *c, return ret; } +int __bch2_bkey_fsck_err(struct bch_fs *c, + struct bkey_s_c k, + enum bch_fsck_flags flags, + enum bch_sb_error_id err, + const char *fmt, ...) +{ + struct printbuf buf = PRINTBUF; + va_list args; + + prt_str(&buf, "invalid bkey "); + bch2_bkey_val_to_text(&buf, c, k); + prt_str(&buf, "\n "); + va_start(args, fmt); + prt_vprintf(&buf, fmt, args); + va_end(args); + prt_str(&buf, ": delete?"); + + int ret = __bch2_fsck_err(c, NULL, flags, err, "%s", buf.buf); + printbuf_exit(&buf); + return ret; +} + void bch2_flush_fsck_errs(struct bch_fs *c) { struct fsck_err_state *s, *n; diff --git a/fs/bcachefs/error.h b/fs/bcachefs/error.h index 995e6bba9bad80..2f1b86978f3660 100644 --- a/fs/bcachefs/error.h +++ b/fs/bcachefs/error.h @@ -4,6 +4,7 @@ #include #include +#include "bkey_types.h" #include "sb-errors.h" struct bch_dev; @@ -166,24 +167,30 @@ void bch2_flush_fsck_errs(struct bch_fs *); #define fsck_err_on(cond, c, _err_type, ...) \ __fsck_err_on(cond, c, FSCK_CAN_FIX|FSCK_CAN_IGNORE, _err_type, __VA_ARGS__) -__printf(4, 0) -static inline void bch2_bkey_fsck_err(struct bch_fs *c, - struct printbuf *err_msg, - enum bch_sb_error_id err_type, - const char *fmt, ...) -{ - va_list args; +__printf(5, 6) +int __bch2_bkey_fsck_err(struct bch_fs *, + struct bkey_s_c, + enum bch_fsck_flags, + enum bch_sb_error_id, + const char *, ...); - va_start(args, fmt); - prt_vprintf(err_msg, fmt, args); - va_end(args); -} - -#define bkey_fsck_err(c, _err_msg, _err_type, ...) \ +/* + * for now, bkey fsck errors are always handled by deleting the entire key - + * this will change at some point + */ +#define bkey_fsck_err(c, _err_type, _err_msg, ...) \ do { \ - prt_printf(_err_msg, __VA_ARGS__); \ - bch2_sb_error_count(c, BCH_FSCK_ERR_##_err_type); \ - ret = -BCH_ERR_invalid_bkey; \ + if ((flags & BCH_VALIDATE_silent)) { \ + ret = -BCH_ERR_fsck_delete_bkey; \ + goto fsck_err; \ + } \ + int _ret = __bch2_bkey_fsck_err(c, k, FSCK_CAN_FIX, \ + BCH_FSCK_ERR_##_err_type, \ + _err_msg, ##__VA_ARGS__); \ + if (_ret != -BCH_ERR_fsck_fix && \ + _ret != -BCH_ERR_fsck_ignore) \ + ret = _ret; \ + ret = -BCH_ERR_fsck_delete_bkey; \ goto fsck_err; \ } while (0) diff --git a/fs/bcachefs/extents.c b/fs/bcachefs/extents.c index 07973198e35fb7..4419ad3e454e4f 100644 --- a/fs/bcachefs/extents.c +++ b/fs/bcachefs/extents.c @@ -171,17 +171,16 @@ int bch2_bkey_pick_read_device(struct bch_fs *c, struct bkey_s_c k, /* KEY_TYPE_btree_ptr: */ -int bch2_btree_ptr_invalid(struct bch_fs *c, struct bkey_s_c k, - enum bch_validate_flags flags, - struct printbuf *err) +int bch2_btree_ptr_validate(struct bch_fs *c, struct bkey_s_c k, + enum bch_validate_flags flags) { int ret = 0; - bkey_fsck_err_on(bkey_val_u64s(k.k) > BCH_REPLICAS_MAX, c, err, - btree_ptr_val_too_big, + bkey_fsck_err_on(bkey_val_u64s(k.k) > BCH_REPLICAS_MAX, + c, btree_ptr_val_too_big, "value too big (%zu > %u)", bkey_val_u64s(k.k), BCH_REPLICAS_MAX); - ret = bch2_bkey_ptrs_invalid(c, k, flags, err); + ret = bch2_bkey_ptrs_validate(c, k, flags); fsck_err: return ret; } @@ -192,28 +191,27 @@ void bch2_btree_ptr_to_text(struct printbuf *out, struct bch_fs *c, bch2_bkey_ptrs_to_text(out, c, k); } -int bch2_btree_ptr_v2_invalid(struct bch_fs *c, struct bkey_s_c k, - enum bch_validate_flags flags, - struct printbuf *err) +int bch2_btree_ptr_v2_validate(struct bch_fs *c, struct bkey_s_c k, + enum bch_validate_flags flags) { struct bkey_s_c_btree_ptr_v2 bp = bkey_s_c_to_btree_ptr_v2(k); int ret = 0; bkey_fsck_err_on(bkey_val_u64s(k.k) > BKEY_BTREE_PTR_VAL_U64s_MAX, - c, err, btree_ptr_v2_val_too_big, + c, btree_ptr_v2_val_too_big, "value too big (%zu > %zu)", bkey_val_u64s(k.k), BKEY_BTREE_PTR_VAL_U64s_MAX); bkey_fsck_err_on(bpos_ge(bp.v->min_key, bp.k->p), - c, err, btree_ptr_v2_min_key_bad, + c, btree_ptr_v2_min_key_bad, "min_key > key"); if (flags & BCH_VALIDATE_write) bkey_fsck_err_on(!bp.v->sectors_written, - c, err, btree_ptr_v2_written_0, + c, btree_ptr_v2_written_0, "sectors_written == 0"); - ret = bch2_bkey_ptrs_invalid(c, k, flags, err); + ret = bch2_bkey_ptrs_validate(c, k, flags); fsck_err: return ret; } @@ -399,15 +397,14 @@ bool bch2_extent_merge(struct bch_fs *c, struct bkey_s l, struct bkey_s_c r) /* KEY_TYPE_reservation: */ -int bch2_reservation_invalid(struct bch_fs *c, struct bkey_s_c k, - enum bch_validate_flags flags, - struct printbuf *err) +int bch2_reservation_validate(struct bch_fs *c, struct bkey_s_c k, + enum bch_validate_flags flags) { struct bkey_s_c_reservation r = bkey_s_c_to_reservation(k); int ret = 0; - bkey_fsck_err_on(!r.v->nr_replicas || r.v->nr_replicas > BCH_REPLICAS_MAX, c, err, - reservation_key_nr_replicas_invalid, + bkey_fsck_err_on(!r.v->nr_replicas || r.v->nr_replicas > BCH_REPLICAS_MAX, + c, reservation_key_nr_replicas_invalid, "invalid nr_replicas (%u)", r.v->nr_replicas); fsck_err: return ret; @@ -1102,14 +1099,12 @@ void bch2_bkey_ptrs_to_text(struct printbuf *out, struct bch_fs *c, } } - -static int extent_ptr_invalid(struct bch_fs *c, - struct bkey_s_c k, - enum bch_validate_flags flags, - const struct bch_extent_ptr *ptr, - unsigned size_ondisk, - bool metadata, - struct printbuf *err) +static int extent_ptr_validate(struct bch_fs *c, + struct bkey_s_c k, + enum bch_validate_flags flags, + const struct bch_extent_ptr *ptr, + unsigned size_ondisk, + bool metadata) { int ret = 0; @@ -1128,28 +1123,27 @@ static int extent_ptr_invalid(struct bch_fs *c, struct bkey_ptrs_c ptrs = bch2_bkey_ptrs_c(k); bkey_for_each_ptr(ptrs, ptr2) - bkey_fsck_err_on(ptr != ptr2 && ptr->dev == ptr2->dev, c, err, - ptr_to_duplicate_device, + bkey_fsck_err_on(ptr != ptr2 && ptr->dev == ptr2->dev, + c, ptr_to_duplicate_device, "multiple pointers to same device (%u)", ptr->dev); - bkey_fsck_err_on(bucket >= nbuckets, c, err, - ptr_after_last_bucket, + bkey_fsck_err_on(bucket >= nbuckets, + c, ptr_after_last_bucket, "pointer past last bucket (%llu > %llu)", bucket, nbuckets); - bkey_fsck_err_on(bucket < first_bucket, c, err, - ptr_before_first_bucket, + bkey_fsck_err_on(bucket < first_bucket, + c, ptr_before_first_bucket, "pointer before first bucket (%llu < %u)", bucket, first_bucket); - bkey_fsck_err_on(bucket_offset + size_ondisk > bucket_size, c, err, - ptr_spans_multiple_buckets, + bkey_fsck_err_on(bucket_offset + size_ondisk > bucket_size, + c, ptr_spans_multiple_buckets, "pointer spans multiple buckets (%u + %u > %u)", bucket_offset, size_ondisk, bucket_size); fsck_err: return ret; } -int bch2_bkey_ptrs_invalid(struct bch_fs *c, struct bkey_s_c k, - enum bch_validate_flags flags, - struct printbuf *err) +int bch2_bkey_ptrs_validate(struct bch_fs *c, struct bkey_s_c k, + enum bch_validate_flags flags) { struct bkey_ptrs_c ptrs = bch2_bkey_ptrs_c(k); const union bch_extent_entry *entry; @@ -1164,25 +1158,24 @@ int bch2_bkey_ptrs_invalid(struct bch_fs *c, struct bkey_s_c k, size_ondisk = btree_sectors(c); bkey_extent_entry_for_each(ptrs, entry) { - bkey_fsck_err_on(__extent_entry_type(entry) >= BCH_EXTENT_ENTRY_MAX, c, err, - extent_ptrs_invalid_entry, - "invalid extent entry type (got %u, max %u)", - __extent_entry_type(entry), BCH_EXTENT_ENTRY_MAX); + bkey_fsck_err_on(__extent_entry_type(entry) >= BCH_EXTENT_ENTRY_MAX, + c, extent_ptrs_invalid_entry, + "invalid extent entry type (got %u, max %u)", + __extent_entry_type(entry), BCH_EXTENT_ENTRY_MAX); bkey_fsck_err_on(bkey_is_btree_ptr(k.k) && - !extent_entry_is_ptr(entry), c, err, - btree_ptr_has_non_ptr, + !extent_entry_is_ptr(entry), + c, btree_ptr_has_non_ptr, "has non ptr field"); switch (extent_entry_type(entry)) { case BCH_EXTENT_ENTRY_ptr: - ret = extent_ptr_invalid(c, k, flags, &entry->ptr, - size_ondisk, false, err); + ret = extent_ptr_validate(c, k, flags, &entry->ptr, size_ondisk, false); if (ret) return ret; - bkey_fsck_err_on(entry->ptr.cached && have_ec, c, err, - ptr_cached_and_erasure_coded, + bkey_fsck_err_on(entry->ptr.cached && have_ec, + c, ptr_cached_and_erasure_coded, "cached, erasure coded ptr"); if (!entry->ptr.unwritten) @@ -1199,44 +1192,50 @@ int bch2_bkey_ptrs_invalid(struct bch_fs *c, struct bkey_s_c k, case BCH_EXTENT_ENTRY_crc128: crc = bch2_extent_crc_unpack(k.k, entry_to_crc(entry)); - bkey_fsck_err_on(crc.offset + crc.live_size > crc.uncompressed_size, c, err, - ptr_crc_uncompressed_size_too_small, + bkey_fsck_err_on(crc.offset + crc.live_size > crc.uncompressed_size, + c, ptr_crc_uncompressed_size_too_small, "checksum offset + key size > uncompressed size"); - bkey_fsck_err_on(!bch2_checksum_type_valid(c, crc.csum_type), c, err, - ptr_crc_csum_type_unknown, + bkey_fsck_err_on(!bch2_checksum_type_valid(c, crc.csum_type), + c, ptr_crc_csum_type_unknown, "invalid checksum type"); - bkey_fsck_err_on(crc.compression_type >= BCH_COMPRESSION_TYPE_NR, c, err, - ptr_crc_compression_type_unknown, + bkey_fsck_err_on(crc.compression_type >= BCH_COMPRESSION_TYPE_NR, + c, ptr_crc_compression_type_unknown, "invalid compression type"); if (bch2_csum_type_is_encryption(crc.csum_type)) { if (nonce == UINT_MAX) nonce = crc.offset + crc.nonce; else if (nonce != crc.offset + crc.nonce) - bkey_fsck_err(c, err, ptr_crc_nonce_mismatch, + bkey_fsck_err(c, ptr_crc_nonce_mismatch, "incorrect nonce"); } - bkey_fsck_err_on(crc_since_last_ptr, c, err, - ptr_crc_redundant, + bkey_fsck_err_on(crc_since_last_ptr, + c, ptr_crc_redundant, "redundant crc entry"); crc_since_last_ptr = true; bkey_fsck_err_on(crc_is_encoded(crc) && (crc.uncompressed_size > c->opts.encoded_extent_max >> 9) && - (flags & (BCH_VALIDATE_write|BCH_VALIDATE_commit)), c, err, - ptr_crc_uncompressed_size_too_big, + (flags & (BCH_VALIDATE_write|BCH_VALIDATE_commit)), + c, ptr_crc_uncompressed_size_too_big, "too large encoded extent"); size_ondisk = crc.compressed_size; break; case BCH_EXTENT_ENTRY_stripe_ptr: - bkey_fsck_err_on(have_ec, c, err, - ptr_stripe_redundant, + bkey_fsck_err_on(have_ec, + c, ptr_stripe_redundant, "redundant stripe entry"); have_ec = true; break; case BCH_EXTENT_ENTRY_rebalance: { + /* + * this shouldn't be a fsck error, for forward + * compatibility; the rebalance code should just refetch + * the compression opt if it's unknown + */ +#if 0 const struct bch_extent_rebalance *r = &entry->rebalance; if (!bch2_compression_opt_valid(r->compression)) { @@ -1245,28 +1244,29 @@ int bch2_bkey_ptrs_invalid(struct bch_fs *c, struct bkey_s_c k, opt.type, opt.level); return -BCH_ERR_invalid_bkey; } +#endif break; } } } - bkey_fsck_err_on(!nr_ptrs, c, err, - extent_ptrs_no_ptrs, + bkey_fsck_err_on(!nr_ptrs, + c, extent_ptrs_no_ptrs, "no ptrs"); - bkey_fsck_err_on(nr_ptrs > BCH_BKEY_PTRS_MAX, c, err, - extent_ptrs_too_many_ptrs, + bkey_fsck_err_on(nr_ptrs > BCH_BKEY_PTRS_MAX, + c, extent_ptrs_too_many_ptrs, "too many ptrs: %u > %u", nr_ptrs, BCH_BKEY_PTRS_MAX); - bkey_fsck_err_on(have_written && have_unwritten, c, err, - extent_ptrs_written_and_unwritten, + bkey_fsck_err_on(have_written && have_unwritten, + c, extent_ptrs_written_and_unwritten, "extent with unwritten and written ptrs"); - bkey_fsck_err_on(k.k->type != KEY_TYPE_extent && have_unwritten, c, err, - extent_ptrs_unwritten, + bkey_fsck_err_on(k.k->type != KEY_TYPE_extent && have_unwritten, + c, extent_ptrs_unwritten, "has unwritten ptrs"); - bkey_fsck_err_on(crc_since_last_ptr, c, err, - extent_ptrs_redundant_crc, + bkey_fsck_err_on(crc_since_last_ptr, + c, extent_ptrs_redundant_crc, "redundant crc entry"); - bkey_fsck_err_on(have_ec, c, err, - extent_ptrs_redundant_stripe, + bkey_fsck_err_on(have_ec, + c, extent_ptrs_redundant_stripe, "redundant stripe entry"); fsck_err: return ret; diff --git a/fs/bcachefs/extents.h b/fs/bcachefs/extents.h index facdb8a86eec84..1a6ddee48041d1 100644 --- a/fs/bcachefs/extents.h +++ b/fs/bcachefs/extents.h @@ -409,26 +409,26 @@ int bch2_bkey_pick_read_device(struct bch_fs *, struct bkey_s_c, /* KEY_TYPE_btree_ptr: */ -int bch2_btree_ptr_invalid(struct bch_fs *, struct bkey_s_c, - enum bch_validate_flags, struct printbuf *); +int bch2_btree_ptr_validate(struct bch_fs *, struct bkey_s_c, + enum bch_validate_flags); void bch2_btree_ptr_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c); -int bch2_btree_ptr_v2_invalid(struct bch_fs *, struct bkey_s_c, - enum bch_validate_flags, struct printbuf *); +int bch2_btree_ptr_v2_validate(struct bch_fs *, struct bkey_s_c, + enum bch_validate_flags); void bch2_btree_ptr_v2_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c); void bch2_btree_ptr_v2_compat(enum btree_id, unsigned, unsigned, int, struct bkey_s); #define bch2_bkey_ops_btree_ptr ((struct bkey_ops) { \ - .key_invalid = bch2_btree_ptr_invalid, \ + .key_validate = bch2_btree_ptr_validate, \ .val_to_text = bch2_btree_ptr_to_text, \ .swab = bch2_ptr_swab, \ .trigger = bch2_trigger_extent, \ }) #define bch2_bkey_ops_btree_ptr_v2 ((struct bkey_ops) { \ - .key_invalid = bch2_btree_ptr_v2_invalid, \ + .key_validate = bch2_btree_ptr_v2_validate, \ .val_to_text = bch2_btree_ptr_v2_to_text, \ .swab = bch2_ptr_swab, \ .compat = bch2_btree_ptr_v2_compat, \ @@ -441,7 +441,7 @@ void bch2_btree_ptr_v2_compat(enum btree_id, unsigned, unsigned, bool bch2_extent_merge(struct bch_fs *, struct bkey_s, struct bkey_s_c); #define bch2_bkey_ops_extent ((struct bkey_ops) { \ - .key_invalid = bch2_bkey_ptrs_invalid, \ + .key_validate = bch2_bkey_ptrs_validate, \ .val_to_text = bch2_bkey_ptrs_to_text, \ .swab = bch2_ptr_swab, \ .key_normalize = bch2_extent_normalize, \ @@ -451,13 +451,13 @@ bool bch2_extent_merge(struct bch_fs *, struct bkey_s, struct bkey_s_c); /* KEY_TYPE_reservation: */ -int bch2_reservation_invalid(struct bch_fs *, struct bkey_s_c, - enum bch_validate_flags, struct printbuf *); +int bch2_reservation_validate(struct bch_fs *, struct bkey_s_c, + enum bch_validate_flags); void bch2_reservation_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c); bool bch2_reservation_merge(struct bch_fs *, struct bkey_s, struct bkey_s_c); #define bch2_bkey_ops_reservation ((struct bkey_ops) { \ - .key_invalid = bch2_reservation_invalid, \ + .key_validate = bch2_reservation_validate, \ .val_to_text = bch2_reservation_to_text, \ .key_merge = bch2_reservation_merge, \ .trigger = bch2_trigger_reservation, \ @@ -683,8 +683,8 @@ bool bch2_extent_normalize(struct bch_fs *, struct bkey_s); void bch2_extent_ptr_to_text(struct printbuf *out, struct bch_fs *, const struct bch_extent_ptr *); void bch2_bkey_ptrs_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c); -int bch2_bkey_ptrs_invalid(struct bch_fs *, struct bkey_s_c, - enum bch_validate_flags, struct printbuf *); +int bch2_bkey_ptrs_validate(struct bch_fs *, struct bkey_s_c, + enum bch_validate_flags); void bch2_ptr_swab(struct bkey_s); diff --git a/fs/bcachefs/fs.c b/fs/bcachefs/fs.c index 3a5f49affa0a96..94c392abef65cd 100644 --- a/fs/bcachefs/fs.c +++ b/fs/bcachefs/fs.c @@ -193,7 +193,7 @@ static struct bch_inode_info *bch2_inode_insert(struct bch_fs *c, struct bch_ino * only insert fully created inodes in the inode hash table. But * discard_new_inode() expects it to be set... */ - inode->v.i_flags |= I_NEW; + inode->v.i_state |= I_NEW; /* * We don't want bch2_evict_inode() to delete the inode on disk, * we just raced and had another inode in cache. Normally new @@ -1199,7 +1199,7 @@ static const struct inode_operations bch_file_inode_operations = { .fiemap = bch2_fiemap, .listxattr = bch2_xattr_list, #ifdef CONFIG_BCACHEFS_POSIX_ACL - .get_acl = bch2_get_acl, + .get_inode_acl = bch2_get_acl, .set_acl = bch2_set_acl, #endif }; @@ -1219,7 +1219,7 @@ static const struct inode_operations bch_dir_inode_operations = { .tmpfile = bch2_tmpfile, .listxattr = bch2_xattr_list, #ifdef CONFIG_BCACHEFS_POSIX_ACL - .get_acl = bch2_get_acl, + .get_inode_acl = bch2_get_acl, .set_acl = bch2_set_acl, #endif }; @@ -1241,7 +1241,7 @@ static const struct inode_operations bch_symlink_inode_operations = { .setattr = bch2_setattr, .listxattr = bch2_xattr_list, #ifdef CONFIG_BCACHEFS_POSIX_ACL - .get_acl = bch2_get_acl, + .get_inode_acl = bch2_get_acl, .set_acl = bch2_set_acl, #endif }; @@ -1251,7 +1251,7 @@ static const struct inode_operations bch_special_inode_operations = { .setattr = bch2_setattr, .listxattr = bch2_xattr_list, #ifdef CONFIG_BCACHEFS_POSIX_ACL - .get_acl = bch2_get_acl, + .get_inode_acl = bch2_get_acl, .set_acl = bch2_set_acl, #endif }; diff --git a/fs/bcachefs/inode.c b/fs/bcachefs/inode.c index 1e20020eadd1f5..2be6be33afa3e0 100644 --- a/fs/bcachefs/inode.c +++ b/fs/bcachefs/inode.c @@ -434,100 +434,98 @@ struct bkey_i *bch2_inode_to_v3(struct btree_trans *trans, struct bkey_i *k) return &inode_p->inode.k_i; } -static int __bch2_inode_invalid(struct bch_fs *c, struct bkey_s_c k, struct printbuf *err) +static int __bch2_inode_validate(struct bch_fs *c, struct bkey_s_c k, + enum bch_validate_flags flags) { struct bch_inode_unpacked unpacked; int ret = 0; - bkey_fsck_err_on(k.k->p.inode, c, err, - inode_pos_inode_nonzero, + bkey_fsck_err_on(k.k->p.inode, + c, inode_pos_inode_nonzero, "nonzero k.p.inode"); - bkey_fsck_err_on(k.k->p.offset < BLOCKDEV_INODE_MAX, c, err, - inode_pos_blockdev_range, + bkey_fsck_err_on(k.k->p.offset < BLOCKDEV_INODE_MAX, + c, inode_pos_blockdev_range, "fs inode in blockdev range"); - bkey_fsck_err_on(bch2_inode_unpack(k, &unpacked), c, err, - inode_unpack_error, + bkey_fsck_err_on(bch2_inode_unpack(k, &unpacked), + c, inode_unpack_error, "invalid variable length fields"); - bkey_fsck_err_on(unpacked.bi_data_checksum >= BCH_CSUM_OPT_NR + 1, c, err, - inode_checksum_type_invalid, + bkey_fsck_err_on(unpacked.bi_data_checksum >= BCH_CSUM_OPT_NR + 1, + c, inode_checksum_type_invalid, "invalid data checksum type (%u >= %u", unpacked.bi_data_checksum, BCH_CSUM_OPT_NR + 1); bkey_fsck_err_on(unpacked.bi_compression && - !bch2_compression_opt_valid(unpacked.bi_compression - 1), c, err, - inode_compression_type_invalid, + !bch2_compression_opt_valid(unpacked.bi_compression - 1), + c, inode_compression_type_invalid, "invalid compression opt %u", unpacked.bi_compression - 1); bkey_fsck_err_on((unpacked.bi_flags & BCH_INODE_unlinked) && - unpacked.bi_nlink != 0, c, err, - inode_unlinked_but_nlink_nonzero, + unpacked.bi_nlink != 0, + c, inode_unlinked_but_nlink_nonzero, "flagged as unlinked but bi_nlink != 0"); - bkey_fsck_err_on(unpacked.bi_subvol && !S_ISDIR(unpacked.bi_mode), c, err, - inode_subvol_root_but_not_dir, + bkey_fsck_err_on(unpacked.bi_subvol && !S_ISDIR(unpacked.bi_mode), + c, inode_subvol_root_but_not_dir, "subvolume root but not a directory"); fsck_err: return ret; } -int bch2_inode_invalid(struct bch_fs *c, struct bkey_s_c k, - enum bch_validate_flags flags, - struct printbuf *err) +int bch2_inode_validate(struct bch_fs *c, struct bkey_s_c k, + enum bch_validate_flags flags) { struct bkey_s_c_inode inode = bkey_s_c_to_inode(k); int ret = 0; - bkey_fsck_err_on(INODE_STR_HASH(inode.v) >= BCH_STR_HASH_NR, c, err, - inode_str_hash_invalid, + bkey_fsck_err_on(INODE_STR_HASH(inode.v) >= BCH_STR_HASH_NR, + c, inode_str_hash_invalid, "invalid str hash type (%llu >= %u)", INODE_STR_HASH(inode.v), BCH_STR_HASH_NR); - ret = __bch2_inode_invalid(c, k, err); + ret = __bch2_inode_validate(c, k, flags); fsck_err: return ret; } -int bch2_inode_v2_invalid(struct bch_fs *c, struct bkey_s_c k, - enum bch_validate_flags flags, - struct printbuf *err) +int bch2_inode_v2_validate(struct bch_fs *c, struct bkey_s_c k, + enum bch_validate_flags flags) { struct bkey_s_c_inode_v2 inode = bkey_s_c_to_inode_v2(k); int ret = 0; - bkey_fsck_err_on(INODEv2_STR_HASH(inode.v) >= BCH_STR_HASH_NR, c, err, - inode_str_hash_invalid, + bkey_fsck_err_on(INODEv2_STR_HASH(inode.v) >= BCH_STR_HASH_NR, + c, inode_str_hash_invalid, "invalid str hash type (%llu >= %u)", INODEv2_STR_HASH(inode.v), BCH_STR_HASH_NR); - ret = __bch2_inode_invalid(c, k, err); + ret = __bch2_inode_validate(c, k, flags); fsck_err: return ret; } -int bch2_inode_v3_invalid(struct bch_fs *c, struct bkey_s_c k, - enum bch_validate_flags flags, - struct printbuf *err) +int bch2_inode_v3_validate(struct bch_fs *c, struct bkey_s_c k, + enum bch_validate_flags flags) { struct bkey_s_c_inode_v3 inode = bkey_s_c_to_inode_v3(k); int ret = 0; bkey_fsck_err_on(INODEv3_FIELDS_START(inode.v) < INODEv3_FIELDS_START_INITIAL || - INODEv3_FIELDS_START(inode.v) > bkey_val_u64s(inode.k), c, err, - inode_v3_fields_start_bad, + INODEv3_FIELDS_START(inode.v) > bkey_val_u64s(inode.k), + c, inode_v3_fields_start_bad, "invalid fields_start (got %llu, min %u max %zu)", INODEv3_FIELDS_START(inode.v), INODEv3_FIELDS_START_INITIAL, bkey_val_u64s(inode.k)); - bkey_fsck_err_on(INODEv3_STR_HASH(inode.v) >= BCH_STR_HASH_NR, c, err, - inode_str_hash_invalid, + bkey_fsck_err_on(INODEv3_STR_HASH(inode.v) >= BCH_STR_HASH_NR, + c, inode_str_hash_invalid, "invalid str hash type (%llu >= %u)", INODEv3_STR_HASH(inode.v), BCH_STR_HASH_NR); - ret = __bch2_inode_invalid(c, k, err); + ret = __bch2_inode_validate(c, k, flags); fsck_err: return ret; } @@ -625,14 +623,13 @@ int bch2_trigger_inode(struct btree_trans *trans, return 0; } -int bch2_inode_generation_invalid(struct bch_fs *c, struct bkey_s_c k, - enum bch_validate_flags flags, - struct printbuf *err) +int bch2_inode_generation_validate(struct bch_fs *c, struct bkey_s_c k, + enum bch_validate_flags flags) { int ret = 0; - bkey_fsck_err_on(k.k->p.inode, c, err, - inode_pos_inode_nonzero, + bkey_fsck_err_on(k.k->p.inode, + c, inode_pos_inode_nonzero, "nonzero k.p.inode"); fsck_err: return ret; diff --git a/fs/bcachefs/inode.h b/fs/bcachefs/inode.h index da0e4a7450990f..f1fcb4c58039a5 100644 --- a/fs/bcachefs/inode.h +++ b/fs/bcachefs/inode.h @@ -9,12 +9,12 @@ enum bch_validate_flags; extern const char * const bch2_inode_opts[]; -int bch2_inode_invalid(struct bch_fs *, struct bkey_s_c, - enum bch_validate_flags, struct printbuf *); -int bch2_inode_v2_invalid(struct bch_fs *, struct bkey_s_c, - enum bch_validate_flags, struct printbuf *); -int bch2_inode_v3_invalid(struct bch_fs *, struct bkey_s_c, - enum bch_validate_flags, struct printbuf *); +int bch2_inode_validate(struct bch_fs *, struct bkey_s_c, + enum bch_validate_flags); +int bch2_inode_v2_validate(struct bch_fs *, struct bkey_s_c, + enum bch_validate_flags); +int bch2_inode_v3_validate(struct bch_fs *, struct bkey_s_c, + enum bch_validate_flags); void bch2_inode_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c); int bch2_trigger_inode(struct btree_trans *, enum btree_id, unsigned, @@ -22,21 +22,21 @@ int bch2_trigger_inode(struct btree_trans *, enum btree_id, unsigned, enum btree_iter_update_trigger_flags); #define bch2_bkey_ops_inode ((struct bkey_ops) { \ - .key_invalid = bch2_inode_invalid, \ + .key_validate = bch2_inode_validate, \ .val_to_text = bch2_inode_to_text, \ .trigger = bch2_trigger_inode, \ .min_val_size = 16, \ }) #define bch2_bkey_ops_inode_v2 ((struct bkey_ops) { \ - .key_invalid = bch2_inode_v2_invalid, \ + .key_validate = bch2_inode_v2_validate, \ .val_to_text = bch2_inode_to_text, \ .trigger = bch2_trigger_inode, \ .min_val_size = 32, \ }) #define bch2_bkey_ops_inode_v3 ((struct bkey_ops) { \ - .key_invalid = bch2_inode_v3_invalid, \ + .key_validate = bch2_inode_v3_validate, \ .val_to_text = bch2_inode_to_text, \ .trigger = bch2_trigger_inode, \ .min_val_size = 48, \ @@ -49,12 +49,12 @@ static inline bool bkey_is_inode(const struct bkey *k) k->type == KEY_TYPE_inode_v3; } -int bch2_inode_generation_invalid(struct bch_fs *, struct bkey_s_c, - enum bch_validate_flags, struct printbuf *); +int bch2_inode_generation_validate(struct bch_fs *, struct bkey_s_c, + enum bch_validate_flags); void bch2_inode_generation_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c); #define bch2_bkey_ops_inode_generation ((struct bkey_ops) { \ - .key_invalid = bch2_inode_generation_invalid, \ + .key_validate = bch2_inode_generation_validate, \ .val_to_text = bch2_inode_generation_to_text, \ .min_val_size = 8, \ }) diff --git a/fs/bcachefs/io_misc.c b/fs/bcachefs/io_misc.c index 2cf6297756f8e1..177ed331c00b1d 100644 --- a/fs/bcachefs/io_misc.c +++ b/fs/bcachefs/io_misc.c @@ -126,11 +126,7 @@ int bch2_extent_fallocate(struct btree_trans *trans, if (closure_nr_remaining(&cl) != 1) { bch2_trans_unlock_long(trans); - - if (closure_sync_timeout(&cl, HZ * 10)) { - bch2_print_allocator_stuck(c); - closure_sync(&cl); - } + bch2_wait_on_allocator(c, &cl); } return ret; diff --git a/fs/bcachefs/io_read.c b/fs/bcachefs/io_read.c index 4531c9ab3e1267..7ee3b75480df30 100644 --- a/fs/bcachefs/io_read.c +++ b/fs/bcachefs/io_read.c @@ -406,6 +406,7 @@ static void bch2_read_retry_nodecode(struct bch_fs *c, struct bch_read_bio *rbio bch2_trans_iter_init(trans, &iter, rbio->data_btree, rbio->read_pos, BTREE_ITER_slots); retry: + bch2_trans_begin(trans); rbio->bio.bi_status = 0; k = bch2_btree_iter_peek_slot(&iter); diff --git a/fs/bcachefs/io_write.c b/fs/bcachefs/io_write.c index d31c8d006d9791..1d4761d150023a 100644 --- a/fs/bcachefs/io_write.c +++ b/fs/bcachefs/io_write.c @@ -1503,10 +1503,7 @@ static void __bch2_write(struct bch_write_op *op) if ((op->flags & BCH_WRITE_SYNC) || (!(op->flags & BCH_WRITE_SUBMITTED) && !(op->flags & BCH_WRITE_IN_WORKER))) { - if (closure_sync_timeout(&op->cl, HZ * 10)) { - bch2_print_allocator_stuck(c); - closure_sync(&op->cl); - } + bch2_wait_on_allocator(c, &op->cl); __bch2_write_index(op); diff --git a/fs/bcachefs/journal_io.c b/fs/bcachefs/journal_io.c index 7a833a3f1c63a1..7664b68e6a15ee 100644 --- a/fs/bcachefs/journal_io.c +++ b/fs/bcachefs/journal_io.c @@ -332,7 +332,6 @@ static int journal_validate_key(struct bch_fs *c, { int write = flags & BCH_VALIDATE_write; void *next = vstruct_next(entry); - struct printbuf buf = PRINTBUF; int ret = 0; if (journal_entry_err_on(!k->k.u64s, @@ -368,34 +367,21 @@ static int journal_validate_key(struct bch_fs *c, bch2_bkey_compat(level, btree_id, version, big_endian, write, NULL, bkey_to_packed(k)); - if (bch2_bkey_invalid(c, bkey_i_to_s_c(k), - __btree_node_type(level, btree_id), write, &buf)) { - printbuf_reset(&buf); - journal_entry_err_msg(&buf, version, jset, entry); - prt_newline(&buf); - printbuf_indent_add(&buf, 2); - - bch2_bkey_val_to_text(&buf, c, bkey_i_to_s_c(k)); - prt_newline(&buf); - bch2_bkey_invalid(c, bkey_i_to_s_c(k), - __btree_node_type(level, btree_id), write, &buf); - - mustfix_fsck_err(c, journal_entry_bkey_invalid, - "%s", buf.buf); - + ret = bch2_bkey_validate(c, bkey_i_to_s_c(k), + __btree_node_type(level, btree_id), write); + if (ret == -BCH_ERR_fsck_delete_bkey) { le16_add_cpu(&entry->u64s, -((u16) k->k.u64s)); memmove(k, bkey_next(k), next - (void *) bkey_next(k)); journal_entry_null_range(vstruct_next(entry), next); - - printbuf_exit(&buf); return FSCK_DELETED_KEY; } + if (ret) + goto fsck_err; if (write) bch2_bkey_compat(level, btree_id, version, big_endian, write, NULL, bkey_to_packed(k)); fsck_err: - printbuf_exit(&buf); return ret; } diff --git a/fs/bcachefs/lru.c b/fs/bcachefs/lru.c index 83b1586cb3710b..96f2f4f8c39787 100644 --- a/fs/bcachefs/lru.c +++ b/fs/bcachefs/lru.c @@ -10,14 +10,13 @@ #include "recovery.h" /* KEY_TYPE_lru is obsolete: */ -int bch2_lru_invalid(struct bch_fs *c, struct bkey_s_c k, - enum bch_validate_flags flags, - struct printbuf *err) +int bch2_lru_validate(struct bch_fs *c, struct bkey_s_c k, + enum bch_validate_flags flags) { int ret = 0; - bkey_fsck_err_on(!lru_pos_time(k.k->p), c, err, - lru_entry_at_time_0, + bkey_fsck_err_on(!lru_pos_time(k.k->p), + c, lru_entry_at_time_0, "lru entry at time=0"); fsck_err: return ret; diff --git a/fs/bcachefs/lru.h b/fs/bcachefs/lru.h index 5bd8974a7f11e5..e6a7d8241bb807 100644 --- a/fs/bcachefs/lru.h +++ b/fs/bcachefs/lru.h @@ -33,14 +33,13 @@ static inline enum bch_lru_type lru_type(struct bkey_s_c l) return BCH_LRU_read; } -int bch2_lru_invalid(struct bch_fs *, struct bkey_s_c, - enum bch_validate_flags, struct printbuf *); +int bch2_lru_validate(struct bch_fs *, struct bkey_s_c, enum bch_validate_flags); void bch2_lru_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c); void bch2_lru_pos_to_text(struct printbuf *, struct bpos); #define bch2_bkey_ops_lru ((struct bkey_ops) { \ - .key_invalid = bch2_lru_invalid, \ + .key_validate = bch2_lru_validate, \ .val_to_text = bch2_lru_to_text, \ .min_val_size = 8, \ }) diff --git a/fs/bcachefs/opts.h b/fs/bcachefs/opts.h index 60b93018501f98..cda1725702eaf7 100644 --- a/fs/bcachefs/opts.h +++ b/fs/bcachefs/opts.h @@ -391,6 +391,11 @@ enum fsck_err_opts { OPT_BOOL(), \ BCH_SB_JOURNAL_TRANSACTION_NAMES, true, \ NULL, "Log transaction function names in journal") \ + x(allocator_stuck_timeout, u16, \ + OPT_FS|OPT_FORMAT|OPT_MOUNT|OPT_RUNTIME, \ + OPT_UINT(0, U16_MAX), \ + BCH_SB_ALLOCATOR_STUCK_TIMEOUT, 30, \ + NULL, "Default timeout in seconds for stuck allocator messages")\ x(noexcl, u8, \ OPT_FS|OPT_MOUNT, \ OPT_BOOL(), \ diff --git a/fs/bcachefs/quota.c b/fs/bcachefs/quota.c index a0cca8b70e0ae1..c32a05e252e2ab 100644 --- a/fs/bcachefs/quota.c +++ b/fs/bcachefs/quota.c @@ -59,13 +59,13 @@ const struct bch_sb_field_ops bch_sb_field_ops_quota = { .to_text = bch2_sb_quota_to_text, }; -int bch2_quota_invalid(struct bch_fs *c, struct bkey_s_c k, - enum bch_validate_flags flags, struct printbuf *err) +int bch2_quota_validate(struct bch_fs *c, struct bkey_s_c k, + enum bch_validate_flags flags) { int ret = 0; - bkey_fsck_err_on(k.k->p.inode >= QTYP_NR, c, err, - quota_type_invalid, + bkey_fsck_err_on(k.k->p.inode >= QTYP_NR, + c, quota_type_invalid, "invalid quota type (%llu >= %u)", k.k->p.inode, QTYP_NR); fsck_err: diff --git a/fs/bcachefs/quota.h b/fs/bcachefs/quota.h index 02d37a332218a8..a62abcc5332ad3 100644 --- a/fs/bcachefs/quota.h +++ b/fs/bcachefs/quota.h @@ -8,12 +8,11 @@ enum bch_validate_flags; extern const struct bch_sb_field_ops bch_sb_field_ops_quota; -int bch2_quota_invalid(struct bch_fs *, struct bkey_s_c, - enum bch_validate_flags, struct printbuf *); +int bch2_quota_validate(struct bch_fs *, struct bkey_s_c, enum bch_validate_flags); void bch2_quota_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c); #define bch2_bkey_ops_quota ((struct bkey_ops) { \ - .key_invalid = bch2_quota_invalid, \ + .key_validate = bch2_quota_validate, \ .val_to_text = bch2_quota_to_text, \ .min_val_size = 32, \ }) diff --git a/fs/bcachefs/reflink.c b/fs/bcachefs/reflink.c index 5f92715e1525a2..e59c0abb47723b 100644 --- a/fs/bcachefs/reflink.c +++ b/fs/bcachefs/reflink.c @@ -29,15 +29,14 @@ static inline unsigned bkey_type_to_indirect(const struct bkey *k) /* reflink pointers */ -int bch2_reflink_p_invalid(struct bch_fs *c, struct bkey_s_c k, - enum bch_validate_flags flags, - struct printbuf *err) +int bch2_reflink_p_validate(struct bch_fs *c, struct bkey_s_c k, + enum bch_validate_flags flags) { struct bkey_s_c_reflink_p p = bkey_s_c_to_reflink_p(k); int ret = 0; bkey_fsck_err_on(le64_to_cpu(p.v->idx) < le32_to_cpu(p.v->front_pad), - c, err, reflink_p_front_pad_bad, + c, reflink_p_front_pad_bad, "idx < front_pad (%llu < %u)", le64_to_cpu(p.v->idx), le32_to_cpu(p.v->front_pad)); fsck_err: @@ -256,11 +255,10 @@ int bch2_trigger_reflink_p(struct btree_trans *trans, /* indirect extents */ -int bch2_reflink_v_invalid(struct bch_fs *c, struct bkey_s_c k, - enum bch_validate_flags flags, - struct printbuf *err) +int bch2_reflink_v_validate(struct bch_fs *c, struct bkey_s_c k, + enum bch_validate_flags flags) { - return bch2_bkey_ptrs_invalid(c, k, flags, err); + return bch2_bkey_ptrs_validate(c, k, flags); } void bch2_reflink_v_to_text(struct printbuf *out, struct bch_fs *c, @@ -311,9 +309,8 @@ int bch2_trigger_reflink_v(struct btree_trans *trans, /* indirect inline data */ -int bch2_indirect_inline_data_invalid(struct bch_fs *c, struct bkey_s_c k, - enum bch_validate_flags flags, - struct printbuf *err) +int bch2_indirect_inline_data_validate(struct bch_fs *c, struct bkey_s_c k, + enum bch_validate_flags flags) { return 0; } diff --git a/fs/bcachefs/reflink.h b/fs/bcachefs/reflink.h index e894f3a2c67ac6..51afe11d8ed65b 100644 --- a/fs/bcachefs/reflink.h +++ b/fs/bcachefs/reflink.h @@ -4,41 +4,37 @@ enum bch_validate_flags; -int bch2_reflink_p_invalid(struct bch_fs *, struct bkey_s_c, - enum bch_validate_flags, struct printbuf *); -void bch2_reflink_p_to_text(struct printbuf *, struct bch_fs *, - struct bkey_s_c); +int bch2_reflink_p_validate(struct bch_fs *, struct bkey_s_c, enum bch_validate_flags); +void bch2_reflink_p_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c); bool bch2_reflink_p_merge(struct bch_fs *, struct bkey_s, struct bkey_s_c); int bch2_trigger_reflink_p(struct btree_trans *, enum btree_id, unsigned, struct bkey_s_c, struct bkey_s, enum btree_iter_update_trigger_flags); #define bch2_bkey_ops_reflink_p ((struct bkey_ops) { \ - .key_invalid = bch2_reflink_p_invalid, \ + .key_validate = bch2_reflink_p_validate, \ .val_to_text = bch2_reflink_p_to_text, \ .key_merge = bch2_reflink_p_merge, \ .trigger = bch2_trigger_reflink_p, \ .min_val_size = 16, \ }) -int bch2_reflink_v_invalid(struct bch_fs *, struct bkey_s_c, - enum bch_validate_flags, struct printbuf *); -void bch2_reflink_v_to_text(struct printbuf *, struct bch_fs *, - struct bkey_s_c); +int bch2_reflink_v_validate(struct bch_fs *, struct bkey_s_c, enum bch_validate_flags); +void bch2_reflink_v_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c); int bch2_trigger_reflink_v(struct btree_trans *, enum btree_id, unsigned, struct bkey_s_c, struct bkey_s, enum btree_iter_update_trigger_flags); #define bch2_bkey_ops_reflink_v ((struct bkey_ops) { \ - .key_invalid = bch2_reflink_v_invalid, \ + .key_validate = bch2_reflink_v_validate, \ .val_to_text = bch2_reflink_v_to_text, \ .swab = bch2_ptr_swab, \ .trigger = bch2_trigger_reflink_v, \ .min_val_size = 8, \ }) -int bch2_indirect_inline_data_invalid(struct bch_fs *, struct bkey_s_c, - enum bch_validate_flags, struct printbuf *); +int bch2_indirect_inline_data_validate(struct bch_fs *, struct bkey_s_c, + enum bch_validate_flags); void bch2_indirect_inline_data_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c); int bch2_trigger_indirect_inline_data(struct btree_trans *, @@ -47,7 +43,7 @@ int bch2_trigger_indirect_inline_data(struct btree_trans *, enum btree_iter_update_trigger_flags); #define bch2_bkey_ops_indirect_inline_data ((struct bkey_ops) { \ - .key_invalid = bch2_indirect_inline_data_invalid, \ + .key_validate = bch2_indirect_inline_data_validate, \ .val_to_text = bch2_indirect_inline_data_to_text, \ .trigger = bch2_trigger_indirect_inline_data, \ .min_val_size = 8, \ diff --git a/fs/bcachefs/replicas.c b/fs/bcachefs/replicas.c index 10c96cb2047ae1..1223b710755dac 100644 --- a/fs/bcachefs/replicas.c +++ b/fs/bcachefs/replicas.c @@ -24,7 +24,6 @@ static int bch2_memcmp(const void *l, const void *r, const void *priv) static void verify_replicas_entry(struct bch_replicas_entry_v1 *e) { #ifdef CONFIG_BCACHEFS_DEBUG - BUG_ON(e->data_type >= BCH_DATA_NR); BUG_ON(!e->nr_devs); BUG_ON(e->nr_required > 1 && e->nr_required >= e->nr_devs); diff --git a/fs/bcachefs/sb-downgrade.c b/fs/bcachefs/sb-downgrade.c index dfbbd33c8731b6..650a1f77ca4036 100644 --- a/fs/bcachefs/sb-downgrade.c +++ b/fs/bcachefs/sb-downgrade.c @@ -61,6 +61,20 @@ BCH_FSCK_ERR_dev_usage_buckets_wrong, \ BCH_FSCK_ERR_dev_usage_sectors_wrong, \ BCH_FSCK_ERR_dev_usage_fragmented_wrong, \ + BCH_FSCK_ERR_accounting_mismatch) \ + x(disk_accounting_v3, \ + BIT_ULL(BCH_RECOVERY_PASS_check_allocations), \ + BCH_FSCK_ERR_bkey_version_in_future, \ + BCH_FSCK_ERR_dev_usage_buckets_wrong, \ + BCH_FSCK_ERR_dev_usage_sectors_wrong, \ + BCH_FSCK_ERR_dev_usage_fragmented_wrong, \ + BCH_FSCK_ERR_accounting_mismatch, \ + BCH_FSCK_ERR_accounting_key_replicas_nr_devs_0, \ + BCH_FSCK_ERR_accounting_key_replicas_nr_required_bad, \ + BCH_FSCK_ERR_accounting_key_replicas_devs_unsorted, \ + BCH_FSCK_ERR_accounting_key_junk_at_end) \ + x(disk_accounting_inum, \ + BIT_ULL(BCH_RECOVERY_PASS_check_allocations), \ BCH_FSCK_ERR_accounting_mismatch) #define DOWNGRADE_TABLE() \ @@ -79,6 +93,21 @@ BCH_FSCK_ERR_fs_usage_nr_inodes_wrong, \ BCH_FSCK_ERR_fs_usage_persistent_reserved_wrong, \ BCH_FSCK_ERR_fs_usage_replicas_wrong, \ + BCH_FSCK_ERR_bkey_version_in_future) \ + x(disk_accounting_v3, \ + BIT_ULL(BCH_RECOVERY_PASS_check_allocations), \ + BCH_FSCK_ERR_dev_usage_buckets_wrong, \ + BCH_FSCK_ERR_dev_usage_sectors_wrong, \ + BCH_FSCK_ERR_dev_usage_fragmented_wrong, \ + BCH_FSCK_ERR_fs_usage_hidden_wrong, \ + BCH_FSCK_ERR_fs_usage_btree_wrong, \ + BCH_FSCK_ERR_fs_usage_data_wrong, \ + BCH_FSCK_ERR_fs_usage_cached_wrong, \ + BCH_FSCK_ERR_fs_usage_reserved_wrong, \ + BCH_FSCK_ERR_fs_usage_nr_inodes_wrong, \ + BCH_FSCK_ERR_fs_usage_persistent_reserved_wrong, \ + BCH_FSCK_ERR_fs_usage_replicas_wrong, \ + BCH_FSCK_ERR_accounting_replicas_not_marked, \ BCH_FSCK_ERR_bkey_version_in_future) struct upgrade_downgrade_entry { diff --git a/fs/bcachefs/sb-errors_format.h b/fs/bcachefs/sb-errors_format.h index d1b2f2aa397a71..d3a498617303e6 100644 --- a/fs/bcachefs/sb-errors_format.h +++ b/fs/bcachefs/sb-errors_format.h @@ -287,7 +287,11 @@ enum bch_fsck_flags { x(accounting_replicas_not_marked, 273, 0) \ x(invalid_btree_id, 274, 0) \ x(alloc_key_io_time_bad, 275, 0) \ - x(alloc_key_fragmentation_lru_wrong, 276, FSCK_AUTOFIX) + x(alloc_key_fragmentation_lru_wrong, 276, FSCK_AUTOFIX) \ + x(accounting_key_junk_at_end, 277, 0) \ + x(accounting_key_replicas_nr_devs_0, 278, 0) \ + x(accounting_key_replicas_nr_required_bad, 279, 0) \ + x(accounting_key_replicas_devs_unsorted, 280, 0) \ enum bch_sb_error_id { #define x(t, n, ...) BCH_FSCK_ERR_##t = n, diff --git a/fs/bcachefs/snapshot.c b/fs/bcachefs/snapshot.c index 96744b1a76f5be..8b18a9b483a4df 100644 --- a/fs/bcachefs/snapshot.c +++ b/fs/bcachefs/snapshot.c @@ -31,15 +31,14 @@ void bch2_snapshot_tree_to_text(struct printbuf *out, struct bch_fs *c, le32_to_cpu(t.v->root_snapshot)); } -int bch2_snapshot_tree_invalid(struct bch_fs *c, struct bkey_s_c k, - enum bch_validate_flags flags, - struct printbuf *err) +int bch2_snapshot_tree_validate(struct bch_fs *c, struct bkey_s_c k, + enum bch_validate_flags flags) { int ret = 0; bkey_fsck_err_on(bkey_gt(k.k->p, POS(0, U32_MAX)) || - bkey_lt(k.k->p, POS(0, 1)), c, err, - snapshot_tree_pos_bad, + bkey_lt(k.k->p, POS(0, 1)), + c, snapshot_tree_pos_bad, "bad pos"); fsck_err: return ret; @@ -225,55 +224,54 @@ void bch2_snapshot_to_text(struct printbuf *out, struct bch_fs *c, le32_to_cpu(s.v->skip[2])); } -int bch2_snapshot_invalid(struct bch_fs *c, struct bkey_s_c k, - enum bch_validate_flags flags, - struct printbuf *err) +int bch2_snapshot_validate(struct bch_fs *c, struct bkey_s_c k, + enum bch_validate_flags flags) { struct bkey_s_c_snapshot s; u32 i, id; int ret = 0; bkey_fsck_err_on(bkey_gt(k.k->p, POS(0, U32_MAX)) || - bkey_lt(k.k->p, POS(0, 1)), c, err, - snapshot_pos_bad, + bkey_lt(k.k->p, POS(0, 1)), + c, snapshot_pos_bad, "bad pos"); s = bkey_s_c_to_snapshot(k); id = le32_to_cpu(s.v->parent); - bkey_fsck_err_on(id && id <= k.k->p.offset, c, err, - snapshot_parent_bad, + bkey_fsck_err_on(id && id <= k.k->p.offset, + c, snapshot_parent_bad, "bad parent node (%u <= %llu)", id, k.k->p.offset); - bkey_fsck_err_on(le32_to_cpu(s.v->children[0]) < le32_to_cpu(s.v->children[1]), c, err, - snapshot_children_not_normalized, + bkey_fsck_err_on(le32_to_cpu(s.v->children[0]) < le32_to_cpu(s.v->children[1]), + c, snapshot_children_not_normalized, "children not normalized"); - bkey_fsck_err_on(s.v->children[0] && s.v->children[0] == s.v->children[1], c, err, - snapshot_child_duplicate, + bkey_fsck_err_on(s.v->children[0] && s.v->children[0] == s.v->children[1], + c, snapshot_child_duplicate, "duplicate child nodes"); for (i = 0; i < 2; i++) { id = le32_to_cpu(s.v->children[i]); - bkey_fsck_err_on(id >= k.k->p.offset, c, err, - snapshot_child_bad, + bkey_fsck_err_on(id >= k.k->p.offset, + c, snapshot_child_bad, "bad child node (%u >= %llu)", id, k.k->p.offset); } if (bkey_val_bytes(k.k) > offsetof(struct bch_snapshot, skip)) { bkey_fsck_err_on(le32_to_cpu(s.v->skip[0]) > le32_to_cpu(s.v->skip[1]) || - le32_to_cpu(s.v->skip[1]) > le32_to_cpu(s.v->skip[2]), c, err, - snapshot_skiplist_not_normalized, + le32_to_cpu(s.v->skip[1]) > le32_to_cpu(s.v->skip[2]), + c, snapshot_skiplist_not_normalized, "skiplist not normalized"); for (i = 0; i < ARRAY_SIZE(s.v->skip); i++) { id = le32_to_cpu(s.v->skip[i]); - bkey_fsck_err_on(id && id < le32_to_cpu(s.v->parent), c, err, - snapshot_skiplist_bad, + bkey_fsck_err_on(id && id < le32_to_cpu(s.v->parent), + c, snapshot_skiplist_bad, "bad skiplist node %u", id); } } diff --git a/fs/bcachefs/snapshot.h b/fs/bcachefs/snapshot.h index 31b0ee03e96288..eb5ef64221d6e1 100644 --- a/fs/bcachefs/snapshot.h +++ b/fs/bcachefs/snapshot.h @@ -5,11 +5,11 @@ enum bch_validate_flags; void bch2_snapshot_tree_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c); -int bch2_snapshot_tree_invalid(struct bch_fs *, struct bkey_s_c, - enum bch_validate_flags, struct printbuf *); +int bch2_snapshot_tree_validate(struct bch_fs *, struct bkey_s_c, + enum bch_validate_flags); #define bch2_bkey_ops_snapshot_tree ((struct bkey_ops) { \ - .key_invalid = bch2_snapshot_tree_invalid, \ + .key_validate = bch2_snapshot_tree_validate, \ .val_to_text = bch2_snapshot_tree_to_text, \ .min_val_size = 8, \ }) @@ -19,14 +19,13 @@ struct bkey_i_snapshot_tree *__bch2_snapshot_tree_create(struct btree_trans *); int bch2_snapshot_tree_lookup(struct btree_trans *, u32, struct bch_snapshot_tree *); void bch2_snapshot_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c); -int bch2_snapshot_invalid(struct bch_fs *, struct bkey_s_c, - enum bch_validate_flags, struct printbuf *); +int bch2_snapshot_validate(struct bch_fs *, struct bkey_s_c, enum bch_validate_flags); int bch2_mark_snapshot(struct btree_trans *, enum btree_id, unsigned, struct bkey_s_c, struct bkey_s, enum btree_iter_update_trigger_flags); #define bch2_bkey_ops_snapshot ((struct bkey_ops) { \ - .key_invalid = bch2_snapshot_invalid, \ + .key_validate = bch2_snapshot_validate, \ .val_to_text = bch2_snapshot_to_text, \ .trigger = bch2_mark_snapshot, \ .min_val_size = 24, \ diff --git a/fs/bcachefs/subvolume.c b/fs/bcachefs/subvolume.c index f56720b558626a..dbe834cb349f4a 100644 --- a/fs/bcachefs/subvolume.c +++ b/fs/bcachefs/subvolume.c @@ -207,23 +207,23 @@ int bch2_check_subvol_children(struct bch_fs *c) /* Subvolumes: */ -int bch2_subvolume_invalid(struct bch_fs *c, struct bkey_s_c k, - enum bch_validate_flags flags, struct printbuf *err) +int bch2_subvolume_validate(struct bch_fs *c, struct bkey_s_c k, + enum bch_validate_flags flags) { struct bkey_s_c_subvolume subvol = bkey_s_c_to_subvolume(k); int ret = 0; bkey_fsck_err_on(bkey_lt(k.k->p, SUBVOL_POS_MIN) || - bkey_gt(k.k->p, SUBVOL_POS_MAX), c, err, - subvol_pos_bad, + bkey_gt(k.k->p, SUBVOL_POS_MAX), + c, subvol_pos_bad, "invalid pos"); - bkey_fsck_err_on(!subvol.v->snapshot, c, err, - subvol_snapshot_bad, + bkey_fsck_err_on(!subvol.v->snapshot, + c, subvol_snapshot_bad, "invalid snapshot"); - bkey_fsck_err_on(!subvol.v->inode, c, err, - subvol_inode_bad, + bkey_fsck_err_on(!subvol.v->inode, + c, subvol_inode_bad, "invalid inode"); fsck_err: return ret; diff --git a/fs/bcachefs/subvolume.h b/fs/bcachefs/subvolume.h index afa5e871efb252..a8299ba2cab2ce 100644 --- a/fs/bcachefs/subvolume.h +++ b/fs/bcachefs/subvolume.h @@ -10,15 +10,14 @@ enum bch_validate_flags; int bch2_check_subvols(struct bch_fs *); int bch2_check_subvol_children(struct bch_fs *); -int bch2_subvolume_invalid(struct bch_fs *, struct bkey_s_c, - enum bch_validate_flags, struct printbuf *); +int bch2_subvolume_validate(struct bch_fs *, struct bkey_s_c, enum bch_validate_flags); void bch2_subvolume_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c); int bch2_subvolume_trigger(struct btree_trans *, enum btree_id, unsigned, struct bkey_s_c, struct bkey_s, enum btree_iter_update_trigger_flags); #define bch2_bkey_ops_subvolume ((struct bkey_ops) { \ - .key_invalid = bch2_subvolume_invalid, \ + .key_validate = bch2_subvolume_validate, \ .val_to_text = bch2_subvolume_to_text, \ .trigger = bch2_subvolume_trigger, \ .min_val_size = 16, \ diff --git a/fs/bcachefs/super-io.c b/fs/bcachefs/super-io.c index 8bc81983279044..c8c2ccbdfbb589 100644 --- a/fs/bcachefs/super-io.c +++ b/fs/bcachefs/super-io.c @@ -414,6 +414,10 @@ static int bch2_sb_validate(struct bch_sb_handle *disk_sb, if (!BCH_SB_VERSION_UPGRADE_COMPLETE(sb)) SET_BCH_SB_VERSION_UPGRADE_COMPLETE(sb, le16_to_cpu(sb->version)); + + if (le16_to_cpu(sb->version) <= bcachefs_metadata_version_disk_accounting_v2 && + !BCH_SB_ALLOCATOR_STUCK_TIMEOUT(sb)) + SET_BCH_SB_ALLOCATOR_STUCK_TIMEOUT(sb, 30); } for (opt_id = 0; opt_id < bch2_opts_nr; opt_id++) { diff --git a/fs/bcachefs/super.c b/fs/bcachefs/super.c index 0455a1001fec2b..e7fa2de3501459 100644 --- a/fs/bcachefs/super.c +++ b/fs/bcachefs/super.c @@ -1193,7 +1193,6 @@ static void bch2_dev_free(struct bch_dev *ca) if (ca->kobj.state_in_sysfs) kobject_del(&ca->kobj); - kfree(ca->buckets_nouse); bch2_free_super(&ca->disk_sb); bch2_dev_allocator_background_exit(ca); bch2_dev_journal_exit(ca); diff --git a/fs/bcachefs/sysfs.c b/fs/bcachefs/sysfs.c index 1c0d1fb20276aa..f393023a3ae29a 100644 --- a/fs/bcachefs/sysfs.c +++ b/fs/bcachefs/sysfs.c @@ -367,7 +367,7 @@ SHOW(bch2_fs) bch2_stripes_heap_to_text(out, c); if (attr == &sysfs_open_buckets) - bch2_open_buckets_to_text(out, c); + bch2_open_buckets_to_text(out, c, NULL); if (attr == &sysfs_open_buckets_partial) bch2_open_buckets_partial_to_text(out, c); @@ -811,6 +811,9 @@ SHOW(bch2_dev) if (attr == &sysfs_alloc_debug) bch2_dev_alloc_debug_to_text(out, ca); + if (attr == &sysfs_open_buckets) + bch2_open_buckets_to_text(out, c, ca); + return 0; } @@ -892,6 +895,7 @@ struct attribute *bch2_dev_files[] = { /* debug: */ &sysfs_alloc_debug, + &sysfs_open_buckets, NULL }; diff --git a/fs/bcachefs/trace.c b/fs/bcachefs/trace.c index dc48b52b01b49c..dfad1d06633ddb 100644 --- a/fs/bcachefs/trace.c +++ b/fs/bcachefs/trace.c @@ -4,6 +4,7 @@ #include "buckets.h" #include "btree_cache.h" #include "btree_iter.h" +#include "btree_key_cache.h" #include "btree_locking.h" #include "btree_update_interior.h" #include "keylist.h" diff --git a/fs/bcachefs/trace.h b/fs/bcachefs/trace.h index d0e6b9deb6cb4d..c62f00322d1ed6 100644 --- a/fs/bcachefs/trace.h +++ b/fs/bcachefs/trace.h @@ -988,10 +988,33 @@ TRACE_EVENT(trans_restart_split_race, __entry->u64s_remaining) ); -DEFINE_EVENT(transaction_event, trans_blocked_journal_reclaim, +TRACE_EVENT(trans_blocked_journal_reclaim, TP_PROTO(struct btree_trans *trans, unsigned long caller_ip), - TP_ARGS(trans, caller_ip) + TP_ARGS(trans, caller_ip), + + TP_STRUCT__entry( + __array(char, trans_fn, 32 ) + __field(unsigned long, caller_ip ) + + __field(unsigned long, key_cache_nr_keys ) + __field(unsigned long, key_cache_nr_dirty ) + __field(long, must_wait ) + ), + + TP_fast_assign( + strscpy(__entry->trans_fn, trans->fn, sizeof(__entry->trans_fn)); + __entry->caller_ip = caller_ip; + __entry->key_cache_nr_keys = atomic_long_read(&trans->c->btree_key_cache.nr_keys); + __entry->key_cache_nr_dirty = atomic_long_read(&trans->c->btree_key_cache.nr_dirty); + __entry->must_wait = __bch2_btree_key_cache_must_wait(trans->c); + ), + + TP_printk("%s %pS key cache keys %lu dirty %lu must_wait %li", + __entry->trans_fn, (void *) __entry->caller_ip, + __entry->key_cache_nr_keys, + __entry->key_cache_nr_dirty, + __entry->must_wait) ); TRACE_EVENT(trans_restart_journal_preres_get, diff --git a/fs/bcachefs/xattr.c b/fs/bcachefs/xattr.c index c11bf6dacc2c76..f2b4c17a0307df 100644 --- a/fs/bcachefs/xattr.c +++ b/fs/bcachefs/xattr.c @@ -70,17 +70,16 @@ const struct bch_hash_desc bch2_xattr_hash_desc = { .cmp_bkey = xattr_cmp_bkey, }; -int bch2_xattr_invalid(struct bch_fs *c, struct bkey_s_c k, - enum bch_validate_flags flags, - struct printbuf *err) +int bch2_xattr_validate(struct bch_fs *c, struct bkey_s_c k, + enum bch_validate_flags flags) { struct bkey_s_c_xattr xattr = bkey_s_c_to_xattr(k); unsigned val_u64s = xattr_val_u64s(xattr.v->x_name_len, le16_to_cpu(xattr.v->x_val_len)); int ret = 0; - bkey_fsck_err_on(bkey_val_u64s(k.k) < val_u64s, c, err, - xattr_val_size_too_small, + bkey_fsck_err_on(bkey_val_u64s(k.k) < val_u64s, + c, xattr_val_size_too_small, "value too small (%zu < %u)", bkey_val_u64s(k.k), val_u64s); @@ -88,17 +87,17 @@ int bch2_xattr_invalid(struct bch_fs *c, struct bkey_s_c k, val_u64s = xattr_val_u64s(xattr.v->x_name_len, le16_to_cpu(xattr.v->x_val_len) + 4); - bkey_fsck_err_on(bkey_val_u64s(k.k) > val_u64s, c, err, - xattr_val_size_too_big, + bkey_fsck_err_on(bkey_val_u64s(k.k) > val_u64s, + c, xattr_val_size_too_big, "value too big (%zu > %u)", bkey_val_u64s(k.k), val_u64s); - bkey_fsck_err_on(!bch2_xattr_type_to_handler(xattr.v->x_type), c, err, - xattr_invalid_type, + bkey_fsck_err_on(!bch2_xattr_type_to_handler(xattr.v->x_type), + c, xattr_invalid_type, "invalid type (%u)", xattr.v->x_type); - bkey_fsck_err_on(memchr(xattr.v->x_name, '\0', xattr.v->x_name_len), c, err, - xattr_name_invalid_chars, + bkey_fsck_err_on(memchr(xattr.v->x_name, '\0', xattr.v->x_name_len), + c, xattr_name_invalid_chars, "xattr name has invalid characters"); fsck_err: return ret; diff --git a/fs/bcachefs/xattr.h b/fs/bcachefs/xattr.h index 1574b9eb4c8505..c188a5ad64cef6 100644 --- a/fs/bcachefs/xattr.h +++ b/fs/bcachefs/xattr.h @@ -6,12 +6,11 @@ extern const struct bch_hash_desc bch2_xattr_hash_desc; -int bch2_xattr_invalid(struct bch_fs *, struct bkey_s_c, - enum bch_validate_flags, struct printbuf *); +int bch2_xattr_validate(struct bch_fs *, struct bkey_s_c, enum bch_validate_flags); void bch2_xattr_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c); #define bch2_bkey_ops_xattr ((struct bkey_ops) { \ - .key_invalid = bch2_xattr_invalid, \ + .key_validate = bch2_xattr_validate, \ .val_to_text = bch2_xattr_to_text, \ .min_val_size = 8, \ }) diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c index c26545d71d39a3..cd6d5bbb4b9df5 100644 --- a/fs/binfmt_flat.c +++ b/fs/binfmt_flat.c @@ -72,8 +72,10 @@ #ifdef CONFIG_BINFMT_FLAT_NO_DATA_START_OFFSET #define DATA_START_OFFSET_WORDS (0) +#define MAX_SHARED_LIBS_UPDATE (0) #else #define DATA_START_OFFSET_WORDS (MAX_SHARED_LIBS) +#define MAX_SHARED_LIBS_UPDATE (MAX_SHARED_LIBS) #endif struct lib_info { @@ -880,7 +882,7 @@ static int load_flat_binary(struct linux_binprm *bprm) return res; /* Update data segment pointers for all libraries */ - for (i = 0; i < MAX_SHARED_LIBS; i++) { + for (i = 0; i < MAX_SHARED_LIBS_UPDATE; i++) { if (!libinfo.lib_list[i].loaded) continue; for (j = 0; j < MAX_SHARED_LIBS; j++) { diff --git a/fs/btrfs/block-group.c b/fs/btrfs/block-group.c index 498442d0c2163d..2e49d978f504ed 100644 --- a/fs/btrfs/block-group.c +++ b/fs/btrfs/block-group.c @@ -1223,8 +1223,8 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans, block_group->space_info->total_bytes -= block_group->length; block_group->space_info->bytes_readonly -= (block_group->length - block_group->zone_unusable); - block_group->space_info->bytes_zone_unusable -= - block_group->zone_unusable; + btrfs_space_info_update_bytes_zone_unusable(fs_info, block_group->space_info, + -block_group->zone_unusable); block_group->space_info->disk_total -= block_group->length * factor; spin_unlock(&block_group->space_info->lock); @@ -1396,7 +1396,8 @@ static int inc_block_group_ro(struct btrfs_block_group *cache, int force) if (btrfs_is_zoned(cache->fs_info)) { /* Migrate zone_unusable bytes to readonly */ sinfo->bytes_readonly += cache->zone_unusable; - sinfo->bytes_zone_unusable -= cache->zone_unusable; + btrfs_space_info_update_bytes_zone_unusable(cache->fs_info, sinfo, + -cache->zone_unusable); cache->zone_unusable = 0; } cache->ro++; @@ -3056,9 +3057,11 @@ void btrfs_dec_block_group_ro(struct btrfs_block_group *cache) if (btrfs_is_zoned(cache->fs_info)) { /* Migrate zone_unusable bytes back */ cache->zone_unusable = - (cache->alloc_offset - cache->used) + + (cache->alloc_offset - cache->used - cache->pinned - + cache->reserved) + (cache->length - cache->zone_capacity); - sinfo->bytes_zone_unusable += cache->zone_unusable; + btrfs_space_info_update_bytes_zone_unusable(cache->fs_info, sinfo, + cache->zone_unusable); sinfo->bytes_readonly -= cache->zone_unusable; } num_bytes = cache->length - cache->reserved - diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index c8568b1a61c432..75fa563e4cacb8 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -459,6 +459,7 @@ struct btrfs_file_private { void *filldir_buf; u64 last_index; struct extent_state *llseek_cached_state; + bool fsync_skip_inode_lock; }; static inline u32 BTRFS_LEAF_DATA_SIZE(const struct btrfs_fs_info *info) diff --git a/fs/btrfs/delayed-ref.c b/fs/btrfs/delayed-ref.c index 2ac9296edccb7c..06a9e0542d708b 100644 --- a/fs/btrfs/delayed-ref.c +++ b/fs/btrfs/delayed-ref.c @@ -1134,6 +1134,73 @@ btrfs_find_delayed_ref_head(struct btrfs_delayed_ref_root *delayed_refs, u64 byt return find_ref_head(delayed_refs, bytenr, false); } +static int find_comp(struct btrfs_delayed_ref_node *entry, u64 root, u64 parent) +{ + int type = parent ? BTRFS_SHARED_BLOCK_REF_KEY : BTRFS_TREE_BLOCK_REF_KEY; + + if (type < entry->type) + return -1; + if (type > entry->type) + return 1; + + if (type == BTRFS_TREE_BLOCK_REF_KEY) { + if (root < entry->ref_root) + return -1; + if (root > entry->ref_root) + return 1; + } else { + if (parent < entry->parent) + return -1; + if (parent > entry->parent) + return 1; + } + return 0; +} + +/* + * Check to see if a given root/parent reference is attached to the head. This + * only checks for BTRFS_ADD_DELAYED_REF references that match, as that + * indicates the reference exists for the given root or parent. This is for + * tree blocks only. + * + * @head: the head of the bytenr we're searching. + * @root: the root objectid of the reference if it is a normal reference. + * @parent: the parent if this is a shared backref. + */ +bool btrfs_find_delayed_tree_ref(struct btrfs_delayed_ref_head *head, + u64 root, u64 parent) +{ + struct rb_node *node; + bool found = false; + + lockdep_assert_held(&head->mutex); + + spin_lock(&head->lock); + node = head->ref_tree.rb_root.rb_node; + while (node) { + struct btrfs_delayed_ref_node *entry; + int ret; + + entry = rb_entry(node, struct btrfs_delayed_ref_node, ref_node); + ret = find_comp(entry, root, parent); + if (ret < 0) { + node = node->rb_left; + } else if (ret > 0) { + node = node->rb_right; + } else { + /* + * We only want to count ADD actions, as drops mean the + * ref doesn't exist. + */ + if (entry->action == BTRFS_ADD_DELAYED_REF) + found = true; + break; + } + } + spin_unlock(&head->lock); + return found; +} + void __cold btrfs_delayed_ref_exit(void) { kmem_cache_destroy(btrfs_delayed_ref_head_cachep); diff --git a/fs/btrfs/delayed-ref.h b/fs/btrfs/delayed-ref.h index ef15e998be0350..05f634eb472d84 100644 --- a/fs/btrfs/delayed-ref.h +++ b/fs/btrfs/delayed-ref.h @@ -389,6 +389,8 @@ void btrfs_dec_delayed_refs_rsv_bg_updates(struct btrfs_fs_info *fs_info); int btrfs_delayed_refs_rsv_refill(struct btrfs_fs_info *fs_info, enum btrfs_reserve_flush_enum flush); bool btrfs_check_space_for_delayed_refs(struct btrfs_fs_info *fs_info); +bool btrfs_find_delayed_tree_ref(struct btrfs_delayed_ref_head *head, + u64 root, u64 parent); static inline u64 btrfs_delayed_ref_owner(struct btrfs_delayed_ref_node *node) { diff --git a/fs/btrfs/direct-io.c b/fs/btrfs/direct-io.c index f9fb2db6a1e4ad..67adbe9d294aec 100644 --- a/fs/btrfs/direct-io.c +++ b/fs/btrfs/direct-io.c @@ -856,21 +856,37 @@ ssize_t btrfs_direct_write(struct kiocb *iocb, struct iov_iter *from) * So here we disable page faults in the iov_iter and then retry if we * got -EFAULT, faulting in the pages before the retry. */ +again: from->nofault = true; dio = btrfs_dio_write(iocb, from, written); from->nofault = false; - /* - * iomap_dio_complete() will call btrfs_sync_file() if we have a dsync - * iocb, and that needs to lock the inode. So unlock it before calling - * iomap_dio_complete() to avoid a deadlock. - */ - btrfs_inode_unlock(BTRFS_I(inode), ilock_flags); - - if (IS_ERR_OR_NULL(dio)) + if (IS_ERR_OR_NULL(dio)) { ret = PTR_ERR_OR_ZERO(dio); - else + } else { + struct btrfs_file_private stack_private = { 0 }; + struct btrfs_file_private *private; + const bool have_private = (file->private_data != NULL); + + if (!have_private) + file->private_data = &stack_private; + + /* + * If we have a synchronous write, we must make sure the fsync + * triggered by the iomap_dio_complete() call below doesn't + * deadlock on the inode lock - we are already holding it and we + * can't call it after unlocking because we may need to complete + * partial writes due to the input buffer (or parts of it) not + * being already faulted in. + */ + private = file->private_data; + private->fsync_skip_inode_lock = true; ret = iomap_dio_complete(dio); + private->fsync_skip_inode_lock = false; + + if (!have_private) + file->private_data = NULL; + } /* No increment (+=) because iomap returns a cumulative value. */ if (ret > 0) @@ -897,10 +913,12 @@ ssize_t btrfs_direct_write(struct kiocb *iocb, struct iov_iter *from) } else { fault_in_iov_iter_readable(from, left); prev_left = left; - goto relock; + goto again; } } + btrfs_inode_unlock(BTRFS_I(inode), ilock_flags); + /* * If 'ret' is -ENOTBLK or we have not written all data, then it means * we must fallback to buffered IO. diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index d77498e7671c72..feec49e6f9c801 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -2793,7 +2793,8 @@ static int unpin_extent_range(struct btrfs_fs_info *fs_info, readonly = true; } else if (btrfs_is_zoned(fs_info)) { /* Need reset before reusing in a zoned block group */ - space_info->bytes_zone_unusable += len; + btrfs_space_info_update_bytes_zone_unusable(fs_info, space_info, + len); readonly = true; } spin_unlock(&cache->lock); @@ -5471,23 +5472,62 @@ static int check_ref_exists(struct btrfs_trans_handle *trans, struct btrfs_root *root, u64 bytenr, u64 parent, int level) { + struct btrfs_delayed_ref_root *delayed_refs; + struct btrfs_delayed_ref_head *head; struct btrfs_path *path; struct btrfs_extent_inline_ref *iref; int ret; + bool exists = false; path = btrfs_alloc_path(); if (!path) return -ENOMEM; - +again: ret = lookup_extent_backref(trans, path, &iref, bytenr, root->fs_info->nodesize, parent, btrfs_root_id(root), level, 0); + if (ret != -ENOENT) { + /* + * If we get 0 then we found our reference, return 1, else + * return the error if it's not -ENOENT; + */ + btrfs_free_path(path); + return (ret < 0 ) ? ret : 1; + } + + /* + * We could have a delayed ref with this reference, so look it up while + * we're holding the path open to make sure we don't race with the + * delayed ref running. + */ + delayed_refs = &trans->transaction->delayed_refs; + spin_lock(&delayed_refs->lock); + head = btrfs_find_delayed_ref_head(delayed_refs, bytenr); + if (!head) + goto out; + if (!mutex_trylock(&head->mutex)) { + /* + * We're contended, means that the delayed ref is running, get a + * reference and wait for the ref head to be complete and then + * try again. + */ + refcount_inc(&head->refs); + spin_unlock(&delayed_refs->lock); + + btrfs_release_path(path); + + mutex_lock(&head->mutex); + mutex_unlock(&head->mutex); + btrfs_put_delayed_ref_head(head); + goto again; + } + + exists = btrfs_find_delayed_tree_ref(head, root->root_key.objectid, parent); + mutex_unlock(&head->mutex); +out: + spin_unlock(&delayed_refs->lock); btrfs_free_path(path); - if (ret == -ENOENT) - return 0; - if (ret < 0) - return ret; - return 1; + return exists ? 1 : 0; } /* diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index aa7f8148cd0d06..c73cd4f89015f6 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -1496,6 +1496,13 @@ static noinline_for_stack int __extent_writepage_io(struct btrfs_inode *inode, free_extent_map(em); em = NULL; + /* + * Although the PageDirty bit might be cleared before entering + * this function, subpage dirty bit is not cleared. + * So clear subpage dirty bit here so next time we won't submit + * page for range already written to disk. + */ + btrfs_folio_clear_dirty(fs_info, page_folio(page), cur, iosize); btrfs_set_range_writeback(inode, cur, cur + iosize - 1); if (!PageWriteback(page)) { btrfs_err(inode->root->fs_info, @@ -1503,13 +1510,6 @@ static noinline_for_stack int __extent_writepage_io(struct btrfs_inode *inode, page->index, cur, end); } - /* - * Although the PageDirty bit is cleared before entering this - * function, subpage dirty bit is not cleared. - * So clear subpage dirty bit here so next time we won't submit - * page for range already written to disk. - */ - btrfs_folio_clear_dirty(fs_info, page_folio(page), cur, iosize); submit_extent_page(bio_ctrl, disk_bytenr, page, iosize, cur - page_offset(page)); diff --git a/fs/btrfs/extent_map.c b/fs/btrfs/extent_map.c index 81558f90ee80fa..10ac5f657e3889 100644 --- a/fs/btrfs/extent_map.c +++ b/fs/btrfs/extent_map.c @@ -664,7 +664,7 @@ static noinline int merge_extent_mapping(struct btrfs_inode *inode, start_diff = start - em->start; em->start = start; em->len = end - start; - if (em->disk_bytenr < EXTENT_MAP_LAST_BYTE && !extent_map_is_compressed(em)) + if (em->disk_bytenr < EXTENT_MAP_LAST_BYTE) em->offset += start_diff; return add_extent_mapping(inode, em, 0); } @@ -1147,8 +1147,7 @@ static long btrfs_scan_inode(struct btrfs_inode *inode, struct btrfs_em_shrink_c return 0; /* - * We want to be fast because we can be called from any path trying to - * allocate memory, so if the lock is busy we don't want to spend time + * We want to be fast so if the lock is busy we don't want to spend time * waiting for it - either some task is about to do IO for the inode or * we may have another task shrinking extent maps, here in this code, so * skip this inode. @@ -1191,9 +1190,7 @@ static long btrfs_scan_inode(struct btrfs_inode *inode, struct btrfs_em_shrink_c /* * Stop if we need to reschedule or there's contention on the * lock. This is to avoid slowing other tasks trying to take the - * lock and because the shrinker might be called during a memory - * allocation path and we want to avoid taking a very long time - * and slowing down all sorts of tasks. + * lock. */ if (need_resched() || rwlock_needbreak(&tree->lock)) break; @@ -1222,12 +1219,7 @@ static long btrfs_scan_root(struct btrfs_root *root, struct btrfs_em_shrink_ctx if (ctx->scanned >= ctx->nr_to_scan) break; - /* - * We may be called from memory allocation paths, so we don't - * want to take too much time and slowdown tasks. - */ - if (need_resched()) - break; + cond_resched(); inode = btrfs_find_first_inode(root, min_ino); } @@ -1285,14 +1277,12 @@ long btrfs_free_extent_maps(struct btrfs_fs_info *fs_info, long nr_to_scan) ctx.last_ino); } - /* - * We may be called from memory allocation paths, so we don't want to - * take too much time and slowdown tasks, so stop if we need reschedule. - */ - while (ctx.scanned < ctx.nr_to_scan && !need_resched()) { + while (ctx.scanned < ctx.nr_to_scan) { struct btrfs_root *root; unsigned long count; + cond_resched(); + spin_lock(&fs_info->fs_roots_radix_lock); count = radix_tree_gang_lookup(&fs_info->fs_roots_radix, (void **)&root, diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index 21381de906f607..9914419f3b7d61 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c @@ -1603,6 +1603,7 @@ static inline bool skip_inode_logging(const struct btrfs_log_ctx *ctx) */ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) { + struct btrfs_file_private *private = file->private_data; struct dentry *dentry = file_dentry(file); struct btrfs_inode *inode = BTRFS_I(d_inode(dentry)); struct btrfs_root *root = inode->root; @@ -1612,6 +1613,7 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) int ret = 0, err; u64 len; bool full_sync; + const bool skip_ilock = (private ? private->fsync_skip_inode_lock : false); trace_btrfs_sync_file(file, datasync); @@ -1639,7 +1641,10 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) if (ret) goto out; - btrfs_inode_lock(inode, BTRFS_ILOCK_MMAP); + if (skip_ilock) + down_write(&inode->i_mmap_lock); + else + btrfs_inode_lock(inode, BTRFS_ILOCK_MMAP); atomic_inc(&root->log_batch); @@ -1663,7 +1668,10 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) */ ret = start_ordered_ops(inode, start, end); if (ret) { - btrfs_inode_unlock(inode, BTRFS_ILOCK_MMAP); + if (skip_ilock) + up_write(&inode->i_mmap_lock); + else + btrfs_inode_unlock(inode, BTRFS_ILOCK_MMAP); goto out; } @@ -1788,7 +1796,10 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) * file again, but that will end up using the synchronization * inside btrfs_sync_log to keep things safe. */ - btrfs_inode_unlock(inode, BTRFS_ILOCK_MMAP); + if (skip_ilock) + up_write(&inode->i_mmap_lock); + else + btrfs_inode_unlock(inode, BTRFS_ILOCK_MMAP); if (ret == BTRFS_NO_LOG_SYNC) { ret = btrfs_end_transaction(trans); @@ -1857,7 +1868,10 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) out_release_extents: btrfs_release_log_ctx_extents(&ctx); - btrfs_inode_unlock(inode, BTRFS_ILOCK_MMAP); + if (skip_ilock) + up_write(&inode->i_mmap_lock); + else + btrfs_inode_unlock(inode, BTRFS_ILOCK_MMAP); goto out; } diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c index 3f9b7507543ad4..eaa1dbd313528c 100644 --- a/fs/btrfs/free-space-cache.c +++ b/fs/btrfs/free-space-cache.c @@ -2697,15 +2697,16 @@ static int __btrfs_add_free_space_zoned(struct btrfs_block_group *block_group, u64 offset = bytenr - block_group->start; u64 to_free, to_unusable; int bg_reclaim_threshold = 0; - bool initial = ((size == block_group->length) && (block_group->alloc_offset == 0)); + bool initial; u64 reclaimable_unusable; - WARN_ON(!initial && offset + size > block_group->zone_capacity); + spin_lock(&block_group->lock); + initial = ((size == block_group->length) && (block_group->alloc_offset == 0)); + WARN_ON(!initial && offset + size > block_group->zone_capacity); if (!initial) bg_reclaim_threshold = READ_ONCE(sinfo->bg_reclaim_threshold); - spin_lock(&ctl->tree_lock); if (!used) to_free = size; else if (initial) @@ -2718,18 +2719,19 @@ static int __btrfs_add_free_space_zoned(struct btrfs_block_group *block_group, to_free = offset + size - block_group->alloc_offset; to_unusable = size - to_free; + spin_lock(&ctl->tree_lock); ctl->free_space += to_free; + spin_unlock(&ctl->tree_lock); /* * If the block group is read-only, we should account freed space into * bytes_readonly. */ - if (!block_group->ro) + if (!block_group->ro) { block_group->zone_unusable += to_unusable; - spin_unlock(&ctl->tree_lock); + WARN_ON(block_group->zone_unusable > block_group->length); + } if (!used) { - spin_lock(&block_group->lock); block_group->alloc_offset -= size; - spin_unlock(&block_group->lock); } reclaimable_unusable = block_group->zone_unusable - @@ -2743,6 +2745,8 @@ static int __btrfs_add_free_space_zoned(struct btrfs_block_group *block_group, btrfs_mark_bg_to_reclaim(block_group); } + spin_unlock(&block_group->lock); + return 0; } diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 01eab695564727..b1b6564ab68f0c 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -714,8 +714,9 @@ static noinline int __cow_file_range_inline(struct btrfs_inode *inode, u64 offse return ret; } -static noinline int cow_file_range_inline(struct btrfs_inode *inode, u64 offset, - u64 end, +static noinline int cow_file_range_inline(struct btrfs_inode *inode, + struct page *locked_page, + u64 offset, u64 end, size_t compressed_size, int compress_type, struct folio *compressed_folio, @@ -739,7 +740,10 @@ static noinline int cow_file_range_inline(struct btrfs_inode *inode, u64 offset, return ret; } - extent_clear_unlock_delalloc(inode, offset, end, NULL, &cached, + if (ret == 0) + locked_page = NULL; + + extent_clear_unlock_delalloc(inode, offset, end, locked_page, &cached, clear_flags, PAGE_UNLOCK | PAGE_START_WRITEBACK | PAGE_END_WRITEBACK); @@ -1043,10 +1047,10 @@ static void compress_file_range(struct btrfs_work *work) * extent for the subpage case. */ if (total_in < actual_end) - ret = cow_file_range_inline(inode, start, end, 0, + ret = cow_file_range_inline(inode, NULL, start, end, 0, BTRFS_COMPRESS_NONE, NULL, false); else - ret = cow_file_range_inline(inode, start, end, total_compressed, + ret = cow_file_range_inline(inode, NULL, start, end, total_compressed, compress_type, folios[0], false); if (ret <= 0) { if (ret < 0) @@ -1359,7 +1363,7 @@ static noinline int cow_file_range(struct btrfs_inode *inode, if (!no_inline) { /* lets try to make an inline extent */ - ret = cow_file_range_inline(inode, start, end, 0, + ret = cow_file_range_inline(inode, locked_page, start, end, 0, BTRFS_COMPRESS_NONE, NULL, false); if (ret <= 0) { /* @@ -1581,6 +1585,7 @@ static noinline int cow_file_range(struct btrfs_inode *inode, locked_page, &cached, clear_bits, page_ops); + btrfs_qgroup_free_data(inode, NULL, start, cur_alloc_size, NULL); start += cur_alloc_size; } @@ -1594,6 +1599,7 @@ static noinline int cow_file_range(struct btrfs_inode *inode, clear_bits |= EXTENT_CLEAR_DATA_RESV; extent_clear_unlock_delalloc(inode, start, end, locked_page, &cached, clear_bits, page_ops); + btrfs_qgroup_free_data(inode, NULL, start, cur_alloc_size, NULL); } return ret; } @@ -2255,6 +2261,7 @@ static noinline int run_delalloc_nocow(struct btrfs_inode *inode, EXTENT_DO_ACCOUNTING, PAGE_UNLOCK | PAGE_START_WRITEBACK | PAGE_END_WRITEBACK); + btrfs_qgroup_free_data(inode, NULL, cur_offset, end - cur_offset + 1, NULL); } btrfs_free_path(path); return ret; @@ -4188,6 +4195,7 @@ static int __btrfs_unlink_inode(struct btrfs_trans_handle *trans, btrfs_i_size_write(dir, dir->vfs_inode.i_size - name->len * 2); inode_inc_iversion(&inode->vfs_inode); + inode_set_ctime_current(&inode->vfs_inode); inode_inc_iversion(&dir->vfs_inode); inode_set_mtime_to_ts(&dir->vfs_inode, inode_set_ctime_current(&dir->vfs_inode)); ret = btrfs_update_inode(trans, dir); @@ -5660,7 +5668,7 @@ struct inode *btrfs_lookup_dentry(struct inode *dir, struct dentry *dentry) struct inode *inode; struct btrfs_root *root = BTRFS_I(dir)->root; struct btrfs_root *sub_root = root; - struct btrfs_key location; + struct btrfs_key location = { 0 }; u8 di_type = 0; int ret = 0; @@ -7198,6 +7206,12 @@ static void wait_subpage_spinlock(struct page *page) spin_unlock_irq(&subpage->lock); } +static int btrfs_launder_folio(struct folio *folio) +{ + return btrfs_qgroup_free_data(folio_to_inode(folio), NULL, folio_pos(folio), + PAGE_SIZE, NULL); +} + static bool __btrfs_release_folio(struct folio *folio, gfp_t gfp_flags) { if (try_release_extent_mapping(&folio->page, gfp_flags)) { @@ -10133,6 +10147,7 @@ static const struct address_space_operations btrfs_aops = { .writepages = btrfs_writepages, .readahead = btrfs_readahead, .invalidate_folio = btrfs_invalidate_folio, + .launder_folio = btrfs_launder_folio, .release_folio = btrfs_release_folio, .migrate_folio = btrfs_migrate_folio, .dirty_folio = filemap_dirty_folio, diff --git a/fs/btrfs/print-tree.c b/fs/btrfs/print-tree.c index 32dcea662da38e..fc821aa446f02f 100644 --- a/fs/btrfs/print-tree.c +++ b/fs/btrfs/print-tree.c @@ -14,7 +14,7 @@ struct root_name_map { u64 id; - char name[16]; + const char *name; }; static const struct root_name_map root_map[] = { diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c index 14a8d710001838..0de9162ff48138 100644 --- a/fs/btrfs/scrub.c +++ b/fs/btrfs/scrub.c @@ -1648,14 +1648,20 @@ static void scrub_reset_stripe(struct scrub_stripe *stripe) } } +static u32 stripe_length(const struct scrub_stripe *stripe) +{ + ASSERT(stripe->bg); + + return min(BTRFS_STRIPE_LEN, + stripe->bg->start + stripe->bg->length - stripe->logical); +} + static void scrub_submit_extent_sector_read(struct scrub_ctx *sctx, struct scrub_stripe *stripe) { struct btrfs_fs_info *fs_info = stripe->bg->fs_info; struct btrfs_bio *bbio = NULL; - unsigned int nr_sectors = min(BTRFS_STRIPE_LEN, stripe->bg->start + - stripe->bg->length - stripe->logical) >> - fs_info->sectorsize_bits; + unsigned int nr_sectors = stripe_length(stripe) >> fs_info->sectorsize_bits; u64 stripe_len = BTRFS_STRIPE_LEN; int mirror = stripe->mirror_num; int i; @@ -1729,9 +1735,7 @@ static void scrub_submit_initial_read(struct scrub_ctx *sctx, { struct btrfs_fs_info *fs_info = sctx->fs_info; struct btrfs_bio *bbio; - unsigned int nr_sectors = min(BTRFS_STRIPE_LEN, stripe->bg->start + - stripe->bg->length - stripe->logical) >> - fs_info->sectorsize_bits; + unsigned int nr_sectors = stripe_length(stripe) >> fs_info->sectorsize_bits; int mirror = stripe->mirror_num; ASSERT(stripe->bg); @@ -1871,6 +1875,9 @@ static int flush_scrub_stripes(struct scrub_ctx *sctx) stripe = &sctx->stripes[i]; wait_scrub_stripe_io(stripe); + spin_lock(&sctx->stat_lock); + sctx->stat.last_physical = stripe->physical + stripe_length(stripe); + spin_unlock(&sctx->stat_lock); scrub_reset_stripe(stripe); } out: @@ -2139,7 +2146,9 @@ static int scrub_simple_mirror(struct scrub_ctx *sctx, cur_physical, &found_logical); if (ret > 0) { /* No more extent, just update the accounting */ + spin_lock(&sctx->stat_lock); sctx->stat.last_physical = physical + logical_length; + spin_unlock(&sctx->stat_lock); ret = 0; break; } @@ -2336,6 +2345,10 @@ static noinline_for_stack int scrub_stripe(struct scrub_ctx *sctx, stripe_logical += chunk_logical; ret = scrub_raid56_parity_stripe(sctx, scrub_dev, bg, map, stripe_logical); + spin_lock(&sctx->stat_lock); + sctx->stat.last_physical = min(physical + BTRFS_STRIPE_LEN, + physical_end); + spin_unlock(&sctx->stat_lock); if (ret) goto out; goto next; diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c index 4ca711a773efa9..619fa0b8b3f6f9 100644 --- a/fs/btrfs/send.c +++ b/fs/btrfs/send.c @@ -347,7 +347,7 @@ struct name_cache_entry { int ret; int need_later_update; int name_len; - char name[]; + char name[] __counted_by(name_len); }; /* See the comment at lru_cache.h about struct btrfs_lru_cache_entry. */ @@ -6157,25 +6157,51 @@ static int send_write_or_clone(struct send_ctx *sctx, u64 offset = key->offset; u64 end; u64 bs = sctx->send_root->fs_info->sectorsize; + struct btrfs_file_extent_item *ei; + u64 disk_byte; + u64 data_offset; + u64 num_bytes; + struct btrfs_inode_info info = { 0 }; end = min_t(u64, btrfs_file_extent_end(path), sctx->cur_inode_size); if (offset >= end) return 0; - if (clone_root && IS_ALIGNED(end, bs)) { - struct btrfs_file_extent_item *ei; - u64 disk_byte; - u64 data_offset; + num_bytes = end - offset; - ei = btrfs_item_ptr(path->nodes[0], path->slots[0], - struct btrfs_file_extent_item); - disk_byte = btrfs_file_extent_disk_bytenr(path->nodes[0], ei); - data_offset = btrfs_file_extent_offset(path->nodes[0], ei); - ret = clone_range(sctx, path, clone_root, disk_byte, - data_offset, offset, end - offset); - } else { - ret = send_extent_data(sctx, path, offset, end - offset); - } + if (!clone_root) + goto write_data; + + if (IS_ALIGNED(end, bs)) + goto clone_data; + + /* + * If the extent end is not aligned, we can clone if the extent ends at + * the i_size of the inode and the clone range ends at the i_size of the + * source inode, otherwise the clone operation fails with -EINVAL. + */ + if (end != sctx->cur_inode_size) + goto write_data; + + ret = get_inode_info(clone_root->root, clone_root->ino, &info); + if (ret < 0) + return ret; + + if (clone_root->offset + num_bytes == info.size) + goto clone_data; + +write_data: + ret = send_extent_data(sctx, path, offset, num_bytes); + sctx->cur_inode_next_write_offset = end; + return ret; + +clone_data: + ei = btrfs_item_ptr(path->nodes[0], path->slots[0], + struct btrfs_file_extent_item); + disk_byte = btrfs_file_extent_disk_bytenr(path->nodes[0], ei); + data_offset = btrfs_file_extent_offset(path->nodes[0], ei); + ret = clone_range(sctx, path, clone_root, disk_byte, data_offset, offset, + num_bytes); sctx->cur_inode_next_write_offset = end; return ret; } diff --git a/fs/btrfs/space-info.c b/fs/btrfs/space-info.c index 9ac94d3119e8dd..68e14fd486384e 100644 --- a/fs/btrfs/space-info.c +++ b/fs/btrfs/space-info.c @@ -316,7 +316,7 @@ void btrfs_add_bg_to_space_info(struct btrfs_fs_info *info, found->bytes_used += block_group->used; found->disk_used += block_group->used * factor; found->bytes_readonly += block_group->bytes_super; - found->bytes_zone_unusable += block_group->zone_unusable; + btrfs_space_info_update_bytes_zone_unusable(info, found, block_group->zone_unusable); if (block_group->length > 0) found->full = 0; btrfs_try_granting_tickets(info, found); @@ -583,8 +583,7 @@ void btrfs_dump_space_info(struct btrfs_fs_info *fs_info, spin_lock(&cache->lock); avail = cache->length - cache->used - cache->pinned - - cache->reserved - cache->delalloc_bytes - - cache->bytes_super - cache->zone_unusable; + cache->reserved - cache->bytes_super - cache->zone_unusable; btrfs_info(fs_info, "block group %llu has %llu bytes, %llu used %llu pinned %llu reserved %llu delalloc %llu super %llu zone_unusable (%llu bytes available) %s", cache->start, cache->length, cache->used, cache->pinned, diff --git a/fs/btrfs/space-info.h b/fs/btrfs/space-info.h index 4db8a0267c1606..88b44221ce9782 100644 --- a/fs/btrfs/space-info.h +++ b/fs/btrfs/space-info.h @@ -249,6 +249,7 @@ btrfs_space_info_update_##name(struct btrfs_fs_info *fs_info, \ DECLARE_SPACE_INFO_UPDATE(bytes_may_use, "space_info"); DECLARE_SPACE_INFO_UPDATE(bytes_pinned, "pinned"); +DECLARE_SPACE_INFO_UPDATE(bytes_zone_unusable, "zone_unusable"); int btrfs_init_space_info(struct btrfs_fs_info *fs_info); void btrfs_add_bg_to_space_info(struct btrfs_fs_info *info, diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 08d33cb372fbcb..98fa0f382480a2 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c @@ -28,6 +28,7 @@ #include #include #include +#include #include "messages.h" #include "delayed-inode.h" #include "ctree.h" @@ -683,8 +684,11 @@ bool btrfs_check_options(const struct btrfs_fs_info *info, ret = false; if (!test_bit(BTRFS_FS_STATE_REMOUNTING, &info->fs_state)) { - if (btrfs_raw_test_opt(*mount_opt, SPACE_CACHE)) + if (btrfs_raw_test_opt(*mount_opt, SPACE_CACHE)) { btrfs_info(info, "disk space caching is enabled"); + btrfs_warn(info, +"space cache v1 is being deprecated and will be removed in a future release, please use -o space_cache=v2"); + } if (btrfs_raw_test_opt(*mount_opt, FREE_SPACE_TREE)) btrfs_info(info, "using free-space-tree"); } @@ -2398,7 +2402,13 @@ static long btrfs_nr_cached_objects(struct super_block *sb, struct shrink_contro trace_btrfs_extent_map_shrinker_count(fs_info, nr); - return nr; + /* + * Only report the real number for DEBUG builds, as there are reports of + * serious performance degradation caused by too frequent shrinks. + */ + if (IS_ENABLED(CONFIG_BTRFS_DEBUG)) + return nr; + return 0; } static long btrfs_free_cached_objects(struct super_block *sb, struct shrink_control *sc) @@ -2406,6 +2416,15 @@ static long btrfs_free_cached_objects(struct super_block *sb, struct shrink_cont const long nr_to_scan = min_t(unsigned long, LONG_MAX, sc->nr_to_scan); struct btrfs_fs_info *fs_info = btrfs_sb(sb); + /* + * We may be called from any task trying to allocate memory and we don't + * want to slow it down with scanning and dropping extent maps. It would + * also cause heavy lock contention if many tasks concurrently enter + * here. Therefore only allow kswapd tasks to scan and drop extent maps. + */ + if (!current_is_kswapd()) + return 0; + return btrfs_free_extent_maps(fs_info, nr_to_scan); } diff --git a/fs/btrfs/tests/extent-map-tests.c b/fs/btrfs/tests/extent-map-tests.c index ebec4ab361b82a..56e61ac1cc64c8 100644 --- a/fs/btrfs/tests/extent-map-tests.c +++ b/fs/btrfs/tests/extent-map-tests.c @@ -900,6 +900,102 @@ static int test_case_7(struct btrfs_fs_info *fs_info, struct btrfs_inode *inode) return ret; } +/* + * Test a regression for compressed extent map adjustment when we attempt to + * add an extent map that is partially overlapped by another existing extent + * map. The resulting extent map offset was left unchanged despite having + * incremented its start offset. + */ +static int test_case_8(struct btrfs_fs_info *fs_info, struct btrfs_inode *inode) +{ + struct extent_map_tree *em_tree = &inode->extent_tree; + struct extent_map *em; + int ret; + int ret2; + + em = alloc_extent_map(); + if (!em) { + test_std_err(TEST_ALLOC_EXTENT_MAP); + return -ENOMEM; + } + + /* Compressed extent for the file range [120K, 128K). */ + em->start = SZ_1K * 120; + em->len = SZ_8K; + em->disk_num_bytes = SZ_4K; + em->ram_bytes = SZ_8K; + em->flags |= EXTENT_FLAG_COMPRESS_ZLIB; + write_lock(&em_tree->lock); + ret = btrfs_add_extent_mapping(inode, &em, em->start, em->len); + write_unlock(&em_tree->lock); + free_extent_map(em); + if (ret < 0) { + test_err("couldn't add extent map for range [120K, 128K)"); + goto out; + } + + em = alloc_extent_map(); + if (!em) { + test_std_err(TEST_ALLOC_EXTENT_MAP); + ret = -ENOMEM; + goto out; + } + + /* + * Compressed extent for the file range [108K, 144K), which overlaps + * with the [120K, 128K) we previously inserted. + */ + em->start = SZ_1K * 108; + em->len = SZ_1K * 36; + em->disk_num_bytes = SZ_4K; + em->ram_bytes = SZ_1K * 36; + em->flags |= EXTENT_FLAG_COMPRESS_ZLIB; + + /* + * Try to add the extent map but with a search range of [140K, 144K), + * this should succeed and adjust the extent map to the range + * [128K, 144K), with a length of 16K and an offset of 20K. + * + * This simulates a scenario where in the subvolume tree of an inode we + * have a compressed file extent item for the range [108K, 144K) and we + * have an overlapping compressed extent map for the range [120K, 128K), + * which was created by an encoded write, but its ordered extent was not + * yet completed, so the subvolume tree doesn't have yet the file extent + * item for that range - we only have the extent map in the inode's + * extent map tree. + */ + write_lock(&em_tree->lock); + ret = btrfs_add_extent_mapping(inode, &em, SZ_1K * 140, SZ_4K); + write_unlock(&em_tree->lock); + free_extent_map(em); + if (ret < 0) { + test_err("couldn't add extent map for range [108K, 144K)"); + goto out; + } + + if (em->start != SZ_128K) { + test_err("unexpected extent map start %llu (should be 128K)", em->start); + ret = -EINVAL; + goto out; + } + if (em->len != SZ_16K) { + test_err("unexpected extent map length %llu (should be 16K)", em->len); + ret = -EINVAL; + goto out; + } + if (em->offset != SZ_1K * 20) { + test_err("unexpected extent map offset %llu (should be 20K)", em->offset); + ret = -EINVAL; + goto out; + } +out: + ret2 = free_extent_map_tree(inode); + if (ret == 0) + ret = ret2; + + return ret; +} + struct rmap_test_vector { u64 raid_type; u64 physical_start; @@ -1076,6 +1172,9 @@ int btrfs_test_extent_map(void) if (ret) goto out; ret = test_case_7(fs_info, BTRFS_I(inode)); + if (ret) + goto out; + ret = test_case_8(fs_info, BTRFS_I(inode)); if (ret) goto out; diff --git a/fs/btrfs/tree-checker.c b/fs/btrfs/tree-checker.c index 6388786fd8b5d3..634d69964fe4c1 100644 --- a/fs/btrfs/tree-checker.c +++ b/fs/btrfs/tree-checker.c @@ -569,9 +569,10 @@ static int check_dir_item(struct extent_buffer *leaf, /* dir type check */ dir_type = btrfs_dir_ftype(leaf, di); - if (unlikely(dir_type >= BTRFS_FT_MAX)) { + if (unlikely(dir_type <= BTRFS_FT_UNKNOWN || + dir_type >= BTRFS_FT_MAX)) { dir_item_err(leaf, slot, - "invalid dir item type, have %u expect [0, %u)", + "invalid dir item type, have %u expect (0, %u)", dir_type, BTRFS_FT_MAX); return -EUCLEAN; } @@ -634,7 +635,7 @@ static int check_dir_item(struct extent_buffer *leaf, */ if (key->type == BTRFS_DIR_ITEM_KEY || key->type == BTRFS_XATTR_ITEM_KEY) { - char namebuf[max(BTRFS_NAME_LEN, XATTR_NAME_MAX)]; + char namebuf[MAX(BTRFS_NAME_LEN, XATTR_NAME_MAX)]; read_extent_buffer(leaf, namebuf, (unsigned long)(di + 1), name_len); @@ -1289,6 +1290,19 @@ static void extent_err(const struct extent_buffer *eb, int slot, va_end(args); } +static bool is_valid_dref_root(u64 rootid) +{ + /* + * The following tree root objectids are allowed to have a data backref: + * - subvolume trees + * - data reloc tree + * - tree root + * For v1 space cache + */ + return is_fstree(rootid) || rootid == BTRFS_DATA_RELOC_TREE_OBJECTID || + rootid == BTRFS_ROOT_TREE_OBJECTID; +} + static int check_extent_item(struct extent_buffer *leaf, struct btrfs_key *key, int slot, struct btrfs_key *prev_key) @@ -1441,6 +1455,8 @@ static int check_extent_item(struct extent_buffer *leaf, struct btrfs_extent_data_ref *dref; struct btrfs_shared_data_ref *sref; u64 seq; + u64 dref_root; + u64 dref_objectid; u64 dref_offset; u64 inline_offset; u8 inline_type; @@ -1484,11 +1500,26 @@ static int check_extent_item(struct extent_buffer *leaf, */ case BTRFS_EXTENT_DATA_REF_KEY: dref = (struct btrfs_extent_data_ref *)(&iref->offset); + dref_root = btrfs_extent_data_ref_root(leaf, dref); + dref_objectid = btrfs_extent_data_ref_objectid(leaf, dref); dref_offset = btrfs_extent_data_ref_offset(leaf, dref); seq = hash_extent_data_ref( btrfs_extent_data_ref_root(leaf, dref), btrfs_extent_data_ref_objectid(leaf, dref), btrfs_extent_data_ref_offset(leaf, dref)); + if (unlikely(!is_valid_dref_root(dref_root))) { + extent_err(leaf, slot, + "invalid data ref root value %llu", + dref_root); + return -EUCLEAN; + } + if (unlikely(dref_objectid < BTRFS_FIRST_FREE_OBJECTID || + dref_objectid > BTRFS_LAST_FREE_OBJECTID)) { + extent_err(leaf, slot, + "invalid data ref objectid value %llu", + dref_root); + return -EUCLEAN; + } if (unlikely(!IS_ALIGNED(dref_offset, fs_info->sectorsize))) { extent_err(leaf, slot, @@ -1627,6 +1658,8 @@ static int check_extent_data_ref(struct extent_buffer *leaf, return -EUCLEAN; } for (; ptr < end; ptr += sizeof(*dref)) { + u64 root; + u64 objectid; u64 offset; /* @@ -1634,7 +1667,22 @@ static int check_extent_data_ref(struct extent_buffer *leaf, * overflow from the leaf due to hash collisions. */ dref = (struct btrfs_extent_data_ref *)ptr; + root = btrfs_extent_data_ref_root(leaf, dref); + objectid = btrfs_extent_data_ref_objectid(leaf, dref); offset = btrfs_extent_data_ref_offset(leaf, dref); + if (unlikely(!is_valid_dref_root(root))) { + extent_err(leaf, slot, + "invalid extent data backref root value %llu", + root); + return -EUCLEAN; + } + if (unlikely(objectid < BTRFS_FIRST_FREE_OBJECTID || + objectid > BTRFS_LAST_FREE_OBJECTID)) { + extent_err(leaf, slot, + "invalid extent data backref objectid value %llu", + root); + return -EUCLEAN; + } if (unlikely(!IS_ALIGNED(offset, leaf->fs_info->sectorsize))) { extent_err(leaf, slot, "invalid extent data backref offset, have %llu expect aligned to %u", @@ -1716,6 +1764,72 @@ static int check_raid_stripe_extent(const struct extent_buffer *leaf, return 0; } +static int check_dev_extent_item(const struct extent_buffer *leaf, + const struct btrfs_key *key, + int slot, + struct btrfs_key *prev_key) +{ + struct btrfs_dev_extent *de; + const u32 sectorsize = leaf->fs_info->sectorsize; + + de = btrfs_item_ptr(leaf, slot, struct btrfs_dev_extent); + /* Basic fixed member checks. */ + if (unlikely(btrfs_dev_extent_chunk_tree(leaf, de) != + BTRFS_CHUNK_TREE_OBJECTID)) { + generic_err(leaf, slot, + "invalid dev extent chunk tree id, has %llu expect %llu", + btrfs_dev_extent_chunk_tree(leaf, de), + BTRFS_CHUNK_TREE_OBJECTID); + return -EUCLEAN; + } + if (unlikely(btrfs_dev_extent_chunk_objectid(leaf, de) != + BTRFS_FIRST_CHUNK_TREE_OBJECTID)) { + generic_err(leaf, slot, + "invalid dev extent chunk objectid, has %llu expect %llu", + btrfs_dev_extent_chunk_objectid(leaf, de), + BTRFS_FIRST_CHUNK_TREE_OBJECTID); + return -EUCLEAN; + } + /* Alignment check. */ + if (unlikely(!IS_ALIGNED(key->offset, sectorsize))) { + generic_err(leaf, slot, + "invalid dev extent key.offset, has %llu not aligned to %u", + key->offset, sectorsize); + return -EUCLEAN; + } + if (unlikely(!IS_ALIGNED(btrfs_dev_extent_chunk_offset(leaf, de), + sectorsize))) { + generic_err(leaf, slot, + "invalid dev extent chunk offset, has %llu not aligned to %u", + btrfs_dev_extent_chunk_objectid(leaf, de), + sectorsize); + return -EUCLEAN; + } + if (unlikely(!IS_ALIGNED(btrfs_dev_extent_length(leaf, de), + sectorsize))) { + generic_err(leaf, slot, + "invalid dev extent length, has %llu not aligned to %u", + btrfs_dev_extent_length(leaf, de), sectorsize); + return -EUCLEAN; + } + /* Overlap check with previous dev extent. */ + if (slot && prev_key->objectid == key->objectid && + prev_key->type == key->type) { + struct btrfs_dev_extent *prev_de; + u64 prev_len; + + prev_de = btrfs_item_ptr(leaf, slot - 1, struct btrfs_dev_extent); + prev_len = btrfs_dev_extent_length(leaf, prev_de); + if (unlikely(prev_key->offset + prev_len > key->offset)) { + generic_err(leaf, slot, + "dev extent overlap, prev offset %llu len %llu current offset %llu", + prev_key->objectid, prev_len, key->offset); + return -EUCLEAN; + } + } + return 0; +} + /* * Common point to switch the item-specific validation. */ @@ -1752,6 +1866,9 @@ static enum btrfs_tree_block_status check_leaf_item(struct extent_buffer *leaf, case BTRFS_DEV_ITEM_KEY: ret = check_dev_item(leaf, key, slot); break; + case BTRFS_DEV_EXTENT_KEY: + ret = check_dev_extent_item(leaf, key, slot, prev_key); + break; case BTRFS_INODE_ITEM_KEY: ret = check_inode_item(leaf, key, slot); break; diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c index 8c16bc5250ef56..c4744a02db753c 100644 --- a/fs/ceph/addr.c +++ b/fs/ceph/addr.c @@ -246,7 +246,8 @@ static void finish_netfs_read(struct ceph_osd_request *req) if (err >= 0) { if (sparse && err > 0) err = ceph_sparse_ext_map_end(op); - if (err < subreq->len) + if (err < subreq->len && + subreq->rreq->origin != NETFS_DIO_READ) __set_bit(NETFS_SREQ_CLEAR_TAIL, &subreq->flags); if (IS_ENCRYPTED(inode) && err > 0) { err = ceph_fscrypt_decrypt_extents(inode, @@ -282,7 +283,8 @@ static bool ceph_netfs_issue_op_inline(struct netfs_io_subrequest *subreq) size_t len; int mode; - __set_bit(NETFS_SREQ_CLEAR_TAIL, &subreq->flags); + if (rreq->origin != NETFS_DIO_READ) + __set_bit(NETFS_SREQ_CLEAR_TAIL, &subreq->flags); __clear_bit(NETFS_SREQ_COPY_TO_CACHE, &subreq->flags); if (subreq->start >= inode->i_size) @@ -424,6 +426,9 @@ static int ceph_init_request(struct netfs_io_request *rreq, struct file *file) struct ceph_netfs_request_data *priv; int ret = 0; + /* [DEPRECATED] Use PG_private_2 to mark folio being written to the cache. */ + __set_bit(NETFS_RREQ_USE_PGPRIV2, &rreq->flags); + if (rreq->origin != NETFS_READAHEAD) return 0; @@ -498,6 +503,11 @@ const struct netfs_request_ops ceph_netfs_ops = { }; #ifdef CONFIG_CEPH_FSCACHE +static void ceph_set_page_fscache(struct page *page) +{ + folio_start_private_2(page_folio(page)); /* [DEPRECATED] */ +} + static void ceph_fscache_write_terminated(void *priv, ssize_t error, bool was_async) { struct inode *inode = priv; @@ -515,6 +525,10 @@ static void ceph_fscache_write_to_cache(struct inode *inode, u64 off, u64 len, b ceph_fscache_write_terminated, inode, true, caching); } #else +static inline void ceph_set_page_fscache(struct page *page) +{ +} + static inline void ceph_fscache_write_to_cache(struct inode *inode, u64 off, u64 len, bool caching) { } @@ -706,6 +720,8 @@ static int writepage_nounlock(struct page *page, struct writeback_control *wbc) len = wlen; set_page_writeback(page); + if (caching) + ceph_set_page_fscache(page); ceph_fscache_write_to_cache(inode, page_off, len, caching); if (IS_ENCRYPTED(inode)) { @@ -789,6 +805,8 @@ static int ceph_writepage(struct page *page, struct writeback_control *wbc) return AOP_WRITEPAGE_ACTIVATE; } + folio_wait_private_2(page_folio(page)); /* [DEPRECATED] */ + err = writepage_nounlock(page, wbc); if (err == -ERESTARTSYS) { /* direct memory reclaimer was killed by SIGKILL. return 0 @@ -1062,7 +1080,8 @@ static int ceph_writepages_start(struct address_space *mapping, unlock_page(page); break; } - if (PageWriteback(page)) { + if (PageWriteback(page) || + PagePrivate2(page) /* [DEPRECATED] */) { if (wbc->sync_mode == WB_SYNC_NONE) { doutc(cl, "%p under writeback\n", page); unlock_page(page); @@ -1070,6 +1089,7 @@ static int ceph_writepages_start(struct address_space *mapping, } doutc(cl, "waiting on writeback %p\n", page); wait_on_page_writeback(page); + folio_wait_private_2(page_folio(page)); /* [DEPRECATED] */ } if (!clear_page_dirty_for_io(page)) { @@ -1254,6 +1274,8 @@ static int ceph_writepages_start(struct address_space *mapping, } set_page_writeback(page); + if (caching) + ceph_set_page_fscache(page); len += thp_size(page); } ceph_fscache_write_to_cache(inode, offset, len, caching); diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c index e98aa821930361..808c9c04827683 100644 --- a/fs/ceph/caps.c +++ b/fs/ceph/caps.c @@ -2016,6 +2016,8 @@ bool __ceph_should_report_size(struct ceph_inode_info *ci) * CHECK_CAPS_AUTHONLY - we should only check the auth cap * CHECK_CAPS_FLUSH - we should flush any dirty caps immediately, without * further delay. + * CHECK_CAPS_FLUSH_FORCE - we should flush any caps immediately, without + * further delay. */ void ceph_check_caps(struct ceph_inode_info *ci, int flags) { @@ -2097,7 +2099,7 @@ void ceph_check_caps(struct ceph_inode_info *ci, int flags) } doutc(cl, "%p %llx.%llx file_want %s used %s dirty %s " - "flushing %s issued %s revoking %s retain %s %s%s%s\n", + "flushing %s issued %s revoking %s retain %s %s%s%s%s\n", inode, ceph_vinop(inode), ceph_cap_string(file_wanted), ceph_cap_string(used), ceph_cap_string(ci->i_dirty_caps), ceph_cap_string(ci->i_flushing_caps), @@ -2105,7 +2107,8 @@ void ceph_check_caps(struct ceph_inode_info *ci, int flags) ceph_cap_string(retain), (flags & CHECK_CAPS_AUTHONLY) ? " AUTHONLY" : "", (flags & CHECK_CAPS_FLUSH) ? " FLUSH" : "", - (flags & CHECK_CAPS_NOINVAL) ? " NOINVAL" : ""); + (flags & CHECK_CAPS_NOINVAL) ? " NOINVAL" : "", + (flags & CHECK_CAPS_FLUSH_FORCE) ? " FLUSH_FORCE" : ""); /* * If we no longer need to hold onto old our caps, and we may @@ -2180,6 +2183,11 @@ void ceph_check_caps(struct ceph_inode_info *ci, int flags) queue_writeback = true; } + if (flags & CHECK_CAPS_FLUSH_FORCE) { + doutc(cl, "force to flush caps\n"); + goto ack; + } + if (cap == ci->i_auth_cap && (cap->issued & CEPH_CAP_FILE_WR)) { /* request larger max_size from MDS? */ @@ -3510,6 +3518,8 @@ static void handle_cap_grant(struct inode *inode, bool queue_invalidate = false; bool deleted_inode = false; bool fill_inline = false; + bool revoke_wait = false; + int flags = 0; /* * If there is at least one crypto block then we'll trust @@ -3705,16 +3715,18 @@ static void handle_cap_grant(struct inode *inode, ceph_cap_string(cap->issued), ceph_cap_string(newcaps), ceph_cap_string(revoking)); if (S_ISREG(inode->i_mode) && - (revoking & used & CEPH_CAP_FILE_BUFFER)) + (revoking & used & CEPH_CAP_FILE_BUFFER)) { writeback = true; /* initiate writeback; will delay ack */ - else if (queue_invalidate && + revoke_wait = true; + } else if (queue_invalidate && revoking == CEPH_CAP_FILE_CACHE && - (newcaps & CEPH_CAP_FILE_LAZYIO) == 0) - ; /* do nothing yet, invalidation will be queued */ - else if (cap == ci->i_auth_cap) + (newcaps & CEPH_CAP_FILE_LAZYIO) == 0) { + revoke_wait = true; /* do nothing yet, invalidation will be queued */ + } else if (cap == ci->i_auth_cap) { check_caps = 1; /* check auth cap only */ - else + } else { check_caps = 2; /* check all caps */ + } /* If there is new caps, try to wake up the waiters */ if (~cap->issued & newcaps) wake = true; @@ -3741,8 +3753,9 @@ static void handle_cap_grant(struct inode *inode, BUG_ON(cap->issued & ~cap->implemented); /* don't let check_caps skip sending a response to MDS for revoke msgs */ - if (le32_to_cpu(grant->op) == CEPH_CAP_OP_REVOKE) { + if (!revoke_wait && le32_to_cpu(grant->op) == CEPH_CAP_OP_REVOKE) { cap->mds_wanted = 0; + flags |= CHECK_CAPS_FLUSH_FORCE; if (cap == ci->i_auth_cap) check_caps = 1; /* check auth cap only */ else @@ -3798,9 +3811,9 @@ static void handle_cap_grant(struct inode *inode, mutex_unlock(&session->s_mutex); if (check_caps == 1) - ceph_check_caps(ci, CHECK_CAPS_AUTHONLY | CHECK_CAPS_NOINVAL); + ceph_check_caps(ci, flags | CHECK_CAPS_AUTHONLY | CHECK_CAPS_NOINVAL); else if (check_caps == 2) - ceph_check_caps(ci, CHECK_CAPS_NOINVAL); + ceph_check_caps(ci, flags | CHECK_CAPS_NOINVAL); } /* diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index 8f8de8f33abbfb..71cd70514efa55 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c @@ -577,8 +577,6 @@ struct inode *ceph_alloc_inode(struct super_block *sb) /* Set parameters for the netfs library */ netfs_inode_init(&ci->netfs, &ceph_netfs_ops, false); - /* [DEPRECATED] Use PG_private_2 to mark folio being written to the cache. */ - __set_bit(NETFS_ICTX_USE_PGPRIV2, &ci->netfs.flags); spin_lock_init(&ci->i_ceph_lock); diff --git a/fs/ceph/super.h b/fs/ceph/super.h index b63b4cd9b5b685..6e817bf1337c65 100644 --- a/fs/ceph/super.h +++ b/fs/ceph/super.h @@ -200,9 +200,10 @@ struct ceph_cap { struct list_head caps_item; }; -#define CHECK_CAPS_AUTHONLY 1 /* only check auth cap */ -#define CHECK_CAPS_FLUSH 2 /* flush any dirty caps */ -#define CHECK_CAPS_NOINVAL 4 /* don't invalidate pagecache */ +#define CHECK_CAPS_AUTHONLY 1 /* only check auth cap */ +#define CHECK_CAPS_FLUSH 2 /* flush any dirty caps */ +#define CHECK_CAPS_NOINVAL 4 /* don't invalidate pagecache */ +#define CHECK_CAPS_FLUSH_FORCE 8 /* force flush any caps */ struct ceph_cap_flush { u64 tid; diff --git a/fs/exec.c b/fs/exec.c index a126e3d1cacb01..50e76cc633c4ba 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -1692,6 +1692,7 @@ static void bprm_fill_uid(struct linux_binprm *bprm, struct file *file) unsigned int mode; vfsuid_t vfsuid; vfsgid_t vfsgid; + int err; if (!mnt_may_suid(file->f_path.mnt)) return; @@ -1708,12 +1709,17 @@ static void bprm_fill_uid(struct linux_binprm *bprm, struct file *file) /* Be careful if suid/sgid is set */ inode_lock(inode); - /* reload atomically mode/uid/gid now that lock held */ + /* Atomically reload and check mode/uid/gid now that lock held. */ mode = inode->i_mode; vfsuid = i_uid_into_vfsuid(idmap, inode); vfsgid = i_gid_into_vfsgid(idmap, inode); + err = inode_permission(idmap, inode, MAY_EXEC); inode_unlock(inode); + /* Did the exec bit vanish out from under us? Give up. */ + if (err) + return; + /* We ignore suid/sgid if there are no mappings for them in the ns */ if (!vfsuid_has_mapping(bprm->cred->user_ns, vfsuid) || !vfsgid_has_mapping(bprm->cred->user_ns, vfsgid)) diff --git a/fs/file.c b/fs/file.c index a3b72aa64f1164..655338effe9c72 100644 --- a/fs/file.c +++ b/fs/file.c @@ -46,27 +46,23 @@ static void free_fdtable_rcu(struct rcu_head *rcu) #define BITBIT_NR(nr) BITS_TO_LONGS(BITS_TO_LONGS(nr)) #define BITBIT_SIZE(nr) (BITBIT_NR(nr) * sizeof(long)) +#define fdt_words(fdt) ((fdt)->max_fds / BITS_PER_LONG) // words in ->open_fds /* * Copy 'count' fd bits from the old table to the new table and clear the extra * space if any. This does not copy the file pointers. Called with the files * spinlock held for write. */ -static void copy_fd_bitmaps(struct fdtable *nfdt, struct fdtable *ofdt, - unsigned int count) +static inline void copy_fd_bitmaps(struct fdtable *nfdt, struct fdtable *ofdt, + unsigned int copy_words) { - unsigned int cpy, set; - - cpy = count / BITS_PER_BYTE; - set = (nfdt->max_fds - count) / BITS_PER_BYTE; - memcpy(nfdt->open_fds, ofdt->open_fds, cpy); - memset((char *)nfdt->open_fds + cpy, 0, set); - memcpy(nfdt->close_on_exec, ofdt->close_on_exec, cpy); - memset((char *)nfdt->close_on_exec + cpy, 0, set); - - cpy = BITBIT_SIZE(count); - set = BITBIT_SIZE(nfdt->max_fds) - cpy; - memcpy(nfdt->full_fds_bits, ofdt->full_fds_bits, cpy); - memset((char *)nfdt->full_fds_bits + cpy, 0, set); + unsigned int nwords = fdt_words(nfdt); + + bitmap_copy_and_extend(nfdt->open_fds, ofdt->open_fds, + copy_words * BITS_PER_LONG, nwords * BITS_PER_LONG); + bitmap_copy_and_extend(nfdt->close_on_exec, ofdt->close_on_exec, + copy_words * BITS_PER_LONG, nwords * BITS_PER_LONG); + bitmap_copy_and_extend(nfdt->full_fds_bits, ofdt->full_fds_bits, + copy_words, nwords); } /* @@ -84,7 +80,7 @@ static void copy_fdtable(struct fdtable *nfdt, struct fdtable *ofdt) memcpy(nfdt->fd, ofdt->fd, cpy); memset((char *)nfdt->fd + cpy, 0, set); - copy_fd_bitmaps(nfdt, ofdt, ofdt->max_fds); + copy_fd_bitmaps(nfdt, ofdt, fdt_words(ofdt)); } /* @@ -379,7 +375,7 @@ struct files_struct *dup_fd(struct files_struct *oldf, unsigned int max_fds, int open_files = sane_fdtable_size(old_fdt, max_fds); } - copy_fd_bitmaps(new_fdt, old_fdt, open_files); + copy_fd_bitmaps(new_fdt, old_fdt, open_files / BITS_PER_LONG); old_fds = old_fdt->fd; new_fds = new_fdt->fd; @@ -1248,6 +1244,7 @@ __releases(&files->file_lock) * tables and this condition does not arise without those. */ fdt = files_fdtable(files); + fd = array_index_nospec(fd, fdt->max_fds); tofree = fdt->fd[fd]; if (!tofree && fd_is_open(fd, fdt)) goto Ebusy; diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index 9eb191b5c4de12..7146038b2fe7d6 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -1618,9 +1618,11 @@ static int fuse_notify_store(struct fuse_conn *fc, unsigned int size, this_num = min_t(unsigned, num, PAGE_SIZE - offset); err = fuse_copy_page(cs, &page, offset, this_num, 0); - if (!err && offset == 0 && - (this_num == PAGE_SIZE || file_size == end)) + if (!PageUptodate(page) && !err && offset == 0 && + (this_num == PAGE_SIZE || file_size == end)) { + zero_user_segment(page, this_num, PAGE_SIZE); SetPageUptodate(page); + } unlock_page(page); put_page(page); diff --git a/fs/inode.c b/fs/inode.c index 86670941884b48..10c4619faeef8c 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -488,6 +488,39 @@ static void inode_lru_list_del(struct inode *inode) this_cpu_dec(nr_unused); } +static void inode_pin_lru_isolating(struct inode *inode) +{ + lockdep_assert_held(&inode->i_lock); + WARN_ON(inode->i_state & (I_LRU_ISOLATING | I_FREEING | I_WILL_FREE)); + inode->i_state |= I_LRU_ISOLATING; +} + +static void inode_unpin_lru_isolating(struct inode *inode) +{ + spin_lock(&inode->i_lock); + WARN_ON(!(inode->i_state & I_LRU_ISOLATING)); + inode->i_state &= ~I_LRU_ISOLATING; + smp_mb(); + wake_up_bit(&inode->i_state, __I_LRU_ISOLATING); + spin_unlock(&inode->i_lock); +} + +static void inode_wait_for_lru_isolating(struct inode *inode) +{ + spin_lock(&inode->i_lock); + if (inode->i_state & I_LRU_ISOLATING) { + DEFINE_WAIT_BIT(wq, &inode->i_state, __I_LRU_ISOLATING); + wait_queue_head_t *wqh; + + wqh = bit_waitqueue(&inode->i_state, __I_LRU_ISOLATING); + spin_unlock(&inode->i_lock); + __wait_on_bit(wqh, &wq, bit_wait, TASK_UNINTERRUPTIBLE); + spin_lock(&inode->i_lock); + WARN_ON(inode->i_state & I_LRU_ISOLATING); + } + spin_unlock(&inode->i_lock); +} + /** * inode_sb_list_add - add inode to the superblock list of inodes * @inode: inode to add @@ -657,6 +690,8 @@ static void evict(struct inode *inode) inode_sb_list_del(inode); + inode_wait_for_lru_isolating(inode); + /* * Wait for flusher thread to be done with the inode so that filesystem * does not start destroying it while writeback is still running. Since @@ -855,7 +890,7 @@ static enum lru_status inode_lru_isolate(struct list_head *item, * be under pressure before the cache inside the highmem zone. */ if (inode_has_buffers(inode) || !mapping_empty(&inode->i_data)) { - __iget(inode); + inode_pin_lru_isolating(inode); spin_unlock(&inode->i_lock); spin_unlock(lru_lock); if (remove_inode_buffers(inode)) { @@ -867,7 +902,7 @@ static enum lru_status inode_lru_isolate(struct list_head *item, __count_vm_events(PGINODESTEAL, reap); mm_account_reclaimed_pages(reap); } - iput(inode); + inode_unpin_lru_isolating(inode); spin_lock(lru_lock); return LRU_RETRY; } diff --git a/fs/libfs.c b/fs/libfs.c index 8aa34870449fe1..02602d00939e96 100644 --- a/fs/libfs.c +++ b/fs/libfs.c @@ -450,6 +450,14 @@ void simple_offset_destroy(struct offset_ctx *octx) mtree_destroy(&octx->mt); } +static int offset_dir_open(struct inode *inode, struct file *file) +{ + struct offset_ctx *ctx = inode->i_op->get_offset_ctx(inode); + + file->private_data = (void *)ctx->next_offset; + return 0; +} + /** * offset_dir_llseek - Advance the read position of a directory descriptor * @file: an open directory whose position is to be updated @@ -463,6 +471,9 @@ void simple_offset_destroy(struct offset_ctx *octx) */ static loff_t offset_dir_llseek(struct file *file, loff_t offset, int whence) { + struct inode *inode = file->f_inode; + struct offset_ctx *ctx = inode->i_op->get_offset_ctx(inode); + switch (whence) { case SEEK_CUR: offset += file->f_pos; @@ -476,7 +487,8 @@ static loff_t offset_dir_llseek(struct file *file, loff_t offset, int whence) } /* In this case, ->private_data is protected by f_pos_lock */ - file->private_data = NULL; + if (!offset) + file->private_data = (void *)ctx->next_offset; return vfs_setpos(file, offset, LONG_MAX); } @@ -507,7 +519,7 @@ static bool offset_dir_emit(struct dir_context *ctx, struct dentry *dentry) inode->i_ino, fs_umode_to_dtype(inode->i_mode)); } -static void *offset_iterate_dir(struct inode *inode, struct dir_context *ctx) +static void offset_iterate_dir(struct inode *inode, struct dir_context *ctx, long last_index) { struct offset_ctx *octx = inode->i_op->get_offset_ctx(inode); struct dentry *dentry; @@ -515,17 +527,21 @@ static void *offset_iterate_dir(struct inode *inode, struct dir_context *ctx) while (true) { dentry = offset_find_next(octx, ctx->pos); if (!dentry) - return ERR_PTR(-ENOENT); + return; + + if (dentry2offset(dentry) >= last_index) { + dput(dentry); + return; + } if (!offset_dir_emit(ctx, dentry)) { dput(dentry); - break; + return; } ctx->pos = dentry2offset(dentry) + 1; dput(dentry); } - return NULL; } /** @@ -552,22 +568,19 @@ static void *offset_iterate_dir(struct inode *inode, struct dir_context *ctx) static int offset_readdir(struct file *file, struct dir_context *ctx) { struct dentry *dir = file->f_path.dentry; + long last_index = (long)file->private_data; lockdep_assert_held(&d_inode(dir)->i_rwsem); if (!dir_emit_dots(file, ctx)) return 0; - /* In this case, ->private_data is protected by f_pos_lock */ - if (ctx->pos == DIR_OFFSET_MIN) - file->private_data = NULL; - else if (file->private_data == ERR_PTR(-ENOENT)) - return 0; - file->private_data = offset_iterate_dir(d_inode(dir), ctx); + offset_iterate_dir(d_inode(dir), ctx, last_index); return 0; } const struct file_operations simple_offset_dir_operations = { + .open = offset_dir_open, .llseek = offset_dir_llseek, .iterate_shared = offset_readdir, .read = generic_read_dir, diff --git a/fs/locks.c b/fs/locks.c index 9afb16e0683ffd..e45cad40f8b6bd 100644 --- a/fs/locks.c +++ b/fs/locks.c @@ -2984,7 +2984,7 @@ static int __init filelock_init(void) filelock_cache = kmem_cache_create("file_lock_cache", sizeof(struct file_lock), 0, SLAB_PANIC, NULL); - filelease_cache = kmem_cache_create("file_lock_cache", + filelease_cache = kmem_cache_create("file_lease_cache", sizeof(struct file_lease), 0, SLAB_PANIC, NULL); for_each_possible_cpu(i) { diff --git a/fs/netfs/Kconfig b/fs/netfs/Kconfig index 1b78e8b65ebc14..7701c037c3283f 100644 --- a/fs/netfs/Kconfig +++ b/fs/netfs/Kconfig @@ -24,7 +24,7 @@ config NETFS_STATS config NETFS_DEBUG bool "Enable dynamic debugging netfslib and FS-Cache" - depends on NETFS + depends on NETFS_SUPPORT help This permits debugging to be dynamically enabled in the local caching management module. If this is set, the debugging output may be diff --git a/fs/netfs/buffered_read.c b/fs/netfs/buffered_read.c index a688d4c75d9926..27c750d3947626 100644 --- a/fs/netfs/buffered_read.c +++ b/fs/netfs/buffered_read.c @@ -9,6 +9,97 @@ #include #include "internal.h" +/* + * [DEPRECATED] Unlock the folios in a read operation for when the filesystem + * is using PG_private_2 and direct writing to the cache from here rather than + * marking the page for writeback. + * + * Note that we don't touch folio->private in this code. + */ +static void netfs_rreq_unlock_folios_pgpriv2(struct netfs_io_request *rreq, + size_t *account) +{ + struct netfs_io_subrequest *subreq; + struct folio *folio; + pgoff_t start_page = rreq->start / PAGE_SIZE; + pgoff_t last_page = ((rreq->start + rreq->len) / PAGE_SIZE) - 1; + bool subreq_failed = false; + + XA_STATE(xas, &rreq->mapping->i_pages, start_page); + + /* Walk through the pagecache and the I/O request lists simultaneously. + * We may have a mixture of cached and uncached sections and we only + * really want to write out the uncached sections. This is slightly + * complicated by the possibility that we might have huge pages with a + * mixture inside. + */ + subreq = list_first_entry(&rreq->subrequests, + struct netfs_io_subrequest, rreq_link); + subreq_failed = (subreq->error < 0); + + trace_netfs_rreq(rreq, netfs_rreq_trace_unlock_pgpriv2); + + rcu_read_lock(); + xas_for_each(&xas, folio, last_page) { + loff_t pg_end; + bool pg_failed = false; + bool folio_started = false; + + if (xas_retry(&xas, folio)) + continue; + + pg_end = folio_pos(folio) + folio_size(folio) - 1; + + for (;;) { + loff_t sreq_end; + + if (!subreq) { + pg_failed = true; + break; + } + + if (!folio_started && + test_bit(NETFS_SREQ_COPY_TO_CACHE, &subreq->flags) && + fscache_operation_valid(&rreq->cache_resources)) { + trace_netfs_folio(folio, netfs_folio_trace_copy_to_cache); + folio_start_private_2(folio); + folio_started = true; + } + + pg_failed |= subreq_failed; + sreq_end = subreq->start + subreq->len - 1; + if (pg_end < sreq_end) + break; + + *account += subreq->transferred; + if (!list_is_last(&subreq->rreq_link, &rreq->subrequests)) { + subreq = list_next_entry(subreq, rreq_link); + subreq_failed = (subreq->error < 0); + } else { + subreq = NULL; + subreq_failed = false; + } + + if (pg_end == sreq_end) + break; + } + + if (!pg_failed) { + flush_dcache_folio(folio); + folio_mark_uptodate(folio); + } + + if (!test_bit(NETFS_RREQ_DONT_UNLOCK_FOLIOS, &rreq->flags)) { + if (folio->index == rreq->no_unlock_folio && + test_bit(NETFS_RREQ_NO_UNLOCK_FOLIO, &rreq->flags)) + _debug("no unlock"); + else + folio_unlock(folio); + } + } + rcu_read_unlock(); +} + /* * Unlock the folios in a read operation. We need to set PG_writeback on any * folios we're going to write back before we unlock them. @@ -35,6 +126,12 @@ void netfs_rreq_unlock_folios(struct netfs_io_request *rreq) } } + /* Handle deprecated PG_private_2 case. */ + if (test_bit(NETFS_RREQ_USE_PGPRIV2, &rreq->flags)) { + netfs_rreq_unlock_folios_pgpriv2(rreq, &account); + goto out; + } + /* Walk through the pagecache and the I/O request lists simultaneously. * We may have a mixture of cached and uncached sections and we only * really want to write out the uncached sections. This is slightly @@ -52,7 +149,6 @@ void netfs_rreq_unlock_folios(struct netfs_io_request *rreq) loff_t pg_end; bool pg_failed = false; bool wback_to_cache = false; - bool folio_started = false; if (xas_retry(&xas, folio)) continue; @@ -66,17 +162,8 @@ void netfs_rreq_unlock_folios(struct netfs_io_request *rreq) pg_failed = true; break; } - if (test_bit(NETFS_RREQ_USE_PGPRIV2, &rreq->flags)) { - if (!folio_started && test_bit(NETFS_SREQ_COPY_TO_CACHE, - &subreq->flags)) { - trace_netfs_folio(folio, netfs_folio_trace_copy_to_cache); - folio_start_private_2(folio); - folio_started = true; - } - } else { - wback_to_cache |= - test_bit(NETFS_SREQ_COPY_TO_CACHE, &subreq->flags); - } + + wback_to_cache |= test_bit(NETFS_SREQ_COPY_TO_CACHE, &subreq->flags); pg_failed |= subreq_failed; sreq_end = subreq->start + subreq->len - 1; if (pg_end < sreq_end) @@ -124,6 +211,7 @@ void netfs_rreq_unlock_folios(struct netfs_io_request *rreq) } rcu_read_unlock(); +out: task_io_account_read(account); if (rreq->netfs_ops->done) rreq->netfs_ops->done(rreq); @@ -395,7 +483,7 @@ static bool netfs_skip_folio_read(struct folio *folio, loff_t pos, size_t len, } /** - * netfs_write_begin - Helper to prepare for writing + * netfs_write_begin - Helper to prepare for writing [DEPRECATED] * @ctx: The netfs context * @file: The file to read from * @mapping: The mapping to read from @@ -426,6 +514,9 @@ static bool netfs_skip_folio_read(struct folio *folio, loff_t pos, size_t len, * inode before calling this. * * This is usable whether or not caching is enabled. + * + * Note that this should be considered deprecated and netfs_perform_write() + * used instead. */ int netfs_write_begin(struct netfs_inode *ctx, struct file *file, struct address_space *mapping, @@ -466,7 +557,7 @@ int netfs_write_begin(struct netfs_inode *ctx, if (!netfs_is_cache_enabled(ctx) && netfs_skip_folio_read(folio, pos, len, false)) { netfs_stat(&netfs_n_rh_write_zskip); - goto have_folio; + goto have_folio_no_wait; } rreq = netfs_alloc_request(mapping, file, @@ -507,6 +598,10 @@ int netfs_write_begin(struct netfs_inode *ctx, netfs_put_request(rreq, false, netfs_rreq_trace_put_return); have_folio: + ret = folio_wait_private_2_killable(folio); + if (ret < 0) + goto error; +have_folio_no_wait: *_folio = folio; _leave(" = 0"); return 0; diff --git a/fs/netfs/buffered_write.c b/fs/netfs/buffered_write.c index 4726c315453c3a..ca53c5d1622ede 100644 --- a/fs/netfs/buffered_write.c +++ b/fs/netfs/buffered_write.c @@ -184,7 +184,7 @@ ssize_t netfs_perform_write(struct kiocb *iocb, struct iov_iter *iter, unsigned int bdp_flags = (iocb->ki_flags & IOCB_NOWAIT) ? BDP_ASYNC : 0; ssize_t written = 0, ret, ret2; loff_t i_size, pos = iocb->ki_pos, from, to; - size_t max_chunk = PAGE_SIZE << MAX_PAGECACHE_ORDER; + size_t max_chunk = mapping_max_folio_size(mapping); bool maybe_trouble = false; if (unlikely(test_bit(NETFS_ICTX_WRITETHROUGH, &ctx->flags) || diff --git a/fs/netfs/fscache_cookie.c b/fs/netfs/fscache_cookie.c index bce2492186d0b4..d4d4b3a8b10603 100644 --- a/fs/netfs/fscache_cookie.c +++ b/fs/netfs/fscache_cookie.c @@ -741,6 +741,10 @@ static void fscache_cookie_state_machine(struct fscache_cookie *cookie) spin_lock(&cookie->lock); } if (test_bit(FSCACHE_COOKIE_DO_LRU_DISCARD, &cookie->flags)) { + if (atomic_read(&cookie->n_accesses) != 0) + /* still being accessed: postpone it */ + break; + __fscache_set_cookie_state(cookie, FSCACHE_COOKIE_STATE_LRU_DISCARDING); wake = true; diff --git a/fs/netfs/io.c b/fs/netfs/io.c index c93851b9836889..5367caf3fa2863 100644 --- a/fs/netfs/io.c +++ b/fs/netfs/io.c @@ -98,6 +98,146 @@ static void netfs_rreq_completed(struct netfs_io_request *rreq, bool was_async) netfs_put_request(rreq, was_async, netfs_rreq_trace_put_complete); } +/* + * [DEPRECATED] Deal with the completion of writing the data to the cache. We + * have to clear the PG_fscache bits on the folios involved and release the + * caller's ref. + * + * May be called in softirq mode and we inherit a ref from the caller. + */ +static void netfs_rreq_unmark_after_write(struct netfs_io_request *rreq, + bool was_async) +{ + struct netfs_io_subrequest *subreq; + struct folio *folio; + pgoff_t unlocked = 0; + bool have_unlocked = false; + + rcu_read_lock(); + + list_for_each_entry(subreq, &rreq->subrequests, rreq_link) { + XA_STATE(xas, &rreq->mapping->i_pages, subreq->start / PAGE_SIZE); + + xas_for_each(&xas, folio, (subreq->start + subreq->len - 1) / PAGE_SIZE) { + if (xas_retry(&xas, folio)) + continue; + + /* We might have multiple writes from the same huge + * folio, but we mustn't unlock a folio more than once. + */ + if (have_unlocked && folio->index <= unlocked) + continue; + unlocked = folio_next_index(folio) - 1; + trace_netfs_folio(folio, netfs_folio_trace_end_copy); + folio_end_private_2(folio); + have_unlocked = true; + } + } + + rcu_read_unlock(); + netfs_rreq_completed(rreq, was_async); +} + +static void netfs_rreq_copy_terminated(void *priv, ssize_t transferred_or_error, + bool was_async) /* [DEPRECATED] */ +{ + struct netfs_io_subrequest *subreq = priv; + struct netfs_io_request *rreq = subreq->rreq; + + if (IS_ERR_VALUE(transferred_or_error)) { + netfs_stat(&netfs_n_rh_write_failed); + trace_netfs_failure(rreq, subreq, transferred_or_error, + netfs_fail_copy_to_cache); + } else { + netfs_stat(&netfs_n_rh_write_done); + } + + trace_netfs_sreq(subreq, netfs_sreq_trace_write_term); + + /* If we decrement nr_copy_ops to 0, the ref belongs to us. */ + if (atomic_dec_and_test(&rreq->nr_copy_ops)) + netfs_rreq_unmark_after_write(rreq, was_async); + + netfs_put_subrequest(subreq, was_async, netfs_sreq_trace_put_terminated); +} + +/* + * [DEPRECATED] Perform any outstanding writes to the cache. We inherit a ref + * from the caller. + */ +static void netfs_rreq_do_write_to_cache(struct netfs_io_request *rreq) +{ + struct netfs_cache_resources *cres = &rreq->cache_resources; + struct netfs_io_subrequest *subreq, *next, *p; + struct iov_iter iter; + int ret; + + trace_netfs_rreq(rreq, netfs_rreq_trace_copy); + + /* We don't want terminating writes trying to wake us up whilst we're + * still going through the list. + */ + atomic_inc(&rreq->nr_copy_ops); + + list_for_each_entry_safe(subreq, p, &rreq->subrequests, rreq_link) { + if (!test_bit(NETFS_SREQ_COPY_TO_CACHE, &subreq->flags)) { + list_del_init(&subreq->rreq_link); + netfs_put_subrequest(subreq, false, + netfs_sreq_trace_put_no_copy); + } + } + + list_for_each_entry(subreq, &rreq->subrequests, rreq_link) { + /* Amalgamate adjacent writes */ + while (!list_is_last(&subreq->rreq_link, &rreq->subrequests)) { + next = list_next_entry(subreq, rreq_link); + if (next->start != subreq->start + subreq->len) + break; + subreq->len += next->len; + list_del_init(&next->rreq_link); + netfs_put_subrequest(next, false, + netfs_sreq_trace_put_merged); + } + + ret = cres->ops->prepare_write(cres, &subreq->start, &subreq->len, + subreq->len, rreq->i_size, true); + if (ret < 0) { + trace_netfs_failure(rreq, subreq, ret, netfs_fail_prepare_write); + trace_netfs_sreq(subreq, netfs_sreq_trace_write_skip); + continue; + } + + iov_iter_xarray(&iter, ITER_SOURCE, &rreq->mapping->i_pages, + subreq->start, subreq->len); + + atomic_inc(&rreq->nr_copy_ops); + netfs_stat(&netfs_n_rh_write); + netfs_get_subrequest(subreq, netfs_sreq_trace_get_copy_to_cache); + trace_netfs_sreq(subreq, netfs_sreq_trace_write); + cres->ops->write(cres, subreq->start, &iter, + netfs_rreq_copy_terminated, subreq); + } + + /* If we decrement nr_copy_ops to 0, the usage ref belongs to us. */ + if (atomic_dec_and_test(&rreq->nr_copy_ops)) + netfs_rreq_unmark_after_write(rreq, false); +} + +static void netfs_rreq_write_to_cache_work(struct work_struct *work) /* [DEPRECATED] */ +{ + struct netfs_io_request *rreq = + container_of(work, struct netfs_io_request, work); + + netfs_rreq_do_write_to_cache(rreq); +} + +static void netfs_rreq_write_to_cache(struct netfs_io_request *rreq) /* [DEPRECATED] */ +{ + rreq->work.func = netfs_rreq_write_to_cache_work; + if (!queue_work(system_unbound_wq, &rreq->work)) + BUG(); +} + /* * Handle a short read. */ @@ -275,6 +415,10 @@ static void netfs_rreq_assess(struct netfs_io_request *rreq, bool was_async) clear_bit_unlock(NETFS_RREQ_IN_PROGRESS, &rreq->flags); wake_up_bit(&rreq->flags, NETFS_RREQ_IN_PROGRESS); + if (test_bit(NETFS_RREQ_COPY_TO_CACHE, &rreq->flags) && + test_bit(NETFS_RREQ_USE_PGPRIV2, &rreq->flags)) + return netfs_rreq_write_to_cache(rreq); + netfs_rreq_completed(rreq, was_async); } @@ -386,7 +530,8 @@ void netfs_subreq_terminated(struct netfs_io_subrequest *subreq, if (transferred_or_error == 0) { if (__test_and_set_bit(NETFS_SREQ_NO_PROGRESS, &subreq->flags)) { - subreq->error = -ENODATA; + if (rreq->origin != NETFS_DIO_READ) + subreq->error = -ENODATA; goto failed; } } else { @@ -457,9 +602,14 @@ netfs_rreq_prepare_read(struct netfs_io_request *rreq, } if (subreq->len > ictx->zero_point - subreq->start) subreq->len = ictx->zero_point - subreq->start; + + /* We limit buffered reads to the EOF, but let the + * server deal with larger-than-EOF DIO/unbuffered + * reads. + */ + if (subreq->len > rreq->i_size - subreq->start) + subreq->len = rreq->i_size - subreq->start; } - if (subreq->len > rreq->i_size - subreq->start) - subreq->len = rreq->i_size - subreq->start; if (rreq->rsize && subreq->len > rreq->rsize) subreq->len = rreq->rsize; @@ -595,11 +745,10 @@ int netfs_begin_read(struct netfs_io_request *rreq, bool sync) do { _debug("submit %llx + %llx >= %llx", rreq->start, rreq->submitted, rreq->i_size); - if (rreq->origin == NETFS_DIO_READ && - rreq->start + rreq->submitted >= rreq->i_size) - break; if (!netfs_rreq_submit_slice(rreq, &io_iter)) break; + if (test_bit(NETFS_SREQ_NO_PROGRESS, &rreq->flags)) + break; if (test_bit(NETFS_RREQ_BLOCKED, &rreq->flags) && test_bit(NETFS_RREQ_NONBLOCK, &rreq->flags)) break; diff --git a/fs/netfs/objects.c b/fs/netfs/objects.c index f4a64272747925..0294df70c3ff45 100644 --- a/fs/netfs/objects.c +++ b/fs/netfs/objects.c @@ -24,10 +24,6 @@ struct netfs_io_request *netfs_alloc_request(struct address_space *mapping, struct netfs_io_request *rreq; mempool_t *mempool = ctx->ops->request_pool ?: &netfs_request_pool; struct kmem_cache *cache = mempool->pool_data; - bool is_unbuffered = (origin == NETFS_UNBUFFERED_WRITE || - origin == NETFS_DIO_READ || - origin == NETFS_DIO_WRITE); - bool cached = !is_unbuffered && netfs_is_cache_enabled(ctx); int ret; for (;;) { @@ -56,12 +52,6 @@ struct netfs_io_request *netfs_alloc_request(struct address_space *mapping, refcount_set(&rreq->ref, 1); __set_bit(NETFS_RREQ_IN_PROGRESS, &rreq->flags); - if (cached) { - __set_bit(NETFS_RREQ_WRITE_TO_CACHE, &rreq->flags); - if (test_bit(NETFS_ICTX_USE_PGPRIV2, &ctx->flags)) - /* Filesystem uses deprecated PG_private_2 marking. */ - __set_bit(NETFS_RREQ_USE_PGPRIV2, &rreq->flags); - } if (file && file->f_flags & O_NONBLOCK) __set_bit(NETFS_RREQ_NONBLOCK, &rreq->flags); if (rreq->netfs_ops->init_request) { diff --git a/fs/netfs/write_issue.c b/fs/netfs/write_issue.c index 9258d30cffe3cf..3f7e37e50c7d02 100644 --- a/fs/netfs/write_issue.c +++ b/fs/netfs/write_issue.c @@ -94,6 +94,8 @@ struct netfs_io_request *netfs_create_write_req(struct address_space *mapping, { struct netfs_io_request *wreq; struct netfs_inode *ictx; + bool is_buffered = (origin == NETFS_WRITEBACK || + origin == NETFS_WRITETHROUGH); wreq = netfs_alloc_request(mapping, file, start, 0, origin); if (IS_ERR(wreq)) @@ -102,7 +104,7 @@ struct netfs_io_request *netfs_create_write_req(struct address_space *mapping, _enter("R=%x", wreq->debug_id); ictx = netfs_inode(wreq->inode); - if (test_bit(NETFS_RREQ_WRITE_TO_CACHE, &wreq->flags)) + if (is_buffered && netfs_is_cache_enabled(ictx)) fscache_begin_write_operation(&wreq->cache_resources, netfs_i_cookie(ictx)); wreq->contiguity = wreq->start; diff --git a/fs/nfs/fscache.c b/fs/nfs/fscache.c index 7202ce84d0eb03..7a558dea75c409 100644 --- a/fs/nfs/fscache.c +++ b/fs/nfs/fscache.c @@ -265,6 +265,8 @@ static int nfs_netfs_init_request(struct netfs_io_request *rreq, struct file *fi { rreq->netfs_priv = get_nfs_open_context(nfs_file_open_context(file)); rreq->debug_id = atomic_inc_return(&nfs_netfs_debug_id); + /* [DEPRECATED] Use PG_private_2 to mark folio being written to the cache. */ + __set_bit(NETFS_RREQ_USE_PGPRIV2, &rreq->flags); return 0; } @@ -361,7 +363,8 @@ void nfs_netfs_read_completion(struct nfs_pgio_header *hdr) return; sreq = netfs->sreq; - if (test_bit(NFS_IOHDR_EOF, &hdr->flags)) + if (test_bit(NFS_IOHDR_EOF, &hdr->flags) && + sreq->rreq->origin != NETFS_DIO_READ) __set_bit(NETFS_SREQ_CLEAR_TAIL, &sreq->flags); if (hdr->error) diff --git a/fs/nfs/fscache.h b/fs/nfs/fscache.h index fbed0027996f88..e8adae1bc260a3 100644 --- a/fs/nfs/fscache.h +++ b/fs/nfs/fscache.h @@ -81,8 +81,6 @@ static inline void nfs_netfs_put(struct nfs_netfs_io_data *netfs) static inline void nfs_netfs_inode_init(struct nfs_inode *nfsi) { netfs_inode_init(&nfsi->netfs, &nfs_netfs_ops, false); - /* [DEPRECATED] Use PG_private_2 to mark folio being written to the cache. */ - __set_bit(NETFS_ICTX_USE_PGPRIV2, &nfsi->netfs.flags); } extern void nfs_netfs_initiate_read(struct nfs_pgio_header *hdr); extern void nfs_netfs_read_completion(struct nfs_pgio_header *hdr); diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index 9e0ea6fc2aa326..34eb2c2cbcde34 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c @@ -2069,8 +2069,7 @@ int nfsd_nl_listener_set_doit(struct sk_buff *skb, struct genl_info *info) continue; } - ret = svc_xprt_create_from_sa(serv, xcl_name, net, sa, - SVC_SOCK_ANONYMOUS, + ret = svc_xprt_create_from_sa(serv, xcl_name, net, sa, 0, get_current_cred()); /* always save the latest error */ if (ret < 0) diff --git a/fs/smb/client/cifs_debug.c b/fs/smb/client/cifs_debug.c index c71ae5c043060e..4a20e92474b234 100644 --- a/fs/smb/client/cifs_debug.c +++ b/fs/smb/client/cifs_debug.c @@ -1072,7 +1072,7 @@ static int cifs_security_flags_proc_open(struct inode *inode, struct file *file) static void cifs_security_flags_handle_must_flags(unsigned int *flags) { - unsigned int signflags = *flags & CIFSSEC_MUST_SIGN; + unsigned int signflags = *flags & (CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL); if ((*flags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5) *flags = CIFSSEC_MUST_KRB5; diff --git a/fs/smb/client/cifsfs.h b/fs/smb/client/cifsfs.h index 62d5fee3e5ebbd..ca2bd204bcc591 100644 --- a/fs/smb/client/cifsfs.h +++ b/fs/smb/client/cifsfs.h @@ -147,6 +147,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 49 -#define CIFS_VERSION "2.49" +#define SMB3_PRODUCT_BUILD 50 +#define CIFS_VERSION "2.50" #endif /* _CIFSFS_H */ diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h index 8e86fec7dcd2ba..5c9b3e6cd95f20 100644 --- a/fs/smb/client/cifsglob.h +++ b/fs/smb/client/cifsglob.h @@ -345,7 +345,7 @@ struct smb_version_operations { /* connect to a server share */ int (*tree_connect)(const unsigned int, struct cifs_ses *, const char *, struct cifs_tcon *, const struct nls_table *); - /* close tree connecion */ + /* close tree connection */ int (*tree_disconnect)(const unsigned int, struct cifs_tcon *); /* get DFS referrals */ int (*get_dfs_refer)(const unsigned int, struct cifs_ses *, @@ -816,7 +816,7 @@ struct TCP_Server_Info { * Protected by @refpath_lock and @srv_lock. The @refpath_lock is * mostly used for not requiring a copy of @leaf_fullpath when getting * cached or new DFS referrals (which might also sleep during I/O). - * While @srv_lock is held for making string and NULL comparions against + * While @srv_lock is held for making string and NULL comparisons against * both fields as in mount(2) and cache refresh. * * format: \\HOST\SHARE[\OPTIONAL PATH] @@ -1471,29 +1471,6 @@ struct cifs_io_parms { struct TCP_Server_Info *server; }; -struct cifs_aio_ctx { - struct kref refcount; - struct list_head list; - struct mutex aio_mutex; - struct completion done; - struct iov_iter iter; - struct kiocb *iocb; - struct cifsFileInfo *cfile; - struct bio_vec *bv; - loff_t pos; - unsigned int nr_pinned_pages; - ssize_t rc; - unsigned int len; - unsigned int total_len; - unsigned int bv_need_unpin; /* If ->bv[] needs unpinning */ - bool should_dirty; - /* - * Indicates if this aio_ctx is for direct_io, - * If yes, iter is a copy of the user passed iov_iter - */ - bool direct_io; -}; - struct cifs_io_request { struct netfs_io_request rreq; struct cifsFileInfo *cfile; @@ -1904,7 +1881,7 @@ static inline bool is_replayable_error(int error) #define CIFSSEC_MAY_SIGN 0x00001 #define CIFSSEC_MAY_NTLMV2 0x00004 #define CIFSSEC_MAY_KRB5 0x00008 -#define CIFSSEC_MAY_SEAL 0x00040 /* not supported yet */ +#define CIFSSEC_MAY_SEAL 0x00040 #define CIFSSEC_MAY_NTLMSSP 0x00080 /* raw ntlmssp with ntlmv2 */ #define CIFSSEC_MUST_SIGN 0x01001 @@ -1914,11 +1891,11 @@ require use of the stronger protocol */ #define CIFSSEC_MUST_NTLMV2 0x04004 #define CIFSSEC_MUST_KRB5 0x08008 #ifdef CONFIG_CIFS_UPCALL -#define CIFSSEC_MASK 0x8F08F /* flags supported if no weak allowed */ +#define CIFSSEC_MASK 0xCF0CF /* flags supported if no weak allowed */ #else -#define CIFSSEC_MASK 0x87087 /* flags supported if no weak allowed */ +#define CIFSSEC_MASK 0xC70C7 /* flags supported if no weak allowed */ #endif /* UPCALL */ -#define CIFSSEC_MUST_SEAL 0x40040 /* not supported yet */ +#define CIFSSEC_MUST_SEAL 0x40040 #define CIFSSEC_MUST_NTLMSSP 0x80080 /* raw ntlmssp with ntlmv2 */ #define CIFSSEC_DEF (CIFSSEC_MAY_SIGN | CIFSSEC_MAY_NTLMV2 | CIFSSEC_MAY_NTLMSSP | CIFSSEC_MAY_SEAL) @@ -2010,7 +1987,6 @@ require use of the stronger protocol */ * cifsFileInfo->file_info_lock cifsFileInfo->count cifs_new_fileinfo * ->invalidHandle initiate_cifs_search * ->oplock_break_cancelled - * cifs_aio_ctx->aio_mutex cifs_aio_ctx cifs_aio_ctx_alloc ****************************************************************************/ #ifdef DECLARE_GLOBALS_HERE diff --git a/fs/smb/client/cifsproto.h b/fs/smb/client/cifsproto.h index c15bb5ee7eb7d6..497bf3c447bcb5 100644 --- a/fs/smb/client/cifsproto.h +++ b/fs/smb/client/cifsproto.h @@ -619,8 +619,6 @@ int __cifs_calc_signature(struct smb_rqst *rqst, struct shash_desc *shash); enum securityEnum cifs_select_sectype(struct TCP_Server_Info *, enum securityEnum); -struct cifs_aio_ctx *cifs_aio_ctx_alloc(void); -void cifs_aio_ctx_release(struct kref *refcount); int cifs_alloc_hash(const char *name, struct shash_desc **sdesc); void cifs_free_hash(struct shash_desc **sdesc); diff --git a/fs/smb/client/file.c b/fs/smb/client/file.c index b2405dd4d4d4da..1fc66bcf49eb45 100644 --- a/fs/smb/client/file.c +++ b/fs/smb/client/file.c @@ -217,7 +217,8 @@ static void cifs_req_issue_read(struct netfs_io_subrequest *subreq) goto out; } - __set_bit(NETFS_SREQ_CLEAR_TAIL, &subreq->flags); + if (subreq->rreq->origin != NETFS_DIO_READ) + __set_bit(NETFS_SREQ_CLEAR_TAIL, &subreq->flags); rc = rdata->server->ops->async_readv(rdata); out: @@ -315,7 +316,7 @@ static void cifs_free_subrequest(struct netfs_io_subrequest *subreq) #endif } - if (rdata->credits.value != 0) + if (rdata->credits.value != 0) { trace_smb3_rw_credits(rdata->rreq->debug_id, rdata->subreq.debug_index, rdata->credits.value, @@ -323,8 +324,12 @@ static void cifs_free_subrequest(struct netfs_io_subrequest *subreq) rdata->server ? rdata->server->in_flight : 0, -rdata->credits.value, cifs_trace_rw_credits_free_subreq); + if (rdata->server) + add_credits_and_wake_if(rdata->server, &rdata->credits, 0); + else + rdata->credits.value = 0; + } - add_credits_and_wake_if(rdata->server, &rdata->credits, 0); if (rdata->have_xid) free_xid(rdata->xid); } @@ -2749,6 +2754,7 @@ cifs_writev(struct kiocb *iocb, struct iov_iter *from) struct inode *inode = file->f_mapping->host; struct cifsInodeInfo *cinode = CIFS_I(inode); struct TCP_Server_Info *server = tlink_tcon(cfile->tlink)->ses->server; + struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); ssize_t rc; rc = netfs_start_io_write(inode); @@ -2765,12 +2771,16 @@ cifs_writev(struct kiocb *iocb, struct iov_iter *from) if (rc <= 0) goto out; - if (!cifs_find_lock_conflict(cfile, iocb->ki_pos, iov_iter_count(from), + if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) && + (cifs_find_lock_conflict(cfile, iocb->ki_pos, iov_iter_count(from), server->vals->exclusive_lock_type, 0, - NULL, CIFS_WRITE_OP)) - rc = netfs_buffered_write_iter_locked(iocb, from, NULL); - else + NULL, CIFS_WRITE_OP))) { rc = -EACCES; + goto out; + } + + rc = netfs_buffered_write_iter_locked(iocb, from, NULL); + out: up_read(&cinode->lock_sem); netfs_end_io_write(inode); diff --git a/fs/smb/client/inode.c b/fs/smb/client/inode.c index 4a8aa1de95223d..dd0afa23734c8d 100644 --- a/fs/smb/client/inode.c +++ b/fs/smb/client/inode.c @@ -1042,13 +1042,26 @@ static int reparse_info_to_fattr(struct cifs_open_info_data *data, } rc = -EOPNOTSUPP; - switch ((data->reparse.tag = tag)) { - case 0: /* SMB1 symlink */ + data->reparse.tag = tag; + if (!data->reparse.tag) { if (server->ops->query_symlink) { rc = server->ops->query_symlink(xid, tcon, cifs_sb, full_path, &data->symlink_target); } + if (rc == -EOPNOTSUPP) + data->reparse.tag = IO_REPARSE_TAG_INTERNAL; + } + + switch (data->reparse.tag) { + case 0: /* SMB1 symlink */ + break; + case IO_REPARSE_TAG_INTERNAL: + rc = 0; + if (le32_to_cpu(data->fi.Attributes) & ATTR_DIRECTORY) { + cifs_create_junction_fattr(fattr, sb); + goto out; + } break; case IO_REPARSE_TAG_MOUNT_POINT: cifs_create_junction_fattr(fattr, sb); diff --git a/fs/smb/client/ioctl.c b/fs/smb/client/ioctl.c index 855ac5a62edfaa..44dbaf9929a4e3 100644 --- a/fs/smb/client/ioctl.c +++ b/fs/smb/client/ioctl.c @@ -170,7 +170,10 @@ static long smb_mnt_get_fsinfo(unsigned int xid, struct cifs_tcon *tcon, static int cifs_shutdown(struct super_block *sb, unsigned long arg) { struct cifs_sb_info *sbi = CIFS_SB(sb); + struct tcon_link *tlink; + struct cifs_tcon *tcon; __u32 flags; + int rc; if (!capable(CAP_SYS_ADMIN)) return -EPERM; @@ -178,14 +181,21 @@ static int cifs_shutdown(struct super_block *sb, unsigned long arg) if (get_user(flags, (__u32 __user *)arg)) return -EFAULT; - if (flags > CIFS_GOING_FLAGS_NOLOGFLUSH) - return -EINVAL; + tlink = cifs_sb_tlink(sbi); + if (IS_ERR(tlink)) + return PTR_ERR(tlink); + tcon = tlink_tcon(tlink); + + trace_smb3_shutdown_enter(flags, tcon->tid); + if (flags > CIFS_GOING_FLAGS_NOLOGFLUSH) { + rc = -EINVAL; + goto shutdown_out_err; + } if (cifs_forced_shutdown(sbi)) - return 0; + goto shutdown_good; cifs_dbg(VFS, "shut down requested (%d)", flags); -/* trace_cifs_shutdown(sb, flags);*/ /* * see: @@ -201,7 +211,8 @@ static int cifs_shutdown(struct super_block *sb, unsigned long arg) */ case CIFS_GOING_FLAGS_DEFAULT: cifs_dbg(FYI, "shutdown with default flag not supported\n"); - return -EINVAL; + rc = -EINVAL; + goto shutdown_out_err; /* * FLAGS_LOGFLUSH is easy since it asks to write out metadata (not * data) but metadata writes are not cached on the client, so can treat @@ -210,11 +221,18 @@ static int cifs_shutdown(struct super_block *sb, unsigned long arg) case CIFS_GOING_FLAGS_LOGFLUSH: case CIFS_GOING_FLAGS_NOLOGFLUSH: sbi->mnt_cifs_flags |= CIFS_MOUNT_SHUTDOWN; - return 0; + goto shutdown_good; default: - return -EINVAL; + rc = -EINVAL; + goto shutdown_out_err; } + +shutdown_good: + trace_smb3_shutdown_done(flags, tcon->tid); return 0; +shutdown_out_err: + trace_smb3_shutdown_err(rc, flags, tcon->tid); + return rc; } static int cifs_dump_full_key(struct cifs_tcon *tcon, struct smb3_full_key_debug_info __user *in) diff --git a/fs/smb/client/misc.c b/fs/smb/client/misc.c index 07c468ddb88a89..c6f11e6f9eb995 100644 --- a/fs/smb/client/misc.c +++ b/fs/smb/client/misc.c @@ -352,7 +352,7 @@ checkSMB(char *buf, unsigned int total_read, struct TCP_Server_Info *server) * on simple responses (wct, bcc both zero) * in particular have seen this on * ulogoffX and FindClose. This leaves - * one byte of bcc potentially unitialized + * one byte of bcc potentially uninitialized */ /* zero rest of bcc */ tmp[sizeof(struct smb_hdr)+1] = 0; @@ -995,60 +995,6 @@ parse_dfs_referrals(struct get_dfs_referral_rsp *rsp, u32 rsp_size, return rc; } -struct cifs_aio_ctx * -cifs_aio_ctx_alloc(void) -{ - struct cifs_aio_ctx *ctx; - - /* - * Must use kzalloc to initialize ctx->bv to NULL and ctx->direct_io - * to false so that we know when we have to unreference pages within - * cifs_aio_ctx_release() - */ - ctx = kzalloc(sizeof(struct cifs_aio_ctx), GFP_KERNEL); - if (!ctx) - return NULL; - - INIT_LIST_HEAD(&ctx->list); - mutex_init(&ctx->aio_mutex); - init_completion(&ctx->done); - kref_init(&ctx->refcount); - return ctx; -} - -void -cifs_aio_ctx_release(struct kref *refcount) -{ - struct cifs_aio_ctx *ctx = container_of(refcount, - struct cifs_aio_ctx, refcount); - - cifsFileInfo_put(ctx->cfile); - - /* - * ctx->bv is only set if setup_aio_ctx_iter() was call successfuly - * which means that iov_iter_extract_pages() was a success and thus - * that we may have references or pins on pages that we need to - * release. - */ - if (ctx->bv) { - if (ctx->should_dirty || ctx->bv_need_unpin) { - unsigned int i; - - for (i = 0; i < ctx->nr_pinned_pages; i++) { - struct page *page = ctx->bv[i].bv_page; - - if (ctx->should_dirty) - set_page_dirty(page); - if (ctx->bv_need_unpin) - unpin_user_page(page); - } - } - kvfree(ctx->bv); - } - - kfree(ctx); -} - /** * cifs_alloc_hash - allocate hash and hash context together * @name: The name of the crypto hash algo @@ -1288,6 +1234,7 @@ int cifs_inval_name_dfs_link_error(const unsigned int xid, const char *full_path, bool *islink) { + struct TCP_Server_Info *server = tcon->ses->server; struct cifs_ses *ses = tcon->ses; size_t len; char *path; @@ -1304,12 +1251,12 @@ int cifs_inval_name_dfs_link_error(const unsigned int xid, !is_tcon_dfs(tcon)) return 0; - spin_lock(&tcon->tc_lock); - if (!tcon->origin_fullpath) { - spin_unlock(&tcon->tc_lock); + spin_lock(&server->srv_lock); + if (!server->leaf_fullpath) { + spin_unlock(&server->srv_lock); return 0; } - spin_unlock(&tcon->tc_lock); + spin_unlock(&server->srv_lock); /* * Slow path - tcon is DFS and @full_path has prefix path, so attempt diff --git a/fs/smb/client/reparse.c b/fs/smb/client/reparse.c index a0ffbda9073317..689d8a506d4593 100644 --- a/fs/smb/client/reparse.c +++ b/fs/smb/client/reparse.c @@ -505,6 +505,10 @@ bool cifs_reparse_point_to_fattr(struct cifs_sb_info *cifs_sb, } switch (tag) { + case IO_REPARSE_TAG_INTERNAL: + if (!(fattr->cf_cifsattrs & ATTR_DIRECTORY)) + return false; + fallthrough; case IO_REPARSE_TAG_DFS: case IO_REPARSE_TAG_DFSR: case IO_REPARSE_TAG_MOUNT_POINT: diff --git a/fs/smb/client/reparse.h b/fs/smb/client/reparse.h index 6b55d1df9e2f84..2c0644bc4e65a7 100644 --- a/fs/smb/client/reparse.h +++ b/fs/smb/client/reparse.h @@ -12,6 +12,12 @@ #include "fs_context.h" #include "cifsglob.h" +/* + * Used only by cifs.ko to ignore reparse points from files when client or + * server doesn't support FSCTL_GET_REPARSE_POINT. + */ +#define IO_REPARSE_TAG_INTERNAL ((__u32)~0U) + static inline dev_t reparse_nfs_mkdev(struct reparse_posix_data *buf) { u64 v = le64_to_cpu(*(__le64 *)buf->DataBuffer); @@ -78,10 +84,19 @@ static inline u32 reparse_mode_wsl_tag(mode_t mode) static inline bool reparse_inode_match(struct inode *inode, struct cifs_fattr *fattr) { + struct cifsInodeInfo *cinode = CIFS_I(inode); struct timespec64 ctime = inode_get_ctime(inode); - return (CIFS_I(inode)->cifsAttrs & ATTR_REPARSE) && - CIFS_I(inode)->reparse_tag == fattr->cf_cifstag && + /* + * Do not match reparse tags when client or server doesn't support + * FSCTL_GET_REPARSE_POINT. @fattr->cf_cifstag should contain correct + * reparse tag from query dir response but the client won't be able to + * read the reparse point data anyway. This spares us a revalidation. + */ + if (cinode->reparse_tag != IO_REPARSE_TAG_INTERNAL && + cinode->reparse_tag != fattr->cf_cifstag) + return false; + return (cinode->cifsAttrs & ATTR_REPARSE) && timespec64_equal(&ctime, &fattr->cf_ctime); } diff --git a/fs/smb/client/smb2inode.c b/fs/smb/client/smb2inode.c index 5c02a12251c848..9f5bc41433c156 100644 --- a/fs/smb/client/smb2inode.c +++ b/fs/smb/client/smb2inode.c @@ -930,6 +930,8 @@ int smb2_query_path_info(const unsigned int xid, switch (rc) { case 0: + rc = parse_create_response(data, cifs_sb, &out_iov[0]); + break; case -EOPNOTSUPP: /* * BB TODO: When support for special files added to Samba @@ -948,7 +950,8 @@ int smb2_query_path_info(const unsigned int xid, cmds[num_cmds++] = SMB2_OP_GET_REPARSE; oparms = CIFS_OPARMS(cifs_sb, tcon, full_path, - FILE_READ_ATTRIBUTES | FILE_READ_EA, + FILE_READ_ATTRIBUTES | + FILE_READ_EA | SYNCHRONIZE, FILE_OPEN, create_options | OPEN_REPARSE_POINT, ACL_NO_MODE); cifs_get_readable_path(tcon, full_path, &cfile); @@ -1256,7 +1259,8 @@ int smb2_query_reparse_point(const unsigned int xid, cifs_dbg(FYI, "%s: path: %s\n", __func__, full_path); cifs_get_readable_path(tcon, full_path, &cfile); - oparms = CIFS_OPARMS(cifs_sb, tcon, full_path, FILE_READ_ATTRIBUTES, + oparms = CIFS_OPARMS(cifs_sb, tcon, full_path, + FILE_READ_ATTRIBUTES | FILE_READ_EA | SYNCHRONIZE, FILE_OPEN, OPEN_REPARSE_POINT, ACL_NO_MODE); rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, &oparms, &in_iov, diff --git a/fs/smb/client/smb2pdu.c b/fs/smb/client/smb2pdu.c index 9a06b5594669b3..83facb54276a31 100644 --- a/fs/smb/client/smb2pdu.c +++ b/fs/smb/client/smb2pdu.c @@ -82,6 +82,9 @@ int smb3_encryption_required(const struct cifs_tcon *tcon) if (tcon->seal && (tcon->ses->server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION)) return 1; + if (((global_secflags & CIFSSEC_MUST_SEAL) == CIFSSEC_MUST_SEAL) && + (tcon->ses->server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION)) + return 1; return 0; } diff --git a/fs/smb/client/smbdirect.c b/fs/smb/client/smbdirect.c index d74e829de51c22..7bcc379014cadd 100644 --- a/fs/smb/client/smbdirect.c +++ b/fs/smb/client/smbdirect.c @@ -406,7 +406,7 @@ static void smbd_post_send_credits(struct work_struct *work) else response = get_empty_queue_buffer(info); if (!response) { - /* now switch to emtpy packet queue */ + /* now switch to empty packet queue */ if (use_receive_queue) { use_receive_queue = 0; continue; @@ -618,7 +618,7 @@ static struct rdma_cm_id *smbd_create_id( /* * Test if FRWR (Fast Registration Work Requests) is supported on the device - * This implementation requries FRWR on RDMA read/write + * This implementation requires FRWR on RDMA read/write * return value: true if it is supported */ static bool frwr_is_supported(struct ib_device_attr *attrs) @@ -2177,7 +2177,7 @@ static int allocate_mr_list(struct smbd_connection *info) * MR available in the list. It may access the list while the * smbd_mr_recovery_work is recovering the MR list. This doesn't need a lock * as they never modify the same places. However, there may be several CPUs - * issueing I/O trying to get MR at the same time, mr_list_lock is used to + * issuing I/O trying to get MR at the same time, mr_list_lock is used to * protect this situation. */ static struct smbd_mr *get_mr(struct smbd_connection *info) @@ -2311,7 +2311,7 @@ struct smbd_mr *smbd_register_mr(struct smbd_connection *info, /* * There is no need for waiting for complemtion on ib_post_send * on IB_WR_REG_MR. Hardware enforces a barrier and order of execution - * on the next ib_post_send when we actaully send I/O to remote peer + * on the next ib_post_send when we actually send I/O to remote peer */ rc = ib_post_send(info->id->qp, ®_wr->wr, NULL); if (!rc) diff --git a/fs/smb/client/trace.h b/fs/smb/client/trace.h index 6b3bdfb97211ff..0f0c10c7ada73f 100644 --- a/fs/smb/client/trace.h +++ b/fs/smb/client/trace.h @@ -1388,7 +1388,7 @@ DECLARE_EVENT_CLASS(smb3_ioctl_class, __entry->command = command; ), TP_printk("xid=%u fid=0x%llx ioctl cmd=0x%x", - __entry->xid, __entry->fid, __entry->command) + __entry->xid, __entry->fid, __entry->command) ) #define DEFINE_SMB3_IOCTL_EVENT(name) \ @@ -1400,9 +1400,58 @@ DEFINE_EVENT(smb3_ioctl_class, smb3_##name, \ DEFINE_SMB3_IOCTL_EVENT(ioctl); +DECLARE_EVENT_CLASS(smb3_shutdown_class, + TP_PROTO(__u32 flags, + __u32 tid), + TP_ARGS(flags, tid), + TP_STRUCT__entry( + __field(__u32, flags) + __field(__u32, tid) + ), + TP_fast_assign( + __entry->flags = flags; + __entry->tid = tid; + ), + TP_printk("flags=0x%x tid=0x%x", + __entry->flags, __entry->tid) +) + +#define DEFINE_SMB3_SHUTDOWN_EVENT(name) \ +DEFINE_EVENT(smb3_shutdown_class, smb3_##name, \ + TP_PROTO(__u32 flags, \ + __u32 tid), \ + TP_ARGS(flags, tid)) + +DEFINE_SMB3_SHUTDOWN_EVENT(shutdown_enter); +DEFINE_SMB3_SHUTDOWN_EVENT(shutdown_done); +DECLARE_EVENT_CLASS(smb3_shutdown_err_class, + TP_PROTO(int rc, + __u32 flags, + __u32 tid), + TP_ARGS(rc, flags, tid), + TP_STRUCT__entry( + __field(int, rc) + __field(__u32, flags) + __field(__u32, tid) + ), + TP_fast_assign( + __entry->rc = rc; + __entry->flags = flags; + __entry->tid = tid; + ), + TP_printk("rc=%d flags=0x%x tid=0x%x", + __entry->rc, __entry->flags, __entry->tid) +) +#define DEFINE_SMB3_SHUTDOWN_ERR_EVENT(name) \ +DEFINE_EVENT(smb3_shutdown_err_class, smb3_##name, \ + TP_PROTO(int rc, \ + __u32 flags, \ + __u32 tid), \ + TP_ARGS(rc, flags, tid)) +DEFINE_SMB3_SHUTDOWN_ERR_EVENT(shutdown_err); DECLARE_EVENT_CLASS(smb3_credit_class, TP_PROTO(__u64 currmid, diff --git a/fs/smb/client/transport.c b/fs/smb/client/transport.c index adfe0d05870108..6e68aaf5bd2035 100644 --- a/fs/smb/client/transport.c +++ b/fs/smb/client/transport.c @@ -1289,7 +1289,7 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses, out: /* * This will dequeue all mids. After this it is important that the - * demultiplex_thread will not process any of these mids any futher. + * demultiplex_thread will not process any of these mids any further. * This is prevented above by using a noop callback that will not * wake this thread except for the very last PDU. */ diff --git a/fs/smb/common/smb2pdu.h b/fs/smb/common/smb2pdu.h index c3ee42188d252e..c769f9dbc0b467 100644 --- a/fs/smb/common/smb2pdu.h +++ b/fs/smb/common/smb2pdu.h @@ -1216,6 +1216,8 @@ struct create_context { ); __u8 Buffer[]; } __packed; +static_assert(offsetof(struct create_context, Buffer) == sizeof(struct create_context_hdr), + "struct member likely outside of __struct_group()"); struct smb2_create_req { struct smb2_hdr hdr; diff --git a/fs/smb/server/mgmt/share_config.c b/fs/smb/server/mgmt/share_config.c index e0a6b758094fc5..d8d03070ae44b4 100644 --- a/fs/smb/server/mgmt/share_config.c +++ b/fs/smb/server/mgmt/share_config.c @@ -15,6 +15,7 @@ #include "share_config.h" #include "user_config.h" #include "user_session.h" +#include "../connection.h" #include "../transport_ipc.h" #include "../misc.h" @@ -120,12 +121,13 @@ static int parse_veto_list(struct ksmbd_share_config *share, return 0; } -static struct ksmbd_share_config *share_config_request(struct unicode_map *um, +static struct ksmbd_share_config *share_config_request(struct ksmbd_work *work, const char *name) { struct ksmbd_share_config_response *resp; struct ksmbd_share_config *share = NULL; struct ksmbd_share_config *lookup; + struct unicode_map *um = work->conn->um; int ret; resp = ksmbd_ipc_share_config_request(name); @@ -181,7 +183,14 @@ static struct ksmbd_share_config *share_config_request(struct unicode_map *um, KSMBD_SHARE_CONFIG_VETO_LIST(resp), resp->veto_list_sz); if (!ret && share->path) { + if (__ksmbd_override_fsids(work, share)) { + kill_share(share); + share = NULL; + goto out; + } + ret = kern_path(share->path, 0, &share->vfs_path); + ksmbd_revert_fsids(work); if (ret) { ksmbd_debug(SMB, "failed to access '%s'\n", share->path); @@ -214,7 +223,7 @@ static struct ksmbd_share_config *share_config_request(struct unicode_map *um, return share; } -struct ksmbd_share_config *ksmbd_share_config_get(struct unicode_map *um, +struct ksmbd_share_config *ksmbd_share_config_get(struct ksmbd_work *work, const char *name) { struct ksmbd_share_config *share; @@ -227,7 +236,7 @@ struct ksmbd_share_config *ksmbd_share_config_get(struct unicode_map *um, if (share) return share; - return share_config_request(um, name); + return share_config_request(work, name); } bool ksmbd_share_veto_filename(struct ksmbd_share_config *share, diff --git a/fs/smb/server/mgmt/share_config.h b/fs/smb/server/mgmt/share_config.h index 5f591751b92365..d4ac2dd4de2040 100644 --- a/fs/smb/server/mgmt/share_config.h +++ b/fs/smb/server/mgmt/share_config.h @@ -11,6 +11,8 @@ #include #include +struct ksmbd_work; + struct ksmbd_share_config { char *name; char *path; @@ -68,7 +70,7 @@ static inline void ksmbd_share_config_put(struct ksmbd_share_config *share) __ksmbd_share_config_put(share); } -struct ksmbd_share_config *ksmbd_share_config_get(struct unicode_map *um, +struct ksmbd_share_config *ksmbd_share_config_get(struct ksmbd_work *work, const char *name); bool ksmbd_share_veto_filename(struct ksmbd_share_config *share, const char *filename); diff --git a/fs/smb/server/mgmt/tree_connect.c b/fs/smb/server/mgmt/tree_connect.c index d2c81a8a11dda1..94a52a75014a43 100644 --- a/fs/smb/server/mgmt/tree_connect.c +++ b/fs/smb/server/mgmt/tree_connect.c @@ -16,17 +16,18 @@ #include "user_session.h" struct ksmbd_tree_conn_status -ksmbd_tree_conn_connect(struct ksmbd_conn *conn, struct ksmbd_session *sess, - const char *share_name) +ksmbd_tree_conn_connect(struct ksmbd_work *work, const char *share_name) { struct ksmbd_tree_conn_status status = {-ENOENT, NULL}; struct ksmbd_tree_connect_response *resp = NULL; struct ksmbd_share_config *sc; struct ksmbd_tree_connect *tree_conn = NULL; struct sockaddr *peer_addr; + struct ksmbd_conn *conn = work->conn; + struct ksmbd_session *sess = work->sess; int ret; - sc = ksmbd_share_config_get(conn->um, share_name); + sc = ksmbd_share_config_get(work, share_name); if (!sc) return status; @@ -61,7 +62,7 @@ ksmbd_tree_conn_connect(struct ksmbd_conn *conn, struct ksmbd_session *sess, struct ksmbd_share_config *new_sc; ksmbd_share_config_del(sc); - new_sc = ksmbd_share_config_get(conn->um, share_name); + new_sc = ksmbd_share_config_get(work, share_name); if (!new_sc) { pr_err("Failed to update stale share config\n"); status.ret = -ESTALE; diff --git a/fs/smb/server/mgmt/tree_connect.h b/fs/smb/server/mgmt/tree_connect.h index 6377a70b811c89..a42cdd05104114 100644 --- a/fs/smb/server/mgmt/tree_connect.h +++ b/fs/smb/server/mgmt/tree_connect.h @@ -13,6 +13,7 @@ struct ksmbd_share_config; struct ksmbd_user; struct ksmbd_conn; +struct ksmbd_work; enum { TREE_NEW = 0, @@ -50,8 +51,7 @@ static inline int test_tree_conn_flag(struct ksmbd_tree_connect *tree_conn, struct ksmbd_session; struct ksmbd_tree_conn_status -ksmbd_tree_conn_connect(struct ksmbd_conn *conn, struct ksmbd_session *sess, - const char *share_name); +ksmbd_tree_conn_connect(struct ksmbd_work *work, const char *share_name); void ksmbd_tree_connect_put(struct ksmbd_tree_connect *tcon); int ksmbd_tree_conn_disconnect(struct ksmbd_session *sess, diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c index 37a39ab4ee6543..2df1354288e68a 100644 --- a/fs/smb/server/smb2pdu.c +++ b/fs/smb/server/smb2pdu.c @@ -1955,7 +1955,7 @@ int smb2_tree_connect(struct ksmbd_work *work) ksmbd_debug(SMB, "tree connect request for tree %s treename %s\n", name, treename); - status = ksmbd_tree_conn_connect(conn, sess, name); + status = ksmbd_tree_conn_connect(work, name); if (status.ret == KSMBD_TREE_CONN_STATUS_OK) rsp->hdr.Id.SyncId.TreeId = cpu_to_le32(status.tree_conn->id); else @@ -5596,6 +5596,11 @@ int smb2_query_info(struct ksmbd_work *work) ksmbd_debug(SMB, "GOT query info request\n"); + if (ksmbd_override_fsids(work)) { + rc = -ENOMEM; + goto err_out; + } + switch (req->InfoType) { case SMB2_O_INFO_FILE: ksmbd_debug(SMB, "GOT SMB2_O_INFO_FILE\n"); @@ -5614,6 +5619,7 @@ int smb2_query_info(struct ksmbd_work *work) req->InfoType); rc = -EOPNOTSUPP; } + ksmbd_revert_fsids(work); if (!rc) { rsp->StructureSize = cpu_to_le16(9); @@ -5623,6 +5629,7 @@ int smb2_query_info(struct ksmbd_work *work) le32_to_cpu(rsp->OutputBufferLength)); } +err_out: if (rc < 0) { if (rc == -EACCES) rsp->hdr.Status = STATUS_ACCESS_DENIED; diff --git a/fs/smb/server/smb_common.c b/fs/smb/server/smb_common.c index 474dadf6b7b8bc..13818ecb6e1b2f 100644 --- a/fs/smb/server/smb_common.c +++ b/fs/smb/server/smb_common.c @@ -732,10 +732,10 @@ bool is_asterisk(char *p) return p && p[0] == '*'; } -int ksmbd_override_fsids(struct ksmbd_work *work) +int __ksmbd_override_fsids(struct ksmbd_work *work, + struct ksmbd_share_config *share) { struct ksmbd_session *sess = work->sess; - struct ksmbd_share_config *share = work->tcon->share_conf; struct cred *cred; struct group_info *gi; unsigned int uid; @@ -775,6 +775,11 @@ int ksmbd_override_fsids(struct ksmbd_work *work) return 0; } +int ksmbd_override_fsids(struct ksmbd_work *work) +{ + return __ksmbd_override_fsids(work, work->tcon->share_conf); +} + void ksmbd_revert_fsids(struct ksmbd_work *work) { const struct cred *cred; diff --git a/fs/smb/server/smb_common.h b/fs/smb/server/smb_common.h index f1092519c0c288..4a3148b0167f54 100644 --- a/fs/smb/server/smb_common.h +++ b/fs/smb/server/smb_common.h @@ -447,6 +447,8 @@ int ksmbd_extract_shortname(struct ksmbd_conn *conn, int ksmbd_smb_negotiate_common(struct ksmbd_work *work, unsigned int command); int ksmbd_smb_check_shared_mode(struct file *filp, struct ksmbd_file *curr_fp); +int __ksmbd_override_fsids(struct ksmbd_work *work, + struct ksmbd_share_config *share); int ksmbd_override_fsids(struct ksmbd_work *work); void ksmbd_revert_fsids(struct ksmbd_work *work); diff --git a/fs/squashfs/inode.c b/fs/squashfs/inode.c index 16bd693d0b3aa2..d5918eba27e371 100644 --- a/fs/squashfs/inode.c +++ b/fs/squashfs/inode.c @@ -279,8 +279,13 @@ int squashfs_read_inode(struct inode *inode, long long ino) if (err < 0) goto failed_read; - set_nlink(inode, le32_to_cpu(sqsh_ino->nlink)); inode->i_size = le32_to_cpu(sqsh_ino->symlink_size); + if (inode->i_size > PAGE_SIZE) { + ERROR("Corrupted symlink\n"); + return -EINVAL; + } + + set_nlink(inode, le32_to_cpu(sqsh_ino->nlink)); inode->i_op = &squashfs_symlink_inode_ops; inode_nohighmem(inode); inode->i_data.a_ops = &squashfs_symlink_aops; diff --git a/fs/tracefs/event_inode.c b/fs/tracefs/event_inode.c index 5d88c184f0fc15..01e99e98457ddb 100644 --- a/fs/tracefs/event_inode.c +++ b/fs/tracefs/event_inode.c @@ -112,7 +112,7 @@ static void release_ei(struct kref *ref) entry->release(entry->name, ei->data); } - call_rcu(&ei->rcu, free_ei_rcu); + call_srcu(&eventfs_srcu, &ei->rcu, free_ei_rcu); } static inline void put_ei(struct eventfs_inode *ei) @@ -736,7 +736,7 @@ struct eventfs_inode *eventfs_create_dir(const char *name, struct eventfs_inode /* Was the parent freed? */ if (list_empty(&ei->list)) { cleanup_ei(ei); - ei = NULL; + ei = ERR_PTR(-EBUSY); } return ei; } diff --git a/fs/tracefs/inode.c b/fs/tracefs/inode.c index 1028ab6d9a744b..1748dff58c3bc9 100644 --- a/fs/tracefs/inode.c +++ b/fs/tracefs/inode.c @@ -42,7 +42,7 @@ static struct inode *tracefs_alloc_inode(struct super_block *sb) struct tracefs_inode *ti; unsigned long flags; - ti = kmem_cache_alloc(tracefs_inode_cachep, GFP_KERNEL); + ti = alloc_inode_sb(sb, tracefs_inode_cachep, GFP_KERNEL); if (!ti) return NULL; @@ -53,15 +53,14 @@ static struct inode *tracefs_alloc_inode(struct super_block *sb) return &ti->vfs_inode; } -static void tracefs_free_inode_rcu(struct rcu_head *rcu) +static void tracefs_free_inode(struct inode *inode) { - struct tracefs_inode *ti; + struct tracefs_inode *ti = get_tracefs(inode); - ti = container_of(rcu, struct tracefs_inode, rcu); kmem_cache_free(tracefs_inode_cachep, ti); } -static void tracefs_free_inode(struct inode *inode) +static void tracefs_destroy_inode(struct inode *inode) { struct tracefs_inode *ti = get_tracefs(inode); unsigned long flags; @@ -69,8 +68,6 @@ static void tracefs_free_inode(struct inode *inode) spin_lock_irqsave(&tracefs_inode_lock, flags); list_del_rcu(&ti->list); spin_unlock_irqrestore(&tracefs_inode_lock, flags); - - call_rcu(&ti->rcu, tracefs_free_inode_rcu); } static ssize_t default_read_file(struct file *file, char __user *buf, @@ -437,6 +434,7 @@ static int tracefs_drop_inode(struct inode *inode) static const struct super_operations tracefs_super_operations = { .alloc_inode = tracefs_alloc_inode, .free_inode = tracefs_free_inode, + .destroy_inode = tracefs_destroy_inode, .drop_inode = tracefs_drop_inode, .statfs = simple_statfs, .show_options = tracefs_show_options, diff --git a/fs/tracefs/internal.h b/fs/tracefs/internal.h index f704d8348357ed..d83c2a25f288e0 100644 --- a/fs/tracefs/internal.h +++ b/fs/tracefs/internal.h @@ -10,10 +10,7 @@ enum { }; struct tracefs_inode { - union { - struct inode vfs_inode; - struct rcu_head rcu; - }; + struct inode vfs_inode; /* The below gets initialized with memset_after(ti, 0, vfs_inode) */ struct list_head list; unsigned long flags; diff --git a/fs/xfs/libxfs/xfs_quota_defs.h b/fs/xfs/libxfs/xfs_quota_defs.h index cb035da3f990b0..fb05f44f6c754a 100644 --- a/fs/xfs/libxfs/xfs_quota_defs.h +++ b/fs/xfs/libxfs/xfs_quota_defs.h @@ -56,7 +56,7 @@ typedef uint8_t xfs_dqtype_t; * And, of course, we also need to take into account the dquot log format item * used to describe each dquot. */ -#define XFS_DQUOT_LOGRES(mp) \ +#define XFS_DQUOT_LOGRES \ ((sizeof(struct xfs_dq_logformat) + sizeof(struct xfs_disk_dquot)) * 6) #define XFS_IS_QUOTA_ON(mp) ((mp)->m_qflags & XFS_ALL_QUOTA_ACCT) diff --git a/fs/xfs/libxfs/xfs_trans_resv.c b/fs/xfs/libxfs/xfs_trans_resv.c index 3dc8f785bf2947..45aaf169806aa5 100644 --- a/fs/xfs/libxfs/xfs_trans_resv.c +++ b/fs/xfs/libxfs/xfs_trans_resv.c @@ -338,11 +338,11 @@ xfs_calc_write_reservation( blksz); t1 += adj; t3 += adj; - return XFS_DQUOT_LOGRES(mp) + max3(t1, t2, t3); + return XFS_DQUOT_LOGRES + max3(t1, t2, t3); } t4 = xfs_calc_refcountbt_reservation(mp, 1); - return XFS_DQUOT_LOGRES(mp) + max(t4, max3(t1, t2, t3)); + return XFS_DQUOT_LOGRES + max(t4, max3(t1, t2, t3)); } unsigned int @@ -410,11 +410,11 @@ xfs_calc_itruncate_reservation( xfs_refcountbt_block_count(mp, 4), blksz); - return XFS_DQUOT_LOGRES(mp) + max3(t1, t2, t3); + return XFS_DQUOT_LOGRES + max3(t1, t2, t3); } t4 = xfs_calc_refcountbt_reservation(mp, 2); - return XFS_DQUOT_LOGRES(mp) + max(t4, max3(t1, t2, t3)); + return XFS_DQUOT_LOGRES + max(t4, max3(t1, t2, t3)); } unsigned int @@ -466,7 +466,7 @@ STATIC uint xfs_calc_rename_reservation( struct xfs_mount *mp) { - unsigned int overhead = XFS_DQUOT_LOGRES(mp); + unsigned int overhead = XFS_DQUOT_LOGRES; struct xfs_trans_resv *resp = M_RES(mp); unsigned int t1, t2, t3 = 0; @@ -577,7 +577,7 @@ STATIC uint xfs_calc_link_reservation( struct xfs_mount *mp) { - unsigned int overhead = XFS_DQUOT_LOGRES(mp); + unsigned int overhead = XFS_DQUOT_LOGRES; struct xfs_trans_resv *resp = M_RES(mp); unsigned int t1, t2, t3 = 0; @@ -641,7 +641,7 @@ STATIC uint xfs_calc_remove_reservation( struct xfs_mount *mp) { - unsigned int overhead = XFS_DQUOT_LOGRES(mp); + unsigned int overhead = XFS_DQUOT_LOGRES; struct xfs_trans_resv *resp = M_RES(mp); unsigned int t1, t2, t3 = 0; @@ -729,7 +729,7 @@ xfs_calc_icreate_reservation( struct xfs_mount *mp) { struct xfs_trans_resv *resp = M_RES(mp); - unsigned int overhead = XFS_DQUOT_LOGRES(mp); + unsigned int overhead = XFS_DQUOT_LOGRES; unsigned int t1, t2, t3 = 0; t1 = xfs_calc_icreate_resv_alloc(mp); @@ -747,7 +747,7 @@ STATIC uint xfs_calc_create_tmpfile_reservation( struct xfs_mount *mp) { - uint res = XFS_DQUOT_LOGRES(mp); + uint res = XFS_DQUOT_LOGRES; res += xfs_calc_icreate_resv_alloc(mp); return res + xfs_calc_iunlink_add_reservation(mp); @@ -829,7 +829,7 @@ STATIC uint xfs_calc_ifree_reservation( struct xfs_mount *mp) { - return XFS_DQUOT_LOGRES(mp) + + return XFS_DQUOT_LOGRES + xfs_calc_inode_res(mp, 1) + xfs_calc_buf_res(3, mp->m_sb.sb_sectsize) + xfs_calc_iunlink_remove_reservation(mp) + @@ -846,7 +846,7 @@ STATIC uint xfs_calc_ichange_reservation( struct xfs_mount *mp) { - return XFS_DQUOT_LOGRES(mp) + + return XFS_DQUOT_LOGRES + xfs_calc_inode_res(mp, 1) + xfs_calc_buf_res(1, mp->m_sb.sb_sectsize); @@ -955,7 +955,7 @@ STATIC uint xfs_calc_addafork_reservation( struct xfs_mount *mp) { - return XFS_DQUOT_LOGRES(mp) + + return XFS_DQUOT_LOGRES + xfs_calc_inode_res(mp, 1) + xfs_calc_buf_res(2, mp->m_sb.sb_sectsize) + xfs_calc_buf_res(1, mp->m_dir_geo->blksize) + @@ -1003,7 +1003,7 @@ STATIC uint xfs_calc_attrsetm_reservation( struct xfs_mount *mp) { - return XFS_DQUOT_LOGRES(mp) + + return XFS_DQUOT_LOGRES + xfs_calc_inode_res(mp, 1) + xfs_calc_buf_res(1, mp->m_sb.sb_sectsize) + xfs_calc_buf_res(XFS_DA_NODE_MAXDEPTH, XFS_FSB_TO_B(mp, 1)); @@ -1043,7 +1043,7 @@ STATIC uint xfs_calc_attrrm_reservation( struct xfs_mount *mp) { - return XFS_DQUOT_LOGRES(mp) + + return XFS_DQUOT_LOGRES + max((xfs_calc_inode_res(mp, 1) + xfs_calc_buf_res(XFS_DA_NODE_MAXDEPTH, XFS_FSB_TO_B(mp, 1)) + diff --git a/fs/xfs/scrub/agheader_repair.c b/fs/xfs/scrub/agheader_repair.c index 0dbc484b182f98..2f98d90d7fd66d 100644 --- a/fs/xfs/scrub/agheader_repair.c +++ b/fs/xfs/scrub/agheader_repair.c @@ -696,7 +696,7 @@ xrep_agfl_init_header( * step. */ xagb_bitmap_init(&af.used_extents); - af.agfl_bno = xfs_buf_to_agfl_bno(agfl_bp), + af.agfl_bno = xfs_buf_to_agfl_bno(agfl_bp); xagb_bitmap_walk(agfl_extents, xrep_agfl_fill, &af); error = xagb_bitmap_disunion(agfl_extents, &af.used_extents); if (error) diff --git a/fs/xfs/scrub/bmap.c b/fs/xfs/scrub/bmap.c index 24a15bf784f11b..5ab2ac53c92002 100644 --- a/fs/xfs/scrub/bmap.c +++ b/fs/xfs/scrub/bmap.c @@ -938,7 +938,13 @@ xchk_bmap( } break; case XFS_ATTR_FORK: - if (!xfs_has_attr(mp) && !xfs_has_attr2(mp)) + /* + * "attr" means that an attr fork was created at some point in + * the life of this filesystem. "attr2" means that inodes have + * variable-sized data/attr fork areas. Hence we only check + * attr here. + */ + if (!xfs_has_attr(mp)) xchk_ino_set_corrupt(sc, sc->ip->i_ino); break; default: diff --git a/fs/xfs/scrub/parent.c b/fs/xfs/scrub/parent.c index 733c410a22797a..91e7b51ce0680b 100644 --- a/fs/xfs/scrub/parent.c +++ b/fs/xfs/scrub/parent.c @@ -799,7 +799,7 @@ xchk_parent_pptr( } if (pp->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) - goto out_pp; + goto out_names; /* * Complain if the number of parent pointers doesn't match the link diff --git a/fs/xfs/scrub/trace.h b/fs/xfs/scrub/trace.h index 92ef4cdc486e90..c886d5d0eb021a 100644 --- a/fs/xfs/scrub/trace.h +++ b/fs/xfs/scrub/trace.h @@ -959,18 +959,16 @@ TRACE_EVENT(xfile_create, TP_STRUCT__entry( __field(dev_t, dev) __field(unsigned long, ino) - __array(char, pathname, 256) + __array(char, pathname, MAXNAMELEN) ), TP_fast_assign( - char pathname[257]; char *path; __entry->ino = file_inode(xf->file)->i_ino; - memset(pathname, 0, sizeof(pathname)); - path = file_path(xf->file, pathname, sizeof(pathname) - 1); + path = file_path(xf->file, __entry->pathname, MAXNAMELEN); if (IS_ERR(path)) - path = "(unknown)"; - strncpy(__entry->pathname, path, sizeof(__entry->pathname)); + strncpy(__entry->pathname, "(unknown)", + sizeof(__entry->pathname)); ), TP_printk("xfino 0x%lx path '%s'", __entry->ino, diff --git a/fs/xfs/xfs_attr_list.c b/fs/xfs/xfs_attr_list.c index 5c947e5ce8b881..7db38630487514 100644 --- a/fs/xfs/xfs_attr_list.c +++ b/fs/xfs/xfs_attr_list.c @@ -139,7 +139,7 @@ xfs_attr_shortform_list( sbp->name = sfe->nameval; sbp->namelen = sfe->namelen; /* These are bytes, and both on-disk, don't endian-flip */ - sbp->value = &sfe->nameval[sfe->namelen], + sbp->value = &sfe->nameval[sfe->namelen]; sbp->valuelen = sfe->valuelen; sbp->flags = sfe->flags; sbp->hash = xfs_attr_hashval(dp->i_mount, sfe->flags, diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c index 4e933db75b12b9..6b13666d4e9635 100644 --- a/fs/xfs/xfs_ioctl.c +++ b/fs/xfs/xfs_ioctl.c @@ -483,6 +483,17 @@ xfs_ioctl_setattr_xflags( /* Can't change realtime flag if any extents are allocated. */ if (ip->i_df.if_nextents || ip->i_delayed_blks) return -EINVAL; + + /* + * If S_DAX is enabled on this file, we can only switch the + * device if both support fsdax. We can't update S_DAX because + * there might be other threads walking down the access paths. + */ + if (IS_DAX(VFS_I(ip)) && + (mp->m_ddev_targp->bt_daxdev == NULL || + (mp->m_rtdev_targp && + mp->m_rtdev_targp->bt_daxdev == NULL))) + return -EINVAL; } if (rtflag) { diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index 5646d300b2861e..180ce697305a92 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h @@ -4715,20 +4715,18 @@ TRACE_EVENT(xmbuf_create, TP_STRUCT__entry( __field(dev_t, dev) __field(unsigned long, ino) - __array(char, pathname, 256) + __array(char, pathname, MAXNAMELEN) ), TP_fast_assign( - char pathname[257]; char *path; struct file *file = btp->bt_file; __entry->dev = btp->bt_mount->m_super->s_dev; __entry->ino = file_inode(file)->i_ino; - memset(pathname, 0, sizeof(pathname)); - path = file_path(file, pathname, sizeof(pathname) - 1); + path = file_path(file, __entry->pathname, MAXNAMELEN); if (IS_ERR(path)) - path = "(unknown)"; - strncpy(__entry->pathname, path, sizeof(__entry->pathname)); + strncpy(__entry->pathname, "(unknown)", + sizeof(__entry->pathname)); ), TP_printk("dev %d:%d xmino 0x%lx path '%s'", MAJOR(__entry->dev), MINOR(__entry->dev), diff --git a/fs/xfs/xfs_trans_ail.c b/fs/xfs/xfs_trans_ail.c index 0fafcc9f3dbe44..8ede9d099d1fea 100644 --- a/fs/xfs/xfs_trans_ail.c +++ b/fs/xfs/xfs_trans_ail.c @@ -644,7 +644,12 @@ xfsaild( set_freezable(); while (1) { - if (tout) + /* + * Long waits of 50ms or more occur when we've run out of items + * to push, so we only want uninterruptible state if we're + * actually blocked on something. + */ + if (tout && tout <= 20) set_current_state(TASK_KILLABLE|TASK_FREEZABLE); else set_current_state(TASK_INTERRUPTIBLE|TASK_FREEZABLE); diff --git a/fs/xfs/xfs_xattr.c b/fs/xfs/xfs_xattr.c index ab3d22f662f280..eaf849260bd672 100644 --- a/fs/xfs/xfs_xattr.c +++ b/fs/xfs/xfs_xattr.c @@ -110,7 +110,24 @@ xfs_attr_change( args->whichfork = XFS_ATTR_FORK; xfs_attr_sethash(args); - return xfs_attr_set(args, op, args->attr_filter & XFS_ATTR_ROOT); + /* + * Some xattrs must be resistant to allocation failure at ENOSPC, e.g. + * creating an inode with ACLs or security attributes requires the + * allocation of the xattr holding that information to succeed. Hence + * we allow xattrs in the VFS TRUSTED, SYSTEM, POSIX_ACL and SECURITY + * (LSM xattr) namespaces to dip into the reserve block pool to allow + * manipulation of these xattrs when at ENOSPC. These VFS xattr + * namespaces translate to the XFS_ATTR_ROOT and XFS_ATTR_SECURE on-disk + * namespaces. + * + * For most of these cases, these special xattrs will fit in the inode + * itself and so consume no extra space or only require temporary extra + * space while an overwrite is being made. Hence the use of the reserved + * pool is largely to avoid the worst case reservation from preventing + * the xattr from being created at ENOSPC. + */ + return xfs_attr_set(args, op, + args->attr_filter & (XFS_ATTR_ROOT | XFS_ATTR_SECURE)); } diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h index 80dc36f9d5274c..9f1c1d225e32c6 100644 --- a/include/acpi/acpixf.h +++ b/include/acpi/acpixf.h @@ -660,12 +660,9 @@ ACPI_EXTERNAL_RETURN_STATUS(acpi_status void *context)) ACPI_EXTERNAL_RETURN_STATUS(acpi_status acpi_execute_reg_methods(acpi_handle device, + u32 nax_depth, acpi_adr_space_type space_id)) -ACPI_EXTERNAL_RETURN_STATUS(acpi_status - acpi_execute_orphan_reg_method(acpi_handle device, - acpi_adr_space_type - space_id)) ACPI_EXTERNAL_RETURN_STATUS(acpi_status acpi_remove_address_space_handler(acpi_handle device, diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index ad6afc5c49183a..1ae44793132a8d 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -911,13 +911,12 @@ #define CON_INITCALL \ BOUNDED_SECTION_POST_LABEL(.con_initcall.init, __con_initcall, _start, _end) -#define RUNTIME_NAME(t,x) runtime_##t##_##x +#define NAMED_SECTION(name) \ + . = ALIGN(8); \ + name : AT(ADDR(name) - LOAD_OFFSET) \ + { BOUNDED_SECTION_PRE_LABEL(name, name, __start_, __stop_) } -#define RUNTIME_CONST(t,x) \ - . = ALIGN(8); \ - RUNTIME_NAME(t,x) : AT(ADDR(RUNTIME_NAME(t,x)) - LOAD_OFFSET) { \ - *(RUNTIME_NAME(t,x)); \ - } +#define RUNTIME_CONST(t,x) NAMED_SECTION(runtime_##t##_##x) /* Alignment must be consistent with (kunit_suite *) in include/kunit/test.h */ #define KUNIT_TABLE() \ diff --git a/include/drm/drm_buddy.h b/include/drm/drm_buddy.h index 2a74fa9d0ce554..9689a7c5dd36b2 100644 --- a/include/drm/drm_buddy.h +++ b/include/drm/drm_buddy.h @@ -27,6 +27,7 @@ #define DRM_BUDDY_CONTIGUOUS_ALLOCATION BIT(2) #define DRM_BUDDY_CLEAR_ALLOCATION BIT(3) #define DRM_BUDDY_CLEARED BIT(4) +#define DRM_BUDDY_TRIM_DISABLE BIT(5) struct drm_buddy_block { #define DRM_BUDDY_HEADER_OFFSET GENMASK_ULL(63, 12) @@ -155,6 +156,7 @@ int drm_buddy_alloc_blocks(struct drm_buddy *mm, unsigned long flags); int drm_buddy_block_trim(struct drm_buddy *mm, + u64 *start, u64 new_size, struct list_head *blocks); diff --git a/include/linux/bitmap.h b/include/linux/bitmap.h index 8c4768c44a01b3..d3b66d77df7a3c 100644 --- a/include/linux/bitmap.h +++ b/include/linux/bitmap.h @@ -270,6 +270,18 @@ static inline void bitmap_copy_clear_tail(unsigned long *dst, dst[nbits / BITS_PER_LONG] &= BITMAP_LAST_WORD_MASK(nbits); } +static inline void bitmap_copy_and_extend(unsigned long *to, + const unsigned long *from, + unsigned int count, unsigned int size) +{ + unsigned int copy = BITS_TO_LONGS(count); + + memcpy(to, from, copy * sizeof(long)); + if (count % BITS_PER_LONG) + to[copy - 1] &= BITMAP_LAST_WORD_MASK(count); + memset(to + copy, 0, bitmap_size(size) - copy * sizeof(long)); +} + /* * On 32-bit systems bitmaps are represented as u32 arrays internally. On LE64 * machines the order of hi and lo parts of numbers match the bitmap structure. diff --git a/include/linux/bpf_verifier.h b/include/linux/bpf_verifier.h index 6503c85b10a30a..7b776dae36e584 100644 --- a/include/linux/bpf_verifier.h +++ b/include/linux/bpf_verifier.h @@ -856,8 +856,8 @@ static inline u32 type_flag(u32 type) /* only use after check_attach_btf_id() */ static inline enum bpf_prog_type resolve_prog_type(const struct bpf_prog *prog) { - return (prog->type == BPF_PROG_TYPE_EXT && prog->aux->dst_prog) ? - prog->aux->dst_prog->type : prog->type; + return (prog->type == BPF_PROG_TYPE_EXT && prog->aux->saved_dst_prog_type) ? + prog->aux->saved_dst_prog_type : prog->type; } static inline bool bpf_prog_check_recur(const struct bpf_prog *prog) diff --git a/include/linux/compiler.h b/include/linux/compiler.h index 2594553bb30b10..2df665fa2964d3 100644 --- a/include/linux/compiler.h +++ b/include/linux/compiler.h @@ -296,6 +296,15 @@ static inline void *offset_to_ptr(const int *off) #define is_signed_type(type) (((type)(-1)) < (__force type)1) #define is_unsigned_type(type) (!is_signed_type(type)) +/* + * Useful shorthand for "is this condition known at compile-time?" + * + * Note that the condition may involve non-constant values, + * but the compiler may know enough about the details of the + * values to determine that the condition is statically true. + */ +#define statically_true(x) (__builtin_constant_p(x) && (x)) + /* * This is needed in functions which generate the stack canary, see * arch/x86/kernel/smpboot.c::start_secondary() for an example. diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h index 51ba681b915a97..9316c39260e0e4 100644 --- a/include/linux/cpuhotplug.h +++ b/include/linux/cpuhotplug.h @@ -100,7 +100,6 @@ enum cpuhp_state { CPUHP_WORKQUEUE_PREP, CPUHP_POWER_NUMA_PREPARE, CPUHP_HRTIMERS_PREPARE, - CPUHP_PROFILE_PREPARE, CPUHP_X2APIC_PREPARE, CPUHP_SMPCFD_PREPARE, CPUHP_RELAY_PREPARE, @@ -148,6 +147,7 @@ enum cpuhp_state { CPUHP_AP_IRQ_LOONGARCH_STARTING, CPUHP_AP_IRQ_SIFIVE_PLIC_STARTING, CPUHP_AP_IRQ_RISCV_IMSIC_STARTING, + CPUHP_AP_IRQ_RISCV_SBI_IPI_STARTING, CPUHP_AP_ARM_MVEBU_COHERENCY, CPUHP_AP_PERF_X86_AMD_UNCORE_STARTING, CPUHP_AP_PERF_X86_STARTING, diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h index 801a7e524113e7..53158de44b8378 100644 --- a/include/linux/cpumask.h +++ b/include/linux/cpumask.h @@ -1037,7 +1037,7 @@ void init_cpu_online(const struct cpumask *src); assign_bit(cpumask_check(cpu), cpumask_bits(mask), (val)) #define set_cpu_possible(cpu, possible) assign_cpu((cpu), &__cpu_possible_mask, (possible)) -#define set_cpu_enabled(cpu, enabled) assign_cpu((cpu), &__cpu_possible_mask, (enabled)) +#define set_cpu_enabled(cpu, enabled) assign_cpu((cpu), &__cpu_enabled_mask, (enabled)) #define set_cpu_present(cpu, present) assign_cpu((cpu), &__cpu_present_mask, (present)) #define set_cpu_active(cpu, active) assign_cpu((cpu), &__cpu_active_mask, (active)) #define set_cpu_dying(cpu, dying) assign_cpu((cpu), &__cpu_dying_mask, (dying)) diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h index 303fda54ef1791..989c94eddb2b4f 100644 --- a/include/linux/ethtool.h +++ b/include/linux/ethtool.h @@ -736,10 +736,10 @@ struct kernel_ethtool_ts_info { * @rxfh_key_space: same as @rxfh_indir_space, but for the key. * @rxfh_priv_size: size of the driver private data area the core should * allocate for an RSS context (in &struct ethtool_rxfh_context). - * @rxfh_max_context_id: maximum (exclusive) supported RSS context ID. If this - * is zero then the core may choose any (nonzero) ID, otherwise the core - * will only use IDs strictly less than this value, as the @rss_context - * argument to @create_rxfh_context and friends. + * @rxfh_max_num_contexts: maximum (exclusive) supported RSS context ID. + * If this is zero then the core may choose any (nonzero) ID, otherwise + * the core will only use IDs strictly less than this value, as the + * @rss_context argument to @create_rxfh_context and friends. * @supported_coalesce_params: supported types of interrupt coalescing. * @supported_ring_params: supported ring params. * @get_drvinfo: Report driver/device information. Modern drivers no @@ -954,7 +954,7 @@ struct ethtool_ops { u32 rxfh_indir_space; u16 rxfh_key_space; u16 rxfh_priv_size; - u32 rxfh_max_context_id; + u32 rxfh_max_num_contexts; u32 supported_coalesce_params; u32 supported_ring_params; void (*get_drvinfo)(struct net_device *, struct ethtool_drvinfo *); diff --git a/include/linux/file.h b/include/linux/file.h index 237931f20739f3..59b146a14dcad0 100644 --- a/include/linux/file.h +++ b/include/linux/file.h @@ -110,7 +110,7 @@ DEFINE_CLASS(get_unused_fd, int, if (_T >= 0) put_unused_fd(_T), * * f = dentry_open(&path, O_RDONLY, current_cred()); * if (IS_ERR(f)) - * return PTR_ERR(fd); + * return PTR_ERR(f); * * fd_install(fd, f); * return take_fd(fd); diff --git a/include/linux/fs.h b/include/linux/fs.h index fd34b5755c0b52..fb0426f349fc5c 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2392,6 +2392,9 @@ static inline void kiocb_clone(struct kiocb *kiocb, struct kiocb *kiocb_src, * * I_PINNING_FSCACHE_WB Inode is pinning an fscache object for writeback. * + * I_LRU_ISOLATING Inode is pinned being isolated from LRU without holding + * i_count. + * * Q: What is the difference between I_WILL_FREE and I_FREEING? */ #define I_DIRTY_SYNC (1 << 0) @@ -2415,6 +2418,8 @@ static inline void kiocb_clone(struct kiocb *kiocb, struct kiocb *kiocb_src, #define I_DONTCACHE (1 << 16) #define I_SYNC_QUEUED (1 << 17) #define I_PINNING_NETFS_WB (1 << 18) +#define __I_LRU_ISOLATING 19 +#define I_LRU_ISOLATING (1 << __I_LRU_ISOLATING) #define I_DIRTY_INODE (I_DIRTY_SYNC | I_DIRTY_DATASYNC) #define I_DIRTY (I_DIRTY_INODE | I_DIRTY_PAGES) diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h index c9bf68c239a011..45bf05ad5c53a1 100644 --- a/include/linux/hugetlb.h +++ b/include/linux/hugetlb.h @@ -944,10 +944,37 @@ static inline bool htlb_allow_alloc_fallback(int reason) static inline spinlock_t *huge_pte_lockptr(struct hstate *h, struct mm_struct *mm, pte_t *pte) { - if (huge_page_size(h) == PMD_SIZE) + const unsigned long size = huge_page_size(h); + + VM_WARN_ON(size == PAGE_SIZE); + + /* + * hugetlb must use the exact same PT locks as core-mm page table + * walkers would. When modifying a PTE table, hugetlb must take the + * PTE PT lock, when modifying a PMD table, hugetlb must take the PMD + * PT lock etc. + * + * The expectation is that any hugetlb folio smaller than a PMD is + * always mapped into a single PTE table and that any hugetlb folio + * smaller than a PUD (but at least as big as a PMD) is always mapped + * into a single PMD table. + * + * If that does not hold for an architecture, then that architecture + * must disable split PT locks such that all *_lockptr() functions + * will give us the same result: the per-MM PT lock. + * + * Note that with e.g., CONFIG_PGTABLE_LEVELS=2 where + * PGDIR_SIZE==P4D_SIZE==PUD_SIZE==PMD_SIZE, we'd use pud_lockptr() + * and core-mm would use pmd_lockptr(). However, in such configurations + * split PMD locks are disabled -- they don't make sense on a single + * PGDIR page table -- and the end result is the same. + */ + if (size >= PUD_SIZE) + return pud_lockptr(mm, (pud_t *) pte); + else if (size >= PMD_SIZE || IS_ENABLED(CONFIG_HIGHPTE)) return pmd_lockptr(mm, (pmd_t *) pte); - VM_BUG_ON(huge_page_size(h) == PAGE_SIZE); - return &mm->page_table_lock; + /* pte_alloc_huge() only applies with !CONFIG_HIGHPTE */ + return ptep_lockptr(mm, pte); } #ifndef hugepages_supported diff --git a/include/linux/i2c.h b/include/linux/i2c.h index 07e33bbc9256dd..377def4972985c 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -1066,7 +1066,7 @@ static inline int of_i2c_get_board_info(struct device *dev, struct acpi_resource; struct acpi_resource_i2c_serialbus; -#if IS_ENABLED(CONFIG_ACPI) +#if IS_REACHABLE(CONFIG_ACPI) && IS_REACHABLE(CONFIG_I2C) bool i2c_acpi_get_i2c_resource(struct acpi_resource *ares, struct acpi_resource_i2c_serialbus **i2c); int i2c_acpi_client_count(struct acpi_device *adev); diff --git a/include/linux/iommu.h b/include/linux/iommu.h index 4d47f2c3331185..04cbdae0052eb2 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -795,8 +795,6 @@ extern int iommu_attach_device(struct iommu_domain *domain, struct device *dev); extern void iommu_detach_device(struct iommu_domain *domain, struct device *dev); -extern int iommu_sva_unbind_gpasid(struct iommu_domain *domain, - struct device *dev, ioasid_t pasid); extern struct iommu_domain *iommu_get_domain_for_dev(struct device *dev); extern struct iommu_domain *iommu_get_dma_domain(struct device *dev); extern int iommu_map(struct iommu_domain *domain, unsigned long iova, diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h index de6105f68fecdf..e432b6a12a32f9 100644 --- a/include/linux/irqdomain.h +++ b/include/linux/irqdomain.h @@ -291,7 +291,12 @@ struct irq_domain_chip_generic_info; * @hwirq_max: Maximum number of interrupts supported by controller * @direct_max: Maximum value of direct maps; * Use ~0 for no limit; 0 for no direct mapping + * @hwirq_base: The first hardware interrupt number (legacy domains only) + * @virq_base: The first Linux interrupt number for legacy domains to + * immediately associate the interrupts after domain creation * @bus_token: Domain bus token + * @name_suffix: Optional name suffix to avoid collisions when multiple + * domains are added using same fwnode * @ops: Domain operation callbacks * @host_data: Controller private data pointer * @dgc_info: Geneneric chip information structure pointer used to @@ -307,7 +312,10 @@ struct irq_domain_info { unsigned int size; irq_hw_number_t hwirq_max; int direct_max; + unsigned int hwirq_base; + unsigned int virq_base; enum irq_domain_bus_token bus_token; + const char *name_suffix; const struct irq_domain_ops *ops; void *host_data; #ifdef CONFIG_IRQ_DOMAIN_HIERARCHY diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index 689e8be873a755..b23c6d48392f7c 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h @@ -715,6 +715,13 @@ static inline bool kvm_arch_has_private_mem(struct kvm *kvm) } #endif +#ifndef kvm_arch_has_readonly_mem +static inline bool kvm_arch_has_readonly_mem(struct kvm *kvm) +{ + return IS_ENABLED(CONFIG_HAVE_KVM_READONLY_MEM); +} +#endif + struct kvm_memslots { u64 generation; atomic_long_t last_used_slot; @@ -2414,7 +2421,7 @@ static inline unsigned long kvm_get_memory_attributes(struct kvm *kvm, gfn_t gfn } bool kvm_range_has_memory_attributes(struct kvm *kvm, gfn_t start, gfn_t end, - unsigned long attrs); + unsigned long mask, unsigned long attrs); bool kvm_arch_pre_set_memory_attributes(struct kvm *kvm, struct kvm_gfn_range *range); bool kvm_arch_post_set_memory_attributes(struct kvm *kvm, @@ -2445,11 +2452,11 @@ static inline int kvm_gmem_get_pfn(struct kvm *kvm, } #endif /* CONFIG_KVM_PRIVATE_MEM */ -#ifdef CONFIG_HAVE_KVM_GMEM_PREPARE +#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_PREPARE int kvm_arch_gmem_prepare(struct kvm *kvm, gfn_t gfn, kvm_pfn_t pfn, int max_order); -bool kvm_arch_gmem_prepare_needed(struct kvm *kvm); #endif +#ifdef CONFIG_KVM_GENERIC_PRIVATE_MEM /** * kvm_gmem_populate() - Populate/prepare a GPA range with guest data * @@ -2476,8 +2483,9 @@ typedef int (*kvm_gmem_populate_cb)(struct kvm *kvm, gfn_t gfn, kvm_pfn_t pfn, long kvm_gmem_populate(struct kvm *kvm, gfn_t gfn, void __user *src, long npages, kvm_gmem_populate_cb post_populate, void *opaque); +#endif -#ifdef CONFIG_HAVE_KVM_GMEM_INVALIDATE +#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_INVALIDATE void kvm_arch_gmem_invalidate(kvm_pfn_t start, kvm_pfn_t end); #endif diff --git a/include/linux/minmax.h b/include/linux/minmax.h index 9c2848abc80496..98008dd92153db 100644 --- a/include/linux/minmax.h +++ b/include/linux/minmax.h @@ -26,19 +26,63 @@ #define __typecheck(x, y) \ (!!(sizeof((typeof(x) *)1 == (typeof(y) *)1))) -/* is_signed_type() isn't a constexpr for pointer types */ -#define __is_signed(x) \ - __builtin_choose_expr(__is_constexpr(is_signed_type(typeof(x))), \ - is_signed_type(typeof(x)), 0) +/* + * __sign_use for integer expressions: + * bit #0 set if ok for unsigned comparisons + * bit #1 set if ok for signed comparisons + * + * In particular, statically non-negative signed integer + * expressions are ok for both. + * + * NOTE! Unsigned types smaller than 'int' are implicitly + * converted to 'int' in expressions, and are accepted for + * signed conversions for now. This is debatable. + * + * Note that 'x' is the original expression, and 'ux' is + * the unique variable that contains the value. + * + * We use 'ux' for pure type checking, and 'x' for when + * we need to look at the value (but without evaluating + * it for side effects! Careful to only ever evaluate it + * with sizeof() or __builtin_constant_p() etc). + * + * Pointers end up being checked by the normal C type + * rules at the actual comparison, and these expressions + * only need to be careful to not cause warnings for + * pointer use. + */ +#define __signed_type_use(x,ux) (2+__is_nonneg(x,ux)) +#define __unsigned_type_use(x,ux) (1+2*(sizeof(ux)<4)) +#define __sign_use(x,ux) (is_signed_type(typeof(ux))? \ + __signed_type_use(x,ux):__unsigned_type_use(x,ux)) -/* True for a non-negative signed int constant */ -#define __is_noneg_int(x) \ - (__builtin_choose_expr(__is_constexpr(x) && __is_signed(x), x, -1) >= 0) +/* + * To avoid warnings about casting pointers to integers + * of different sizes, we need that special sign type. + * + * On 64-bit we can just always use 'long', since any + * integer or pointer type can just be cast to that. + * + * This does not work for 128-bit signed integers since + * the cast would truncate them, but we do not use s128 + * types in the kernel (we do use 'u128', but they will + * be handled by the !is_signed_type() case). + * + * NOTE! The cast is there only to avoid any warnings + * from when values that aren't signed integer types. + */ +#ifdef CONFIG_64BIT + #define __signed_type(ux) long +#else + #define __signed_type(ux) typeof(__builtin_choose_expr(sizeof(ux)>4,1LL,1L)) +#endif +#define __is_nonneg(x,ux) statically_true((__signed_type(ux))(x)>=0) + +#define __types_ok(x,y,ux,uy) \ + (__sign_use(x,ux) & __sign_use(y,uy)) -#define __types_ok(x, y) \ - (__is_signed(x) == __is_signed(y) || \ - __is_signed((x) + 0) == __is_signed((y) + 0) || \ - __is_noneg_int(x) || __is_noneg_int(y)) +#define __types_ok3(x,y,z,ux,uy,uz) \ + (__sign_use(x,ux) & __sign_use(y,uy) & __sign_use(z,uz)) #define __cmp_op_min < #define __cmp_op_max > @@ -51,34 +95,31 @@ #define __cmp_once(op, type, x, y) \ __cmp_once_unique(op, type, x, y, __UNIQUE_ID(x_), __UNIQUE_ID(y_)) -#define __careful_cmp_once(op, x, y) ({ \ - static_assert(__types_ok(x, y), \ - #op "(" #x ", " #y ") signedness error, fix types or consider u" #op "() before " #op "_t()"); \ - __cmp_once(op, __auto_type, x, y); }) +#define __careful_cmp_once(op, x, y, ux, uy) ({ \ + __auto_type ux = (x); __auto_type uy = (y); \ + BUILD_BUG_ON_MSG(!__types_ok(x,y,ux,uy), \ + #op"("#x", "#y") signedness error"); \ + __cmp(op, ux, uy); }) -#define __careful_cmp(op, x, y) \ - __builtin_choose_expr(__is_constexpr((x) - (y)), \ - __cmp(op, x, y), __careful_cmp_once(op, x, y)) +#define __careful_cmp(op, x, y) \ + __careful_cmp_once(op, x, y, __UNIQUE_ID(x_), __UNIQUE_ID(y_)) #define __clamp(val, lo, hi) \ ((val) >= (hi) ? (hi) : ((val) <= (lo) ? (lo) : (val))) -#define __clamp_once(val, lo, hi, unique_val, unique_lo, unique_hi) ({ \ - typeof(val) unique_val = (val); \ - typeof(lo) unique_lo = (lo); \ - typeof(hi) unique_hi = (hi); \ +#define __clamp_once(val, lo, hi, uval, ulo, uhi) ({ \ + __auto_type uval = (val); \ + __auto_type ulo = (lo); \ + __auto_type uhi = (hi); \ static_assert(__builtin_choose_expr(__is_constexpr((lo) > (hi)), \ (lo) <= (hi), true), \ "clamp() low limit " #lo " greater than high limit " #hi); \ - static_assert(__types_ok(val, lo), "clamp() 'lo' signedness error"); \ - static_assert(__types_ok(val, hi), "clamp() 'hi' signedness error"); \ - __clamp(unique_val, unique_lo, unique_hi); }) + BUILD_BUG_ON_MSG(!__types_ok3(val,lo,hi,uval,ulo,uhi), \ + "clamp("#val", "#lo", "#hi") signedness error"); \ + __clamp(uval, ulo, uhi); }) -#define __careful_clamp(val, lo, hi) ({ \ - __builtin_choose_expr(__is_constexpr((val) - (lo) + (hi)), \ - __clamp(val, lo, hi), \ - __clamp_once(val, lo, hi, __UNIQUE_ID(__val), \ - __UNIQUE_ID(__lo), __UNIQUE_ID(__hi))); }) +#define __careful_clamp(val, lo, hi) \ + __clamp_once(val, lo, hi, __UNIQUE_ID(v_), __UNIQUE_ID(l_), __UNIQUE_ID(h_)) /** * min - return minimum of two values of the same or compatible types @@ -111,13 +152,20 @@ #define umax(x, y) \ __careful_cmp(max, (x) + 0u + 0ul + 0ull, (y) + 0u + 0ul + 0ull) +#define __careful_op3(op, x, y, z, ux, uy, uz) ({ \ + __auto_type ux = (x); __auto_type uy = (y);__auto_type uz = (z);\ + BUILD_BUG_ON_MSG(!__types_ok3(x,y,z,ux,uy,uz), \ + #op"3("#x", "#y", "#z") signedness error"); \ + __cmp(op, ux, __cmp(op, uy, uz)); }) + /** * min3 - return minimum of three values * @x: first value * @y: second value * @z: third value */ -#define min3(x, y, z) min((typeof(x))min(x, y), z) +#define min3(x, y, z) \ + __careful_op3(min, x, y, z, __UNIQUE_ID(x_), __UNIQUE_ID(y_), __UNIQUE_ID(z_)) /** * max3 - return maximum of three values @@ -125,7 +173,8 @@ * @y: second value * @z: third value */ -#define max3(x, y, z) max((typeof(x))max(x, y), z) +#define max3(x, y, z) \ + __careful_op3(max, x, y, z, __UNIQUE_ID(x_), __UNIQUE_ID(y_), __UNIQUE_ID(z_)) /** * min_not_zero - return the minimum that is _not_ zero, unless both are zero @@ -277,6 +326,8 @@ static inline bool in_range32(u32 val, u32 start, u32 len) * Use these carefully: no type checking, and uses the arguments * multiple times. Use for obvious constants only. */ +#define MIN(a,b) __cmp(min,a,b) +#define MAX(a,b) __cmp(max,a,b) #define MIN_T(type,a,b) __cmp(min,(type)(a),(type)(b)) #define MAX_T(type,a,b) __cmp(max,(type)(a),(type)(b)) diff --git a/include/linux/mm.h b/include/linux/mm.h index c4b238a20b76e9..6549d0979b28f9 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -2920,6 +2920,13 @@ static inline spinlock_t *pte_lockptr(struct mm_struct *mm, pmd_t *pmd) return ptlock_ptr(page_ptdesc(pmd_page(*pmd))); } +static inline spinlock_t *ptep_lockptr(struct mm_struct *mm, pte_t *pte) +{ + BUILD_BUG_ON(IS_ENABLED(CONFIG_HIGHPTE)); + BUILD_BUG_ON(MAX_PTRS_PER_PTE * sizeof(pte_t) > PAGE_SIZE); + return ptlock_ptr(virt_to_ptdesc(pte)); +} + static inline bool ptlock_init(struct ptdesc *ptdesc) { /* @@ -2944,6 +2951,10 @@ static inline spinlock_t *pte_lockptr(struct mm_struct *mm, pmd_t *pmd) { return &mm->page_table_lock; } +static inline spinlock_t *ptep_lockptr(struct mm_struct *mm, pte_t *pte) +{ + return &mm->page_table_lock; +} static inline void ptlock_cache_init(void) {} static inline bool ptlock_init(struct ptdesc *ptdesc) { return true; } static inline void ptlock_free(struct ptdesc *ptdesc) {} diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index 41458892bc8a34..1dc6248feb8324 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -220,8 +220,6 @@ enum node_stat_item { PGDEMOTE_KSWAPD, PGDEMOTE_DIRECT, PGDEMOTE_KHUGEPAGED, - NR_MEMMAP, /* page metadata allocated through buddy allocator */ - NR_MEMMAP_BOOT, /* page metadata allocated through boot allocator */ NR_VM_NODE_STAT_ITEMS }; diff --git a/include/linux/netfs.h b/include/linux/netfs.h index 5d0288938cc2dc..983816608f15d7 100644 --- a/include/linux/netfs.h +++ b/include/linux/netfs.h @@ -73,8 +73,6 @@ struct netfs_inode { #define NETFS_ICTX_ODIRECT 0 /* The file has DIO in progress */ #define NETFS_ICTX_UNBUFFERED 1 /* I/O should not use the pagecache */ #define NETFS_ICTX_WRITETHROUGH 2 /* Write-through caching */ -#define NETFS_ICTX_USE_PGPRIV2 31 /* [DEPRECATED] Use PG_private_2 to mark - * write to cache on read */ }; /* @@ -269,7 +267,6 @@ struct netfs_io_request { #define NETFS_RREQ_DONT_UNLOCK_FOLIOS 3 /* Don't unlock the folios on completion */ #define NETFS_RREQ_FAILED 4 /* The request failed */ #define NETFS_RREQ_IN_PROGRESS 5 /* Unlocked when the request completes */ -#define NETFS_RREQ_WRITE_TO_CACHE 7 /* Need to write to the cache */ #define NETFS_RREQ_UPLOAD_TO_SERVER 8 /* Need to write to the server */ #define NETFS_RREQ_NONBLOCK 9 /* Don't block if possible (O_NONBLOCK) */ #define NETFS_RREQ_BLOCKED 10 /* We blocked */ diff --git a/include/linux/pgalloc_tag.h b/include/linux/pgalloc_tag.h index 18cd0c0c73d93d..207f0c83c8e975 100644 --- a/include/linux/pgalloc_tag.h +++ b/include/linux/pgalloc_tag.h @@ -43,6 +43,18 @@ static inline void put_page_tag_ref(union codetag_ref *ref) page_ext_put(page_ext_from_codetag_ref(ref)); } +static inline void clear_page_tag_ref(struct page *page) +{ + if (mem_alloc_profiling_enabled()) { + union codetag_ref *ref = get_page_tag_ref(page); + + if (ref) { + set_codetag_empty(ref); + put_page_tag_ref(ref); + } + } +} + static inline void pgalloc_tag_add(struct page *page, struct task_struct *task, unsigned int nr) { @@ -126,6 +138,7 @@ static inline void pgalloc_tag_sub_pages(struct alloc_tag *tag, unsigned int nr) static inline union codetag_ref *get_page_tag_ref(struct page *page) { return NULL; } static inline void put_page_tag_ref(union codetag_ref *ref) {} +static inline void clear_page_tag_ref(struct page *page) {} static inline void pgalloc_tag_add(struct page *page, struct task_struct *task, unsigned int nr) {} static inline void pgalloc_tag_sub(struct page *page, unsigned int nr) {} diff --git a/include/linux/profile.h b/include/linux/profile.h index 2fb487f61d12ab..3f53cdb0c27c1a 100644 --- a/include/linux/profile.h +++ b/include/linux/profile.h @@ -10,7 +10,6 @@ #define CPU_PROFILING 1 #define SCHED_PROFILING 2 -#define SLEEP_PROFILING 3 #define KVM_PROFILING 4 struct proc_dir_entry; diff --git a/include/linux/refcount.h b/include/linux/refcount.h index 59b3b752394d3c..35f039ecb27256 100644 --- a/include/linux/refcount.h +++ b/include/linux/refcount.h @@ -266,12 +266,12 @@ bool __refcount_sub_and_test(int i, refcount_t *r, int *oldp) if (oldp) *oldp = old; - if (old == i) { + if (old > 0 && old == i) { smp_acquire__after_ctrl_dep(); return true; } - if (unlikely(old < 0 || old - i < 0)) + if (unlikely(old <= 0 || old - i < 0)) refcount_warn_saturate(r, REFCOUNT_SUB_UAF); return false; diff --git a/include/linux/regmap.h b/include/linux/regmap.h index 122e38161acb8d..f9ccad32fc5cba 100644 --- a/include/linux/regmap.h +++ b/include/linux/regmap.h @@ -1521,6 +1521,9 @@ struct regmap_irq_chip_data; * struct regmap_irq_chip - Description of a generic regmap irq_chip. * * @name: Descriptive name for IRQ controller. + * @domain_suffix: Name suffix to be appended to end of IRQ domain name. Needed + * when multiple regmap-IRQ controllers are created from same + * device. * * @main_status: Base main status register address. For chips which have * interrupts arranged in separate sub-irq blocks with own IRQ @@ -1606,6 +1609,7 @@ struct regmap_irq_chip_data; */ struct regmap_irq_chip { const char *name; + const char *domain_suffix; unsigned int main_status; unsigned int num_main_status_bits; diff --git a/include/linux/ring_buffer.h b/include/linux/ring_buffer.h index 96d2140b471ede..fd35d4ec12e1d5 100644 --- a/include/linux/ring_buffer.h +++ b/include/linux/ring_buffer.h @@ -193,7 +193,6 @@ void ring_buffer_set_clock(struct trace_buffer *buffer, void ring_buffer_set_time_stamp_abs(struct trace_buffer *buffer, bool abs); bool ring_buffer_time_stamp_abs(struct trace_buffer *buffer); -size_t ring_buffer_nr_pages(struct trace_buffer *buffer, int cpu); size_t ring_buffer_nr_dirty_pages(struct trace_buffer *buffer, int cpu); struct buffer_data_read_page; diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index e4f3f3d30a0390..d47d5f14ff992f 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -902,12 +902,29 @@ extern int devm_spi_register_controller(struct device *dev, struct spi_controller *ctlr); extern void spi_unregister_controller(struct spi_controller *ctlr); -#if IS_ENABLED(CONFIG_ACPI) +#if IS_ENABLED(CONFIG_ACPI) && IS_ENABLED(CONFIG_SPI_MASTER) extern struct spi_controller *acpi_spi_find_controller_by_adev(struct acpi_device *adev); extern struct spi_device *acpi_spi_device_alloc(struct spi_controller *ctlr, struct acpi_device *adev, int index); int acpi_spi_count_resources(struct acpi_device *adev); +#else +static inline struct spi_controller *acpi_spi_find_controller_by_adev(struct acpi_device *adev) +{ + return NULL; +} + +static inline struct spi_device *acpi_spi_device_alloc(struct spi_controller *ctlr, + struct acpi_device *adev, + int index) +{ + return ERR_PTR(-ENODEV); +} + +static inline int acpi_spi_count_resources(struct acpi_device *adev) +{ + return 0; +} #endif /* diff --git a/include/linux/thermal.h b/include/linux/thermal.h index 25fbf960b474bd..b86ddca46b9e81 100644 --- a/include/linux/thermal.h +++ b/include/linux/thermal.h @@ -55,6 +55,7 @@ enum thermal_notify_event { THERMAL_TZ_BIND_CDEV, /* Cooling dev is bind to the thermal zone */ THERMAL_TZ_UNBIND_CDEV, /* Cooling dev is unbind from the thermal zone */ THERMAL_INSTANCE_WEIGHT_CHANGED, /* Thermal instance weight changed */ + THERMAL_TZ_RESUME, /* Thermal zone is resuming after system sleep */ }; /** diff --git a/include/linux/trace_events.h b/include/linux/trace_events.h index 9df3e2973626bc..42bedcddd5113e 100644 --- a/include/linux/trace_events.h +++ b/include/linux/trace_events.h @@ -680,7 +680,7 @@ struct trace_event_file { * caching and such. Which is mostly OK ;-) */ unsigned long flags; - atomic_t ref; /* ref count for opened files */ + refcount_t ref; /* ref count for opened files */ atomic_t sm_ref; /* soft-mode reference counter */ atomic_t tm_ref; /* trigger-mode reference counter */ }; @@ -880,7 +880,6 @@ do { \ struct perf_event; DECLARE_PER_CPU(struct pt_regs, perf_trace_regs); -DECLARE_PER_CPU(int, bpf_kprobe_override); extern int perf_trace_init(struct perf_event *event); extern void perf_trace_destroy(struct perf_event *event); diff --git a/include/linux/virtio.h b/include/linux/virtio.h index ecc5cb7b8c91ed..4b16844c6bc29a 100644 --- a/include/linux/virtio.h +++ b/include/linux/virtio.h @@ -10,6 +10,7 @@ #include #include #include +#include /** * struct virtqueue - a queue to register buffers for sending or receiving. @@ -109,6 +110,8 @@ struct virtio_admin_cmd { __le64 group_member_id; struct scatterlist *data_sg; struct scatterlist *result_sg; + struct completion completion; + int ret; }; /** diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h index ab4b9a3fef6ba1..169c7d367facb3 100644 --- a/include/linux/virtio_config.h +++ b/include/linux/virtio_config.h @@ -104,8 +104,6 @@ struct virtqueue_info { * Returns 0 on success or error status * If disable_vq_and_reset is set, then enable_vq_after_reset must also be * set. - * @create_avq: create admin virtqueue resource. - * @destroy_avq: destroy admin virtqueue resource. */ struct virtio_config_ops { void (*get)(struct virtio_device *vdev, unsigned offset, @@ -133,8 +131,6 @@ struct virtio_config_ops { struct virtio_shm_region *region, u8 id); int (*disable_vq_and_reset)(struct virtqueue *vq); int (*enable_vq_after_reset)(struct virtqueue *vq); - int (*create_avq)(struct virtio_device *vdev); - void (*destroy_avq)(struct virtio_device *vdev); }; /* If driver didn't advertise the feature, it will never appear. */ diff --git a/include/linux/virtio_net.h b/include/linux/virtio_net.h index d1d7825318c32d..6c395a2600e8d1 100644 --- a/include/linux/virtio_net.h +++ b/include/linux/virtio_net.h @@ -56,7 +56,6 @@ static inline int virtio_net_hdr_to_skb(struct sk_buff *skb, unsigned int thlen = 0; unsigned int p_off = 0; unsigned int ip_proto; - u64 ret, remainder, gso_size; if (hdr->gso_type != VIRTIO_NET_HDR_GSO_NONE) { switch (hdr->gso_type & ~VIRTIO_NET_HDR_GSO_ECN) { @@ -99,16 +98,6 @@ static inline int virtio_net_hdr_to_skb(struct sk_buff *skb, u32 off = __virtio16_to_cpu(little_endian, hdr->csum_offset); u32 needed = start + max_t(u32, thlen, off + sizeof(__sum16)); - if (hdr->gso_size) { - gso_size = __virtio16_to_cpu(little_endian, hdr->gso_size); - ret = div64_u64_rem(skb->len, gso_size, &remainder); - if (!(ret && (hdr->gso_size > needed) && - ((remainder > needed) || (remainder == 0)))) { - return -EINVAL; - } - skb_shinfo(skb)->tx_flags |= SKBFL_SHARED_FRAG; - } - if (!pskb_may_pull(skb, needed)) return -EINVAL; @@ -182,6 +171,11 @@ static inline int virtio_net_hdr_to_skb(struct sk_buff *skb, if (gso_type != SKB_GSO_UDP_L4) return -EINVAL; break; + case SKB_GSO_TCPV4: + case SKB_GSO_TCPV6: + if (skb->csum_offset != offsetof(struct tcphdr, check)) + return -EINVAL; + break; } /* Kernel has a special handling for GSO_BY_FRAGS. */ diff --git a/include/linux/vmstat.h b/include/linux/vmstat.h index 23cd179420363c..9eb77c9007e623 100644 --- a/include/linux/vmstat.h +++ b/include/linux/vmstat.h @@ -34,10 +34,13 @@ struct reclaim_stat { unsigned nr_lazyfree_fail; }; -enum writeback_stat_item { +/* Stat data for system wide items */ +enum vm_stat_item { NR_DIRTY_THRESHOLD, NR_DIRTY_BG_THRESHOLD, - NR_VM_WRITEBACK_STAT_ITEMS, + NR_MEMMAP_PAGES, /* page metadata allocated through buddy allocator */ + NR_MEMMAP_BOOT_PAGES, /* page metadata allocated through boot allocator */ + NR_VM_STAT_ITEMS, }; #ifdef CONFIG_VM_EVENT_COUNTERS @@ -514,21 +517,13 @@ static inline const char *lru_list_name(enum lru_list lru) return node_stat_name(NR_LRU_BASE + lru) + 3; // skip "nr_" } -static inline const char *writeback_stat_name(enum writeback_stat_item item) -{ - return vmstat_text[NR_VM_ZONE_STAT_ITEMS + - NR_VM_NUMA_EVENT_ITEMS + - NR_VM_NODE_STAT_ITEMS + - item]; -} - #if defined(CONFIG_VM_EVENT_COUNTERS) || defined(CONFIG_MEMCG) static inline const char *vm_event_name(enum vm_event_item item) { return vmstat_text[NR_VM_ZONE_STAT_ITEMS + NR_VM_NUMA_EVENT_ITEMS + NR_VM_NODE_STAT_ITEMS + - NR_VM_WRITEBACK_STAT_ITEMS + + NR_VM_STAT_ITEMS + item]; } #endif /* CONFIG_VM_EVENT_COUNTERS || CONFIG_MEMCG */ @@ -625,7 +620,6 @@ static inline void lruvec_stat_sub_folio(struct folio *folio, lruvec_stat_mod_folio(folio, idx, -folio_nr_pages(folio)); } -void __meminit mod_node_early_perpage_metadata(int nid, long delta); -void __meminit store_early_perpage_metadata(void); - +void memmap_boot_pages_add(long delta); +void memmap_pages_add(long delta); #endif /* _LINUX_VMSTAT_H */ diff --git a/include/net/af_vsock.h b/include/net/af_vsock.h index 535701efc1e5ce..24d970f7a4fa22 100644 --- a/include/net/af_vsock.h +++ b/include/net/af_vsock.h @@ -230,8 +230,12 @@ struct vsock_tap { int vsock_add_tap(struct vsock_tap *vt); int vsock_remove_tap(struct vsock_tap *vt); void vsock_deliver_tap(struct sk_buff *build_skb(void *opaque), void *opaque); +int __vsock_connectible_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, + int flags); int vsock_connectible_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, int flags); +int __vsock_dgram_recvmsg(struct socket *sock, struct msghdr *msg, + size_t len, int flags); int vsock_dgram_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, int flags); diff --git a/include/net/mana/mana.h b/include/net/mana/mana.h index 6439fd8b437b66..7caa334f48880e 100644 --- a/include/net/mana/mana.h +++ b/include/net/mana/mana.h @@ -275,6 +275,7 @@ struct mana_cq { /* NAPI data */ struct napi_struct napi; int work_done; + int work_done_since_doorbell; int budget; }; diff --git a/include/sound/aci.h b/include/sound/aci.h index 6ebbd4223f127f..36a761c9820de9 100644 --- a/include/sound/aci.h +++ b/include/sound/aci.h @@ -72,6 +72,7 @@ #define ACI_SET_EQ7 0x46 /* ... to Treble */ struct snd_miro_aci { + struct snd_card *card; unsigned long aci_port; int aci_vendor; int aci_product; diff --git a/include/sound/control.h b/include/sound/control.h index 13511c50825f69..e07f6b960641ff 100644 --- a/include/sound/control.h +++ b/include/sound/control.h @@ -140,9 +140,7 @@ int snd_ctl_remove_id(struct snd_card * card, struct snd_ctl_elem_id *id); int snd_ctl_rename_id(struct snd_card * card, struct snd_ctl_elem_id *src_id, struct snd_ctl_elem_id *dst_id); void snd_ctl_rename(struct snd_card *card, struct snd_kcontrol *kctl, const char *name); int snd_ctl_activate_id(struct snd_card *card, struct snd_ctl_elem_id *id, int active); -struct snd_kcontrol *snd_ctl_find_numid_locked(struct snd_card *card, unsigned int numid); struct snd_kcontrol *snd_ctl_find_numid(struct snd_card *card, unsigned int numid); -struct snd_kcontrol *snd_ctl_find_id_locked(struct snd_card *card, const struct snd_ctl_elem_id *id); struct snd_kcontrol *snd_ctl_find_id(struct snd_card *card, const struct snd_ctl_elem_id *id); /** @@ -167,29 +165,6 @@ snd_ctl_find_id_mixer(struct snd_card *card, const char *name) return snd_ctl_find_id(card, &id); } -/** - * snd_ctl_find_id_mixer_locked - find the control instance with the given name string - * @card: the card instance - * @name: the name string - * - * Finds the control instance with the given name and - * @SNDRV_CTL_ELEM_IFACE_MIXER. Other fields are set to zero. - * - * This is merely a wrapper to snd_ctl_find_id_locked(). - * The caller must down card->controls_rwsem before calling this function. - * - * Return: The pointer of the instance if found, or %NULL if not. - */ -static inline struct snd_kcontrol * -snd_ctl_find_id_mixer_locked(struct snd_card *card, const char *name) -{ - struct snd_ctl_elem_id id = {}; - - id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - strscpy(id.name, name, sizeof(id.name)); - return snd_ctl_find_id_locked(card, &id); -} - int snd_ctl_create(struct snd_card *card); int snd_ctl_register_ioctl(snd_kctl_ioctl_func_t fcn); diff --git a/include/sound/core.h b/include/sound/core.h index dfef0c9d4b9f7e..1f3f5dccd7364f 100644 --- a/include/sound/core.h +++ b/include/sound/core.h @@ -99,7 +99,7 @@ struct snd_card { struct device *ctl_dev; /* control device */ unsigned int last_numid; /* last used numeric ID */ struct rw_semaphore controls_rwsem; /* controls lock (list and values) */ - rwlock_t ctl_files_rwlock; /* ctl_files list lock */ + rwlock_t controls_rwlock; /* lock for lookup and ctl_files list */ int controls_count; /* count of all controls */ size_t user_ctl_alloc_size; // current memory allocation by user controls. struct list_head controls; /* all controls for this card */ @@ -345,45 +345,7 @@ void release_and_free_resource(struct resource *res); /* --- */ -/* sound printk debug levels */ -enum { - SND_PR_ALWAYS, - SND_PR_DEBUG, - SND_PR_VERBOSE, -}; - -#if defined(CONFIG_SND_DEBUG) || defined(CONFIG_SND_VERBOSE_PRINTK) -__printf(4, 5) -void __snd_printk(unsigned int level, const char *file, int line, - const char *format, ...); -#else -#define __snd_printk(level, file, line, format, ...) \ - printk(format, ##__VA_ARGS__) -#endif - -/** - * snd_printk - printk wrapper - * @fmt: format string - * - * Works like printk() but prints the file and the line of the caller - * when configured with CONFIG_SND_VERBOSE_PRINTK. - */ -#define snd_printk(fmt, ...) \ - __snd_printk(0, __FILE__, __LINE__, fmt, ##__VA_ARGS__) - #ifdef CONFIG_SND_DEBUG -/** - * snd_printd - debug printk - * @fmt: format string - * - * Works like snd_printk() for debugging purposes. - * Ignored when CONFIG_SND_DEBUG is not set. - */ -#define snd_printd(fmt, ...) \ - __snd_printk(1, __FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define _snd_printd(level, fmt, ...) \ - __snd_printk(level, __FILE__, __LINE__, fmt, ##__VA_ARGS__) - /** * snd_BUG - give a BUG warning message and stack trace * @@ -392,12 +354,6 @@ void __snd_printk(unsigned int level, const char *file, int line, */ #define snd_BUG() WARN(1, "BUG?\n") -/** - * snd_printd_ratelimit - Suppress high rates of output when - * CONFIG_SND_DEBUG is enabled. - */ -#define snd_printd_ratelimit() printk_ratelimit() - /** * snd_BUG_ON - debugging check macro * @cond: condition to evaluate @@ -409,11 +365,6 @@ void __snd_printk(unsigned int level, const char *file, int line, #else /* !CONFIG_SND_DEBUG */ -__printf(1, 2) -static inline void snd_printd(const char *format, ...) {} -__printf(2, 3) -static inline void _snd_printd(int level, const char *format, ...) {} - #define snd_BUG() do { } while (0) #define snd_BUG_ON(condition) ({ \ @@ -421,26 +372,8 @@ static inline void _snd_printd(int level, const char *format, ...) {} unlikely(__ret_warn_on); \ }) -static inline bool snd_printd_ratelimit(void) { return false; } - #endif /* CONFIG_SND_DEBUG */ -#ifdef CONFIG_SND_DEBUG_VERBOSE -/** - * snd_printdd - debug printk - * @format: format string - * - * Works like snd_printk() for debugging purposes. - * Ignored when CONFIG_SND_DEBUG_VERBOSE is not set. - */ -#define snd_printdd(format, ...) \ - __snd_printk(2, __FILE__, __LINE__, format, ##__VA_ARGS__) -#else -__printf(1, 2) -static inline void snd_printdd(const char *format, ...) {} -#endif - - #define SNDRV_OSS_VERSION ((3<<16)|(8<<8)|(1<<4)|(0)) /* 3.8.1a */ /* for easier backward-porting */ diff --git a/include/sound/cs35l56.h b/include/sound/cs35l56.h index a6aa112e57416c..a51acefa785f72 100644 --- a/include/sound/cs35l56.h +++ b/include/sound/cs35l56.h @@ -277,6 +277,11 @@ static inline int cs35l56_force_sync_asp1_registers_from_cache(struct cs35l56_ba return 0; } +static inline bool cs35l56_is_otp_register(unsigned int reg) +{ + return (reg >> 16) == 3; +} + extern struct regmap_config cs35l56_regmap_i2c; extern struct regmap_config cs35l56_regmap_spi; extern struct regmap_config cs35l56_regmap_sdw; diff --git a/include/sound/es1688.h b/include/sound/es1688.h index 099569c31fbb3b..425a3717d77a2e 100644 --- a/include/sound/es1688.h +++ b/include/sound/es1688.h @@ -17,6 +17,7 @@ #define ES1688_HW_UNDEF 0x0003 struct snd_es1688 { + struct snd_card *card; unsigned long port; /* port of ESS chip */ struct resource *res_port; unsigned long mpu_port; /* MPU-401 port of ESS chip */ diff --git a/include/sound/pcm.h b/include/sound/pcm.h index ac8f3aef920523..384032b6c59cdc 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h @@ -498,6 +498,9 @@ struct snd_pcm_substream { /* misc flags */ unsigned int hw_opened: 1; unsigned int managed_buffer_alloc:1; +#ifdef CONFIG_SND_PCM_XRUN_DEBUG + unsigned int xrun_counter; /* number of times xrun happens */ +#endif /* CONFIG_SND_PCM_XRUN_DEBUG */ }; #define SUBSTREAM_BUSY(substream) ((substream)->ref_count > 0) diff --git a/include/sound/seq_kernel.h b/include/sound/seq_kernel.h index c8621671fa70d0..00c32eed2124bf 100644 --- a/include/sound/seq_kernel.h +++ b/include/sound/seq_kernel.h @@ -86,10 +86,6 @@ static inline size_t snd_seq_event_packet_size(struct snd_seq_event *ev) /* interface for OSS emulation */ int snd_seq_set_queue_tempo(int client, struct snd_seq_queue_tempo *tempo); -/* port callback routines */ -void snd_port_init_callback(struct snd_seq_port_callback *p); -struct snd_seq_port_callback *snd_port_alloc_callback(void); - /* port attach/detach */ int snd_seq_event_port_attach(int client, struct snd_seq_port_callback *pcbp, int cap, int type, int midi_channels, int midi_voices, char *portname); diff --git a/include/sound/snd_wavefront.h b/include/sound/snd_wavefront.h index 55053557c898ef..27f7e8a477c244 100644 --- a/include/sound/snd_wavefront.h +++ b/include/sound/snd_wavefront.h @@ -137,8 +137,4 @@ extern int snd_wavefront_fx_ioctl (struct snd_hwdep *, extern int snd_wavefront_fx_open (struct snd_hwdep *, struct file *); extern int snd_wavefront_fx_release (struct snd_hwdep *, struct file *); -/* prefix in all snd_printk() delivered messages */ - -#define LOGNAME "WaveFront: " - #endif /* __SOUND_SND_WAVEFRONT_H__ */ diff --git a/include/sound/soc-card.h b/include/sound/soc-card.h index 1f4c39922d8250..ecc02e955279fd 100644 --- a/include/sound/soc-card.h +++ b/include/sound/soc-card.h @@ -30,8 +30,6 @@ static inline void snd_soc_card_mutex_unlock(struct snd_soc_card *card) struct snd_kcontrol *snd_soc_card_get_kcontrol(struct snd_soc_card *soc_card, const char *name); -struct snd_kcontrol *snd_soc_card_get_kcontrol_locked(struct snd_soc_card *soc_card, - const char *name); int snd_soc_card_jack_new(struct snd_soc_card *card, const char *id, int type, struct snd_soc_jack *jack); int snd_soc_card_jack_new_pins(struct snd_soc_card *card, const char *id, diff --git a/include/sound/soc-component.h b/include/sound/soc-component.h index bf2e381cd124b6..61534ac0edd1d8 100644 --- a/include/sound/soc-component.h +++ b/include/sound/soc-component.h @@ -464,9 +464,6 @@ int snd_soc_component_force_enable_pin_unlocked( /* component controls */ struct snd_kcontrol *snd_soc_component_get_kcontrol(struct snd_soc_component *component, const char * const ctl); -struct snd_kcontrol * -snd_soc_component_get_kcontrol_locked(struct snd_soc_component *component, - const char * const ctl); int snd_soc_component_notify_control(struct snd_soc_component *component, const char * const ctl); diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index bbb72ad4c95182..ab4e109fe71d22 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -240,8 +240,6 @@ int snd_soc_pcm_dai_new(struct snd_soc_pcm_runtime *rtd); int snd_soc_pcm_dai_prepare(struct snd_pcm_substream *substream); int snd_soc_pcm_dai_trigger(struct snd_pcm_substream *substream, int cmd, int rollback); -int snd_soc_pcm_dai_bespoke_trigger(struct snd_pcm_substream *substream, - int cmd); void snd_soc_pcm_dai_delay(struct snd_pcm_substream *substream, snd_pcm_sframes_t *cpu_delay, snd_pcm_sframes_t *codec_delay); @@ -345,8 +343,7 @@ struct snd_soc_dai_ops { */ int (*trigger)(struct snd_pcm_substream *, int, struct snd_soc_dai *); - int (*bespoke_trigger)(struct snd_pcm_substream *, int, - struct snd_soc_dai *); + /* * For hardware based FIFO caused delay reporting. * Optional. diff --git a/include/sound/soc-dpcm.h b/include/sound/soc-dpcm.h index ebd24753dd000b..773f2db8c31c82 100644 --- a/include/sound/soc-dpcm.h +++ b/include/sound/soc-dpcm.h @@ -58,7 +58,6 @@ enum snd_soc_dpcm_state { enum snd_soc_dpcm_trigger { SND_SOC_DPCM_TRIGGER_PRE = 0, SND_SOC_DPCM_TRIGGER_POST, - SND_SOC_DPCM_TRIGGER_BESPOKE, }; /* diff --git a/include/sound/soundfont.h b/include/sound/soundfont.h index 98ed98d89d6de0..8a40cc15f66db7 100644 --- a/include/sound/soundfont.h +++ b/include/sound/soundfont.h @@ -86,9 +86,11 @@ struct snd_sf_list { }; /* Prototypes for soundfont.c */ -int snd_soundfont_load(struct snd_sf_list *sflist, const void __user *data, +int snd_soundfont_load(struct snd_card *card, + struct snd_sf_list *sflist, const void __user *data, long count, int client); -int snd_soundfont_load_guspatch(struct snd_sf_list *sflist, const char __user *data, +int snd_soundfont_load_guspatch(struct snd_card *card, + struct snd_sf_list *sflist, const char __user *data, long count); int snd_soundfont_close_check(struct snd_sf_list *sflist, int client); diff --git a/include/sound/tas2781.h b/include/sound/tas2781.h index 18161d02a96f7c..dbda552398b5b9 100644 --- a/include/sound/tas2781.h +++ b/include/sound/tas2781.h @@ -81,11 +81,6 @@ struct tasdevice { bool is_loaderr; }; -struct tasdevice_irqinfo { - int irq_gpio; - int irq; -}; - struct calidata { unsigned char *data; unsigned long total_sz; @@ -93,7 +88,6 @@ struct calidata { struct tasdevice_priv { struct tasdevice tasdevice[TASDEVICE_MAX_CHANNELS]; - struct tasdevice_irqinfo irq_info; struct tasdevice_rca rcabin; struct calidata cali_data; struct tasdevice_fw *fmw; @@ -115,6 +109,7 @@ struct tasdevice_priv { unsigned int chip_id; unsigned int sysclk; + int irq; int cur_prog; int cur_conf; int fw_state; diff --git a/include/sound/ump.h b/include/sound/ump.h index 7f68056acdffed..532c2c3ea28e3c 100644 --- a/include/sound/ump.h +++ b/include/sound/ump.h @@ -18,6 +18,7 @@ struct snd_ump_group { unsigned int dir_bits; /* directions */ bool active; /* activeness */ bool valid; /* valid group (referred by blocks) */ + bool is_midi1; /* belongs to a MIDI1 FB */ char name[64]; /* group name */ }; @@ -122,6 +123,7 @@ static inline int snd_ump_attach_legacy_rawmidi(struct snd_ump_endpoint *ump, int snd_ump_receive_ump_val(struct snd_ump_endpoint *ump, u32 val); int snd_ump_switch_protocol(struct snd_ump_endpoint *ump, unsigned int protocol); +void snd_ump_update_group_attrs(struct snd_ump_endpoint *ump); /* * Some definitions for UMP diff --git a/include/sound/ump_convert.h b/include/sound/ump_convert.h index 28c364c63245d0..d099ae27f8491a 100644 --- a/include/sound/ump_convert.h +++ b/include/sound/ump_convert.h @@ -13,6 +13,7 @@ struct ump_cvt_to_ump_bank { unsigned char cc_nrpn_msb, cc_nrpn_lsb; unsigned char cc_data_msb, cc_data_lsb; unsigned char cc_bank_msb, cc_bank_lsb; + bool cc_data_msb_set, cc_data_lsb_set; }; /* context for converting from MIDI1 byte stream to UMP packet */ diff --git a/include/sound/vx_core.h b/include/sound/vx_core.h index 1ddd3036bdfc75..ca87fa6a813548 100644 --- a/include/sound/vx_core.h +++ b/include/sound/vx_core.h @@ -155,7 +155,6 @@ struct vx_core { unsigned int chip_status; unsigned int pcm_running; - struct device *dev; struct snd_hwdep *hwdep; struct vx_rmh irq_rmh; /* RMH used in interrupts */ diff --git a/include/trace/events/btrfs.h b/include/trace/events/btrfs.h index 246c0fbd582ee3..0a523023bdcc38 100644 --- a/include/trace/events/btrfs.h +++ b/include/trace/events/btrfs.h @@ -2383,6 +2383,14 @@ DEFINE_EVENT(btrfs__space_info_update, update_bytes_pinned, TP_ARGS(fs_info, sinfo, old, diff) ); +DEFINE_EVENT(btrfs__space_info_update, update_bytes_zone_unusable, + + TP_PROTO(const struct btrfs_fs_info *fs_info, + const struct btrfs_space_info *sinfo, u64 old, s64 diff), + + TP_ARGS(fs_info, sinfo, old, diff) +); + DECLARE_EVENT_CLASS(btrfs_raid56_bio, TP_PROTO(const struct btrfs_raid_bio *rbio, diff --git a/include/trace/events/mptcp.h b/include/trace/events/mptcp.h index 09e72215b9f9bb..085b749cdd97e6 100644 --- a/include/trace/events/mptcp.h +++ b/include/trace/events/mptcp.h @@ -34,7 +34,7 @@ TRACE_EVENT(mptcp_subflow_get_send, struct sock *ssk; __entry->active = mptcp_subflow_active(subflow); - __entry->backup = subflow->backup; + __entry->backup = subflow->backup || subflow->request_bkup; if (subflow->tcp_sock && sk_fullsock(subflow->tcp_sock)) __entry->free = sk_stream_memory_free(subflow->tcp_sock); diff --git a/include/trace/events/netfs.h b/include/trace/events/netfs.h index da23484268dfcf..606b4a0f92dae2 100644 --- a/include/trace/events/netfs.h +++ b/include/trace/events/netfs.h @@ -51,6 +51,7 @@ EM(netfs_rreq_trace_resubmit, "RESUBMT") \ EM(netfs_rreq_trace_set_pause, "PAUSE ") \ EM(netfs_rreq_trace_unlock, "UNLOCK ") \ + EM(netfs_rreq_trace_unlock_pgpriv2, "UNLCK-2") \ EM(netfs_rreq_trace_unmark, "UNMARK ") \ EM(netfs_rreq_trace_wait_ip, "WAIT-IP") \ EM(netfs_rreq_trace_wait_pause, "WT-PAUS") \ @@ -145,6 +146,7 @@ EM(netfs_folio_trace_clear_g, "clear-g") \ EM(netfs_folio_trace_clear_s, "clear-s") \ EM(netfs_folio_trace_copy_to_cache, "mark-copy") \ + EM(netfs_folio_trace_end_copy, "end-copy") \ EM(netfs_folio_trace_filled_gaps, "filled-gaps") \ EM(netfs_folio_trace_kill, "kill") \ EM(netfs_folio_trace_kill_cc, "kill-cc") \ diff --git a/include/uapi/asm-generic/unistd.h b/include/uapi/asm-generic/unistd.h index 985a262d0f9eee..5bf6148cac2b93 100644 --- a/include/uapi/asm-generic/unistd.h +++ b/include/uapi/asm-generic/unistd.h @@ -841,11 +841,8 @@ __SYSCALL(__NR_lsm_list_modules, sys_lsm_list_modules) #define __NR_mseal 462 __SYSCALL(__NR_mseal, sys_mseal) -#define __NR_uretprobe 463 -__SYSCALL(__NR_uretprobe, sys_uretprobe) - #undef __NR_syscalls -#define __NR_syscalls 464 +#define __NR_syscalls 463 /* * 32 bit systems traditionally used different diff --git a/include/uapi/linux/io_uring.h b/include/uapi/linux/io_uring.h index 2aaf7ee256ac42..adc2524fd8e3dc 100644 --- a/include/uapi/linux/io_uring.h +++ b/include/uapi/linux/io_uring.h @@ -421,7 +421,7 @@ enum io_uring_msg_ring_flags { * IO completion data structure (Completion Queue Entry) */ struct io_uring_cqe { - __u64 user_data; /* sqe->data submission passed back */ + __u64 user_data; /* sqe->user_data value passed back */ __s32 res; /* result code for this event */ __u32 flags; diff --git a/include/uapi/linux/nsfs.h b/include/uapi/linux/nsfs.h index b133211331f6a6..5fad3d0fcd7078 100644 --- a/include/uapi/linux/nsfs.h +++ b/include/uapi/linux/nsfs.h @@ -3,6 +3,7 @@ #define __LINUX_NSFS_H #include +#include #define NSIO 0xb7 @@ -16,7 +17,7 @@ /* Get owner UID (in the caller's user namespace) for a user namespace */ #define NS_GET_OWNER_UID _IO(NSIO, 0x4) /* Get the id for a mount namespace */ -#define NS_GET_MNTNS_ID _IO(NSIO, 0x5) +#define NS_GET_MNTNS_ID _IOR(NSIO, 0x5, __u64) /* Translate pid from target pid namespace into the caller's pid namespace. */ #define NS_GET_PID_FROM_PIDNS _IOR(NSIO, 0x6, int) /* Return thread-group leader id of pid in the callers pid namespace. */ diff --git a/include/uapi/linux/psp-sev.h b/include/uapi/linux/psp-sev.h index 2289b7c76c59aa..832c15d9155bdb 100644 --- a/include/uapi/linux/psp-sev.h +++ b/include/uapi/linux/psp-sev.h @@ -51,6 +51,7 @@ typedef enum { SEV_RET_INVALID_PLATFORM_STATE, SEV_RET_INVALID_GUEST_STATE, SEV_RET_INAVLID_CONFIG, + SEV_RET_INVALID_CONFIG = SEV_RET_INAVLID_CONFIG, SEV_RET_INVALID_LEN, SEV_RET_ALREADY_OWNED, SEV_RET_INVALID_CERTIFICATE, diff --git a/include/uapi/misc/fastrpc.h b/include/uapi/misc/fastrpc.h index 91583690bddc52..f33d914d8f4699 100644 --- a/include/uapi/misc/fastrpc.h +++ b/include/uapi/misc/fastrpc.h @@ -8,14 +8,11 @@ #define FASTRPC_IOCTL_ALLOC_DMA_BUFF _IOWR('R', 1, struct fastrpc_alloc_dma_buf) #define FASTRPC_IOCTL_FREE_DMA_BUFF _IOWR('R', 2, __u32) #define FASTRPC_IOCTL_INVOKE _IOWR('R', 3, struct fastrpc_invoke) -/* This ioctl is only supported with secure device nodes */ #define FASTRPC_IOCTL_INIT_ATTACH _IO('R', 4) #define FASTRPC_IOCTL_INIT_CREATE _IOWR('R', 5, struct fastrpc_init_create) #define FASTRPC_IOCTL_MMAP _IOWR('R', 6, struct fastrpc_req_mmap) #define FASTRPC_IOCTL_MUNMAP _IOWR('R', 7, struct fastrpc_req_munmap) -/* This ioctl is only supported with secure device nodes */ #define FASTRPC_IOCTL_INIT_ATTACH_SNS _IO('R', 8) -/* This ioctl is only supported with secure device nodes */ #define FASTRPC_IOCTL_INIT_CREATE_STATIC _IOWR('R', 9, struct fastrpc_init_create_static) #define FASTRPC_IOCTL_MEM_MAP _IOWR('R', 10, struct fastrpc_mem_map) #define FASTRPC_IOCTL_MEM_UNMAP _IOWR('R', 11, struct fastrpc_mem_unmap) diff --git a/include/uapi/sound/asequencer.h b/include/uapi/sound/asequencer.h index 39b37edcf81316..bc30c1f2a10945 100644 --- a/include/uapi/sound/asequencer.h +++ b/include/uapi/sound/asequencer.h @@ -461,6 +461,8 @@ struct snd_seq_remove_events { #define SNDRV_SEQ_PORT_FLG_TIMESTAMP (1<<1) #define SNDRV_SEQ_PORT_FLG_TIME_REAL (1<<2) +#define SNDRV_SEQ_PORT_FLG_IS_MIDI1 (1<<3) /* Keep MIDI 1.0 protocol */ + /* port direction */ #define SNDRV_SEQ_PORT_DIR_UNKNOWN 0 #define SNDRV_SEQ_PORT_DIR_INPUT 1 diff --git a/include/uapi/sound/asound.h b/include/uapi/sound/asound.h index 8bf7e8a0eb6f03..4cd513215bcd8f 100644 --- a/include/uapi/sound/asound.h +++ b/include/uapi/sound/asound.h @@ -869,7 +869,7 @@ struct snd_ump_block_info { * Timer section - /dev/snd/timer */ -#define SNDRV_TIMER_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 7) +#define SNDRV_TIMER_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 8) enum { SNDRV_TIMER_CLASS_NONE = -1, @@ -894,6 +894,7 @@ enum { #define SNDRV_TIMER_GLOBAL_RTC 1 /* unused */ #define SNDRV_TIMER_GLOBAL_HPET 2 #define SNDRV_TIMER_GLOBAL_HRTIMER 3 +#define SNDRV_TIMER_GLOBAL_UDRIVEN 4 /* info flags */ #define SNDRV_TIMER_FLG_SLAVE (1<<0) /* cannot be controlled */ @@ -974,6 +975,18 @@ struct snd_timer_status { }; #endif +/* + * This structure describes the userspace-driven timer. Such timers are purely virtual, + * and can only be triggered from software (for instance, by userspace application). + */ +struct snd_timer_uinfo { + /* To pretend being a normal timer, we need to know the resolution in ns. */ + __u64 resolution; + int fd; + unsigned int id; + unsigned char reserved[16]; +}; + #define SNDRV_TIMER_IOCTL_PVERSION _IOR('T', 0x00, int) #define SNDRV_TIMER_IOCTL_NEXT_DEVICE _IOWR('T', 0x01, struct snd_timer_id) #define SNDRV_TIMER_IOCTL_TREAD_OLD _IOW('T', 0x02, int) @@ -990,6 +1003,8 @@ struct snd_timer_status { #define SNDRV_TIMER_IOCTL_CONTINUE _IO('T', 0xa2) #define SNDRV_TIMER_IOCTL_PAUSE _IO('T', 0xa3) #define SNDRV_TIMER_IOCTL_TREAD64 _IOW('T', 0xa4, int) +#define SNDRV_TIMER_IOCTL_CREATE _IOWR('T', 0xa5, struct snd_timer_uinfo) +#define SNDRV_TIMER_IOCTL_TRIGGER _IO('T', 0xa6) #if __BITS_PER_LONG == 64 #define SNDRV_TIMER_IOCTL_TREAD SNDRV_TIMER_IOCTL_TREAD_OLD diff --git a/include/ufs/ufshcd.h b/include/ufs/ufshcd.h index a43b14276bc33d..cac0cdb9a916c7 100644 --- a/include/ufs/ufshcd.h +++ b/include/ufs/ufshcd.h @@ -1109,6 +1109,7 @@ struct ufs_hba { bool ext_iid_sup; bool scsi_host_added; bool mcq_sup; + bool lsdb_sup; bool mcq_enabled; struct ufshcd_res_info res[RES_MAX]; void __iomem *mcq_base; diff --git a/include/ufs/ufshci.h b/include/ufs/ufshci.h index 38fe97971a65fa..9917c7743d808c 100644 --- a/include/ufs/ufshci.h +++ b/include/ufs/ufshci.h @@ -77,6 +77,7 @@ enum { MASK_OUT_OF_ORDER_DATA_DELIVERY_SUPPORT = 0x02000000, MASK_UIC_DME_TEST_MODE_SUPPORT = 0x04000000, MASK_CRYPTO_SUPPORT = 0x10000000, + MASK_LSDB_SUPPORT = 0x20000000, MASK_MCQ_SUPPORT = 0x40000000, }; diff --git a/init/Kconfig b/init/Kconfig index a465ea9525bd59..5783a0b8751726 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -1902,6 +1902,7 @@ config RUST depends on !MODVERSIONS depends on !GCC_PLUGINS depends on !RANDSTRUCT + depends on !SHADOW_CALL_STACK depends on !DEBUG_INFO_BTF || PAHOLE_HAS_LANG_EXCLUDE help Enables Rust support in the kernel. @@ -1919,7 +1920,7 @@ config RUST config RUSTC_VERSION_TEXT string depends on RUST - default $(shell,command -v $(RUSTC) >/dev/null 2>&1 && $(RUSTC) --version || echo n) + default "$(shell,$(RUSTC) --version 2>/dev/null)" config BINDGEN_VERSION_TEXT string @@ -1927,7 +1928,7 @@ config BINDGEN_VERSION_TEXT # The dummy parameter `workaround-for-0.69.0` is required to support 0.69.0 # (https://github.com/rust-lang/rust-bindgen/pull/2678). It can be removed when # the minimum version is upgraded past that (0.69.1 already fixed the issue). - default $(shell,command -v $(BINDGEN) >/dev/null 2>&1 && $(BINDGEN) --version workaround-for-0.69.0 || echo n) + default "$(shell,$(BINDGEN) --version workaround-for-0.69.0 2>/dev/null)" # # Place an empty function call at each tracepoint site. Can be diff --git a/io_uring/napi.c b/io_uring/napi.c index 4fd6bb331e1ed9..1de1d4d629254c 100644 --- a/io_uring/napi.c +++ b/io_uring/napi.c @@ -26,7 +26,6 @@ static struct io_napi_entry *io_napi_hash_find(struct hlist_head *hash_list, hlist_for_each_entry_rcu(e, hash_list, node) { if (e->napi_id != napi_id) continue; - e->timeout = jiffies + NAPI_TIMEOUT; return e; } @@ -205,7 +204,6 @@ void io_napi_init(struct io_ring_ctx *ctx) void io_napi_free(struct io_ring_ctx *ctx) { struct io_napi_entry *e; - LIST_HEAD(napi_list); unsigned int i; spin_lock(&ctx->napi_lock); @@ -303,7 +301,7 @@ void __io_napi_busy_loop(struct io_ring_ctx *ctx, struct io_wait_queue *iowq) { iowq->napi_prefer_busy_poll = READ_ONCE(ctx->napi_prefer_busy_poll); - if (!(ctx->flags & IORING_SETUP_SQPOLL) && ctx->napi_enabled) + if (!(ctx->flags & IORING_SETUP_SQPOLL)) io_napi_blocking_busy_loop(ctx, iowq); } @@ -315,7 +313,6 @@ void __io_napi_busy_loop(struct io_ring_ctx *ctx, struct io_wait_queue *iowq) */ int io_napi_sqpoll_busy_poll(struct io_ring_ctx *ctx) { - LIST_HEAD(napi_list); bool is_stale = false; if (!READ_ONCE(ctx->napi_busy_poll_dt)) diff --git a/io_uring/napi.h b/io_uring/napi.h index 88f1c21d5548ff..27b88c3eb42894 100644 --- a/io_uring/napi.h +++ b/io_uring/napi.h @@ -55,7 +55,7 @@ static inline void io_napi_add(struct io_kiocb *req) struct io_ring_ctx *ctx = req->ctx; struct socket *sock; - if (!READ_ONCE(ctx->napi_busy_poll_dt)) + if (!READ_ONCE(ctx->napi_enabled)) return; sock = sock_from_file(req->file); diff --git a/io_uring/net.c b/io_uring/net.c index 594490a1389ba2..d08abcca89cc5b 100644 --- a/io_uring/net.c +++ b/io_uring/net.c @@ -601,17 +601,18 @@ int io_send(struct io_kiocb *req, unsigned int issue_flags) .iovs = &kmsg->fast_iov, .max_len = INT_MAX, .nr_iovs = 1, - .mode = KBUF_MODE_EXPAND, }; if (kmsg->free_iov) { arg.nr_iovs = kmsg->free_iov_nr; arg.iovs = kmsg->free_iov; - arg.mode |= KBUF_MODE_FREE; + arg.mode = KBUF_MODE_FREE; } if (!(sr->flags & IORING_RECVSEND_BUNDLE)) arg.nr_iovs = 1; + else + arg.mode |= KBUF_MODE_EXPAND; ret = io_buffers_select(req, &arg, issue_flags); if (unlikely(ret < 0)) @@ -623,6 +624,7 @@ int io_send(struct io_kiocb *req, unsigned int issue_flags) if (arg.iovs != &kmsg->fast_iov && arg.iovs != kmsg->free_iov) { kmsg->free_iov_nr = ret; kmsg->free_iov = arg.iovs; + req->flags |= REQ_F_NEED_CLEANUP; } } @@ -1094,6 +1096,7 @@ static int io_recv_buf_select(struct io_kiocb *req, struct io_async_msghdr *kmsg if (arg.iovs != &kmsg->fast_iov && arg.iovs != kmsg->free_iov) { kmsg->free_iov_nr = ret; kmsg->free_iov = arg.iovs; + req->flags |= REQ_F_NEED_CLEANUP; } } else { void __user *buf; diff --git a/io_uring/poll.c b/io_uring/poll.c index 0a8e02944689fa..1f63b60e85e7c0 100644 --- a/io_uring/poll.c +++ b/io_uring/poll.c @@ -347,6 +347,7 @@ static int io_poll_check_events(struct io_kiocb *req, struct io_tw_state *ts) v &= IO_POLL_REF_MASK; } while (atomic_sub_return(v, &req->poll_refs) & IO_POLL_REF_MASK); + io_napi_add(req); return IOU_POLL_NO_ACTION; } diff --git a/io_uring/sqpoll.c b/io_uring/sqpoll.c index b3722e5275e77e..3b50dc9586d14f 100644 --- a/io_uring/sqpoll.c +++ b/io_uring/sqpoll.c @@ -44,7 +44,7 @@ void io_sq_thread_unpark(struct io_sq_data *sqd) void io_sq_thread_park(struct io_sq_data *sqd) __acquires(&sqd->lock) { - WARN_ON_ONCE(sqd->thread == current); + WARN_ON_ONCE(data_race(sqd->thread) == current); atomic_inc(&sqd->park_pending); set_bit(IO_SQ_THREAD_SHOULD_PARK, &sqd->state); diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 4cb5441ad75fc5..d8520095ca030e 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -16884,8 +16884,9 @@ static bool stacksafe(struct bpf_verifier_env *env, struct bpf_func_state *old, spi = i / BPF_REG_SIZE; if (exact != NOT_EXACT && - old->stack[spi].slot_type[i % BPF_REG_SIZE] != - cur->stack[spi].slot_type[i % BPF_REG_SIZE]) + (i >= cur->allocated_stack || + old->stack[spi].slot_type[i % BPF_REG_SIZE] != + cur->stack[spi].slot_type[i % BPF_REG_SIZE])) return false; if (!(old->stack[spi].spilled_ptr.live & REG_LIVE_READ) diff --git a/kernel/cpu.c b/kernel/cpu.c index 1209ddaec026da..b1fd2a3db91a2e 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c @@ -2689,6 +2689,16 @@ int cpuhp_smt_disable(enum cpuhp_smt_control ctrlval) return ret; } +/** + * Check if the core a CPU belongs to is online + */ +#if !defined(topology_is_core_online) +static inline bool topology_is_core_online(unsigned int cpu) +{ + return true; +} +#endif + int cpuhp_smt_enable(void) { int cpu, ret = 0; @@ -2699,7 +2709,7 @@ int cpuhp_smt_enable(void) /* Skip online CPUs and CPUs on offline nodes */ if (cpu_online(cpu) || !node_online(cpu_to_node(cpu))) continue; - if (!cpu_smt_thread_allowed(cpu)) + if (!cpu_smt_thread_allowed(cpu) || !topology_is_core_online(cpu)) continue; ret = _cpu_up(cpu, 0, CPUHP_ONLINE); if (ret) diff --git a/kernel/crash_reserve.c b/kernel/crash_reserve.c index d3b4cd12bdd134..64d44a52c01147 100644 --- a/kernel/crash_reserve.c +++ b/kernel/crash_reserve.c @@ -423,7 +423,8 @@ void __init reserve_crashkernel_generic(char *cmdline, if (high && search_end == CRASH_ADDR_HIGH_MAX) { search_end = CRASH_ADDR_LOW_MAX; search_base = 0; - goto retry; + if (search_end != CRASH_ADDR_HIGH_MAX) + goto retry; } pr_warn("cannot allocate crashkernel (size:0x%llx)\n", crash_size); diff --git a/kernel/dma/debug.c b/kernel/dma/debug.c index a6e3792b15f8a5..d570535342cb78 100644 --- a/kernel/dma/debug.c +++ b/kernel/dma/debug.c @@ -416,8 +416,11 @@ static unsigned long long phys_addr(struct dma_debug_entry *entry) * dma_active_cacheline entry to track per event. dma_map_sg(), on the * other hand, consumes a single dma_debug_entry, but inserts 'nents' * entries into the tree. + * + * Use __GFP_NOWARN because the printk from an OOM, to netconsole, could end + * up right back in the DMA debugging code, leading to a deadlock. */ -static RADIX_TREE(dma_active_cacheline, GFP_ATOMIC); +static RADIX_TREE(dma_active_cacheline, GFP_ATOMIC | __GFP_NOWARN); static DEFINE_SPINLOCK(radix_lock); #define ACTIVE_CACHELINE_MAX_OVERLAP ((1 << RADIX_TREE_MAX_TAGS) - 1) #define CACHELINE_PER_PAGE_SHIFT (PAGE_SHIFT - L1_CACHE_SHIFT) diff --git a/kernel/events/core.c b/kernel/events/core.c index aa3450bdc2276c..c973e3c11e036f 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -9706,7 +9706,8 @@ static int __perf_event_overflow(struct perf_event *event, ret = __perf_event_account_interrupt(event, throttle); - if (event->prog && !bpf_overflow_handler(event, data, regs)) + if (event->prog && event->prog->type == BPF_PROG_TYPE_PERF_EVENT && + !bpf_overflow_handler(event, data, regs)) return ret; /* diff --git a/kernel/fork.c b/kernel/fork.c index cc760491f20127..18bdc87209d057 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -2053,11 +2053,24 @@ static int __pidfd_prepare(struct pid *pid, unsigned int flags, struct file **re */ int pidfd_prepare(struct pid *pid, unsigned int flags, struct file **ret) { - bool thread = flags & PIDFD_THREAD; - - if (!pid || !pid_has_task(pid, thread ? PIDTYPE_PID : PIDTYPE_TGID)) + if (!pid) return -EINVAL; + scoped_guard(rcu) { + struct task_struct *tsk; + + if (flags & PIDFD_THREAD) + tsk = pid_task(pid, PIDTYPE_PID); + else + tsk = pid_task(pid, PIDTYPE_TGID); + if (!tsk) + return -EINVAL; + + /* Don't create pidfds for kernel threads for now. */ + if (tsk->flags & PF_KTHREAD) + return -EINVAL; + } + return __pidfd_prepare(pid, flags, ret); } @@ -2403,6 +2416,12 @@ __latent_entropy struct task_struct *copy_process( if (clone_flags & CLONE_PIDFD) { int flags = (clone_flags & CLONE_THREAD) ? PIDFD_THREAD : 0; + /* Don't create pidfds for kernel threads for now. */ + if (args->kthread) { + retval = -EINVAL; + goto bad_fork_free_pid; + } + /* Note that no task has been attached to @pid yet. */ retval = __pidfd_prepare(pid, flags, &pidfile); if (retval < 0) diff --git a/kernel/irq/irqdesc.c b/kernel/irq/irqdesc.c index 07e99c936ba5d8..1dee88ba0ae449 100644 --- a/kernel/irq/irqdesc.c +++ b/kernel/irq/irqdesc.c @@ -530,6 +530,7 @@ static int alloc_descs(unsigned int start, unsigned int cnt, int node, flags = IRQD_AFFINITY_MANAGED | IRQD_MANAGED_SHUTDOWN; } + flags |= IRQD_AFFINITY_SET; mask = &affinity->mask; node = cpu_to_node(cpumask_first(mask)); affinity++; diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c index cea8f6874b1fbc..01001eb615ecc6 100644 --- a/kernel/irq/irqdomain.c +++ b/kernel/irq/irqdomain.c @@ -128,72 +128,92 @@ void irq_domain_free_fwnode(struct fwnode_handle *fwnode) } EXPORT_SYMBOL_GPL(irq_domain_free_fwnode); -static int irq_domain_set_name(struct irq_domain *domain, - const struct fwnode_handle *fwnode, - enum irq_domain_bus_token bus_token) +static int alloc_name(struct irq_domain *domain, char *base, enum irq_domain_bus_token bus_token) +{ + domain->name = bus_token ? kasprintf(GFP_KERNEL, "%s-%d", base, bus_token) : + kasprintf(GFP_KERNEL, "%s", base); + if (!domain->name) + return -ENOMEM; + + domain->flags |= IRQ_DOMAIN_NAME_ALLOCATED; + return 0; +} + +static int alloc_fwnode_name(struct irq_domain *domain, const struct fwnode_handle *fwnode, + enum irq_domain_bus_token bus_token, const char *suffix) +{ + const char *sep = suffix ? "-" : ""; + const char *suf = suffix ? : ""; + char *name; + + name = bus_token ? kasprintf(GFP_KERNEL, "%pfw-%s%s%d", fwnode, suf, sep, bus_token) : + kasprintf(GFP_KERNEL, "%pfw-%s", fwnode, suf); + if (!name) + return -ENOMEM; + + /* + * fwnode paths contain '/', which debugfs is legitimately unhappy + * about. Replace them with ':', which does the trick and is not as + * offensive as '\'... + */ + domain->name = strreplace(name, '/', ':'); + domain->flags |= IRQ_DOMAIN_NAME_ALLOCATED; + return 0; +} + +static int alloc_unknown_name(struct irq_domain *domain, enum irq_domain_bus_token bus_token) { static atomic_t unknown_domains; - struct irqchip_fwid *fwid; + int id = atomic_inc_return(&unknown_domains); + + domain->name = bus_token ? kasprintf(GFP_KERNEL, "unknown-%d-%d", id, bus_token) : + kasprintf(GFP_KERNEL, "unknown-%d", id); + + if (!domain->name) + return -ENOMEM; + domain->flags |= IRQ_DOMAIN_NAME_ALLOCATED; + return 0; +} + +static int irq_domain_set_name(struct irq_domain *domain, const struct irq_domain_info *info) +{ + enum irq_domain_bus_token bus_token = info->bus_token; + const struct fwnode_handle *fwnode = info->fwnode; if (is_fwnode_irqchip(fwnode)) { - fwid = container_of(fwnode, struct irqchip_fwid, fwnode); + struct irqchip_fwid *fwid = container_of(fwnode, struct irqchip_fwid, fwnode); + + /* + * The name_suffix is only intended to be used to avoid a name + * collision when multiple domains are created for a single + * device and the name is picked using a real device node. + * (Typical use-case is regmap-IRQ controllers for devices + * providing more than one physical IRQ.) There should be no + * need to use name_suffix with irqchip-fwnode. + */ + if (info->name_suffix) + return -EINVAL; switch (fwid->type) { case IRQCHIP_FWNODE_NAMED: case IRQCHIP_FWNODE_NAMED_ID: - domain->name = bus_token ? - kasprintf(GFP_KERNEL, "%s-%d", - fwid->name, bus_token) : - kstrdup(fwid->name, GFP_KERNEL); - if (!domain->name) - return -ENOMEM; - domain->flags |= IRQ_DOMAIN_NAME_ALLOCATED; - break; + return alloc_name(domain, fwid->name, bus_token); default: domain->name = fwid->name; - if (bus_token) { - domain->name = kasprintf(GFP_KERNEL, "%s-%d", - fwid->name, bus_token); - if (!domain->name) - return -ENOMEM; - domain->flags |= IRQ_DOMAIN_NAME_ALLOCATED; - } - break; + if (bus_token) + return alloc_name(domain, fwid->name, bus_token); } - } else if (is_of_node(fwnode) || is_acpi_device_node(fwnode) || - is_software_node(fwnode)) { - char *name; - - /* - * fwnode paths contain '/', which debugfs is legitimately - * unhappy about. Replace them with ':', which does - * the trick and is not as offensive as '\'... - */ - name = bus_token ? - kasprintf(GFP_KERNEL, "%pfw-%d", fwnode, bus_token) : - kasprintf(GFP_KERNEL, "%pfw", fwnode); - if (!name) - return -ENOMEM; - domain->name = strreplace(name, '/', ':'); - domain->flags |= IRQ_DOMAIN_NAME_ALLOCATED; + } else if (is_of_node(fwnode) || is_acpi_device_node(fwnode) || is_software_node(fwnode)) { + return alloc_fwnode_name(domain, fwnode, bus_token, info->name_suffix); } - if (!domain->name) { - if (fwnode) - pr_err("Invalid fwnode type for irqdomain\n"); - domain->name = bus_token ? - kasprintf(GFP_KERNEL, "unknown-%d-%d", - atomic_inc_return(&unknown_domains), - bus_token) : - kasprintf(GFP_KERNEL, "unknown-%d", - atomic_inc_return(&unknown_domains)); - if (!domain->name) - return -ENOMEM; - domain->flags |= IRQ_DOMAIN_NAME_ALLOCATED; - } + if (domain->name) + return 0; - return 0; + if (fwnode) + pr_err("Invalid fwnode type for irqdomain\n"); + return alloc_unknown_name(domain, bus_token); } static struct irq_domain *__irq_domain_create(const struct irq_domain_info *info) @@ -211,7 +231,7 @@ static struct irq_domain *__irq_domain_create(const struct irq_domain_info *info if (!domain) return ERR_PTR(-ENOMEM); - err = irq_domain_set_name(domain, info->fwnode, info->bus_token); + err = irq_domain_set_name(domain, info); if (err) { kfree(domain); return ERR_PTR(err); @@ -267,13 +287,20 @@ static void irq_domain_free(struct irq_domain *domain) kfree(domain); } -/** - * irq_domain_instantiate() - Instantiate a new irq domain data structure - * @info: Domain information pointer pointing to the information for this domain - * - * Return: A pointer to the instantiated irq domain or an ERR_PTR value. - */ -struct irq_domain *irq_domain_instantiate(const struct irq_domain_info *info) +static void irq_domain_instantiate_descs(const struct irq_domain_info *info) +{ + if (!IS_ENABLED(CONFIG_SPARSE_IRQ)) + return; + + if (irq_alloc_descs(info->virq_base, info->virq_base, info->size, + of_node_to_nid(to_of_node(info->fwnode))) < 0) { + pr_info("Cannot allocate irq_descs @ IRQ%d, assuming pre-allocated\n", + info->virq_base); + } +} + +static struct irq_domain *__irq_domain_instantiate(const struct irq_domain_info *info, + bool cond_alloc_descs) { struct irq_domain *domain; int err; @@ -306,6 +333,15 @@ struct irq_domain *irq_domain_instantiate(const struct irq_domain_info *info) __irq_domain_publish(domain); + if (cond_alloc_descs && info->virq_base > 0) + irq_domain_instantiate_descs(info); + + /* Legacy interrupt domains have a fixed Linux interrupt number */ + if (info->virq_base > 0) { + irq_domain_associate_many(domain, info->virq_base, info->hwirq_base, + info->size - info->hwirq_base); + } + return domain; err_domain_gc_remove: @@ -315,6 +351,17 @@ struct irq_domain *irq_domain_instantiate(const struct irq_domain_info *info) irq_domain_free(domain); return ERR_PTR(err); } + +/** + * irq_domain_instantiate() - Instantiate a new irq domain data structure + * @info: Domain information pointer pointing to the information for this domain + * + * Return: A pointer to the instantiated irq domain or an ERR_PTR value. + */ +struct irq_domain *irq_domain_instantiate(const struct irq_domain_info *info) +{ + return __irq_domain_instantiate(info, false); +} EXPORT_SYMBOL_GPL(irq_domain_instantiate); /** @@ -413,28 +460,13 @@ struct irq_domain *irq_domain_create_simple(struct fwnode_handle *fwnode, .fwnode = fwnode, .size = size, .hwirq_max = size, + .virq_base = first_irq, .ops = ops, .host_data = host_data, }; - struct irq_domain *domain; - - domain = irq_domain_instantiate(&info); - if (IS_ERR(domain)) - return NULL; + struct irq_domain *domain = __irq_domain_instantiate(&info, true); - if (first_irq > 0) { - if (IS_ENABLED(CONFIG_SPARSE_IRQ)) { - /* attempt to allocated irq_descs */ - int rc = irq_alloc_descs(first_irq, first_irq, size, - of_node_to_nid(to_of_node(fwnode))); - if (rc < 0) - pr_info("Cannot allocate irq_descs @ IRQ%d, assuming pre-allocated\n", - first_irq); - } - irq_domain_associate_many(domain, first_irq, 0, size); - } - - return domain; + return IS_ERR(domain) ? NULL : domain; } EXPORT_SYMBOL_GPL(irq_domain_create_simple); @@ -476,18 +508,14 @@ struct irq_domain *irq_domain_create_legacy(struct fwnode_handle *fwnode, .fwnode = fwnode, .size = first_hwirq + size, .hwirq_max = first_hwirq + size, + .hwirq_base = first_hwirq, + .virq_base = first_irq, .ops = ops, .host_data = host_data, }; - struct irq_domain *domain; + struct irq_domain *domain = irq_domain_instantiate(&info); - domain = irq_domain_instantiate(&info); - if (IS_ERR(domain)) - return NULL; - - irq_domain_associate_many(domain, first_irq, first_hwirq, size); - - return domain; + return IS_ERR(domain) ? NULL : domain; } EXPORT_SYMBOL_GPL(irq_domain_create_legacy); diff --git a/kernel/jump_label.c b/kernel/jump_label.c index 4ad5ed8adf9691..6dc76b590703ed 100644 --- a/kernel/jump_label.c +++ b/kernel/jump_label.c @@ -236,7 +236,7 @@ void static_key_disable_cpuslocked(struct static_key *key) } jump_label_lock(); - if (atomic_cmpxchg(&key->enabled, 1, 0)) + if (atomic_cmpxchg(&key->enabled, 1, 0) == 1) jump_label_update(key); jump_label_unlock(); } @@ -289,7 +289,7 @@ static void __static_key_slow_dec_cpuslocked(struct static_key *key) return; guard(mutex)(&jump_label_mutex); - if (atomic_cmpxchg(&key->enabled, 1, 0)) + if (atomic_cmpxchg(&key->enabled, 1, 0) == 1) jump_label_update(key); else WARN_ON_ONCE(!static_key_slow_try_dec(key)); diff --git a/kernel/kallsyms.c b/kernel/kallsyms.c index fb2c77368d187e..a9a0ca605d4a8c 100644 --- a/kernel/kallsyms.c +++ b/kernel/kallsyms.c @@ -160,38 +160,6 @@ unsigned long kallsyms_sym_address(int idx) return kallsyms_relative_base - 1 - kallsyms_offsets[idx]; } -static void cleanup_symbol_name(char *s) -{ - char *res; - - if (!IS_ENABLED(CONFIG_LTO_CLANG)) - return; - - /* - * LLVM appends various suffixes for local functions and variables that - * must be promoted to global scope as part of LTO. This can break - * hooking of static functions with kprobes. '.' is not a valid - * character in an identifier in C. Suffixes only in LLVM LTO observed: - * - foo.llvm.[0-9a-f]+ - */ - res = strstr(s, ".llvm."); - if (res) - *res = '\0'; - - return; -} - -static int compare_symbol_name(const char *name, char *namebuf) -{ - /* The kallsyms_seqs_of_names is sorted based on names after - * cleanup_symbol_name() (see scripts/kallsyms.c) if clang lto is enabled. - * To ensure correct bisection in kallsyms_lookup_names(), do - * cleanup_symbol_name(namebuf) before comparing name and namebuf. - */ - cleanup_symbol_name(namebuf); - return strcmp(name, namebuf); -} - static unsigned int get_symbol_seq(int index) { unsigned int i, seq = 0; @@ -219,7 +187,7 @@ static int kallsyms_lookup_names(const char *name, seq = get_symbol_seq(mid); off = get_symbol_offset(seq); kallsyms_expand_symbol(off, namebuf, ARRAY_SIZE(namebuf)); - ret = compare_symbol_name(name, namebuf); + ret = strcmp(name, namebuf); if (ret > 0) low = mid + 1; else if (ret < 0) @@ -236,7 +204,7 @@ static int kallsyms_lookup_names(const char *name, seq = get_symbol_seq(low - 1); off = get_symbol_offset(seq); kallsyms_expand_symbol(off, namebuf, ARRAY_SIZE(namebuf)); - if (compare_symbol_name(name, namebuf)) + if (strcmp(name, namebuf)) break; low--; } @@ -248,7 +216,7 @@ static int kallsyms_lookup_names(const char *name, seq = get_symbol_seq(high + 1); off = get_symbol_offset(seq); kallsyms_expand_symbol(off, namebuf, ARRAY_SIZE(namebuf)); - if (compare_symbol_name(name, namebuf)) + if (strcmp(name, namebuf)) break; high++; } @@ -407,8 +375,7 @@ static int kallsyms_lookup_buildid(unsigned long addr, if (modbuildid) *modbuildid = NULL; - ret = strlen(namebuf); - goto found; + return strlen(namebuf); } /* See if it's in a module or a BPF JITed image. */ @@ -422,8 +389,6 @@ static int kallsyms_lookup_buildid(unsigned long addr, ret = ftrace_mod_address_lookup(addr, symbolsize, offset, modname, namebuf); -found: - cleanup_symbol_name(namebuf); return ret; } @@ -450,8 +415,6 @@ const char *kallsyms_lookup(unsigned long addr, int lookup_symbol_name(unsigned long addr, char *symname) { - int res; - symname[0] = '\0'; symname[KSYM_NAME_LEN - 1] = '\0'; @@ -462,16 +425,10 @@ int lookup_symbol_name(unsigned long addr, char *symname) /* Grab name */ kallsyms_expand_symbol(get_symbol_offset(pos), symname, KSYM_NAME_LEN); - goto found; + return 0; } /* See if it's in a module. */ - res = lookup_module_symbol_name(addr, symname); - if (res) - return res; - -found: - cleanup_symbol_name(symname); - return 0; + return lookup_module_symbol_name(addr, symname); } /* Look up a kernel symbol and return it in a text buffer. */ diff --git a/kernel/kallsyms_selftest.c b/kernel/kallsyms_selftest.c index 2f84896a7bcbdf..873f7c445488c1 100644 --- a/kernel/kallsyms_selftest.c +++ b/kernel/kallsyms_selftest.c @@ -187,31 +187,11 @@ static void test_perf_kallsyms_lookup_name(void) stat.min, stat.max, div_u64(stat.sum, stat.real_cnt)); } -static bool match_cleanup_name(const char *s, const char *name) -{ - char *p; - int len; - - if (!IS_ENABLED(CONFIG_LTO_CLANG)) - return false; - - p = strstr(s, ".llvm."); - if (!p) - return false; - - len = strlen(name); - if (p - s != len) - return false; - - return !strncmp(s, name, len); -} - static int find_symbol(void *data, const char *name, unsigned long addr) { struct test_stat *stat = (struct test_stat *)data; - if (strcmp(name, stat->name) == 0 || - (!stat->perf && match_cleanup_name(name, stat->name))) { + if (!strcmp(name, stat->name)) { stat->real_cnt++; stat->addr = addr; diff --git a/kernel/kcov.c b/kernel/kcov.c index f0a69d402066e1..274b6b7c718de6 100644 --- a/kernel/kcov.c +++ b/kernel/kcov.c @@ -161,6 +161,15 @@ static void kcov_remote_area_put(struct kcov_remote_area *area, kmsan_unpoison_memory(&area->list, sizeof(area->list)); } +/* + * Unlike in_serving_softirq(), this function returns false when called during + * a hardirq or an NMI that happened in the softirq context. + */ +static inline bool in_softirq_really(void) +{ + return in_serving_softirq() && !in_hardirq() && !in_nmi(); +} + static notrace bool check_kcov_mode(enum kcov_mode needed_mode, struct task_struct *t) { unsigned int mode; @@ -170,7 +179,7 @@ static notrace bool check_kcov_mode(enum kcov_mode needed_mode, struct task_stru * so we ignore code executed in interrupts, unless we are in a remote * coverage collection section in a softirq. */ - if (!in_task() && !(in_serving_softirq() && t->kcov_softirq)) + if (!in_task() && !(in_softirq_really() && t->kcov_softirq)) return false; mode = READ_ONCE(t->kcov_mode); /* @@ -849,7 +858,7 @@ void kcov_remote_start(u64 handle) if (WARN_ON(!kcov_check_handle(handle, true, true, true))) return; - if (!in_task() && !in_serving_softirq()) + if (!in_task() && !in_softirq_really()) return; local_lock_irqsave(&kcov_percpu_data.lock, flags); @@ -991,7 +1000,7 @@ void kcov_remote_stop(void) int sequence; unsigned long flags; - if (!in_task() && !in_serving_softirq()) + if (!in_task() && !in_softirq_really()) return; local_lock_irqsave(&kcov_percpu_data.lock, flags); diff --git a/kernel/kprobes.c b/kernel/kprobes.c index e85de37d9e1e01..da59c68df8412c 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c @@ -1557,8 +1557,8 @@ static bool is_cfi_preamble_symbol(unsigned long addr) if (lookup_symbol_name(addr, symbuf)) return false; - return str_has_prefix("__cfi_", symbuf) || - str_has_prefix("__pfx_", symbuf); + return str_has_prefix(symbuf, "__cfi_") || + str_has_prefix(symbuf, "__pfx_"); } static int check_kprobe_address_safe(struct kprobe *p, diff --git a/kernel/ksysfs.c b/kernel/ksysfs.c index 07fb5987b42bdf..1bab21b4718fff 100644 --- a/kernel/ksysfs.c +++ b/kernel/ksysfs.c @@ -92,7 +92,14 @@ static ssize_t profiling_store(struct kobject *kobj, const char *buf, size_t count) { int ret; + static DEFINE_MUTEX(lock); + /* + * We need serialization, for profile_setup() initializes prof_on + * value and profile_init() must not reallocate prof_buffer after + * once allocated. + */ + guard(mutex)(&lock); if (prof_on) return -EEXIST; /* diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c index 58c88220a478ac..0349f957e672da 100644 --- a/kernel/locking/lockdep.c +++ b/kernel/locking/lockdep.c @@ -5936,6 +5936,9 @@ __lock_contended(struct lockdep_map *lock, unsigned long ip) if (DEBUG_LOCKS_WARN_ON(!depth)) return; + if (unlikely(lock->key == &__lockdep_no_track__)) + return; + hlock = find_held_lock(curr, lock, depth, &i); if (!hlock) { print_lock_contention_bug(curr, lock, ip); @@ -5978,6 +5981,9 @@ __lock_acquired(struct lockdep_map *lock, unsigned long ip) if (DEBUG_LOCKS_WARN_ON(!depth)) return; + if (unlikely(lock->key == &__lockdep_no_track__)) + return; + hlock = find_held_lock(curr, lock, depth, &i); if (!hlock) { print_lock_contention_bug(curr, lock, _RET_IP_); diff --git a/kernel/locking/qspinlock_paravirt.h b/kernel/locking/qspinlock_paravirt.h index f5a36e67b59355..ac2e2250274105 100644 --- a/kernel/locking/qspinlock_paravirt.h +++ b/kernel/locking/qspinlock_paravirt.h @@ -357,7 +357,7 @@ static void pv_wait_node(struct mcs_spinlock *node, struct mcs_spinlock *prev) static void pv_kick_node(struct qspinlock *lock, struct mcs_spinlock *node) { struct pv_node *pn = (struct pv_node *)node; - enum vcpu_state old = vcpu_halted; + u8 old = vcpu_halted; /* * If the vCPU is indeed halted, advance its state to match that of * pv_wait_node(). If OTOH this fails, the vCPU was running and will diff --git a/kernel/module/main.c b/kernel/module/main.c index d9592195c5bbb4..71396e297499f4 100644 --- a/kernel/module/main.c +++ b/kernel/module/main.c @@ -3104,7 +3104,7 @@ static bool idempotent(struct idempotent *u, const void *cookie) struct idempotent *existing; bool first; - u->ret = 0; + u->ret = -EINTR; u->cookie = cookie; init_completion(&u->complete); @@ -3140,7 +3140,7 @@ static int idempotent_complete(struct idempotent *u, int ret) hlist_for_each_entry_safe(pos, next, head, entry) { if (pos->cookie != cookie) continue; - hlist_del(&pos->entry); + hlist_del_init(&pos->entry); pos->ret = ret; complete(&pos->complete); } @@ -3148,6 +3148,28 @@ static int idempotent_complete(struct idempotent *u, int ret) return ret; } +/* + * Wait for the idempotent worker. + * + * If we get interrupted, we need to remove ourselves from the + * the idempotent list, and the completion may still come in. + * + * The 'idem_lock' protects against the race, and 'idem.ret' was + * initialized to -EINTR and is thus always the right return + * value even if the idempotent work then completes between + * the wait_for_completion and the cleanup. + */ +static int idempotent_wait_for_completion(struct idempotent *u) +{ + if (wait_for_completion_interruptible(&u->complete)) { + spin_lock(&idem_lock); + if (!hlist_unhashed(&u->entry)) + hlist_del(&u->entry); + spin_unlock(&idem_lock); + } + return u->ret; +} + static int init_module_from_file(struct file *f, const char __user * uargs, int flags) { struct load_info info = { }; @@ -3183,15 +3205,16 @@ static int idempotent_init_module(struct file *f, const char __user * uargs, int if (!f || !(f->f_mode & FMODE_READ)) return -EBADF; - /* See if somebody else is doing the operation? */ - if (idempotent(&idem, file_inode(f))) { - wait_for_completion(&idem.complete); - return idem.ret; + /* Are we the winners of the race and get to do this? */ + if (!idempotent(&idem, file_inode(f))) { + int ret = init_module_from_file(f, uargs, flags); + return idempotent_complete(&idem, ret); } - /* Otherwise, we'll do it and complete others */ - return idempotent_complete(&idem, - init_module_from_file(f, uargs, flags)); + /* + * Somebody else won the race and is loading the module. + */ + return idempotent_wait_for_completion(&idem); } SYSCALL_DEFINE3(finit_module, int, fd, const char __user *, uargs, int, flags) diff --git a/kernel/padata.c b/kernel/padata.c index 53f4bc9127127c..0fa6c289546032 100644 --- a/kernel/padata.c +++ b/kernel/padata.c @@ -517,6 +517,13 @@ void __init padata_do_multithreaded(struct padata_mt_job *job) ps.chunk_size = max(ps.chunk_size, job->min_chunk); ps.chunk_size = roundup(ps.chunk_size, job->align); + /* + * chunk_size can be 0 if the caller sets min_chunk to 0. So force it + * to at least 1 to prevent divide-by-0 panic in padata_mt_helper().` + */ + if (!ps.chunk_size) + ps.chunk_size = 1U; + list_for_each_entry(pw, &works, pw_list) if (job->numa_aware) { int old_node = atomic_read(&last_used_nid); diff --git a/kernel/profile.c b/kernel/profile.c index 2b775cc5c28f96..1fcf1adcf4eb03 100644 --- a/kernel/profile.c +++ b/kernel/profile.c @@ -47,30 +47,14 @@ static unsigned short int prof_shift; int prof_on __read_mostly; EXPORT_SYMBOL_GPL(prof_on); -static cpumask_var_t prof_cpu_mask; -#if defined(CONFIG_SMP) && defined(CONFIG_PROC_FS) -static DEFINE_PER_CPU(struct profile_hit *[2], cpu_profile_hits); -static DEFINE_PER_CPU(int, cpu_profile_flip); -static DEFINE_MUTEX(profile_flip_mutex); -#endif /* CONFIG_SMP */ - int profile_setup(char *str) { static const char schedstr[] = "schedule"; - static const char sleepstr[] = "sleep"; static const char kvmstr[] = "kvm"; const char *select = NULL; int par; - if (!strncmp(str, sleepstr, strlen(sleepstr))) { -#ifdef CONFIG_SCHEDSTATS - force_schedstat_enabled(); - prof_on = SLEEP_PROFILING; - select = sleepstr; -#else - pr_warn("kernel sleep profiling requires CONFIG_SCHEDSTATS\n"); -#endif /* CONFIG_SCHEDSTATS */ - } else if (!strncmp(str, schedstr, strlen(schedstr))) { + if (!strncmp(str, schedstr, strlen(schedstr))) { prof_on = SCHED_PROFILING; select = schedstr; } else if (!strncmp(str, kvmstr, strlen(kvmstr))) { @@ -114,11 +98,6 @@ int __ref profile_init(void) buffer_bytes = prof_len*sizeof(atomic_t); - if (!alloc_cpumask_var(&prof_cpu_mask, GFP_KERNEL)) - return -ENOMEM; - - cpumask_copy(prof_cpu_mask, cpu_possible_mask); - prof_buffer = kzalloc(buffer_bytes, GFP_KERNEL|__GFP_NOWARN); if (prof_buffer) return 0; @@ -132,195 +111,16 @@ int __ref profile_init(void) if (prof_buffer) return 0; - free_cpumask_var(prof_cpu_mask); return -ENOMEM; } -#if defined(CONFIG_SMP) && defined(CONFIG_PROC_FS) -/* - * Each cpu has a pair of open-addressed hashtables for pending - * profile hits. read_profile() IPI's all cpus to request them - * to flip buffers and flushes their contents to prof_buffer itself. - * Flip requests are serialized by the profile_flip_mutex. The sole - * use of having a second hashtable is for avoiding cacheline - * contention that would otherwise happen during flushes of pending - * profile hits required for the accuracy of reported profile hits - * and so resurrect the interrupt livelock issue. - * - * The open-addressed hashtables are indexed by profile buffer slot - * and hold the number of pending hits to that profile buffer slot on - * a cpu in an entry. When the hashtable overflows, all pending hits - * are accounted to their corresponding profile buffer slots with - * atomic_add() and the hashtable emptied. As numerous pending hits - * may be accounted to a profile buffer slot in a hashtable entry, - * this amortizes a number of atomic profile buffer increments likely - * to be far larger than the number of entries in the hashtable, - * particularly given that the number of distinct profile buffer - * positions to which hits are accounted during short intervals (e.g. - * several seconds) is usually very small. Exclusion from buffer - * flipping is provided by interrupt disablement (note that for - * SCHED_PROFILING or SLEEP_PROFILING profile_hit() may be called from - * process context). - * The hash function is meant to be lightweight as opposed to strong, - * and was vaguely inspired by ppc64 firmware-supported inverted - * pagetable hash functions, but uses a full hashtable full of finite - * collision chains, not just pairs of them. - * - * -- nyc - */ -static void __profile_flip_buffers(void *unused) -{ - int cpu = smp_processor_id(); - - per_cpu(cpu_profile_flip, cpu) = !per_cpu(cpu_profile_flip, cpu); -} - -static void profile_flip_buffers(void) -{ - int i, j, cpu; - - mutex_lock(&profile_flip_mutex); - j = per_cpu(cpu_profile_flip, get_cpu()); - put_cpu(); - on_each_cpu(__profile_flip_buffers, NULL, 1); - for_each_online_cpu(cpu) { - struct profile_hit *hits = per_cpu(cpu_profile_hits, cpu)[j]; - for (i = 0; i < NR_PROFILE_HIT; ++i) { - if (!hits[i].hits) { - if (hits[i].pc) - hits[i].pc = 0; - continue; - } - atomic_add(hits[i].hits, &prof_buffer[hits[i].pc]); - hits[i].hits = hits[i].pc = 0; - } - } - mutex_unlock(&profile_flip_mutex); -} - -static void profile_discard_flip_buffers(void) -{ - int i, cpu; - - mutex_lock(&profile_flip_mutex); - i = per_cpu(cpu_profile_flip, get_cpu()); - put_cpu(); - on_each_cpu(__profile_flip_buffers, NULL, 1); - for_each_online_cpu(cpu) { - struct profile_hit *hits = per_cpu(cpu_profile_hits, cpu)[i]; - memset(hits, 0, NR_PROFILE_HIT*sizeof(struct profile_hit)); - } - mutex_unlock(&profile_flip_mutex); -} - -static void do_profile_hits(int type, void *__pc, unsigned int nr_hits) -{ - unsigned long primary, secondary, flags, pc = (unsigned long)__pc; - int i, j, cpu; - struct profile_hit *hits; - - pc = min((pc - (unsigned long)_stext) >> prof_shift, prof_len - 1); - i = primary = (pc & (NR_PROFILE_GRP - 1)) << PROFILE_GRPSHIFT; - secondary = (~(pc << 1) & (NR_PROFILE_GRP - 1)) << PROFILE_GRPSHIFT; - cpu = get_cpu(); - hits = per_cpu(cpu_profile_hits, cpu)[per_cpu(cpu_profile_flip, cpu)]; - if (!hits) { - put_cpu(); - return; - } - /* - * We buffer the global profiler buffer into a per-CPU - * queue and thus reduce the number of global (and possibly - * NUMA-alien) accesses. The write-queue is self-coalescing: - */ - local_irq_save(flags); - do { - for (j = 0; j < PROFILE_GRPSZ; ++j) { - if (hits[i + j].pc == pc) { - hits[i + j].hits += nr_hits; - goto out; - } else if (!hits[i + j].hits) { - hits[i + j].pc = pc; - hits[i + j].hits = nr_hits; - goto out; - } - } - i = (i + secondary) & (NR_PROFILE_HIT - 1); - } while (i != primary); - - /* - * Add the current hit(s) and flush the write-queue out - * to the global buffer: - */ - atomic_add(nr_hits, &prof_buffer[pc]); - for (i = 0; i < NR_PROFILE_HIT; ++i) { - atomic_add(hits[i].hits, &prof_buffer[hits[i].pc]); - hits[i].pc = hits[i].hits = 0; - } -out: - local_irq_restore(flags); - put_cpu(); -} - -static int profile_dead_cpu(unsigned int cpu) -{ - struct page *page; - int i; - - if (cpumask_available(prof_cpu_mask)) - cpumask_clear_cpu(cpu, prof_cpu_mask); - - for (i = 0; i < 2; i++) { - if (per_cpu(cpu_profile_hits, cpu)[i]) { - page = virt_to_page(per_cpu(cpu_profile_hits, cpu)[i]); - per_cpu(cpu_profile_hits, cpu)[i] = NULL; - __free_page(page); - } - } - return 0; -} - -static int profile_prepare_cpu(unsigned int cpu) -{ - int i, node = cpu_to_mem(cpu); - struct page *page; - - per_cpu(cpu_profile_flip, cpu) = 0; - - for (i = 0; i < 2; i++) { - if (per_cpu(cpu_profile_hits, cpu)[i]) - continue; - - page = __alloc_pages_node(node, GFP_KERNEL | __GFP_ZERO, 0); - if (!page) { - profile_dead_cpu(cpu); - return -ENOMEM; - } - per_cpu(cpu_profile_hits, cpu)[i] = page_address(page); - - } - return 0; -} - -static int profile_online_cpu(unsigned int cpu) -{ - if (cpumask_available(prof_cpu_mask)) - cpumask_set_cpu(cpu, prof_cpu_mask); - - return 0; -} - -#else /* !CONFIG_SMP */ -#define profile_flip_buffers() do { } while (0) -#define profile_discard_flip_buffers() do { } while (0) - static void do_profile_hits(int type, void *__pc, unsigned int nr_hits) { unsigned long pc; pc = ((unsigned long)__pc - (unsigned long)_stext) >> prof_shift; - atomic_add(nr_hits, &prof_buffer[min(pc, prof_len - 1)]); + if (pc < prof_len) + atomic_add(nr_hits, &prof_buffer[pc]); } -#endif /* !CONFIG_SMP */ void profile_hits(int type, void *__pc, unsigned int nr_hits) { @@ -334,8 +134,8 @@ void profile_tick(int type) { struct pt_regs *regs = get_irq_regs(); - if (!user_mode(regs) && cpumask_available(prof_cpu_mask) && - cpumask_test_cpu(smp_processor_id(), prof_cpu_mask)) + /* This is the old kernel-only legacy profiling */ + if (!user_mode(regs)) profile_hit(type, (void *)profile_pc(regs)); } @@ -358,7 +158,6 @@ read_profile(struct file *file, char __user *buf, size_t count, loff_t *ppos) char *pnt; unsigned long sample_step = 1UL << prof_shift; - profile_flip_buffers(); if (p >= (prof_len+1)*sizeof(unsigned int)) return 0; if (count > (prof_len+1)*sizeof(unsigned int) - p) @@ -404,7 +203,6 @@ static ssize_t write_profile(struct file *file, const char __user *buf, return -EINVAL; } #endif - profile_discard_flip_buffers(); memset(prof_buffer, 0, prof_len * sizeof(atomic_t)); return count; } @@ -418,40 +216,14 @@ static const struct proc_ops profile_proc_ops = { int __ref create_proc_profile(void) { struct proc_dir_entry *entry; -#ifdef CONFIG_SMP - enum cpuhp_state online_state; -#endif - int err = 0; if (!prof_on) return 0; -#ifdef CONFIG_SMP - err = cpuhp_setup_state(CPUHP_PROFILE_PREPARE, "PROFILE_PREPARE", - profile_prepare_cpu, profile_dead_cpu); - if (err) - return err; - - err = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "AP_PROFILE_ONLINE", - profile_online_cpu, NULL); - if (err < 0) - goto err_state_prep; - online_state = err; - err = 0; -#endif entry = proc_create("profile", S_IWUSR | S_IRUGO, NULL, &profile_proc_ops); - if (!entry) - goto err_state_onl; - proc_set_size(entry, (1 + prof_len) * sizeof(atomic_t)); - - return err; -err_state_onl: -#ifdef CONFIG_SMP - cpuhp_remove_state(online_state); -err_state_prep: - cpuhp_remove_state(CPUHP_PROFILE_PREPARE); -#endif + if (entry) + proc_set_size(entry, (1 + prof_len) * sizeof(atomic_t)); return err; } subsys_initcall(create_proc_profile); diff --git a/kernel/sched/core.c b/kernel/sched/core.c index a9f655025607b9..f3951e4a55e5b6 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -7845,6 +7845,30 @@ void set_rq_offline(struct rq *rq) } } +static inline void sched_set_rq_online(struct rq *rq, int cpu) +{ + struct rq_flags rf; + + rq_lock_irqsave(rq, &rf); + if (rq->rd) { + BUG_ON(!cpumask_test_cpu(cpu, rq->rd->span)); + set_rq_online(rq); + } + rq_unlock_irqrestore(rq, &rf); +} + +static inline void sched_set_rq_offline(struct rq *rq, int cpu) +{ + struct rq_flags rf; + + rq_lock_irqsave(rq, &rf); + if (rq->rd) { + BUG_ON(!cpumask_test_cpu(cpu, rq->rd->span)); + set_rq_offline(rq); + } + rq_unlock_irqrestore(rq, &rf); +} + /* * used to mark begin/end of suspend/resume: */ @@ -7895,10 +7919,25 @@ static int cpuset_cpu_inactive(unsigned int cpu) return 0; } +static inline void sched_smt_present_inc(int cpu) +{ +#ifdef CONFIG_SCHED_SMT + if (cpumask_weight(cpu_smt_mask(cpu)) == 2) + static_branch_inc_cpuslocked(&sched_smt_present); +#endif +} + +static inline void sched_smt_present_dec(int cpu) +{ +#ifdef CONFIG_SCHED_SMT + if (cpumask_weight(cpu_smt_mask(cpu)) == 2) + static_branch_dec_cpuslocked(&sched_smt_present); +#endif +} + int sched_cpu_activate(unsigned int cpu) { struct rq *rq = cpu_rq(cpu); - struct rq_flags rf; /* * Clear the balance_push callback and prepare to schedule @@ -7906,13 +7945,10 @@ int sched_cpu_activate(unsigned int cpu) */ balance_push_set(cpu, false); -#ifdef CONFIG_SCHED_SMT /* * When going up, increment the number of cores with SMT present. */ - if (cpumask_weight(cpu_smt_mask(cpu)) == 2) - static_branch_inc_cpuslocked(&sched_smt_present); -#endif + sched_smt_present_inc(cpu); set_cpu_active(cpu, true); if (sched_smp_initialized) { @@ -7930,12 +7966,7 @@ int sched_cpu_activate(unsigned int cpu) * 2) At runtime, if cpuset_cpu_active() fails to rebuild the * domains. */ - rq_lock_irqsave(rq, &rf); - if (rq->rd) { - BUG_ON(!cpumask_test_cpu(cpu, rq->rd->span)); - set_rq_online(rq); - } - rq_unlock_irqrestore(rq, &rf); + sched_set_rq_online(rq, cpu); return 0; } @@ -7943,7 +7974,6 @@ int sched_cpu_activate(unsigned int cpu) int sched_cpu_deactivate(unsigned int cpu) { struct rq *rq = cpu_rq(cpu); - struct rq_flags rf; int ret; /* @@ -7974,20 +8004,14 @@ int sched_cpu_deactivate(unsigned int cpu) */ synchronize_rcu(); - rq_lock_irqsave(rq, &rf); - if (rq->rd) { - BUG_ON(!cpumask_test_cpu(cpu, rq->rd->span)); - set_rq_offline(rq); - } - rq_unlock_irqrestore(rq, &rf); + sched_set_rq_offline(rq, cpu); -#ifdef CONFIG_SCHED_SMT /* * When going down, decrement the number of cores with SMT present. */ - if (cpumask_weight(cpu_smt_mask(cpu)) == 2) - static_branch_dec_cpuslocked(&sched_smt_present); + sched_smt_present_dec(cpu); +#ifdef CONFIG_SCHED_SMT sched_core_cpu_deactivate(cpu); #endif @@ -7997,6 +8021,8 @@ int sched_cpu_deactivate(unsigned int cpu) sched_update_numa(cpu, false); ret = cpuset_cpu_inactive(cpu); if (ret) { + sched_smt_present_inc(cpu); + sched_set_rq_online(rq, cpu); balance_push_set(cpu, false); set_cpu_active(cpu, true); sched_update_numa(cpu, true); diff --git a/kernel/sched/cputime.c b/kernel/sched/cputime.c index a5e00293ae4330..0bed0fa1acd988 100644 --- a/kernel/sched/cputime.c +++ b/kernel/sched/cputime.c @@ -582,6 +582,12 @@ void cputime_adjust(struct task_cputime *curr, struct prev_cputime *prev, } stime = mul_u64_u64_div_u64(stime, rtime, stime + utime); + /* + * Because mul_u64_u64_div_u64() can approximate on some + * achitectures; enforce the constraint that: a*b/(b+c) <= a. + */ + if (unlikely(stime > rtime)) + stime = rtime; update: /* diff --git a/kernel/sched/stats.c b/kernel/sched/stats.c index 78e48f5426ee1f..eb0cdcd4d9212e 100644 --- a/kernel/sched/stats.c +++ b/kernel/sched/stats.c @@ -92,16 +92,6 @@ void __update_stats_enqueue_sleeper(struct rq *rq, struct task_struct *p, trace_sched_stat_blocked(p, delta); - /* - * Blocking time is in units of nanosecs, so shift by - * 20 to get a milliseconds-range estimation of the - * amount of time that the task spent sleeping: - */ - if (unlikely(prof_on == SLEEP_PROFILING)) { - profile_hits(SLEEP_PROFILING, - (void *)get_wchan(p), - delta >> 20); - } account_scheduler_latency(p, delta >> 10, 0); } } diff --git a/kernel/task_work.c b/kernel/task_work.c index 5c2daa7ad3f906..5d14d639ac71b5 100644 --- a/kernel/task_work.c +++ b/kernel/task_work.c @@ -6,12 +6,14 @@ static struct callback_head work_exited; /* all we need is ->next == NULL */ +#ifdef CONFIG_IRQ_WORK static void task_work_set_notify_irq(struct irq_work *entry) { test_and_set_tsk_thread_flag(current, TIF_NOTIFY_RESUME); } static DEFINE_PER_CPU(struct irq_work, irq_work_NMI_resume) = IRQ_WORK_INIT_HARD(task_work_set_notify_irq); +#endif /** * task_work_add - ask the @task to execute @work->func() @@ -57,6 +59,8 @@ int task_work_add(struct task_struct *task, struct callback_head *work, if (notify == TWA_NMI_CURRENT) { if (WARN_ON_ONCE(task != current)) return -EINVAL; + if (!IS_ENABLED(CONFIG_IRQ_WORK)) + return -EINVAL; } else { /* record the work call stack in order to print it in KASAN reports */ kasan_record_aux_stack(work); @@ -81,9 +85,11 @@ int task_work_add(struct task_struct *task, struct callback_head *work, case TWA_SIGNAL_NO_IPI: __set_notify_signal(task); break; +#ifdef CONFIG_IRQ_WORK case TWA_NMI_CURRENT: irq_work_queue(this_cpu_ptr(&irq_work_NMI_resume)); break; +#endif default: WARN_ON_ONCE(1); break; diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c index d25ba49e313cca..d0538a75f4c63a 100644 --- a/kernel/time/clocksource.c +++ b/kernel/time/clocksource.c @@ -246,7 +246,7 @@ static enum wd_read_status cs_watchdog_read(struct clocksource *cs, u64 *csnow, wd_delay = cycles_to_nsec_safe(watchdog, *wdnow, wd_end); if (wd_delay <= WATCHDOG_MAX_SKEW) { - if (nretries > 1 || nretries >= max_retries) { + if (nretries > 1 && nretries >= max_retries) { pr_warn("timekeeping watchdog on CPU%d: %s retried %d times before success\n", smp_processor_id(), watchdog->name, nretries); } diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c index 406dccb79c2b6b..8d2dd214ec6822 100644 --- a/kernel/time/ntp.c +++ b/kernel/time/ntp.c @@ -727,17 +727,16 @@ static inline void process_adjtimex_modes(const struct __kernel_timex *txc, } if (txc->modes & ADJ_MAXERROR) - time_maxerror = txc->maxerror; + time_maxerror = clamp(txc->maxerror, 0, NTP_PHASE_LIMIT); if (txc->modes & ADJ_ESTERROR) - time_esterror = txc->esterror; + time_esterror = clamp(txc->esterror, 0, NTP_PHASE_LIMIT); if (txc->modes & ADJ_TIMECONST) { - time_constant = txc->constant; + time_constant = clamp(txc->constant, 0, MAXTC); if (!(time_status & STA_NANO)) time_constant += 4; - time_constant = min(time_constant, (long)MAXTC); - time_constant = max(time_constant, 0l); + time_constant = clamp(time_constant, 0, MAXTC); } if (txc->modes & ADJ_TAI && diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c index b4843099a8da74..ed58eebb4e8f42 100644 --- a/kernel/time/tick-broadcast.c +++ b/kernel/time/tick-broadcast.c @@ -1141,7 +1141,6 @@ void tick_broadcast_switch_to_oneshot(void) #ifdef CONFIG_HOTPLUG_CPU void hotplug_cpu__broadcast_tick_pull(int deadcpu) { - struct tick_device *td = this_cpu_ptr(&tick_cpu_device); struct clock_event_device *bc; unsigned long flags; @@ -1167,6 +1166,8 @@ void hotplug_cpu__broadcast_tick_pull(int deadcpu) * device to avoid the starvation. */ if (tick_check_broadcast_expired()) { + struct tick_device *td = this_cpu_ptr(&tick_cpu_device); + cpumask_clear_cpu(smp_processor_id(), tick_broadcast_force_mask); tick_program_event(td->evtdev->next_event, 1); } diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index 2fa87dcfeda9c2..5391e4167d6022 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -2606,7 +2606,7 @@ int do_adjtimex(struct __kernel_timex *txc) clock_set |= timekeeping_advance(TK_ADV_FREQ); if (clock_set) - clock_was_set(CLOCK_REALTIME); + clock_was_set(CLOCK_SET_WALL); ntp_notify_cmos_timer(); diff --git a/kernel/trace/fgraph.c b/kernel/trace/fgraph.c index fc205ad167a9b7..d1d5ea2d0a1b70 100644 --- a/kernel/trace/fgraph.c +++ b/kernel/trace/fgraph.c @@ -902,7 +902,7 @@ unsigned long ftrace_graph_ret_addr(struct task_struct *task, int *idx, i = *idx ? : task->curr_ret_stack; while (i > 0) { - ret_stack = get_ret_stack(current, i, &i); + ret_stack = get_ret_stack(task, i, &i); if (!ret_stack) break; /* diff --git a/kernel/trace/preemptirq_delay_test.c b/kernel/trace/preemptirq_delay_test.c index cb0871fbdb07f0..314ffc143039c5 100644 --- a/kernel/trace/preemptirq_delay_test.c +++ b/kernel/trace/preemptirq_delay_test.c @@ -34,8 +34,6 @@ MODULE_PARM_DESC(cpu_affinity, "Cpu num test is running on"); static struct completion done; -#define MIN(x, y) ((x) < (y) ? (x) : (y)) - static void busy_wait(ulong time) { u64 start, end; diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index 28853966aa9aff..cebd879a30cbd1 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c @@ -692,18 +692,6 @@ u64 ring_buffer_event_time_stamp(struct trace_buffer *buffer, return ts; } -/** - * ring_buffer_nr_pages - get the number of buffer pages in the ring buffer - * @buffer: The ring_buffer to get the number of pages from - * @cpu: The cpu of the ring_buffer to get the number of pages from - * - * Returns the number of pages used by a per_cpu buffer of the ring buffer. - */ -size_t ring_buffer_nr_pages(struct trace_buffer *buffer, int cpu) -{ - return buffer->buffers[cpu]->nr_pages; -} - /** * ring_buffer_nr_dirty_pages - get the number of used pages in the ring buffer * @buffer: The ring_buffer to get the number of pages from diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 10cd38bce2f1c4..ebe7ce2f5f4a50 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -7956,7 +7956,7 @@ tracing_buffers_read(struct file *filp, char __user *ubuf, trace_access_unlock(iter->cpu_file); if (ret < 0) { - if (trace_empty(iter)) { + if (trace_empty(iter) && !iter->closed) { if ((filp->f_flags & O_NONBLOCK)) return -EAGAIN; diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index 8783bebd0562e5..bd3e3069300e26 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h @@ -1634,6 +1634,29 @@ static inline void *event_file_data(struct file *filp) extern struct mutex event_mutex; extern struct list_head ftrace_events; +/* + * When the trace_event_file is the filp->i_private pointer, + * it must be taken under the event_mutex lock, and then checked + * if the EVENT_FILE_FL_FREED flag is set. If it is, then the + * data pointed to by the trace_event_file can not be trusted. + * + * Use the event_file_file() to access the trace_event_file from + * the filp the first time under the event_mutex and check for + * NULL. If it is needed to be retrieved again and the event_mutex + * is still held, then the event_file_data() can be used and it + * is guaranteed to be valid. + */ +static inline struct trace_event_file *event_file_file(struct file *filp) +{ + struct trace_event_file *file; + + lockdep_assert_held(&event_mutex); + file = READ_ONCE(file_inode(filp)->i_private); + if (!file || file->flags & EVENT_FILE_FL_FREED) + return NULL; + return file; +} + extern const struct file_operations event_trigger_fops; extern const struct file_operations event_hist_fops; extern const struct file_operations event_hist_debug_fops; diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index 6ef29eba90ceb7..7266ec2a4eea00 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c @@ -992,18 +992,18 @@ static void remove_subsystem(struct trace_subsystem_dir *dir) void event_file_get(struct trace_event_file *file) { - atomic_inc(&file->ref); + refcount_inc(&file->ref); } void event_file_put(struct trace_event_file *file) { - if (WARN_ON_ONCE(!atomic_read(&file->ref))) { + if (WARN_ON_ONCE(!refcount_read(&file->ref))) { if (file->flags & EVENT_FILE_FL_FREED) kmem_cache_free(file_cachep, file); return; } - if (atomic_dec_and_test(&file->ref)) { + if (refcount_dec_and_test(&file->ref)) { /* Count should only go to zero when it is freed */ if (WARN_ON_ONCE(!(file->flags & EVENT_FILE_FL_FREED))) return; @@ -1386,12 +1386,12 @@ event_enable_read(struct file *filp, char __user *ubuf, size_t cnt, char buf[4] = "0"; mutex_lock(&event_mutex); - file = event_file_data(filp); + file = event_file_file(filp); if (likely(file)) flags = file->flags; mutex_unlock(&event_mutex); - if (!file || flags & EVENT_FILE_FL_FREED) + if (!file) return -ENODEV; if (flags & EVENT_FILE_FL_ENABLED && @@ -1424,8 +1424,8 @@ event_enable_write(struct file *filp, const char __user *ubuf, size_t cnt, case 1: ret = -ENODEV; mutex_lock(&event_mutex); - file = event_file_data(filp); - if (likely(file && !(file->flags & EVENT_FILE_FL_FREED))) { + file = event_file_file(filp); + if (likely(file)) { ret = tracing_update_buffers(file->tr); if (ret < 0) { mutex_unlock(&event_mutex); @@ -1540,7 +1540,8 @@ enum { static void *f_next(struct seq_file *m, void *v, loff_t *pos) { - struct trace_event_call *call = event_file_data(m->private); + struct trace_event_file *file = event_file_data(m->private); + struct trace_event_call *call = file->event_call; struct list_head *common_head = &ftrace_common_fields; struct list_head *head = trace_get_fields(call); struct list_head *node = v; @@ -1572,7 +1573,8 @@ static void *f_next(struct seq_file *m, void *v, loff_t *pos) static int f_show(struct seq_file *m, void *v) { - struct trace_event_call *call = event_file_data(m->private); + struct trace_event_file *file = event_file_data(m->private); + struct trace_event_call *call = file->event_call; struct ftrace_event_field *field; const char *array_descriptor; @@ -1627,12 +1629,14 @@ static int f_show(struct seq_file *m, void *v) static void *f_start(struct seq_file *m, loff_t *pos) { + struct trace_event_file *file; void *p = (void *)FORMAT_HEADER; loff_t l = 0; /* ->stop() is called even if ->start() fails */ mutex_lock(&event_mutex); - if (!event_file_data(m->private)) + file = event_file_file(m->private); + if (!file) return ERR_PTR(-ENODEV); while (l < *pos && p) @@ -1706,8 +1710,8 @@ event_filter_read(struct file *filp, char __user *ubuf, size_t cnt, trace_seq_init(s); mutex_lock(&event_mutex); - file = event_file_data(filp); - if (file && !(file->flags & EVENT_FILE_FL_FREED)) + file = event_file_file(filp); + if (file) print_event_filter(file, s); mutex_unlock(&event_mutex); @@ -1736,9 +1740,13 @@ event_filter_write(struct file *filp, const char __user *ubuf, size_t cnt, return PTR_ERR(buf); mutex_lock(&event_mutex); - file = event_file_data(filp); - if (file) - err = apply_event_filter(file, buf); + file = event_file_file(filp); + if (file) { + if (file->flags & EVENT_FILE_FL_FREED) + err = -ENODEV; + else + err = apply_event_filter(file, buf); + } mutex_unlock(&event_mutex); kfree(buf); @@ -2485,7 +2493,6 @@ static int event_callback(const char *name, umode_t *mode, void **data, if (strcmp(name, "format") == 0) { *mode = TRACE_MODE_READ; *fops = &ftrace_event_format_fops; - *data = call; return 1; } @@ -2996,7 +3003,7 @@ trace_create_new_event(struct trace_event_call *call, atomic_set(&file->tm_ref, 0); INIT_LIST_HEAD(&file->triggers); list_add(&file->list, &tr->events); - event_file_get(file); + refcount_set(&file->ref, 1); return file; } diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c index 6ece1308d36a02..5f9119eb7c67f6 100644 --- a/kernel/trace/trace_events_hist.c +++ b/kernel/trace/trace_events_hist.c @@ -5601,7 +5601,7 @@ static int hist_show(struct seq_file *m, void *v) mutex_lock(&event_mutex); - event_file = event_file_data(m->private); + event_file = event_file_file(m->private); if (unlikely(!event_file)) { ret = -ENODEV; goto out_unlock; @@ -5880,7 +5880,7 @@ static int hist_debug_show(struct seq_file *m, void *v) mutex_lock(&event_mutex); - event_file = event_file_data(m->private); + event_file = event_file_file(m->private); if (unlikely(!event_file)) { ret = -ENODEV; goto out_unlock; diff --git a/kernel/trace/trace_events_inject.c b/kernel/trace/trace_events_inject.c index 8650562bdaa988..a8f076809db4d5 100644 --- a/kernel/trace/trace_events_inject.c +++ b/kernel/trace/trace_events_inject.c @@ -299,7 +299,7 @@ event_inject_write(struct file *filp, const char __user *ubuf, size_t cnt, strim(buf); mutex_lock(&event_mutex); - file = event_file_data(filp); + file = event_file_file(filp); if (file) { call = file->event_call; size = parse_entry(buf, call, &entry); diff --git a/kernel/trace/trace_events_trigger.c b/kernel/trace/trace_events_trigger.c index 4bec043c8690d3..a5e3d6acf1e1e2 100644 --- a/kernel/trace/trace_events_trigger.c +++ b/kernel/trace/trace_events_trigger.c @@ -159,7 +159,7 @@ static void *trigger_start(struct seq_file *m, loff_t *pos) /* ->stop() is called even if ->start() fails */ mutex_lock(&event_mutex); - event_file = event_file_data(m->private); + event_file = event_file_file(m->private); if (unlikely(!event_file)) return ERR_PTR(-ENODEV); @@ -213,7 +213,7 @@ static int event_trigger_regex_open(struct inode *inode, struct file *file) mutex_lock(&event_mutex); - if (unlikely(!event_file_data(file))) { + if (unlikely(!event_file_file(file))) { mutex_unlock(&event_mutex); return -ENODEV; } @@ -293,7 +293,7 @@ static ssize_t event_trigger_regex_write(struct file *file, strim(buf); mutex_lock(&event_mutex); - event_file = event_file_data(file); + event_file = event_file_file(file); if (unlikely(!event_file)) { mutex_unlock(&event_mutex); kfree(buf); diff --git a/kernel/trace/tracing_map.c b/kernel/trace/tracing_map.c index a4dcf0f2435213..3a56e7c8aa4f67 100644 --- a/kernel/trace/tracing_map.c +++ b/kernel/trace/tracing_map.c @@ -454,7 +454,7 @@ static struct tracing_map_elt *get_free_elt(struct tracing_map *map) struct tracing_map_elt *elt = NULL; int idx; - idx = atomic_inc_return(&map->next_elt); + idx = atomic_fetch_add_unless(&map->next_elt, 1, map->max_elts); if (idx < map->max_elts) { elt = *(TRACING_MAP_ELT(map->elts, idx)); if (map->ops && map->ops->elt_init) @@ -699,7 +699,7 @@ void tracing_map_clear(struct tracing_map *map) { unsigned int i; - atomic_set(&map->next_elt, -1); + atomic_set(&map->next_elt, 0); atomic64_set(&map->hits, 0); atomic64_set(&map->drops, 0); @@ -783,7 +783,7 @@ struct tracing_map *tracing_map_create(unsigned int map_bits, map->map_bits = map_bits; map->max_elts = (1 << map_bits); - atomic_set(&map->next_elt, -1); + atomic_set(&map->next_elt, 0); map->map_size = (1 << (map_bits + 1)); map->ops = ops; diff --git a/lib/btree.c b/lib/btree.c index 49420cae3a8330..bb81d3393ac5c5 100644 --- a/lib/btree.c +++ b/lib/btree.c @@ -43,7 +43,6 @@ #include #include -#define MAX(a, b) ((a) > (b) ? (a) : (b)) #define NODESIZE MAX(L1_CACHE_BYTES, 128) struct btree_geo { diff --git a/lib/decompress_unlzma.c b/lib/decompress_unlzma.c index 20a858031f12b7..9d34d35908daa8 100644 --- a/lib/decompress_unlzma.c +++ b/lib/decompress_unlzma.c @@ -37,7 +37,9 @@ #include +#ifndef MIN #define MIN(a, b) (((a) < (b)) ? (a) : (b)) +#endif static long long INIT read_int(unsigned char *ptr, int size) { diff --git a/lib/generic-radix-tree.c b/lib/generic-radix-tree.c index aaefb9b678c8e4..fa692c86f06969 100644 --- a/lib/generic-radix-tree.c +++ b/lib/generic-radix-tree.c @@ -121,6 +121,8 @@ void *__genradix_ptr_alloc(struct __genradix *radix, size_t offset, if ((v = cmpxchg_release(&radix->root, r, new_root)) == r) { v = new_root; new_node = NULL; + } else { + new_node->children[0] = NULL; } } diff --git a/lib/overflow_kunit.c b/lib/overflow_kunit.c index f314a0c15a6d83..2abc78367dd110 100644 --- a/lib/overflow_kunit.c +++ b/lib/overflow_kunit.c @@ -668,7 +668,6 @@ DEFINE_TEST_ALLOC(devm_kzalloc, devm_kfree, 1, 1, 0); static void overflow_allocation_test(struct kunit *test) { - const char device_name[] = "overflow-test"; struct device *dev; int count = 0; @@ -678,7 +677,7 @@ static void overflow_allocation_test(struct kunit *test) } while (0) /* Create dummy device for devm_kmalloc()-family tests. */ - dev = kunit_device_register(test, device_name); + dev = kunit_device_register(test, "overflow-test"); KUNIT_ASSERT_FALSE_MSG(test, IS_ERR(dev), "Cannot register test device\n"); diff --git a/lib/vsprintf.c b/lib/vsprintf.c index cdd4e2314bfc6e..2d71b11159161b 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -1080,7 +1080,7 @@ char *resource_string(char *buf, char *end, struct resource *res, #define FLAG_BUF_SIZE (2 * sizeof(res->flags)) #define DECODED_BUF_SIZE sizeof("[mem - 64bit pref window disabled]") #define RAW_BUF_SIZE sizeof("[mem - flags 0x]") - char sym[max(2*RSRC_BUF_SIZE + DECODED_BUF_SIZE, + char sym[MAX(2*RSRC_BUF_SIZE + DECODED_BUF_SIZE, 2*RSRC_BUF_SIZE + FLAG_BUF_SIZE + RAW_BUF_SIZE)]; char *p = sym, *pend = sym + sizeof(sym); diff --git a/mm/huge_memory.c b/mm/huge_memory.c index f4be468e06a49a..67c86a5d64a6a9 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -1685,7 +1685,7 @@ vm_fault_t do_huge_pmd_numa_page(struct vm_fault *vmf) vmf->ptl = pmd_lock(vma->vm_mm, vmf->pmd); if (unlikely(!pmd_same(oldpmd, *vmf->pmd))) { spin_unlock(vmf->ptl); - goto out; + return 0; } pmd = pmd_modify(oldpmd, vma->vm_page_prot); @@ -1728,22 +1728,16 @@ vm_fault_t do_huge_pmd_numa_page(struct vm_fault *vmf) if (!migrate_misplaced_folio(folio, vma, target_nid)) { flags |= TNF_MIGRATED; nid = target_nid; - } else { - flags |= TNF_MIGRATE_FAIL; - vmf->ptl = pmd_lock(vma->vm_mm, vmf->pmd); - if (unlikely(!pmd_same(oldpmd, *vmf->pmd))) { - spin_unlock(vmf->ptl); - goto out; - } - goto out_map; - } - -out: - if (nid != NUMA_NO_NODE) task_numa_fault(last_cpupid, nid, HPAGE_PMD_NR, flags); + return 0; + } - return 0; - + flags |= TNF_MIGRATE_FAIL; + vmf->ptl = pmd_lock(vma->vm_mm, vmf->pmd); + if (unlikely(!pmd_same(oldpmd, *vmf->pmd))) { + spin_unlock(vmf->ptl); + return 0; + } out_map: /* Restore the PMD */ pmd = pmd_modify(oldpmd, vma->vm_page_prot); @@ -1753,7 +1747,10 @@ vm_fault_t do_huge_pmd_numa_page(struct vm_fault *vmf) set_pmd_at(vma->vm_mm, haddr, vmf->pmd, pmd); update_mmu_cache_pmd(vma, vmf->address, vmf->pmd); spin_unlock(vmf->ptl); - goto out; + + if (nid != NUMA_NO_NODE) + task_numa_fault(last_cpupid, nid, HPAGE_PMD_NR, flags); + return 0; } /* diff --git a/mm/hugetlb_vmemmap.c b/mm/hugetlb_vmemmap.c index 829112b0a914c9..0c3f56b3578eba 100644 --- a/mm/hugetlb_vmemmap.c +++ b/mm/hugetlb_vmemmap.c @@ -185,11 +185,11 @@ static int vmemmap_remap_range(unsigned long start, unsigned long end, static inline void free_vmemmap_page(struct page *page) { if (PageReserved(page)) { + memmap_boot_pages_add(-1); free_bootmem_page(page); - mod_node_page_state(page_pgdat(page), NR_MEMMAP_BOOT, -1); } else { + memmap_pages_add(-1); __free_page(page); - mod_node_page_state(page_pgdat(page), NR_MEMMAP, -1); } } @@ -341,7 +341,7 @@ static int vmemmap_remap_free(unsigned long start, unsigned long end, copy_page(page_to_virt(walk.reuse_page), (void *)walk.reuse_addr); list_add(&walk.reuse_page->lru, vmemmap_pages); - mod_node_page_state(NODE_DATA(nid), NR_MEMMAP, 1); + memmap_pages_add(1); } /* @@ -392,14 +392,11 @@ static int alloc_vmemmap_page_list(unsigned long start, unsigned long end, for (i = 0; i < nr_pages; i++) { page = alloc_pages_node(nid, gfp_mask, 0); - if (!page) { - mod_node_page_state(NODE_DATA(nid), NR_MEMMAP, i); + if (!page) goto out; - } list_add(&page->lru, list); } - - mod_node_page_state(NODE_DATA(nid), NR_MEMMAP, nr_pages); + memmap_pages_add(nr_pages); return 0; out: diff --git a/mm/list_lru.c b/mm/list_lru.c index a29d96929d7c7e..9b7ff06e9d326b 100644 --- a/mm/list_lru.c +++ b/mm/list_lru.c @@ -85,6 +85,7 @@ list_lru_from_memcg_idx(struct list_lru *lru, int nid, int idx) } #endif /* CONFIG_MEMCG */ +/* The caller must ensure the memcg lifetime. */ bool list_lru_add(struct list_lru *lru, struct list_head *item, int nid, struct mem_cgroup *memcg) { @@ -109,14 +110,22 @@ EXPORT_SYMBOL_GPL(list_lru_add); bool list_lru_add_obj(struct list_lru *lru, struct list_head *item) { + bool ret; int nid = page_to_nid(virt_to_page(item)); - struct mem_cgroup *memcg = list_lru_memcg_aware(lru) ? - mem_cgroup_from_slab_obj(item) : NULL; - return list_lru_add(lru, item, nid, memcg); + if (list_lru_memcg_aware(lru)) { + rcu_read_lock(); + ret = list_lru_add(lru, item, nid, mem_cgroup_from_slab_obj(item)); + rcu_read_unlock(); + } else { + ret = list_lru_add(lru, item, nid, NULL); + } + + return ret; } EXPORT_SYMBOL_GPL(list_lru_add_obj); +/* The caller must ensure the memcg lifetime. */ bool list_lru_del(struct list_lru *lru, struct list_head *item, int nid, struct mem_cgroup *memcg) { @@ -139,11 +148,18 @@ EXPORT_SYMBOL_GPL(list_lru_del); bool list_lru_del_obj(struct list_lru *lru, struct list_head *item) { + bool ret; int nid = page_to_nid(virt_to_page(item)); - struct mem_cgroup *memcg = list_lru_memcg_aware(lru) ? - mem_cgroup_from_slab_obj(item) : NULL; - return list_lru_del(lru, item, nid, memcg); + if (list_lru_memcg_aware(lru)) { + rcu_read_lock(); + ret = list_lru_del(lru, item, nid, mem_cgroup_from_slab_obj(item)); + rcu_read_unlock(); + } else { + ret = list_lru_del(lru, item, nid, NULL); + } + + return ret; } EXPORT_SYMBOL_GPL(list_lru_del_obj); diff --git a/mm/memcontrol-v1.c b/mm/memcontrol-v1.c index 2aeea4d8bf8e53..417c96f2da28e8 100644 --- a/mm/memcontrol-v1.c +++ b/mm/memcontrol-v1.c @@ -1842,9 +1842,12 @@ static ssize_t memcg_write_event_control(struct kernfs_open_file *of, buf = endp + 1; cfd = simple_strtoul(buf, &endp, 10); - if ((*endp != ' ') && (*endp != '\0')) + if (*endp == '\0') + buf = endp; + else if (*endp == ' ') + buf = endp + 1; + else return -EINVAL; - buf = endp + 1; event = kzalloc(sizeof(*event), GFP_KERNEL); if (!event) diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 96037178868772..f29157288b7dd6 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -3386,11 +3386,28 @@ static void memcg_wb_domain_size_changed(struct mem_cgroup *memcg) #define MEM_CGROUP_ID_MAX ((1UL << MEM_CGROUP_ID_SHIFT) - 1) static DEFINE_IDR(mem_cgroup_idr); +static DEFINE_SPINLOCK(memcg_idr_lock); + +static int mem_cgroup_alloc_id(void) +{ + int ret; + + idr_preload(GFP_KERNEL); + spin_lock(&memcg_idr_lock); + ret = idr_alloc(&mem_cgroup_idr, NULL, 1, MEM_CGROUP_ID_MAX + 1, + GFP_NOWAIT); + spin_unlock(&memcg_idr_lock); + idr_preload_end(); + return ret; +} static void mem_cgroup_id_remove(struct mem_cgroup *memcg) { if (memcg->id.id > 0) { + spin_lock(&memcg_idr_lock); idr_remove(&mem_cgroup_idr, memcg->id.id); + spin_unlock(&memcg_idr_lock); + memcg->id.id = 0; } } @@ -3524,8 +3541,7 @@ static struct mem_cgroup *mem_cgroup_alloc(struct mem_cgroup *parent) if (!memcg) return ERR_PTR(error); - memcg->id.id = idr_alloc(&mem_cgroup_idr, NULL, - 1, MEM_CGROUP_ID_MAX + 1, GFP_KERNEL); + memcg->id.id = mem_cgroup_alloc_id(); if (memcg->id.id < 0) { error = memcg->id.id; goto fail; @@ -3667,7 +3683,9 @@ static int mem_cgroup_css_online(struct cgroup_subsys_state *css) * publish it here at the end of onlining. This matches the * regular ID destruction during offlining. */ + spin_lock(&memcg_idr_lock); idr_replace(&mem_cgroup_idr, memcg, memcg->id.id); + spin_unlock(&memcg_idr_lock); return 0; offline_kmem: diff --git a/mm/memory-failure.c b/mm/memory-failure.c index 581d3e5c911758..7066fc84f35172 100644 --- a/mm/memory-failure.c +++ b/mm/memory-failure.c @@ -2417,7 +2417,7 @@ struct memory_failure_entry { struct memory_failure_cpu { DECLARE_KFIFO(fifo, struct memory_failure_entry, MEMORY_FAILURE_FIFO_SIZE); - spinlock_t lock; + raw_spinlock_t lock; struct work_struct work; }; @@ -2443,20 +2443,22 @@ void memory_failure_queue(unsigned long pfn, int flags) { struct memory_failure_cpu *mf_cpu; unsigned long proc_flags; + bool buffer_overflow; struct memory_failure_entry entry = { .pfn = pfn, .flags = flags, }; mf_cpu = &get_cpu_var(memory_failure_cpu); - spin_lock_irqsave(&mf_cpu->lock, proc_flags); - if (kfifo_put(&mf_cpu->fifo, entry)) + raw_spin_lock_irqsave(&mf_cpu->lock, proc_flags); + buffer_overflow = !kfifo_put(&mf_cpu->fifo, entry); + if (!buffer_overflow) schedule_work_on(smp_processor_id(), &mf_cpu->work); - else + raw_spin_unlock_irqrestore(&mf_cpu->lock, proc_flags); + put_cpu_var(memory_failure_cpu); + if (buffer_overflow) pr_err("buffer overflow when queuing memory failure at %#lx\n", pfn); - spin_unlock_irqrestore(&mf_cpu->lock, proc_flags); - put_cpu_var(memory_failure_cpu); } EXPORT_SYMBOL_GPL(memory_failure_queue); @@ -2469,9 +2471,9 @@ static void memory_failure_work_func(struct work_struct *work) mf_cpu = container_of(work, struct memory_failure_cpu, work); for (;;) { - spin_lock_irqsave(&mf_cpu->lock, proc_flags); + raw_spin_lock_irqsave(&mf_cpu->lock, proc_flags); gotten = kfifo_get(&mf_cpu->fifo, &entry); - spin_unlock_irqrestore(&mf_cpu->lock, proc_flags); + raw_spin_unlock_irqrestore(&mf_cpu->lock, proc_flags); if (!gotten) break; if (entry.flags & MF_SOFT_OFFLINE) @@ -2501,7 +2503,7 @@ static int __init memory_failure_init(void) for_each_possible_cpu(cpu) { mf_cpu = &per_cpu(memory_failure_cpu, cpu); - spin_lock_init(&mf_cpu->lock); + raw_spin_lock_init(&mf_cpu->lock); INIT_KFIFO(mf_cpu->fifo); INIT_WORK(&mf_cpu->work, memory_failure_work_func); } diff --git a/mm/memory.c b/mm/memory.c index 34f8402d2046f3..3c01d68065be21 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -5295,7 +5295,7 @@ static vm_fault_t do_numa_page(struct vm_fault *vmf) if (unlikely(!pte_same(old_pte, vmf->orig_pte))) { pte_unmap_unlock(vmf->pte, vmf->ptl); - goto out; + return 0; } pte = pte_modify(old_pte, vma->vm_page_prot); @@ -5358,23 +5358,19 @@ static vm_fault_t do_numa_page(struct vm_fault *vmf) if (!migrate_misplaced_folio(folio, vma, target_nid)) { nid = target_nid; flags |= TNF_MIGRATED; - } else { - flags |= TNF_MIGRATE_FAIL; - vmf->pte = pte_offset_map_lock(vma->vm_mm, vmf->pmd, - vmf->address, &vmf->ptl); - if (unlikely(!vmf->pte)) - goto out; - if (unlikely(!pte_same(ptep_get(vmf->pte), vmf->orig_pte))) { - pte_unmap_unlock(vmf->pte, vmf->ptl); - goto out; - } - goto out_map; + task_numa_fault(last_cpupid, nid, nr_pages, flags); + return 0; } -out: - if (nid != NUMA_NO_NODE) - task_numa_fault(last_cpupid, nid, nr_pages, flags); - return 0; + flags |= TNF_MIGRATE_FAIL; + vmf->pte = pte_offset_map_lock(vma->vm_mm, vmf->pmd, + vmf->address, &vmf->ptl); + if (unlikely(!vmf->pte)) + return 0; + if (unlikely(!pte_same(ptep_get(vmf->pte), vmf->orig_pte))) { + pte_unmap_unlock(vmf->pte, vmf->ptl); + return 0; + } out_map: /* * Make it present again, depending on how arch implements @@ -5387,7 +5383,10 @@ static vm_fault_t do_numa_page(struct vm_fault *vmf) numa_rebuild_single_mapping(vmf, vma, vmf->address, vmf->pte, writable); pte_unmap_unlock(vmf->pte, vmf->ptl); - goto out; + + if (nid != NUMA_NO_NODE) + task_numa_fault(last_cpupid, nid, nr_pages, flags); + return 0; } static inline vm_fault_t create_huge_pmd(struct vm_fault *vmf) diff --git a/mm/migrate.c b/mm/migrate.c index e7296c0fb5d57a..923ea80ba7442b 100644 --- a/mm/migrate.c +++ b/mm/migrate.c @@ -1479,11 +1479,17 @@ static int unmap_and_move_huge_page(new_folio_t get_new_folio, return rc; } -static inline int try_split_folio(struct folio *folio, struct list_head *split_folios) +static inline int try_split_folio(struct folio *folio, struct list_head *split_folios, + enum migrate_mode mode) { int rc; - folio_lock(folio); + if (mode == MIGRATE_ASYNC) { + if (!folio_trylock(folio)) + return -EAGAIN; + } else { + folio_lock(folio); + } rc = split_folio_to_list(folio, split_folios); folio_unlock(folio); if (!rc) @@ -1677,7 +1683,7 @@ static int migrate_pages_batch(struct list_head *from, */ if (nr_pages > 2 && !list_empty(&folio->_deferred_list)) { - if (try_split_folio(folio, split_folios) == 0) { + if (!try_split_folio(folio, split_folios, mode)) { nr_failed++; stats->nr_thp_failed += is_thp; stats->nr_thp_split += is_thp; @@ -1699,7 +1705,7 @@ static int migrate_pages_batch(struct list_head *from, if (!thp_migration_supported() && is_thp) { nr_failed++; stats->nr_thp_failed++; - if (!try_split_folio(folio, split_folios)) { + if (!try_split_folio(folio, split_folios, mode)) { stats->nr_thp_split++; stats->nr_split++; continue; @@ -1731,7 +1737,7 @@ static int migrate_pages_batch(struct list_head *from, stats->nr_thp_failed += is_thp; /* Large folio NUMA faulting doesn't split to retry. */ if (is_large && !nosplit) { - int ret = try_split_folio(folio, split_folios); + int ret = try_split_folio(folio, split_folios, mode); if (!ret) { stats->nr_thp_split += is_thp; diff --git a/mm/mm_init.c b/mm/mm_init.c index 75c3bd42799b93..51960079875baa 100644 --- a/mm/mm_init.c +++ b/mm/mm_init.c @@ -1623,8 +1623,7 @@ static void __init alloc_node_mem_map(struct pglist_data *pgdat) panic("Failed to allocate %ld bytes for node %d memory map\n", size, pgdat->node_id); pgdat->node_mem_map = map + offset; - mod_node_early_perpage_metadata(pgdat->node_id, - DIV_ROUND_UP(size, PAGE_SIZE)); + memmap_boot_pages_add(DIV_ROUND_UP(size, PAGE_SIZE)); pr_debug("%s: node %d, pgdat %08lx, node_mem_map %08lx\n", __func__, pgdat->node_id, (unsigned long)pgdat, (unsigned long)pgdat->node_mem_map); @@ -2245,6 +2244,8 @@ void __init init_cma_reserved_pageblock(struct page *page) set_pageblock_migratetype(page, MIGRATE_CMA); set_page_refcounted(page); + /* pages were reserved and not allocated */ + clear_page_tag_ref(page); __free_pages(page, pageblock_order); adjust_managed_page_count(page, pageblock_nr_pages); @@ -2460,15 +2461,7 @@ void __init memblock_free_pages(struct page *page, unsigned long pfn, } /* pages were reserved and not allocated */ - if (mem_alloc_profiling_enabled()) { - union codetag_ref *ref = get_page_tag_ref(page); - - if (ref) { - set_codetag_empty(ref); - put_page_tag_ref(ref); - } - } - + clear_page_tag_ref(page); __free_pages_core(page, order, MEMINIT_EARLY); } diff --git a/mm/mseal.c b/mm/mseal.c index bf783bba8ed0b9..15bba28acc005f 100644 --- a/mm/mseal.c +++ b/mm/mseal.c @@ -40,9 +40,17 @@ static bool can_modify_vma(struct vm_area_struct *vma) static bool is_madv_discard(int behavior) { - return behavior & - (MADV_FREE | MADV_DONTNEED | MADV_DONTNEED_LOCKED | - MADV_REMOVE | MADV_DONTFORK | MADV_WIPEONFORK); + switch (behavior) { + case MADV_FREE: + case MADV_DONTNEED: + case MADV_DONTNEED_LOCKED: + case MADV_REMOVE: + case MADV_DONTFORK: + case MADV_WIPEONFORK: + return true; + } + + return false; } static bool is_ro_anon(struct vm_area_struct *vma) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 28f80daf5c0418..c565de8f48e9d8 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -287,7 +287,7 @@ EXPORT_SYMBOL(nr_online_nodes); static bool page_contains_unaccepted(struct page *page, unsigned int order); static void accept_page(struct page *page, unsigned int order); -static bool try_to_accept_memory(struct zone *zone, unsigned int order); +static bool cond_accept_memory(struct zone *zone, unsigned int order); static inline bool has_unaccepted_memory(void); static bool __free_unaccepted(struct page *page); @@ -3072,9 +3072,6 @@ static inline long __zone_watermark_unusable_free(struct zone *z, if (!(alloc_flags & ALLOC_CMA)) unusable_free += zone_page_state(z, NR_FREE_CMA_PAGES); #endif -#ifdef CONFIG_UNACCEPTED_MEMORY - unusable_free += zone_page_state(z, NR_UNACCEPTED); -#endif return unusable_free; } @@ -3368,6 +3365,8 @@ get_page_from_freelist(gfp_t gfp_mask, unsigned int order, int alloc_flags, } } + cond_accept_memory(zone, order); + /* * Detect whether the number of free pages is below high * watermark. If so, we will decrease pcp->high and free @@ -3393,10 +3392,8 @@ get_page_from_freelist(gfp_t gfp_mask, unsigned int order, int alloc_flags, gfp_mask)) { int ret; - if (has_unaccepted_memory()) { - if (try_to_accept_memory(zone, order)) - goto try_this_zone; - } + if (cond_accept_memory(zone, order)) + goto try_this_zone; #ifdef CONFIG_DEFERRED_STRUCT_PAGE_INIT /* @@ -3450,10 +3447,8 @@ get_page_from_freelist(gfp_t gfp_mask, unsigned int order, int alloc_flags, return page; } else { - if (has_unaccepted_memory()) { - if (try_to_accept_memory(zone, order)) - goto try_this_zone; - } + if (cond_accept_memory(zone, order)) + goto try_this_zone; #ifdef CONFIG_DEFERRED_STRUCT_PAGE_INIT /* Try again if zone has deferred pages */ @@ -5755,7 +5750,6 @@ void __init setup_per_cpu_pageset(void) for_each_online_pgdat(pgdat) pgdat->per_cpu_nodestats = alloc_percpu(struct per_cpu_nodestat); - store_early_perpage_metadata(); } __meminit void zone_pcp_init(struct zone *zone) @@ -5821,14 +5815,7 @@ unsigned long free_reserved_area(void *start, void *end, int poison, const char void free_reserved_page(struct page *page) { - if (mem_alloc_profiling_enabled()) { - union codetag_ref *ref = get_page_tag_ref(page); - - if (ref) { - set_codetag_empty(ref); - put_page_tag_ref(ref); - } - } + clear_page_tag_ref(page); ClearPageReserved(page); init_page_count(page); __free_page(page); @@ -6951,9 +6938,6 @@ static bool try_to_accept_memory_one(struct zone *zone) struct page *page; bool last; - if (list_empty(&zone->unaccepted_pages)) - return false; - spin_lock_irqsave(&zone->lock, flags); page = list_first_entry_or_null(&zone->unaccepted_pages, struct page, lru); @@ -6979,23 +6963,29 @@ static bool try_to_accept_memory_one(struct zone *zone) return true; } -static bool try_to_accept_memory(struct zone *zone, unsigned int order) +static bool cond_accept_memory(struct zone *zone, unsigned int order) { long to_accept; - int ret = false; + bool ret = false; + + if (!has_unaccepted_memory()) + return false; + + if (list_empty(&zone->unaccepted_pages)) + return false; /* How much to accept to get to high watermark? */ to_accept = high_wmark_pages(zone) - (zone_page_state(zone, NR_FREE_PAGES) - - __zone_watermark_unusable_free(zone, order, 0)); + __zone_watermark_unusable_free(zone, order, 0) - + zone_page_state(zone, NR_UNACCEPTED)); - /* Accept at least one page */ - do { + while (to_accept > 0) { if (!try_to_accept_memory_one(zone)) break; ret = true; to_accept -= MAX_ORDER_NR_PAGES; - } while (to_accept > 0); + } return ret; } @@ -7038,7 +7028,7 @@ static void accept_page(struct page *page, unsigned int order) { } -static bool try_to_accept_memory(struct zone *zone, unsigned int order) +static bool cond_accept_memory(struct zone *zone, unsigned int order) { return false; } diff --git a/mm/page_ext.c b/mm/page_ext.c index c191e490c401ba..641d93f6af4c1e 100644 --- a/mm/page_ext.c +++ b/mm/page_ext.c @@ -214,8 +214,7 @@ static int __init alloc_node_page_ext(int nid) return -ENOMEM; NODE_DATA(nid)->node_page_ext = base; total_usage += table_size; - mod_node_page_state(NODE_DATA(nid), NR_MEMMAP_BOOT, - DIV_ROUND_UP(table_size, PAGE_SIZE)); + memmap_boot_pages_add(DIV_ROUND_UP(table_size, PAGE_SIZE)); return 0; } @@ -275,10 +274,8 @@ static void *__meminit alloc_page_ext(size_t size, int nid) else addr = vzalloc_node(size, nid); - if (addr) { - mod_node_page_state(NODE_DATA(nid), NR_MEMMAP, - DIV_ROUND_UP(size, PAGE_SIZE)); - } + if (addr) + memmap_pages_add(DIV_ROUND_UP(size, PAGE_SIZE)); return addr; } @@ -323,25 +320,18 @@ static void free_page_ext(void *addr) { size_t table_size; struct page *page; - struct pglist_data *pgdat; table_size = page_ext_size * PAGES_PER_SECTION; + memmap_pages_add(-1L * (DIV_ROUND_UP(table_size, PAGE_SIZE))); if (is_vmalloc_addr(addr)) { - page = vmalloc_to_page(addr); - pgdat = page_pgdat(page); vfree(addr); } else { page = virt_to_page(addr); - pgdat = page_pgdat(page); BUG_ON(PageReserved(page)); kmemleak_free(addr); free_pages_exact(addr, table_size); } - - mod_node_page_state(pgdat, NR_MEMMAP, - -1L * (DIV_ROUND_UP(table_size, PAGE_SIZE))); - } static void __free_page_ext(unsigned long pfn) diff --git a/mm/shmem.c b/mm/shmem.c index 2faa9daaf54baa..5a77acf6ac6a62 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -1629,11 +1629,6 @@ unsigned long shmem_allowable_huge_orders(struct inode *inode, unsigned long mask = READ_ONCE(huge_shmem_orders_always); unsigned long within_size_orders = READ_ONCE(huge_shmem_orders_within_size); unsigned long vm_flags = vma->vm_flags; - /* - * Check all the (large) orders below HPAGE_PMD_ORDER + 1 that - * are enabled for this vma. - */ - unsigned long orders = BIT(PMD_ORDER + 1) - 1; loff_t i_size; int order; @@ -1678,7 +1673,7 @@ unsigned long shmem_allowable_huge_orders(struct inode *inode, if (global_huge) mask |= READ_ONCE(huge_shmem_orders_inherit); - return orders & mask; + return THP_ORDERS_ALL_FILE_DEFAULT & mask; } static unsigned long shmem_suitable_orders(struct inode *inode, struct vm_fault *vmf, @@ -1686,6 +1681,7 @@ static unsigned long shmem_suitable_orders(struct inode *inode, struct vm_fault unsigned long orders) { struct vm_area_struct *vma = vmf->vma; + pgoff_t aligned_index; unsigned long pages; int order; @@ -1697,9 +1693,9 @@ static unsigned long shmem_suitable_orders(struct inode *inode, struct vm_fault order = highest_order(orders); while (orders) { pages = 1UL << order; - index = round_down(index, pages); - if (!xa_find(&mapping->i_pages, &index, - index + pages - 1, XA_PRESENT)) + aligned_index = round_down(index, pages); + if (!xa_find(&mapping->i_pages, &aligned_index, + aligned_index + pages - 1, XA_PRESENT)) break; order = next_order(&orders, order); } diff --git a/mm/slub.c b/mm/slub.c index 3520acaf9afaf3..c9d8a2497fd65e 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -4690,6 +4690,9 @@ static void __kmem_cache_free_bulk(struct kmem_cache *s, size_t size, void **p) if (!df.slab) continue; + if (kfence_free(df.freelist)) + continue; + do_slab_free(df.s, df.slab, df.freelist, df.tail, df.cnt, _RET_IP_); } while (likely(size)); diff --git a/mm/sparse-vmemmap.c b/mm/sparse-vmemmap.c index 1dda6c53370b0a..edcc7a6b0f6f20 100644 --- a/mm/sparse-vmemmap.c +++ b/mm/sparse-vmemmap.c @@ -469,13 +469,10 @@ struct page * __meminit __populate_section_memmap(unsigned long pfn, if (r < 0) return NULL; - if (system_state == SYSTEM_BOOTING) { - mod_node_early_perpage_metadata(nid, DIV_ROUND_UP(end - start, - PAGE_SIZE)); - } else { - mod_node_page_state(NODE_DATA(nid), NR_MEMMAP, - DIV_ROUND_UP(end - start, PAGE_SIZE)); - } + if (system_state == SYSTEM_BOOTING) + memmap_boot_pages_add(DIV_ROUND_UP(end - start, PAGE_SIZE)); + else + memmap_pages_add(DIV_ROUND_UP(end - start, PAGE_SIZE)); return pfn_to_page(pfn); } diff --git a/mm/sparse.c b/mm/sparse.c index e4b830091d1373..0f018c6f9ec52f 100644 --- a/mm/sparse.c +++ b/mm/sparse.c @@ -463,7 +463,7 @@ static void __init sparse_buffer_init(unsigned long size, int nid) sparsemap_buf = memmap_alloc(size, section_map_size(), addr, nid, true); sparsemap_buf_end = sparsemap_buf + size; #ifndef CONFIG_SPARSEMEM_VMEMMAP - mod_node_early_perpage_metadata(nid, DIV_ROUND_UP(size, PAGE_SIZE)); + memmap_boot_pages_add(DIV_ROUND_UP(size, PAGE_SIZE)); #endif } @@ -643,8 +643,7 @@ static void depopulate_section_memmap(unsigned long pfn, unsigned long nr_pages, unsigned long start = (unsigned long) pfn_to_page(pfn); unsigned long end = start + nr_pages * sizeof(struct page); - mod_node_page_state(page_pgdat(pfn_to_page(pfn)), NR_MEMMAP, - -1L * (DIV_ROUND_UP(end - start, PAGE_SIZE))); + memmap_pages_add(-1L * (DIV_ROUND_UP(end - start, PAGE_SIZE))); vmemmap_free(start, end, altmap); } static void free_map_bootmem(struct page *memmap) diff --git a/mm/vmalloc.c b/mm/vmalloc.c index 6b783baf12a143..af2de36549d608 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c @@ -3584,15 +3584,8 @@ vm_area_alloc_pages(gfp_t gfp, int nid, page = alloc_pages_noprof(alloc_gfp, order); else page = alloc_pages_node_noprof(nid, alloc_gfp, order); - if (unlikely(!page)) { - if (!nofail) - break; - - /* fall back to the zero order allocations */ - alloc_gfp |= __GFP_NOFAIL; - order = 0; - continue; - } + if (unlikely(!page)) + break; /* * Higher order allocations must be able to be treated as diff --git a/mm/vmstat.c b/mm/vmstat.c index 04a1cb6cc6365a..e875f2a4915f5f 100644 --- a/mm/vmstat.c +++ b/mm/vmstat.c @@ -1033,6 +1033,24 @@ unsigned long node_page_state(struct pglist_data *pgdat, } #endif +/* + * Count number of pages "struct page" and "struct page_ext" consume. + * nr_memmap_boot_pages: # of pages allocated by boot allocator + * nr_memmap_pages: # of pages that were allocated by buddy allocator + */ +static atomic_long_t nr_memmap_boot_pages = ATOMIC_LONG_INIT(0); +static atomic_long_t nr_memmap_pages = ATOMIC_LONG_INIT(0); + +void memmap_boot_pages_add(long delta) +{ + atomic_long_add(delta, &nr_memmap_boot_pages); +} + +void memmap_pages_add(long delta) +{ + atomic_long_add(delta, &nr_memmap_pages); +} + #ifdef CONFIG_COMPACTION struct contig_page_info { @@ -1255,11 +1273,11 @@ const char * const vmstat_text[] = { "pgdemote_kswapd", "pgdemote_direct", "pgdemote_khugepaged", - "nr_memmap", - "nr_memmap_boot", - /* enum writeback_stat_item counters */ + /* system-wide enum vm_stat_item counters */ "nr_dirty_threshold", "nr_dirty_background_threshold", + "nr_memmap_pages", + "nr_memmap_boot_pages", #if defined(CONFIG_VM_EVENT_COUNTERS) || defined(CONFIG_MEMCG) /* enum vm_event_item counters */ @@ -1790,7 +1808,7 @@ static const struct seq_operations zoneinfo_op = { #define NR_VMSTAT_ITEMS (NR_VM_ZONE_STAT_ITEMS + \ NR_VM_NUMA_EVENT_ITEMS + \ NR_VM_NODE_STAT_ITEMS + \ - NR_VM_WRITEBACK_STAT_ITEMS + \ + NR_VM_STAT_ITEMS + \ (IS_ENABLED(CONFIG_VM_EVENT_COUNTERS) ? \ NR_VM_EVENT_ITEMS : 0)) @@ -1827,7 +1845,9 @@ static void *vmstat_start(struct seq_file *m, loff_t *pos) global_dirty_limits(v + NR_DIRTY_BG_THRESHOLD, v + NR_DIRTY_THRESHOLD); - v += NR_VM_WRITEBACK_STAT_ITEMS; + v[NR_MEMMAP_PAGES] = atomic_long_read(&nr_memmap_pages); + v[NR_MEMMAP_BOOT_PAGES] = atomic_long_read(&nr_memmap_boot_pages); + v += NR_VM_STAT_ITEMS; #ifdef CONFIG_VM_EVENT_COUNTERS all_vm_events(v); @@ -2285,25 +2305,3 @@ static int __init extfrag_debug_init(void) module_init(extfrag_debug_init); #endif - -/* - * Page metadata size (struct page and page_ext) in pages - */ -static unsigned long early_perpage_metadata[MAX_NUMNODES] __meminitdata; - -void __meminit mod_node_early_perpage_metadata(int nid, long delta) -{ - early_perpage_metadata[nid] += delta; -} - -void __meminit store_early_perpage_metadata(void) -{ - int nid; - struct pglist_data *pgdat; - - for_each_online_pgdat(pgdat) { - nid = pgdat->node_id; - mod_node_page_state(NODE_DATA(nid), NR_MEMMAP_BOOT, - early_perpage_metadata[nid]); - } -} diff --git a/mm/zsmalloc.c b/mm/zsmalloc.c index 5d6581ab7c073d..2d3163e4da96a5 100644 --- a/mm/zsmalloc.c +++ b/mm/zsmalloc.c @@ -120,8 +120,6 @@ #define CLASS_BITS 8 #define MAGIC_VAL_BITS 8 -#define MAX(a, b) ((a) >= (b) ? (a) : (b)) - #define ZS_MAX_PAGES_PER_ZSPAGE (_AC(CONFIG_ZSMALLOC_CHAIN_SIZE, UL)) /* ZS_MIN_ALLOC_SIZE must be multiple of ZS_ALIGN */ diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 8a4ebd93adfcd7..06da8ac13dca8e 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -119,13 +119,6 @@ void hci_discovery_set_state(struct hci_dev *hdev, int state) case DISCOVERY_STARTING: break; case DISCOVERY_FINDING: - /* If discovery was not started then it was initiated by the - * MGMT interface so no MGMT event shall be generated either - */ - if (old_state != DISCOVERY_STARTING) { - hdev->discovery.state = old_state; - return; - } mgmt_discovering(hdev, 1); break; case DISCOVERY_RESOLVING: diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index dce8035ca7990c..d0c118c47f6c93 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -1721,9 +1721,10 @@ static void le_set_scan_enable_complete(struct hci_dev *hdev, u8 enable) switch (enable) { case LE_SCAN_ENABLE: hci_dev_set_flag(hdev, HCI_LE_SCAN); - if (hdev->le_scan_type == LE_SCAN_ACTIVE) + if (hdev->le_scan_type == LE_SCAN_ACTIVE) { clear_pending_adv_report(hdev); - hci_discovery_set_state(hdev, DISCOVERY_FINDING); + hci_discovery_set_state(hdev, DISCOVERY_FINDING); + } break; case LE_SCAN_DISABLE: diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c index cd2ed16da8a466..e79cd40bd079df 100644 --- a/net/bluetooth/hci_sync.c +++ b/net/bluetooth/hci_sync.c @@ -2976,6 +2976,27 @@ static int hci_passive_scan_sync(struct hci_dev *hdev) */ filter_policy = hci_update_accept_list_sync(hdev); + /* If suspended and filter_policy set to 0x00 (no acceptlist) then + * passive scanning cannot be started since that would require the host + * to be woken up to process the reports. + */ + if (hdev->suspended && !filter_policy) { + /* Check if accept list is empty then there is no need to scan + * while suspended. + */ + if (list_empty(&hdev->le_accept_list)) + return 0; + + /* If there are devices is the accept_list that means some + * devices could not be programmed which in non-suspended case + * means filter_policy needs to be set to 0x00 so the host needs + * to filter, but since this is treating suspended case we + * can ignore device needing host to filter to allow devices in + * the acceptlist to be able to wakeup the system. + */ + filter_policy = 0x01; + } + /* When the controller is using random resolvable addresses and * with that having LE privacy enabled, then controllers with * Extended Scanner Filter Policies support can now enable support @@ -2998,6 +3019,20 @@ static int hci_passive_scan_sync(struct hci_dev *hdev) } else if (hci_is_adv_monitoring(hdev)) { window = hdev->le_scan_window_adv_monitor; interval = hdev->le_scan_int_adv_monitor; + + /* Disable duplicates filter when scanning for advertisement + * monitor for the following reasons. + * + * For HW pattern filtering (ex. MSFT), Realtek and Qualcomm + * controllers ignore RSSI_Sampling_Period when the duplicates + * filter is enabled. + * + * For SW pattern filtering, when we're not doing interleaved + * scanning, it is necessary to disable duplicates filter, + * otherwise hosts can only receive one advertisement and it's + * impossible to know if a peer is still in range. + */ + filter_dups = LE_SCAN_FILTER_DUP_DISABLE; } else { window = hdev->le_scan_window; interval = hdev->le_scan_interval; diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index c3c26bbb5ddaeb..9988ba382b686a 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -6774,6 +6774,7 @@ static void l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, bt_cb(skb)->l2cap.psm = psm; if (!chan->ops->recv(chan, skb)) { + l2cap_chan_unlock(chan); l2cap_chan_put(chan); return; } diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 9a1cb5079a7a07..b2ae0d2434d2eb 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -2045,16 +2045,14 @@ void br_multicast_del_port(struct net_bridge_port *port) { struct net_bridge *br = port->br; struct net_bridge_port_group *pg; - HLIST_HEAD(deleted_head); struct hlist_node *n; /* Take care of the remaining groups, only perm ones should be left */ spin_lock_bh(&br->multicast_lock); hlist_for_each_entry_safe(pg, n, &port->mglist, mglist) br_multicast_find_del_pg(br, pg); - hlist_move_list(&br->mcast_gc_list, &deleted_head); spin_unlock_bh(&br->multicast_lock); - br_multicast_gc(&deleted_head); + flush_work(&br->mcast_gc_work); br_multicast_port_ctx_deinit(&port->multicast_ctx); free_percpu(port->mcast_stats); } diff --git a/net/bridge/br_netfilter_hooks.c b/net/bridge/br_netfilter_hooks.c index 09f6a773a7080a..8f9c19d992ac5c 100644 --- a/net/bridge/br_netfilter_hooks.c +++ b/net/bridge/br_netfilter_hooks.c @@ -622,8 +622,12 @@ static unsigned int br_nf_local_in(void *priv, if (likely(nf_ct_is_confirmed(ct))) return NF_ACCEPT; + if (WARN_ON_ONCE(refcount_read(&nfct->use) != 1)) { + nf_reset_ct(skb); + return NF_ACCEPT; + } + WARN_ON_ONCE(skb_shared(skb)); - WARN_ON_ONCE(refcount_read(&nfct->use) != 1); /* We can't call nf_confirm here, it would create a dependency * on nf_conntrack module. diff --git a/net/core/dev.c b/net/core/dev.c index 6ea1d20676fbe9..f66e6140788328 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -5150,6 +5150,7 @@ int do_xdp_generic(struct bpf_prog *xdp_prog, struct sk_buff **pskb) bpf_net_ctx_clear(bpf_net_ctx); return XDP_DROP; } + bpf_net_ctx_clear(bpf_net_ctx); } return XDP_PASS; out_redir: @@ -9911,6 +9912,15 @@ static void netdev_sync_lower_features(struct net_device *upper, } } +static bool netdev_has_ip_or_hw_csum(netdev_features_t features) +{ + netdev_features_t ip_csum_mask = NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM; + bool ip_csum = (features & ip_csum_mask) == ip_csum_mask; + bool hw_csum = features & NETIF_F_HW_CSUM; + + return ip_csum || hw_csum; +} + static netdev_features_t netdev_fix_features(struct net_device *dev, netdev_features_t features) { @@ -9992,15 +10002,9 @@ static netdev_features_t netdev_fix_features(struct net_device *dev, features &= ~NETIF_F_LRO; } - if (features & NETIF_F_HW_TLS_TX) { - bool ip_csum = (features & (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM)) == - (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM); - bool hw_csum = features & NETIF_F_HW_CSUM; - - if (!ip_csum && !hw_csum) { - netdev_dbg(dev, "Dropping TLS TX HW offload feature since no CSUM feature.\n"); - features &= ~NETIF_F_HW_TLS_TX; - } + if ((features & NETIF_F_HW_TLS_TX) && !netdev_has_ip_or_hw_csum(features)) { + netdev_dbg(dev, "Dropping TLS TX HW offload feature since no CSUM feature.\n"); + features &= ~NETIF_F_HW_TLS_TX; } if ((features & NETIF_F_HW_TLS_RX) && !(features & NETIF_F_RXCSUM)) { @@ -10008,6 +10012,11 @@ static netdev_features_t netdev_fix_features(struct net_device *dev, features &= ~NETIF_F_HW_TLS_RX; } + if ((features & NETIF_F_GSO_UDP_L4) && !netdev_has_ip_or_hw_csum(features)) { + netdev_dbg(dev, "Dropping USO feature since no CSUM feature.\n"); + features &= ~NETIF_F_GSO_UDP_L4; + } + return features; } diff --git a/net/core/link_watch.c b/net/core/link_watch.c index 8ec35194bfcb85..ab150641142aa1 100644 --- a/net/core/link_watch.c +++ b/net/core/link_watch.c @@ -148,9 +148,9 @@ static void linkwatch_schedule_work(int urgent) * override the existing timer. */ if (test_bit(LW_URGENT, &linkwatch_flags)) - mod_delayed_work(system_wq, &linkwatch_work, 0); + mod_delayed_work(system_unbound_wq, &linkwatch_work, 0); else - schedule_delayed_work(&linkwatch_work, delay); + queue_delayed_work(system_unbound_wq, &linkwatch_work, delay); } diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 87e67194f24046..73fd7f543fd095 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -3288,7 +3288,7 @@ static int rtnl_dellink(struct sk_buff *skb, struct nlmsghdr *nlh, if (ifm->ifi_index > 0) dev = __dev_get_by_index(tgt_net, ifm->ifi_index); else if (tb[IFLA_IFNAME] || tb[IFLA_ALT_IFNAME]) - dev = rtnl_dev_get(net, tb); + dev = rtnl_dev_get(tgt_net, tb); else if (tb[IFLA_GROUP]) err = rtnl_group_dellink(tgt_net, nla_get_u32(tb[IFLA_GROUP])); else diff --git a/net/ethtool/cmis_fw_update.c b/net/ethtool/cmis_fw_update.c index ae4b4b28a6014f..655ff5224ffa30 100644 --- a/net/ethtool/cmis_fw_update.c +++ b/net/ethtool/cmis_fw_update.c @@ -35,7 +35,10 @@ struct cmis_cdb_fw_mng_features_rpl { __be16 resv7; }; -#define CMIS_CDB_FW_WRITE_MECHANISM_LPL 0x01 +enum cmis_cdb_fw_write_mechanism { + CMIS_CDB_FW_WRITE_MECHANISM_LPL = 0x01, + CMIS_CDB_FW_WRITE_MECHANISM_BOTH = 0x11, +}; static int cmis_fw_update_fw_mng_features_get(struct ethtool_cmis_cdb *cdb, @@ -64,7 +67,8 @@ cmis_fw_update_fw_mng_features_get(struct ethtool_cmis_cdb *cdb, } rpl = (struct cmis_cdb_fw_mng_features_rpl *)args.req.payload; - if (!(rpl->write_mechanism == CMIS_CDB_FW_WRITE_MECHANISM_LPL)) { + if (!(rpl->write_mechanism == CMIS_CDB_FW_WRITE_MECHANISM_LPL || + rpl->write_mechanism == CMIS_CDB_FW_WRITE_MECHANISM_BOTH)) { ethnl_module_fw_flash_ntf_err(dev, ntf_params, "Write LPL is not supported", NULL); diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c index 983fee76f5cf15..e18823bf23306d 100644 --- a/net/ethtool/ioctl.c +++ b/net/ethtool/ioctl.c @@ -1331,13 +1331,13 @@ static noinline_for_stack int ethtool_set_rxfh(struct net_device *dev, u32 rss_cfg_offset = offsetof(struct ethtool_rxfh, rss_config[0]); const struct ethtool_ops *ops = dev->ethtool_ops; u32 dev_indir_size = 0, dev_key_size = 0, i; + u32 user_indir_len = 0, indir_bytes = 0; struct ethtool_rxfh_param rxfh_dev = {}; struct ethtool_rxfh_context *ctx = NULL; struct netlink_ext_ack *extack = NULL; struct ethtool_rxnfc rx_rings; struct ethtool_rxfh rxfh; bool locked = false; /* dev->ethtool->rss_lock taken */ - u32 indir_bytes = 0; bool create = false; u8 *rss_config; int ret; @@ -1369,23 +1369,25 @@ static noinline_for_stack int ethtool_set_rxfh(struct net_device *dev, return -EOPNOTSUPP; create = rxfh.rss_context == ETH_RXFH_CONTEXT_ALLOC; - /* If either indir, hash key or function is valid, proceed further. - * Must request at least one change: indir size, hash key, function - * or input transformation. - */ if ((rxfh.indir_size && rxfh.indir_size != ETH_RXFH_INDIR_NO_CHANGE && rxfh.indir_size != dev_indir_size) || - (rxfh.key_size && (rxfh.key_size != dev_key_size)) || + (rxfh.key_size && rxfh.key_size != dev_key_size)) + return -EINVAL; + + /* Must request at least one change: indir size, hash key, function + * or input transformation. + * There's no need for any of it in case of context creation. + */ + if (!create && (rxfh.indir_size == ETH_RXFH_INDIR_NO_CHANGE && rxfh.key_size == 0 && rxfh.hfunc == ETH_RSS_HASH_NO_CHANGE && rxfh.input_xfrm == RXH_XFRM_NO_CHANGE)) return -EINVAL; - if (rxfh.indir_size != ETH_RXFH_INDIR_NO_CHANGE) - indir_bytes = dev_indir_size * sizeof(rxfh_dev.indir[0]); + indir_bytes = dev_indir_size * sizeof(rxfh_dev.indir[0]); - rss_config = kzalloc(indir_bytes + rxfh.key_size, GFP_USER); + rss_config = kzalloc(indir_bytes + dev_key_size, GFP_USER); if (!rss_config) return -ENOMEM; @@ -1400,6 +1402,7 @@ static noinline_for_stack int ethtool_set_rxfh(struct net_device *dev, */ if (rxfh.indir_size && rxfh.indir_size != ETH_RXFH_INDIR_NO_CHANGE) { + user_indir_len = indir_bytes; rxfh_dev.indir = (u32 *)rss_config; rxfh_dev.indir_size = dev_indir_size; ret = ethtool_copy_validate_indir(rxfh_dev.indir, @@ -1426,7 +1429,7 @@ static noinline_for_stack int ethtool_set_rxfh(struct net_device *dev, rxfh_dev.key_size = dev_key_size; rxfh_dev.key = rss_config + indir_bytes; if (copy_from_user(rxfh_dev.key, - useraddr + rss_cfg_offset + indir_bytes, + useraddr + rss_cfg_offset + user_indir_len, rxfh.key_size)) { ret = -EFAULT; goto out; @@ -1449,12 +1452,13 @@ static noinline_for_stack int ethtool_set_rxfh(struct net_device *dev, } if (ops->create_rxfh_context) { - u32 limit = ops->rxfh_max_context_id ?: U32_MAX; + u32 limit = ops->rxfh_max_num_contexts ?: U32_MAX; u32 ctx_id; /* driver uses new API, core allocates ID */ ret = xa_alloc(&dev->ethtool->rss_ctx, &ctx_id, ctx, - XA_LIMIT(1, limit), GFP_KERNEL_ACCOUNT); + XA_LIMIT(1, limit - 1), + GFP_KERNEL_ACCOUNT); if (ret < 0) { kfree(ctx); goto out; @@ -1474,16 +1478,21 @@ static noinline_for_stack int ethtool_set_rxfh(struct net_device *dev, rxfh_dev.input_xfrm = rxfh.input_xfrm; if (rxfh.rss_context && ops->create_rxfh_context) { - if (create) + if (create) { ret = ops->create_rxfh_context(dev, ctx, &rxfh_dev, extack); - else if (rxfh_dev.rss_delete) + /* Make sure driver populates defaults */ + WARN_ON_ONCE(!ret && !rxfh_dev.key && + !memchr_inv(ethtool_rxfh_context_key(ctx), + 0, ctx->key_size)); + } else if (rxfh_dev.rss_delete) { ret = ops->remove_rxfh_context(dev, ctx, rxfh.rss_context, extack); - else + } else { ret = ops->modify_rxfh_context(dev, ctx, &rxfh_dev, extack); + } } else { ret = ops->set_rxfh(dev, &rxfh_dev, extack); } @@ -1522,6 +1531,22 @@ static noinline_for_stack int ethtool_set_rxfh(struct net_device *dev, kfree(ctx); goto out; } + + /* Fetch the defaults for the old API, in the new API drivers + * should write defaults into ctx themselves. + */ + rxfh_dev.indir = (u32 *)rss_config; + rxfh_dev.indir_size = dev_indir_size; + + rxfh_dev.key = rss_config + indir_bytes; + rxfh_dev.key_size = dev_key_size; + + ret = ops->get_rxfh(dev, &rxfh_dev); + if (WARN_ON(ret)) { + xa_erase(&dev->ethtool->rss_ctx, rxfh.rss_context); + kfree(ctx); + goto out; + } } if (rxfh_dev.rss_delete) { WARN_ON(xa_erase(&dev->ethtool->rss_ctx, rxfh.rss_context) != ctx); @@ -1530,12 +1555,14 @@ static noinline_for_stack int ethtool_set_rxfh(struct net_device *dev, if (rxfh_dev.indir) { for (i = 0; i < dev_indir_size; i++) ethtool_rxfh_context_indir(ctx)[i] = rxfh_dev.indir[i]; - ctx->indir_configured = 1; + ctx->indir_configured = + rxfh.indir_size && + rxfh.indir_size != ETH_RXFH_INDIR_NO_CHANGE; } if (rxfh_dev.key) { memcpy(ethtool_rxfh_context_key(ctx), rxfh_dev.key, dev_key_size); - ctx->key_configured = 1; + ctx->key_configured = !!rxfh.key_size; } if (rxfh_dev.hfunc != ETH_RSS_HASH_NO_CHANGE) ctx->hfunc = rxfh_dev.hfunc; diff --git a/net/ethtool/rss.c b/net/ethtool/rss.c index 71679137eff218..5c4c4505ab9a4a 100644 --- a/net/ethtool/rss.c +++ b/net/ethtool/rss.c @@ -111,7 +111,8 @@ rss_reply_size(const struct ethnl_req_info *req_base, const struct rss_reply_data *data = RSS_REPDATA(reply_base); int len; - len = nla_total_size(sizeof(u32)) + /* _RSS_HFUNC */ + len = nla_total_size(sizeof(u32)) + /* _RSS_CONTEXT */ + nla_total_size(sizeof(u32)) + /* _RSS_HFUNC */ nla_total_size(sizeof(u32)) + /* _RSS_INPUT_XFRM */ nla_total_size(sizeof(u32) * data->indir_size) + /* _RSS_INDIR */ nla_total_size(data->hkey_size); /* _RSS_HKEY */ @@ -124,6 +125,11 @@ rss_fill_reply(struct sk_buff *skb, const struct ethnl_req_info *req_base, const struct ethnl_reply_data *reply_base) { const struct rss_reply_data *data = RSS_REPDATA(reply_base); + struct rss_req_info *request = RSS_REQINFO(req_base); + + if (request->rss_context && + nla_put_u32(skb, ETHTOOL_A_RSS_CONTEXT, request->rss_context)) + return -EMSGSIZE; if ((data->hfunc && nla_put_u32(skb, ETHTOOL_A_RSS_HFUNC, data->hfunc)) || diff --git a/net/ipv4/netfilter/iptable_nat.c b/net/ipv4/netfilter/iptable_nat.c index 4d42d0756fd70c..a5db7c67d61bef 100644 --- a/net/ipv4/netfilter/iptable_nat.c +++ b/net/ipv4/netfilter/iptable_nat.c @@ -145,25 +145,27 @@ static struct pernet_operations iptable_nat_net_ops = { static int __init iptable_nat_init(void) { - int ret = xt_register_template(&nf_nat_ipv4_table, - iptable_nat_table_init); + int ret; + /* net->gen->ptr[iptable_nat_net_id] must be allocated + * before calling iptable_nat_table_init(). + */ + ret = register_pernet_subsys(&iptable_nat_net_ops); if (ret < 0) return ret; - ret = register_pernet_subsys(&iptable_nat_net_ops); - if (ret < 0) { - xt_unregister_template(&nf_nat_ipv4_table); - return ret; - } + ret = xt_register_template(&nf_nat_ipv4_table, + iptable_nat_table_init); + if (ret < 0) + unregister_pernet_subsys(&iptable_nat_net_ops); return ret; } static void __exit iptable_nat_exit(void) { - unregister_pernet_subsys(&iptable_nat_net_ops); xt_unregister_template(&nf_nat_ipv4_table); + unregister_pernet_subsys(&iptable_nat_net_ops); } module_init(iptable_nat_init); diff --git a/net/ipv4/tcp_ao.c b/net/ipv4/tcp_ao.c index 85531437890cee..db6516092daf5b 100644 --- a/net/ipv4/tcp_ao.c +++ b/net/ipv4/tcp_ao.c @@ -267,32 +267,49 @@ static void tcp_ao_key_free_rcu(struct rcu_head *head) kfree_sensitive(key); } -void tcp_ao_destroy_sock(struct sock *sk, bool twsk) +static void tcp_ao_info_free_rcu(struct rcu_head *head) { - struct tcp_ao_info *ao; + struct tcp_ao_info *ao = container_of(head, struct tcp_ao_info, rcu); struct tcp_ao_key *key; struct hlist_node *n; + hlist_for_each_entry_safe(key, n, &ao->head, node) { + hlist_del(&key->node); + tcp_sigpool_release(key->tcp_sigpool_id); + kfree_sensitive(key); + } + kfree(ao); + static_branch_slow_dec_deferred(&tcp_ao_needed); +} + +static void tcp_ao_sk_omem_free(struct sock *sk, struct tcp_ao_info *ao) +{ + size_t total_ao_sk_mem = 0; + struct tcp_ao_key *key; + + hlist_for_each_entry(key, &ao->head, node) + total_ao_sk_mem += tcp_ao_sizeof_key(key); + atomic_sub(total_ao_sk_mem, &sk->sk_omem_alloc); +} + +void tcp_ao_destroy_sock(struct sock *sk, bool twsk) +{ + struct tcp_ao_info *ao; + if (twsk) { ao = rcu_dereference_protected(tcp_twsk(sk)->ao_info, 1); - tcp_twsk(sk)->ao_info = NULL; + rcu_assign_pointer(tcp_twsk(sk)->ao_info, NULL); } else { ao = rcu_dereference_protected(tcp_sk(sk)->ao_info, 1); - tcp_sk(sk)->ao_info = NULL; + rcu_assign_pointer(tcp_sk(sk)->ao_info, NULL); } if (!ao || !refcount_dec_and_test(&ao->refcnt)) return; - hlist_for_each_entry_safe(key, n, &ao->head, node) { - hlist_del_rcu(&key->node); - if (!twsk) - atomic_sub(tcp_ao_sizeof_key(key), &sk->sk_omem_alloc); - call_rcu(&key->rcu, tcp_ao_key_free_rcu); - } - - kfree_rcu(ao, rcu); - static_branch_slow_dec_deferred(&tcp_ao_needed); + if (!twsk) + tcp_ao_sk_omem_free(sk, ao); + call_rcu(&ao->rcu, tcp_ao_info_free_rcu); } void tcp_ao_time_wait(struct tcp_timewait_sock *tcptw, struct tcp_sock *tp) diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 454362e359da56..e37488d3453f03 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -238,9 +238,14 @@ static void tcp_measure_rcv_mss(struct sock *sk, const struct sk_buff *skb) */ if (unlikely(len != icsk->icsk_ack.rcv_mss)) { u64 val = (u64)skb->len << TCP_RMEM_TO_WIN_SCALE; + u8 old_ratio = tcp_sk(sk)->scaling_ratio; do_div(val, skb->truesize); tcp_sk(sk)->scaling_ratio = val ? val : 1; + + if (old_ratio != tcp_sk(sk)->scaling_ratio) + WRITE_ONCE(tcp_sk(sk)->window_clamp, + tcp_win_from_space(sk, sk->sk_rcvbuf)); } icsk->icsk_ack.rcv_mss = min_t(unsigned int, len, tcp_sk(sk)->advmss); diff --git a/net/ipv4/tcp_offload.c b/net/ipv4/tcp_offload.c index 4b791e74529e15..e4ad3311e14895 100644 --- a/net/ipv4/tcp_offload.c +++ b/net/ipv4/tcp_offload.c @@ -140,6 +140,9 @@ struct sk_buff *tcp_gso_segment(struct sk_buff *skb, if (thlen < sizeof(*th)) goto out; + if (unlikely(skb_checksum_start(skb) != skb_transport_header(skb))) + goto out; + if (!pskb_may_pull(skb, thlen)) goto out; diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c index aa2e0a28ca6138..b254a5dadfcf3f 100644 --- a/net/ipv4/udp_offload.c +++ b/net/ipv4/udp_offload.c @@ -278,6 +278,16 @@ struct sk_buff *__udp_gso_segment(struct sk_buff *gso_skb, if (gso_skb->len <= sizeof(*uh) + mss) return ERR_PTR(-EINVAL); + if (unlikely(skb_checksum_start(gso_skb) != + skb_transport_header(gso_skb))) + return ERR_PTR(-EINVAL); + + /* We don't know if egress device can segment and checksum the packet + * when IPv6 extension headers are present. Fall back to software GSO. + */ + if (gso_skb->ip_summed != CHECKSUM_PARTIAL) + features &= ~(NETIF_F_GSO_UDP_L4 | NETIF_F_CSUM_MASK); + if (skb_gso_ok(gso_skb, features | NETIF_F_GSO_ROBUST)) { /* Packet is from an untrusted source, reset gso_segs. */ skb_shinfo(gso_skb)->gso_segs = DIV_ROUND_UP(gso_skb->len - sizeof(*uh), diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 70a0b2ad6bd70c..b8eec1b6cc2c88 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -227,6 +227,7 @@ struct ndisc_options *ndisc_parse_options(const struct net_device *dev, return NULL; memset(ndopts, 0, sizeof(*ndopts)); while (opt_len) { + bool unknown = false; int l; if (opt_len < sizeof(struct nd_opt_hdr)) return NULL; @@ -262,22 +263,23 @@ struct ndisc_options *ndisc_parse_options(const struct net_device *dev, break; #endif default: - if (ndisc_is_useropt(dev, nd_opt)) { - ndopts->nd_useropts_end = nd_opt; - if (!ndopts->nd_useropts) - ndopts->nd_useropts = nd_opt; - } else { - /* - * Unknown options must be silently ignored, - * to accommodate future extension to the - * protocol. - */ - ND_PRINTK(2, notice, - "%s: ignored unsupported option; type=%d, len=%d\n", - __func__, - nd_opt->nd_opt_type, - nd_opt->nd_opt_len); - } + unknown = true; + } + if (ndisc_is_useropt(dev, nd_opt)) { + ndopts->nd_useropts_end = nd_opt; + if (!ndopts->nd_useropts) + ndopts->nd_useropts = nd_opt; + } else if (unknown) { + /* + * Unknown options must be silently ignored, + * to accommodate future extension to the + * protocol. + */ + ND_PRINTK(2, notice, + "%s: ignored unsupported option; type=%d, len=%d\n", + __func__, + nd_opt->nd_opt_type, + nd_opt->nd_opt_len); } next_opt: opt_len -= l; diff --git a/net/ipv6/netfilter/ip6table_nat.c b/net/ipv6/netfilter/ip6table_nat.c index 52cf104e347881..e119d4f090cc88 100644 --- a/net/ipv6/netfilter/ip6table_nat.c +++ b/net/ipv6/netfilter/ip6table_nat.c @@ -147,23 +147,27 @@ static struct pernet_operations ip6table_nat_net_ops = { static int __init ip6table_nat_init(void) { - int ret = xt_register_template(&nf_nat_ipv6_table, - ip6table_nat_table_init); + int ret; + /* net->gen->ptr[ip6table_nat_net_id] must be allocated + * before calling ip6t_nat_register_lookups(). + */ + ret = register_pernet_subsys(&ip6table_nat_net_ops); if (ret < 0) return ret; - ret = register_pernet_subsys(&ip6table_nat_net_ops); + ret = xt_register_template(&nf_nat_ipv6_table, + ip6table_nat_table_init); if (ret) - xt_unregister_template(&nf_nat_ipv6_table); + unregister_pernet_subsys(&ip6table_nat_net_ops); return ret; } static void __exit ip6table_nat_exit(void) { - unregister_pernet_subsys(&ip6table_nat_net_ops); xt_unregister_template(&nf_nat_ipv6_table); + unregister_pernet_subsys(&ip6table_nat_net_ops); } module_init(ip6table_nat_init); diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c index 6f0844c9315d18..4120e67a8ce6bb 100644 --- a/net/ipv6/netfilter/nf_conntrack_reasm.c +++ b/net/ipv6/netfilter/nf_conntrack_reasm.c @@ -154,6 +154,10 @@ static struct frag_queue *fq_find(struct net *net, __be32 id, u32 user, }; struct inet_frag_queue *q; + if (!(ipv6_addr_type(&hdr->daddr) & (IPV6_ADDR_MULTICAST | + IPV6_ADDR_LINKLOCAL))) + key.iif = 0; + q = inet_frag_find(nf_frag->fqdir, &key); if (!q) return NULL; diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c index c3b0b610b0aa35..c00323fa9eb66e 100644 --- a/net/iucv/af_iucv.c +++ b/net/iucv/af_iucv.c @@ -335,8 +335,8 @@ static void iucv_sever_path(struct sock *sk, int with_user_data) struct iucv_sock *iucv = iucv_sk(sk); struct iucv_path *path = iucv->path; - if (iucv->path) { - iucv->path = NULL; + /* Whoever resets the path pointer, must sever and free it. */ + if (xchg(&iucv->path, NULL)) { if (with_user_data) { low_nmcpy(user_data, iucv->src_name); high_nmcpy(user_data, iucv->dst_name); diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c index c80ab3f26084fb..2e86f520f79941 100644 --- a/net/l2tp/l2tp_core.c +++ b/net/l2tp/l2tp_core.c @@ -86,6 +86,11 @@ /* Default trace flags */ #define L2TP_DEFAULT_DEBUG_FLAGS 0 +#define L2TP_DEPTH_NESTING 2 +#if L2TP_DEPTH_NESTING == SINGLE_DEPTH_NESTING +#error "L2TP requires its own lockdep subclass" +#endif + /* Private data stored for received packets in the skb. */ struct l2tp_skb_cb { @@ -1124,7 +1129,13 @@ static int l2tp_xmit_core(struct l2tp_session *session, struct sk_buff *skb, uns IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED | IPSKB_REROUTED); nf_reset_ct(skb); - bh_lock_sock_nested(sk); + /* L2TP uses its own lockdep subclass to avoid lockdep splats caused by + * nested socket calls on the same lockdep socket class. This can + * happen when data from a user socket is routed over l2tp, which uses + * another userspace socket. + */ + spin_lock_nested(&sk->sk_lock.slock, L2TP_DEPTH_NESTING); + if (sock_owned_by_user(sk)) { kfree_skb(skb); ret = NET_XMIT_DROP; @@ -1176,7 +1187,7 @@ static int l2tp_xmit_core(struct l2tp_session *session, struct sk_buff *skb, uns ret = l2tp_xmit_queue(tunnel, skb, &inet->cork.fl); out_unlock: - bh_unlock_sock(sk); + spin_unlock(&sk->sk_lock.slock); return ret; } diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 85cb71de370f29..b02b84ce213076 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -114,7 +114,7 @@ static int ieee80211_set_mon_options(struct ieee80211_sub_if_data *sdata, /* apply all changes now - no failures allowed */ - if (monitor_sdata) + if (monitor_sdata && ieee80211_hw_check(&local->hw, WANT_MONITOR_VIF)) ieee80211_set_mu_mimo_follow(monitor_sdata, params); if (params->flags) { @@ -3053,6 +3053,9 @@ static int ieee80211_set_tx_power(struct wiphy *wiphy, sdata = IEEE80211_WDEV_TO_SUB_IF(wdev); if (sdata->vif.type == NL80211_IFTYPE_MONITOR) { + if (!ieee80211_hw_check(&local->hw, WANT_MONITOR_VIF)) + return -EOPNOTSUPP; + sdata = wiphy_dereference(local->hw.wiphy, local->monitor_sdata); if (!sdata) @@ -3115,7 +3118,7 @@ static int ieee80211_set_tx_power(struct wiphy *wiphy, if (has_monitor) { sdata = wiphy_dereference(local->hw.wiphy, local->monitor_sdata); - if (sdata) { + if (sdata && ieee80211_hw_check(&local->hw, WANT_MONITOR_VIF)) { sdata->deflink.user_power_level = local->user_power_level; if (txp_type != sdata->vif.bss_conf.txpower_type) update_txp_type = true; diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 72a9ba8bc5fd97..edba4a31844fb6 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1768,7 +1768,7 @@ static bool __ieee80211_tx(struct ieee80211_local *local, break; } sdata = rcu_dereference(local->monitor_sdata); - if (sdata) { + if (sdata && ieee80211_hw_check(&local->hw, WANT_MONITOR_VIF)) { vif = &sdata->vif; info->hw_queue = vif->hw_queue[skb_get_queue_mapping(skb)]; @@ -3957,7 +3957,8 @@ struct sk_buff *ieee80211_tx_dequeue(struct ieee80211_hw *hw, break; } tx.sdata = rcu_dereference(local->monitor_sdata); - if (tx.sdata) { + if (tx.sdata && + ieee80211_hw_check(&local->hw, WANT_MONITOR_VIF)) { vif = &tx.sdata->vif; info->hw_queue = vif->hw_queue[skb_get_queue_mapping(skb)]; diff --git a/net/mac80211/util.c b/net/mac80211/util.c index ced19ce7c51a33..c7ad9bc5973a0e 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -776,7 +776,7 @@ static void __iterate_interfaces(struct ieee80211_local *local, sdata = rcu_dereference_check(local->monitor_sdata, lockdep_is_held(&local->iflist_mtx) || lockdep_is_held(&local->hw.wiphy->mtx)); - if (sdata && + if (sdata && ieee80211_hw_check(&local->hw, WANT_MONITOR_VIF) && (iter_flags & IEEE80211_IFACE_ITER_RESUME_ALL || !active_only || sdata->flags & IEEE80211_SDATA_IN_DRIVER)) iterator(data, sdata->vif.addr, &sdata->vif); diff --git a/net/mptcp/diag.c b/net/mptcp/diag.c index 3ae46b545d2c2b..2d3efb405437d8 100644 --- a/net/mptcp/diag.c +++ b/net/mptcp/diag.c @@ -94,7 +94,7 @@ static size_t subflow_get_info_size(const struct sock *sk) nla_total_size(4) + /* MPTCP_SUBFLOW_ATTR_RELWRITE_SEQ */ nla_total_size_64bit(8) + /* MPTCP_SUBFLOW_ATTR_MAP_SEQ */ nla_total_size(4) + /* MPTCP_SUBFLOW_ATTR_MAP_SFSEQ */ - nla_total_size(2) + /* MPTCP_SUBFLOW_ATTR_SSN_OFFSET */ + nla_total_size(4) + /* MPTCP_SUBFLOW_ATTR_SSN_OFFSET */ nla_total_size(2) + /* MPTCP_SUBFLOW_ATTR_MAP_DATALEN */ nla_total_size(4) + /* MPTCP_SUBFLOW_ATTR_FLAGS */ nla_total_size(1) + /* MPTCP_SUBFLOW_ATTR_ID_REM */ diff --git a/net/mptcp/mib.c b/net/mptcp/mib.c index c30405e7683370..7884217f33eb2f 100644 --- a/net/mptcp/mib.c +++ b/net/mptcp/mib.c @@ -19,7 +19,9 @@ static const struct snmp_mib mptcp_snmp_list[] = { SNMP_MIB_ITEM("MPTCPRetrans", MPTCP_MIB_RETRANSSEGS), SNMP_MIB_ITEM("MPJoinNoTokenFound", MPTCP_MIB_JOINNOTOKEN), SNMP_MIB_ITEM("MPJoinSynRx", MPTCP_MIB_JOINSYNRX), + SNMP_MIB_ITEM("MPJoinSynBackupRx", MPTCP_MIB_JOINSYNBACKUPRX), SNMP_MIB_ITEM("MPJoinSynAckRx", MPTCP_MIB_JOINSYNACKRX), + SNMP_MIB_ITEM("MPJoinSynAckBackupRx", MPTCP_MIB_JOINSYNACKBACKUPRX), SNMP_MIB_ITEM("MPJoinSynAckHMacFailure", MPTCP_MIB_JOINSYNACKMAC), SNMP_MIB_ITEM("MPJoinAckRx", MPTCP_MIB_JOINACKRX), SNMP_MIB_ITEM("MPJoinAckHMacFailure", MPTCP_MIB_JOINACKMAC), diff --git a/net/mptcp/mib.h b/net/mptcp/mib.h index 2704afd0dfe452..66aa67f49d032c 100644 --- a/net/mptcp/mib.h +++ b/net/mptcp/mib.h @@ -14,7 +14,9 @@ enum linux_mptcp_mib_field { MPTCP_MIB_RETRANSSEGS, /* Segments retransmitted at the MPTCP-level */ MPTCP_MIB_JOINNOTOKEN, /* Received MP_JOIN but the token was not found */ MPTCP_MIB_JOINSYNRX, /* Received a SYN + MP_JOIN */ + MPTCP_MIB_JOINSYNBACKUPRX, /* Received a SYN + MP_JOIN + backup flag */ MPTCP_MIB_JOINSYNACKRX, /* Received a SYN/ACK + MP_JOIN */ + MPTCP_MIB_JOINSYNACKBACKUPRX, /* Received a SYN/ACK + MP_JOIN + backup flag */ MPTCP_MIB_JOINSYNACKMAC, /* HMAC was wrong on SYN/ACK + MP_JOIN */ MPTCP_MIB_JOINACKRX, /* Received an ACK + MP_JOIN */ MPTCP_MIB_JOINACKMAC, /* HMAC was wrong on ACK + MP_JOIN */ diff --git a/net/mptcp/options.c b/net/mptcp/options.c index 8e8dcfbc299382..ac2f1a54cc43ae 100644 --- a/net/mptcp/options.c +++ b/net/mptcp/options.c @@ -909,7 +909,7 @@ bool mptcp_synack_options(const struct request_sock *req, unsigned int *size, return true; } else if (subflow_req->mp_join) { opts->suboptions = OPTION_MPTCP_MPJ_SYNACK; - opts->backup = subflow_req->backup; + opts->backup = subflow_req->request_bkup; opts->join_id = subflow_req->local_id; opts->thmac = subflow_req->thmac; opts->nonce = subflow_req->local_nonce; @@ -958,7 +958,8 @@ static bool check_fully_established(struct mptcp_sock *msk, struct sock *ssk, if (subflow->remote_key_valid && (((mp_opt->suboptions & OPTION_MPTCP_DSS) && mp_opt->use_ack) || - ((mp_opt->suboptions & OPTION_MPTCP_ADD_ADDR) && !mp_opt->echo))) { + ((mp_opt->suboptions & OPTION_MPTCP_ADD_ADDR) && + (!mp_opt->echo || subflow->mp_join)))) { /* subflows are fully established as soon as we get any * additional ack, including ADD_ADDR. */ diff --git a/net/mptcp/pm.c b/net/mptcp/pm.c index 55406720c60711..23bb89c94e90d6 100644 --- a/net/mptcp/pm.c +++ b/net/mptcp/pm.c @@ -426,6 +426,18 @@ int mptcp_pm_get_local_id(struct mptcp_sock *msk, struct sock_common *skc) return mptcp_pm_nl_get_local_id(msk, &skc_local); } +bool mptcp_pm_is_backup(struct mptcp_sock *msk, struct sock_common *skc) +{ + struct mptcp_addr_info skc_local; + + mptcp_local_address((struct sock_common *)skc, &skc_local); + + if (mptcp_pm_is_userspace(msk)) + return mptcp_userspace_pm_is_backup(msk, &skc_local); + + return mptcp_pm_nl_is_backup(msk, &skc_local); +} + int mptcp_pm_get_flags_and_ifindex_by_id(struct mptcp_sock *msk, unsigned int id, u8 *flags, int *ifindex) { diff --git a/net/mptcp/pm_netlink.c b/net/mptcp/pm_netlink.c index ea9e5817b9e9d3..4cae2aa7be5cbc 100644 --- a/net/mptcp/pm_netlink.c +++ b/net/mptcp/pm_netlink.c @@ -348,7 +348,7 @@ bool mptcp_pm_alloc_anno_list(struct mptcp_sock *msk, add_entry = mptcp_lookup_anno_list_by_saddr(msk, addr); if (add_entry) { - if (mptcp_pm_is_kernel(msk)) + if (WARN_ON_ONCE(mptcp_pm_is_kernel(msk))) return false; sk_reset_timer(sk, &add_entry->add_timer, @@ -471,7 +471,6 @@ static void __mptcp_pm_send_ack(struct mptcp_sock *msk, struct mptcp_subflow_con slow = lock_sock_fast(ssk); if (prio) { subflow->send_mp_prio = 1; - subflow->backup = backup; subflow->request_bkup = backup; } @@ -513,8 +512,8 @@ __lookup_addr(struct pm_nl_pernet *pernet, const struct mptcp_addr_info *info) static void mptcp_pm_create_subflow_or_signal_addr(struct mptcp_sock *msk) { + struct mptcp_pm_addr_entry *local, *signal_and_subflow = NULL; struct sock *sk = (struct sock *)msk; - struct mptcp_pm_addr_entry *local; unsigned int add_addr_signal_max; unsigned int local_addr_max; struct pm_nl_pernet *pernet; @@ -556,8 +555,6 @@ static void mptcp_pm_create_subflow_or_signal_addr(struct mptcp_sock *msk) /* check first for announce */ if (msk->pm.add_addr_signaled < add_addr_signal_max) { - local = select_signal_address(pernet, msk); - /* due to racing events on both ends we can reach here while * previous add address is still running: if we invoke now * mptcp_pm_announce_addr(), that will fail and the @@ -568,16 +565,26 @@ static void mptcp_pm_create_subflow_or_signal_addr(struct mptcp_sock *msk) if (msk->pm.addr_signal & BIT(MPTCP_ADD_ADDR_SIGNAL)) return; - if (local) { - if (mptcp_pm_alloc_anno_list(msk, &local->addr)) { - __clear_bit(local->addr.id, msk->pm.id_avail_bitmap); - msk->pm.add_addr_signaled++; - mptcp_pm_announce_addr(msk, &local->addr, false); - mptcp_pm_nl_addr_send_ack(msk); - } - } + local = select_signal_address(pernet, msk); + if (!local) + goto subflow; + + /* If the alloc fails, we are on memory pressure, not worth + * continuing, and trying to create subflows. + */ + if (!mptcp_pm_alloc_anno_list(msk, &local->addr)) + return; + + __clear_bit(local->addr.id, msk->pm.id_avail_bitmap); + msk->pm.add_addr_signaled++; + mptcp_pm_announce_addr(msk, &local->addr, false); + mptcp_pm_nl_addr_send_ack(msk); + + if (local->flags & MPTCP_PM_ADDR_FLAG_SUBFLOW) + signal_and_subflow = local; } +subflow: /* check if should create a new subflow */ while (msk->pm.local_addr_used < local_addr_max && msk->pm.subflows < subflows_max) { @@ -585,9 +592,14 @@ static void mptcp_pm_create_subflow_or_signal_addr(struct mptcp_sock *msk) bool fullmesh; int i, nr; - local = select_local_address(pernet, msk); - if (!local) - break; + if (signal_and_subflow) { + local = signal_and_subflow; + signal_and_subflow = NULL; + } else { + local = select_local_address(pernet, msk); + if (!local) + break; + } fullmesh = !!(local->flags & MPTCP_PM_ADDR_FLAG_FULLMESH); @@ -1102,6 +1114,24 @@ int mptcp_pm_nl_get_local_id(struct mptcp_sock *msk, struct mptcp_addr_info *skc return ret; } +bool mptcp_pm_nl_is_backup(struct mptcp_sock *msk, struct mptcp_addr_info *skc) +{ + struct pm_nl_pernet *pernet = pm_nl_get_pernet_from_msk(msk); + struct mptcp_pm_addr_entry *entry; + bool backup = false; + + rcu_read_lock(); + list_for_each_entry_rcu(entry, &pernet->local_addr_list, list) { + if (mptcp_addresses_equal(&entry->addr, skc, entry->addr.port)) { + backup = !!(entry->flags & MPTCP_PM_ADDR_FLAG_BACKUP); + break; + } + } + rcu_read_unlock(); + + return backup; +} + #define MPTCP_PM_CMD_GRP_OFFSET 0 #define MPTCP_PM_EV_GRP_OFFSET 1 @@ -1311,8 +1341,8 @@ int mptcp_pm_nl_add_addr_doit(struct sk_buff *skb, struct genl_info *info) if (ret < 0) return ret; - if (addr.addr.port && !(addr.flags & MPTCP_PM_ADDR_FLAG_SIGNAL)) { - GENL_SET_ERR_MSG(info, "flags must have signal when using port"); + if (addr.addr.port && !address_use_port(&addr)) { + GENL_SET_ERR_MSG(info, "flags must have signal and not subflow when using port"); return -EINVAL; } @@ -1401,6 +1431,7 @@ static bool mptcp_pm_remove_anno_addr(struct mptcp_sock *msk, ret = remove_anno_list_by_saddr(msk, addr); if (ret || force) { spin_lock_bh(&msk->pm.lock); + msk->pm.add_addr_signaled -= ret; mptcp_pm_remove_addr(msk, &list); spin_unlock_bh(&msk->pm.lock); } @@ -1534,16 +1565,25 @@ void mptcp_pm_remove_addrs(struct mptcp_sock *msk, struct list_head *rm_list) { struct mptcp_rm_list alist = { .nr = 0 }; struct mptcp_pm_addr_entry *entry; + int anno_nr = 0; list_for_each_entry(entry, rm_list, list) { - if ((remove_anno_list_by_saddr(msk, &entry->addr) || - lookup_subflow_by_saddr(&msk->conn_list, &entry->addr)) && - alist.nr < MPTCP_RM_IDS_MAX) - alist.ids[alist.nr++] = entry->addr.id; + if (alist.nr >= MPTCP_RM_IDS_MAX) + break; + + /* only delete if either announced or matching a subflow */ + if (remove_anno_list_by_saddr(msk, &entry->addr)) + anno_nr++; + else if (!lookup_subflow_by_saddr(&msk->conn_list, + &entry->addr)) + continue; + + alist.ids[alist.nr++] = entry->addr.id; } if (alist.nr) { spin_lock_bh(&msk->pm.lock); + msk->pm.add_addr_signaled -= anno_nr; mptcp_pm_remove_addr(msk, &alist); spin_unlock_bh(&msk->pm.lock); } @@ -1556,17 +1596,18 @@ static void mptcp_pm_remove_addrs_and_subflows(struct mptcp_sock *msk, struct mptcp_pm_addr_entry *entry; list_for_each_entry(entry, rm_list, list) { - if (lookup_subflow_by_saddr(&msk->conn_list, &entry->addr) && - slist.nr < MPTCP_RM_IDS_MAX) + if (slist.nr < MPTCP_RM_IDS_MAX && + lookup_subflow_by_saddr(&msk->conn_list, &entry->addr)) slist.ids[slist.nr++] = entry->addr.id; - if (remove_anno_list_by_saddr(msk, &entry->addr) && - alist.nr < MPTCP_RM_IDS_MAX) + if (alist.nr < MPTCP_RM_IDS_MAX && + remove_anno_list_by_saddr(msk, &entry->addr)) alist.ids[alist.nr++] = entry->addr.id; } if (alist.nr) { spin_lock_bh(&msk->pm.lock); + msk->pm.add_addr_signaled -= alist.nr; mptcp_pm_remove_addr(msk, &alist); spin_unlock_bh(&msk->pm.lock); } diff --git a/net/mptcp/pm_userspace.c b/net/mptcp/pm_userspace.c index f0a4590506c69a..8eaa9fbe3e343b 100644 --- a/net/mptcp/pm_userspace.c +++ b/net/mptcp/pm_userspace.c @@ -165,6 +165,24 @@ int mptcp_userspace_pm_get_local_id(struct mptcp_sock *msk, return mptcp_userspace_pm_append_new_local_addr(msk, &new_entry, true); } +bool mptcp_userspace_pm_is_backup(struct mptcp_sock *msk, + struct mptcp_addr_info *skc) +{ + struct mptcp_pm_addr_entry *entry; + bool backup = false; + + spin_lock_bh(&msk->pm.lock); + list_for_each_entry(entry, &msk->pm.userspace_pm_local_addr_list, list) { + if (mptcp_addresses_equal(&entry->addr, skc, false)) { + backup = !!(entry->flags & MPTCP_PM_ADDR_FLAG_BACKUP); + break; + } + } + spin_unlock_bh(&msk->pm.lock); + + return backup; +} + int mptcp_pm_nl_announce_doit(struct sk_buff *skb, struct genl_info *info) { struct nlattr *token = info->attrs[MPTCP_PM_ATTR_TOKEN]; diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c index a26c2c840fd9ca..0d536b183a6c55 100644 --- a/net/mptcp/protocol.c +++ b/net/mptcp/protocol.c @@ -350,8 +350,10 @@ static bool __mptcp_move_skb(struct mptcp_sock *msk, struct sock *ssk, skb_orphan(skb); /* try to fetch required memory from subflow */ - if (!mptcp_rmem_schedule(sk, ssk, skb->truesize)) + if (!mptcp_rmem_schedule(sk, ssk, skb->truesize)) { + MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_RCVPRUNED); goto drop; + } has_rxtstamp = TCP_SKB_CB(skb)->has_rxtstamp; @@ -844,10 +846,8 @@ void mptcp_data_ready(struct sock *sk, struct sock *ssk) sk_rbuf = ssk_rbuf; /* over limit? can't append more skbs to msk, Also, no need to wake-up*/ - if (__mptcp_rmem(sk) > sk_rbuf) { - MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_RCVPRUNED); + if (__mptcp_rmem(sk) > sk_rbuf) return; - } /* Wake-up the reader only for in-sequence data */ mptcp_data_lock(sk); @@ -1422,13 +1422,15 @@ struct sock *mptcp_subflow_get_send(struct mptcp_sock *msk) } mptcp_for_each_subflow(msk, subflow) { + bool backup = subflow->backup || subflow->request_bkup; + trace_mptcp_subflow_get_send(subflow); ssk = mptcp_subflow_tcp_sock(subflow); if (!mptcp_subflow_active(subflow)) continue; tout = max(tout, mptcp_timeout_from_subflow(subflow)); - nr_active += !subflow->backup; + nr_active += !backup; pace = subflow->avg_pacing_rate; if (unlikely(!pace)) { /* init pacing rate from socket */ @@ -1439,9 +1441,9 @@ struct sock *mptcp_subflow_get_send(struct mptcp_sock *msk) } linger_time = div_u64((u64)READ_ONCE(ssk->sk_wmem_queued) << 32, pace); - if (linger_time < send_info[subflow->backup].linger_time) { - send_info[subflow->backup].ssk = ssk; - send_info[subflow->backup].linger_time = linger_time; + if (linger_time < send_info[backup].linger_time) { + send_info[backup].ssk = ssk; + send_info[backup].linger_time = linger_time; } } __mptcp_set_timeout(sk, tout); diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h index b11a4e50d52b6f..60c6b073d65fe5 100644 --- a/net/mptcp/protocol.h +++ b/net/mptcp/protocol.h @@ -448,6 +448,7 @@ struct mptcp_subflow_request_sock { u16 mp_capable : 1, mp_join : 1, backup : 1, + request_bkup : 1, csum_reqd : 1, allow_join_id0 : 1; u8 local_id; @@ -1108,6 +1109,9 @@ bool mptcp_pm_rm_addr_signal(struct mptcp_sock *msk, unsigned int remaining, int mptcp_pm_get_local_id(struct mptcp_sock *msk, struct sock_common *skc); int mptcp_pm_nl_get_local_id(struct mptcp_sock *msk, struct mptcp_addr_info *skc); int mptcp_userspace_pm_get_local_id(struct mptcp_sock *msk, struct mptcp_addr_info *skc); +bool mptcp_pm_is_backup(struct mptcp_sock *msk, struct sock_common *skc); +bool mptcp_pm_nl_is_backup(struct mptcp_sock *msk, struct mptcp_addr_info *skc); +bool mptcp_userspace_pm_is_backup(struct mptcp_sock *msk, struct mptcp_addr_info *skc); int mptcp_pm_dump_addr(struct sk_buff *msg, struct netlink_callback *cb); int mptcp_pm_nl_dump_addr(struct sk_buff *msg, struct netlink_callback *cb); diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c index 39e2cbdf38019c..a21c712350c36e 100644 --- a/net/mptcp/subflow.c +++ b/net/mptcp/subflow.c @@ -100,6 +100,7 @@ static struct mptcp_sock *subflow_token_join_request(struct request_sock *req) return NULL; } subflow_req->local_id = local_id; + subflow_req->request_bkup = mptcp_pm_is_backup(msk, (struct sock_common *)req); return msk; } @@ -168,6 +169,9 @@ static int subflow_check_req(struct request_sock *req, return 0; } else if (opt_mp_join) { SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_JOINSYNRX); + + if (mp_opt.backup) + SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_JOINSYNBACKUPRX); } if (opt_mp_capable && listener->request_mptcp) { @@ -577,6 +581,9 @@ static void subflow_finish_connect(struct sock *sk, const struct sk_buff *skb) subflow->mp_join = 1; MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_JOINSYNACKRX); + if (subflow->backup) + MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_JOINSYNACKBACKUPRX); + if (subflow_use_different_dport(msk, sk)) { pr_debug("synack inet_dport=%d %d", ntohs(inet_sk(sk)->inet_dport), @@ -614,6 +621,8 @@ static int subflow_chk_local_id(struct sock *sk) return err; subflow_set_local_id(subflow, err); + subflow->request_bkup = mptcp_pm_is_backup(msk, (struct sock_common *)sk); + return 0; } @@ -1221,14 +1230,22 @@ static void mptcp_subflow_discard_data(struct sock *ssk, struct sk_buff *skb, { struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk); bool fin = TCP_SKB_CB(skb)->tcp_flags & TCPHDR_FIN; - u32 incr; + struct tcp_sock *tp = tcp_sk(ssk); + u32 offset, incr, avail_len; - incr = limit >= skb->len ? skb->len + fin : limit; + offset = tp->copied_seq - TCP_SKB_CB(skb)->seq; + if (WARN_ON_ONCE(offset > skb->len)) + goto out; - pr_debug("discarding=%d len=%d seq=%d", incr, skb->len, - subflow->map_subflow_seq); + avail_len = skb->len - offset; + incr = limit >= avail_len ? avail_len + fin : limit; + + pr_debug("discarding=%d len=%d offset=%d seq=%d", incr, skb->len, + offset, subflow->map_subflow_seq); MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_DUPDATA); tcp_sk(ssk)->copied_seq += incr; + +out: if (!before(tcp_sk(ssk)->copied_seq, TCP_SKB_CB(skb)->end_seq)) sk_eat_skb(ssk, skb); if (mptcp_subflow_get_map_offset(subflow) >= subflow->map_data_len) @@ -2005,6 +2022,7 @@ static void subflow_ulp_clone(const struct request_sock *req, new_ctx->fully_established = 1; new_ctx->remote_key_valid = 1; new_ctx->backup = subflow_req->backup; + new_ctx->request_bkup = subflow_req->request_bkup; WRITE_ONCE(new_ctx->remote_id, subflow_req->remote_id); new_ctx->token = subflow_req->token; new_ctx->thmac = subflow_req->thmac; diff --git a/net/netfilter/nf_flow_table_offload.c b/net/netfilter/nf_flow_table_offload.c index ff1a4e36c2b5dc..e06bc36f49fe74 100644 --- a/net/netfilter/nf_flow_table_offload.c +++ b/net/netfilter/nf_flow_table_offload.c @@ -841,8 +841,8 @@ static int nf_flow_offload_tuple(struct nf_flowtable *flowtable, struct list_head *block_cb_list) { struct flow_cls_offload cls_flow = {}; + struct netlink_ext_ack extack = {}; struct flow_block_cb *block_cb; - struct netlink_ext_ack extack; __be16 proto = ETH_P_ALL; int err, i = 0; diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index 481ee78e77bcf9..0a2f7934695896 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c @@ -8020,6 +8020,19 @@ static int nf_tables_dump_obj(struct sk_buff *skb, struct netlink_callback *cb) return skb->len; } +static int nf_tables_dumpreset_obj(struct sk_buff *skb, + struct netlink_callback *cb) +{ + struct nftables_pernet *nft_net = nft_pernet(sock_net(skb->sk)); + int ret; + + mutex_lock(&nft_net->commit_mutex); + ret = nf_tables_dump_obj(skb, cb); + mutex_unlock(&nft_net->commit_mutex); + + return ret; +} + static int nf_tables_dump_obj_start(struct netlink_callback *cb) { struct nft_obj_dump_ctx *ctx = (void *)cb->ctx; @@ -8036,12 +8049,18 @@ static int nf_tables_dump_obj_start(struct netlink_callback *cb) if (nla[NFTA_OBJ_TYPE]) ctx->type = ntohl(nla_get_be32(nla[NFTA_OBJ_TYPE])); - if (NFNL_MSG_TYPE(cb->nlh->nlmsg_type) == NFT_MSG_GETOBJ_RESET) - ctx->reset = true; - return 0; } +static int nf_tables_dumpreset_obj_start(struct netlink_callback *cb) +{ + struct nft_obj_dump_ctx *ctx = (void *)cb->ctx; + + ctx->reset = true; + + return nf_tables_dump_obj_start(cb); +} + static int nf_tables_dump_obj_done(struct netlink_callback *cb) { struct nft_obj_dump_ctx *ctx = (void *)cb->ctx; @@ -8052,8 +8071,9 @@ static int nf_tables_dump_obj_done(struct netlink_callback *cb) } /* called with rcu_read_lock held */ -static int nf_tables_getobj(struct sk_buff *skb, const struct nfnl_info *info, - const struct nlattr * const nla[]) +static struct sk_buff * +nf_tables_getobj_single(u32 portid, const struct nfnl_info *info, + const struct nlattr * const nla[], bool reset) { struct netlink_ext_ack *extack = info->extack; u8 genmask = nft_genmask_cur(info->net); @@ -8062,72 +8082,109 @@ static int nf_tables_getobj(struct sk_buff *skb, const struct nfnl_info *info, struct net *net = info->net; struct nft_object *obj; struct sk_buff *skb2; - bool reset = false; u32 objtype; int err; - if (info->nlh->nlmsg_flags & NLM_F_DUMP) { - struct netlink_dump_control c = { - .start = nf_tables_dump_obj_start, - .dump = nf_tables_dump_obj, - .done = nf_tables_dump_obj_done, - .module = THIS_MODULE, - .data = (void *)nla, - }; - - return nft_netlink_dump_start_rcu(info->sk, skb, info->nlh, &c); - } - if (!nla[NFTA_OBJ_NAME] || !nla[NFTA_OBJ_TYPE]) - return -EINVAL; + return ERR_PTR(-EINVAL); table = nft_table_lookup(net, nla[NFTA_OBJ_TABLE], family, genmask, 0); if (IS_ERR(table)) { NL_SET_BAD_ATTR(extack, nla[NFTA_OBJ_TABLE]); - return PTR_ERR(table); + return ERR_CAST(table); } objtype = ntohl(nla_get_be32(nla[NFTA_OBJ_TYPE])); obj = nft_obj_lookup(net, table, nla[NFTA_OBJ_NAME], objtype, genmask); if (IS_ERR(obj)) { NL_SET_BAD_ATTR(extack, nla[NFTA_OBJ_NAME]); - return PTR_ERR(obj); + return ERR_CAST(obj); } skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC); if (!skb2) - return -ENOMEM; + return ERR_PTR(-ENOMEM); - if (NFNL_MSG_TYPE(info->nlh->nlmsg_type) == NFT_MSG_GETOBJ_RESET) - reset = true; + err = nf_tables_fill_obj_info(skb2, net, portid, + info->nlh->nlmsg_seq, NFT_MSG_NEWOBJ, 0, + family, table, obj, reset); + if (err < 0) { + kfree_skb(skb2); + return ERR_PTR(err); + } - if (reset) { - const struct nftables_pernet *nft_net; - char *buf; + return skb2; +} - nft_net = nft_pernet(net); - buf = kasprintf(GFP_ATOMIC, "%s:%u", table->name, nft_net->base_seq); +static int nf_tables_getobj(struct sk_buff *skb, const struct nfnl_info *info, + const struct nlattr * const nla[]) +{ + u32 portid = NETLINK_CB(skb).portid; + struct sk_buff *skb2; - audit_log_nfcfg(buf, - family, - 1, - AUDIT_NFT_OP_OBJ_RESET, - GFP_ATOMIC); - kfree(buf); + if (info->nlh->nlmsg_flags & NLM_F_DUMP) { + struct netlink_dump_control c = { + .start = nf_tables_dump_obj_start, + .dump = nf_tables_dump_obj, + .done = nf_tables_dump_obj_done, + .module = THIS_MODULE, + .data = (void *)nla, + }; + + return nft_netlink_dump_start_rcu(info->sk, skb, info->nlh, &c); } - err = nf_tables_fill_obj_info(skb2, net, NETLINK_CB(skb).portid, - info->nlh->nlmsg_seq, NFT_MSG_NEWOBJ, 0, - family, table, obj, reset); - if (err < 0) - goto err_fill_obj_info; + skb2 = nf_tables_getobj_single(portid, info, nla, false); + if (IS_ERR(skb2)) + return PTR_ERR(skb2); - return nfnetlink_unicast(skb2, net, NETLINK_CB(skb).portid); + return nfnetlink_unicast(skb2, info->net, portid); +} -err_fill_obj_info: - kfree_skb(skb2); - return err; +static int nf_tables_getobj_reset(struct sk_buff *skb, + const struct nfnl_info *info, + const struct nlattr * const nla[]) +{ + struct nftables_pernet *nft_net = nft_pernet(info->net); + u32 portid = NETLINK_CB(skb).portid; + struct net *net = info->net; + struct sk_buff *skb2; + char *buf; + + if (info->nlh->nlmsg_flags & NLM_F_DUMP) { + struct netlink_dump_control c = { + .start = nf_tables_dumpreset_obj_start, + .dump = nf_tables_dumpreset_obj, + .done = nf_tables_dump_obj_done, + .module = THIS_MODULE, + .data = (void *)nla, + }; + + return nft_netlink_dump_start_rcu(info->sk, skb, info->nlh, &c); + } + + if (!try_module_get(THIS_MODULE)) + return -EINVAL; + rcu_read_unlock(); + mutex_lock(&nft_net->commit_mutex); + skb2 = nf_tables_getobj_single(portid, info, nla, true); + mutex_unlock(&nft_net->commit_mutex); + rcu_read_lock(); + module_put(THIS_MODULE); + + if (IS_ERR(skb2)) + return PTR_ERR(skb2); + + buf = kasprintf(GFP_ATOMIC, "%.*s:%u", + nla_len(nla[NFTA_OBJ_TABLE]), + (char *)nla_data(nla[NFTA_OBJ_TABLE]), + nft_net->base_seq); + audit_log_nfcfg(buf, info->nfmsg->nfgen_family, 1, + AUDIT_NFT_OP_OBJ_RESET, GFP_ATOMIC); + kfree(buf); + + return nfnetlink_unicast(skb2, net, portid); } static void nft_obj_destroy(const struct nft_ctx *ctx, struct nft_object *obj) @@ -9410,7 +9467,7 @@ static const struct nfnl_callback nf_tables_cb[NFT_MSG_MAX] = { .policy = nft_obj_policy, }, [NFT_MSG_GETOBJ_RESET] = { - .call = nf_tables_getobj, + .call = nf_tables_getobj_reset, .type = NFNL_CB_RCU, .attr_count = NFTA_OBJ_MAX, .policy = nft_obj_policy, diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c index 4abf660c7baff0..932b3ddb34f13c 100644 --- a/net/netfilter/nfnetlink.c +++ b/net/netfilter/nfnetlink.c @@ -427,8 +427,10 @@ static void nfnetlink_rcv_batch(struct sk_buff *skb, struct nlmsghdr *nlh, nfnl_unlock(subsys_id); - if (nlh->nlmsg_flags & NLM_F_ACK) + if (nlh->nlmsg_flags & NLM_F_ACK) { + memset(&extack, 0, sizeof(extack)); nfnl_err_add(&err_list, nlh, 0, &extack); + } while (skb->len >= nlmsg_total_size(0)) { int msglen, type; @@ -577,6 +579,7 @@ static void nfnetlink_rcv_batch(struct sk_buff *skb, struct nlmsghdr *nlh, ss->abort(net, oskb, NFNL_ABORT_NONE); netlink_ack(oskb, nlmsg_hdr(oskb), err, NULL); } else if (nlh->nlmsg_flags & NLM_F_ACK) { + memset(&extack, 0, sizeof(extack)); nfnl_err_add(&err_list, nlh, 0, &extack); } } else { diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c index 55e28e1da66ec6..e0716da256bf55 100644 --- a/net/netfilter/nfnetlink_queue.c +++ b/net/netfilter/nfnetlink_queue.c @@ -820,10 +820,41 @@ static bool nf_ct_drop_unconfirmed(const struct nf_queue_entry *entry) { #if IS_ENABLED(CONFIG_NF_CONNTRACK) static const unsigned long flags = IPS_CONFIRMED | IPS_DYING; - const struct nf_conn *ct = (void *)skb_nfct(entry->skb); + struct nf_conn *ct = (void *)skb_nfct(entry->skb); + unsigned long status; + unsigned int use; - if (ct && ((ct->status & flags) == IPS_DYING)) + if (!ct) + return false; + + status = READ_ONCE(ct->status); + if ((status & flags) == IPS_DYING) return true; + + if (status & IPS_CONFIRMED) + return false; + + /* in some cases skb_clone() can occur after initial conntrack + * pickup, but conntrack assumes exclusive skb->_nfct ownership for + * unconfirmed entries. + * + * This happens for br_netfilter and with ip multicast routing. + * We can't be solved with serialization here because one clone could + * have been queued for local delivery. + */ + use = refcount_read(&ct->ct_general.use); + if (likely(use == 1)) + return false; + + /* Can't decrement further? Exclusive ownership. */ + if (!refcount_dec_not_one(&ct->ct_general.use)) + return false; + + skb_set_nfct(entry->skb, 0); + /* No nf_ct_put(): we already decremented .use and it cannot + * drop down to 0. + */ + return true; #endif return false; } diff --git a/net/sched/act_ct.c b/net/sched/act_ct.c index 113b907da0f757..3ba8e7e739b58a 100644 --- a/net/sched/act_ct.c +++ b/net/sched/act_ct.c @@ -44,6 +44,8 @@ static DEFINE_MUTEX(zones_mutex); struct zones_ht_key { struct net *net; u16 zone; + /* Note : pad[] must be the last field. */ + u8 pad[]; }; struct tcf_ct_flow_table { @@ -60,7 +62,7 @@ struct tcf_ct_flow_table { static const struct rhashtable_params zones_params = { .head_offset = offsetof(struct tcf_ct_flow_table, node), .key_offset = offsetof(struct tcf_ct_flow_table, key), - .key_len = sizeof_field(struct tcf_ct_flow_table, key), + .key_len = offsetof(struct zones_ht_key, pad), .automatic_shrinking = true, }; diff --git a/net/sctp/input.c b/net/sctp/input.c index 17fcaa9b0df945..a8a254a5008e52 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c @@ -735,15 +735,19 @@ static int __sctp_hash_endpoint(struct sctp_endpoint *ep) struct sock *sk = ep->base.sk; struct net *net = sock_net(sk); struct sctp_hashbucket *head; + int err = 0; ep->hashent = sctp_ep_hashfn(net, ep->base.bind_addr.port); head = &sctp_ep_hashtable[ep->hashent]; + write_lock(&head->lock); if (sk->sk_reuseport) { bool any = sctp_is_ep_boundall(sk); struct sctp_endpoint *ep2; struct list_head *list; - int cnt = 0, err = 1; + int cnt = 0; + + err = 1; list_for_each(list, &ep->base.bind_addr.address_list) cnt++; @@ -761,24 +765,24 @@ static int __sctp_hash_endpoint(struct sctp_endpoint *ep) if (!err) { err = reuseport_add_sock(sk, sk2, any); if (err) - return err; + goto out; break; } else if (err < 0) { - return err; + goto out; } } if (err) { err = reuseport_alloc(sk, any); if (err) - return err; + goto out; } } - write_lock(&head->lock); hlist_add_head(&ep->node, &head->chain); +out: write_unlock(&head->lock); - return 0; + return err; } /* Add an endpoint to the hash. Local BH-safe. */ @@ -803,10 +807,9 @@ static void __sctp_unhash_endpoint(struct sctp_endpoint *ep) head = &sctp_ep_hashtable[ep->hashent]; + write_lock(&head->lock); if (rcu_access_pointer(sk->sk_reuseport_cb)) reuseport_detach_sock(sk); - - write_lock(&head->lock); hlist_del_init(&ep->node); write_unlock(&head->lock); } diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c index 73a875573e7ad5..8e3093938cd226 100644 --- a/net/smc/af_smc.c +++ b/net/smc/af_smc.c @@ -3319,10 +3319,8 @@ int smc_create_clcsk(struct net *net, struct sock *sk, int family) rc = sock_create_kern(net, family, SOCK_STREAM, IPPROTO_TCP, &smc->clcsock); - if (rc) { - sk_common_release(sk); + if (rc) return rc; - } /* smc_clcsock_release() does not wait smc->clcsock->sk's * destruction; its sk_state might not be TCP_CLOSE after @@ -3368,6 +3366,9 @@ static int __smc_create(struct net *net, struct socket *sock, int protocol, smc->clcsock = clcsock; else rc = smc_create_clcsk(net, sk, family); + + if (rc) + sk_common_release(sk); out: return rc; } diff --git a/net/smc/smc_stats.h b/net/smc/smc_stats.h index 9d32058db2b5d6..e19177ce409230 100644 --- a/net/smc/smc_stats.h +++ b/net/smc/smc_stats.h @@ -19,7 +19,7 @@ #include "smc_clc.h" -#define SMC_MAX_FBACK_RSN_CNT 30 +#define SMC_MAX_FBACK_RSN_CNT 36 enum { SMC_BUF_8K, diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c index e03f14024e471d..88a59cfa5583c0 100644 --- a/net/sunrpc/svc.c +++ b/net/sunrpc/svc.c @@ -161,7 +161,7 @@ param_get_pool_mode(char *buf, const struct kernel_param *kp) str[len] = '\n'; str[len + 1] = '\0'; - return sysfs_emit(buf, str); + return sysfs_emit(buf, "%s", str); } module_param_call(pool_mode, param_set_pool_mode, param_get_pool_mode, diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c index 4b040285aa78c0..0ff9b2dd86bac2 100644 --- a/net/vmw_vsock/af_vsock.c +++ b/net/vmw_vsock/af_vsock.c @@ -1270,25 +1270,28 @@ static int vsock_dgram_connect(struct socket *sock, return err; } +int __vsock_dgram_recvmsg(struct socket *sock, struct msghdr *msg, + size_t len, int flags) +{ + struct sock *sk = sock->sk; + struct vsock_sock *vsk = vsock_sk(sk); + + return vsk->transport->dgram_dequeue(vsk, msg, len, flags); +} + int vsock_dgram_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, int flags) { #ifdef CONFIG_BPF_SYSCALL + struct sock *sk = sock->sk; const struct proto *prot; -#endif - struct vsock_sock *vsk; - struct sock *sk; - sk = sock->sk; - vsk = vsock_sk(sk); - -#ifdef CONFIG_BPF_SYSCALL prot = READ_ONCE(sk->sk_prot); if (prot != &vsock_proto) return prot->recvmsg(sk, msg, len, flags, NULL); #endif - return vsk->transport->dgram_dequeue(vsk, msg, len, flags); + return __vsock_dgram_recvmsg(sock, msg, len, flags); } EXPORT_SYMBOL_GPL(vsock_dgram_recvmsg); @@ -2174,15 +2177,12 @@ static int __vsock_seqpacket_recvmsg(struct sock *sk, struct msghdr *msg, } int -vsock_connectible_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, - int flags) +__vsock_connectible_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, + int flags) { struct sock *sk; struct vsock_sock *vsk; const struct vsock_transport *transport; -#ifdef CONFIG_BPF_SYSCALL - const struct proto *prot; -#endif int err; sk = sock->sk; @@ -2233,14 +2233,6 @@ vsock_connectible_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, goto out; } -#ifdef CONFIG_BPF_SYSCALL - prot = READ_ONCE(sk->sk_prot); - if (prot != &vsock_proto) { - release_sock(sk); - return prot->recvmsg(sk, msg, len, flags, NULL); - } -#endif - if (sk->sk_type == SOCK_STREAM) err = __vsock_stream_recvmsg(sk, msg, len, flags); else @@ -2250,6 +2242,22 @@ vsock_connectible_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, release_sock(sk); return err; } + +int +vsock_connectible_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, + int flags) +{ +#ifdef CONFIG_BPF_SYSCALL + struct sock *sk = sock->sk; + const struct proto *prot; + + prot = READ_ONCE(sk->sk_prot); + if (prot != &vsock_proto) + return prot->recvmsg(sk, msg, len, flags, NULL); +#endif + + return __vsock_connectible_recvmsg(sock, msg, len, flags); +} EXPORT_SYMBOL_GPL(vsock_connectible_recvmsg); static int vsock_set_rcvlowat(struct sock *sk, int val) diff --git a/net/vmw_vsock/vsock_bpf.c b/net/vmw_vsock/vsock_bpf.c index a3c97546ab84a6..c42c5cc18f3241 100644 --- a/net/vmw_vsock/vsock_bpf.c +++ b/net/vmw_vsock/vsock_bpf.c @@ -64,9 +64,9 @@ static int __vsock_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int int err; if (sk->sk_type == SOCK_STREAM || sk->sk_type == SOCK_SEQPACKET) - err = vsock_connectible_recvmsg(sock, msg, len, flags); + err = __vsock_connectible_recvmsg(sock, msg, len, flags); else if (sk->sk_type == SOCK_DGRAM) - err = vsock_dgram_recvmsg(sock, msg, len, flags); + err = __vsock_dgram_recvmsg(sock, msg, len, flags); else err = -EPROTOTYPE; diff --git a/net/wireless/scan.c b/net/wireless/scan.c index d99319d8220549..64eeed82d43d5c 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c @@ -3178,8 +3178,7 @@ cfg80211_inform_bss_frame_data(struct wiphy *wiphy, struct ieee80211_mgmt *mgmt, size_t len, gfp_t gfp) { - size_t min_hdr_len = offsetof(struct ieee80211_mgmt, - u.probe_resp.variable); + size_t min_hdr_len; struct ieee80211_ext *ext = NULL; enum cfg80211_bss_frame_type ftype; u16 beacon_interval; @@ -3202,10 +3201,16 @@ cfg80211_inform_bss_frame_data(struct wiphy *wiphy, if (ieee80211_is_s1g_beacon(mgmt->frame_control)) { ext = (void *) mgmt; - min_hdr_len = offsetof(struct ieee80211_ext, u.s1g_beacon); if (ieee80211_is_s1g_short_beacon(mgmt->frame_control)) min_hdr_len = offsetof(struct ieee80211_ext, u.s1g_short_beacon.variable); + else + min_hdr_len = offsetof(struct ieee80211_ext, + u.s1g_beacon.variable); + } else { + /* same for beacons */ + min_hdr_len = offsetof(struct ieee80211_mgmt, + u.probe_resp.variable); } if (WARN_ON(len < min_hdr_len)) diff --git a/net/wireless/sme.c b/net/wireless/sme.c index e419aa8c4a5ac6..d9d7bf8bb5c1ac 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c @@ -1045,6 +1045,7 @@ void cfg80211_connect_done(struct net_device *dev, cfg80211_hold_bss( bss_from_pub(params->links[link].bss)); ev->cr.links[link].bss = params->links[link].bss; + ev->cr.links[link].status = params->links[link].status; if (params->links[link].addr) { ev->cr.links[link].addr = next; diff --git a/rust/Makefile b/rust/Makefile index 1f10f92737f2c0..8de3ebba95512c 100644 --- a/rust/Makefile +++ b/rust/Makefile @@ -227,7 +227,7 @@ bindgen_skip_c_flags := -mno-fp-ret-in-387 -mpreferred-stack-boundary=% \ -fno-reorder-blocks -fno-allow-store-data-races -fasan-shadow-offset=% \ -fzero-call-used-regs=% -fno-stack-clash-protection \ -fno-inline-functions-called-once -fsanitize=bounds-strict \ - -fstrict-flex-arrays=% \ + -fstrict-flex-arrays=% -fmin-function-alignment=% \ --param=% --param asan-% # Derived from `scripts/Makefile.clang`. @@ -350,12 +350,12 @@ rust-analyzer: $(Q)$(srctree)/scripts/generate_rust_analyzer.py \ --cfgs='core=$(core-cfgs)' --cfgs='alloc=$(alloc-cfgs)' \ $(realpath $(srctree)) $(realpath $(objtree)) \ - $(RUST_LIB_SRC) $(KBUILD_EXTMOD) > \ + $(rustc_sysroot) $(RUST_LIB_SRC) $(KBUILD_EXTMOD) > \ $(if $(KBUILD_EXTMOD),$(extmod_prefix),$(objtree))/rust-project.json redirect-intrinsics = \ - __addsf3 __eqsf2 __gesf2 __lesf2 __ltsf2 __mulsf3 __nesf2 __unordsf2 \ - __adddf3 __ledf2 __ltdf2 __muldf3 __unorddf2 \ + __addsf3 __eqsf2 __extendsfdf2 __gesf2 __lesf2 __ltsf2 __mulsf3 __nesf2 __truncdfsf2 __unordsf2 \ + __adddf3 __eqdf2 __ledf2 __ltdf2 __muldf3 __unorddf2 \ __muloti4 __multi3 \ __udivmodti4 __udivti3 __umodti3 diff --git a/rust/compiler_builtins.rs b/rust/compiler_builtins.rs index bba2922c6ef77f..f14b8d7caf8996 100644 --- a/rust/compiler_builtins.rs +++ b/rust/compiler_builtins.rs @@ -40,16 +40,19 @@ macro_rules! define_panicking_intrinsics( define_panicking_intrinsics!("`f32` should not be used", { __addsf3, __eqsf2, + __extendsfdf2, __gesf2, __lesf2, __ltsf2, __mulsf3, __nesf2, + __truncdfsf2, __unordsf2, }); define_panicking_intrinsics!("`f64` should not be used", { __adddf3, + __eqdf2, __ledf2, __ltdf2, __muldf3, diff --git a/rust/kernel/firmware.rs b/rust/kernel/firmware.rs index 2ba03af9f0369d..dee5b4b18aec40 100644 --- a/rust/kernel/firmware.rs +++ b/rust/kernel/firmware.rs @@ -2,7 +2,7 @@ //! Firmware abstraction //! -//! C header: [`include/linux/firmware.h`](srctree/include/linux/firmware.h") +//! C header: [`include/linux/firmware.h`](srctree/include/linux/firmware.h) use crate::{bindings, device::Device, error::Error, error::Result, str::CStr}; use core::ptr::NonNull; diff --git a/rust/macros/lib.rs b/rust/macros/lib.rs index 159e7529297075..5be0cb9db3ee49 100644 --- a/rust/macros/lib.rs +++ b/rust/macros/lib.rs @@ -94,7 +94,7 @@ use proc_macro::TokenStream; /// - `license`: ASCII string literal of the license of the kernel module (required). /// - `alias`: array of ASCII string literals of the alias names of the kernel module. /// - `firmware`: array of ASCII string literals of the firmware files of -/// the kernel module. +/// the kernel module. #[proc_macro] pub fn module(ts: TokenStream) -> TokenStream { module::module(ts) diff --git a/scripts/gcc-plugins/randomize_layout_plugin.c b/scripts/gcc-plugins/randomize_layout_plugin.c index 746ff2d272f256..5694df3da2e95b 100644 --- a/scripts/gcc-plugins/randomize_layout_plugin.c +++ b/scripts/gcc-plugins/randomize_layout_plugin.c @@ -19,10 +19,6 @@ #include "gcc-common.h" #include "randomize_layout_seed.h" -#if BUILDING_GCC_MAJOR < 4 || (BUILDING_GCC_MAJOR == 4 && BUILDING_GCC_MINOR < 7) -#error "The RANDSTRUCT plugin requires GCC 4.7 or newer." -#endif - #define ORIG_TYPE_NAME(node) \ (TYPE_NAME(TYPE_MAIN_VARIANT(node)) != NULL_TREE ? ((const unsigned char *)IDENTIFIER_POINTER(TYPE_NAME(TYPE_MAIN_VARIANT(node)))) : (const unsigned char *)"anonymous") diff --git a/scripts/generate_rust_analyzer.py b/scripts/generate_rust_analyzer.py index f270c7b0cf345d..d2bc63cde8c6a3 100755 --- a/scripts/generate_rust_analyzer.py +++ b/scripts/generate_rust_analyzer.py @@ -145,6 +145,7 @@ def main(): parser.add_argument('--cfgs', action='append', default=[]) parser.add_argument("srctree", type=pathlib.Path) parser.add_argument("objtree", type=pathlib.Path) + parser.add_argument("sysroot", type=pathlib.Path) parser.add_argument("sysroot_src", type=pathlib.Path) parser.add_argument("exttree", type=pathlib.Path, nargs="?") args = parser.parse_args() @@ -154,9 +155,12 @@ def main(): level=logging.INFO if args.verbose else logging.WARNING ) + # Making sure that the `sysroot` and `sysroot_src` belong to the same toolchain. + assert args.sysroot in args.sysroot_src.parents + rust_project = { "crates": generate_crates(args.srctree, args.objtree, args.sysroot_src, args.exttree, args.cfgs), - "sysroot_src": str(args.sysroot_src), + "sysroot": str(args.sysroot), } json.dump(rust_project, sys.stdout, sort_keys=True, indent=4) diff --git a/scripts/generate_rust_target.rs b/scripts/generate_rust_target.rs index 87f34925eb7b71..404edf7587e088 100644 --- a/scripts/generate_rust_target.rs +++ b/scripts/generate_rust_target.rs @@ -162,7 +162,7 @@ fn main() { "data-layout", "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128", ); - let mut features = "-3dnow,-3dnowa,-mmx,+soft-float".to_string(); + let mut features = "-mmx,+soft-float".to_string(); if cfg.has("MITIGATION_RETPOLINE") { features += ",+retpoline-external-thunk"; } @@ -179,7 +179,7 @@ fn main() { "data-layout", "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i128:128-f64:32:64-f80:32-n8:16:32-S128", ); - let mut features = "-3dnow,-3dnowa,-mmx,+soft-float".to_string(); + let mut features = "-mmx,+soft-float".to_string(); if cfg.has("MITIGATION_RETPOLINE") { features += ",+retpoline-external-thunk"; } diff --git a/scripts/kallsyms.c b/scripts/kallsyms.c index 0ed873491bf555..123dab0572f800 100644 --- a/scripts/kallsyms.c +++ b/scripts/kallsyms.c @@ -5,8 +5,7 @@ * This software may be used and distributed according to the terms * of the GNU General Public License, incorporated herein by reference. * - * Usage: kallsyms [--all-symbols] [--absolute-percpu] - * [--lto-clang] in.map > out.S + * Usage: kallsyms [--all-symbols] [--absolute-percpu] in.map > out.S * * Table compression uses all the unused char codes on the symbols and * maps these to the most used substrings (tokens). For instance, it might @@ -62,7 +61,6 @@ static struct sym_entry **table; static unsigned int table_size, table_cnt; static int all_symbols; static int absolute_percpu; -static int lto_clang; static int token_profit[0x10000]; @@ -73,8 +71,7 @@ static unsigned char best_table_len[256]; static void usage(void) { - fprintf(stderr, "Usage: kallsyms [--all-symbols] [--absolute-percpu] " - "[--lto-clang] in.map > out.S\n"); + fprintf(stderr, "Usage: kallsyms [--all-symbols] [--absolute-percpu] in.map > out.S\n"); exit(1); } @@ -344,25 +341,6 @@ static bool symbol_absolute(const struct sym_entry *s) return s->percpu_absolute; } -static void cleanup_symbol_name(char *s) -{ - char *p; - - /* - * ASCII[.] = 2e - * ASCII[0-9] = 30,39 - * ASCII[A-Z] = 41,5a - * ASCII[_] = 5f - * ASCII[a-z] = 61,7a - * - * As above, replacing the first '.' in ".llvm." with '\0' does not - * affect the main sorting, but it helps us with subsorting. - */ - p = strstr(s, ".llvm."); - if (p) - *p = '\0'; -} - static int compare_names(const void *a, const void *b) { int ret; @@ -526,10 +504,6 @@ static void write_src(void) output_address(relative_base); printf("\n"); - if (lto_clang) - for (i = 0; i < table_cnt; i++) - cleanup_symbol_name((char *)table[i]->sym); - sort_symbols_by_name(); output_label("kallsyms_seqs_of_names"); for (i = 0; i < table_cnt; i++) @@ -807,7 +781,6 @@ int main(int argc, char **argv) static const struct option long_options[] = { {"all-symbols", no_argument, &all_symbols, 1}, {"absolute-percpu", no_argument, &absolute_percpu, 1}, - {"lto-clang", no_argument, <o_clang, 1}, {}, }; diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh index f7b2503cdba956..22d0bc8439863f 100755 --- a/scripts/link-vmlinux.sh +++ b/scripts/link-vmlinux.sh @@ -156,10 +156,6 @@ kallsyms() kallsymopt="${kallsymopt} --absolute-percpu" fi - if is_enabled CONFIG_LTO_CLANG; then - kallsymopt="${kallsymopt} --lto-clang" - fi - info KSYMS "${2}.S" scripts/kallsyms ${kallsymopt} "${1}" > "${2}.S" diff --git a/scripts/syscall.tbl b/scripts/syscall.tbl index 591d85e8ca7e35..845e24eb372e7f 100644 --- a/scripts/syscall.tbl +++ b/scripts/syscall.tbl @@ -53,6 +53,7 @@ 39 common umount2 sys_umount 40 common mount sys_mount 41 common pivot_root sys_pivot_root +42 common nfsservctl sys_ni_syscall 43 32 statfs64 sys_statfs64 compat_sys_statfs64 43 64 statfs sys_statfs 44 32 fstatfs64 sys_fstatfs64 compat_sys_fstatfs64 @@ -98,9 +99,9 @@ 77 common tee sys_tee 78 common readlinkat sys_readlinkat 79 stat64 fstatat64 sys_fstatat64 -79 newstat fstatat sys_newfstatat +79 64 newfstatat sys_newfstatat 80 stat64 fstat64 sys_fstat64 -80 newstat fstat sys_newfstat +80 64 fstat sys_newfstat 81 common sync sys_sync 82 common fsync sys_fsync 83 common fdatasync sys_fdatasync @@ -402,4 +403,3 @@ 460 common lsm_set_self_attr sys_lsm_set_self_attr 461 common lsm_list_modules sys_lsm_list_modules 462 common mseal sys_mseal -467 common uretprobe sys_uretprobe diff --git a/security/keys/trusted-keys/trusted_dcp.c b/security/keys/trusted-keys/trusted_dcp.c index b5f81a05be3676..4edc5bbbcda3c9 100644 --- a/security/keys/trusted-keys/trusted_dcp.c +++ b/security/keys/trusted-keys/trusted_dcp.c @@ -186,20 +186,21 @@ static int do_aead_crypto(u8 *in, u8 *out, size_t len, u8 *key, u8 *nonce, return ret; } -static int decrypt_blob_key(u8 *key) +static int decrypt_blob_key(u8 *encrypted_key, u8 *plain_key) { - return do_dcp_crypto(key, key, false); + return do_dcp_crypto(encrypted_key, plain_key, false); } -static int encrypt_blob_key(u8 *key) +static int encrypt_blob_key(u8 *plain_key, u8 *encrypted_key) { - return do_dcp_crypto(key, key, true); + return do_dcp_crypto(plain_key, encrypted_key, true); } static int trusted_dcp_seal(struct trusted_key_payload *p, char *datablob) { struct dcp_blob_fmt *b = (struct dcp_blob_fmt *)p->blob; int blen, ret; + u8 plain_blob_key[AES_KEYSIZE_128]; blen = calc_blob_len(p->key_len); if (blen > MAX_BLOB_SIZE) @@ -207,30 +208,36 @@ static int trusted_dcp_seal(struct trusted_key_payload *p, char *datablob) b->fmt_version = DCP_BLOB_VERSION; get_random_bytes(b->nonce, AES_KEYSIZE_128); - get_random_bytes(b->blob_key, AES_KEYSIZE_128); + get_random_bytes(plain_blob_key, AES_KEYSIZE_128); - ret = do_aead_crypto(p->key, b->payload, p->key_len, b->blob_key, + ret = do_aead_crypto(p->key, b->payload, p->key_len, plain_blob_key, b->nonce, true); if (ret) { pr_err("Unable to encrypt blob payload: %i\n", ret); - return ret; + goto out; } - ret = encrypt_blob_key(b->blob_key); + ret = encrypt_blob_key(plain_blob_key, b->blob_key); if (ret) { pr_err("Unable to encrypt blob key: %i\n", ret); - return ret; + goto out; } - b->payload_len = get_unaligned_le32(&p->key_len); + put_unaligned_le32(p->key_len, &b->payload_len); p->blob_len = blen; - return 0; + ret = 0; + +out: + memzero_explicit(plain_blob_key, sizeof(plain_blob_key)); + + return ret; } static int trusted_dcp_unseal(struct trusted_key_payload *p, char *datablob) { struct dcp_blob_fmt *b = (struct dcp_blob_fmt *)p->blob; int blen, ret; + u8 plain_blob_key[AES_KEYSIZE_128]; if (b->fmt_version != DCP_BLOB_VERSION) { pr_err("DCP blob has bad version: %i, expected %i\n", @@ -248,14 +255,14 @@ static int trusted_dcp_unseal(struct trusted_key_payload *p, char *datablob) goto out; } - ret = decrypt_blob_key(b->blob_key); + ret = decrypt_blob_key(b->blob_key, plain_blob_key); if (ret) { pr_err("Unable to decrypt blob key: %i\n", ret); goto out; } ret = do_aead_crypto(b->payload, p->key, p->key_len + DCP_BLOB_AUTHLEN, - b->blob_key, b->nonce, false); + plain_blob_key, b->nonce, false); if (ret) { pr_err("Unwrap of DCP payload failed: %i\n", ret); goto out; @@ -263,6 +270,8 @@ static int trusted_dcp_unseal(struct trusted_key_payload *p, char *datablob) ret = 0; out: + memzero_explicit(plain_blob_key, sizeof(plain_blob_key)); + return ret; } diff --git a/security/selinux/avc.c b/security/selinux/avc.c index 32eb67fb3e42c0..b49c44869dc462 100644 --- a/security/selinux/avc.c +++ b/security/selinux/avc.c @@ -330,12 +330,12 @@ static int avc_add_xperms_decision(struct avc_node *node, { struct avc_xperms_decision_node *dest_xpd; - node->ae.xp_node->xp.len++; dest_xpd = avc_xperms_decision_alloc(src->used); if (!dest_xpd) return -ENOMEM; avc_copy_xperms_decision(&dest_xpd->xpd, src); list_add(&dest_xpd->xpd_list, &node->ae.xp_node->xpd_head); + node->ae.xp_node->xp.len++; return 0; } @@ -907,7 +907,11 @@ static int avc_update_node(u32 event, u32 perms, u8 driver, u8 xperm, u32 ssid, node->ae.avd.auditdeny &= ~perms; break; case AVC_CALLBACK_ADD_XPERMS: - avc_add_xperms_decision(node, xpd); + rc = avc_add_xperms_decision(node, xpd); + if (rc) { + avc_node_kill(node); + goto out_unlock; + } break; } avc_node_replace(node, orig); diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 55c78c318ccd78..bfa61e005aace2 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -3852,7 +3852,17 @@ static int selinux_file_mprotect(struct vm_area_struct *vma, if (default_noexec && (prot & PROT_EXEC) && !(vma->vm_flags & VM_EXEC)) { int rc = 0; - if (vma_is_initial_heap(vma)) { + /* + * We don't use the vma_is_initial_heap() helper as it has + * a history of problems and is currently broken on systems + * where there is no heap, e.g. brk == start_brk. Before + * replacing the conditional below with vma_is_initial_heap(), + * or something similar, please ensure that the logic is the + * same as what we have below or you have tested every possible + * corner case you can think to test. + */ + if (vma->vm_start >= vma->vm_mm->start_brk && + vma->vm_end <= vma->vm_mm->brk) { rc = avc_has_perm(sid, sid, SECCLASS_PROCESS, PROCESS__EXECHEAP, NULL); } else if (!vma->vm_file && (vma_is_initial_stack(vma) || diff --git a/sound/aoa/soundbus/i2sbus/core.c b/sound/aoa/soundbus/i2sbus/core.c index 5431d2c4942106..ce84288168e459 100644 --- a/sound/aoa/soundbus/i2sbus/core.c +++ b/sound/aoa/soundbus/i2sbus/core.c @@ -335,7 +335,7 @@ static int i2sbus_add_dev(struct macio_dev *macio, static int i2sbus_probe(struct macio_dev* dev, const struct of_device_id *match) { - struct device_node *np = NULL; + struct device_node *np; int got = 0, err; struct i2sbus_control *control = NULL; @@ -347,7 +347,7 @@ static int i2sbus_probe(struct macio_dev* dev, const struct of_device_id *match) return -ENODEV; } - while ((np = of_get_next_child(dev->ofdev.dev.of_node, np))) { + for_each_child_of_node(dev->ofdev.dev.of_node, np) { if (of_device_is_compatible(np, "i2sbus") || of_device_is_compatible(np, "i2s-modem")) { got += i2sbus_add_dev(dev, control, np); diff --git a/sound/core/Kconfig b/sound/core/Kconfig index b970a173464708..2c5b9f964703d0 100644 --- a/sound/core/Kconfig +++ b/sound/core/Kconfig @@ -175,15 +175,6 @@ config SND_VERBOSE_PROCFS useful information to developers when a problem occurs). On the other side, it makes the ALSA subsystem larger. -config SND_VERBOSE_PRINTK - bool "Verbose printk" - help - Say Y here to enable verbose log messages. These messages - will help to identify source file and position containing - printed messages. - - You don't need this unless you're debugging ALSA. - config SND_CTL_FAST_LOOKUP bool "Fast lookup of control elements" if EXPERT default y @@ -251,6 +242,16 @@ config SND_JACK_INJECTION_DEBUG Say Y if you are debugging via jack injection interface. If unsure select "N". +config SND_UTIMER + bool "Enable support for userspace-controlled virtual timers" + depends on SND_TIMER + help + Say Y to enable the support of userspace-controlled timers. These + timers are purely virtual, and they are supposed to be triggered + from userspace. They could be quite useful when synchronizing the + sound timing with userspace applications (for instance, when sending + data through snd-aloop). + config SND_VMASTER bool diff --git a/sound/core/control.c b/sound/core/control.c index f668826649b376..7d7d592a842800 100644 --- a/sound/core/control.c +++ b/sound/core/control.c @@ -79,7 +79,7 @@ static int snd_ctl_open(struct inode *inode, struct file *file) ctl->preferred_subdevice[i] = -1; ctl->pid = get_pid(task_pid(current)); file->private_data = ctl; - scoped_guard(write_lock_irqsave, &card->ctl_files_rwlock) + scoped_guard(write_lock_irqsave, &card->controls_rwlock) list_add_tail(&ctl->list, &card->ctl_files); snd_card_unref(card); return 0; @@ -117,7 +117,7 @@ static int snd_ctl_release(struct inode *inode, struct file *file) file->private_data = NULL; card = ctl->card; - scoped_guard(write_lock_irqsave, &card->ctl_files_rwlock) + scoped_guard(write_lock_irqsave, &card->controls_rwlock) list_del(&ctl->list); scoped_guard(rwsem_write, &card->controls_rwsem) { @@ -157,7 +157,7 @@ void snd_ctl_notify(struct snd_card *card, unsigned int mask, if (card->shutdown) return; - guard(read_lock_irqsave)(&card->ctl_files_rwlock); + guard(read_lock_irqsave)(&card->controls_rwlock); #if IS_ENABLED(CONFIG_SND_MIXER_OSS) card->mixer_oss_change_count++; #endif @@ -470,7 +470,7 @@ static int __snd_ctl_add_replace(struct snd_card *card, if (id.index > UINT_MAX - kcontrol->count) return -EINVAL; - old = snd_ctl_find_id_locked(card, &id); + old = snd_ctl_find_id(card, &id); if (!old) { if (mode == CTL_REPLACE) return -EINVAL; @@ -491,10 +491,12 @@ static int __snd_ctl_add_replace(struct snd_card *card, if (snd_ctl_find_hole(card, kcontrol->count) < 0) return -ENOMEM; - list_add_tail(&kcontrol->list, &card->controls); - card->controls_count += kcontrol->count; - kcontrol->id.numid = card->last_numid + 1; - card->last_numid += kcontrol->count; + scoped_guard(write_lock_irq, &card->controls_rwlock) { + list_add_tail(&kcontrol->list, &card->controls); + card->controls_count += kcontrol->count; + kcontrol->id.numid = card->last_numid + 1; + card->last_numid += kcontrol->count; + } add_hash_entries(card, kcontrol); @@ -579,12 +581,15 @@ static int __snd_ctl_remove(struct snd_card *card, if (snd_BUG_ON(!card || !kcontrol)) return -EINVAL; - list_del(&kcontrol->list); if (remove_hash) remove_hash_entries(card, kcontrol); - card->controls_count -= kcontrol->count; + scoped_guard(write_lock_irq, &card->controls_rwlock) { + list_del(&kcontrol->list); + card->controls_count -= kcontrol->count; + } + for (idx = 0; idx < kcontrol->count; idx++) snd_ctl_notify_one(card, SNDRV_CTL_EVENT_MASK_REMOVE, kcontrol, idx); snd_ctl_free_one(kcontrol); @@ -634,7 +639,7 @@ int snd_ctl_remove_id(struct snd_card *card, struct snd_ctl_elem_id *id) struct snd_kcontrol *kctl; guard(rwsem_write)(&card->controls_rwsem); - kctl = snd_ctl_find_id_locked(card, id); + kctl = snd_ctl_find_id(card, id); if (kctl == NULL) return -ENOENT; return snd_ctl_remove_locked(card, kctl); @@ -659,7 +664,7 @@ static int snd_ctl_remove_user_ctl(struct snd_ctl_file * file, int idx; guard(rwsem_write)(&card->controls_rwsem); - kctl = snd_ctl_find_id_locked(card, id); + kctl = snd_ctl_find_id(card, id); if (kctl == NULL) return -ENOENT; if (!(kctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_USER)) @@ -691,7 +696,7 @@ int snd_ctl_activate_id(struct snd_card *card, struct snd_ctl_elem_id *id, int ret; down_write(&card->controls_rwsem); - kctl = snd_ctl_find_id_locked(card, id); + kctl = snd_ctl_find_id(card, id); if (kctl == NULL) { ret = -ENOENT; goto unlock; @@ -745,7 +750,7 @@ int snd_ctl_rename_id(struct snd_card *card, struct snd_ctl_elem_id *src_id, int saved_numid; guard(rwsem_write)(&card->controls_rwsem); - kctl = snd_ctl_find_id_locked(card, src_id); + kctl = snd_ctl_find_id(card, src_id); if (kctl == NULL) return -ENOENT; saved_numid = kctl->id.numid; @@ -787,6 +792,7 @@ snd_ctl_find_numid_slow(struct snd_card *card, unsigned int numid) { struct snd_kcontrol *kctl; + guard(read_lock_irqsave)(&card->controls_rwlock); list_for_each_entry(kctl, &card->controls, list) { if (kctl->id.numid <= numid && kctl->id.numid + kctl->count > numid) return kctl; @@ -796,72 +802,51 @@ snd_ctl_find_numid_slow(struct snd_card *card, unsigned int numid) #endif /* !CONFIG_SND_CTL_FAST_LOOKUP */ /** - * snd_ctl_find_numid_locked - find the control instance with the given number-id + * snd_ctl_find_numid - find the control instance with the given number-id * @card: the card instance * @numid: the number-id to search * * Finds the control instance with the given number-id from the card. * - * The caller must down card->controls_rwsem before calling this function - * (if the race condition can happen). - * * Return: The pointer of the instance if found, or %NULL if not. + * + * Note that this function takes card->controls_rwlock lock internally. */ -struct snd_kcontrol * -snd_ctl_find_numid_locked(struct snd_card *card, unsigned int numid) +struct snd_kcontrol *snd_ctl_find_numid(struct snd_card *card, + unsigned int numid) { if (snd_BUG_ON(!card || !numid)) return NULL; - lockdep_assert_held(&card->controls_rwsem); + #ifdef CONFIG_SND_CTL_FAST_LOOKUP return xa_load(&card->ctl_numids, numid); #else return snd_ctl_find_numid_slow(card, numid); #endif } -EXPORT_SYMBOL(snd_ctl_find_numid_locked); - -/** - * snd_ctl_find_numid - find the control instance with the given number-id - * @card: the card instance - * @numid: the number-id to search - * - * Finds the control instance with the given number-id from the card. - * - * Return: The pointer of the instance if found, or %NULL if not. - * - * Note that this function takes card->controls_rwsem lock internally. - */ -struct snd_kcontrol *snd_ctl_find_numid(struct snd_card *card, - unsigned int numid) -{ - guard(rwsem_read)(&card->controls_rwsem); - return snd_ctl_find_numid_locked(card, numid); -} EXPORT_SYMBOL(snd_ctl_find_numid); /** - * snd_ctl_find_id_locked - find the control instance with the given id + * snd_ctl_find_id - find the control instance with the given id * @card: the card instance * @id: the id to search * * Finds the control instance with the given id from the card. * - * The caller must down card->controls_rwsem before calling this function - * (if the race condition can happen). - * * Return: The pointer of the instance if found, or %NULL if not. + * + * Note that this function takes card->controls_rwlock lock internally. */ -struct snd_kcontrol *snd_ctl_find_id_locked(struct snd_card *card, - const struct snd_ctl_elem_id *id) +struct snd_kcontrol *snd_ctl_find_id(struct snd_card *card, + const struct snd_ctl_elem_id *id) { struct snd_kcontrol *kctl; if (snd_BUG_ON(!card || !id)) return NULL; - lockdep_assert_held(&card->controls_rwsem); + if (id->numid != 0) - return snd_ctl_find_numid_locked(card, id->numid); + return snd_ctl_find_numid(card, id->numid); #ifdef CONFIG_SND_CTL_FAST_LOOKUP kctl = xa_load(&card->ctl_hash, get_ctl_id_hash(id)); if (kctl && elem_id_matches(kctl, id)) @@ -870,31 +855,13 @@ struct snd_kcontrol *snd_ctl_find_id_locked(struct snd_card *card, return NULL; /* we can rely on only hash table */ #endif /* no matching in hash table - try all as the last resort */ + guard(read_lock_irqsave)(&card->controls_rwlock); list_for_each_entry(kctl, &card->controls, list) if (elem_id_matches(kctl, id)) return kctl; return NULL; } -EXPORT_SYMBOL(snd_ctl_find_id_locked); - -/** - * snd_ctl_find_id - find the control instance with the given id - * @card: the card instance - * @id: the id to search - * - * Finds the control instance with the given id from the card. - * - * Return: The pointer of the instance if found, or %NULL if not. - * - * Note that this function takes card->controls_rwsem lock internally. - */ -struct snd_kcontrol *snd_ctl_find_id(struct snd_card *card, - const struct snd_ctl_elem_id *id) -{ - guard(rwsem_read)(&card->controls_rwsem); - return snd_ctl_find_id_locked(card, id); -} EXPORT_SYMBOL(snd_ctl_find_id); static int snd_ctl_card_info(struct snd_card *card, struct snd_ctl_file * ctl, @@ -1196,7 +1163,7 @@ static int snd_ctl_elem_info(struct snd_ctl_file *ctl, struct snd_kcontrol *kctl; guard(rwsem_read)(&card->controls_rwsem); - kctl = snd_ctl_find_id_locked(card, &info->id); + kctl = snd_ctl_find_id(card, &info->id); if (!kctl) return -ENOENT; return __snd_ctl_elem_info(card, kctl, info, ctl); @@ -1237,7 +1204,7 @@ static int snd_ctl_elem_read(struct snd_card *card, int ret; guard(rwsem_read)(&card->controls_rwsem); - kctl = snd_ctl_find_id_locked(card, &control->id); + kctl = snd_ctl_find_id(card, &control->id); if (!kctl) return -ENOENT; @@ -1306,7 +1273,7 @@ static int snd_ctl_elem_write(struct snd_card *card, struct snd_ctl_file *file, int result = 0; down_write(&card->controls_rwsem); - kctl = snd_ctl_find_id_locked(card, &control->id); + kctl = snd_ctl_find_id(card, &control->id); if (kctl == NULL) { up_write(&card->controls_rwsem); return -ENOENT; @@ -1386,7 +1353,7 @@ static int snd_ctl_elem_lock(struct snd_ctl_file *file, if (copy_from_user(&id, _id, sizeof(id))) return -EFAULT; guard(rwsem_write)(&card->controls_rwsem); - kctl = snd_ctl_find_id_locked(card, &id); + kctl = snd_ctl_find_id(card, &id); if (!kctl) return -ENOENT; vd = &kctl->vd[snd_ctl_get_ioff(kctl, &id)]; @@ -1407,7 +1374,7 @@ static int snd_ctl_elem_unlock(struct snd_ctl_file *file, if (copy_from_user(&id, _id, sizeof(id))) return -EFAULT; guard(rwsem_write)(&card->controls_rwsem); - kctl = snd_ctl_find_id_locked(card, &id); + kctl = snd_ctl_find_id(card, &id); if (!kctl) return -ENOENT; vd = &kctl->vd[snd_ctl_get_ioff(kctl, &id)]; @@ -1904,7 +1871,7 @@ static int snd_ctl_tlv_ioctl(struct snd_ctl_file *file, container_size = header.length; container = buf->tlv; - kctl = snd_ctl_find_numid_locked(file->card, header.numid); + kctl = snd_ctl_find_numid(file->card, header.numid); if (kctl == NULL) return -ENOENT; @@ -2191,7 +2158,7 @@ int snd_ctl_get_preferred_subdevice(struct snd_card *card, int type) struct snd_ctl_file *kctl; int subdevice = -1; - guard(read_lock_irqsave)(&card->ctl_files_rwlock); + guard(read_lock_irqsave)(&card->controls_rwlock); list_for_each_entry(kctl, &card->ctl_files, list) { if (kctl->pid == task_pid(current)) { subdevice = kctl->preferred_subdevice[type]; @@ -2341,7 +2308,7 @@ static int snd_ctl_dev_disconnect(struct snd_device *device) struct snd_card *card = device->device_data; struct snd_ctl_file *ctl; - scoped_guard(read_lock_irqsave, &card->ctl_files_rwlock) { + scoped_guard(read_lock_irqsave, &card->controls_rwlock) { list_for_each_entry(ctl, &card->ctl_files, list) { wake_up(&ctl->change_sleep); snd_kill_fasync(ctl->fasync, SIGIO, POLL_ERR); diff --git a/sound/core/control_compat.c b/sound/core/control_compat.c index 934bb945e702a2..6459809ed36486 100644 --- a/sound/core/control_compat.c +++ b/sound/core/control_compat.c @@ -79,6 +79,7 @@ struct snd_ctl_elem_info32 { static int snd_ctl_elem_info_compat(struct snd_ctl_file *ctl, struct snd_ctl_elem_info32 __user *data32) { + struct snd_card *card = ctl->card; struct snd_ctl_elem_info *data __free(kfree) = NULL; int err; @@ -95,7 +96,11 @@ static int snd_ctl_elem_info_compat(struct snd_ctl_file *ctl, if (get_user(data->value.enumerated.item, &data32->value.enumerated.item)) return -EFAULT; + err = snd_power_ref_and_wait(card); + if (err < 0) + return err; err = snd_ctl_elem_info(ctl, data); + snd_power_unref(card); if (err < 0) return err; /* restore info to 32bit */ @@ -168,17 +173,14 @@ static int get_ctl_type(struct snd_card *card, struct snd_ctl_elem_id *id, int err; guard(rwsem_read)(&card->controls_rwsem); - kctl = snd_ctl_find_id_locked(card, id); + kctl = snd_ctl_find_id(card, id); if (!kctl) return -ENOENT; info = kzalloc(sizeof(*info), GFP_KERNEL); if (info == NULL) return -ENOMEM; info->id = *id; - err = snd_power_ref_and_wait(card); - if (!err) - err = kctl->info(kctl, info); - snd_power_unref(card); + err = kctl->info(kctl, info); if (err >= 0) { err = info->type; *countp = info->count; @@ -275,8 +277,8 @@ static int copy_ctl_value_to_user(void __user *userdata, return 0; } -static int ctl_elem_read_user(struct snd_card *card, - void __user *userdata, void __user *valuep) +static int __ctl_elem_read_user(struct snd_card *card, + void __user *userdata, void __user *valuep) { struct snd_ctl_elem_value *data __free(kfree) = NULL; int err, type, count; @@ -296,8 +298,21 @@ static int ctl_elem_read_user(struct snd_card *card, return copy_ctl_value_to_user(userdata, valuep, data, type, count); } -static int ctl_elem_write_user(struct snd_ctl_file *file, - void __user *userdata, void __user *valuep) +static int ctl_elem_read_user(struct snd_card *card, + void __user *userdata, void __user *valuep) +{ + int err; + + err = snd_power_ref_and_wait(card); + if (err < 0) + return err; + err = __ctl_elem_read_user(card, userdata, valuep); + snd_power_unref(card); + return err; +} + +static int __ctl_elem_write_user(struct snd_ctl_file *file, + void __user *userdata, void __user *valuep) { struct snd_ctl_elem_value *data __free(kfree) = NULL; struct snd_card *card = file->card; @@ -318,6 +333,20 @@ static int ctl_elem_write_user(struct snd_ctl_file *file, return copy_ctl_value_to_user(userdata, valuep, data, type, count); } +static int ctl_elem_write_user(struct snd_ctl_file *file, + void __user *userdata, void __user *valuep) +{ + struct snd_card *card = file->card; + int err; + + err = snd_power_ref_and_wait(card); + if (err < 0) + return err; + err = __ctl_elem_write_user(file, userdata, valuep); + snd_power_unref(card); + return err; +} + static int snd_ctl_elem_read_user_compat(struct snd_card *card, struct snd_ctl_elem_value32 __user *data32) { diff --git a/sound/core/control_led.c b/sound/core/control_led.c index 804805a95e2f04..65a1ebe877768f 100644 --- a/sound/core/control_led.c +++ b/sound/core/control_led.c @@ -254,7 +254,7 @@ static int snd_ctl_led_set_id(int card_number, struct snd_ctl_elem_id *id, if (!card) return -ENXIO; guard(rwsem_write)(&card->controls_rwsem); - kctl = snd_ctl_find_id_locked(card, id); + kctl = snd_ctl_find_id(card, id); if (!kctl) return -ENOENT; ioff = snd_ctl_get_ioff(kctl, id); @@ -677,7 +677,7 @@ static void snd_ctl_led_sysfs_add(struct snd_card *card) cerr: put_device(&led_card->dev); cerr2: - printk(KERN_ERR "snd_ctl_led: unable to add card%d", card->number); + dev_err(card->dev, "snd_ctl_led: unable to add card%d", card->number); } } diff --git a/sound/core/init.c b/sound/core/init.c index b9b708cf980d6d..b92aa7103589e5 100644 --- a/sound/core/init.c +++ b/sound/core/init.c @@ -315,7 +315,7 @@ static int snd_card_init(struct snd_card *card, struct device *parent, card->module = module; INIT_LIST_HEAD(&card->devices); init_rwsem(&card->controls_rwsem); - rwlock_init(&card->ctl_files_rwlock); + rwlock_init(&card->controls_rwlock); INIT_LIST_HEAD(&card->controls); INIT_LIST_HEAD(&card->ctl_files); #ifdef CONFIG_SND_CTL_FAST_LOOKUP diff --git a/sound/core/misc.c b/sound/core/misc.c index d32a19976a2b95..c2fda3bd90a0d4 100644 --- a/sound/core/misc.c +++ b/sound/core/misc.c @@ -13,20 +13,6 @@ #include #include -#ifdef CONFIG_SND_DEBUG - -#ifdef CONFIG_SND_DEBUG_VERBOSE -#define DEFAULT_DEBUG_LEVEL 2 -#else -#define DEFAULT_DEBUG_LEVEL 1 -#endif - -static int debug = DEFAULT_DEBUG_LEVEL; -module_param(debug, int, 0644); -MODULE_PARM_DESC(debug, "Debug level (0 = disable)"); - -#endif /* CONFIG_SND_DEBUG */ - void release_and_free_resource(struct resource *res) { if (res) { @@ -36,63 +22,6 @@ void release_and_free_resource(struct resource *res) } EXPORT_SYMBOL(release_and_free_resource); -#ifdef CONFIG_SND_VERBOSE_PRINTK -/* strip the leading path if the given path is absolute */ -static const char *sanity_file_name(const char *path) -{ - if (*path == '/') - return strrchr(path, '/') + 1; - else - return path; -} -#endif - -#if defined(CONFIG_SND_DEBUG) || defined(CONFIG_SND_VERBOSE_PRINTK) -void __snd_printk(unsigned int level, const char *path, int line, - const char *format, ...) -{ - va_list args; -#ifdef CONFIG_SND_VERBOSE_PRINTK - int kern_level; - struct va_format vaf; - char verbose_fmt[] = KERN_DEFAULT "ALSA %s:%d %pV"; - bool level_found = false; -#endif - -#ifdef CONFIG_SND_DEBUG - if (debug < level) - return; -#endif - - va_start(args, format); -#ifdef CONFIG_SND_VERBOSE_PRINTK - vaf.fmt = format; - vaf.va = &args; - - while ((kern_level = printk_get_level(vaf.fmt)) != 0) { - const char *end_of_header = printk_skip_level(vaf.fmt); - - /* Ignore KERN_CONT. We print filename:line for each piece. */ - if (kern_level >= '0' && kern_level <= '7') { - memcpy(verbose_fmt, vaf.fmt, end_of_header - vaf.fmt); - level_found = true; - } - - vaf.fmt = end_of_header; - } - - if (!level_found && level) - memcpy(verbose_fmt, KERN_DEBUG, sizeof(KERN_DEBUG) - 1); - - printk(verbose_fmt, sanity_file_name(path), line, &vaf); -#else - vprintk(format, args); -#endif - va_end(args); -} -EXPORT_SYMBOL_GPL(__snd_printk); -#endif - #ifdef CONFIG_PCI #include /** diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c index 6a0508093ea688..33bf9a220adac6 100644 --- a/sound/core/oss/mixer_oss.c +++ b/sound/core/oss/mixer_oss.c @@ -510,7 +510,7 @@ static struct snd_kcontrol *snd_mixer_oss_test_id(struct snd_mixer_oss *mixer, c id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; strscpy(id.name, name, sizeof(id.name)); id.index = index; - return snd_ctl_find_id_locked(card, &id); + return snd_ctl_find_id(card, &id); } static void snd_mixer_oss_get_volume1_vol(struct snd_mixer_oss_file *fmixer, @@ -526,7 +526,7 @@ static void snd_mixer_oss_get_volume1_vol(struct snd_mixer_oss_file *fmixer, if (numid == ID_UNKNOWN) return; guard(rwsem_read)(&card->controls_rwsem); - kctl = snd_ctl_find_numid_locked(card, numid); + kctl = snd_ctl_find_numid(card, numid); if (!kctl) return; uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL); @@ -559,7 +559,7 @@ static void snd_mixer_oss_get_volume1_sw(struct snd_mixer_oss_file *fmixer, if (numid == ID_UNKNOWN) return; guard(rwsem_read)(&card->controls_rwsem); - kctl = snd_ctl_find_numid_locked(card, numid); + kctl = snd_ctl_find_numid(card, numid); if (!kctl) return; uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL); @@ -619,7 +619,7 @@ static void snd_mixer_oss_put_volume1_vol(struct snd_mixer_oss_file *fmixer, if (numid == ID_UNKNOWN) return; guard(rwsem_read)(&card->controls_rwsem); - kctl = snd_ctl_find_numid_locked(card, numid); + kctl = snd_ctl_find_numid(card, numid); if (!kctl) return; uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL); @@ -656,7 +656,7 @@ static void snd_mixer_oss_put_volume1_sw(struct snd_mixer_oss_file *fmixer, if (numid == ID_UNKNOWN) return; guard(rwsem_read)(&card->controls_rwsem); - kctl = snd_ctl_find_numid_locked(card, numid); + kctl = snd_ctl_find_numid(card, numid); if (!kctl) return; uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL); diff --git a/sound/core/oss/pcm_plugin.h b/sound/core/oss/pcm_plugin.h index 50a6b50f5db4c3..7b76cf64157e10 100644 --- a/sound/core/oss/pcm_plugin.h +++ b/sound/core/oss/pcm_plugin.h @@ -74,7 +74,6 @@ int snd_pcm_plugin_build(struct snd_pcm_substream *handle, size_t extra, struct snd_pcm_plugin **ret); int snd_pcm_plugin_free(struct snd_pcm_plugin *plugin); -int snd_pcm_plugin_clear(struct snd_pcm_plugin **first); int snd_pcm_plug_alloc(struct snd_pcm_substream *plug, snd_pcm_uframes_t frames); snd_pcm_sframes_t snd_pcm_plug_client_size(struct snd_pcm_substream *handle, snd_pcm_uframes_t drv_size); snd_pcm_sframes_t snd_pcm_plug_slave_size(struct snd_pcm_substream *handle, snd_pcm_uframes_t clt_size); @@ -139,8 +138,6 @@ int snd_pcm_area_copy(const struct snd_pcm_channel_area *src_channel, size_t dst_offset, size_t samples, snd_pcm_format_t format); -void *snd_pcm_plug_buf_alloc(struct snd_pcm_substream *plug, snd_pcm_uframes_t size); -void snd_pcm_plug_buf_unlock(struct snd_pcm_substream *plug, void *ptr); #else static inline snd_pcm_sframes_t snd_pcm_plug_client_size(struct snd_pcm_substream *handle, snd_pcm_uframes_t drv_size) { return drv_size; } @@ -160,7 +157,7 @@ snd_pcm_sframes_t snd_pcm_oss_readv3(struct snd_pcm_substream *substream, void **bufs, snd_pcm_uframes_t frames); #ifdef PLUGIN_DEBUG -#define pdprintf(fmt, args...) printk(KERN_DEBUG "plugin: " fmt, ##args) +#define pdprintf(fmt, args...) pr_debug("plugin: " fmt, ##args) #else #define pdprintf(fmt, args...) #endif diff --git a/sound/core/pcm.c b/sound/core/pcm.c index dc37f3508dc7a0..290690fc2abcbb 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c @@ -462,6 +462,9 @@ static void snd_pcm_substream_proc_status_read(struct snd_info_entry *entry, snd_iprintf(buffer, "-----\n"); snd_iprintf(buffer, "hw_ptr : %ld\n", runtime->status->hw_ptr); snd_iprintf(buffer, "appl_ptr : %ld\n", runtime->control->appl_ptr); +#ifdef CONFIG_SND_PCM_XRUN_DEBUG + snd_iprintf(buffer, "xrun_counter: %d\n", substream->xrun_counter); +#endif } #ifdef CONFIG_SND_PCM_XRUN_DEBUG @@ -970,6 +973,9 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream, substream->pid = get_pid(task_pid(current)); pstr->substream_opened++; *rsubstream = substream; +#ifdef CONFIG_SND_PCM_XRUN_DEBUG + substream->xrun_counter = 0; +#endif /* CONFIG_SND_PCM_XRUN_DEBUG */ return 0; } diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index 6e7905749c4a3b..6eaa950504cfc0 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c @@ -184,6 +184,9 @@ void __snd_pcm_xrun(struct snd_pcm_substream *substream) pcm_warn(substream->pcm, "XRUN: %s\n", name); dump_stack_on_xrun(substream); } +#ifdef CONFIG_SND_PCM_XRUN_DEBUG + substream->xrun_counter++; +#endif } #ifdef CONFIG_SND_PCM_XRUN_DEBUG diff --git a/sound/core/seq/oss/seq_oss_device.h b/sound/core/seq/oss/seq_oss_device.h index f0e964b19af7ae..98dd20b429764c 100644 --- a/sound/core/seq/oss/seq_oss_device.h +++ b/sound/core/seq/oss/seq_oss_device.h @@ -116,10 +116,6 @@ __poll_t snd_seq_oss_poll(struct seq_oss_devinfo *dp, struct file *file, poll_ta void snd_seq_oss_reset(struct seq_oss_devinfo *dp); -/* */ -void snd_seq_oss_process_queue(struct seq_oss_devinfo *dp, abstime_t time); - - /* proc interface */ void snd_seq_oss_system_info_read(struct snd_info_buffer *buf); void snd_seq_oss_midi_info_read(struct snd_info_buffer *buf); diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c index 8c4ee5066afe5b..6437193e42bf40 100644 --- a/sound/core/seq/seq_clientmgr.c +++ b/sound/core/seq/seq_clientmgr.c @@ -70,7 +70,7 @@ static int bounce_error_event(struct snd_seq_client *client, int err, int atomic, int hop); static int snd_seq_deliver_single_event(struct snd_seq_client *client, struct snd_seq_event *event, - int filter, int atomic, int hop); + int atomic, int hop); #if IS_ENABLED(CONFIG_SND_SEQ_UMP) static void free_ump_info(struct snd_seq_client *client); @@ -525,10 +525,8 @@ static int check_port_perm(struct snd_seq_client_port *port, unsigned int flags) /* * check if the destination client is available, and return the pointer - * if filter is non-zero, client filter bitmap is tested. */ -static struct snd_seq_client *get_event_dest_client(struct snd_seq_event *event, - int filter) +static struct snd_seq_client *get_event_dest_client(struct snd_seq_event *event) { struct snd_seq_client *dest; @@ -537,11 +535,12 @@ static struct snd_seq_client *get_event_dest_client(struct snd_seq_event *event, return NULL; if (! dest->accept_input) goto __not_avail; + if (snd_seq_ev_is_ump(event)) + return dest; /* ok - no filter checks */ + if ((dest->filter & SNDRV_SEQ_FILTER_USE_EVENT) && ! test_bit(event->type, dest->event_filter)) goto __not_avail; - if (filter && !(dest->filter & filter)) - goto __not_avail; return dest; /* ok - accessible */ __not_avail: @@ -585,7 +584,7 @@ static int bounce_error_event(struct snd_seq_client *client, bounce_ev.data.quote.origin = event->dest; bounce_ev.data.quote.event = event; bounce_ev.data.quote.value = -err; /* use positive value */ - result = snd_seq_deliver_single_event(NULL, &bounce_ev, 0, atomic, hop + 1); + result = snd_seq_deliver_single_event(NULL, &bounce_ev, atomic, hop + 1); if (result < 0) { client->event_lost++; return result; @@ -652,7 +651,7 @@ int __snd_seq_deliver_single_event(struct snd_seq_client *dest, */ static int snd_seq_deliver_single_event(struct snd_seq_client *client, struct snd_seq_event *event, - int filter, int atomic, int hop) + int atomic, int hop) { struct snd_seq_client *dest = NULL; struct snd_seq_client_port *dest_port = NULL; @@ -661,7 +660,7 @@ static int snd_seq_deliver_single_event(struct snd_seq_client *client, direct = snd_seq_ev_is_direct(event); - dest = get_event_dest_client(event, filter); + dest = get_event_dest_client(event); if (dest == NULL) goto __skip; dest_port = snd_seq_port_use_ptr(dest, event->dest.port); @@ -741,8 +740,7 @@ static int __deliver_to_subscribers(struct snd_seq_client *client, /* convert time according to flag with subscription */ update_timestamp_of_queue(event, subs->info.queue, subs->info.flags & SNDRV_SEQ_PORT_SUBS_TIME_REAL); - err = snd_seq_deliver_single_event(client, event, - 0, atomic, hop); + err = snd_seq_deliver_single_event(client, event, atomic, hop); if (err < 0) { /* save first error that occurs and continue */ if (!result) @@ -815,7 +813,7 @@ static int snd_seq_deliver_event(struct snd_seq_client *client, struct snd_seq_e event->dest.client == SNDRV_SEQ_ADDRESS_SUBSCRIBERS) result = deliver_to_subscribers(client, event, atomic, hop); else - result = snd_seq_deliver_single_event(client, event, 0, atomic, hop); + result = snd_seq_deliver_single_event(client, event, atomic, hop); return result; } @@ -2633,13 +2631,18 @@ static void snd_seq_info_dump_ports(struct snd_info_buffer *buffer, list_for_each_entry(p, &client->ports_list_head, list) { if (p->capability & SNDRV_SEQ_PORT_CAP_INACTIVE) continue; - snd_iprintf(buffer, " Port %3d : \"%s\" (%c%c%c%c) [%s]\n", + snd_iprintf(buffer, " Port %3d : \"%s\" (%c%c%c%c) [%s]", p->addr.port, p->name, FLAG_PERM_RD(p->capability), FLAG_PERM_WR(p->capability), FLAG_PERM_EX(p->capability), FLAG_PERM_DUPLEX(p->capability), port_direction_name(p->direction)); +#if IS_ENABLED(CONFIG_SND_SEQ_UMP) + if (snd_seq_client_is_midi2(client) && p->is_midi1) + snd_iprintf(buffer, " [MIDI1]"); +#endif + snd_iprintf(buffer, "\n"); snd_seq_info_dump_subscribers(buffer, &p->c_src, 1, " Connecting To: "); snd_seq_info_dump_subscribers(buffer, &p->c_dest, 0, " Connected From: "); } diff --git a/sound/core/seq/seq_ports.c b/sound/core/seq/seq_ports.c index ca631ca4f2c64e..cc2f8e846584e9 100644 --- a/sound/core/seq/seq_ports.c +++ b/sound/core/seq/seq_ports.c @@ -362,6 +362,8 @@ int snd_seq_set_port_info(struct snd_seq_client_port * port, port->direction |= SNDRV_SEQ_PORT_DIR_OUTPUT; } + port->is_midi1 = !!(info->flags & SNDRV_SEQ_PORT_FLG_IS_MIDI1); + return 0; } @@ -399,6 +401,9 @@ int snd_seq_get_port_info(struct snd_seq_client_port * port, info->time_queue = port->time_queue; } + if (port->is_midi1) + info->flags |= SNDRV_SEQ_PORT_FLG_IS_MIDI1; + /* UMP direction and group */ info->direction = port->direction; info->ump_group = port->ump_group; diff --git a/sound/core/seq/seq_ports.h b/sound/core/seq/seq_ports.h index b111382f697aa6..b3b35018cb8209 100644 --- a/sound/core/seq/seq_ports.h +++ b/sound/core/seq/seq_ports.h @@ -7,6 +7,7 @@ #define __SND_SEQ_PORTS_H #include +#include #include "seq_lock.h" /* list of 'exported' ports */ @@ -42,17 +43,6 @@ struct snd_seq_port_subs_info { int (*close)(void *private_data, struct snd_seq_port_subscribe *info); }; -/* context for converting from legacy control event to UMP packet */ -struct snd_seq_ump_midi2_bank { - bool rpn_set; - bool nrpn_set; - bool bank_set; - unsigned char cc_rpn_msb, cc_rpn_lsb; - unsigned char cc_nrpn_msb, cc_nrpn_lsb; - unsigned char cc_data_msb, cc_data_lsb; - unsigned char cc_bank_msb, cc_bank_lsb; -}; - struct snd_seq_client_port { struct snd_seq_addr addr; /* client/port number */ @@ -87,8 +77,10 @@ struct snd_seq_client_port { unsigned char direction; unsigned char ump_group; + bool is_midi1; /* keep MIDI 1.0 protocol */ + #if IS_ENABLED(CONFIG_SND_SEQ_UMP) - struct snd_seq_ump_midi2_bank midi2_bank[16]; /* per channel */ + struct ump_cvt_to_ump_bank midi2_bank[16]; /* per channel */ #endif }; diff --git a/sound/core/seq/seq_queue.h b/sound/core/seq/seq_queue.h index c69105dc1a1037..74cc31aacdac15 100644 --- a/sound/core/seq/seq_queue.h +++ b/sound/core/seq/seq_queue.h @@ -84,7 +84,6 @@ void snd_seq_check_queue(struct snd_seq_queue *q, int atomic, int hop); int snd_seq_queue_check_access(int queueid, int client); int snd_seq_queue_timer_set_tempo(int queueid, int client, struct snd_seq_queue_tempo *info); int snd_seq_queue_set_owner(int queueid, int client, int locked); -int snd_seq_queue_set_locked(int queueid, int client, int locked); int snd_seq_queue_timer_open(int queueid); int snd_seq_queue_timer_close(int queueid); int snd_seq_queue_use(int queueid, int client, int use); diff --git a/sound/core/seq/seq_timer.h b/sound/core/seq/seq_timer.h index 3b906064bde1be..c8803216a3a416 100644 --- a/sound/core/seq/seq_timer.h +++ b/sound/core/seq/seq_timer.h @@ -109,8 +109,6 @@ static inline void snd_seq_inc_time_nsec(snd_seq_real_time_t *tm, unsigned long struct snd_seq_queue; int snd_seq_timer_open(struct snd_seq_queue *q); int snd_seq_timer_close(struct snd_seq_queue *q); -int snd_seq_timer_midi_open(struct snd_seq_queue *q); -int snd_seq_timer_midi_close(struct snd_seq_queue *q); void snd_seq_timer_defaults(struct snd_seq_timer *tmr); void snd_seq_timer_reset(struct snd_seq_timer *tmr); int snd_seq_timer_stop(struct snd_seq_timer *tmr); diff --git a/sound/core/seq/seq_ump_client.c b/sound/core/seq/seq_ump_client.c index 637154bd1a3fcc..e5d3f4d206bf6a 100644 --- a/sound/core/seq/seq_ump_client.c +++ b/sound/core/seq/seq_ump_client.c @@ -189,6 +189,8 @@ static void fill_port_info(struct snd_seq_port_info *port, port->ump_group = group->group + 1; if (!group->active) port->capability |= SNDRV_SEQ_PORT_CAP_INACTIVE; + if (group->is_midi1) + port->flags |= SNDRV_SEQ_PORT_FLG_IS_MIDI1; port->type = SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC | SNDRV_SEQ_PORT_TYPE_MIDI_UMP | SNDRV_SEQ_PORT_TYPE_HARDWARE | @@ -223,7 +225,7 @@ static int seq_ump_group_init(struct seq_ump_client *client, int group_index) return -ENOMEM; fill_port_info(port, client, group); - port->flags = SNDRV_SEQ_PORT_FLG_GIVEN_PORT; + port->flags |= SNDRV_SEQ_PORT_FLG_GIVEN_PORT; memset(&pcallbacks, 0, sizeof(pcallbacks)); pcallbacks.owner = THIS_MODULE; pcallbacks.private_data = client; diff --git a/sound/core/seq/seq_ump_convert.c b/sound/core/seq/seq_ump_convert.c index d9dacfbe4a9ae7..ff7e558b4d51d0 100644 --- a/sound/core/seq/seq_ump_convert.c +++ b/sound/core/seq/seq_ump_convert.c @@ -368,7 +368,7 @@ static int cvt_ump_midi1_to_midi2(struct snd_seq_client *dest, struct snd_seq_ump_event ev_cvt; const union snd_ump_midi1_msg *midi1 = (const union snd_ump_midi1_msg *)event->ump; union snd_ump_midi2_msg *midi2 = (union snd_ump_midi2_msg *)ev_cvt.ump; - struct snd_seq_ump_midi2_bank *cc; + struct ump_cvt_to_ump_bank *cc; ev_cvt = *event; memset(&ev_cvt.ump, 0, sizeof(ev_cvt.ump)); @@ -595,12 +595,13 @@ int snd_seq_deliver_from_ump(struct snd_seq_client *source, type = ump_message_type(ump_ev->ump[0]); if (snd_seq_client_is_ump(dest)) { - if (snd_seq_client_is_midi2(dest) && - type == UMP_MSG_TYPE_MIDI1_CHANNEL_VOICE) + bool is_midi2 = snd_seq_client_is_midi2(dest) && + !dest_port->is_midi1; + + if (is_midi2 && type == UMP_MSG_TYPE_MIDI1_CHANNEL_VOICE) return cvt_ump_midi1_to_midi2(dest, dest_port, event, atomic, hop); - else if (!snd_seq_client_is_midi2(dest) && - type == UMP_MSG_TYPE_MIDI2_CHANNEL_VOICE) + else if (!is_midi2 && type == UMP_MSG_TYPE_MIDI2_CHANNEL_VOICE) return cvt_ump_midi2_to_midi1(dest, dest_port, event, atomic, hop); /* non-EP port and different group is set? */ @@ -789,28 +790,45 @@ static int paf_ev_to_ump_midi2(const struct snd_seq_event *event, return 1; } +static void reset_rpn(struct ump_cvt_to_ump_bank *cc) +{ + cc->rpn_set = 0; + cc->nrpn_set = 0; + cc->cc_rpn_msb = cc->cc_rpn_lsb = 0; + cc->cc_data_msb = cc->cc_data_lsb = 0; + cc->cc_data_msb_set = cc->cc_data_lsb_set = 0; +} + /* set up the MIDI2 RPN/NRPN packet data from the parsed info */ -static void fill_rpn(struct snd_seq_ump_midi2_bank *cc, - union snd_ump_midi2_msg *data, - unsigned char channel) +static int fill_rpn(struct ump_cvt_to_ump_bank *cc, + union snd_ump_midi2_msg *data, + unsigned char channel, + bool flush) { + if (!(cc->cc_data_lsb_set || cc->cc_data_msb_set)) + return 0; // skip + /* when not flushing, wait for complete data set */ + if (!flush && (!cc->cc_data_lsb_set || !cc->cc_data_msb_set)) + return 0; // skip + if (cc->rpn_set) { data->rpn.status = UMP_MSG_STATUS_RPN; data->rpn.bank = cc->cc_rpn_msb; data->rpn.index = cc->cc_rpn_lsb; - cc->rpn_set = 0; - cc->cc_rpn_msb = cc->cc_rpn_lsb = 0; - } else { + } else if (cc->nrpn_set) { data->rpn.status = UMP_MSG_STATUS_NRPN; data->rpn.bank = cc->cc_nrpn_msb; data->rpn.index = cc->cc_nrpn_lsb; - cc->nrpn_set = 0; - cc->cc_nrpn_msb = cc->cc_nrpn_lsb = 0; + } else { + return 0; // skip } + data->rpn.data = upscale_14_to_32bit((cc->cc_data_msb << 7) | cc->cc_data_lsb); data->rpn.channel = channel; - cc->cc_data_msb = cc->cc_data_lsb = 0; + + reset_rpn(cc); + return 1; } /* convert CC event to MIDI 2.0 UMP */ @@ -822,29 +840,39 @@ static int cc_ev_to_ump_midi2(const struct snd_seq_event *event, unsigned char channel = event->data.control.channel & 0x0f; unsigned char index = event->data.control.param & 0x7f; unsigned char val = event->data.control.value & 0x7f; - struct snd_seq_ump_midi2_bank *cc = &dest_port->midi2_bank[channel]; + struct ump_cvt_to_ump_bank *cc = &dest_port->midi2_bank[channel]; + int ret; /* process special CC's (bank/rpn/nrpn) */ switch (index) { case UMP_CC_RPN_MSB: + ret = fill_rpn(cc, data, channel, true); cc->rpn_set = 1; cc->cc_rpn_msb = val; - return 0; // skip + if (cc->cc_rpn_msb == 0x7f && cc->cc_rpn_lsb == 0x7f) + reset_rpn(cc); + return ret; case UMP_CC_RPN_LSB: + ret = fill_rpn(cc, data, channel, true); cc->rpn_set = 1; cc->cc_rpn_lsb = val; - return 0; // skip + if (cc->cc_rpn_msb == 0x7f && cc->cc_rpn_lsb == 0x7f) + reset_rpn(cc); + return ret; case UMP_CC_NRPN_MSB: + ret = fill_rpn(cc, data, channel, true); cc->nrpn_set = 1; cc->cc_nrpn_msb = val; - return 0; // skip + return ret; case UMP_CC_NRPN_LSB: + ret = fill_rpn(cc, data, channel, true); cc->nrpn_set = 1; cc->cc_nrpn_lsb = val; - return 0; // skip + return ret; case UMP_CC_DATA: + cc->cc_data_msb_set = 1; cc->cc_data_msb = val; - return 0; // skip + return fill_rpn(cc, data, channel, false); case UMP_CC_BANK_SELECT: cc->bank_set = 1; cc->cc_bank_msb = val; @@ -854,11 +882,9 @@ static int cc_ev_to_ump_midi2(const struct snd_seq_event *event, cc->cc_bank_lsb = val; return 0; // skip case UMP_CC_DATA_LSB: + cc->cc_data_lsb_set = 1; cc->cc_data_lsb = val; - if (!(cc->rpn_set || cc->nrpn_set)) - return 0; // skip - fill_rpn(cc, data, channel); - return 1; + return fill_rpn(cc, data, channel, false); } data->cc.status = status; @@ -887,7 +913,7 @@ static int pgm_ev_to_ump_midi2(const struct snd_seq_event *event, unsigned char status) { unsigned char channel = event->data.control.channel & 0x0f; - struct snd_seq_ump_midi2_bank *cc = &dest_port->midi2_bank[channel]; + struct ump_cvt_to_ump_bank *cc = &dest_port->midi2_bank[channel]; data->pg.status = status; data->pg.channel = channel; @@ -924,8 +950,9 @@ static int ctrl14_ev_to_ump_midi2(const struct snd_seq_event *event, { unsigned char channel = event->data.control.channel & 0x0f; unsigned char index = event->data.control.param & 0x7f; - struct snd_seq_ump_midi2_bank *cc = &dest_port->midi2_bank[channel]; + struct ump_cvt_to_ump_bank *cc = &dest_port->midi2_bank[channel]; unsigned char msb, lsb; + int ret; msb = (event->data.control.value >> 7) & 0x7f; lsb = event->data.control.value & 0x7f; @@ -939,28 +966,27 @@ static int ctrl14_ev_to_ump_midi2(const struct snd_seq_event *event, cc->cc_bank_lsb = lsb; return 0; // skip case UMP_CC_RPN_MSB: - cc->cc_rpn_msb = msb; - fallthrough; case UMP_CC_RPN_LSB: - cc->rpn_set = 1; + ret = fill_rpn(cc, data, channel, true); + cc->cc_rpn_msb = msb; cc->cc_rpn_lsb = lsb; - return 0; // skip + cc->rpn_set = 1; + if (cc->cc_rpn_msb == 0x7f && cc->cc_rpn_lsb == 0x7f) + reset_rpn(cc); + return ret; case UMP_CC_NRPN_MSB: - cc->cc_nrpn_msb = msb; - fallthrough; case UMP_CC_NRPN_LSB: + ret = fill_rpn(cc, data, channel, true); + cc->cc_nrpn_msb = msb; cc->nrpn_set = 1; cc->cc_nrpn_lsb = lsb; - return 0; // skip + return ret; case UMP_CC_DATA: - cc->cc_data_msb = msb; - fallthrough; case UMP_CC_DATA_LSB: + cc->cc_data_msb_set = cc->cc_data_lsb_set = 1; + cc->cc_data_msb = msb; cc->cc_data_lsb = lsb; - if (!(cc->rpn_set || cc->nrpn_set)) - return 0; // skip - fill_rpn(cc, data, channel); - return 1; + return fill_rpn(cc, data, channel, false); } data->cc.status = UMP_MSG_STATUS_CC; @@ -1254,7 +1280,7 @@ int snd_seq_deliver_to_ump(struct snd_seq_client *source, return 0; /* group filtered - skip the event */ if (event->type == SNDRV_SEQ_EVENT_SYSEX) return cvt_sysex_to_ump(dest, dest_port, event, atomic, hop); - else if (snd_seq_client_is_midi2(dest)) + else if (snd_seq_client_is_midi2(dest) && !dest_port->is_midi1) return cvt_to_ump_midi2(dest, dest_port, event, atomic, hop); else return cvt_to_ump_midi1(dest, dest_port, event, atomic, hop); diff --git a/sound/core/timer.c b/sound/core/timer.c index d104adc75a8b0e..7610f102360dff 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c @@ -13,6 +13,8 @@ #include #include #include +#include +#include #include #include #include @@ -109,6 +111,16 @@ struct snd_timer_status64 { unsigned char reserved[64]; /* reserved */ }; +#ifdef CONFIG_SND_UTIMER +#define SNDRV_UTIMERS_MAX_COUNT 128 +/* Internal data structure for keeping the state of the userspace-driven timer */ +struct snd_utimer { + char *name; + struct snd_timer *timer; + unsigned int id; +}; +#endif + #define SNDRV_TIMER_IOCTL_STATUS64 _IOR('T', 0x14, struct snd_timer_status64) /* list of timers */ @@ -547,7 +559,7 @@ static int snd_timer_start1(struct snd_timer_instance *timeri, /* check the actual time for the start tick; * bail out as error if it's way too low (< 100us) */ - if (start) { + if (start && !(timer->hw.flags & SNDRV_TIMER_HW_SLAVE)) { if ((u64)snd_timer_hw_resolution(timer) * ticks < 100000) return -EINVAL; } @@ -2009,6 +2021,217 @@ enum { SNDRV_TIMER_IOCTL_PAUSE_OLD = _IO('T', 0x23), }; +#ifdef CONFIG_SND_UTIMER +/* + * Since userspace-driven timers are passed to userspace, we need to have an identifier + * which will allow us to use them (basically, the subdevice number of udriven timer). + */ +static DEFINE_IDA(snd_utimer_ids); + +static void snd_utimer_put_id(struct snd_utimer *utimer) +{ + int timer_id = utimer->id; + + snd_BUG_ON(timer_id < 0 || timer_id >= SNDRV_UTIMERS_MAX_COUNT); + ida_free(&snd_utimer_ids, timer_id); +} + +static int snd_utimer_take_id(void) +{ + return ida_alloc_max(&snd_utimer_ids, SNDRV_UTIMERS_MAX_COUNT - 1, GFP_KERNEL); +} + +static void snd_utimer_free(struct snd_utimer *utimer) +{ + snd_timer_free(utimer->timer); + snd_utimer_put_id(utimer); + kfree(utimer->name); + kfree(utimer); +} + +static int snd_utimer_release(struct inode *inode, struct file *file) +{ + struct snd_utimer *utimer = (struct snd_utimer *)file->private_data; + + snd_utimer_free(utimer); + return 0; +} + +static int snd_utimer_trigger(struct file *file) +{ + struct snd_utimer *utimer = (struct snd_utimer *)file->private_data; + + snd_timer_interrupt(utimer->timer, utimer->timer->sticks); + return 0; +} + +static long snd_utimer_ioctl(struct file *file, unsigned int ioctl, unsigned long arg) +{ + switch (ioctl) { + case SNDRV_TIMER_IOCTL_TRIGGER: + return snd_utimer_trigger(file); + } + + return -ENOTTY; +} + +static const struct file_operations snd_utimer_fops = { + .llseek = noop_llseek, + .release = snd_utimer_release, + .unlocked_ioctl = snd_utimer_ioctl, +}; + +static int snd_utimer_start(struct snd_timer *t) +{ + return 0; +} + +static int snd_utimer_stop(struct snd_timer *t) +{ + return 0; +} + +static int snd_utimer_open(struct snd_timer *t) +{ + return 0; +} + +static int snd_utimer_close(struct snd_timer *t) +{ + return 0; +} + +static const struct snd_timer_hardware timer_hw = { + .flags = SNDRV_TIMER_HW_AUTO | SNDRV_TIMER_HW_WORK, + .open = snd_utimer_open, + .close = snd_utimer_close, + .start = snd_utimer_start, + .stop = snd_utimer_stop, +}; + +static int snd_utimer_create(struct snd_timer_uinfo *utimer_info, + struct snd_utimer **r_utimer) +{ + struct snd_utimer *utimer; + struct snd_timer *timer; + struct snd_timer_id tid; + int utimer_id; + int err = 0; + + if (!utimer_info || utimer_info->resolution == 0) + return -EINVAL; + + utimer = kzalloc(sizeof(*utimer), GFP_KERNEL); + if (!utimer) + return -ENOMEM; + + /* We hold the ioctl lock here so we won't get a race condition when allocating id */ + utimer_id = snd_utimer_take_id(); + if (utimer_id < 0) { + err = utimer_id; + goto err_take_id; + } + + utimer->name = kasprintf(GFP_KERNEL, "snd-utimer%d", utimer_id); + if (!utimer->name) { + err = -ENOMEM; + goto err_get_name; + } + + utimer->id = utimer_id; + + tid.dev_sclass = SNDRV_TIMER_SCLASS_APPLICATION; + tid.dev_class = SNDRV_TIMER_CLASS_GLOBAL; + tid.card = -1; + tid.device = SNDRV_TIMER_GLOBAL_UDRIVEN; + tid.subdevice = utimer_id; + + err = snd_timer_new(NULL, utimer->name, &tid, &timer); + if (err < 0) { + pr_err("Can't create userspace-driven timer\n"); + goto err_timer_new; + } + + timer->module = THIS_MODULE; + timer->hw = timer_hw; + timer->hw.resolution = utimer_info->resolution; + timer->hw.ticks = 1; + timer->max_instances = MAX_SLAVE_INSTANCES; + + utimer->timer = timer; + + err = snd_timer_global_register(timer); + if (err < 0) { + pr_err("Can't register a userspace-driven timer\n"); + goto err_timer_reg; + } + + *r_utimer = utimer; + return 0; + +err_timer_reg: + snd_timer_free(timer); +err_timer_new: + kfree(utimer->name); +err_get_name: + snd_utimer_put_id(utimer); +err_take_id: + kfree(utimer); + + return err; +} + +static int snd_utimer_ioctl_create(struct file *file, + struct snd_timer_uinfo __user *_utimer_info) +{ + struct snd_utimer *utimer; + struct snd_timer_uinfo *utimer_info __free(kfree) = NULL; + int err, timer_fd; + + utimer_info = memdup_user(_utimer_info, sizeof(*utimer_info)); + if (IS_ERR(utimer_info)) + return PTR_ERR(no_free_ptr(utimer_info)); + + err = snd_utimer_create(utimer_info, &utimer); + if (err < 0) + return err; + + utimer_info->id = utimer->id; + + timer_fd = anon_inode_getfd(utimer->name, &snd_utimer_fops, utimer, O_RDWR | O_CLOEXEC); + if (timer_fd < 0) { + snd_utimer_free(utimer); + return timer_fd; + } + + utimer_info->fd = timer_fd; + + err = copy_to_user(_utimer_info, utimer_info, sizeof(*utimer_info)); + if (err) { + /* + * "Leak" the fd, as there is nothing we can do about it. + * It might have been closed already since anon_inode_getfd + * makes it available for userspace. + * + * We have to rely on the process exit path to do any + * necessary cleanup (e.g. releasing the file). + */ + return -EFAULT; + } + + return 0; +} + +#else + +static int snd_utimer_ioctl_create(struct file *file, + struct snd_timer_uinfo __user *_utimer_info) +{ + return -ENOTTY; +} + +#endif + static long __snd_timer_user_ioctl(struct file *file, unsigned int cmd, unsigned long arg, bool compat) { @@ -2053,6 +2276,8 @@ static long __snd_timer_user_ioctl(struct file *file, unsigned int cmd, case SNDRV_TIMER_IOCTL_PAUSE: case SNDRV_TIMER_IOCTL_PAUSE_OLD: return snd_timer_user_pause(file); + case SNDRV_TIMER_IOCTL_CREATE: + return snd_utimer_ioctl_create(file, argp); } return -ENOTTY; } diff --git a/sound/core/ump.c b/sound/core/ump.c index e39e9cda4912fc..243ecdbb2a6e5f 100644 --- a/sound/core/ump.c +++ b/sound/core/ump.c @@ -525,7 +525,7 @@ static void snd_ump_proc_read(struct snd_info_entry *entry, } /* update dir_bits and active flag for all groups in the client */ -static void update_group_attrs(struct snd_ump_endpoint *ump) +void snd_ump_update_group_attrs(struct snd_ump_endpoint *ump) { struct snd_ump_block *fb; struct snd_ump_group *group; @@ -538,6 +538,7 @@ static void update_group_attrs(struct snd_ump_endpoint *ump) group->active = 0; group->group = i; group->valid = false; + group->is_midi1 = false; } list_for_each_entry(fb, &ump->block_list, list) { @@ -548,6 +549,8 @@ static void update_group_attrs(struct snd_ump_endpoint *ump) group->valid = true; if (fb->info.active) group->active = 1; + if (fb->info.flags & SNDRV_UMP_BLOCK_IS_MIDI1) + group->is_midi1 = true; switch (fb->info.direction) { case SNDRV_UMP_DIR_INPUT: group->dir_bits |= (1 << SNDRV_RAWMIDI_STREAM_INPUT); @@ -575,6 +578,7 @@ static void update_group_attrs(struct snd_ump_endpoint *ump) } } } +EXPORT_SYMBOL_GPL(snd_ump_update_group_attrs); /* * UMP endpoint and function block handling @@ -654,6 +658,17 @@ static int ump_append_string(struct snd_ump_endpoint *ump, char *dest, format == UMP_STREAM_MSG_FORMAT_END); } +/* Choose the default protocol */ +static void choose_default_protocol(struct snd_ump_endpoint *ump) +{ + if (ump->info.protocol & SNDRV_UMP_EP_INFO_PROTO_MIDI_MASK) + return; + if (ump->info.protocol_caps & SNDRV_UMP_EP_INFO_PROTO_MIDI2) + ump->info.protocol |= SNDRV_UMP_EP_INFO_PROTO_MIDI2; + else + ump->info.protocol |= SNDRV_UMP_EP_INFO_PROTO_MIDI1; +} + /* handle EP info stream message; update the UMP attributes */ static int ump_handle_ep_info_msg(struct snd_ump_endpoint *ump, const union snd_ump_stream_msg *buf) @@ -675,6 +690,10 @@ static int ump_handle_ep_info_msg(struct snd_ump_endpoint *ump, ump_dbg(ump, "EP info: version=%x, num_blocks=%x, proto_caps=%x\n", ump->info.version, ump->info.num_blocks, ump->info.protocol_caps); + + ump->info.protocol &= ump->info.protocol_caps; + choose_default_protocol(ump); + return 1; /* finished */ } @@ -845,7 +864,7 @@ static int ump_handle_fb_info_msg(struct snd_ump_endpoint *ump, if (fb) { fill_fb_info(ump, &fb->info, buf); if (ump->parsed) { - update_group_attrs(ump); + snd_ump_update_group_attrs(ump); seq_notify_fb_change(ump, fb); } } @@ -877,7 +896,7 @@ static int ump_handle_fb_name_msg(struct snd_ump_endpoint *ump, buf->raw, 3); /* notify the FB name update to sequencer, too */ if (ret > 0 && ump->parsed) { - update_group_attrs(ump); + snd_ump_update_group_attrs(ump); seq_notify_fb_change(ump, fb); } return ret; @@ -1037,12 +1056,7 @@ int snd_ump_parse_endpoint(struct snd_ump_endpoint *ump) ump_dbg(ump, "Unable to get UMP EP stream config\n"); /* If no protocol is set by some reason, assume the valid one */ - if (!(ump->info.protocol & SNDRV_UMP_EP_INFO_PROTO_MIDI_MASK)) { - if (ump->info.protocol_caps & SNDRV_UMP_EP_INFO_PROTO_MIDI2) - ump->info.protocol |= SNDRV_UMP_EP_INFO_PROTO_MIDI2; - else if (ump->info.protocol_caps & SNDRV_UMP_EP_INFO_PROTO_MIDI1) - ump->info.protocol |= SNDRV_UMP_EP_INFO_PROTO_MIDI1; - } + choose_default_protocol(ump); /* Query and create blocks from Function Blocks */ for (blk = 0; blk < ump->info.num_blocks; blk++) { @@ -1052,7 +1066,7 @@ int snd_ump_parse_endpoint(struct snd_ump_endpoint *ump) } /* initialize group attributions */ - update_group_attrs(ump); + snd_ump_update_group_attrs(ump); error: ump->parsed = true; @@ -1156,6 +1170,7 @@ static int process_legacy_output(struct snd_ump_endpoint *ump, struct snd_rawmidi_substream *substream; struct ump_cvt_to_ump *ctx; const int dir = SNDRV_RAWMIDI_STREAM_OUTPUT; + unsigned int protocol; unsigned char c; int group, size = 0; @@ -1168,9 +1183,13 @@ static int process_legacy_output(struct snd_ump_endpoint *ump, if (!substream) continue; ctx = &ump->out_cvts[group]; + protocol = ump->info.protocol; + if ((protocol & SNDRV_UMP_EP_INFO_PROTO_MIDI2) && + ump->groups[group].is_midi1) + protocol = SNDRV_UMP_EP_INFO_PROTO_MIDI1; while (!ctx->ump_bytes && snd_rawmidi_transmit(substream, &c, 1) > 0) - snd_ump_convert_to_ump(ctx, group, ump->info.protocol, c); + snd_ump_convert_to_ump(ctx, group, protocol, c); if (ctx->ump_bytes && ctx->ump_bytes <= count) { size = ctx->ump_bytes; memcpy(buffer, ctx->ump, size); diff --git a/sound/core/ump_convert.c b/sound/core/ump_convert.c index f67c44c83fde44..0fe13d03165686 100644 --- a/sound/core/ump_convert.c +++ b/sound/core/ump_convert.c @@ -287,25 +287,42 @@ static int cvt_legacy_system_to_ump(struct ump_cvt_to_ump *cvt, return 4; } -static void fill_rpn(struct ump_cvt_to_ump_bank *cc, - union snd_ump_midi2_msg *midi2) +static void reset_rpn(struct ump_cvt_to_ump_bank *cc) { + cc->rpn_set = 0; + cc->nrpn_set = 0; + cc->cc_rpn_msb = cc->cc_rpn_lsb = 0; + cc->cc_data_msb = cc->cc_data_lsb = 0; + cc->cc_data_msb_set = cc->cc_data_lsb_set = 0; +} + +static int fill_rpn(struct ump_cvt_to_ump_bank *cc, + union snd_ump_midi2_msg *midi2, + bool flush) +{ + if (!(cc->cc_data_lsb_set || cc->cc_data_msb_set)) + return 0; // skip + /* when not flushing, wait for complete data set */ + if (!flush && (!cc->cc_data_lsb_set || !cc->cc_data_msb_set)) + return 0; // skip + if (cc->rpn_set) { midi2->rpn.status = UMP_MSG_STATUS_RPN; midi2->rpn.bank = cc->cc_rpn_msb; midi2->rpn.index = cc->cc_rpn_lsb; - cc->rpn_set = 0; - cc->cc_rpn_msb = cc->cc_rpn_lsb = 0; - } else { + } else if (cc->nrpn_set) { midi2->rpn.status = UMP_MSG_STATUS_NRPN; midi2->rpn.bank = cc->cc_nrpn_msb; midi2->rpn.index = cc->cc_nrpn_lsb; - cc->nrpn_set = 0; - cc->cc_nrpn_msb = cc->cc_nrpn_lsb = 0; + } else { + return 0; // skip } + midi2->rpn.data = upscale_14_to_32bit((cc->cc_data_msb << 7) | cc->cc_data_lsb); - cc->cc_data_msb = cc->cc_data_lsb = 0; + + reset_rpn(cc); + return 1; } /* convert to a MIDI 1.0 Channel Voice message */ @@ -318,6 +335,7 @@ static int cvt_legacy_cmd_to_ump(struct ump_cvt_to_ump *cvt, struct ump_cvt_to_ump_bank *cc; union snd_ump_midi2_msg *midi2 = (union snd_ump_midi2_msg *)data; unsigned char status, channel; + int ret; BUILD_BUG_ON(sizeof(union snd_ump_midi1_msg) != 4); BUILD_BUG_ON(sizeof(union snd_ump_midi2_msg) != 8); @@ -358,24 +376,33 @@ static int cvt_legacy_cmd_to_ump(struct ump_cvt_to_ump *cvt, case UMP_MSG_STATUS_CC: switch (buf[1]) { case UMP_CC_RPN_MSB: + ret = fill_rpn(cc, midi2, true); cc->rpn_set = 1; cc->cc_rpn_msb = buf[2]; - return 0; // skip + if (cc->cc_rpn_msb == 0x7f && cc->cc_rpn_lsb == 0x7f) + reset_rpn(cc); + return ret; case UMP_CC_RPN_LSB: + ret = fill_rpn(cc, midi2, true); cc->rpn_set = 1; cc->cc_rpn_lsb = buf[2]; - return 0; // skip + if (cc->cc_rpn_msb == 0x7f && cc->cc_rpn_lsb == 0x7f) + reset_rpn(cc); + return ret; case UMP_CC_NRPN_MSB: + ret = fill_rpn(cc, midi2, true); cc->nrpn_set = 1; cc->cc_nrpn_msb = buf[2]; - return 0; // skip + return ret; case UMP_CC_NRPN_LSB: + ret = fill_rpn(cc, midi2, true); cc->nrpn_set = 1; cc->cc_nrpn_lsb = buf[2]; - return 0; // skip + return ret; case UMP_CC_DATA: + cc->cc_data_msb_set = 1; cc->cc_data_msb = buf[2]; - return 0; // skip + return fill_rpn(cc, midi2, false); case UMP_CC_BANK_SELECT: cc->bank_set = 1; cc->cc_bank_msb = buf[2]; @@ -385,12 +412,9 @@ static int cvt_legacy_cmd_to_ump(struct ump_cvt_to_ump *cvt, cc->cc_bank_lsb = buf[2]; return 0; // skip case UMP_CC_DATA_LSB: + cc->cc_data_lsb_set = 1; cc->cc_data_lsb = buf[2]; - if (cc->rpn_set || cc->nrpn_set) - fill_rpn(cc, midi2); - else - return 0; // skip - break; + return fill_rpn(cc, midi2, false); default: midi2->cc.index = buf[1]; midi2->cc.data = upscale_7_to_32bit(buf[2]); diff --git a/sound/drivers/aloop.c b/sound/drivers/aloop.c index 439d12ad878790..eb8a68a06c4d9c 100644 --- a/sound/drivers/aloop.c +++ b/sound/drivers/aloop.c @@ -1129,6 +1129,8 @@ static int loopback_parse_timer_id(const char *str, } } } + if (card_idx == -1) + tid->dev_class = SNDRV_TIMER_CLASS_GLOBAL; if (!err && tid) { tid->card = card_idx; tid->device = dev; @@ -1896,7 +1898,7 @@ static int __init alsa_card_loopback_init(void) } if (!cards) { #ifdef MODULE - printk(KERN_ERR "aloop: No loopback enabled\n"); + pr_err("aloop: No loopback enabled\n"); #endif loopback_unregister_all(); return -ENODEV; diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c index 52ff6ac3f74356..8f5df9b3aaaaa5 100644 --- a/sound/drivers/dummy.c +++ b/sound/drivers/dummy.c @@ -1033,8 +1033,7 @@ static int snd_dummy_probe(struct platform_device *devptr) dummy->card = card; for (mdl = dummy_models; *mdl && model[dev]; mdl++) { if (strcmp(model[dev], (*mdl)->name) == 0) { - printk(KERN_INFO - "snd-dummy: Using model '%s' for card %i\n", + pr_info("snd-dummy: Using model '%s' for card %i\n", (*mdl)->name, card->number); m = dummy->model = *mdl; break; @@ -1168,7 +1167,7 @@ static int __init alsa_card_dummy_init(void) } if (!cards) { #ifdef MODULE - printk(KERN_ERR "Dummy soundcard not found or device busy\n"); + pr_err("Dummy soundcard not found or device busy\n"); #endif snd_dummy_unregister_all(); return -ENODEV; diff --git a/sound/drivers/mpu401/mpu401.c b/sound/drivers/mpu401/mpu401.c index 3398aee33baad0..cd01af5fa4edfc 100644 --- a/sound/drivers/mpu401/mpu401.c +++ b/sound/drivers/mpu401/mpu401.c @@ -56,7 +56,7 @@ static int snd_mpu401_create(struct device *devptr, int dev, int err; if (!uart_enter[dev]) - snd_printk(KERN_ERR "the uart_enter option is obsolete; remove it\n"); + dev_err(devptr, "the uart_enter option is obsolete; remove it\n"); *rcard = NULL; err = snd_devm_card_new(devptr, index[dev], id[dev], THIS_MODULE, @@ -75,7 +75,7 @@ static int snd_mpu401_create(struct device *devptr, int dev, err = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, port[dev], 0, irq[dev], NULL); if (err < 0) { - printk(KERN_ERR "MPU401 not detected at 0x%lx\n", port[dev]); + dev_err(devptr, "MPU401 not detected at 0x%lx\n", port[dev]); return err; } @@ -90,11 +90,11 @@ static int snd_mpu401_probe(struct platform_device *devptr) struct snd_card *card; if (port[dev] == SNDRV_AUTO_PORT) { - snd_printk(KERN_ERR "specify port\n"); + dev_err(&devptr->dev, "specify port\n"); return -EINVAL; } if (irq[dev] == SNDRV_AUTO_IRQ) { - snd_printk(KERN_ERR "specify or disable IRQ\n"); + dev_err(&devptr->dev, "specify or disable IRQ\n"); return -EINVAL; } err = snd_mpu401_create(&devptr->dev, dev, &card); @@ -133,11 +133,11 @@ static int snd_mpu401_pnp(int dev, struct pnp_dev *device, { if (!pnp_port_valid(device, 0) || pnp_port_flags(device, 0) & IORESOURCE_DISABLED) { - snd_printk(KERN_ERR "no PnP port\n"); + dev_err(&device->dev, "no PnP port\n"); return -ENODEV; } if (pnp_port_len(device, 0) < IO_EXTENT) { - snd_printk(KERN_ERR "PnP port length is %llu, expected %d\n", + dev_err(&device->dev, "PnP port length is %llu, expected %d\n", (unsigned long long)pnp_port_len(device, 0), IO_EXTENT); return -ENODEV; @@ -146,7 +146,7 @@ static int snd_mpu401_pnp(int dev, struct pnp_dev *device, if (!pnp_irq_valid(device, 0) || pnp_irq_flags(device, 0) & IORESOURCE_DISABLED) { - snd_printk(KERN_WARNING "no PnP irq, using polling\n"); + dev_warn(&device->dev, "no PnP irq, using polling\n"); irq[dev] = -1; } else { irq[dev] = pnp_irq(device, 0); @@ -234,7 +234,7 @@ static int __init alsa_card_mpu401_init(void) if (!snd_mpu401_devices) { #ifdef MODULE - printk(KERN_ERR "MPU-401 device not found or device busy\n"); + pr_err("MPU-401 device not found or device busy\n"); #endif snd_mpu401_unregister_all(); return -ENODEV; diff --git a/sound/drivers/mpu401/mpu401_uart.c b/sound/drivers/mpu401/mpu401_uart.c index f435b9b4ae2414..8e3318e1771793 100644 --- a/sound/drivers/mpu401/mpu401_uart.c +++ b/sound/drivers/mpu401/mpu401_uart.c @@ -73,8 +73,9 @@ static void snd_mpu401_uart_clear_rx(struct snd_mpu401 *mpu) mpu->read(mpu, MPU401D(mpu)); #ifdef CONFIG_SND_DEBUG if (timeout <= 0) - snd_printk(KERN_ERR "cmd: clear rx timeout (status = 0x%x)\n", - mpu->read(mpu, MPU401C(mpu))); + dev_err(mpu->rmidi->dev, + "cmd: clear rx timeout (status = 0x%x)\n", + mpu->read(mpu, MPU401C(mpu))); #endif } @@ -224,8 +225,9 @@ static int snd_mpu401_uart_cmd(struct snd_mpu401 * mpu, unsigned char cmd, udelay(10); #ifdef CONFIG_SND_DEBUG if (!timeout) - snd_printk(KERN_ERR "cmd: tx timeout (status = 0x%x)\n", - mpu->read(mpu, MPU401C(mpu))); + dev_err(mpu->rmidi->dev, + "cmd: tx timeout (status = 0x%x)\n", + mpu->read(mpu, MPU401C(mpu))); #endif } mpu->write(mpu, cmd, MPU401C(mpu)); @@ -244,10 +246,11 @@ static int snd_mpu401_uart_cmd(struct snd_mpu401 * mpu, unsigned char cmd, ok = 1; spin_unlock_irqrestore(&mpu->input_lock, flags); if (!ok) { - snd_printk(KERN_ERR "cmd: 0x%x failed at 0x%lx " - "(status = 0x%x, data = 0x%x)\n", cmd, mpu->port, - mpu->read(mpu, MPU401C(mpu)), - mpu->read(mpu, MPU401D(mpu))); + dev_err(mpu->rmidi->dev, + "cmd: 0x%x failed at 0x%lx (status = 0x%x, data = 0x%x)\n", + cmd, mpu->port, + mpu->read(mpu, MPU401C(mpu)), + mpu->read(mpu, MPU401D(mpu))); return 1; } return 0; @@ -546,13 +549,14 @@ int snd_mpu401_uart_new(struct snd_card *card, int device, spin_lock_init(&mpu->timer_lock); mpu->hardware = hardware; mpu->irq = -1; + mpu->rmidi = rmidi; if (! (info_flags & MPU401_INFO_INTEGRATED)) { int res_size = hardware == MPU401_HW_PC98II ? 4 : 2; mpu->res = request_region(port, res_size, "MPU401 UART"); if (!mpu->res) { - snd_printk(KERN_ERR "mpu401_uart: " - "unable to grab port 0x%lx size %d\n", - port, res_size); + dev_err(rmidi->dev, + "mpu401_uart: unable to grab port 0x%lx size %d\n", + port, res_size); err = -EBUSY; goto free_device; } @@ -572,8 +576,8 @@ int snd_mpu401_uart_new(struct snd_card *card, int device, if (irq >= 0) { if (request_irq(irq, snd_mpu401_uart_interrupt, 0, "MPU401 UART", (void *) mpu)) { - snd_printk(KERN_ERR "mpu401_uart: " - "unable to grab IRQ %d\n", irq); + dev_err(rmidi->dev, + "mpu401_uart: unable to grab IRQ %d\n", irq); err = -EBUSY; goto free_device; } @@ -599,7 +603,6 @@ int snd_mpu401_uart_new(struct snd_card *card, int device, if (out_enable) rmidi->info_flags |= SNDRV_RAWMIDI_INFO_DUPLEX; } - mpu->rmidi = rmidi; if (rrawmidi) *rrawmidi = rmidi; return 0; diff --git a/sound/drivers/mtpav.c b/sound/drivers/mtpav.c index f212f233ea618e..946184a2a75891 100644 --- a/sound/drivers/mtpav.c +++ b/sound/drivers/mtpav.c @@ -285,10 +285,6 @@ static void snd_mtpav_output_port_write(struct mtpav *mtp_card, snd_mtpav_send_byte(mtp_card, 0xf5); snd_mtpav_send_byte(mtp_card, portp->hwport); - /* - snd_printk(KERN_DEBUG "new outport: 0x%x\n", - (unsigned int) portp->hwport); - */ if (!(outbyte & 0x80) && portp->running_status) snd_mtpav_send_byte(mtp_card, portp->running_status); } @@ -522,8 +518,6 @@ static void snd_mtpav_read_bytes(struct mtpav *mcrd) u8 sbyt = snd_mtpav_getreg(mcrd, SREG); - /* printk(KERN_DEBUG "snd_mtpav_read_bytes() sbyt: 0x%x\n", sbyt); */ - if (!(sbyt & SIGS_BYTE)) return; @@ -569,13 +563,13 @@ static int snd_mtpav_get_ISA(struct mtpav *mcard) mcard->res_port = devm_request_region(mcard->card->dev, port, 3, "MotuMTPAV MIDI"); if (!mcard->res_port) { - snd_printk(KERN_ERR "MTVAP port 0x%lx is busy\n", port); + dev_err(mcard->card->dev, "MTVAP port 0x%lx is busy\n", port); return -EBUSY; } mcard->port = port; if (devm_request_irq(mcard->card->dev, irq, snd_mtpav_irqh, 0, "MOTU MTPAV", mcard)) { - snd_printk(KERN_ERR "MTVAP IRQ %d busy\n", irq); + dev_err(mcard->card->dev, "MTVAP IRQ %d busy\n", irq); return -EBUSY; } mcard->irq = irq; @@ -717,7 +711,9 @@ static int snd_mtpav_probe(struct platform_device *dev) card->private_free = snd_mtpav_free; platform_set_drvdata(dev, card); - printk(KERN_INFO "Motu MidiTimePiece on parallel port irq: %d ioport: 0x%lx\n", irq, port); + dev_info(card->dev, + "Motu MidiTimePiece on parallel port irq: %d ioport: 0x%lx\n", + irq, port); return 0; } diff --git a/sound/drivers/mts64.c b/sound/drivers/mts64.c index b1b333d1cf396f..6fc255a6754d1f 100644 --- a/sound/drivers/mts64.c +++ b/sound/drivers/mts64.c @@ -652,8 +652,8 @@ static int snd_mts64_ctl_create(struct snd_card *card, for (i = 0; control[i]; ++i) { err = snd_ctl_add(card, snd_ctl_new1(control[i], mts)); if (err < 0) { - snd_printd("Cannot create control: %s\n", - control[i]->name); + dev_dbg(card->dev, "Cannot create control: %s\n", + control[i]->name); return err; } } @@ -926,7 +926,7 @@ static int snd_mts64_probe(struct platform_device *pdev) err = snd_card_new(&pdev->dev, index[dev], id[dev], THIS_MODULE, 0, &card); if (err < 0) { - snd_printd("Cannot create card\n"); + dev_dbg(&pdev->dev, "Cannot create card\n"); return err; } strcpy(card->driver, DRIVER_NAME); @@ -940,21 +940,21 @@ static int snd_mts64_probe(struct platform_device *pdev) &mts64_cb, /* callbacks */ pdev->id); /* device number */ if (!pardev) { - snd_printd("Cannot register pardevice\n"); + dev_dbg(card->dev, "Cannot register pardevice\n"); err = -EIO; goto __err; } /* claim parport */ if (parport_claim(pardev)) { - snd_printd("Cannot claim parport 0x%lx\n", pardev->port->base); + dev_dbg(card->dev, "Cannot claim parport 0x%lx\n", pardev->port->base); err = -EIO; goto free_pardev; } err = snd_mts64_create(card, pardev, &mts); if (err < 0) { - snd_printd("Cannot create main component\n"); + dev_dbg(card->dev, "Cannot create main component\n"); goto release_pardev; } card->private_data = mts; @@ -968,7 +968,7 @@ static int snd_mts64_probe(struct platform_device *pdev) err = snd_mts64_rawmidi_create(card); if (err < 0) { - snd_printd("Creating Rawmidi component failed\n"); + dev_dbg(card->dev, "Creating Rawmidi component failed\n"); goto __err; } @@ -982,11 +982,11 @@ static int snd_mts64_probe(struct platform_device *pdev) /* At this point card will be usable */ err = snd_card_register(card); if (err < 0) { - snd_printd("Cannot register card\n"); + dev_dbg(card->dev, "Cannot register card\n"); goto __err; } - snd_printk(KERN_INFO "ESI Miditerminal 4140 on 0x%lx\n", p->base); + dev_info(card->dev, "ESI Miditerminal 4140 on 0x%lx\n", p->base); return 0; release_pardev: diff --git a/sound/drivers/opl3/opl3_lib.c b/sound/drivers/opl3/opl3_lib.c index 6c1f1cc092d86f..4e57e3b2f11898 100644 --- a/sound/drivers/opl3/opl3_lib.c +++ b/sound/drivers/opl3/opl3_lib.c @@ -92,7 +92,7 @@ static int snd_opl3_detect(struct snd_opl3 * opl3) opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER_CONTROL, OPL3_IRQ_RESET); signature = stat1 = inb(opl3->l_port); /* Status register */ if ((stat1 & 0xe0) != 0x00) { /* Should be 0x00 */ - snd_printd("OPL3: stat1 = 0x%x\n", stat1); + dev_dbg(opl3->card->dev, "OPL3: stat1 = 0x%x\n", stat1); return -ENODEV; } /* Set timer1 to 0xff */ @@ -108,7 +108,7 @@ static int snd_opl3_detect(struct snd_opl3 * opl3) /* Reset the IRQ of the FM chip */ opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER_CONTROL, OPL3_IRQ_RESET); if ((stat2 & 0xe0) != 0xc0) { /* There is no YM3812 */ - snd_printd("OPL3: stat2 = 0x%x\n", stat2); + dev_dbg(opl3->card->dev, "OPL3: stat2 = 0x%x\n", stat2); return -ENODEV; } @@ -289,9 +289,6 @@ void snd_opl3_interrupt(struct snd_hwdep * hw) opl3 = hw->private_data; status = inb(opl3->l_port); -#if 0 - snd_printk(KERN_DEBUG "AdLib IRQ status = 0x%x\n", status); -#endif if (!(status & 0x80)) return; @@ -365,7 +362,8 @@ EXPORT_SYMBOL(snd_opl3_new); int snd_opl3_init(struct snd_opl3 *opl3) { if (! opl3->command) { - printk(KERN_ERR "snd_opl3_init: command not defined!\n"); + dev_err(opl3->card->dev, + "snd_opl3_init: command not defined!\n"); return -EINVAL; } @@ -405,14 +403,14 @@ int snd_opl3_create(struct snd_card *card, if (! integrated) { opl3->res_l_port = request_region(l_port, 2, "OPL2/3 (left)"); if (!opl3->res_l_port) { - snd_printk(KERN_ERR "opl3: can't grab left port 0x%lx\n", l_port); + dev_err(card->dev, "opl3: can't grab left port 0x%lx\n", l_port); snd_device_free(card, opl3); return -EBUSY; } if (r_port != 0) { opl3->res_r_port = request_region(r_port, 2, "OPL2/3 (right)"); if (!opl3->res_r_port) { - snd_printk(KERN_ERR "opl3: can't grab right port 0x%lx\n", r_port); + dev_err(card->dev, "opl3: can't grab right port 0x%lx\n", r_port); snd_device_free(card, opl3); return -EBUSY; } @@ -432,8 +430,8 @@ int snd_opl3_create(struct snd_card *card, opl3->command = &snd_opl2_command; err = snd_opl3_detect(opl3); if (err < 0) { - snd_printd("OPL2/3 chip not detected at 0x%lx/0x%lx\n", - opl3->l_port, opl3->r_port); + dev_dbg(card->dev, "OPL2/3 chip not detected at 0x%lx/0x%lx\n", + opl3->l_port, opl3->r_port); snd_device_free(card, opl3); return err; } diff --git a/sound/drivers/opl3/opl3_midi.c b/sound/drivers/opl3/opl3_midi.c index e2b7be67f0e303..9bee454441b07b 100644 --- a/sound/drivers/opl3/opl3_midi.c +++ b/sound/drivers/opl3/opl3_midi.c @@ -11,6 +11,13 @@ #include "opl3_voice.h" #include +#ifdef DEBUG_MIDI +#define opl3_dbg(opl3, fmt, ...) \ + dev_dbg(((struct snd_opl3 *)(opl3))->card->dev, fmt, ##__VA_ARGS__) +#else +#define opl3_dbg(opl3, fmt, ...) do {} while (0) +#endif + static void snd_opl3_note_off_unsafe(void *p, int note, int vel, struct snd_midi_channel *chan); /* @@ -107,14 +114,17 @@ static void snd_opl3_calc_pitch(unsigned char *fnum, unsigned char *blocknum, #ifdef DEBUG_ALLOC -static void debug_alloc(struct snd_opl3 *opl3, char *s, int voice) { +static void debug_alloc(struct snd_opl3 *opl3, char *s, int voice) +{ int i; - char *str = "x.24"; + const char *str = "x.24"; + char buf[MAX_OPL3_VOICES + 1]; - printk(KERN_DEBUG "time %.5i: %s [%.2i]: ", opl3->use_time, s, voice); for (i = 0; i < opl3->max_voices; i++) - printk(KERN_CONT "%c", *(str + opl3->voices[i].state + 1)); - printk(KERN_CONT "\n"); + buf[i] = str[opl3->voices[i].state + 1]; + buf[i] = 0; + dev_dbg(opl3->card->dev, "time %.5i: %s [%.2i]: %s\n", + opl3->use_time, s, voice, buf); } #endif @@ -203,9 +213,10 @@ static int opl3_get_voice(struct snd_opl3 *opl3, int instr_4op, for (i = 0; i < END; i++) { if (best[i].voice >= 0) { #ifdef DEBUG_ALLOC - printk(KERN_DEBUG "%s %iop allocation on voice %i\n", - alloc_type[i], instr_4op ? 4 : 2, - best[i].voice); + dev_dbg(opl3->card->dev, + "%s %iop allocation on voice %i\n", + alloc_type[i], instr_4op ? 4 : 2, + best[i].voice); #endif return best[i].voice; } @@ -302,10 +313,8 @@ void snd_opl3_note_on(void *p, int note, int vel, struct snd_midi_channel *chan) opl3 = p; -#ifdef DEBUG_MIDI - snd_printk(KERN_DEBUG "Note on, ch %i, inst %i, note %i, vel %i\n", - chan->number, chan->midi_program, note, vel); -#endif + opl3_dbg(opl3, "Note on, ch %i, inst %i, note %i, vel %i\n", + chan->number, chan->midi_program, note, vel); /* in SYNTH mode, application takes care of voices */ /* in SEQ mode, drum voice numbers are notes on drum channel */ @@ -358,10 +367,8 @@ void snd_opl3_note_on(void *p, int note, int vel, struct snd_midi_channel *chan) spin_unlock_irqrestore(&opl3->voice_lock, flags); return; } -#ifdef DEBUG_MIDI - snd_printk(KERN_DEBUG " --> OPL%i instrument: %s\n", - instr_4op ? 3 : 2, patch->name); -#endif + opl3_dbg(opl3, " --> OPL%i instrument: %s\n", + instr_4op ? 3 : 2, patch->name); /* in SYNTH mode, application takes care of voices */ /* in SEQ mode, allocate voice on free OPL3 channel */ if (opl3->synth_mode == SNDRV_OPL3_MODE_SEQ) { @@ -422,10 +429,8 @@ void snd_opl3_note_on(void *p, int note, int vel, struct snd_midi_channel *chan) } } -#ifdef DEBUG_MIDI - snd_printk(KERN_DEBUG " --> setting OPL3 connection: 0x%x\n", - opl3->connection_reg); -#endif + opl3_dbg(opl3, " --> setting OPL3 connection: 0x%x\n", + opl3->connection_reg); /* * calculate volume depending on connection * between FM operators (see include/opl3.h) @@ -457,9 +462,7 @@ void snd_opl3_note_on(void *p, int note, int vel, struct snd_midi_channel *chan) /* Program the FM voice characteristics */ for (i = 0; i < (instr_4op ? 4 : 2); i++) { -#ifdef DEBUG_MIDI - snd_printk(KERN_DEBUG " --> programming operator %i\n", i); -#endif + opl3_dbg(opl3, " --> programming operator %i\n", i); op_offset = snd_opl3_regmap[voice_offset][i]; /* Set OPL3 AM_VIB register of requested voice/operator */ @@ -537,9 +540,7 @@ void snd_opl3_note_on(void *p, int note, int vel, struct snd_midi_channel *chan) /* Set output sound flag */ blocknum |= OPL3_KEYON_BIT; -#ifdef DEBUG_MIDI - snd_printk(KERN_DEBUG " --> trigger voice %i\n", voice); -#endif + opl3_dbg(opl3, " --> trigger voice %i\n", voice); /* Set OPL3 KEYON_BLOCK register of requested voice */ opl3_reg = reg_side | (OPL3_REG_KEYON_BLOCK + voice_offset); opl3->command(opl3, opl3_reg, blocknum); @@ -593,9 +594,7 @@ void snd_opl3_note_on(void *p, int note, int vel, struct snd_midi_channel *chan) bank = 0; prg = extra_prg - 1; } -#ifdef DEBUG_MIDI - snd_printk(KERN_DEBUG " *** allocating extra program\n"); -#endif + opl3_dbg(opl3, " *** allocating extra program\n"); goto __extra_prg; } spin_unlock_irqrestore(&opl3->voice_lock, flags); @@ -624,9 +623,7 @@ static void snd_opl3_kill_voice(struct snd_opl3 *opl3, int voice) } /* kill voice */ -#ifdef DEBUG_MIDI - snd_printk(KERN_DEBUG " --> kill voice %i\n", voice); -#endif + opl3_dbg(opl3, " --> kill voice %i\n", voice); opl3_reg = reg_side | (OPL3_REG_KEYON_BLOCK + voice_offset); /* clear Key ON bit */ opl3->command(opl3, opl3_reg, vp->keyon_reg); @@ -660,10 +657,8 @@ static void snd_opl3_note_off_unsafe(void *p, int note, int vel, opl3 = p; -#ifdef DEBUG_MIDI - snd_printk(KERN_DEBUG "Note off, ch %i, inst %i, note %i\n", - chan->number, chan->midi_program, note); -#endif + opl3_dbg(opl3, "Note off, ch %i, inst %i, note %i\n", + chan->number, chan->midi_program, note); if (opl3->synth_mode == SNDRV_OPL3_MODE_SEQ) { if (chan->drum_channel && use_internal_drums) { @@ -703,10 +698,8 @@ void snd_opl3_note_off(void *p, int note, int vel, */ void snd_opl3_key_press(void *p, int note, int vel, struct snd_midi_channel *chan) { -#ifdef DEBUG_MIDI - snd_printk(KERN_DEBUG "Key pressure, ch#: %i, inst#: %i\n", - chan->number, chan->midi_program); -#endif + opl3_dbg(p, "Key pressure, ch#: %i, inst#: %i\n", + chan->number, chan->midi_program); } /* @@ -714,10 +707,8 @@ void snd_opl3_key_press(void *p, int note, int vel, struct snd_midi_channel *cha */ void snd_opl3_terminate_note(void *p, int note, struct snd_midi_channel *chan) { -#ifdef DEBUG_MIDI - snd_printk(KERN_DEBUG "Terminate note, ch#: %i, inst#: %i\n", - chan->number, chan->midi_program); -#endif + opl3_dbg(p, "Terminate note, ch#: %i, inst#: %i\n", + chan->number, chan->midi_program); } static void snd_opl3_update_pitch(struct snd_opl3 *opl3, int voice) @@ -803,10 +794,8 @@ void snd_opl3_control(void *p, int type, struct snd_midi_channel *chan) struct snd_opl3 *opl3; opl3 = p; -#ifdef DEBUG_MIDI - snd_printk(KERN_DEBUG "Controller, TYPE = %i, ch#: %i, inst#: %i\n", - type, chan->number, chan->midi_program); -#endif + opl3_dbg(opl3, "Controller, TYPE = %i, ch#: %i, inst#: %i\n", + type, chan->number, chan->midi_program); switch (type) { case MIDI_CTL_MSB_MODWHEEL: @@ -837,10 +826,8 @@ void snd_opl3_control(void *p, int type, struct snd_midi_channel *chan) void snd_opl3_nrpn(void *p, struct snd_midi_channel *chan, struct snd_midi_channel_set *chset) { -#ifdef DEBUG_MIDI - snd_printk(KERN_DEBUG "NRPN, ch#: %i, inst#: %i\n", - chan->number, chan->midi_program); -#endif + opl3_dbg(p, "NRPN, ch#: %i, inst#: %i\n", + chan->number, chan->midi_program); } /* @@ -849,7 +836,5 @@ void snd_opl3_nrpn(void *p, struct snd_midi_channel *chan, void snd_opl3_sysex(void *p, unsigned char *buf, int len, int parsed, struct snd_midi_channel_set *chset) { -#ifdef DEBUG_MIDI - snd_printk(KERN_DEBUG "SYSEX\n"); -#endif + opl3_dbg(p, "SYSEX\n"); } diff --git a/sound/drivers/opl3/opl3_oss.c b/sound/drivers/opl3/opl3_oss.c index 7645365eec894e..6d39b2b77b80c5 100644 --- a/sound/drivers/opl3/opl3_oss.c +++ b/sound/drivers/opl3/opl3_oss.c @@ -193,14 +193,14 @@ static int snd_opl3_load_patch_seq_oss(struct snd_seq_oss_arg *arg, int format, return -EINVAL; if (count < (int)sizeof(sbi)) { - snd_printk(KERN_ERR "FM Error: Patch record too short\n"); + dev_err(opl3->card->dev, "FM Error: Patch record too short\n"); return -EINVAL; } if (copy_from_user(&sbi, buf, sizeof(sbi))) return -EFAULT; if (sbi.channel < 0 || sbi.channel >= SBFM_MAXINSTR) { - snd_printk(KERN_ERR "FM Error: Invalid instrument number %d\n", + dev_err(opl3->card->dev, "FM Error: Invalid instrument number %d\n", sbi.channel); return -EINVAL; } @@ -220,13 +220,15 @@ static int snd_opl3_load_patch_seq_oss(struct snd_seq_oss_arg *arg, int format, static int snd_opl3_ioctl_seq_oss(struct snd_seq_oss_arg *arg, unsigned int cmd, unsigned long ioarg) { + struct snd_opl3 *opl3; + if (snd_BUG_ON(!arg)) return -ENXIO; + opl3 = arg->private_data; switch (cmd) { case SNDCTL_FM_LOAD_INSTR: - snd_printk(KERN_ERR "OPL3: " - "Obsolete ioctl(SNDCTL_FM_LOAD_INSTR) used. " - "Fix the program.\n"); + dev_err(opl3->card->dev, + "OPL3: Obsolete ioctl(SNDCTL_FM_LOAD_INSTR) used. Fix the program.\n"); return -EINVAL; case SNDCTL_SYNTH_MEMAVL: diff --git a/sound/drivers/opl3/opl3_synth.c b/sound/drivers/opl3/opl3_synth.c index 97d30a833ac81e..10f622b439a006 100644 --- a/sound/drivers/opl3/opl3_synth.c +++ b/sound/drivers/opl3/opl3_synth.c @@ -158,10 +158,8 @@ int snd_opl3_ioctl(struct snd_hwdep * hw, struct file *file, return 0; #endif -#ifdef CONFIG_SND_DEBUG default: - snd_printk(KERN_WARNING "unknown IOCTL: 0x%x\n", cmd); -#endif + dev_dbg(opl3->card->dev, "unknown IOCTL: 0x%x\n", cmd); } return -ENOTTY; } diff --git a/sound/drivers/opl4/opl4_lib.c b/sound/drivers/opl4/opl4_lib.c index 035645eb5e8d3b..8fa61596875a5e 100644 --- a/sound/drivers/opl4/opl4_lib.c +++ b/sound/drivers/opl4/opl4_lib.c @@ -114,7 +114,7 @@ static int snd_opl4_detect(struct snd_opl4 *opl4) snd_opl4_enable_opl4(opl4); id1 = snd_opl4_read(opl4, OPL4_REG_MEMORY_CONFIGURATION); - snd_printdd("OPL4[02]=%02x\n", id1); + dev_dbg(opl4->card->dev, "OPL4[02]=%02x\n", id1); switch (id1 & OPL4_DEVICE_ID_MASK) { case 0x20: opl4->hardware = OPL3_HW_OPL4; @@ -130,7 +130,7 @@ static int snd_opl4_detect(struct snd_opl4 *opl4) snd_opl4_write(opl4, OPL4_REG_MIX_CONTROL_PCM, 0xff); id1 = snd_opl4_read(opl4, OPL4_REG_MIX_CONTROL_FM); id2 = snd_opl4_read(opl4, OPL4_REG_MIX_CONTROL_PCM); - snd_printdd("OPL4 id1=%02x id2=%02x\n", id1, id2); + dev_dbg(opl4->card->dev, "OPL4 id1=%02x id2=%02x\n", id1, id2); if (id1 != 0x00 || id2 != 0xff) return -ENODEV; @@ -200,7 +200,7 @@ int snd_opl4_create(struct snd_card *card, opl4->res_fm_port = request_region(fm_port, 8, "OPL4 FM"); opl4->res_pcm_port = request_region(pcm_port, 8, "OPL4 PCM/MIX"); if (!opl4->res_fm_port || !opl4->res_pcm_port) { - snd_printk(KERN_ERR "opl4: can't grab ports 0x%lx, 0x%lx\n", fm_port, pcm_port); + dev_err(card->dev, "opl4: can't grab ports 0x%lx, 0x%lx\n", fm_port, pcm_port); snd_opl4_free(opl4); return -EBUSY; } @@ -214,7 +214,7 @@ int snd_opl4_create(struct snd_card *card, err = snd_opl4_detect(opl4); if (err < 0) { snd_opl4_free(opl4); - snd_printd("OPL4 chip not detected at %#lx/%#lx\n", fm_port, pcm_port); + dev_dbg(card->dev, "OPL4 chip not detected at %#lx/%#lx\n", fm_port, pcm_port); return err; } diff --git a/sound/drivers/opl4/yrw801.c b/sound/drivers/opl4/yrw801.c index 6c335492d082e4..9e464b84b9053f 100644 --- a/sound/drivers/opl4/yrw801.c +++ b/sound/drivers/opl4/yrw801.c @@ -43,7 +43,7 @@ int snd_yrw801_detect(struct snd_opl4 *opl4) snd_opl4_read_memory(opl4, buf, 0x1ffffe, 2); if (buf[0] != 0x01) return -ENODEV; - snd_printdd("YRW801 ROM version %02x.%02x\n", buf[0], buf[1]); + dev_dbg(opl4->card->dev, "YRW801 ROM version %02x.%02x\n", buf[0], buf[1]); return 0; } diff --git a/sound/drivers/pcsp/pcsp.c b/sound/drivers/pcsp/pcsp.c index 7195cb49e00f8c..78c9b1c7590f51 100644 --- a/sound/drivers/pcsp/pcsp.c +++ b/sound/drivers/pcsp/pcsp.c @@ -47,11 +47,12 @@ static int snd_pcsp_create(struct snd_card *card) if (!nopcm) { if (resolution > PCSP_MAX_PERIOD_NS) { - printk(KERN_ERR "PCSP: Timer resolution is not sufficient " - "(%unS)\n", resolution); - printk(KERN_ERR "PCSP: Make sure you have HPET and ACPI " - "enabled.\n"); - printk(KERN_ERR "PCSP: Turned into nopcm mode.\n"); + dev_err(card->dev, + "PCSP: Timer resolution is not sufficient (%unS)\n", + resolution); + dev_err(card->dev, + "PCSP: Make sure you have HPET and ACPI enabled.\n"); + dev_err(card->dev, "PCSP: Turned into nopcm mode.\n"); nopcm = 1; } } @@ -61,8 +62,8 @@ static int snd_pcsp_create(struct snd_card *card) else min_div = MAX_DIV; #if PCSP_DEBUG - printk(KERN_DEBUG "PCSP: lpj=%li, min_div=%i, res=%u\n", - loops_per_jiffy, min_div, resolution); + dev_dbg(card->dev, "PCSP: lpj=%li, min_div=%i, res=%u\n", + loops_per_jiffy, min_div, resolution); #endif div = MAX_DIV / min_div; @@ -141,14 +142,14 @@ static int alsa_card_pcsp_init(struct device *dev) err = snd_card_pcsp_probe(0, dev); if (err) { - printk(KERN_ERR "PC-Speaker initialization failed.\n"); + dev_err(dev, "PC-Speaker initialization failed.\n"); return err; } /* Well, CONFIG_DEBUG_PAGEALLOC makes the sound horrible. Lets alert */ if (debug_pagealloc_enabled()) { - printk(KERN_WARNING "PCSP: CONFIG_DEBUG_PAGEALLOC is enabled, " - "which may make the sound noisy.\n"); + dev_warn(dev, + "PCSP: CONFIG_DEBUG_PAGEALLOC is enabled, which may make the sound noisy.\n"); } return 0; diff --git a/sound/drivers/pcsp/pcsp_lib.c b/sound/drivers/pcsp/pcsp_lib.c index 773db4bf087693..d9bc1ea1b53ccc 100644 --- a/sound/drivers/pcsp/pcsp_lib.c +++ b/sound/drivers/pcsp/pcsp_lib.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include "pcsp.h" @@ -105,8 +106,8 @@ static void pcsp_pointer_update(struct snd_pcsp *chip) periods_elapsed = chip->playback_ptr - chip->period_ptr; if (periods_elapsed < 0) { #if PCSP_DEBUG - printk(KERN_INFO "PCSP: buffer_bytes mod period_bytes != 0 ? " - "(%zi %zi %zi)\n", + dev_dbg(chip->card->dev, + "PCSP: buffer_bytes mod period_bytes != 0 ? (%zi %zi %zi)\n", chip->playback_ptr, period_bytes, buffer_bytes); #endif periods_elapsed += buffer_bytes; @@ -136,7 +137,7 @@ enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle) pointer_update = !chip->thalf; ns = pcsp_timer_update(chip); if (!ns) { - printk(KERN_WARNING "PCSP: unexpected stop\n"); + dev_warn(chip->card->dev, "PCSP: unexpected stop\n"); return HRTIMER_NORESTART; } @@ -151,10 +152,10 @@ enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle) static int pcsp_start_playing(struct snd_pcsp *chip) { #if PCSP_DEBUG - printk(KERN_INFO "PCSP: start_playing called\n"); + dev_dbg(chip->card->dev, "PCSP: start_playing called\n"); #endif if (atomic_read(&chip->timer_active)) { - printk(KERN_ERR "PCSP: Timer already active\n"); + dev_err(chip->card->dev, "PCSP: Timer already active\n"); return -EIO; } @@ -172,7 +173,7 @@ static int pcsp_start_playing(struct snd_pcsp *chip) static void pcsp_stop_playing(struct snd_pcsp *chip) { #if PCSP_DEBUG - printk(KERN_INFO "PCSP: stop_playing called\n"); + dev_dbg(chip->card->dev, "PCSP: stop_playing called\n"); #endif if (!atomic_read(&chip->timer_active)) return; @@ -201,7 +202,7 @@ static int snd_pcsp_playback_close(struct snd_pcm_substream *substream) { struct snd_pcsp *chip = snd_pcm_substream_chip(substream); #if PCSP_DEBUG - printk(KERN_INFO "PCSP: close called\n"); + dev_dbg(chip->card->dev, "PCSP: close called\n"); #endif pcsp_sync_stop(chip); chip->playback_substream = NULL; @@ -220,7 +221,7 @@ static int snd_pcsp_playback_hw_free(struct snd_pcm_substream *substream) { struct snd_pcsp *chip = snd_pcm_substream_chip(substream); #if PCSP_DEBUG - printk(KERN_INFO "PCSP: hw_free called\n"); + dev_dbg(chip->card->dev, "PCSP: hw_free called\n"); #endif pcsp_sync_stop(chip); return 0; @@ -236,14 +237,13 @@ static int snd_pcsp_playback_prepare(struct snd_pcm_substream *substream) snd_pcm_format_physical_width(substream->runtime->format) >> 3; chip->is_signed = snd_pcm_format_signed(substream->runtime->format); #if PCSP_DEBUG - printk(KERN_INFO "PCSP: prepare called, " - "size=%zi psize=%zi f=%zi f1=%i fsize=%i\n", - snd_pcm_lib_buffer_bytes(substream), - snd_pcm_lib_period_bytes(substream), - snd_pcm_lib_buffer_bytes(substream) / - snd_pcm_lib_period_bytes(substream), - substream->runtime->periods, - chip->fmt_size); + dev_dbg(chip->card->dev, "PCSP: prepare called, size=%zi psize=%zi f=%zi f1=%i fsize=%i\n", + snd_pcm_lib_buffer_bytes(substream), + snd_pcm_lib_period_bytes(substream), + snd_pcm_lib_buffer_bytes(substream) / + snd_pcm_lib_period_bytes(substream), + substream->runtime->periods, + chip->fmt_size); #endif return 0; } @@ -252,7 +252,7 @@ static int snd_pcsp_trigger(struct snd_pcm_substream *substream, int cmd) { struct snd_pcsp *chip = snd_pcm_substream_chip(substream); #if PCSP_DEBUG - printk(KERN_INFO "PCSP: trigger called\n"); + dev_dbg(chip->card->dev, "PCSP: trigger called\n"); #endif switch (cmd) { case SNDRV_PCM_TRIGGER_START: @@ -306,10 +306,10 @@ static int snd_pcsp_playback_open(struct snd_pcm_substream *substream) struct snd_pcsp *chip = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; #if PCSP_DEBUG - printk(KERN_INFO "PCSP: open called\n"); + dev_dbg(chip->card->dev, "PCSP: open called\n"); #endif if (atomic_read(&chip->timer_active)) { - printk(KERN_ERR "PCSP: still active!!\n"); + dev_err(chip->card->dev, "PCSP: still active!!\n"); return -EBUSY; } runtime->hw = snd_pcsp_playback; diff --git a/sound/drivers/pcsp/pcsp_mixer.c b/sound/drivers/pcsp/pcsp_mixer.c index da33e5b620a78b..c0ae942358b9b3 100644 --- a/sound/drivers/pcsp/pcsp_mixer.c +++ b/sound/drivers/pcsp/pcsp_mixer.c @@ -73,7 +73,7 @@ static int pcsp_treble_put(struct snd_kcontrol *kcontrol, if (treble != chip->treble) { chip->treble = treble; #if PCSP_DEBUG - printk(KERN_INFO "PCSP: rate set to %li\n", PCSP_RATE()); + dev_dbg(chip->card->dev, "PCSP: rate set to %li\n", PCSP_RATE()); #endif changed = 1; } diff --git a/sound/drivers/portman2x4.c b/sound/drivers/portman2x4.c index 6fd9e887002154..54d818d2f53dc4 100644 --- a/sound/drivers/portman2x4.c +++ b/sound/drivers/portman2x4.c @@ -385,9 +385,8 @@ static void portman_flush_input(struct portman *pm, unsigned char port) command = RXDATA1; break; default: - snd_printk(KERN_WARNING - "portman_flush_input() Won't flush port %i\n", - port); + dev_warn(pm->card->dev, "%s Won't flush port %i\n", + __func__, port); return; } @@ -712,7 +711,7 @@ static int snd_portman_probe(struct platform_device *pdev) err = snd_card_new(&pdev->dev, index[dev], id[dev], THIS_MODULE, 0, &card); if (err < 0) { - snd_printd("Cannot create card\n"); + dev_dbg(&pdev->dev, "Cannot create card\n"); return err; } strcpy(card->driver, DRIVER_NAME); @@ -726,21 +725,21 @@ static int snd_portman_probe(struct platform_device *pdev) &portman_cb, /* callbacks */ pdev->id); /* device number */ if (pardev == NULL) { - snd_printd("Cannot register pardevice\n"); + dev_dbg(card->dev, "Cannot register pardevice\n"); err = -EIO; goto __err; } /* claim parport */ if (parport_claim(pardev)) { - snd_printd("Cannot claim parport 0x%lx\n", pardev->port->base); + dev_dbg(card->dev, "Cannot claim parport 0x%lx\n", pardev->port->base); err = -EIO; goto free_pardev; } err = portman_create(card, pardev, &pm); if (err < 0) { - snd_printd("Cannot create main component\n"); + dev_dbg(card->dev, "Cannot create main component\n"); goto release_pardev; } card->private_data = pm; @@ -754,7 +753,7 @@ static int snd_portman_probe(struct platform_device *pdev) err = snd_portman_rawmidi_create(card); if (err < 0) { - snd_printd("Creating Rawmidi component failed\n"); + dev_dbg(card->dev, "Creating Rawmidi component failed\n"); goto __err; } @@ -768,11 +767,11 @@ static int snd_portman_probe(struct platform_device *pdev) /* At this point card will be usable */ err = snd_card_register(card); if (err < 0) { - snd_printd("Cannot register card\n"); + dev_dbg(card->dev, "Cannot register card\n"); goto __err; } - snd_printk(KERN_INFO "Portman 2x4 on 0x%lx\n", p->base); + dev_info(card->dev, "Portman 2x4 on 0x%lx\n", p->base); return 0; release_pardev: diff --git a/sound/drivers/serial-u16550.c b/sound/drivers/serial-u16550.c index 3cbc7a4adcb464..f66e01624c68ab 100644 --- a/sound/drivers/serial-u16550.c +++ b/sound/drivers/serial-u16550.c @@ -224,9 +224,9 @@ static void snd_uart16550_io_loop(struct snd_uart16550 * uart) snd_rawmidi_receive(uart->midi_input[substream], &c, 1); if (status & UART_LSR_OE) - snd_printk(KERN_WARNING - "%s: Overrun on device at 0x%lx\n", - uart->rmidi->name, uart->base); + dev_warn(uart->card->dev, + "%s: Overrun on device at 0x%lx\n", + uart->rmidi->name, uart->base); } /* remember the last stream */ @@ -323,7 +323,8 @@ static int snd_uart16550_detect(struct snd_uart16550 *uart) } if (!devm_request_region(uart->card->dev, io_base, 8, "Serial MIDI")) { - snd_printk(KERN_ERR "u16550: can't grab port 0x%lx\n", io_base); + dev_err(uart->card->dev, + "u16550: can't grab port 0x%lx\n", io_base); return -EBUSY; } @@ -619,9 +620,9 @@ static int snd_uart16550_output_byte(struct snd_uart16550 *uart, } } else { if (!snd_uart16550_write_buffer(uart, midi_byte)) { - snd_printk(KERN_WARNING - "%s: Buffer overrun on device at 0x%lx\n", - uart->rmidi->name, uart->base); + dev_warn(uart->card->dev, + "%s: Buffer overrun on device at 0x%lx\n", + uart->rmidi->name, uart->base); return 0; } } @@ -775,15 +776,15 @@ static int snd_uart16550_create(struct snd_card *card, err = snd_uart16550_detect(uart); if (err <= 0) { - printk(KERN_ERR "no UART detected at 0x%lx\n", iobase); + dev_err(card->dev, "no UART detected at 0x%lx\n", iobase); return -ENODEV; } if (irq >= 0 && irq != SNDRV_AUTO_IRQ) { if (devm_request_irq(card->dev, irq, snd_uart16550_interrupt, 0, "Serial MIDI", uart)) { - snd_printk(KERN_WARNING - "irq %d busy. Using Polling.\n", irq); + dev_warn(card->dev, + "irq %d busy. Using Polling.\n", irq); } else { uart->irq = irq; } @@ -879,23 +880,23 @@ static int snd_serial_probe(struct platform_device *devptr) case SNDRV_SERIAL_GENERIC: break; default: - snd_printk(KERN_ERR - "Adaptor type is out of range 0-%d (%d)\n", - SNDRV_SERIAL_MAX_ADAPTOR, adaptor[dev]); + dev_err(&devptr->dev, + "Adaptor type is out of range 0-%d (%d)\n", + SNDRV_SERIAL_MAX_ADAPTOR, adaptor[dev]); return -ENODEV; } if (outs[dev] < 1 || outs[dev] > SNDRV_SERIAL_MAX_OUTS) { - snd_printk(KERN_ERR - "Count of outputs is out of range 1-%d (%d)\n", - SNDRV_SERIAL_MAX_OUTS, outs[dev]); + dev_err(&devptr->dev, + "Count of outputs is out of range 1-%d (%d)\n", + SNDRV_SERIAL_MAX_OUTS, outs[dev]); return -ENODEV; } if (ins[dev] < 1 || ins[dev] > SNDRV_SERIAL_MAX_INS) { - snd_printk(KERN_ERR - "Count of inputs is out of range 1-%d (%d)\n", - SNDRV_SERIAL_MAX_INS, ins[dev]); + dev_err(&devptr->dev, + "Count of inputs is out of range 1-%d (%d)\n", + SNDRV_SERIAL_MAX_INS, ins[dev]); return -ENODEV; } @@ -975,7 +976,7 @@ static int __init alsa_card_serial_init(void) } if (! cards) { #ifdef MODULE - printk(KERN_ERR "serial midi soundcard not found or device busy\n"); + pr_err("serial midi soundcard not found or device busy\n"); #endif snd_serial_unregister_all(); return -ENODEV; diff --git a/sound/drivers/virmidi.c b/sound/drivers/virmidi.c index 58012de90c3829..5f7b65ad63e3ab 100644 --- a/sound/drivers/virmidi.c +++ b/sound/drivers/virmidi.c @@ -83,9 +83,9 @@ static int snd_virmidi_probe(struct platform_device *devptr) vmidi->card = card; if (midi_devs[dev] > MAX_MIDI_DEVICES) { - snd_printk(KERN_WARNING - "too much midi devices for virmidi %d: force to use %d\n", - dev, MAX_MIDI_DEVICES); + dev_warn(&devptr->dev, + "too much midi devices for virmidi %d: force to use %d\n", + dev, MAX_MIDI_DEVICES); midi_devs[dev] = MAX_MIDI_DEVICES; } for (idx = 0; idx < midi_devs[dev]; idx++) { @@ -155,7 +155,7 @@ static int __init alsa_card_virmidi_init(void) } if (!cards) { #ifdef MODULE - printk(KERN_ERR "Card-VirMIDI soundcard not found or device busy\n"); + pr_err("Card-VirMIDI soundcard not found or device busy\n"); #endif snd_virmidi_unregister_all(); return -ENODEV; diff --git a/sound/drivers/vx/vx_core.c b/sound/drivers/vx/vx_core.c index 18901e5bcfcf98..e2def8719ed2cd 100644 --- a/sound/drivers/vx/vx_core.c +++ b/sound/drivers/vx/vx_core.c @@ -52,7 +52,9 @@ int snd_vx_check_reg_bit(struct vx_core *chip, int reg, int mask, int bit, int t return 0; //msleep(10); } while (time_after_eq(end_time, jiffies)); - snd_printd(KERN_DEBUG "vx_check_reg_bit: timeout, reg=%s, mask=0x%x, val=0x%x\n", reg_names[reg], mask, snd_vx_inb(chip, reg)); + dev_dbg(chip->card->dev, + "vx_check_reg_bit: timeout, reg=%s, mask=0x%x, val=0x%x\n", + reg_names[reg], mask, snd_vx_inb(chip, reg)); return -EIO; } @@ -129,13 +131,14 @@ static int vx_transfer_end(struct vx_core *chip, int cmd) if (err & ISR_ERR) { err = vx_wait_for_rx_full(chip); if (err < 0) { - snd_printd(KERN_DEBUG "transfer_end: error in rx_full\n"); + dev_dbg(chip->card->dev, + "transfer_end: error in rx_full\n"); return err; } err = vx_inb(chip, RXH) << 16; err |= vx_inb(chip, RXM) << 8; err |= vx_inb(chip, RXL); - snd_printd(KERN_DEBUG "transfer_end: error = 0x%x\n", err); + dev_dbg(chip->card->dev, "transfer_end: error = 0x%x\n", err); return -(VX_ERR_MASK | err); } return 0; @@ -239,20 +242,10 @@ int vx_send_msg_nolock(struct vx_core *chip, struct vx_rmh *rmh) err = vx_reset_chk(chip); if (err < 0) { - snd_printd(KERN_DEBUG "vx_send_msg: vx_reset_chk error\n"); + dev_dbg(chip->card->dev, "vx_send_msg: vx_reset_chk error\n"); return err; } -#if 0 - printk(KERN_DEBUG "rmh: cmd = 0x%06x, length = %d, stype = %d\n", - rmh->Cmd[0], rmh->LgCmd, rmh->DspStat); - if (rmh->LgCmd > 1) { - printk(KERN_DEBUG " "); - for (i = 1; i < rmh->LgCmd; i++) - printk(KERN_CONT "0x%06x ", rmh->Cmd[i]); - printk(KERN_CONT "\n"); - } -#endif /* Check bit M is set according to length of the command */ if (rmh->LgCmd > 1) rmh->Cmd[0] |= MASK_MORE_THAN_1_WORD_COMMAND; @@ -262,7 +255,7 @@ int vx_send_msg_nolock(struct vx_core *chip, struct vx_rmh *rmh) /* Wait for TX empty */ err = vx_wait_isr_bit(chip, ISR_TX_EMPTY); if (err < 0) { - snd_printd(KERN_DEBUG "vx_send_msg: wait tx empty error\n"); + dev_dbg(chip->card->dev, "vx_send_msg: wait tx empty error\n"); return err; } @@ -274,7 +267,8 @@ int vx_send_msg_nolock(struct vx_core *chip, struct vx_rmh *rmh) /* Trigger irq MESSAGE */ err = vx_send_irq_dsp(chip, IRQ_MESSAGE); if (err < 0) { - snd_printd(KERN_DEBUG "vx_send_msg: send IRQ_MESSAGE error\n"); + dev_dbg(chip->card->dev, + "vx_send_msg: send IRQ_MESSAGE error\n"); return err; } @@ -287,13 +281,15 @@ int vx_send_msg_nolock(struct vx_core *chip, struct vx_rmh *rmh) if (vx_inb(chip, ISR) & ISR_ERR) { err = vx_wait_for_rx_full(chip); if (err < 0) { - snd_printd(KERN_DEBUG "vx_send_msg: rx_full read error\n"); + dev_dbg(chip->card->dev, + "vx_send_msg: rx_full read error\n"); return err; } err = vx_inb(chip, RXH) << 16; err |= vx_inb(chip, RXM) << 8; err |= vx_inb(chip, RXL); - snd_printd(KERN_DEBUG "msg got error = 0x%x at cmd[0]\n", err); + dev_dbg(chip->card->dev, + "msg got error = 0x%x at cmd[0]\n", err); err = -(VX_ERR_MASK | err); return err; } @@ -304,7 +300,8 @@ int vx_send_msg_nolock(struct vx_core *chip, struct vx_rmh *rmh) /* Wait for TX ready */ err = vx_wait_isr_bit(chip, ISR_TX_READY); if (err < 0) { - snd_printd(KERN_DEBUG "vx_send_msg: tx_ready error\n"); + dev_dbg(chip->card->dev, + "vx_send_msg: tx_ready error\n"); return err; } @@ -316,14 +313,16 @@ int vx_send_msg_nolock(struct vx_core *chip, struct vx_rmh *rmh) /* Trigger irq MESS_READ_NEXT */ err = vx_send_irq_dsp(chip, IRQ_MESS_READ_NEXT); if (err < 0) { - snd_printd(KERN_DEBUG "vx_send_msg: IRQ_READ_NEXT error\n"); + dev_dbg(chip->card->dev, + "vx_send_msg: IRQ_READ_NEXT error\n"); return err; } } /* Wait for TX empty */ err = vx_wait_isr_bit(chip, ISR_TX_READY); if (err < 0) { - snd_printd(KERN_DEBUG "vx_send_msg: TX_READY error\n"); + dev_dbg(chip->card->dev, + "vx_send_msg: TX_READY error\n"); return err; } /* End of transfer */ @@ -372,9 +371,6 @@ int vx_send_rih_nolock(struct vx_core *chip, int cmd) if (chip->chip_status & VX_STAT_IS_STALE) return -EBUSY; -#if 0 - printk(KERN_DEBUG "send_rih: cmd = 0x%x\n", cmd); -#endif err = vx_reset_chk(chip); if (err < 0) return err; @@ -453,7 +449,7 @@ int snd_vx_load_boot_image(struct vx_core *chip, const struct firmware *boot) if (no_fillup) break; if (vx_wait_isr_bit(chip, ISR_TX_EMPTY) < 0) { - snd_printk(KERN_ERR "dsp boot failed at %d\n", i); + dev_err(chip->card->dev, "dsp boot failed at %d\n", i); return -EIO; } vx_outb(chip, TXH, 0); @@ -462,7 +458,7 @@ int snd_vx_load_boot_image(struct vx_core *chip, const struct firmware *boot) } else { const unsigned char *image = boot->data + i; if (vx_wait_isr_bit(chip, ISR_TX_EMPTY) < 0) { - snd_printk(KERN_ERR "dsp boot failed at %d\n", i); + dev_err(chip->card->dev, "dsp boot failed at %d\n", i); return -EIO; } vx_outb(chip, TXH, image[0]); @@ -510,18 +506,12 @@ irqreturn_t snd_vx_threaded_irq_handler(int irq, void *dev) if (vx_test_irq_src(chip, &events) < 0) return IRQ_HANDLED; -#if 0 - if (events & 0x000800) - printk(KERN_ERR "DSP Stream underrun ! IRQ events = 0x%x\n", events); -#endif - // printk(KERN_DEBUG "IRQ events = 0x%x\n", events); - /* We must prevent any application using this DSP * and block any further request until the application * either unregisters or reloads the DSP */ if (events & FATAL_DSP_ERROR) { - snd_printk(KERN_ERR "vx_core: fatal DSP error!!\n"); + dev_err(chip->card->dev, "vx_core: fatal DSP error!!\n"); return IRQ_HANDLED; } @@ -698,8 +688,8 @@ int snd_vx_dsp_load(struct vx_core *chip, const struct firmware *dsp) /* Wait DSP ready for a new read */ err = vx_wait_isr_bit(chip, ISR_TX_EMPTY); if (err < 0) { - printk(KERN_ERR - "dsp loading error at position %d\n", i); + dev_err(chip->card->dev, + "dsp loading error at position %d\n", i); return err; } cptr = image; @@ -713,7 +703,6 @@ int snd_vx_dsp_load(struct vx_core *chip, const struct firmware *dsp) csum = (csum >> 24) | (csum << 8); vx_outb(chip, TXL, *cptr++); } - snd_printdd(KERN_DEBUG "checksum = 0x%08x\n", csum); msleep(200); @@ -759,7 +748,8 @@ int snd_vx_resume(struct vx_core *chip) continue; err = chip->ops->load_dsp(chip, i, chip->firmware[i]); if (err < 0) { - snd_printk(KERN_ERR "vx: firmware resume error at DSP %d\n", i); + dev_err(chip->card->dev, + "vx: firmware resume error at DSP %d\n", i); return -EIO; } } diff --git a/sound/drivers/vx/vx_hwdep.c b/sound/drivers/vx/vx_hwdep.c index efbb644edba1f8..a7f8ddf4df5a9e 100644 --- a/sound/drivers/vx/vx_hwdep.c +++ b/sound/drivers/vx/vx_hwdep.c @@ -58,8 +58,8 @@ int snd_vx_setup_firmware(struct vx_core *chip) if (! fw_files[chip->type][i]) continue; sprintf(path, "vx/%s", fw_files[chip->type][i]); - if (request_firmware(&fw, path, chip->dev)) { - snd_printk(KERN_ERR "vx: can't load firmware %s\n", path); + if (request_firmware(&fw, path, chip->card->dev)) { + dev_err(chip->card->dev, "vx: can't load firmware %s\n", path); return -ENOENT; } err = chip->ops->load_dsp(chip, i, fw); diff --git a/sound/drivers/vx/vx_pcm.c b/sound/drivers/vx/vx_pcm.c index ceaeb257003bcc..cbc77ca1ebdd54 100644 --- a/sound/drivers/vx/vx_pcm.c +++ b/sound/drivers/vx/vx_pcm.c @@ -190,8 +190,10 @@ static int vx_set_ibl(struct vx_core *chip, struct vx_ibl_info *info) info->max_size = rmh.Stat[1]; info->min_size = rmh.Stat[2]; info->granularity = rmh.Stat[3]; - snd_printdd(KERN_DEBUG "vx_set_ibl: size = %d, max = %d, min = %d, gran = %d\n", - info->size, info->max_size, info->min_size, info->granularity); + dev_dbg(chip->card->dev, + "%s: size = %d, max = %d, min = %d, gran = %d\n", + __func__, info->size, info->max_size, info->min_size, + info->granularity); return 0; } @@ -616,12 +618,12 @@ static int vx_pcm_playback_transfer_chunk(struct vx_core *chip, if (space < 0) { /* disconnect the host, SIZE_HBUF command always switches to the stream mode */ vx_send_rih(chip, IRQ_CONNECT_STREAM_NEXT); - snd_printd("error hbuffer\n"); + dev_dbg(chip->card->dev, "error hbuffer\n"); return space; } if (space < size) { vx_send_rih(chip, IRQ_CONNECT_STREAM_NEXT); - snd_printd("no enough hbuffer space %d\n", space); + dev_dbg(chip->card->dev, "no enough hbuffer space %d\n", space); return -EIO; /* XRUN */ } @@ -795,7 +797,8 @@ static int vx_pcm_prepare(struct snd_pcm_substream *subs) /* IEC958 status (raw-mode) was changed */ /* we reopen the pipe */ struct vx_rmh rmh; - snd_printdd(KERN_DEBUG "reopen the pipe with data_mode = %d\n", data_mode); + dev_dbg(chip->card->dev, + "reopen the pipe with data_mode = %d\n", data_mode); vx_init_rmh(&rmh, CMD_FREE_PIPE); vx_set_pipe_cmd_params(&rmh, 0, pipe->number, 0); err = vx_send_msg(chip, &rmh); @@ -812,8 +815,9 @@ static int vx_pcm_prepare(struct snd_pcm_substream *subs) } if (chip->pcm_running && chip->freq != runtime->rate) { - snd_printk(KERN_ERR "vx: cannot set different clock %d " - "from the current %d\n", runtime->rate, chip->freq); + dev_err(chip->card->dev, + "vx: cannot set different clock %d from the current %d\n", + runtime->rate, chip->freq); return -EINVAL; } vx_set_clock(chip, runtime->rate); @@ -1091,7 +1095,7 @@ void vx_pcm_update_intr(struct vx_core *chip, unsigned int events) chip->irq_rmh.Cmd[0] |= 0x00000002; /* SEL_END_OF_BUF_EVENTS */ if (vx_send_msg(chip, &chip->irq_rmh) < 0) { - snd_printdd(KERN_ERR "msg send error!!\n"); + dev_dbg(chip->card->dev, "msg send error!!\n"); return; } @@ -1141,7 +1145,8 @@ static int vx_init_audio_io(struct vx_core *chip) vx_init_rmh(&rmh, CMD_SUPPORTED); if (vx_send_msg(chip, &rmh) < 0) { - snd_printk(KERN_ERR "vx: cannot get the supported audio data\n"); + dev_err(chip->card->dev, + "vx: cannot get the supported audio data\n"); return -ENXIO; } diff --git a/sound/drivers/vx/vx_uer.c b/sound/drivers/vx/vx_uer.c index 884c40be19dc18..3eca22151225b5 100644 --- a/sound/drivers/vx/vx_uer.c +++ b/sound/drivers/vx/vx_uer.c @@ -196,7 +196,8 @@ void vx_set_internal_clock(struct vx_core *chip, unsigned int freq) /* Get real clock value */ clock = vx_calc_clock_from_freq(chip, freq); - snd_printdd(KERN_DEBUG "set internal clock to 0x%x from freq %d\n", clock, freq); + dev_dbg(chip->card->dev, + "set internal clock to 0x%x from freq %d\n", clock, freq); mutex_lock(&chip->lock); if (vx_is_pcmcia(chip)) { vx_outb(chip, HIFREQ, (clock >> 8) & 0x0f); diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c index 1a163bbcabd79e..c827d7d8d80035 100644 --- a/sound/firewire/amdtp-stream.c +++ b/sound/firewire/amdtp-stream.c @@ -77,6 +77,8 @@ // overrun. Actual device can skip more, then this module stops the packet streaming. #define IR_JUMBO_PAYLOAD_MAX_SKIP_CYCLES 5 +static void pcm_period_work(struct work_struct *work); + /** * amdtp_stream_init - initialize an AMDTP stream structure * @s: the AMDTP stream to initialize @@ -105,6 +107,7 @@ int amdtp_stream_init(struct amdtp_stream *s, struct fw_unit *unit, s->flags = flags; s->context = ERR_PTR(-1); mutex_init(&s->mutex); + INIT_WORK(&s->period_work, pcm_period_work); s->packet_index = 0; init_waitqueue_head(&s->ready_wait); @@ -347,6 +350,7 @@ EXPORT_SYMBOL(amdtp_stream_get_max_payload); */ void amdtp_stream_pcm_prepare(struct amdtp_stream *s) { + cancel_work_sync(&s->period_work); s->pcm_buffer_pointer = 0; s->pcm_period_pointer = 0; } @@ -611,19 +615,21 @@ static void update_pcm_pointers(struct amdtp_stream *s, // The program in user process should periodically check the status of intermediate // buffer associated to PCM substream to process PCM frames in the buffer, instead // of receiving notification of period elapsed by poll wait. - if (!pcm->runtime->no_period_wakeup) { - if (in_softirq()) { - // In software IRQ context for 1394 OHCI. - snd_pcm_period_elapsed(pcm); - } else { - // In process context of ALSA PCM application under acquired lock of - // PCM substream. - snd_pcm_period_elapsed_under_stream_lock(pcm); - } - } + if (!pcm->runtime->no_period_wakeup) + queue_work(system_highpri_wq, &s->period_work); } } +static void pcm_period_work(struct work_struct *work) +{ + struct amdtp_stream *s = container_of(work, struct amdtp_stream, + period_work); + struct snd_pcm_substream *pcm = READ_ONCE(s->pcm); + + if (pcm) + snd_pcm_period_elapsed(pcm); +} + static int queue_packet(struct amdtp_stream *s, struct fw_iso_packet *params, bool sched_irq) { @@ -1849,11 +1855,14 @@ unsigned long amdtp_domain_stream_pcm_pointer(struct amdtp_domain *d, { struct amdtp_stream *irq_target = d->irq_target; - // Process isochronous packets queued till recent isochronous cycle to handle PCM frames. if (irq_target && amdtp_stream_running(irq_target)) { - // In software IRQ context, the call causes dead-lock to disable the tasklet - // synchronously. - if (!in_softirq()) + // use wq to prevent AB/BA deadlock competition for + // substream lock: + // fw_iso_context_flush_completions() acquires + // lock by ohci_flush_iso_completions(), + // amdtp-stream process_rx_packets() attempts to + // acquire same lock by snd_pcm_elapsed() + if (current_work() != &s->period_work) fw_iso_context_flush_completions(irq_target->context); } @@ -1909,6 +1918,7 @@ static void amdtp_stream_stop(struct amdtp_stream *s) return; } + cancel_work_sync(&s->period_work); fw_iso_context_stop(s->context); fw_iso_context_destroy(s->context); s->context = ERR_PTR(-1); diff --git a/sound/firewire/amdtp-stream.h b/sound/firewire/amdtp-stream.h index a1ed2e80f91a7c..775db3fc4959f5 100644 --- a/sound/firewire/amdtp-stream.h +++ b/sound/firewire/amdtp-stream.h @@ -191,6 +191,7 @@ struct amdtp_stream { /* For a PCM substream processing. */ struct snd_pcm_substream *pcm; + struct work_struct period_work; snd_pcm_uframes_t pcm_buffer_pointer; unsigned int pcm_period_pointer; unsigned int pcm_frame_multiplier; diff --git a/sound/hda/intel-dsp-config.c b/sound/hda/intel-dsp-config.c index 913880b090657f..f018bd77986243 100644 --- a/sound/hda/intel-dsp-config.c +++ b/sound/hda/intel-dsp-config.c @@ -56,35 +56,31 @@ static const struct config_entry config_table[] = { }, #endif /* - * Apollolake (Broxton-P) + * Skylake, Kabylake, Apollolake * the legacy HDAudio driver is used except on Up Squared (SOF) and * Chromebooks (SST), as well as devices based on the ES8336 codec */ -#if IS_ENABLED(CONFIG_SND_SOC_SOF_APOLLOLAKE) +#if IS_ENABLED(CONFIG_SND_SOC_INTEL_AVS) { - .flags = FLAG_SOF, - .device = PCI_DEVICE_ID_INTEL_HDA_APL, + .flags = FLAG_SST, + .device = PCI_DEVICE_ID_INTEL_HDA_SKL_LP, .dmi_table = (const struct dmi_system_id []) { { - .ident = "Up Squared", + .ident = "Google Chromebooks", .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "AAEON"), - DMI_MATCH(DMI_BOARD_NAME, "UP-APL01"), + DMI_MATCH(DMI_SYS_VENDOR, "Google"), } }, {} } }, { - .flags = FLAG_SOF, - .device = PCI_DEVICE_ID_INTEL_HDA_APL, - .codec_hid = &essx_83x6, + .flags = FLAG_SST | FLAG_SST_ONLY_IF_DMIC, + .device = PCI_DEVICE_ID_INTEL_HDA_SKL_LP, }, -#endif -#if IS_ENABLED(CONFIG_SND_SOC_INTEL_APL) { .flags = FLAG_SST, - .device = PCI_DEVICE_ID_INTEL_HDA_APL, + .device = PCI_DEVICE_ID_INTEL_HDA_KBL_LP, .dmi_table = (const struct dmi_system_id []) { { .ident = "Google Chromebooks", @@ -95,17 +91,13 @@ static const struct config_entry config_table[] = { {} } }, -#endif -/* - * Skylake and Kabylake use legacy HDAudio driver except for Google - * Chromebooks (SST) - */ - -/* Sunrise Point-LP */ -#if IS_ENABLED(CONFIG_SND_SOC_INTEL_SKL) + { + .flags = FLAG_SST | FLAG_SST_ONLY_IF_DMIC, + .device = PCI_DEVICE_ID_INTEL_HDA_KBL_LP, + }, { .flags = FLAG_SST, - .device = PCI_DEVICE_ID_INTEL_HDA_SKL_LP, + .device = PCI_DEVICE_ID_INTEL_HDA_APL, .dmi_table = (const struct dmi_system_id []) { { .ident = "Google Chromebooks", @@ -116,29 +108,26 @@ static const struct config_entry config_table[] = { {} } }, - { - .flags = FLAG_SST | FLAG_SST_ONLY_IF_DMIC, - .device = PCI_DEVICE_ID_INTEL_HDA_SKL_LP, - }, #endif -/* Kabylake-LP */ -#if IS_ENABLED(CONFIG_SND_SOC_INTEL_KBL) +#if IS_ENABLED(CONFIG_SND_SOC_SOF_APOLLOLAKE) { - .flags = FLAG_SST, - .device = PCI_DEVICE_ID_INTEL_HDA_KBL_LP, + .flags = FLAG_SOF, + .device = PCI_DEVICE_ID_INTEL_HDA_APL, .dmi_table = (const struct dmi_system_id []) { { - .ident = "Google Chromebooks", + .ident = "Up Squared", .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Google"), + DMI_MATCH(DMI_SYS_VENDOR, "AAEON"), + DMI_MATCH(DMI_BOARD_NAME, "UP-APL01"), } }, {} } }, { - .flags = FLAG_SST | FLAG_SST_ONLY_IF_DMIC, - .device = PCI_DEVICE_ID_INTEL_HDA_KBL_LP, + .flags = FLAG_SOF, + .device = PCI_DEVICE_ID_INTEL_HDA_APL, + .codec_hid = &essx_83x6, }, #endif diff --git a/sound/i2c/cs8427.c b/sound/i2c/cs8427.c index f58b14b4904550..29a1a7a0d050c6 100644 --- a/sound/i2c/cs8427.c +++ b/sound/i2c/cs8427.c @@ -52,8 +52,9 @@ int snd_cs8427_reg_write(struct snd_i2c_device *device, unsigned char reg, buf[1] = val; err = snd_i2c_sendbytes(device, buf, 2); if (err != 2) { - snd_printk(KERN_ERR "unable to send bytes 0x%02x:0x%02x " - "to CS8427 (%i)\n", buf[0], buf[1], err); + dev_err(device->bus->card->dev, + "unable to send bytes 0x%02x:0x%02x to CS8427 (%i)\n", + buf[0], buf[1], err); return err < 0 ? err : -EIO; } return 0; @@ -68,14 +69,14 @@ static int snd_cs8427_reg_read(struct snd_i2c_device *device, unsigned char reg) err = snd_i2c_sendbytes(device, ®, 1); if (err != 1) { - snd_printk(KERN_ERR "unable to send register 0x%x byte " - "to CS8427\n", reg); + dev_err(device->bus->card->dev, + "unable to send register 0x%x byte to CS8427\n", reg); return err < 0 ? err : -EIO; } err = snd_i2c_readbytes(device, &buf, 1); if (err != 1) { - snd_printk(KERN_ERR "unable to read register 0x%x byte " - "from CS8427\n", reg); + dev_err(device->bus->card->dev, + "unable to read register 0x%x byte from CS8427\n", reg); return err < 0 ? err : -EIO; } return buf; @@ -195,16 +196,18 @@ int snd_cs8427_init(struct snd_i2c_bus *bus, err = snd_cs8427_reg_read(device, CS8427_REG_ID_AND_VER); if (err != CS8427_VER8427A) { /* give second chance */ - snd_printk(KERN_WARNING "invalid CS8427 signature 0x%x: " - "let me try again...\n", err); + dev_warn(device->bus->card->dev, + "invalid CS8427 signature 0x%x: let me try again...\n", + err); err = snd_cs8427_reg_read(device, CS8427_REG_ID_AND_VER); } if (err != CS8427_VER8427A) { snd_i2c_unlock(bus); - snd_printk(KERN_ERR "unable to find CS8427 signature " - "(expected 0x%x, read 0x%x),\n", - CS8427_VER8427A, err); - snd_printk(KERN_ERR " initialization is not completed\n"); + dev_err(device->bus->card->dev, + "unable to find CS8427 signature (expected 0x%x, read 0x%x),\n", + CS8427_VER8427A, err); + dev_err(device->bus->card->dev, + " initialization is not completed\n"); return -EFAULT; } /* turn off run bit while making changes to configuration */ @@ -289,7 +292,7 @@ int snd_cs8427_create(struct snd_i2c_bus *bus, snd_i2c_sendbytes(device, buf, 1); snd_i2c_readbytes(device, buf, 127); for (xx = 0; xx < 127; xx++) - printk(KERN_DEBUG "reg[0x%x] = 0x%x\n", xx+1, buf[xx]); + dev_dbg(device->bus->card->dev, "reg[0x%x] = 0x%x\n", xx+1, buf[xx]); } #endif @@ -392,15 +395,15 @@ static int snd_cs8427_qsubcode_get(struct snd_kcontrol *kcontrol, snd_i2c_lock(device->bus); err = snd_i2c_sendbytes(device, ®, 1); if (err != 1) { - snd_printk(KERN_ERR "unable to send register 0x%x byte " - "to CS8427\n", reg); + dev_err(device->bus->card->dev, + "unable to send register 0x%x byte to CS8427\n", reg); snd_i2c_unlock(device->bus); return err < 0 ? err : -EIO; } err = snd_i2c_readbytes(device, ucontrol->value.bytes.data, 10); if (err != 10) { - snd_printk(KERN_ERR "unable to read Q-subcode bytes " - "from CS8427\n"); + dev_err(device->bus->card->dev, + "unable to read Q-subcode bytes from CS8427\n"); snd_i2c_unlock(device->bus); return err < 0 ? err : -EIO; } diff --git a/sound/i2c/other/ak4113.c b/sound/i2c/other/ak4113.c index e7213092eb4fb6..c1f7447a4d11de 100644 --- a/sound/i2c/other/ak4113.c +++ b/sound/i2c/other/ak4113.c @@ -599,8 +599,6 @@ int snd_ak4113_check_rate_and_errors(struct ak4113 *ak4113, unsigned int flags) (runtime->rate != res)) { snd_pcm_stream_lock_irqsave(ak4113->substream, _flags); if (snd_pcm_running(ak4113->substream)) { - /*printk(KERN_DEBUG "rate changed (%i <- %i)\n", - * runtime->rate, res); */ snd_pcm_stop(ak4113->substream, SNDRV_PCM_STATE_DRAINING); wake_up(&runtime->sleep); diff --git a/sound/i2c/other/ak4114.c b/sound/i2c/other/ak4114.c index c0cffe28989b13..7c493681f3cb6e 100644 --- a/sound/i2c/other/ak4114.c +++ b/sound/i2c/other/ak4114.c @@ -38,17 +38,6 @@ static inline unsigned char reg_read(struct ak4114 *ak4114, unsigned char reg) return ak4114->read(ak4114->private_data, reg); } -#if 0 -static void reg_dump(struct ak4114 *ak4114) -{ - int i; - - printk(KERN_DEBUG "AK4114 REG DUMP:\n"); - for (i = 0; i < 0x20; i++) - printk(KERN_DEBUG "reg[%02x] = %02x (%02x)\n", i, reg_read(ak4114, i), i < ARRAY_SIZE(ak4114->regmap) ? ak4114->regmap[i] : 0); -} -#endif - static void snd_ak4114_free(struct ak4114 *chip) { atomic_inc(&chip->wq_processing); /* don't schedule new work */ @@ -589,7 +578,6 @@ int snd_ak4114_check_rate_and_errors(struct ak4114 *ak4114, unsigned int flags) if (!(flags & AK4114_CHECK_NO_RATE) && runtime && runtime->rate != res) { snd_pcm_stream_lock_irqsave(ak4114->capture_substream, _flags); if (snd_pcm_running(ak4114->capture_substream)) { - // printk(KERN_DEBUG "rate changed (%i <- %i)\n", runtime->rate, res); snd_pcm_stop(ak4114->capture_substream, SNDRV_PCM_STATE_DRAINING); res = 1; } diff --git a/sound/i2c/other/ak4117.c b/sound/i2c/other/ak4117.c index 640501bb3ca633..165fdda8fda507 100644 --- a/sound/i2c/other/ak4117.c +++ b/sound/i2c/other/ak4117.c @@ -34,17 +34,6 @@ static inline unsigned char reg_read(struct ak4117 *ak4117, unsigned char reg) return ak4117->read(ak4117->private_data, reg); } -#if 0 -static void reg_dump(struct ak4117 *ak4117) -{ - int i; - - printk(KERN_DEBUG "AK4117 REG DUMP:\n"); - for (i = 0; i < 0x1b; i++) - printk(KERN_DEBUG "reg[%02x] = %02x (%02x)\n", i, reg_read(ak4117, i), i < sizeof(ak4117->regmap) ? ak4117->regmap[i] : 0); -} -#endif - static void snd_ak4117_free(struct ak4117 *chip) { timer_shutdown_sync(&chip->timer); @@ -452,7 +441,6 @@ int snd_ak4117_check_rate_and_errors(struct ak4117 *ak4117, unsigned int flags) goto __rate; rcs0 = reg_read(ak4117, AK4117_REG_RCS0); rcs2 = reg_read(ak4117, AK4117_REG_RCS2); - // printk(KERN_DEBUG "AK IRQ: rcs0 = 0x%x, rcs1 = 0x%x, rcs2 = 0x%x\n", rcs0, rcs1, rcs2); spin_lock_irqsave(&ak4117->lock, _flags); if (rcs0 & AK4117_PAR) ak4117->errors[AK4117_PARITY_ERRORS]++; @@ -505,7 +493,6 @@ int snd_ak4117_check_rate_and_errors(struct ak4117 *ak4117, unsigned int flags) if (!(flags & AK4117_CHECK_NO_RATE) && runtime && runtime->rate != res) { snd_pcm_stream_lock_irqsave(ak4117->substream, _flags); if (snd_pcm_running(ak4117->substream)) { - // printk(KERN_DEBUG "rate changed (%i <- %i)\n", runtime->rate, res); snd_pcm_stop(ak4117->substream, SNDRV_PCM_STATE_DRAINING); wake_up(&runtime->sleep); res = 1; diff --git a/sound/i2c/other/ak4xxx-adda.c b/sound/i2c/other/ak4xxx-adda.c index 7d15093844b923..b24c80410d45e3 100644 --- a/sound/i2c/other/ak4xxx-adda.c +++ b/sound/i2c/other/ak4xxx-adda.c @@ -391,8 +391,6 @@ static int put_ak_reg(struct snd_kcontrol *kcontrol, int addr, nval = mask - nval; if (AK_GET_NEEDSMSB(kcontrol->private_value)) nval |= 0x80; - /* printk(KERN_DEBUG "DEBUG - AK writing reg: chip %x addr %x, - nval %x\n", chip, addr, nval); */ snd_akm4xxx_write(ak, chip, addr, nval); return 1; } diff --git a/sound/i2c/other/pt2258.c b/sound/i2c/other/pt2258.c index c913f223892ac0..ba38c285241c08 100644 --- a/sound/i2c/other/pt2258.c +++ b/sound/i2c/other/pt2258.c @@ -63,7 +63,7 @@ int snd_pt2258_reset(struct snd_pt2258 *pt) __error: snd_i2c_unlock(pt->i2c_bus); - snd_printk(KERN_ERR "PT2258 reset failed\n"); + dev_err(pt->card->dev, "PT2258 reset failed\n"); return -EIO; } @@ -124,7 +124,7 @@ static int pt2258_stereo_volume_put(struct snd_kcontrol *kcontrol, __error: snd_i2c_unlock(pt->i2c_bus); - snd_printk(KERN_ERR "PT2258 access failed\n"); + dev_err(pt->card->dev, "PT2258 access failed\n"); return -EIO; } @@ -161,7 +161,7 @@ static int pt2258_switch_put(struct snd_kcontrol *kcontrol, __error: snd_i2c_unlock(pt->i2c_bus); - snd_printk(KERN_ERR "PT2258 access failed 2\n"); + dev_err(pt->card->dev, "PT2258 access failed 2\n"); return -EIO; } diff --git a/sound/i2c/tea6330t.c b/sound/i2c/tea6330t.c index 037d6293f72848..676d5805494472 100644 --- a/sound/i2c/tea6330t.c +++ b/sound/i2c/tea6330t.c @@ -56,9 +56,6 @@ int snd_tea6330t_detect(struct snd_i2c_bus *bus, int equalizer) static void snd_tea6330t_set(struct tea6330t *tea, unsigned char addr, unsigned char value) { -#if 0 - printk(KERN_DEBUG "set - 0x%x/0x%x\n", addr, value); -#endif snd_i2c_write(tea->bus, TEA6330T_ADDR, addr, value, 1); } #endif diff --git a/sound/isa/ad1816a/ad1816a.c b/sound/isa/ad1816a/ad1816a.c index 9ac873773129a9..99006dc4777e91 100644 --- a/sound/isa/ad1816a/ad1816a.c +++ b/sound/isa/ad1816a/ad1816a.c @@ -17,8 +17,6 @@ #include #include -#define PFX "ad1816a: " - MODULE_AUTHOR("Massimo Piccioni "); MODULE_DESCRIPTION("AD1816A, AD1815"); MODULE_LICENSE("GPL"); @@ -87,7 +85,7 @@ static int snd_card_ad1816a_pnp(int dev, struct pnp_card_link *card, err = pnp_activate_dev(pdev); if (err < 0) { - printk(KERN_ERR PFX "AUDIO PnP configure failure\n"); + dev_err(&pdev->dev, "AUDIO PnP configure failure\n"); return -EBUSY; } @@ -100,13 +98,13 @@ static int snd_card_ad1816a_pnp(int dev, struct pnp_card_link *card, pdev = pnp_request_card_device(card, id->devs[1].id, NULL); if (pdev == NULL) { mpu_port[dev] = -1; - snd_printk(KERN_WARNING PFX "MPU401 device busy, skipping.\n"); + dev_warn(&pdev->dev, "MPU401 device busy, skipping.\n"); return 0; } err = pnp_activate_dev(pdev); if (err < 0) { - printk(KERN_ERR PFX "MPU401 PnP configure failure\n"); + dev_err(&pdev->dev, "MPU401 PnP configure failure\n"); mpu_port[dev] = -1; } else { mpu_port[dev] = pnp_port_start(pdev, 0); @@ -166,14 +164,16 @@ static int snd_card_ad1816a_probe(int dev, struct pnp_card_link *pcard, if (snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, mpu_port[dev], 0, mpu_irq[dev], NULL) < 0) - printk(KERN_ERR PFX "no MPU-401 device at 0x%lx.\n", mpu_port[dev]); + dev_err(card->dev, "no MPU-401 device at 0x%lx.\n", + mpu_port[dev]); } if (fm_port[dev] > 0) { if (snd_opl3_create(card, fm_port[dev], fm_port[dev] + 2, OPL3_HW_AUTO, 0, &opl3) < 0) { - printk(KERN_ERR PFX "no OPL device at 0x%lx-0x%lx.\n", fm_port[dev], fm_port[dev] + 2); + dev_err(card->dev, "no OPL device at 0x%lx-0x%lx.\n", + fm_port[dev], fm_port[dev] + 2); } else { error = snd_opl3_hwdep_new(opl3, 0, 1, NULL); if (error < 0) @@ -252,7 +252,7 @@ static int __init alsa_card_ad1816a_init(void) if (!ad1816a_devices) { pnp_unregister_card_driver(&ad1816a_pnpc_driver); #ifdef MODULE - printk(KERN_ERR "no AD1816A based soundcards found.\n"); + pr_err("no AD1816A based soundcards found.\n"); #endif /* MODULE */ return -ENODEV; } diff --git a/sound/isa/ad1816a/ad1816a_lib.c b/sound/isa/ad1816a/ad1816a_lib.c index 132a095dca2c93..2b87036cb94fba 100644 --- a/sound/isa/ad1816a/ad1816a_lib.c +++ b/sound/isa/ad1816a/ad1816a_lib.c @@ -25,7 +25,7 @@ static inline int snd_ad1816a_busy_wait(struct snd_ad1816a *chip) if (inb(AD1816A_REG(AD1816A_CHIP_STATUS)) & AD1816A_READY) return 0; - snd_printk(KERN_WARNING "chip busy.\n"); + dev_warn(chip->card->dev, "chip busy.\n"); return -EBUSY; } @@ -186,7 +186,7 @@ static int snd_ad1816a_trigger(struct snd_ad1816a *chip, unsigned char what, spin_unlock(&chip->lock); break; default: - snd_printk(KERN_WARNING "invalid trigger mode 0x%x.\n", what); + dev_warn(chip->card->dev, "invalid trigger mode 0x%x.\n", what); error = -EINVAL; } @@ -548,8 +548,8 @@ static const char *snd_ad1816a_chip_id(struct snd_ad1816a *chip) case AD1816A_HW_AD1815: return "AD1815"; case AD1816A_HW_AD18MAX10: return "AD18max10"; default: - snd_printk(KERN_WARNING "Unknown chip version %d:%d.\n", - chip->version, chip->hardware); + dev_warn(chip->card->dev, "Unknown chip version %d:%d.\n", + chip->version, chip->hardware); return "AD1816A - unknown"; } } @@ -566,23 +566,23 @@ int snd_ad1816a_create(struct snd_card *card, chip->res_port = devm_request_region(card->dev, port, 16, "AD1816A"); if (!chip->res_port) { - snd_printk(KERN_ERR "ad1816a: can't grab port 0x%lx\n", port); + dev_err(card->dev, "ad1816a: can't grab port 0x%lx\n", port); return -EBUSY; } if (devm_request_irq(card->dev, irq, snd_ad1816a_interrupt, 0, "AD1816A", (void *) chip)) { - snd_printk(KERN_ERR "ad1816a: can't grab IRQ %d\n", irq); + dev_err(card->dev, "ad1816a: can't grab IRQ %d\n", irq); return -EBUSY; } chip->irq = irq; card->sync_irq = chip->irq; if (snd_devm_request_dma(card->dev, dma1, "AD1816A - 1")) { - snd_printk(KERN_ERR "ad1816a: can't grab DMA1 %d\n", dma1); + dev_err(card->dev, "ad1816a: can't grab DMA1 %d\n", dma1); return -EBUSY; } chip->dma1 = dma1; if (snd_devm_request_dma(card->dev, dma2, "AD1816A - 2")) { - snd_printk(KERN_ERR "ad1816a: can't grab DMA2 %d\n", dma2); + dev_err(card->dev, "ad1816a: can't grab DMA2 %d\n", dma2); return -EBUSY; } chip->dma2 = dma2; diff --git a/sound/isa/als100.c b/sound/isa/als100.c index d582eff6408247..e70dbf0b099ab9 100644 --- a/sound/isa/als100.c +++ b/sound/isa/als100.c @@ -23,8 +23,6 @@ #include #include -#define PFX "als100: " - MODULE_DESCRIPTION("Avance Logic ALS007/ALS1X0"); MODULE_AUTHOR("Massimo Piccioni "); MODULE_LICENSE("GPL"); @@ -112,7 +110,7 @@ static int snd_card_als100_pnp(int dev, struct snd_card_als100 *acard, err = pnp_activate_dev(pdev); if (err < 0) { - snd_printk(KERN_ERR PFX "AUDIO pnp configure failure\n"); + dev_err(&pdev->dev, "AUDIO pnp configure failure\n"); return err; } port[dev] = pnp_port_start(pdev, 0); @@ -135,7 +133,7 @@ static int snd_card_als100_pnp(int dev, struct snd_card_als100 *acard, __mpu_error: if (pdev) { pnp_release_card_device(pdev); - snd_printk(KERN_ERR PFX "MPU401 pnp configure failure, skipping\n"); + dev_err(&pdev->dev, "MPU401 pnp configure failure, skipping\n"); } acard->devmpu = NULL; mpu_port[dev] = -1; @@ -151,7 +149,7 @@ static int snd_card_als100_pnp(int dev, struct snd_card_als100 *acard, __fm_error: if (pdev) { pnp_release_card_device(pdev); - snd_printk(KERN_ERR PFX "OPL3 pnp configure failure, skipping\n"); + dev_err(&pdev->dev, "OPL3 pnp configure failure, skipping\n"); } acard->devopl = NULL; fm_port[dev] = -1; @@ -230,15 +228,15 @@ static int snd_card_als100_probe(int dev, mpu_port[dev], 0, mpu_irq[dev], NULL) < 0) - snd_printk(KERN_ERR PFX "no MPU-401 device at 0x%lx\n", mpu_port[dev]); + dev_err(card->dev, "no MPU-401 device at 0x%lx\n", mpu_port[dev]); } if (fm_port[dev] > 0 && fm_port[dev] != SNDRV_AUTO_PORT) { if (snd_opl3_create(card, fm_port[dev], fm_port[dev] + 2, OPL3_HW_AUTO, 0, &opl3) < 0) { - snd_printk(KERN_ERR PFX "no OPL device at 0x%lx-0x%lx\n", - fm_port[dev], fm_port[dev] + 2); + dev_err(card->dev, "no OPL device at 0x%lx-0x%lx\n", + fm_port[dev], fm_port[dev] + 2); } else { error = snd_opl3_timer_new(opl3, 0, 1); if (error < 0) @@ -324,7 +322,7 @@ static int __init alsa_card_als100_init(void) if (!als100_devices) { pnp_unregister_card_driver(&als100_pnpc_driver); #ifdef MODULE - snd_printk(KERN_ERR "no Avance Logic based soundcards found\n"); + pr_err("no Avance Logic based soundcards found\n"); #endif return -ENODEV; } diff --git a/sound/isa/azt2320.c b/sound/isa/azt2320.c index 761cd198df2b0e..b937c9138d1248 100644 --- a/sound/isa/azt2320.c +++ b/sound/isa/azt2320.c @@ -30,8 +30,6 @@ #include #include -#define PFX "azt2320: " - MODULE_AUTHOR("Massimo Piccioni "); MODULE_DESCRIPTION("Aztech Systems AZT2320"); MODULE_LICENSE("GPL"); @@ -99,7 +97,7 @@ static int snd_card_azt2320_pnp(int dev, struct snd_card_azt2320 *acard, err = pnp_activate_dev(pdev); if (err < 0) { - snd_printk(KERN_ERR PFX "AUDIO pnp configure failure\n"); + dev_err(&pdev->dev, "AUDIO pnp configure failure\n"); return err; } port[dev] = pnp_port_start(pdev, 0); @@ -120,7 +118,7 @@ static int snd_card_azt2320_pnp(int dev, struct snd_card_azt2320 *acard, __mpu_error: if (pdev) { pnp_release_card_device(pdev); - snd_printk(KERN_ERR PFX "MPU401 pnp configure failure, skipping\n"); + dev_err(&pdev->dev, "MPU401 pnp configure failure, skipping\n"); } acard->devmpu = NULL; mpu_port[dev] = -1; @@ -210,15 +208,15 @@ static int snd_card_azt2320_probe(int dev, if (snd_mpu401_uart_new(card, 0, MPU401_HW_AZT2320, mpu_port[dev], 0, mpu_irq[dev], NULL) < 0) - snd_printk(KERN_ERR PFX "no MPU-401 device at 0x%lx\n", mpu_port[dev]); + dev_err(card->dev, "no MPU-401 device at 0x%lx\n", mpu_port[dev]); } if (fm_port[dev] > 0 && fm_port[dev] != SNDRV_AUTO_PORT) { if (snd_opl3_create(card, fm_port[dev], fm_port[dev] + 2, OPL3_HW_AUTO, 0, &opl3) < 0) { - snd_printk(KERN_ERR PFX "no OPL device at 0x%lx-0x%lx\n", - fm_port[dev], fm_port[dev] + 2); + dev_err(card->dev, "no OPL device at 0x%lx-0x%lx\n", + fm_port[dev], fm_port[dev] + 2); } else { error = snd_opl3_timer_new(opl3, 1, 2); if (error < 0) @@ -303,7 +301,7 @@ static int __init alsa_card_azt2320_init(void) if (!azt2320_devices) { pnp_unregister_card_driver(&azt2320_pnpc_driver); #ifdef MODULE - snd_printk(KERN_ERR "no AZT2320 based soundcards found\n"); + pr_err("no AZT2320 based soundcards found\n"); #endif return -ENODEV; } diff --git a/sound/isa/cmi8328.c b/sound/isa/cmi8328.c index 8902cfb830f7af..d30cce4cc7e39d 100644 --- a/sound/isa/cmi8328.c +++ b/sound/isa/cmi8328.c @@ -159,7 +159,7 @@ static int snd_cmi8328_mixer(struct snd_wss *chip) strcpy(id2.name, "CD Playback Switch"); err = snd_ctl_rename_id(card, &id1, &id2); if (err < 0) { - snd_printk(KERN_ERR "error renaming control\n"); + dev_err(card->dev, "error renaming control\n"); return err; } /* rename AUX0 volume to CD */ @@ -167,7 +167,7 @@ static int snd_cmi8328_mixer(struct snd_wss *chip) strcpy(id2.name, "CD Playback Volume"); err = snd_ctl_rename_id(card, &id1, &id2); if (err < 0) { - snd_printk(KERN_ERR "error renaming control\n"); + dev_err(card->dev, "error renaming control\n"); return err; } /* rename AUX1 switch to Synth */ @@ -176,7 +176,7 @@ static int snd_cmi8328_mixer(struct snd_wss *chip) strcpy(id2.name, "Synth Playback Switch"); err = snd_ctl_rename_id(card, &id1, &id2); if (err < 0) { - snd_printk(KERN_ERR "error renaming control\n"); + dev_err(card->dev, "error renaming control\n"); return err; } /* rename AUX1 volume to Synth */ @@ -185,7 +185,7 @@ static int snd_cmi8328_mixer(struct snd_wss *chip) strcpy(id2.name, "Synth Playback Volume"); err = snd_ctl_rename_id(card, &id1, &id2); if (err < 0) { - snd_printk(KERN_ERR "error renaming control\n"); + dev_err(card->dev, "error renaming control\n"); return err; } @@ -251,35 +251,35 @@ static int snd_cmi8328_probe(struct device *pdev, unsigned int ndev) if (irq[ndev] == SNDRV_AUTO_IRQ) { irq[ndev] = snd_legacy_find_free_irq(irqs); if (irq[ndev] < 0) { - snd_printk(KERN_ERR "unable to find a free IRQ\n"); + dev_err(pdev, "unable to find a free IRQ\n"); return -EBUSY; } } if (dma1[ndev] == SNDRV_AUTO_DMA) { dma1[ndev] = snd_legacy_find_free_dma(dma1s); if (dma1[ndev] < 0) { - snd_printk(KERN_ERR "unable to find a free DMA1\n"); + dev_err(pdev, "unable to find a free DMA1\n"); return -EBUSY; } } if (dma2[ndev] == SNDRV_AUTO_DMA) { dma2[ndev] = snd_legacy_find_free_dma(dma2s[dma1[ndev] % 4]); if (dma2[ndev] < 0) { - snd_printk(KERN_WARNING "unable to find a free DMA2, full-duplex will not work\n"); + dev_warn(pdev, "unable to find a free DMA2, full-duplex will not work\n"); dma2[ndev] = -1; } } /* configure WSS IRQ... */ pos = array_find(irqs, irq[ndev]); if (pos < 0) { - snd_printk(KERN_ERR "invalid IRQ %d\n", irq[ndev]); + dev_err(pdev, "invalid IRQ %d\n", irq[ndev]); return -EINVAL; } val = irq_bits[pos] << 3; /* ...and DMA... */ pos = array_find(dma1s, dma1[ndev]); if (pos < 0) { - snd_printk(KERN_ERR "invalid DMA1 %d\n", dma1[ndev]); + dev_err(pdev, "invalid DMA1 %d\n", dma1[ndev]); return -EINVAL; } val |= dma_bits[pos]; @@ -287,7 +287,7 @@ static int snd_cmi8328_probe(struct device *pdev, unsigned int ndev) if (dma2[ndev] >= 0 && dma1[ndev] != dma2[ndev]) { pos = array_find(dma2s[dma1[ndev]], dma2[ndev]); if (pos < 0) { - snd_printk(KERN_ERR "invalid DMA2 %d\n", dma2[ndev]); + dev_err(pdev, "invalid DMA2 %d\n", dma2[ndev]); return -EINVAL; } val |= 0x04; /* enable separate capture DMA */ @@ -320,47 +320,47 @@ static int snd_cmi8328_probe(struct device *pdev, unsigned int ndev) return err; if (snd_wss_timer(cmi->wss, 0) < 0) - snd_printk(KERN_WARNING "error initializing WSS timer\n"); + dev_warn(pdev, "error initializing WSS timer\n"); if (mpuport[ndev] == SNDRV_AUTO_PORT) { mpuport[ndev] = snd_legacy_find_free_ioport(mpu_ports, 2); if (mpuport[ndev] < 0) - snd_printk(KERN_ERR "unable to find a free MPU401 port\n"); + dev_err(pdev, "unable to find a free MPU401 port\n"); } if (mpuirq[ndev] == SNDRV_AUTO_IRQ) { mpuirq[ndev] = snd_legacy_find_free_irq(mpu_irqs); if (mpuirq[ndev] < 0) - snd_printk(KERN_ERR "unable to find a free MPU401 IRQ\n"); + dev_err(pdev, "unable to find a free MPU401 IRQ\n"); } /* enable and configure MPU401 */ if (mpuport[ndev] > 0 && mpuirq[ndev] > 0) { val = CFG2_MPU_ENABLE; pos = array_find_l(mpu_ports, mpuport[ndev]); if (pos < 0) - snd_printk(KERN_WARNING "invalid MPU401 port 0x%lx\n", - mpuport[ndev]); + dev_warn(pdev, "invalid MPU401 port 0x%lx\n", + mpuport[ndev]); else { val |= mpu_port_bits[pos] << 5; pos = array_find(mpu_irqs, mpuirq[ndev]); if (pos < 0) - snd_printk(KERN_WARNING "invalid MPU401 IRQ %d\n", - mpuirq[ndev]); + dev_warn(pdev, "invalid MPU401 IRQ %d\n", + mpuirq[ndev]); else { val |= mpu_irq_bits[pos] << 3; snd_cmi8328_cfg_write(port, CFG2, val); if (snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, mpuport[ndev], 0, mpuirq[ndev], NULL) < 0) - snd_printk(KERN_ERR "error initializing MPU401\n"); + dev_err(pdev, "error initializing MPU401\n"); } } } /* OPL3 is hardwired to 0x388 and cannot be disabled */ if (snd_opl3_create(card, 0x388, 0x38a, OPL3_HW_AUTO, 0, &opl3) < 0) - snd_printk(KERN_ERR "error initializing OPL3\n"); + dev_err(pdev, "error initializing OPL3\n"); else if (snd_opl3_hwdep_new(opl3, 0, 1, NULL) < 0) - snd_printk(KERN_WARNING "error initializing OPL3 hwdep\n"); + dev_warn(pdev, "error initializing OPL3 hwdep\n"); strcpy(card->driver, "CMI8328"); strcpy(card->shortname, "C-Media CMI8328"); @@ -378,7 +378,7 @@ static int snd_cmi8328_probe(struct device *pdev, unsigned int ndev) /* gameport is hardwired to 0x200 */ res = devm_request_region(pdev, 0x200, 8, "CMI8328 gameport"); if (!res) - snd_printk(KERN_WARNING "unable to allocate gameport I/O port\n"); + dev_warn(pdev, "unable to allocate gameport I/O port\n"); else { struct gameport *gp = cmi->gameport = gameport_allocate_port(); if (cmi->gameport) { diff --git a/sound/isa/cmi8330.c b/sound/isa/cmi8330.c index f209b16c522901..25b4dc181089c1 100644 --- a/sound/isa/cmi8330.c +++ b/sound/isa/cmi8330.c @@ -342,7 +342,7 @@ static int snd_cmi8330_pnp(int dev, struct snd_cmi8330 *acard, err = pnp_activate_dev(pdev); if (err < 0) { - snd_printk(KERN_ERR "AD1848 PnP configure failure\n"); + dev_err(&pdev->dev, "AD1848 PnP configure failure\n"); return -EBUSY; } wssport[dev] = pnp_port_start(pdev, 0); @@ -356,7 +356,7 @@ static int snd_cmi8330_pnp(int dev, struct snd_cmi8330 *acard, err = pnp_activate_dev(pdev); if (err < 0) { - snd_printk(KERN_ERR "SB16 PnP configure failure\n"); + dev_err(&pdev->dev, "SB16 PnP configure failure\n"); return -EBUSY; } sbport[dev] = pnp_port_start(pdev, 0); @@ -376,7 +376,7 @@ static int snd_cmi8330_pnp(int dev, struct snd_cmi8330 *acard, err = pnp_activate_dev(pdev); if (err < 0) - snd_printk(KERN_ERR "MPU-401 PnP configure failure: will be disabled\n"); + dev_err(&pdev->dev, "MPU-401 PnP configure failure: will be disabled\n"); else { mpuport[dev] = pnp_port_start(pdev, 0); mpuirq[dev] = pnp_irq(pdev, 0); @@ -498,8 +498,6 @@ static int snd_cmi8330_resume(struct snd_card *card) #define is_isapnp_selected(dev) 0 #endif -#define PFX "cmi8330: " - static int snd_cmi8330_card_new(struct device *pdev, int dev, struct snd_card **cardp) { @@ -510,7 +508,7 @@ static int snd_cmi8330_card_new(struct device *pdev, int dev, err = snd_devm_card_new(pdev, index[dev], id[dev], THIS_MODULE, sizeof(struct snd_cmi8330), &card); if (err < 0) { - snd_printk(KERN_ERR PFX "could not get a new card\n"); + dev_err(pdev, "could not get a new card\n"); return err; } acard = card->private_data; @@ -531,11 +529,11 @@ static int snd_cmi8330_probe(struct snd_card *card, int dev) wssdma[dev], -1, WSS_HW_DETECT, 0, &acard->wss); if (err < 0) { - snd_printk(KERN_ERR PFX "AD1848 device busy??\n"); + dev_err(card->dev, "AD1848 device busy??\n"); return err; } if (acard->wss->hardware != WSS_HW_CMI8330) { - snd_printk(KERN_ERR PFX "AD1848 not found during probe\n"); + dev_err(card->dev, "AD1848 not found during probe\n"); return -ENODEV; } @@ -546,11 +544,11 @@ static int snd_cmi8330_probe(struct snd_card *card, int dev) sbdma16[dev], SB_HW_AUTO, &acard->sb); if (err < 0) { - snd_printk(KERN_ERR PFX "SB16 device busy??\n"); + dev_err(card->dev, "SB16 device busy??\n"); return err; } if (acard->sb->hardware != SB_HW_16) { - snd_printk(KERN_ERR PFX "SB16 not found during probe\n"); + dev_err(card->dev, "SB16 not found during probe\n"); return -ENODEV; } @@ -561,22 +559,22 @@ static int snd_cmi8330_probe(struct snd_card *card, int dev) err = snd_cmi8330_mixer(card, acard); if (err < 0) { - snd_printk(KERN_ERR PFX "failed to create mixers\n"); + dev_err(card->dev, "failed to create mixers\n"); return err; } err = snd_cmi8330_pcm(card, acard); if (err < 0) { - snd_printk(KERN_ERR PFX "failed to create pcms\n"); + dev_err(card->dev, "failed to create pcms\n"); return err; } if (fmport[dev] != SNDRV_AUTO_PORT) { if (snd_opl3_create(card, fmport[dev], fmport[dev] + 2, OPL3_HW_AUTO, 0, &opl3) < 0) { - snd_printk(KERN_ERR PFX - "no OPL device at 0x%lx-0x%lx ?\n", - fmport[dev], fmport[dev] + 2); + dev_err(card->dev, + "no OPL device at 0x%lx-0x%lx ?\n", + fmport[dev], fmport[dev] + 2); } else { err = snd_opl3_hwdep_new(opl3, 0, 1, NULL); if (err < 0) @@ -588,7 +586,7 @@ static int snd_cmi8330_probe(struct snd_card *card, int dev) if (snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, mpuport[dev], 0, mpuirq[dev], NULL) < 0) - printk(KERN_ERR PFX "no MPU-401 device at 0x%lx.\n", + dev_err(card->dev, "no MPU-401 device at 0x%lx.\n", mpuport[dev]); } @@ -609,11 +607,11 @@ static int snd_cmi8330_isa_match(struct device *pdev, if (!enable[dev] || is_isapnp_selected(dev)) return 0; if (wssport[dev] == SNDRV_AUTO_PORT) { - snd_printk(KERN_ERR PFX "specify wssport\n"); + dev_err(pdev, "specify wssport\n"); return 0; } if (sbport[dev] == SNDRV_AUTO_PORT) { - snd_printk(KERN_ERR PFX "specify sbport\n"); + dev_err(pdev, "specify sbport\n"); return 0; } return 1; @@ -683,7 +681,7 @@ static int snd_cmi8330_pnp_detect(struct pnp_card_link *pcard, return res; res = snd_cmi8330_pnp(dev, card->private_data, pcard, pid); if (res < 0) { - snd_printk(KERN_ERR PFX "PnP detection failed\n"); + dev_err(card->dev, "PnP detection failed\n"); return res; } res = snd_cmi8330_probe(card, dev); diff --git a/sound/isa/cs423x/cs4236.c b/sound/isa/cs423x/cs4236.c index 7226cbf2d7de4c..ad20bb2649bd55 100644 --- a/sound/isa/cs423x/cs4236.c +++ b/sound/isa/cs423x/cs4236.c @@ -204,7 +204,7 @@ MODULE_DEVICE_TABLE(pnp_card, snd_cs423x_pnpids); static int snd_cs423x_pnp_init_wss(int dev, struct pnp_dev *pdev) { if (pnp_activate_dev(pdev) < 0) { - printk(KERN_ERR IDENT " WSS PnP configure failed for WSS (out of resources?)\n"); + dev_err(&pdev->dev, IDENT " WSS PnP configure failed for WSS (out of resources?)\n"); return -EBUSY; } port[dev] = pnp_port_start(pdev, 0); @@ -214,10 +214,12 @@ static int snd_cs423x_pnp_init_wss(int dev, struct pnp_dev *pdev) irq[dev] = pnp_irq(pdev, 0); dma1[dev] = pnp_dma(pdev, 0); dma2[dev] = pnp_dma(pdev, 1) == 4 ? -1 : (int)pnp_dma(pdev, 1); - snd_printdd("isapnp WSS: wss port=0x%lx, fm port=0x%lx, sb port=0x%lx\n", - port[dev], fm_port[dev], sb_port[dev]); - snd_printdd("isapnp WSS: irq=%i, dma1=%i, dma2=%i\n", - irq[dev], dma1[dev], dma2[dev]); + dev_dbg(&pdev->dev, + "isapnp WSS: wss port=0x%lx, fm port=0x%lx, sb port=0x%lx\n", + port[dev], fm_port[dev], sb_port[dev]); + dev_dbg(&pdev->dev, + "isapnp WSS: irq=%i, dma1=%i, dma2=%i\n", + irq[dev], dma1[dev], dma2[dev]); return 0; } @@ -225,11 +227,11 @@ static int snd_cs423x_pnp_init_wss(int dev, struct pnp_dev *pdev) static int snd_cs423x_pnp_init_ctrl(int dev, struct pnp_dev *pdev) { if (pnp_activate_dev(pdev) < 0) { - printk(KERN_ERR IDENT " CTRL PnP configure failed for WSS (out of resources?)\n"); + dev_err(&pdev->dev, IDENT " CTRL PnP configure failed for WSS (out of resources?)\n"); return -EBUSY; } cport[dev] = pnp_port_start(pdev, 0); - snd_printdd("isapnp CTRL: control port=0x%lx\n", cport[dev]); + dev_dbg(&pdev->dev, "isapnp CTRL: control port=0x%lx\n", cport[dev]); return 0; } @@ -237,7 +239,7 @@ static int snd_cs423x_pnp_init_ctrl(int dev, struct pnp_dev *pdev) static int snd_cs423x_pnp_init_mpu(int dev, struct pnp_dev *pdev) { if (pnp_activate_dev(pdev) < 0) { - printk(KERN_ERR IDENT " MPU401 PnP configure failed for WSS (out of resources?)\n"); + dev_err(&pdev->dev, IDENT " MPU401 PnP configure failed for WSS (out of resources?)\n"); mpu_port[dev] = SNDRV_AUTO_PORT; mpu_irq[dev] = SNDRV_AUTO_IRQ; } else { @@ -250,7 +252,7 @@ static int snd_cs423x_pnp_init_mpu(int dev, struct pnp_dev *pdev) mpu_irq[dev] = -1; /* disable interrupt */ } } - snd_printdd("isapnp MPU: port=0x%lx, irq=%i\n", mpu_port[dev], mpu_irq[dev]); + dev_dbg(&pdev->dev, "isapnp MPU: port=0x%lx, irq=%i\n", mpu_port[dev], mpu_irq[dev]); return 0; } @@ -333,7 +335,8 @@ static int snd_cs423x_probe(struct snd_card *card, int dev) if (sb_port[dev] > 0 && sb_port[dev] != SNDRV_AUTO_PORT) { if (!devm_request_region(card->dev, sb_port[dev], 16, IDENT " SB")) { - printk(KERN_ERR IDENT ": unable to register SB port at 0x%lx\n", sb_port[dev]); + dev_err(card->dev, IDENT ": unable to register SB port at 0x%lx\n", + sb_port[dev]); return -EBUSY; } } @@ -384,7 +387,7 @@ static int snd_cs423x_probe(struct snd_card *card, int dev) if (snd_opl3_create(card, fm_port[dev], fm_port[dev] + 2, OPL3_HW_OPL3_CS, 0, &opl3) < 0) { - printk(KERN_WARNING IDENT ": OPL3 not detected\n"); + dev_warn(card->dev, IDENT ": OPL3 not detected\n"); } else { err = snd_opl3_hwdep_new(opl3, 0, 1, NULL); if (err < 0) @@ -398,7 +401,7 @@ static int snd_cs423x_probe(struct snd_card *card, int dev) if (snd_mpu401_uart_new(card, 0, MPU401_HW_CS4232, mpu_port[dev], 0, mpu_irq[dev], NULL) < 0) - printk(KERN_WARNING IDENT ": MPU401 not detected\n"); + dev_warn(card->dev, IDENT ": MPU401 not detected\n"); } return snd_card_register(card); @@ -521,7 +524,7 @@ static int snd_cs423x_pnpbios_detect(struct pnp_dev *pdev, return err; err = snd_card_cs423x_pnp(dev, card->private_data, pdev, cdev); if (err < 0) { - printk(KERN_ERR "PnP BIOS detection failed for " IDENT "\n"); + dev_err(card->dev, "PnP BIOS detection failed for " IDENT "\n"); return err; } err = snd_cs423x_probe(card, dev); @@ -573,7 +576,7 @@ static int snd_cs423x_pnpc_detect(struct pnp_card_link *pcard, return res; res = snd_card_cs423x_pnpc(dev, card->private_data, pcard, pid); if (res < 0) { - printk(KERN_ERR "isapnp detection failed and probing for " IDENT + dev_err(card->dev, "isapnp detection failed and probing for " IDENT " is not supported\n"); return res; } diff --git a/sound/isa/cs423x/cs4236_lib.c b/sound/isa/cs423x/cs4236_lib.c index 35f25911adcf0a..1a03cff6915b85 100644 --- a/sound/isa/cs423x/cs4236_lib.c +++ b/sound/isa/cs423x/cs4236_lib.c @@ -279,8 +279,8 @@ int snd_cs4236_create(struct snd_card *card, return err; if ((chip->hardware & WSS_HW_CS4236B_MASK) == 0) { - snd_printd("chip is not CS4236+, hardware=0x%x\n", - chip->hardware); + dev_dbg(card->dev, "chip is not CS4236+, hardware=0x%x\n", + chip->hardware); *rchip = chip; return 0; } @@ -288,25 +288,25 @@ int snd_cs4236_create(struct snd_card *card, { int idx; for (idx = 0; idx < 8; idx++) - snd_printk(KERN_DEBUG "CD%i = 0x%x\n", - idx, inb(chip->cport + idx)); + dev_dbg(card->dev, "CD%i = 0x%x\n", + idx, inb(chip->cport + idx)); for (idx = 0; idx < 9; idx++) - snd_printk(KERN_DEBUG "C%i = 0x%x\n", - idx, snd_cs4236_ctrl_in(chip, idx)); + dev_dbg(card->dev, "C%i = 0x%x\n", + idx, snd_cs4236_ctrl_in(chip, idx)); } #endif if (cport < 0x100 || cport == SNDRV_AUTO_PORT) { - snd_printk(KERN_ERR "please, specify control port " - "for CS4236+ chips\n"); + dev_err(card->dev, "please, specify control port for CS4236+ chips\n"); return -ENODEV; } ver1 = snd_cs4236_ctrl_in(chip, 1); ver2 = snd_cs4236_ext_in(chip, CS4236_VERSION); - snd_printdd("CS4236: [0x%lx] C1 (version) = 0x%x, ext = 0x%x\n", - cport, ver1, ver2); + dev_dbg(card->dev, "CS4236: [0x%lx] C1 (version) = 0x%x, ext = 0x%x\n", + cport, ver1, ver2); if (ver1 != ver2) { - snd_printk(KERN_ERR "CS4236+ chip detected, but " - "control port 0x%lx is not valid\n", cport); + dev_err(card->dev, + "CS4236+ chip detected, but control port 0x%lx is not valid\n", + cport); return -ENODEV; } snd_cs4236_ctrl_out(chip, 0, 0x00); @@ -934,14 +934,14 @@ static int snd_cs4236_get_iec958_switch(struct snd_kcontrol *kcontrol, struct sn spin_lock_irqsave(&chip->reg_lock, flags); ucontrol->value.integer.value[0] = chip->image[CS4231_ALT_FEATURE_1] & 0x02 ? 1 : 0; #if 0 - printk(KERN_DEBUG "get valid: ALT = 0x%x, C3 = 0x%x, C4 = 0x%x, " - "C5 = 0x%x, C6 = 0x%x, C8 = 0x%x\n", - snd_wss_in(chip, CS4231_ALT_FEATURE_1), - snd_cs4236_ctrl_in(chip, 3), - snd_cs4236_ctrl_in(chip, 4), - snd_cs4236_ctrl_in(chip, 5), - snd_cs4236_ctrl_in(chip, 6), - snd_cs4236_ctrl_in(chip, 8)); + dev_dbg(chip->card->dev, + "get valid: ALT = 0x%x, C3 = 0x%x, C4 = 0x%x, C5 = 0x%x, C6 = 0x%x, C8 = 0x%x\n", + snd_wss_in(chip, CS4231_ALT_FEATURE_1), + snd_cs4236_ctrl_in(chip, 3), + snd_cs4236_ctrl_in(chip, 4), + snd_cs4236_ctrl_in(chip, 5), + snd_cs4236_ctrl_in(chip, 6), + snd_cs4236_ctrl_in(chip, 8)); #endif spin_unlock_irqrestore(&chip->reg_lock, flags); return 0; @@ -972,14 +972,14 @@ static int snd_cs4236_put_iec958_switch(struct snd_kcontrol *kcontrol, struct sn mutex_unlock(&chip->mce_mutex); #if 0 - printk(KERN_DEBUG "set valid: ALT = 0x%x, C3 = 0x%x, C4 = 0x%x, " - "C5 = 0x%x, C6 = 0x%x, C8 = 0x%x\n", - snd_wss_in(chip, CS4231_ALT_FEATURE_1), - snd_cs4236_ctrl_in(chip, 3), - snd_cs4236_ctrl_in(chip, 4), - snd_cs4236_ctrl_in(chip, 5), - snd_cs4236_ctrl_in(chip, 6), - snd_cs4236_ctrl_in(chip, 8)); + dev_dbg(chip->card->dev, + "set valid: ALT = 0x%x, C3 = 0x%x, C4 = 0x%x, C5 = 0x%x, C6 = 0x%x, C8 = 0x%x\n", + snd_wss_in(chip, CS4231_ALT_FEATURE_1), + snd_cs4236_ctrl_in(chip, 3), + snd_cs4236_ctrl_in(chip, 4), + snd_cs4236_ctrl_in(chip, 5), + snd_cs4236_ctrl_in(chip, 6), + snd_cs4236_ctrl_in(chip, 8)); #endif return change; } diff --git a/sound/isa/es1688/es1688.c b/sound/isa/es1688/es1688.c index 97728bf4547423..6a95dfb7600a3b 100644 --- a/sound/isa/es1688/es1688.c +++ b/sound/isa/es1688/es1688.c @@ -213,7 +213,7 @@ static int snd_card_es968_pnp(struct snd_card *card, unsigned int n, error = pnp_activate_dev(pdev); if (error < 0) { - snd_printk(KERN_ERR "ES968 pnp configure failure\n"); + dev_err(card->dev, "ES968 pnp configure failure\n"); return error; } port[n] = pnp_port_start(pdev, 0); diff --git a/sound/isa/es1688/es1688_lib.c b/sound/isa/es1688/es1688_lib.c index 8554cb2263c1f9..c0c230149a750d 100644 --- a/sound/isa/es1688/es1688_lib.c +++ b/sound/isa/es1688/es1688_lib.c @@ -30,9 +30,7 @@ static int snd_es1688_dsp_command(struct snd_es1688 *chip, unsigned char val) outb(val, ES1688P(chip, COMMAND)); return 1; } -#ifdef CONFIG_SND_DEBUG - printk(KERN_DEBUG "snd_es1688_dsp_command: timeout (0x%x)\n", val); -#endif + dev_dbg(chip->card->dev, "%s: timeout (0x%x)\n", __func__, val); return 0; } @@ -43,7 +41,8 @@ static int snd_es1688_dsp_get_byte(struct snd_es1688 *chip) for (i = 1000; i; i--) if (inb(ES1688P(chip, DATA_AVAIL)) & 0x80) return inb(ES1688P(chip, READ)); - snd_printd("es1688 get byte failed: 0x%lx = 0x%x!!!\n", ES1688P(chip, DATA_AVAIL), inb(ES1688P(chip, DATA_AVAIL))); + dev_dbg(chip->card->dev, "es1688 get byte failed: 0x%lx = 0x%x!!!\n", + ES1688P(chip, DATA_AVAIL), inb(ES1688P(chip, DATA_AVAIL))); return -ENODEV; } @@ -95,7 +94,8 @@ int snd_es1688_reset(struct snd_es1688 *chip) udelay(30); for (i = 0; i < 1000 && !(inb(ES1688P(chip, DATA_AVAIL)) & 0x80); i++); if (inb(ES1688P(chip, READ)) != 0xaa) { - snd_printd("ess_reset at 0x%lx: failed!!!\n", chip->port); + dev_dbg(chip->card->dev, "ess_reset at 0x%lx: failed!!!\n", + chip->port); return -ENODEV; } snd_es1688_dsp_command(chip, 0xc6); /* enable extended mode */ @@ -127,7 +127,8 @@ static int snd_es1688_probe(struct snd_es1688 *chip) inb(ES1688P(chip, ENABLE0)); /* ENABLE0 */ if (snd_es1688_reset(chip) < 0) { - snd_printdd("ESS: [0x%lx] reset failed... 0x%x\n", chip->port, inb(ES1688P(chip, READ))); + dev_dbg(chip->card->dev, "ESS: [0x%lx] reset failed... 0x%x\n", + chip->port, inb(ES1688P(chip, READ))); spin_unlock_irqrestore(&chip->reg_lock, flags); return -ENODEV; } @@ -145,7 +146,9 @@ static int snd_es1688_probe(struct snd_es1688 *chip) spin_unlock_irqrestore(&chip->reg_lock, flags); - snd_printdd("ESS: [0x%lx] found.. major = 0x%x, minor = 0x%x\n", chip->port, major, minor); + dev_dbg(chip->card->dev, + "ESS: [0x%lx] found.. major = 0x%x, minor = 0x%x\n", + chip->port, major, minor); chip->version = (major << 8) | minor; if (!chip->version) @@ -153,15 +156,16 @@ static int snd_es1688_probe(struct snd_es1688 *chip) switch (chip->version & 0xfff0) { case 0x4880: - snd_printk(KERN_ERR "[0x%lx] ESS: AudioDrive ES488 detected, " - "but driver is in another place\n", chip->port); + dev_err(chip->card->dev, + "[0x%lx] ESS: AudioDrive ES488 detected, but driver is in another place\n", + chip->port); return -ENODEV; case 0x6880: break; default: - snd_printk(KERN_ERR "[0x%lx] ESS: unknown AudioDrive chip " - "with version 0x%x (Jazz16 soundcard?)\n", - chip->port, chip->version); + dev_err(chip->card->dev, + "[0x%lx] ESS: unknown AudioDrive chip with version 0x%x (Jazz16 soundcard?)\n", + chip->port, chip->version); return -ENODEV; } @@ -210,9 +214,6 @@ static int snd_es1688_init(struct snd_es1688 * chip, int enable) } } } -#if 0 - snd_printk(KERN_DEBUG "mpu cfg = 0x%x\n", cfg); -#endif spin_lock_irqsave(&chip->reg_lock, flags); snd_es1688_mixer_write(chip, 0x40, cfg); spin_unlock_irqrestore(&chip->reg_lock, flags); @@ -225,9 +226,9 @@ static int snd_es1688_init(struct snd_es1688 * chip, int enable) cfg = 0xf0; /* enable only DMA counter interrupt */ irq_bits = irqs[chip->irq & 0x0f]; if (irq_bits < 0) { - snd_printk(KERN_ERR "[0x%lx] ESS: bad IRQ %d " - "for ES1688 chip!!\n", - chip->port, chip->irq); + dev_err(chip->card->dev, + "[0x%lx] ESS: bad IRQ %d for ES1688 chip!!\n", + chip->port, chip->irq); #if 0 irq_bits = 0; cfg = 0x10; @@ -240,8 +241,9 @@ static int snd_es1688_init(struct snd_es1688 * chip, int enable) cfg = 0xf0; /* extended mode DMA enable */ dma = chip->dma8; if (dma > 3 || dma == 2) { - snd_printk(KERN_ERR "[0x%lx] ESS: bad DMA channel %d " - "for ES1688 chip!!\n", chip->port, dma); + dev_err(chip->card->dev, + "[0x%lx] ESS: bad DMA channel %d for ES1688 chip!!\n", + chip->port, dma); #if 0 dma_bits = 0; cfg = 0x00; /* disable all DMA */ @@ -326,9 +328,9 @@ static int snd_es1688_trigger(struct snd_es1688 *chip, int cmd, unsigned char va return -EINVAL; /* something is wrong */ } #if 0 - printk(KERN_DEBUG "trigger: val = 0x%x, value = 0x%x\n", val, value); - printk(KERN_DEBUG "trigger: pointer = 0x%x\n", - snd_dma_pointer(chip->dma8, chip->dma_size)); + dev_dbg(chip->card->dev, "trigger: val = 0x%x, value = 0x%x\n", val, value); + dev_dbg(chip->card->dev, "trigger: pointer = 0x%x\n", + snd_dma_pointer(chip->dma8, chip->dma_size)); #endif snd_es1688_write(chip, 0xb8, (val & 0xf0) | value); spin_unlock(&chip->reg_lock); @@ -620,20 +622,21 @@ int snd_es1688_create(struct snd_card *card, if (chip == NULL) return -ENOMEM; + chip->card = card; chip->irq = -1; chip->dma8 = -1; chip->hardware = ES1688_HW_UNDEF; chip->res_port = request_region(port + 4, 12, "ES1688"); if (chip->res_port == NULL) { - snd_printk(KERN_ERR "es1688: can't grab port 0x%lx\n", port + 4); + dev_err(card->dev, "es1688: can't grab port 0x%lx\n", port + 4); err = -EBUSY; goto exit; } err = request_irq(irq, snd_es1688_interrupt, 0, "ES1688", (void *) chip); if (err < 0) { - snd_printk(KERN_ERR "es1688: can't grab IRQ %d\n", irq); + dev_err(card->dev, "es1688: can't grab IRQ %d\n", irq); goto exit; } @@ -642,7 +645,7 @@ int snd_es1688_create(struct snd_card *card, err = request_dma(dma8, "ES1688"); if (err < 0) { - snd_printk(KERN_ERR "es1688: can't grab DMA8 %d\n", dma8); + dev_err(card->dev, "es1688: can't grab DMA8 %d\n", dma8); goto exit; } chip->dma8 = dma8; diff --git a/sound/isa/es18xx.c b/sound/isa/es18xx.c index 0a32845b1017a6..59c784a70ac1a0 100644 --- a/sound/isa/es18xx.c +++ b/sound/isa/es18xx.c @@ -82,9 +82,8 @@ #define SNDRV_LEGACY_FIND_FREE_DMA #include -#define PFX "es18xx: " - struct snd_es18xx { + struct snd_card *card; unsigned long port; /* port of ESS chip */ unsigned long ctrl_port; /* Control port of ESS chip */ int irq; /* IRQ number of ESS chip */ @@ -165,7 +164,7 @@ static int snd_es18xx_dsp_command(struct snd_es18xx *chip, unsigned char val) outb(val, chip->port + 0x0C); return 0; } - snd_printk(KERN_ERR "dsp_command: timeout (0x%x)\n", val); + dev_err(chip->card->dev, "dsp_command: timeout (0x%x)\n", val); return -EINVAL; } @@ -176,8 +175,8 @@ static int snd_es18xx_dsp_get_byte(struct snd_es18xx *chip) for(i = MILLISECOND/10; i; i--) if (inb(chip->port + 0x0C) & 0x40) return inb(chip->port + 0x0A); - snd_printk(KERN_ERR "dsp_get_byte failed: 0x%lx = 0x%x!!!\n", - chip->port + 0x0A, inb(chip->port + 0x0A)); + dev_err(chip->card->dev, "dsp_get_byte failed: 0x%lx = 0x%x!!!\n", + chip->port + 0x0A, inb(chip->port + 0x0A)); return -ENODEV; } @@ -197,7 +196,7 @@ static int snd_es18xx_write(struct snd_es18xx *chip, end: spin_unlock_irqrestore(&chip->reg_lock, flags); #ifdef REG_DEBUG - snd_printk(KERN_DEBUG "Reg %02x set to %02x\n", reg, data); + dev_dbg(chip->card->dev, "Reg %02x set to %02x\n", reg, data); #endif return ret; } @@ -216,7 +215,7 @@ static int snd_es18xx_read(struct snd_es18xx *chip, unsigned char reg) data = snd_es18xx_dsp_get_byte(chip); ret = data; #ifdef REG_DEBUG - snd_printk(KERN_DEBUG "Reg %02x now is %02x (%d)\n", reg, data, ret); + dev_dbg(chip->card->dev, "Reg %02x now is %02x (%d)\n", reg, data, ret); #endif end: spin_unlock_irqrestore(&chip->reg_lock, flags); @@ -252,8 +251,8 @@ static int snd_es18xx_bits(struct snd_es18xx *chip, unsigned char reg, if (ret < 0) goto end; #ifdef REG_DEBUG - snd_printk(KERN_DEBUG "Reg %02x was %02x, set to %02x (%d)\n", - reg, old, new, ret); + dev_dbg(chip->card->dev, "Reg %02x was %02x, set to %02x (%d)\n", + reg, old, new, ret); #endif } ret = oval; @@ -271,7 +270,7 @@ static inline void snd_es18xx_mixer_write(struct snd_es18xx *chip, outb(data, chip->port + 0x05); spin_unlock_irqrestore(&chip->mixer_lock, flags); #ifdef REG_DEBUG - snd_printk(KERN_DEBUG "Mixer reg %02x set to %02x\n", reg, data); + dev_dbg(chip->card->dev, "Mixer reg %02x set to %02x\n", reg, data); #endif } @@ -284,7 +283,7 @@ static inline int snd_es18xx_mixer_read(struct snd_es18xx *chip, unsigned char r data = inb(chip->port + 0x05); spin_unlock_irqrestore(&chip->mixer_lock, flags); #ifdef REG_DEBUG - snd_printk(KERN_DEBUG "Mixer reg %02x now is %02x\n", reg, data); + dev_dbg(chip->card->dev, "Mixer reg %02x now is %02x\n", reg, data); #endif return data; } @@ -303,8 +302,8 @@ static inline int snd_es18xx_mixer_bits(struct snd_es18xx *chip, unsigned char r new = (old & ~mask) | (val & mask); outb(new, chip->port + 0x05); #ifdef REG_DEBUG - snd_printk(KERN_DEBUG "Mixer reg %02x was %02x, set to %02x\n", - reg, old, new); + dev_dbg(chip->card->dev, "Mixer reg %02x was %02x, set to %02x\n", + reg, old, new); #endif } spin_unlock_irqrestore(&chip->mixer_lock, flags); @@ -324,8 +323,8 @@ static inline int snd_es18xx_mixer_writable(struct snd_es18xx *chip, unsigned ch new = inb(chip->port + 0x05); spin_unlock_irqrestore(&chip->mixer_lock, flags); #ifdef REG_DEBUG - snd_printk(KERN_DEBUG "Mixer reg %02x was %02x, set to %02x, now is %02x\n", - reg, old, expected, new); + dev_dbg(chip->card->dev, "Mixer reg %02x was %02x, set to %02x, now is %02x\n", + reg, old, expected, new); #endif return expected == new; } @@ -1356,7 +1355,7 @@ static void snd_es18xx_config_write(struct snd_es18xx *chip, outb(reg, chip->ctrl_port); outb(data, chip->ctrl_port + 1); #ifdef REG_DEBUG - snd_printk(KERN_DEBUG "Config reg %02x set to %02x\n", reg, data); + dev_dbg(chip->card->dev, "Config reg %02x set to %02x\n", reg, data); #endif } @@ -1425,7 +1424,7 @@ static int snd_es18xx_initialize(struct snd_es18xx *chip, irqmask = 3; break; default: - snd_printk(KERN_ERR "invalid irq %d\n", chip->irq); + dev_err(chip->card->dev, "invalid irq %d\n", chip->irq); return -ENODEV; } switch (chip->dma1) { @@ -1439,7 +1438,7 @@ static int snd_es18xx_initialize(struct snd_es18xx *chip, dma1mask = 3; break; default: - snd_printk(KERN_ERR "invalid dma1 %d\n", chip->dma1); + dev_err(chip->card->dev, "invalid dma1 %d\n", chip->dma1); return -ENODEV; } switch (chip->dma2) { @@ -1456,7 +1455,7 @@ static int snd_es18xx_initialize(struct snd_es18xx *chip, dma2mask = 3; break; default: - snd_printk(KERN_ERR "invalid dma2 %d\n", chip->dma2); + dev_err(chip->card->dev, "invalid dma2 %d\n", chip->dma2); return -ENODEV; } @@ -1531,7 +1530,7 @@ static int snd_es18xx_identify(struct snd_card *card, struct snd_es18xx *chip) /* reset */ if (snd_es18xx_reset(chip) < 0) { - snd_printk(KERN_ERR "reset at 0x%lx failed!!!\n", chip->port); + dev_err(card->dev, "reset at 0x%lx failed!!!\n", chip->port); return -ENODEV; } @@ -1569,7 +1568,7 @@ static int snd_es18xx_identify(struct snd_card *card, struct snd_es18xx *chip) if (!devm_request_region(card->dev, chip->ctrl_port, 8, "ES18xx - CTRL")) { - snd_printk(KERN_ERR PFX "unable go grab port 0x%lx\n", chip->ctrl_port); + dev_err(card->dev, "unable go grab port 0x%lx\n", chip->ctrl_port); return -EBUSY; } @@ -1601,7 +1600,7 @@ static int snd_es18xx_probe(struct snd_card *card, unsigned long fm_port) { if (snd_es18xx_identify(card, chip) < 0) { - snd_printk(KERN_ERR PFX "[0x%lx] ESS chip not found\n", chip->port); + dev_err(card->dev, "[0x%lx] ESS chip not found\n", chip->port); return -ENODEV; } @@ -1623,12 +1622,12 @@ static int snd_es18xx_probe(struct snd_card *card, chip->caps = ES18XX_PCM2 | ES18XX_RECMIX | ES18XX_AUXB | ES18XX_DUPLEX_SAME | ES18XX_GPO_2BIT; break; default: - snd_printk(KERN_ERR "[0x%lx] unsupported chip ES%x\n", - chip->port, chip->version); + dev_err(card->dev, "[0x%lx] unsupported chip ES%x\n", + chip->port, chip->version); return -ENODEV; } - snd_printd("[0x%lx] ESS%x chip found\n", chip->port, chip->version); + dev_dbg(card->dev, "[0x%lx] ESS%x chip found\n", chip->port, chip->version); if (chip->dma1 == chip->dma2) chip->caps &= ~(ES18XX_PCM2 | ES18XX_DUPLEX_SAME); @@ -1725,6 +1724,7 @@ static int snd_es18xx_new_device(struct snd_card *card, { struct snd_es18xx *chip = card->private_data; + chip->card = card; spin_lock_init(&chip->reg_lock); spin_lock_init(&chip->mixer_lock); chip->port = port; @@ -1735,27 +1735,27 @@ static int snd_es18xx_new_device(struct snd_card *card, chip->active = 0; if (!devm_request_region(card->dev, port, 16, "ES18xx")) { - snd_printk(KERN_ERR PFX "unable to grap ports 0x%lx-0x%lx\n", port, port + 16 - 1); + dev_err(card->dev, "unable to grap ports 0x%lx-0x%lx\n", port, port + 16 - 1); return -EBUSY; } if (devm_request_irq(card->dev, irq, snd_es18xx_interrupt, 0, "ES18xx", (void *) card)) { - snd_printk(KERN_ERR PFX "unable to grap IRQ %d\n", irq); + dev_err(card->dev, "unable to grap IRQ %d\n", irq); return -EBUSY; } chip->irq = irq; card->sync_irq = chip->irq; if (snd_devm_request_dma(card->dev, dma1, "ES18xx DMA 1")) { - snd_printk(KERN_ERR PFX "unable to grap DMA1 %d\n", dma1); + dev_err(card->dev, "unable to grap DMA1 %d\n", dma1); return -EBUSY; } chip->dma1 = dma1; if (dma2 != dma1 && snd_devm_request_dma(card->dev, dma2, "ES18xx DMA 2")) { - snd_printk(KERN_ERR PFX "unable to grap DMA2 %d\n", dma2); + dev_err(card->dev, "unable to grap DMA2 %d\n", dma2); return -EBUSY; } chip->dma2 = dma2; @@ -1954,7 +1954,7 @@ MODULE_DEVICE_TABLE(pnp, snd_audiodrive_pnpbiosids); static int snd_audiodrive_pnp_init_main(int dev, struct pnp_dev *pdev) { if (pnp_activate_dev(pdev) < 0) { - snd_printk(KERN_ERR PFX "PnP configure failure (out of resources?)\n"); + dev_err(&pdev->dev, "PnP configure failure (out of resources?)\n"); return -EBUSY; } /* ok. hack using Vendor-Defined Card-Level registers */ @@ -1973,8 +1973,12 @@ static int snd_audiodrive_pnp_init_main(int dev, struct pnp_dev *pdev) dma1[dev] = pnp_dma(pdev, 0); dma2[dev] = pnp_dma(pdev, 1); irq[dev] = pnp_irq(pdev, 0); - snd_printdd("PnP ES18xx: port=0x%lx, fm port=0x%lx, mpu port=0x%lx\n", port[dev], fm_port[dev], mpu_port[dev]); - snd_printdd("PnP ES18xx: dma1=%i, dma2=%i, irq=%i\n", dma1[dev], dma2[dev], irq[dev]); + dev_dbg(&pdev->dev, + "PnP ES18xx: port=0x%lx, fm port=0x%lx, mpu port=0x%lx\n", + port[dev], fm_port[dev], mpu_port[dev]); + dev_dbg(&pdev->dev, + "PnP ES18xx: dma1=%i, dma2=%i, irq=%i\n", + dma1[dev], dma2[dev], irq[dev]); return 0; } @@ -2022,11 +2026,12 @@ static int snd_audiodrive_pnpc(int dev, struct snd_es18xx *chip, /* Control port initialization */ if (pnp_activate_dev(chip->devc) < 0) { - snd_printk(KERN_ERR PFX "PnP control configure failure (out of resources?)\n"); + dev_err(chip->card->dev, + "PnP control configure failure (out of resources?)\n"); return -EAGAIN; } - snd_printdd("pnp: port=0x%llx\n", - (unsigned long long)pnp_port_start(chip->devc, 0)); + dev_dbg(chip->card->dev, "pnp: port=0x%llx\n", + (unsigned long long)pnp_port_start(chip->devc, 0)); if (snd_audiodrive_pnp_init_main(dev, chip->dev) < 0) return -EBUSY; @@ -2084,9 +2089,9 @@ static int snd_audiodrive_probe(struct snd_card *card, int dev) if (fm_port[dev] > 0 && fm_port[dev] != SNDRV_AUTO_PORT) { if (snd_opl3_create(card, fm_port[dev], fm_port[dev] + 2, OPL3_HW_OPL3, 0, &opl3) < 0) { - snd_printk(KERN_WARNING PFX - "opl3 not detected at 0x%lx\n", - fm_port[dev]); + dev_warn(card->dev, + "opl3 not detected at 0x%lx\n", + fm_port[dev]); } else { err = snd_opl3_hwdep_new(opl3, 0, 1, NULL); if (err < 0) @@ -2134,21 +2139,21 @@ static int snd_es18xx_isa_probe(struct device *pdev, unsigned int dev) if (irq[dev] == SNDRV_AUTO_IRQ) { irq[dev] = snd_legacy_find_free_irq(possible_irqs); if (irq[dev] < 0) { - snd_printk(KERN_ERR PFX "unable to find a free IRQ\n"); + dev_err(pdev, "unable to find a free IRQ\n"); return -EBUSY; } } if (dma1[dev] == SNDRV_AUTO_DMA) { dma1[dev] = snd_legacy_find_free_dma(possible_dmas); if (dma1[dev] < 0) { - snd_printk(KERN_ERR PFX "unable to find a free DMA1\n"); + dev_err(pdev, "unable to find a free DMA1\n"); return -EBUSY; } } if (dma2[dev] == SNDRV_AUTO_DMA) { dma2[dev] = snd_legacy_find_free_dma(possible_dmas); if (dma2[dev] < 0) { - snd_printk(KERN_ERR PFX "unable to find a free DMA2\n"); + dev_err(pdev, "unable to find a free DMA2\n"); return -EBUSY; } } diff --git a/sound/isa/gus/gus_dma.c b/sound/isa/gus/gus_dma.c index 6d664dd8dde0b4..bb5a4e2fbfb3c1 100644 --- a/sound/isa/gus/gus_dma.c +++ b/sound/isa/gus/gus_dma.c @@ -30,15 +30,18 @@ static void snd_gf1_dma_program(struct snd_gus_card * gus, unsigned char dma_cmd; unsigned int address_high; - snd_printdd("dma_transfer: addr=0x%x, buf=0x%lx, count=0x%x\n", - addr, buf_addr, count); + dev_dbg(gus->card->dev, + "dma_transfer: addr=0x%x, buf=0x%lx, count=0x%x\n", + addr, buf_addr, count); if (gus->gf1.dma1 > 3) { if (gus->gf1.enh_mode) { address = addr >> 1; } else { if (addr & 0x1f) { - snd_printd("snd_gf1_dma_transfer: unaligned address (0x%x)?\n", addr); + dev_dbg(gus->card->dev, + "%s: unaligned address (0x%x)?\n", + __func__, addr); return; } address = (addr & 0x000c0000) | ((addr & 0x0003ffff) >> 1); @@ -63,8 +66,9 @@ static void snd_gf1_dma_program(struct snd_gus_card * gus, snd_gf1_dma_ack(gus); snd_dma_program(gus->gf1.dma1, buf_addr, count, dma_cmd & SNDRV_GF1_DMA_READ ? DMA_MODE_READ : DMA_MODE_WRITE); #if 0 - snd_printk(KERN_DEBUG "address = 0x%x, count = 0x%x, dma_cmd = 0x%x\n", - address << 1, count, dma_cmd); + dev_dbg(gus->card->dev, + "address = 0x%x, count = 0x%x, dma_cmd = 0x%x\n", + address << 1, count, dma_cmd); #endif spin_lock_irqsave(&gus->reg_lock, flags); if (gus->gf1.enh_mode) { @@ -131,9 +135,9 @@ static void snd_gf1_dma_interrupt(struct snd_gus_card * gus) snd_gf1_dma_program(gus, block->addr, block->buf_addr, block->count, (unsigned short) block->cmd); kfree(block); #if 0 - snd_printd(KERN_DEBUG "program dma (IRQ) - " - "addr = 0x%x, buffer = 0x%lx, count = 0x%x, cmd = 0x%x\n", - block->addr, block->buf_addr, block->count, block->cmd); + dev_dbg(gus->card->dev, + "program dma (IRQ) - addr = 0x%x, buffer = 0x%lx, count = 0x%x, cmd = 0x%x\n", + block->addr, block->buf_addr, block->count, block->cmd); #endif } @@ -194,14 +198,17 @@ int snd_gf1_dma_transfer_block(struct snd_gus_card * gus, *block = *__block; block->next = NULL; - snd_printdd("addr = 0x%x, buffer = 0x%lx, count = 0x%x, cmd = 0x%x\n", - block->addr, (long) block->buffer, block->count, - block->cmd); - - snd_printdd("gus->gf1.dma_data_pcm_last = 0x%lx\n", - (long)gus->gf1.dma_data_pcm_last); - snd_printdd("gus->gf1.dma_data_pcm = 0x%lx\n", - (long)gus->gf1.dma_data_pcm); + dev_dbg(gus->card->dev, + "addr = 0x%x, buffer = 0x%lx, count = 0x%x, cmd = 0x%x\n", + block->addr, (long) block->buffer, block->count, + block->cmd); + + dev_dbg(gus->card->dev, + "gus->gf1.dma_data_pcm_last = 0x%lx\n", + (long)gus->gf1.dma_data_pcm_last); + dev_dbg(gus->card->dev, + "gus->gf1.dma_data_pcm = 0x%lx\n", + (long)gus->gf1.dma_data_pcm); spin_lock_irqsave(&gus->dma_lock, flags); if (synth) { diff --git a/sound/isa/gus/gus_io.c b/sound/isa/gus/gus_io.c index fb7b5e2636b85e..1dc9e0edb3d991 100644 --- a/sound/isa/gus/gus_io.c +++ b/sound/isa/gus/gus_io.c @@ -325,10 +325,8 @@ void snd_gf1_pokew(struct snd_gus_card * gus, unsigned int addr, unsigned short { unsigned long flags; -#ifdef CONFIG_SND_DEBUG if (!gus->interwave) - snd_printk(KERN_DEBUG "snd_gf1_pokew - GF1!!!\n"); -#endif + dev_dbg(gus->card->dev, "%s - GF1!!!\n", __func__); spin_lock_irqsave(&gus->reg_lock, flags); outb(SNDRV_GF1_GW_DRAM_IO_LOW, gus->gf1.reg_regsel); mb(); @@ -349,10 +347,8 @@ unsigned short snd_gf1_peekw(struct snd_gus_card * gus, unsigned int addr) unsigned long flags; unsigned short res; -#ifdef CONFIG_SND_DEBUG if (!gus->interwave) - snd_printk(KERN_DEBUG "snd_gf1_peekw - GF1!!!\n"); -#endif + dev_dbg(gus->card->dev, "%s - GF1!!!\n", __func__); spin_lock_irqsave(&gus->reg_lock, flags); outb(SNDRV_GF1_GW_DRAM_IO_LOW, gus->gf1.reg_regsel); mb(); @@ -375,10 +371,8 @@ void snd_gf1_dram_setmem(struct snd_gus_card * gus, unsigned int addr, unsigned long port; unsigned long flags; -#ifdef CONFIG_SND_DEBUG if (!gus->interwave) - snd_printk(KERN_DEBUG "snd_gf1_dram_setmem - GF1!!!\n"); -#endif + dev_dbg(gus->card->dev, "%s - GF1!!!\n", __func__); addr &= ~1; count >>= 1; port = GUSP(gus, GF1DATALOW); @@ -433,30 +427,73 @@ void snd_gf1_print_voice_registers(struct snd_gus_card * gus) int voice, ctrl; voice = gus->gf1.active_voice; - printk(KERN_INFO " -%i- GF1 voice ctrl, ramp ctrl = 0x%x, 0x%x\n", voice, ctrl = snd_gf1_i_read8(gus, 0), snd_gf1_i_read8(gus, 0x0d)); - printk(KERN_INFO " -%i- GF1 frequency = 0x%x\n", voice, snd_gf1_i_read16(gus, 1)); - printk(KERN_INFO " -%i- GF1 loop start, end = 0x%x (0x%x), 0x%x (0x%x)\n", voice, snd_gf1_i_read_addr(gus, 2, ctrl & 4), snd_gf1_i_read_addr(gus, 2, (ctrl & 4) ^ 4), snd_gf1_i_read_addr(gus, 4, ctrl & 4), snd_gf1_i_read_addr(gus, 4, (ctrl & 4) ^ 4)); - printk(KERN_INFO " -%i- GF1 ramp start, end, rate = 0x%x, 0x%x, 0x%x\n", voice, snd_gf1_i_read8(gus, 7), snd_gf1_i_read8(gus, 8), snd_gf1_i_read8(gus, 6)); - printk(KERN_INFO" -%i- GF1 volume = 0x%x\n", voice, snd_gf1_i_read16(gus, 9)); - printk(KERN_INFO " -%i- GF1 position = 0x%x (0x%x)\n", voice, snd_gf1_i_read_addr(gus, 0x0a, ctrl & 4), snd_gf1_i_read_addr(gus, 0x0a, (ctrl & 4) ^ 4)); + dev_info(gus->card->dev, + " -%i- GF1 voice ctrl, ramp ctrl = 0x%x, 0x%x\n", + voice, ctrl = snd_gf1_i_read8(gus, 0), snd_gf1_i_read8(gus, 0x0d)); + dev_info(gus->card->dev, + " -%i- GF1 frequency = 0x%x\n", + voice, snd_gf1_i_read16(gus, 1)); + dev_info(gus->card->dev, + " -%i- GF1 loop start, end = 0x%x (0x%x), 0x%x (0x%x)\n", + voice, snd_gf1_i_read_addr(gus, 2, ctrl & 4), + snd_gf1_i_read_addr(gus, 2, (ctrl & 4) ^ 4), + snd_gf1_i_read_addr(gus, 4, ctrl & 4), + snd_gf1_i_read_addr(gus, 4, (ctrl & 4) ^ 4)); + dev_info(gus->card->dev, + " -%i- GF1 ramp start, end, rate = 0x%x, 0x%x, 0x%x\n", + voice, snd_gf1_i_read8(gus, 7), snd_gf1_i_read8(gus, 8), + snd_gf1_i_read8(gus, 6)); + dev_info(gus->card->dev, + " -%i- GF1 volume = 0x%x\n", + voice, snd_gf1_i_read16(gus, 9)); + dev_info(gus->card->dev, + " -%i- GF1 position = 0x%x (0x%x)\n", + voice, snd_gf1_i_read_addr(gus, 0x0a, ctrl & 4), + snd_gf1_i_read_addr(gus, 0x0a, (ctrl & 4) ^ 4)); if (gus->interwave && snd_gf1_i_read8(gus, 0x19) & 0x01) { /* enhanced mode */ mode = snd_gf1_i_read8(gus, 0x15); - printk(KERN_INFO " -%i- GFA1 mode = 0x%x\n", voice, mode); + dev_info(gus->card->dev, + " -%i- GFA1 mode = 0x%x\n", + voice, mode); if (mode & 0x01) { /* Effect processor */ - printk(KERN_INFO " -%i- GFA1 effect address = 0x%x\n", voice, snd_gf1_i_read_addr(gus, 0x11, ctrl & 4)); - printk(KERN_INFO " -%i- GFA1 effect volume = 0x%x\n", voice, snd_gf1_i_read16(gus, 0x16)); - printk(KERN_INFO " -%i- GFA1 effect volume final = 0x%x\n", voice, snd_gf1_i_read16(gus, 0x1d)); - printk(KERN_INFO " -%i- GFA1 effect accumulator = 0x%x\n", voice, snd_gf1_i_read8(gus, 0x14)); + dev_info(gus->card->dev, + " -%i- GFA1 effect address = 0x%x\n", + voice, snd_gf1_i_read_addr(gus, 0x11, ctrl & 4)); + dev_info(gus->card->dev, + " -%i- GFA1 effect volume = 0x%x\n", + voice, snd_gf1_i_read16(gus, 0x16)); + dev_info(gus->card->dev, + " -%i- GFA1 effect volume final = 0x%x\n", + voice, snd_gf1_i_read16(gus, 0x1d)); + dev_info(gus->card->dev, + " -%i- GFA1 effect accumulator = 0x%x\n", + voice, snd_gf1_i_read8(gus, 0x14)); } if (mode & 0x20) { - printk(KERN_INFO " -%i- GFA1 left offset = 0x%x (%i)\n", voice, snd_gf1_i_read16(gus, 0x13), snd_gf1_i_read16(gus, 0x13) >> 4); - printk(KERN_INFO " -%i- GFA1 left offset final = 0x%x (%i)\n", voice, snd_gf1_i_read16(gus, 0x1c), snd_gf1_i_read16(gus, 0x1c) >> 4); - printk(KERN_INFO " -%i- GFA1 right offset = 0x%x (%i)\n", voice, snd_gf1_i_read16(gus, 0x0c), snd_gf1_i_read16(gus, 0x0c) >> 4); - printk(KERN_INFO " -%i- GFA1 right offset final = 0x%x (%i)\n", voice, snd_gf1_i_read16(gus, 0x1b), snd_gf1_i_read16(gus, 0x1b) >> 4); + dev_info(gus->card->dev, + " -%i- GFA1 left offset = 0x%x (%i)\n", + voice, snd_gf1_i_read16(gus, 0x13), + snd_gf1_i_read16(gus, 0x13) >> 4); + dev_info(gus->card->dev, + " -%i- GFA1 left offset final = 0x%x (%i)\n", + voice, snd_gf1_i_read16(gus, 0x1c), + snd_gf1_i_read16(gus, 0x1c) >> 4); + dev_info(gus->card->dev, + " -%i- GFA1 right offset = 0x%x (%i)\n", + voice, snd_gf1_i_read16(gus, 0x0c), + snd_gf1_i_read16(gus, 0x0c) >> 4); + dev_info(gus->card->dev, + " -%i- GFA1 right offset final = 0x%x (%i)\n", + voice, snd_gf1_i_read16(gus, 0x1b), + snd_gf1_i_read16(gus, 0x1b) >> 4); } else - printk(KERN_INFO " -%i- GF1 pan = 0x%x\n", voice, snd_gf1_i_read8(gus, 0x0c)); + dev_info(gus->card->dev, + " -%i- GF1 pan = 0x%x\n", + voice, snd_gf1_i_read8(gus, 0x0c)); } else - printk(KERN_INFO " -%i- GF1 pan = 0x%x\n", voice, snd_gf1_i_read8(gus, 0x0c)); + dev_info(gus->card->dev, + " -%i- GF1 pan = 0x%x\n", + voice, snd_gf1_i_read8(gus, 0x0c)); } #if 0 @@ -465,61 +502,105 @@ void snd_gf1_print_global_registers(struct snd_gus_card * gus) { unsigned char global_mode = 0x00; - printk(KERN_INFO " -G- GF1 active voices = 0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_ACTIVE_VOICES)); + dev_info(gus->card->dev, + " -G- GF1 active voices = 0x%x\n", + snd_gf1_i_look8(gus, SNDRV_GF1_GB_ACTIVE_VOICES)); if (gus->interwave) { global_mode = snd_gf1_i_read8(gus, SNDRV_GF1_GB_GLOBAL_MODE); - printk(KERN_INFO " -G- GF1 global mode = 0x%x\n", global_mode); + dev_info(gus->card->dev, + " -G- GF1 global mode = 0x%x\n", + global_mode); } if (global_mode & 0x02) /* LFO enabled? */ - printk(KERN_INFO " -G- GF1 LFO base = 0x%x\n", snd_gf1_i_look16(gus, SNDRV_GF1_GW_LFO_BASE)); - printk(KERN_INFO " -G- GF1 voices IRQ read = 0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_VOICES_IRQ_READ)); - printk(KERN_INFO " -G- GF1 DRAM DMA control = 0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_DRAM_DMA_CONTROL)); - printk(KERN_INFO " -G- GF1 DRAM DMA high/low = 0x%x/0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_DRAM_DMA_HIGH), snd_gf1_i_read16(gus, SNDRV_GF1_GW_DRAM_DMA_LOW)); - printk(KERN_INFO " -G- GF1 DRAM IO high/low = 0x%x/0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_DRAM_IO_HIGH), snd_gf1_i_read16(gus, SNDRV_GF1_GW_DRAM_IO_LOW)); + dev_info(gus->card->dev, + " -G- GF1 LFO base = 0x%x\n", + snd_gf1_i_look16(gus, SNDRV_GF1_GW_LFO_BASE)); + dev_info(gus->card->dev, + " -G- GF1 voices IRQ read = 0x%x\n", + snd_gf1_i_look8(gus, SNDRV_GF1_GB_VOICES_IRQ_READ)); + dev_info(gus->card->dev, + " -G- GF1 DRAM DMA control = 0x%x\n", + snd_gf1_i_look8(gus, SNDRV_GF1_GB_DRAM_DMA_CONTROL)); + dev_info(gus->card->dev, + " -G- GF1 DRAM DMA high/low = 0x%x/0x%x\n", + snd_gf1_i_look8(gus, SNDRV_GF1_GB_DRAM_DMA_HIGH), + snd_gf1_i_read16(gus, SNDRV_GF1_GW_DRAM_DMA_LOW)); + dev_info(gus->card->dev, + " -G- GF1 DRAM IO high/low = 0x%x/0x%x\n", + snd_gf1_i_look8(gus, SNDRV_GF1_GB_DRAM_IO_HIGH), + snd_gf1_i_read16(gus, SNDRV_GF1_GW_DRAM_IO_LOW)); if (!gus->interwave) - printk(KERN_INFO " -G- GF1 record DMA control = 0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_REC_DMA_CONTROL)); - printk(KERN_INFO " -G- GF1 DRAM IO 16 = 0x%x\n", snd_gf1_i_look16(gus, SNDRV_GF1_GW_DRAM_IO16)); + dev_info(gus->card->dev, + " -G- GF1 record DMA control = 0x%x\n", + snd_gf1_i_look8(gus, SNDRV_GF1_GB_REC_DMA_CONTROL)); + dev_info(gus->card->dev, + " -G- GF1 DRAM IO 16 = 0x%x\n", + snd_gf1_i_look16(gus, SNDRV_GF1_GW_DRAM_IO16)); if (gus->gf1.enh_mode) { - printk(KERN_INFO " -G- GFA1 memory config = 0x%x\n", snd_gf1_i_look16(gus, SNDRV_GF1_GW_MEMORY_CONFIG)); - printk(KERN_INFO " -G- GFA1 memory control = 0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_MEMORY_CONTROL)); - printk(KERN_INFO " -G- GFA1 FIFO record base = 0x%x\n", snd_gf1_i_look16(gus, SNDRV_GF1_GW_FIFO_RECORD_BASE_ADDR)); - printk(KERN_INFO " -G- GFA1 FIFO playback base = 0x%x\n", snd_gf1_i_look16(gus, SNDRV_GF1_GW_FIFO_PLAY_BASE_ADDR)); - printk(KERN_INFO " -G- GFA1 interleave control = 0x%x\n", snd_gf1_i_look16(gus, SNDRV_GF1_GW_INTERLEAVE)); + dev_info(gus->card->dev, + " -G- GFA1 memory config = 0x%x\n", + snd_gf1_i_look16(gus, SNDRV_GF1_GW_MEMORY_CONFIG)); + dev_info(gus->card->dev, + " -G- GFA1 memory control = 0x%x\n", + snd_gf1_i_look8(gus, SNDRV_GF1_GB_MEMORY_CONTROL)); + dev_info(gus->card->dev, + " -G- GFA1 FIFO record base = 0x%x\n", + snd_gf1_i_look16(gus, SNDRV_GF1_GW_FIFO_RECORD_BASE_ADDR)); + dev_info(gus->card->dev, + " -G- GFA1 FIFO playback base = 0x%x\n", + snd_gf1_i_look16(gus, SNDRV_GF1_GW_FIFO_PLAY_BASE_ADDR)); + dev_info(gus->card->dev, + " -G- GFA1 interleave control = 0x%x\n", + snd_gf1_i_look16(gus, SNDRV_GF1_GW_INTERLEAVE)); } } void snd_gf1_print_setup_registers(struct snd_gus_card * gus) { - printk(KERN_INFO " -S- mix control = 0x%x\n", inb(GUSP(gus, MIXCNTRLREG))); - printk(KERN_INFO " -S- IRQ status = 0x%x\n", inb(GUSP(gus, IRQSTAT))); - printk(KERN_INFO " -S- timer control = 0x%x\n", inb(GUSP(gus, TIMERCNTRL))); - printk(KERN_INFO " -S- timer data = 0x%x\n", inb(GUSP(gus, TIMERDATA))); - printk(KERN_INFO " -S- status read = 0x%x\n", inb(GUSP(gus, REGCNTRLS))); - printk(KERN_INFO " -S- Sound Blaster control = 0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_SOUND_BLASTER_CONTROL)); - printk(KERN_INFO " -S- AdLib timer 1/2 = 0x%x/0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_ADLIB_TIMER_1), snd_gf1_i_look8(gus, SNDRV_GF1_GB_ADLIB_TIMER_2)); - printk(KERN_INFO " -S- reset = 0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)); + dev_info(gus->card->dev, + " -S- mix control = 0x%x\n", + inb(GUSP(gus, MIXCNTRLREG))); + dev_info(gus->card->dev, + " -S- IRQ status = 0x%x\n", + inb(GUSP(gus, IRQSTAT))); + dev_info(gus->card->dev, + " -S- timer control = 0x%x\n", + inb(GUSP(gus, TIMERCNTRL))); + dev_info(gus->card->dev, + " -S- timer data = 0x%x\n", + inb(GUSP(gus, TIMERDATA))); + dev_info(gus->card->dev, + " -S- status read = 0x%x\n", + inb(GUSP(gus, REGCNTRLS))); + dev_info(gus->card->dev, + " -S- Sound Blaster control = 0x%x\n", + snd_gf1_i_look8(gus, SNDRV_GF1_GB_SOUND_BLASTER_CONTROL)); + dev_info(gus->card->dev, + " -S- AdLib timer 1/2 = 0x%x/0x%x\n", + snd_gf1_i_look8(gus, SNDRV_GF1_GB_ADLIB_TIMER_1), + snd_gf1_i_look8(gus, SNDRV_GF1_GB_ADLIB_TIMER_2)); + dev_info(gus->card->dev, + " -S- reset = 0x%x\n", + snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)); if (gus->interwave) { - printk(KERN_INFO " -S- compatibility = 0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_COMPATIBILITY)); - printk(KERN_INFO " -S- decode control = 0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_DECODE_CONTROL)); - printk(KERN_INFO " -S- version number = 0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_VERSION_NUMBER)); - printk(KERN_INFO " -S- MPU-401 emul. control A/B = 0x%x/0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_MPU401_CONTROL_A), snd_gf1_i_look8(gus, SNDRV_GF1_GB_MPU401_CONTROL_B)); - printk(KERN_INFO " -S- emulation IRQ = 0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_EMULATION_IRQ)); + dev_info(gus->card->dev, + " -S- compatibility = 0x%x\n", + snd_gf1_i_look8(gus, SNDRV_GF1_GB_COMPATIBILITY)); + dev_info(gus->card->dev, + " -S- decode control = 0x%x\n", + snd_gf1_i_look8(gus, SNDRV_GF1_GB_DECODE_CONTROL)); + dev_info(gus->card->dev, + " -S- version number = 0x%x\n", + snd_gf1_i_look8(gus, SNDRV_GF1_GB_VERSION_NUMBER)); + dev_info(gus->card->dev, + " -S- MPU-401 emul. control A/B = 0x%x/0x%x\n", + snd_gf1_i_look8(gus, SNDRV_GF1_GB_MPU401_CONTROL_A), + snd_gf1_i_look8(gus, SNDRV_GF1_GB_MPU401_CONTROL_B)); + dev_info(gus->card->dev, + " -S- emulation IRQ = 0x%x\n", + snd_gf1_i_look8(gus, SNDRV_GF1_GB_EMULATION_IRQ)); } } - -void snd_gf1_peek_print_block(struct snd_gus_card * gus, unsigned int addr, int count, int w_16bit) -{ - if (!w_16bit) { - while (count-- > 0) - printk(count > 0 ? "%02x:" : "%02x", snd_gf1_peek(gus, addr++)); - } else { - while (count-- > 0) { - printk(count > 0 ? "%04x:" : "%04x", snd_gf1_peek(gus, addr) | (snd_gf1_peek(gus, addr + 1) << 8)); - addr += 2; - } - } -} - #endif /* 0 */ #endif diff --git a/sound/isa/gus/gus_irq.c b/sound/isa/gus/gus_irq.c index 226b8438aa7030..0e1054402c91e1 100644 --- a/sound/isa/gus/gus_irq.c +++ b/sound/isa/gus/gus_irq.c @@ -26,7 +26,6 @@ irqreturn_t snd_gus_interrupt(int irq, void *dev_id) if (status == 0) return IRQ_RETVAL(handled); handled = 1; - /* snd_printk(KERN_DEBUG "IRQ: status = 0x%x\n", status); */ if (status & 0x02) { STAT_ADD(gus->gf1.interrupt_stat_midi_in); if (gus->gf1.interrupt_handler_midi_in) @@ -50,9 +49,9 @@ irqreturn_t snd_gus_interrupt(int irq, void *dev_id) continue; /* multi request */ already |= _current_; /* mark request */ #if 0 - printk(KERN_DEBUG "voice = %i, voice_status = 0x%x, " - "voice_verify = %i\n", - voice, voice_status, inb(GUSP(gus, GF1PAGE))); + dev_dbg(gus->card->dev, + "voice = %i, voice_status = 0x%x, voice_verify = %i\n", + voice, voice_status, inb(GUSP(gus, GF1PAGE))); #endif pvoice = &gus->gf1.voices[voice]; if (pvoice->use) { diff --git a/sound/isa/gus/gus_main.c b/sound/isa/gus/gus_main.c index 3b46490271fe16..51ce405eba7a25 100644 --- a/sound/isa/gus/gus_main.c +++ b/sound/isa/gus/gus_main.c @@ -158,32 +158,32 @@ int snd_gus_create(struct snd_card *card, /* allocate resources */ gus->gf1.res_port1 = request_region(port, 16, "GUS GF1 (Adlib/SB)"); if (!gus->gf1.res_port1) { - snd_printk(KERN_ERR "gus: can't grab SB port 0x%lx\n", port); + dev_err(card->dev, "gus: can't grab SB port 0x%lx\n", port); snd_gus_free(gus); return -EBUSY; } gus->gf1.res_port2 = request_region(port + 0x100, 12, "GUS GF1 (Synth)"); if (!gus->gf1.res_port2) { - snd_printk(KERN_ERR "gus: can't grab synth port 0x%lx\n", port + 0x100); + dev_err(card->dev, "gus: can't grab synth port 0x%lx\n", port + 0x100); snd_gus_free(gus); return -EBUSY; } if (irq >= 0 && request_irq(irq, snd_gus_interrupt, 0, "GUS GF1", (void *) gus)) { - snd_printk(KERN_ERR "gus: can't grab irq %d\n", irq); + dev_err(card->dev, "gus: can't grab irq %d\n", irq); snd_gus_free(gus); return -EBUSY; } gus->gf1.irq = irq; card->sync_irq = irq; if (request_dma(dma1, "GUS - 1")) { - snd_printk(KERN_ERR "gus: can't grab DMA1 %d\n", dma1); + dev_err(card->dev, "gus: can't grab DMA1 %d\n", dma1); snd_gus_free(gus); return -EBUSY; } gus->gf1.dma1 = dma1; if (dma2 >= 0 && dma1 != dma2) { if (request_dma(dma2, "GUS - 2")) { - snd_printk(KERN_ERR "gus: can't grab DMA2 %d\n", dma2); + dev_err(card->dev, "gus: can't grab DMA2 %d\n", dma2); snd_gus_free(gus); return -EBUSY; } @@ -229,7 +229,9 @@ static int snd_gus_detect_memory(struct snd_gus_card * gus) snd_gf1_poke(gus, 0L, 0xaa); snd_gf1_poke(gus, 1L, 0x55); if (snd_gf1_peek(gus, 0L) != 0xaa || snd_gf1_peek(gus, 1L) != 0x55) { - snd_printk(KERN_ERR "plain GF1 card at 0x%lx without onboard DRAM?\n", gus->gf1.port); + dev_err(gus->card->dev, + "plain GF1 card at 0x%lx without onboard DRAM?\n", + gus->gf1.port); return -ENOMEM; } for (idx = 1, d = 0xab; idx < 4; idx++, d++) { @@ -287,14 +289,14 @@ static int snd_gus_init_dma_irq(struct snd_gus_card * gus, int latches) dma1 |= gus->equal_dma ? 0x40 : (dma2 << 3); if ((dma1 & 7) == 0 || (dma2 & 7) == 0) { - snd_printk(KERN_ERR "Error! DMA isn't defined.\n"); + dev_err(gus->card->dev, "Error! DMA isn't defined.\n"); return -EINVAL; } irq = gus->gf1.irq; irq = abs(irq); irq = irqs[irq & 0x0f]; if (irq == 0) { - snd_printk(KERN_ERR "Error! IRQ isn't defined.\n"); + dev_err(gus->card->dev, "Error! IRQ isn't defined.\n"); return -EINVAL; } irq |= 0x40; @@ -357,7 +359,7 @@ static int snd_gus_check_version(struct snd_gus_card * gus) val = inb(GUSP(gus, REGCNTRLS)); rev = inb(GUSP(gus, BOARDVERSION)); spin_unlock_irqrestore(&gus->reg_lock, flags); - snd_printdd("GF1 [0x%lx] init - val = 0x%x, rev = 0x%x\n", gus->gf1.port, val, rev); + dev_dbg(card->dev, "GF1 [0x%lx] init - val = 0x%x, rev = 0x%x\n", gus->gf1.port, val, rev); strcpy(card->driver, "GUS"); strcpy(card->longname, "Gravis UltraSound Classic (2.4)"); if ((val != 255 && (val & 0x06)) || (rev >= 5 && rev != 255)) { @@ -382,8 +384,11 @@ static int snd_gus_check_version(struct snd_gus_card * gus) strcpy(card->longname, "Gravis UltraSound Extreme"); gus->ess_flag = 1; } else { - snd_printk(KERN_ERR "unknown GF1 revision number at 0x%lx - 0x%x (0x%x)\n", gus->gf1.port, rev, val); - snd_printk(KERN_ERR " please - report to \n"); + dev_err(card->dev, + "unknown GF1 revision number at 0x%lx - 0x%x (0x%x)\n", + gus->gf1.port, rev, val); + dev_err(card->dev, + " please - report to \n"); } } } @@ -400,7 +405,7 @@ int snd_gus_initialize(struct snd_gus_card *gus) if (!gus->interwave) { err = snd_gus_check_version(gus); if (err < 0) { - snd_printk(KERN_ERR "version check failed\n"); + dev_err(gus->card->dev, "version check failed\n"); return err; } err = snd_gus_detect_memory(gus); diff --git a/sound/isa/gus/gus_mem.c b/sound/isa/gus/gus_mem.c index 3e56c01c45445e..054058779db608 100644 --- a/sound/isa/gus/gus_mem.c +++ b/sound/isa/gus/gus_mem.c @@ -189,7 +189,7 @@ struct snd_gf1_mem_block *snd_gf1_mem_alloc(struct snd_gf1_mem * alloc, int owne if (nblock != NULL) { if (size != (int)nblock->size) { /* TODO: remove in the future */ - snd_printk(KERN_ERR "snd_gf1_mem_alloc - share: sizes differ\n"); + pr_err("%s - share: sizes differ\n", __func__); goto __std; } nblock->share++; diff --git a/sound/isa/gus/gus_pcm.c b/sound/isa/gus/gus_pcm.c index 850544725da796..bcbcaa924c1278 100644 --- a/sound/isa/gus/gus_pcm.c +++ b/sound/isa/gus/gus_pcm.c @@ -67,10 +67,6 @@ static int snd_gf1_pcm_block_change(struct snd_pcm_substream *substream, count += offset & 31; offset &= ~31; - /* - snd_printk(KERN_DEBUG "block change - offset = 0x%x, count = 0x%x\n", - offset, count); - */ memset(&block, 0, sizeof(block)); block.cmd = SNDRV_GF1_DMA_IRQ; if (snd_pcm_format_unsigned(runtime->format)) @@ -123,11 +119,6 @@ static void snd_gf1_pcm_trigger_up(struct snd_pcm_substream *substream) curr = begin + (pcmp->bpos * pcmp->block_size) / runtime->channels; end = curr + (pcmp->block_size / runtime->channels); end -= snd_pcm_format_width(runtime->format) == 16 ? 2 : 1; - /* - snd_printk(KERN_DEBUG "init: curr=0x%x, begin=0x%x, end=0x%x, " - "ctrl=0x%x, ramp=0x%x, rate=0x%x\n", - curr, begin, end, voice_ctrl, ramp_ctrl, rate); - */ pan = runtime->channels == 2 ? (!voice ? 1 : 14) : 8; vol = !voice ? gus->gf1.pcm_volume_level_left : gus->gf1.pcm_volume_level_right; spin_lock_irqsave(&gus->reg_lock, flags); @@ -178,13 +169,13 @@ static void snd_gf1_pcm_interrupt_wave(struct snd_gus_card * gus, unsigned int end, step; if (!pvoice->private_data) { - snd_printd("snd_gf1_pcm: unknown wave irq?\n"); + dev_dbg(gus->card->dev, "%s: unknown wave irq?\n", __func__); snd_gf1_smart_stop_voice(gus, pvoice->number); return; } pcmp = pvoice->private_data; if (pcmp == NULL) { - snd_printd("snd_gf1_pcm: unknown wave irq?\n"); + dev_dbg(gus->card->dev, "%s: unknown wave irq?\n", __func__); snd_gf1_smart_stop_voice(gus, pvoice->number); return; } @@ -197,11 +188,11 @@ static void snd_gf1_pcm_interrupt_wave(struct snd_gus_card * gus, ramp_ctrl = (snd_gf1_read8(gus, SNDRV_GF1_VB_VOLUME_CONTROL) & ~0xa4) | 0x03; #if 0 snd_gf1_select_voice(gus, pvoice->number); - printk(KERN_DEBUG "position = 0x%x\n", - (snd_gf1_read_addr(gus, SNDRV_GF1_VA_CURRENT, voice_ctrl & 4) >> 4)); + dev_dbg(gus->card->dev, "position = 0x%x\n", + (snd_gf1_read_addr(gus, SNDRV_GF1_VA_CURRENT, voice_ctrl & 4) >> 4)); snd_gf1_select_voice(gus, pcmp->pvoices[1]->number); - printk(KERN_DEBUG "position = 0x%x\n", - (snd_gf1_read_addr(gus, SNDRV_GF1_VA_CURRENT, voice_ctrl & 4) >> 4)); + dev_dbg(gus->card->dev, "position = 0x%x\n", + (snd_gf1_read_addr(gus, SNDRV_GF1_VA_CURRENT, voice_ctrl & 4) >> 4)); snd_gf1_select_voice(gus, pvoice->number); #endif pcmp->bpos++; @@ -293,11 +284,6 @@ static int snd_gf1_pcm_poke_block(struct snd_gus_card *gus, unsigned char *buf, unsigned int len; unsigned long flags; - /* - printk(KERN_DEBUG - "poke block; buf = 0x%x, pos = %i, count = %i, port = 0x%x\n", - (int)buf, pos, count, gus->gf1.port); - */ while (count > 0) { len = count; if (len > 512) /* limit, to allow IRQ */ @@ -673,8 +659,9 @@ static int snd_gf1_pcm_playback_open(struct snd_pcm_substream *substream) runtime->private_free = snd_gf1_pcm_playback_free; #if 0 - printk(KERN_DEBUG "playback.buffer = 0x%lx, gf1.pcm_buffer = 0x%lx\n", - (long) pcm->playback.buffer, (long) gus->gf1.pcm_buffer); + dev_dbg(gus->card->dev, + "playback.buffer = 0x%lx, gf1.pcm_buffer = 0x%lx\n", + (long) pcm->playback.buffer, (long) gus->gf1.pcm_buffer); #endif err = snd_gf1_dma_init(gus); if (err < 0) @@ -695,7 +682,7 @@ static int snd_gf1_pcm_playback_close(struct snd_pcm_substream *substream) struct gus_pcm_private *pcmp = runtime->private_data; if (!wait_event_timeout(pcmp->sleep, (atomic_read(&pcmp->dma_count) <= 0), 2*HZ)) - snd_printk(KERN_ERR "gf1 pcm - serious DMA problem\n"); + dev_err(gus->card->dev, "gf1 pcm - serious DMA problem\n"); snd_gf1_dma_done(gus); return 0; diff --git a/sound/isa/gus/gus_reset.c b/sound/isa/gus/gus_reset.c index 9a1ab5872c4fab..ac5da128104200 100644 --- a/sound/isa/gus/gus_reset.c +++ b/sound/isa/gus/gus_reset.c @@ -116,7 +116,9 @@ void snd_gf1_smart_stop_voice(struct snd_gus_card * gus, unsigned short voice) spin_lock_irqsave(&gus->reg_lock, flags); snd_gf1_select_voice(gus, voice); #if 0 - printk(KERN_DEBUG " -%i- smart stop voice - volume = 0x%x\n", voice, snd_gf1_i_read16(gus, SNDRV_GF1_VW_VOLUME)); + dev_dbg(gus->card->dev, + " -%i- smart stop voice - volume = 0x%x\n", + voice, snd_gf1_i_read16(gus, SNDRV_GF1_VW_VOLUME)); #endif snd_gf1_ctrl_stop(gus, SNDRV_GF1_VB_ADDRESS_CONTROL); snd_gf1_ctrl_stop(gus, SNDRV_GF1_VB_VOLUME_CONTROL); @@ -130,7 +132,9 @@ void snd_gf1_stop_voice(struct snd_gus_card * gus, unsigned short voice) spin_lock_irqsave(&gus->reg_lock, flags); snd_gf1_select_voice(gus, voice); #if 0 - printk(KERN_DEBUG " -%i- stop voice - volume = 0x%x\n", voice, snd_gf1_i_read16(gus, SNDRV_GF1_VW_VOLUME)); + dev_dbg(gus->card->dev, + " -%i- stop voice - volume = 0x%x\n", + voice, snd_gf1_i_read16(gus, SNDRV_GF1_VW_VOLUME)); #endif snd_gf1_ctrl_stop(gus, SNDRV_GF1_VB_ADDRESS_CONTROL); snd_gf1_ctrl_stop(gus, SNDRV_GF1_VB_VOLUME_CONTROL); diff --git a/sound/isa/gus/gus_uart.c b/sound/isa/gus/gus_uart.c index 3975848160e797..08276509447fe9 100644 --- a/sound/isa/gus/gus_uart.c +++ b/sound/isa/gus/gus_uart.c @@ -89,7 +89,9 @@ static int snd_gf1_uart_output_open(struct snd_rawmidi_substream *substream) gus->midi_substream_output = substream; spin_unlock_irqrestore(&gus->uart_cmd_lock, flags); #if 0 - snd_printk(KERN_DEBUG "write init - cmd = 0x%x, stat = 0x%x\n", gus->gf1.uart_cmd, snd_gf1_uart_stat(gus)); + dev_dbg(gus->card->dev, + "write init - cmd = 0x%x, stat = 0x%x\n", + gus->gf1.uart_cmd, snd_gf1_uart_stat(gus)); #endif return 0; } @@ -111,18 +113,17 @@ static int snd_gf1_uart_input_open(struct snd_rawmidi_substream *substream) for (i = 0; i < 1000 && (snd_gf1_uart_stat(gus) & 0x01); i++) snd_gf1_uart_get(gus); /* clean Rx */ if (i >= 1000) - snd_printk(KERN_ERR "gus midi uart init read - cleanup error\n"); + dev_err(gus->card->dev, "gus midi uart init read - cleanup error\n"); } spin_unlock_irqrestore(&gus->uart_cmd_lock, flags); #if 0 - snd_printk(KERN_DEBUG - "read init - enable = %i, cmd = 0x%x, stat = 0x%x\n", - gus->uart_enable, gus->gf1.uart_cmd, snd_gf1_uart_stat(gus)); - snd_printk(KERN_DEBUG - "[0x%x] reg (ctrl/status) = 0x%x, reg (data) = 0x%x " - "(page = 0x%x)\n", - gus->gf1.port + 0x100, inb(gus->gf1.port + 0x100), - inb(gus->gf1.port + 0x101), inb(gus->gf1.port + 0x102)); + dev_dbg(gus->card->dev, + "read init - enable = %i, cmd = 0x%x, stat = 0x%x\n", + gus->uart_enable, gus->gf1.uart_cmd, snd_gf1_uart_stat(gus)); + dev_dbg(gus->card->dev, + "[0x%x] reg (ctrl/status) = 0x%x, reg (data) = 0x%x (page = 0x%x)\n", + gus->gf1.port + 0x100, inb(gus->gf1.port + 0x100), + inb(gus->gf1.port + 0x101), inb(gus->gf1.port + 0x102)); #endif return 0; } diff --git a/sound/isa/gus/gus_volume.c b/sound/isa/gus/gus_volume.c index ed72196a361b82..e729621756cf9f 100644 --- a/sound/isa/gus/gus_volume.c +++ b/sound/isa/gus/gus_volume.c @@ -104,7 +104,8 @@ unsigned short snd_gf1_translate_freq(struct snd_gus_card * gus, unsigned int fr freq16 = 50; if (freq16 & 0xf8000000) { freq16 = ~0xf8000000; - snd_printk(KERN_ERR "snd_gf1_translate_freq: overflow - freq = 0x%x\n", freq16); + dev_err(gus->card->dev, "%s: overflow - freq = 0x%x\n", + __func__, freq16); } return ((freq16 << 9) + (gus->gf1.playback_freq >> 1)) / gus->gf1.playback_freq; } @@ -189,14 +190,14 @@ unsigned short snd_gf1_compute_freq(unsigned int freq, fc = (freq << 10) / rate; if (fc > 97391L) { fc = 97391; - snd_printk(KERN_ERR "patch: (1) fc frequency overflow - %u\n", fc); + pr_err("patch: (1) fc frequency overflow - %u\n", fc); } fc = (fc * 44100UL) / mix_rate; while (scale--) fc <<= 1; if (fc > 65535L) { fc = 65535; - snd_printk(KERN_ERR "patch: (2) fc frequency overflow - %u\n", fc); + pr_err("patch: (2) fc frequency overflow - %u\n", fc); } return (unsigned short) fc; } diff --git a/sound/isa/gus/gusclassic.c b/sound/isa/gus/gusclassic.c index 09cc53ceea2aea..101202acefb366 100644 --- a/sound/isa/gus/gusclassic.c +++ b/sound/isa/gus/gusclassic.c @@ -115,7 +115,7 @@ static int snd_gusclassic_detect(struct snd_gus_card *gus) snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 0); /* reset GF1 */ d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET); if ((d & 0x07) != 0) { - snd_printdd("[0x%lx] check 1 failed - 0x%x\n", gus->gf1.port, d); + dev_dbg(gus->card->dev, "[0x%lx] check 1 failed - 0x%x\n", gus->gf1.port, d); return -ENODEV; } udelay(160); @@ -123,7 +123,7 @@ static int snd_gusclassic_detect(struct snd_gus_card *gus) udelay(160); d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET); if ((d & 0x07) != 1) { - snd_printdd("[0x%lx] check 2 failed - 0x%x\n", gus->gf1.port, d); + dev_dbg(gus->card->dev, "[0x%lx] check 2 failed - 0x%x\n", gus->gf1.port, d); return -ENODEV; } return 0; diff --git a/sound/isa/gus/gusextreme.c b/sound/isa/gus/gusextreme.c index 63d9f2d75df0c9..6eab95bd49c1d6 100644 --- a/sound/isa/gus/gusextreme.c +++ b/sound/isa/gus/gusextreme.c @@ -179,7 +179,7 @@ static int snd_gusextreme_detect(struct snd_gus_card *gus, snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 0); /* reset GF1 */ d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET); if ((d & 0x07) != 0) { - snd_printdd("[0x%lx] check 1 failed - 0x%x\n", gus->gf1.port, d); + dev_dbg(gus->card->dev, "[0x%lx] check 1 failed - 0x%x\n", gus->gf1.port, d); return -EIO; } udelay(160); @@ -187,7 +187,7 @@ static int snd_gusextreme_detect(struct snd_gus_card *gus, udelay(160); d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET); if ((d & 0x07) != 1) { - snd_printdd("[0x%lx] check 2 failed - 0x%x\n", gus->gf1.port, d); + dev_dbg(gus->card->dev, "[0x%lx] check 2 failed - 0x%x\n", gus->gf1.port, d); return -EIO; } diff --git a/sound/isa/gus/gusmax.c b/sound/isa/gus/gusmax.c index 6834c056006405..445fd2fb50f102 100644 --- a/sound/isa/gus/gusmax.c +++ b/sound/isa/gus/gusmax.c @@ -64,8 +64,6 @@ struct snd_gusmax { unsigned short pcm_status_reg; }; -#define PFX "gusmax: " - static int snd_gusmax_detect(struct snd_gus_card *gus) { unsigned char d; @@ -73,7 +71,7 @@ static int snd_gusmax_detect(struct snd_gus_card *gus) snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 0); /* reset GF1 */ d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET); if ((d & 0x07) != 0) { - snd_printdd("[0x%lx] check 1 failed - 0x%x\n", gus->gf1.port, d); + dev_dbg(gus->card->dev, "[0x%lx] check 1 failed - 0x%x\n", gus->gf1.port, d); return -ENODEV; } udelay(160); @@ -81,7 +79,7 @@ static int snd_gusmax_detect(struct snd_gus_card *gus) udelay(160); d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET); if ((d & 0x07) != 1) { - snd_printdd("[0x%lx] check 2 failed - 0x%x\n", gus->gf1.port, d); + dev_dbg(gus->card->dev, "[0x%lx] check 2 failed - 0x%x\n", gus->gf1.port, d); return -ENODEV; } @@ -206,7 +204,7 @@ static int snd_gusmax_probe(struct device *pdev, unsigned int dev) if (xirq == SNDRV_AUTO_IRQ) { xirq = snd_legacy_find_free_irq(possible_irqs); if (xirq < 0) { - snd_printk(KERN_ERR PFX "unable to find a free IRQ\n"); + dev_err(pdev, "unable to find a free IRQ\n"); return -EBUSY; } } @@ -214,7 +212,7 @@ static int snd_gusmax_probe(struct device *pdev, unsigned int dev) if (xdma1 == SNDRV_AUTO_DMA) { xdma1 = snd_legacy_find_free_dma(possible_dmas); if (xdma1 < 0) { - snd_printk(KERN_ERR PFX "unable to find a free DMA1\n"); + dev_err(pdev, "unable to find a free DMA1\n"); return -EBUSY; } } @@ -222,7 +220,7 @@ static int snd_gusmax_probe(struct device *pdev, unsigned int dev) if (xdma2 == SNDRV_AUTO_DMA) { xdma2 = snd_legacy_find_free_dma(possible_dmas); if (xdma2 < 0) { - snd_printk(KERN_ERR PFX "unable to find a free DMA2\n"); + dev_err(pdev, "unable to find a free DMA2\n"); return -EBUSY; } } @@ -267,13 +265,13 @@ static int snd_gusmax_probe(struct device *pdev, unsigned int dev) return err; if (!gus->max_flag) { - snd_printk(KERN_ERR PFX "GUS MAX soundcard was not detected at 0x%lx\n", gus->gf1.port); + dev_err(pdev, "GUS MAX soundcard was not detected at 0x%lx\n", gus->gf1.port); return -ENODEV; } if (devm_request_irq(card->dev, xirq, snd_gusmax_interrupt, 0, "GUS MAX", (void *)maxcard)) { - snd_printk(KERN_ERR PFX "unable to grab IRQ %d\n", xirq); + dev_err(pdev, "unable to grab IRQ %d\n", xirq); return -EBUSY; } maxcard->irq = xirq; diff --git a/sound/isa/gus/interwave.c b/sound/isa/gus/interwave.c index a04a9d3253f88d..18a98123e2867c 100644 --- a/sound/isa/gus/interwave.c +++ b/sound/isa/gus/interwave.c @@ -52,11 +52,9 @@ static int pcm_channels[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2}; static int effect[SNDRV_CARDS]; #ifdef SNDRV_STB -#define PFX "interwave-stb: " #define INTERWAVE_DRIVER "snd_interwave_stb" #define INTERWAVE_PNP_DRIVER "interwave-stb" #else -#define PFX "interwave: " #define INTERWAVE_DRIVER "snd_interwave" #define INTERWAVE_PNP_DRIVER "interwave" #endif @@ -148,7 +146,7 @@ static void snd_interwave_i2c_setlines(struct snd_i2c_bus *bus, int ctrl, int da unsigned long port = bus->private_value; #if 0 - printk(KERN_DEBUG "i2c_setlines - 0x%lx <- %i,%i\n", port, ctrl, data); + dev_dbg(bus->card->dev, "i2c_setlines - 0x%lx <- %i,%i\n", port, ctrl, data); #endif outb((data << 1) | ctrl, port); udelay(10); @@ -161,7 +159,7 @@ static int snd_interwave_i2c_getclockline(struct snd_i2c_bus *bus) res = inb(port) & 1; #if 0 - printk(KERN_DEBUG "i2c_getclockline - 0x%lx -> %i\n", port, res); + dev_dbg(bus->card->dev, "i2c_getclockline - 0x%lx -> %i\n", port, res); #endif return res; } @@ -175,7 +173,7 @@ static int snd_interwave_i2c_getdataline(struct snd_i2c_bus *bus, int ack) udelay(10); res = (inb(port) & 2) >> 1; #if 0 - printk(KERN_DEBUG "i2c_getdataline - 0x%lx -> %i\n", port, res); + dev_dbg(bus->card->dev, "i2c_getdataline - 0x%lx -> %i\n", port, res); #endif return res; } @@ -215,7 +213,7 @@ static int snd_interwave_detect_stb(struct snd_interwave *iwcard, "InterWave (I2C bus)"); } if (iwcard->i2c_res == NULL) { - snd_printk(KERN_ERR "interwave: can't grab i2c bus port\n"); + dev_err(card->dev, "interwave: can't grab i2c bus port\n"); return -ENODEV; } @@ -248,7 +246,7 @@ static int snd_interwave_detect(struct snd_interwave *iwcard, snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 0); /* reset GF1 */ d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET); if ((d & 0x07) != 0) { - snd_printdd("[0x%lx] check 1 failed - 0x%x\n", gus->gf1.port, d); + dev_dbg(gus->card->dev, "[0x%lx] check 1 failed - 0x%x\n", gus->gf1.port, d); return -ENODEV; } udelay(160); @@ -256,7 +254,7 @@ static int snd_interwave_detect(struct snd_interwave *iwcard, udelay(160); d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET); if ((d & 0x07) != 1) { - snd_printdd("[0x%lx] check 2 failed - 0x%x\n", gus->gf1.port, d); + dev_dbg(gus->card->dev, "[0x%lx] check 2 failed - 0x%x\n", gus->gf1.port, d); return -ENODEV; } spin_lock_irqsave(&gus->reg_lock, flags); @@ -265,10 +263,13 @@ static int snd_interwave_detect(struct snd_interwave *iwcard, rev2 = snd_gf1_look8(gus, SNDRV_GF1_GB_VERSION_NUMBER); snd_gf1_write8(gus, SNDRV_GF1_GB_VERSION_NUMBER, rev1); spin_unlock_irqrestore(&gus->reg_lock, flags); - snd_printdd("[0x%lx] InterWave check - rev1=0x%x, rev2=0x%x\n", gus->gf1.port, rev1, rev2); + dev_dbg(gus->card->dev, + "[0x%lx] InterWave check - rev1=0x%x, rev2=0x%x\n", + gus->gf1.port, rev1, rev2); if ((rev1 & 0xf0) == (rev2 & 0xf0) && (rev1 & 0x0f) != (rev2 & 0x0f)) { - snd_printdd("[0x%lx] InterWave check - passed\n", gus->gf1.port); + dev_dbg(gus->card->dev, + "[0x%lx] InterWave check - passed\n", gus->gf1.port); gus->interwave = 1; strcpy(gus->card->shortname, "AMD InterWave"); gus->revision = rev1 >> 4; @@ -278,7 +279,7 @@ static int snd_interwave_detect(struct snd_interwave *iwcard, return snd_interwave_detect_stb(iwcard, gus, dev, rbus); #endif } - snd_printdd("[0x%lx] InterWave check - failed\n", gus->gf1.port); + dev_dbg(gus->card->dev, "[0x%lx] InterWave check - failed\n", gus->gf1.port); return -ENODEV; } @@ -327,7 +328,7 @@ static void snd_interwave_bank_sizes(struct snd_gus_card *gus, int *sizes) snd_gf1_poke(gus, local, d); snd_gf1_poke(gus, local + 1, d + 1); #if 0 - printk(KERN_DEBUG "d = 0x%x, local = 0x%x, " + dev_dbg(gus->card->dev, "d = 0x%x, local = 0x%x, " "local + 1 = 0x%x, idx << 22 = 0x%x\n", d, snd_gf1_peek(gus, local), @@ -342,7 +343,7 @@ static void snd_interwave_bank_sizes(struct snd_gus_card *gus, int *sizes) } } #if 0 - printk(KERN_DEBUG "sizes: %i %i %i %i\n", + dev_dbg(gus->card->dev, "sizes: %i %i %i %i\n", sizes[0], sizes[1], sizes[2], sizes[3]); #endif } @@ -397,12 +398,12 @@ static void snd_interwave_detect_memory(struct snd_gus_card *gus) lmct = (psizes[3] << 24) | (psizes[2] << 16) | (psizes[1] << 8) | psizes[0]; #if 0 - printk(KERN_DEBUG "lmct = 0x%08x\n", lmct); + dev_dbg(gus->card->dev, "lmct = 0x%08x\n", lmct); #endif for (i = 0; i < ARRAY_SIZE(lmc); i++) if (lmct == lmc[i]) { #if 0 - printk(KERN_DEBUG "found !!! %i\n", i); + dev_dbg(gus->card->dev, "found !!! %i\n", i); #endif snd_gf1_write16(gus, SNDRV_GF1_GW_MEMORY_CONFIG, (snd_gf1_look16(gus, SNDRV_GF1_GW_MEMORY_CONFIG) & 0xfff0) | i); snd_interwave_bank_sizes(gus, psizes); @@ -566,12 +567,12 @@ static int snd_interwave_pnp(int dev, struct snd_interwave *iwcard, err = pnp_activate_dev(pdev); if (err < 0) { - snd_printk(KERN_ERR "InterWave PnP configure failure (out of resources?)\n"); + dev_err(&pdev->dev, "InterWave PnP configure failure (out of resources?)\n"); return err; } if (pnp_port_start(pdev, 0) + 0x100 != pnp_port_start(pdev, 1) || pnp_port_start(pdev, 0) + 0x10c != pnp_port_start(pdev, 2)) { - snd_printk(KERN_ERR "PnP configure failure (wrong ports)\n"); + dev_err(&pdev->dev, "PnP configure failure (wrong ports)\n"); return -ENOENT; } port[dev] = pnp_port_start(pdev, 0); @@ -579,22 +580,26 @@ static int snd_interwave_pnp(int dev, struct snd_interwave *iwcard, if (dma2[dev] >= 0) dma2[dev] = pnp_dma(pdev, 1); irq[dev] = pnp_irq(pdev, 0); - snd_printdd("isapnp IW: sb port=0x%llx, gf1 port=0x%llx, codec port=0x%llx\n", - (unsigned long long)pnp_port_start(pdev, 0), - (unsigned long long)pnp_port_start(pdev, 1), - (unsigned long long)pnp_port_start(pdev, 2)); - snd_printdd("isapnp IW: dma1=%i, dma2=%i, irq=%i\n", dma1[dev], dma2[dev], irq[dev]); + dev_dbg(&pdev->dev, + "isapnp IW: sb port=0x%llx, gf1 port=0x%llx, codec port=0x%llx\n", + (unsigned long long)pnp_port_start(pdev, 0), + (unsigned long long)pnp_port_start(pdev, 1), + (unsigned long long)pnp_port_start(pdev, 2)); + dev_dbg(&pdev->dev, + "isapnp IW: dma1=%i, dma2=%i, irq=%i\n", + dma1[dev], dma2[dev], irq[dev]); #ifdef SNDRV_STB /* Tone Control initialization */ pdev = iwcard->devtc; err = pnp_activate_dev(pdev); if (err < 0) { - snd_printk(KERN_ERR "InterWave ToneControl PnP configure failure (out of resources?)\n"); + dev_err(&pdev->dev, + "InterWave ToneControl PnP configure failure (out of resources?)\n"); return err; } port_tc[dev] = pnp_port_start(pdev, 0); - snd_printdd("isapnp IW: tone control port=0x%lx\n", port_tc[dev]); + dev_dbg(&pdev->dev, "isapnp IW: tone control port=0x%lx\n", port_tc[dev]); #endif return 0; } @@ -660,7 +665,7 @@ static int snd_interwave_probe(struct snd_card *card, int dev, if (devm_request_irq(card->dev, xirq, snd_interwave_interrupt, 0, "InterWave", iwcard)) { - snd_printk(KERN_ERR PFX "unable to grab IRQ %d\n", xirq); + dev_err(card->dev, "unable to grab IRQ %d\n", xirq); return -EBUSY; } iwcard->irq = xirq; @@ -780,21 +785,21 @@ static int snd_interwave_isa_probe(struct device *pdev, if (irq[dev] == SNDRV_AUTO_IRQ) { irq[dev] = snd_legacy_find_free_irq(possible_irqs); if (irq[dev] < 0) { - snd_printk(KERN_ERR PFX "unable to find a free IRQ\n"); + dev_err(pdev, "unable to find a free IRQ\n"); return -EBUSY; } } if (dma1[dev] == SNDRV_AUTO_DMA) { dma1[dev] = snd_legacy_find_free_dma(possible_dmas); if (dma1[dev] < 0) { - snd_printk(KERN_ERR PFX "unable to find a free DMA1\n"); + dev_err(pdev, "unable to find a free DMA1\n"); return -EBUSY; } } if (dma2[dev] == SNDRV_AUTO_DMA) { dma2[dev] = snd_legacy_find_free_dma(possible_dmas); if (dma2[dev] < 0) { - snd_printk(KERN_ERR PFX "unable to find a free DMA2\n"); + dev_err(pdev, "unable to find a free DMA2\n"); return -EBUSY; } } diff --git a/sound/isa/msnd/msnd.c b/sound/isa/msnd/msnd.c index c3fd1eb301bb18..69c515421dd81e 100644 --- a/sound/isa/msnd/msnd.c +++ b/sound/isa/msnd/msnd.c @@ -86,7 +86,7 @@ int snd_msnd_send_dsp_cmd(struct snd_msnd *dev, u8 cmd) } spin_unlock_irqrestore(&dev->lock, flags); - snd_printd(KERN_ERR LOGNAME ": Send DSP command timeout\n"); + dev_dbg(dev->card->dev, LOGNAME ": Send DSP command timeout\n"); return -EIO; } @@ -104,7 +104,7 @@ int snd_msnd_send_word(struct snd_msnd *dev, unsigned char high, return 0; } - snd_printd(KERN_ERR LOGNAME ": Send host word timeout\n"); + dev_dbg(dev->card->dev, LOGNAME ": Send host word timeout\n"); return -EIO; } @@ -115,7 +115,7 @@ int snd_msnd_upload_host(struct snd_msnd *dev, const u8 *bin, int len) int i; if (len % 3 != 0) { - snd_printk(KERN_ERR LOGNAME + dev_err(dev->card->dev, LOGNAME ": Upload host data not multiple of 3!\n"); return -EINVAL; } @@ -138,7 +138,7 @@ int snd_msnd_enable_irq(struct snd_msnd *dev) if (dev->irq_ref++) return 0; - snd_printdd(LOGNAME ": Enabling IRQ\n"); + dev_dbg(dev->card->dev, LOGNAME ": Enabling IRQ\n"); spin_lock_irqsave(&dev->lock, flags); if (snd_msnd_wait_TXDE(dev) == 0) { @@ -156,7 +156,7 @@ int snd_msnd_enable_irq(struct snd_msnd *dev) } spin_unlock_irqrestore(&dev->lock, flags); - snd_printd(KERN_ERR LOGNAME ": Enable IRQ failed\n"); + dev_dbg(dev->card->dev, LOGNAME ": Enable IRQ failed\n"); return -EIO; } @@ -170,10 +170,10 @@ int snd_msnd_disable_irq(struct snd_msnd *dev) return 0; if (dev->irq_ref < 0) - snd_printd(KERN_WARNING LOGNAME ": IRQ ref count is %d\n", - dev->irq_ref); + dev_dbg(dev->card->dev, LOGNAME ": IRQ ref count is %d\n", + dev->irq_ref); - snd_printdd(LOGNAME ": Disabling IRQ\n"); + dev_dbg(dev->card->dev, LOGNAME ": Disabling IRQ\n"); spin_lock_irqsave(&dev->lock, flags); if (snd_msnd_wait_TXDE(dev) == 0) { @@ -186,7 +186,7 @@ int snd_msnd_disable_irq(struct snd_msnd *dev) } spin_unlock_irqrestore(&dev->lock, flags); - snd_printd(KERN_ERR LOGNAME ": Disable IRQ failed\n"); + dev_dbg(dev->card->dev, LOGNAME ": Disable IRQ failed\n"); return -EIO; } @@ -220,8 +220,8 @@ void snd_msnd_dsp_halt(struct snd_msnd *chip, struct file *file) snd_msnd_send_dsp_cmd(chip, HDEX_RECORD_STOP); snd_msnd_disable_irq(chip); if (file) { - snd_printd(KERN_INFO LOGNAME - ": Stopping read for %p\n", file); + dev_dbg(chip->card->dev, LOGNAME + ": Stopping read for %p\n", file); chip->mode &= ~FMODE_READ; } clear_bit(F_AUDIO_READ_INUSE, &chip->flags); @@ -233,8 +233,8 @@ void snd_msnd_dsp_halt(struct snd_msnd *chip, struct file *file) } snd_msnd_disable_irq(chip); if (file) { - snd_printd(KERN_INFO - LOGNAME ": Stopping write for %p\n", file); + dev_dbg(chip->card->dev, + LOGNAME ": Stopping write for %p\n", file); chip->mode &= ~FMODE_WRITE; } clear_bit(F_AUDIO_WRITE_INUSE, &chip->flags); @@ -329,12 +329,6 @@ int snd_msnd_DAPQ(struct snd_msnd *chip, int start) ++nbanks; /* Then advance the tail */ - /* - if (protect) - snd_printd(KERN_INFO "B %X %lX\n", - bank_num, xtime.tv_usec); - */ - DAPQ_tail = (++bank_num % 3) * PCTODSP_OFFSET(DAQDS__size); writew(DAPQ_tail, chip->DAPQ + JQS_wTail); /* Tell the DSP to play the bank */ @@ -343,10 +337,6 @@ int snd_msnd_DAPQ(struct snd_msnd *chip, int start) if (2 == bank_num) break; } - /* - if (protect) - snd_printd(KERN_INFO "%lX\n", xtime.tv_usec); - */ /* spin_unlock_irqrestore(&chip->lock, flags); not necessary */ return nbanks; } @@ -406,7 +396,7 @@ static void snd_msnd_capture_reset_queue(struct snd_msnd *chip, #endif chip->capturePeriodBytes = pcm_count; - snd_printdd("snd_msnd_capture_reset_queue() %i\n", pcm_count); + dev_dbg(chip->card->dev, "%s() %i\n", __func__, pcm_count); pDAQ = chip->mappedbase + DARQ_DATA_BUFF; @@ -533,21 +523,21 @@ static int snd_msnd_playback_trigger(struct snd_pcm_substream *substream, int result = 0; if (cmd == SNDRV_PCM_TRIGGER_START) { - snd_printdd("snd_msnd_playback_trigger(START)\n"); + dev_dbg(chip->card->dev, "%s(START)\n", __func__); chip->banksPlayed = 0; set_bit(F_WRITING, &chip->flags); snd_msnd_DAPQ(chip, 1); } else if (cmd == SNDRV_PCM_TRIGGER_STOP) { - snd_printdd("snd_msnd_playback_trigger(STop)\n"); + dev_dbg(chip->card->dev, "%s(STOP)\n", __func__); /* interrupt diagnostic, comment this out later */ clear_bit(F_WRITING, &chip->flags); snd_msnd_send_dsp_cmd(chip, HDEX_PLAY_STOP); } else { - snd_printd(KERN_ERR "snd_msnd_playback_trigger(?????)\n"); + dev_dbg(chip->card->dev, "%s(?????)\n", __func__); result = -EINVAL; } - snd_printdd("snd_msnd_playback_trigger() ENDE\n"); + dev_dbg(chip->card->dev, "%s() ENDE\n", __func__); return result; } diff --git a/sound/isa/msnd/msnd_midi.c b/sound/isa/msnd/msnd_midi.c index 7c61caaf99ad41..3ffc8758bec2c5 100644 --- a/sound/isa/msnd/msnd_midi.c +++ b/sound/isa/msnd/msnd_midi.c @@ -42,8 +42,6 @@ static int snd_msndmidi_input_open(struct snd_rawmidi_substream *substream) { struct snd_msndmidi *mpu; - snd_printdd("snd_msndmidi_input_open()\n"); - mpu = substream->rmidi->private_data; mpu->substream_input = substream; @@ -84,8 +82,6 @@ static void snd_msndmidi_input_trigger(struct snd_rawmidi_substream *substream, unsigned long flags; struct snd_msndmidi *mpu; - snd_printdd("snd_msndmidi_input_trigger(, %i)\n", up); - mpu = substream->rmidi->private_data; spin_lock_irqsave(&mpu->input_lock, flags); if (up) { diff --git a/sound/isa/msnd/msnd_pinnacle.c b/sound/isa/msnd/msnd_pinnacle.c index 4433a92f08e7fc..635403301a155c 100644 --- a/sound/isa/msnd/msnd_pinnacle.c +++ b/sound/isa/msnd/msnd_pinnacle.c @@ -81,11 +81,12 @@ static void snd_msnd_eval_dsp_msg(struct snd_msnd *chip, u16 wMessage) switch (HIBYTE(wMessage)) { case HIMT_PLAY_DONE: { if (chip->banksPlayed < 3) - snd_printdd("%08X: HIMT_PLAY_DONE: %i\n", + dev_dbg(chip->card->dev, "%08X: HIMT_PLAY_DONE: %i\n", (unsigned)jiffies, LOBYTE(wMessage)); if (chip->last_playbank == LOBYTE(wMessage)) { - snd_printdd("chip.last_playbank == LOBYTE(wMessage)\n"); + dev_dbg(chip->card->dev, + "chip.last_playbank == LOBYTE(wMessage)\n"); break; } chip->banksPlayed++; @@ -121,21 +122,22 @@ static void snd_msnd_eval_dsp_msg(struct snd_msnd *chip, u16 wMessage) case HIDSP_PLAY_UNDER: #endif case HIDSP_INT_PLAY_UNDER: - snd_printd(KERN_WARNING LOGNAME ": Play underflow %i\n", + dev_dbg(chip->card->dev, + LOGNAME ": Play underflow %i\n", chip->banksPlayed); if (chip->banksPlayed > 2) clear_bit(F_WRITING, &chip->flags); break; case HIDSP_INT_RECORD_OVER: - snd_printd(KERN_WARNING LOGNAME ": Record overflow\n"); + dev_dbg(chip->card->dev, LOGNAME ": Record overflow\n"); clear_bit(F_READING, &chip->flags); break; default: - snd_printd(KERN_WARNING LOGNAME - ": DSP message %d 0x%02x\n", - LOBYTE(wMessage), LOBYTE(wMessage)); + dev_dbg(chip->card->dev, LOGNAME + ": DSP message %d 0x%02x\n", + LOBYTE(wMessage), LOBYTE(wMessage)); break; } break; @@ -146,8 +148,8 @@ static void snd_msnd_eval_dsp_msg(struct snd_msnd *chip, u16 wMessage) break; default: - snd_printd(KERN_WARNING LOGNAME ": HIMT message %d 0x%02x\n", - HIBYTE(wMessage), HIBYTE(wMessage)); + dev_dbg(chip->card->dev, LOGNAME ": HIMT message %d 0x%02x\n", + HIBYTE(wMessage), HIBYTE(wMessage)); break; } } @@ -180,8 +182,9 @@ static irqreturn_t snd_msnd_interrupt(int irq, void *dev_id) } -static int snd_msnd_reset_dsp(long io, unsigned char *info) +static int snd_msnd_reset_dsp(struct snd_msnd *chip, unsigned char *info) { + long io = chip->io; int timeout = 100; outb(HPDSPRESET_ON, io + HP_DSPR); @@ -197,7 +200,7 @@ static int snd_msnd_reset_dsp(long io, unsigned char *info) return 0; msleep(1); } - snd_printk(KERN_ERR LOGNAME ": Cannot reset DSP\n"); + dev_err(chip->card->dev, LOGNAME ": Cannot reset DSP\n"); return -EIO; } @@ -213,11 +216,11 @@ static int snd_msnd_probe(struct snd_card *card) #endif if (!request_region(chip->io, DSP_NUMIO, "probing")) { - snd_printk(KERN_ERR LOGNAME ": I/O port conflict\n"); + dev_err(card->dev, LOGNAME ": I/O port conflict\n"); return -ENODEV; } - if (snd_msnd_reset_dsp(chip->io, &info) < 0) { + if (snd_msnd_reset_dsp(chip, &info) < 0) { release_region(chip->io, DSP_NUMIO); return -ENODEV; } @@ -225,7 +228,7 @@ static int snd_msnd_probe(struct snd_card *card) #ifdef MSND_CLASSIC strcpy(card->shortname, "Classic/Tahiti/Monterey"); strcpy(card->longname, "Turtle Beach Multisound"); - printk(KERN_INFO LOGNAME ": %s, " + dev_info(card->dev, LOGNAME ": %s, " "I/O 0x%lx-0x%lx, IRQ %d, memory mapped to 0x%lX-0x%lX\n", card->shortname, chip->io, chip->io + DSP_NUMIO - 1, @@ -285,7 +288,7 @@ static int snd_msnd_probe(struct snd_card *card) break; } strcpy(card->longname, "Turtle Beach Multisound Pinnacle"); - printk(KERN_INFO LOGNAME ": %s revision %s, Xilinx version %s, " + dev_info(card->dev, LOGNAME ": %s revision %s, Xilinx version %s, " "I/O 0x%lx-0x%lx, IRQ %d, memory mapped to 0x%lX-0x%lX\n", card->shortname, rev, xv, @@ -377,22 +380,22 @@ static int upload_dsp_code(struct snd_card *card) err = request_firmware(&init_fw, INITCODEFILE, card->dev); if (err < 0) { - printk(KERN_ERR LOGNAME ": Error loading " INITCODEFILE); + dev_err(card->dev, LOGNAME ": Error loading " INITCODEFILE); goto cleanup1; } err = request_firmware(&perm_fw, PERMCODEFILE, card->dev); if (err < 0) { - printk(KERN_ERR LOGNAME ": Error loading " PERMCODEFILE); + dev_err(card->dev, LOGNAME ": Error loading " PERMCODEFILE); goto cleanup; } memcpy_toio(chip->mappedbase, perm_fw->data, perm_fw->size); if (snd_msnd_upload_host(chip, init_fw->data, init_fw->size) < 0) { - printk(KERN_WARNING LOGNAME ": Error uploading to DSP\n"); + dev_warn(card->dev, LOGNAME ": Error uploading to DSP\n"); err = -ENODEV; goto cleanup; } - printk(KERN_INFO LOGNAME ": DSP firmware uploaded\n"); + dev_info(card->dev, LOGNAME ": DSP firmware uploaded\n"); err = 0; cleanup: @@ -425,17 +428,17 @@ static int snd_msnd_initialize(struct snd_card *card) #endif err = snd_msnd_init_sma(chip); if (err < 0) { - printk(KERN_WARNING LOGNAME ": Cannot initialize SMA\n"); + dev_warn(card->dev, LOGNAME ": Cannot initialize SMA\n"); return err; } - err = snd_msnd_reset_dsp(chip->io, NULL); + err = snd_msnd_reset_dsp(chip, NULL); if (err < 0) return err; err = upload_dsp_code(card); if (err < 0) { - printk(KERN_WARNING LOGNAME ": Cannot upload DSP code\n"); + dev_warn(card->dev, LOGNAME ": Cannot upload DSP code\n"); return err; } @@ -444,7 +447,7 @@ static int snd_msnd_initialize(struct snd_card *card) while (readw(chip->mappedbase)) { msleep(1); if (!timeout--) { - snd_printd(KERN_ERR LOGNAME ": DSP reset timeout\n"); + dev_err(card->dev, LOGNAME ": DSP reset timeout\n"); return -EIO; } } @@ -466,7 +469,7 @@ static int snd_msnd_dsp_full_reset(struct snd_card *card) rv = snd_msnd_initialize(card); if (rv) - printk(KERN_WARNING LOGNAME ": DSP reset failed\n"); + dev_warn(card->dev, LOGNAME ": DSP reset failed\n"); snd_msndmix_force_recsrc(chip, 0); clear_bit(F_RESETTING, &chip->flags); return rv; @@ -483,7 +486,7 @@ static int snd_msnd_send_dsp_cmd_chk(struct snd_msnd *chip, u8 cmd) static int snd_msnd_calibrate_adc(struct snd_msnd *chip, u16 srate) { - snd_printdd("snd_msnd_calibrate_adc(%i)\n", srate); + dev_dbg(chip->card->dev, "snd_msnd_calibrate_adc(%i)\n", srate); writew(srate, chip->SMA + SMA_wCalFreqAtoD); if (chip->calibrate_signal == 0) writew(readw(chip->SMA + SMA_wCurrHostStatusFlags) @@ -496,7 +499,7 @@ static int snd_msnd_calibrate_adc(struct snd_msnd *chip, u16 srate) schedule_timeout_interruptible(msecs_to_jiffies(333)); return 0; } - printk(KERN_WARNING LOGNAME ": ADC calibration failed\n"); + dev_warn(chip->card->dev, LOGNAME ": ADC calibration failed\n"); return -EIO; } @@ -527,7 +530,7 @@ static int snd_msnd_attach(struct snd_card *card) err = devm_request_irq(card->dev, chip->irq, snd_msnd_interrupt, 0, card->shortname, chip); if (err < 0) { - printk(KERN_ERR LOGNAME ": Couldn't grab IRQ %d\n", chip->irq); + dev_err(card->dev, LOGNAME ": Couldn't grab IRQ %d\n", chip->irq); return err; } card->sync_irq = chip->irq; @@ -537,14 +540,14 @@ static int snd_msnd_attach(struct snd_card *card) if (!devm_request_mem_region(card->dev, chip->base, BUFFSIZE, card->shortname)) { - printk(KERN_ERR LOGNAME + dev_err(card->dev, LOGNAME ": unable to grab memory region 0x%lx-0x%lx\n", chip->base, chip->base + BUFFSIZE - 1); return -EBUSY; } chip->mappedbase = devm_ioremap(card->dev, chip->base, 0x8000); if (!chip->mappedbase) { - printk(KERN_ERR LOGNAME + dev_err(card->dev, LOGNAME ": unable to map memory region 0x%lx-0x%lx\n", chip->base, chip->base + BUFFSIZE - 1); return -EIO; @@ -556,13 +559,13 @@ static int snd_msnd_attach(struct snd_card *card) err = snd_msnd_pcm(card, 0); if (err < 0) { - printk(KERN_ERR LOGNAME ": error creating new PCM device\n"); + dev_err(card->dev, LOGNAME ": error creating new PCM device\n"); return err; } err = snd_msndmix_new(card); if (err < 0) { - printk(KERN_ERR LOGNAME ": error creating new Mixer device\n"); + dev_err(card->dev, LOGNAME ": error creating new Mixer device\n"); return err; } @@ -577,7 +580,7 @@ static int snd_msnd_attach(struct snd_card *card) mpu_irq[0], &chip->rmidi); if (err < 0) { - printk(KERN_ERR LOGNAME + dev_err(card->dev, LOGNAME ": error creating new Midi device\n"); return err; } @@ -604,103 +607,104 @@ static int snd_msnd_attach(struct snd_card *card) /* Pinnacle/Fiji Logical Device Configuration */ -static int snd_msnd_write_cfg(int cfg, int reg, int value) +static int snd_msnd_write_cfg(struct snd_msnd *chip, int cfg, int reg, int value) { outb(reg, cfg); outb(value, cfg + 1); if (value != inb(cfg + 1)) { - printk(KERN_ERR LOGNAME ": snd_msnd_write_cfg: I/O error\n"); + dev_err(chip->card->dev, LOGNAME ": %s: I/O error\n", __func__); return -EIO; } return 0; } -static int snd_msnd_write_cfg_io0(int cfg, int num, u16 io) +static int snd_msnd_write_cfg_io0(struct snd_msnd *chip, int cfg, int num, u16 io) { - if (snd_msnd_write_cfg(cfg, IREG_LOGDEVICE, num)) + if (snd_msnd_write_cfg(chip, cfg, IREG_LOGDEVICE, num)) return -EIO; - if (snd_msnd_write_cfg(cfg, IREG_IO0_BASEHI, HIBYTE(io))) + if (snd_msnd_write_cfg(chip, cfg, IREG_IO0_BASEHI, HIBYTE(io))) return -EIO; - if (snd_msnd_write_cfg(cfg, IREG_IO0_BASELO, LOBYTE(io))) + if (snd_msnd_write_cfg(chip, cfg, IREG_IO0_BASELO, LOBYTE(io))) return -EIO; return 0; } -static int snd_msnd_write_cfg_io1(int cfg, int num, u16 io) +static int snd_msnd_write_cfg_io1(struct snd_msnd *chip, int cfg, int num, u16 io) { - if (snd_msnd_write_cfg(cfg, IREG_LOGDEVICE, num)) + if (snd_msnd_write_cfg(chip, cfg, IREG_LOGDEVICE, num)) return -EIO; - if (snd_msnd_write_cfg(cfg, IREG_IO1_BASEHI, HIBYTE(io))) + if (snd_msnd_write_cfg(chip, cfg, IREG_IO1_BASEHI, HIBYTE(io))) return -EIO; - if (snd_msnd_write_cfg(cfg, IREG_IO1_BASELO, LOBYTE(io))) + if (snd_msnd_write_cfg(chip, cfg, IREG_IO1_BASELO, LOBYTE(io))) return -EIO; return 0; } -static int snd_msnd_write_cfg_irq(int cfg, int num, u16 irq) +static int snd_msnd_write_cfg_irq(struct snd_msnd *chip, int cfg, int num, u16 irq) { - if (snd_msnd_write_cfg(cfg, IREG_LOGDEVICE, num)) + if (snd_msnd_write_cfg(chip, cfg, IREG_LOGDEVICE, num)) return -EIO; - if (snd_msnd_write_cfg(cfg, IREG_IRQ_NUMBER, LOBYTE(irq))) + if (snd_msnd_write_cfg(chip, cfg, IREG_IRQ_NUMBER, LOBYTE(irq))) return -EIO; - if (snd_msnd_write_cfg(cfg, IREG_IRQ_TYPE, IRQTYPE_EDGE)) + if (snd_msnd_write_cfg(chip, cfg, IREG_IRQ_TYPE, IRQTYPE_EDGE)) return -EIO; return 0; } -static int snd_msnd_write_cfg_mem(int cfg, int num, int mem) +static int snd_msnd_write_cfg_mem(struct snd_msnd *chip, int cfg, int num, int mem) { u16 wmem; mem >>= 8; wmem = (u16)(mem & 0xfff); - if (snd_msnd_write_cfg(cfg, IREG_LOGDEVICE, num)) + if (snd_msnd_write_cfg(chip, cfg, IREG_LOGDEVICE, num)) return -EIO; - if (snd_msnd_write_cfg(cfg, IREG_MEMBASEHI, HIBYTE(wmem))) + if (snd_msnd_write_cfg(chip, cfg, IREG_MEMBASEHI, HIBYTE(wmem))) return -EIO; - if (snd_msnd_write_cfg(cfg, IREG_MEMBASELO, LOBYTE(wmem))) + if (snd_msnd_write_cfg(chip, cfg, IREG_MEMBASELO, LOBYTE(wmem))) return -EIO; - if (wmem && snd_msnd_write_cfg(cfg, IREG_MEMCONTROL, + if (wmem && snd_msnd_write_cfg(chip, cfg, IREG_MEMCONTROL, MEMTYPE_HIADDR | MEMTYPE_16BIT)) return -EIO; return 0; } -static int snd_msnd_activate_logical(int cfg, int num) +static int snd_msnd_activate_logical(struct snd_msnd *chip, int cfg, int num) { - if (snd_msnd_write_cfg(cfg, IREG_LOGDEVICE, num)) + if (snd_msnd_write_cfg(chip, cfg, IREG_LOGDEVICE, num)) return -EIO; - if (snd_msnd_write_cfg(cfg, IREG_ACTIVATE, LD_ACTIVATE)) + if (snd_msnd_write_cfg(chip, cfg, IREG_ACTIVATE, LD_ACTIVATE)) return -EIO; return 0; } -static int snd_msnd_write_cfg_logical(int cfg, int num, u16 io0, +static int snd_msnd_write_cfg_logical(struct snd_msnd *chip, + int cfg, int num, u16 io0, u16 io1, u16 irq, int mem) { - if (snd_msnd_write_cfg(cfg, IREG_LOGDEVICE, num)) + if (snd_msnd_write_cfg(chip, cfg, IREG_LOGDEVICE, num)) return -EIO; - if (snd_msnd_write_cfg_io0(cfg, num, io0)) + if (snd_msnd_write_cfg_io0(chip, cfg, num, io0)) return -EIO; - if (snd_msnd_write_cfg_io1(cfg, num, io1)) + if (snd_msnd_write_cfg_io1(chip, cfg, num, io1)) return -EIO; - if (snd_msnd_write_cfg_irq(cfg, num, irq)) + if (snd_msnd_write_cfg_irq(chip, cfg, num, irq)) return -EIO; - if (snd_msnd_write_cfg_mem(cfg, num, mem)) + if (snd_msnd_write_cfg_mem(chip, cfg, num, mem)) return -EIO; - if (snd_msnd_activate_logical(cfg, num)) + if (snd_msnd_activate_logical(chip, cfg, num)) return -EIO; return 0; } -static int snd_msnd_pinnacle_cfg_reset(int cfg) +static int snd_msnd_pinnacle_cfg_reset(struct snd_msnd *chip, int cfg) { int i; /* Reset devices if told to */ - printk(KERN_INFO LOGNAME ": Resetting all devices\n"); + dev_info(chip->card->dev, LOGNAME ": Resetting all devices\n"); for (i = 0; i < 4; ++i) - if (snd_msnd_write_cfg_logical(cfg, i, 0, 0, 0, 0)) + if (snd_msnd_write_cfg_logical(chip, cfg, i, 0, 0, 0, 0)) return -EIO; return 0; @@ -779,7 +783,7 @@ static int snd_msnd_isa_match(struct device *pdev, unsigned int i) return 0; if (irq[i] == SNDRV_AUTO_PORT || mem[i] == SNDRV_AUTO_PORT) { - printk(KERN_WARNING LOGNAME ": io, irq and mem must be set\n"); + dev_warn(pdev, LOGNAME ": io, irq and mem must be set\n"); return 0; } @@ -792,14 +796,14 @@ static int snd_msnd_isa_match(struct device *pdev, unsigned int i) io[i] == 0x220 || io[i] == 0x210 || io[i] == 0x3e0)) { - printk(KERN_ERR LOGNAME ": \"io\" - DSP I/O base must be set " + dev_err(pdev, LOGNAME ": \"io\" - DSP I/O base must be set " " to 0x210, 0x220, 0x230, 0x240, 0x250, 0x260, 0x290, " "or 0x3E0\n"); return 0; } #else if (io[i] < 0x100 || io[i] > 0x3e0 || (io[i] % 0x10) != 0) { - printk(KERN_ERR LOGNAME + dev_err(pdev, LOGNAME ": \"io\" - DSP I/O base must within the range 0x100 " "to 0x3E0 and must be evenly divisible by 0x10\n"); return 0; @@ -812,7 +816,7 @@ static int snd_msnd_isa_match(struct device *pdev, unsigned int i) irq[i] == 10 || irq[i] == 11 || irq[i] == 12)) { - printk(KERN_ERR LOGNAME + dev_err(pdev, LOGNAME ": \"irq\" - must be set to 5, 7, 9, 10, 11 or 12\n"); return 0; } @@ -823,7 +827,7 @@ static int snd_msnd_isa_match(struct device *pdev, unsigned int i) mem[i] == 0xd8000 || mem[i] == 0xe0000 || mem[i] == 0xe8000)) { - printk(KERN_ERR LOGNAME ": \"mem\" - must be set to " + dev_err(pdev, LOGNAME ": \"mem\" - must be set to " "0xb0000, 0xc8000, 0xd0000, 0xd8000, 0xe0000 or " "0xe8000\n"); return 0; @@ -831,9 +835,9 @@ static int snd_msnd_isa_match(struct device *pdev, unsigned int i) #ifndef MSND_CLASSIC if (cfg[i] == SNDRV_AUTO_PORT) { - printk(KERN_INFO LOGNAME ": Assuming PnP mode\n"); + dev_info(pdev, LOGNAME ": Assuming PnP mode\n"); } else if (cfg[i] != 0x250 && cfg[i] != 0x260 && cfg[i] != 0x270) { - printk(KERN_INFO LOGNAME + dev_info(pdev, LOGNAME ": Config port must be 0x250, 0x260 or 0x270 " "(or unspecified for PnP mode)\n"); return 0; @@ -854,7 +858,7 @@ static int snd_msnd_isa_probe(struct device *pdev, unsigned int idx) || cfg[idx] == SNDRV_AUTO_PORT #endif ) { - printk(KERN_INFO LOGNAME ": Assuming PnP mode\n"); + dev_info(pdev, LOGNAME ": Assuming PnP mode\n"); return -ENODEV; } @@ -897,21 +901,21 @@ static int snd_msnd_isa_probe(struct device *pdev, unsigned int idx) chip->memid = HPMEM_E800; break; } #else - printk(KERN_INFO LOGNAME ": Non-PnP mode: configuring at port 0x%lx\n", - cfg[idx]); + dev_info(pdev, LOGNAME ": Non-PnP mode: configuring at port 0x%lx\n", + cfg[idx]); if (!devm_request_region(card->dev, cfg[idx], 2, "Pinnacle/Fiji Config")) { - printk(KERN_ERR LOGNAME ": Config port 0x%lx conflict\n", - cfg[idx]); + dev_err(pdev, LOGNAME ": Config port 0x%lx conflict\n", + cfg[idx]); return -EIO; } if (reset[idx]) - if (snd_msnd_pinnacle_cfg_reset(cfg[idx])) + if (snd_msnd_pinnacle_cfg_reset(chip, cfg[idx])) return -EIO; /* DSP */ - err = snd_msnd_write_cfg_logical(cfg[idx], 0, + err = snd_msnd_write_cfg_logical(chip, cfg[idx], 0, io[idx], 0, irq[idx], mem[idx]); @@ -923,10 +927,10 @@ static int snd_msnd_isa_probe(struct device *pdev, unsigned int idx) /* MPU */ if (mpu_io[idx] != SNDRV_AUTO_PORT && mpu_irq[idx] != SNDRV_AUTO_IRQ) { - printk(KERN_INFO LOGNAME + dev_info(pdev, LOGNAME ": Configuring MPU to I/O 0x%lx IRQ %d\n", mpu_io[idx], mpu_irq[idx]); - err = snd_msnd_write_cfg_logical(cfg[idx], 1, + err = snd_msnd_write_cfg_logical(chip, cfg[idx], 1, mpu_io[idx], 0, mpu_irq[idx], 0); @@ -938,10 +942,10 @@ static int snd_msnd_isa_probe(struct device *pdev, unsigned int idx) if (ide_io0[idx] != SNDRV_AUTO_PORT && ide_io1[idx] != SNDRV_AUTO_PORT && ide_irq[idx] != SNDRV_AUTO_IRQ) { - printk(KERN_INFO LOGNAME + dev_info(pdev, LOGNAME ": Configuring IDE to I/O 0x%lx, 0x%lx IRQ %d\n", ide_io0[idx], ide_io1[idx], ide_irq[idx]); - err = snd_msnd_write_cfg_logical(cfg[idx], 2, + err = snd_msnd_write_cfg_logical(chip, cfg[idx], 2, ide_io0[idx], ide_io1[idx], ide_irq[idx], 0); @@ -951,10 +955,10 @@ static int snd_msnd_isa_probe(struct device *pdev, unsigned int idx) /* Joystick */ if (joystick_io[idx] != SNDRV_AUTO_PORT) { - printk(KERN_INFO LOGNAME + dev_info(pdev, LOGNAME ": Configuring joystick to I/O 0x%lx\n", joystick_io[idx]); - err = snd_msnd_write_cfg_logical(cfg[idx], 3, + err = snd_msnd_write_cfg_logical(chip, cfg[idx], 3, joystick_io[idx], 0, 0, 0); @@ -989,13 +993,13 @@ static int snd_msnd_isa_probe(struct device *pdev, unsigned int idx) spin_lock_init(&chip->lock); err = snd_msnd_probe(card); if (err < 0) { - printk(KERN_ERR LOGNAME ": Probe failed\n"); + dev_err(pdev, LOGNAME ": Probe failed\n"); return err; } err = snd_msnd_attach(card); if (err < 0) { - printk(KERN_ERR LOGNAME ": Attach failed\n"); + dev_err(pdev, LOGNAME ": Attach failed\n"); return err; } dev_set_drvdata(pdev, card); @@ -1042,12 +1046,12 @@ static int snd_msnd_pnp_detect(struct pnp_card_link *pcard, return -ENODEV; if (!pnp_is_active(pnp_dev) && pnp_activate_dev(pnp_dev) < 0) { - printk(KERN_INFO "msnd_pinnacle: device is inactive\n"); + dev_info(&pcard->card->dev, "msnd_pinnacle: device is inactive\n"); return -EBUSY; } if (!pnp_is_active(mpu_dev) && pnp_activate_dev(mpu_dev) < 0) { - printk(KERN_INFO "msnd_pinnacle: MPU device is inactive\n"); + dev_info(&pcard->card->dev, "msnd_pinnacle: MPU device is inactive\n"); return -EBUSY; } @@ -1098,13 +1102,13 @@ static int snd_msnd_pnp_detect(struct pnp_card_link *pcard, spin_lock_init(&chip->lock); ret = snd_msnd_probe(card); if (ret < 0) { - printk(KERN_ERR LOGNAME ": Probe failed\n"); + dev_err(&pcard->card->dev, LOGNAME ": Probe failed\n"); return ret; } ret = snd_msnd_attach(card); if (ret < 0) { - printk(KERN_ERR LOGNAME ": Attach failed\n"); + dev_err(&pcard->card->dev, LOGNAME ": Attach failed\n"); return ret; } diff --git a/sound/isa/opl3sa2.c b/sound/isa/opl3sa2.c index bad1490a66a023..a5ed5aa0606f1a 100644 --- a/sound/isa/opl3sa2.c +++ b/sound/isa/opl3sa2.c @@ -108,6 +108,7 @@ struct snd_opl3sa2 { int irq; int single_dma; spinlock_t reg_lock; + struct snd_card *card; struct snd_hwdep *synth; struct snd_rawmidi *rmidi; struct snd_wss *wss; @@ -157,12 +158,12 @@ static unsigned char __snd_opl3sa2_read(struct snd_opl3sa2 *chip, unsigned char unsigned char result; #if 0 outb(0x1d, port); /* password */ - printk(KERN_DEBUG "read [0x%lx] = 0x%x\n", port, inb(port)); + dev_dbg(chip->card->dev, "read [0x%lx] = 0x%x\n", port, inb(port)); #endif outb(reg, chip->port); /* register */ result = inb(chip->port + 1); #if 0 - printk(KERN_DEBUG "read [0x%lx] = 0x%x [0x%x]\n", + dev_dbg(chip->card->dev, "read [0x%lx] = 0x%x [0x%x]\n", port, result, inb(port)); #endif return result; @@ -211,17 +212,13 @@ static int snd_opl3sa2_detect(struct snd_card *card) chip->res_port = devm_request_region(card->dev, port, 2, "OPL3-SA control"); if (!chip->res_port) { - snd_printk(KERN_ERR PFX "can't grab port 0x%lx\n", port); + dev_err(card->dev, "can't grab port 0x%lx\n", port); return -EBUSY; } - /* - snd_printk(KERN_DEBUG "REG 0A = 0x%x\n", - snd_opl3sa2_read(chip, 0x0a)); - */ chip->version = 0; tmp = snd_opl3sa2_read(chip, OPL3SA2_MISC); if (tmp == 0xff) { - snd_printd("OPL3-SA [0x%lx] detect = 0x%x\n", port, tmp); + dev_dbg(card->dev, "OPL3-SA [0x%lx] detect = 0x%x\n", port, tmp); return -ENODEV; } switch (tmp & 0x07) { @@ -243,7 +240,7 @@ static int snd_opl3sa2_detect(struct snd_card *card) snd_opl3sa2_write(chip, OPL3SA2_MISC, tmp ^ 7); tmp1 = snd_opl3sa2_read(chip, OPL3SA2_MISC); if (tmp1 != tmp) { - snd_printd("OPL3-SA [0x%lx] detect (1) = 0x%x (0x%x)\n", port, tmp, tmp1); + dev_dbg(card->dev, "OPL3-SA [0x%lx] detect (1) = 0x%x (0x%x)\n", port, tmp, tmp1); return -ENODEV; } /* try if the MIC register is accessible */ @@ -251,7 +248,7 @@ static int snd_opl3sa2_detect(struct snd_card *card) snd_opl3sa2_write(chip, OPL3SA2_MIC, 0x8a); tmp1 = snd_opl3sa2_read(chip, OPL3SA2_MIC); if ((tmp1 & 0x9f) != 0x8a) { - snd_printd("OPL3-SA [0x%lx] detect (2) = 0x%x (0x%x)\n", port, tmp, tmp1); + dev_dbg(card->dev, "OPL3-SA [0x%lx] detect (2) = 0x%x (0x%x)\n", port, tmp, tmp1); return -ENODEV; } snd_opl3sa2_write(chip, OPL3SA2_MIC, 0x9f); @@ -495,14 +492,14 @@ static int snd_opl3sa2_mixer(struct snd_card *card) strcpy(id2.name, "CD Playback Switch"); err = snd_ctl_rename_id(card, &id1, &id2); if (err < 0) { - snd_printk(KERN_ERR "Cannot rename opl3sa2 control\n"); + dev_err(card->dev, "Cannot rename opl3sa2 control\n"); return err; } strcpy(id1.name, "Aux Playback Volume"); strcpy(id2.name, "CD Playback Volume"); err = snd_ctl_rename_id(card, &id1, &id2); if (err < 0) { - snd_printk(KERN_ERR "Cannot rename opl3sa2 control\n"); + dev_err(card->dev, "Cannot rename opl3sa2 control\n"); return err; } /* reassign AUX1 to FM */ @@ -510,14 +507,14 @@ static int snd_opl3sa2_mixer(struct snd_card *card) strcpy(id2.name, "FM Playback Switch"); err = snd_ctl_rename_id(card, &id1, &id2); if (err < 0) { - snd_printk(KERN_ERR "Cannot rename opl3sa2 control\n"); + dev_err(card->dev, "Cannot rename opl3sa2 control\n"); return err; } strcpy(id1.name, "Aux Playback Volume"); strcpy(id2.name, "FM Playback Volume"); err = snd_ctl_rename_id(card, &id1, &id2); if (err < 0) { - snd_printk(KERN_ERR "Cannot rename opl3sa2 control\n"); + dev_err(card->dev, "Cannot rename opl3sa2 control\n"); return err; } /* add OPL3SA2 controls */ @@ -591,7 +588,7 @@ static int snd_opl3sa2_pnp(int dev, struct snd_opl3sa2 *chip, struct pnp_dev *pdev) { if (pnp_activate_dev(pdev) < 0) { - snd_printk(KERN_ERR "PnP configure failure (out of resources?)\n"); + dev_err(chip->card->dev, "PnP configure failure (out of resources?)\n"); return -EBUSY; } sb_port[dev] = pnp_port_start(pdev, 0); @@ -602,9 +599,9 @@ static int snd_opl3sa2_pnp(int dev, struct snd_opl3sa2 *chip, dma1[dev] = pnp_dma(pdev, 0); dma2[dev] = pnp_dma(pdev, 1); irq[dev] = pnp_irq(pdev, 0); - snd_printdd("%sPnP OPL3-SA: sb port=0x%lx, wss port=0x%lx, fm port=0x%lx, midi port=0x%lx\n", + dev_dbg(chip->card->dev, "%sPnP OPL3-SA: sb port=0x%lx, wss port=0x%lx, fm port=0x%lx, midi port=0x%lx\n", pnp_device_is_pnpbios(pdev) ? "BIOS" : "ISA", sb_port[dev], wss_port[dev], fm_port[dev], midi_port[dev]); - snd_printdd("%sPnP OPL3-SA: control port=0x%lx, dma1=%i, dma2=%i, irq=%i\n", + dev_dbg(chip->card->dev, "%sPnP OPL3-SA: control port=0x%lx, dma1=%i, dma2=%i, irq=%i\n", pnp_device_is_pnpbios(pdev) ? "BIOS" : "ISA", port[dev], dma1[dev], dma2[dev], irq[dev]); return 0; } @@ -640,6 +637,7 @@ static int snd_opl3sa2_probe(struct snd_card *card, int dev) /* initialise this card from supplied (or default) parameter*/ chip = card->private_data; + chip->card = card; chip->ymode = opl3sa3_ymode[dev] & 0x03 ; chip->port = port[dev]; xirq = irq[dev]; @@ -653,7 +651,7 @@ static int snd_opl3sa2_probe(struct snd_card *card, int dev) err = devm_request_irq(card->dev, xirq, snd_opl3sa2_interrupt, 0, "OPL3-SA2", card); if (err) { - snd_printk(KERN_ERR PFX "can't grab IRQ %d\n", xirq); + dev_err(card->dev, "can't grab IRQ %d\n", xirq); return -ENODEV; } chip->irq = xirq; @@ -663,7 +661,7 @@ static int snd_opl3sa2_probe(struct snd_card *card, int dev) xirq, xdma1, xdma2, WSS_HW_OPL3SA2, WSS_HWSHARE_IRQ, &wss); if (err < 0) { - snd_printd("Oops, WSS not detected at 0x%lx\n", wss_port[dev] + 4); + dev_dbg(card->dev, "Oops, WSS not detected at 0x%lx\n", wss_port[dev] + 4); return err; } chip->wss = wss; @@ -770,7 +768,7 @@ static int snd_opl3sa2_pnp_cdetect(struct pnp_card_link *pcard, pdev = pnp_request_card_device(pcard, id->devs[0].id, NULL); if (pdev == NULL) { - snd_printk(KERN_ERR PFX "can't get pnp device from id '%s'\n", + dev_err(&pcard->card->dev, "can't get pnp device from id '%s'\n", id->devs[0].id); return -EBUSY; } @@ -828,19 +826,19 @@ static int snd_opl3sa2_isa_match(struct device *pdev, return 0; #endif if (port[dev] == SNDRV_AUTO_PORT) { - snd_printk(KERN_ERR PFX "specify port\n"); + dev_err(pdev, "specify port\n"); return 0; } if (wss_port[dev] == SNDRV_AUTO_PORT) { - snd_printk(KERN_ERR PFX "specify wss_port\n"); + dev_err(pdev, "specify wss_port\n"); return 0; } if (fm_port[dev] == SNDRV_AUTO_PORT) { - snd_printk(KERN_ERR PFX "specify fm_port\n"); + dev_err(pdev, "specify fm_port\n"); return 0; } if (midi_port[dev] == SNDRV_AUTO_PORT) { - snd_printk(KERN_ERR PFX "specify midi_port\n"); + dev_err(pdev, "specify midi_port\n"); return 0; } return 1; diff --git a/sound/isa/opti9xx/miro.c b/sound/isa/opti9xx/miro.c index 59792f2fada1d5..31d736d1dd1011 100644 --- a/sound/isa/opti9xx/miro.c +++ b/sound/isa/opti9xx/miro.c @@ -111,6 +111,7 @@ struct snd_miro { long mpu_port; int mpu_irq; + struct snd_card *card; struct snd_miro_aci *aci; }; @@ -151,8 +152,9 @@ static int aci_busy_wait(struct snd_miro_aci *aci) byte = inb(aci->aci_port + ACI_REG_BUSY); if ((byte & 1) == 0) { if (timeout >= ACI_MINTIME) - snd_printd("aci ready in round %ld.\n", - timeout-ACI_MINTIME); + dev_dbg(aci->card->dev, + "aci ready in round %ld.\n", + timeout-ACI_MINTIME); return byte; } if (timeout >= ACI_MINTIME) { @@ -174,7 +176,7 @@ static int aci_busy_wait(struct snd_miro_aci *aci) } } } - snd_printk(KERN_ERR "aci_busy_wait() time out\n"); + dev_err(aci->card->dev, "%s() time out\n", __func__); return -EBUSY; } @@ -184,7 +186,7 @@ static inline int aci_write(struct snd_miro_aci *aci, unsigned char byte) outb(byte, aci->aci_port + ACI_REG_COMMAND); return 0; } else { - snd_printk(KERN_ERR "aci busy, aci_write(0x%x) stopped.\n", byte); + dev_err(aci->card->dev, "aci busy, %s(0x%x) stopped.\n", __func__, byte); return -EBUSY; } } @@ -197,7 +199,7 @@ static inline int aci_read(struct snd_miro_aci *aci) byte = inb(aci->aci_port + ACI_REG_STATUS); return byte; } else { - snd_printk(KERN_ERR "aci busy, aci_read() stopped.\n"); + dev_err(aci->card->dev, "aci busy, %s() stopped.\n", __func__); return -EBUSY; } } @@ -260,8 +262,8 @@ static int snd_miro_get_capture(struct snd_kcontrol *kcontrol, value = aci_getvalue(miro->aci, ACI_S_GENERAL); if (value < 0) { - snd_printk(KERN_ERR "snd_miro_get_capture() failed: %d\n", - value); + dev_err(miro->card->dev, "%s() failed: %d\n", __func__, + value); return value; } @@ -280,8 +282,8 @@ static int snd_miro_put_capture(struct snd_kcontrol *kcontrol, error = aci_setvalue(miro->aci, ACI_SET_SOLOMODE, value); if (error < 0) { - snd_printk(KERN_ERR "snd_miro_put_capture() failed: %d\n", - error); + dev_err(miro->card->dev, "%s() failed: %d\n", __func__, + error); return error; } @@ -322,8 +324,8 @@ static int snd_miro_get_preamp(struct snd_kcontrol *kcontrol, value = aci_getvalue(miro->aci, ACI_GET_PREAMP); if (value < 0) { - snd_printk(KERN_ERR "snd_miro_get_preamp() failed: %d\n", - value); + dev_err(miro->card->dev, "%s() failed: %d\n", __func__, + value); return value; } @@ -342,8 +344,8 @@ static int snd_miro_put_preamp(struct snd_kcontrol *kcontrol, error = aci_setvalue(miro->aci, ACI_SET_PREAMP, value); if (error < 0) { - snd_printk(KERN_ERR "snd_miro_put_preamp() failed: %d\n", - error); + dev_err(miro->card->dev, "%s() failed: %d\n", __func__, + error); return error; } @@ -374,7 +376,8 @@ static int snd_miro_put_amp(struct snd_kcontrol *kcontrol, error = aci_setvalue(miro->aci, ACI_SET_POWERAMP, value); if (error < 0) { - snd_printk(KERN_ERR "snd_miro_put_amp() to %d failed: %d\n", value, error); + dev_err(miro->card->dev, "%s() to %d failed: %d\n", __func__, + value, error); return error; } @@ -430,13 +433,15 @@ static int snd_miro_get_double(struct snd_kcontrol *kcontrol, right_val = aci_getvalue(miro->aci, right_reg); if (right_val < 0) { - snd_printk(KERN_ERR "aci_getvalue(%d) failed: %d\n", right_reg, right_val); + dev_err(miro->card->dev, "aci_getvalue(%d) failed: %d\n", + right_reg, right_val); return right_val; } left_val = aci_getvalue(miro->aci, left_reg); if (left_val < 0) { - snd_printk(KERN_ERR "aci_getvalue(%d) failed: %d\n", left_reg, left_val); + dev_err(miro->card->dev, "aci_getvalue(%d) failed: %d\n", + left_reg, left_val); return left_val; } @@ -489,13 +494,15 @@ static int snd_miro_put_double(struct snd_kcontrol *kcontrol, left_old = aci_getvalue(aci, getreg_left); if (left_old < 0) { - snd_printk(KERN_ERR "aci_getvalue(%d) failed: %d\n", getreg_left, left_old); + dev_err(miro->card->dev, "aci_getvalue(%d) failed: %d\n", + getreg_left, left_old); return left_old; } right_old = aci_getvalue(aci, getreg_right); if (right_old < 0) { - snd_printk(KERN_ERR "aci_getvalue(%d) failed: %d\n", getreg_right, right_old); + dev_err(miro->card->dev, "aci_getvalue(%d) failed: %d\n", + getreg_right, right_old); return right_old; } @@ -515,15 +522,15 @@ static int snd_miro_put_double(struct snd_kcontrol *kcontrol, if (left >= 0) { error = aci_setvalue(aci, setreg_left, left); if (error < 0) { - snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n", - left, error); + dev_err(miro->card->dev, "aci_setvalue(%d) failed: %d\n", + left, error); return error; } } else { error = aci_setvalue(aci, setreg_left, 0x80 - left); if (error < 0) { - snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n", - 0x80 - left, error); + dev_err(miro->card->dev, "aci_setvalue(%d) failed: %d\n", + 0x80 - left, error); return error; } } @@ -531,15 +538,15 @@ static int snd_miro_put_double(struct snd_kcontrol *kcontrol, if (right >= 0) { error = aci_setvalue(aci, setreg_right, right); if (error < 0) { - snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n", - right, error); + dev_err(miro->card->dev, "aci_setvalue(%d) failed: %d\n", + right, error); return error; } } else { error = aci_setvalue(aci, setreg_right, 0x80 - right); if (error < 0) { - snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n", - 0x80 - right, error); + dev_err(miro->card->dev, "aci_setvalue(%d) failed: %d\n", + 0x80 - right, error); return error; } } @@ -557,14 +564,14 @@ static int snd_miro_put_double(struct snd_kcontrol *kcontrol, error = aci_setvalue(aci, setreg_left, 0x20 - left); if (error < 0) { - snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n", - 0x20 - left, error); + dev_err(miro->card->dev, "aci_setvalue(%d) failed: %d\n", + 0x20 - left, error); return error; } error = aci_setvalue(aci, setreg_right, 0x20 - right); if (error < 0) { - snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n", - 0x20 - right, error); + dev_err(miro->card->dev, "aci_setvalue(%d) failed: %d\n", + 0x20 - right, error); return error; } } @@ -667,7 +674,7 @@ static int snd_set_aci_init_values(struct snd_miro *miro) if ((aci->aci_product == 'A') && wss) { error = aci_setvalue(aci, ACI_SET_WSS, wss); if (error < 0) { - snd_printk(KERN_ERR "enabling WSS mode failed\n"); + dev_err(miro->card->dev, "enabling WSS mode failed\n"); return error; } } @@ -677,7 +684,7 @@ static int snd_set_aci_init_values(struct snd_miro *miro) if (ide) { error = aci_setvalue(aci, ACI_SET_IDE, ide); if (error < 0) { - snd_printk(KERN_ERR "enabling IDE port failed\n"); + dev_err(miro->card->dev, "enabling IDE port failed\n"); return error; } } @@ -688,8 +695,8 @@ static int snd_set_aci_init_values(struct snd_miro *miro) error = aci_setvalue(aci, aci_init_values[idx][0], aci_init_values[idx][1]); if (error < 0) { - snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n", - aci_init_values[idx][0], error); + dev_err(miro->card->dev, "aci_setvalue(%d) failed: %d\n", + aci_init_values[idx][0], error); return error; } } @@ -805,7 +812,7 @@ static int snd_miro_init(struct snd_miro *chip, break; default: - snd_printk(KERN_ERR "sorry, no support for %d\n", hardware); + dev_err(chip->card->dev, "sorry, no support for %d\n", hardware); return -ENODEV; } @@ -836,7 +843,7 @@ static unsigned char snd_miro_read(struct snd_miro *chip, break; default: - snd_printk(KERN_ERR "sorry, no support for %d\n", chip->hardware); + dev_err(chip->card->dev, "sorry, no support for %d\n", chip->hardware); } spin_unlock_irqrestore(&chip->lock, flags); @@ -866,7 +873,7 @@ static void snd_miro_write(struct snd_miro *chip, unsigned char reg, break; default: - snd_printk(KERN_ERR "sorry, no support for %d\n", chip->hardware); + dev_err(chip->card->dev, "sorry, no support for %d\n", chip->hardware); } spin_unlock_irqrestore(&chip->lock, flags); @@ -1022,7 +1029,7 @@ static int snd_miro_configure(struct snd_miro *chip) snd_miro_write_mask(chip, OPTi9XX_MC_REG(4), 0x00, 0x0c); break; default: - snd_printk(KERN_ERR "chip %d not supported\n", chip->hardware); + dev_err(chip->card->dev, "chip %d not supported\n", chip->hardware); return -EINVAL; } @@ -1045,7 +1052,7 @@ static int snd_miro_configure(struct snd_miro *chip) wss_base_bits = 0x02; break; default: - snd_printk(KERN_ERR "WSS port 0x%lx not valid\n", chip->wss_base); + dev_err(chip->card->dev, "WSS port 0x%lx not valid\n", chip->wss_base); goto __skip_base; } snd_miro_write_mask(chip, OPTi9XX_MC_REG(1), wss_base_bits << 4, 0x30); @@ -1068,7 +1075,7 @@ static int snd_miro_configure(struct snd_miro *chip) irq_bits = 0x04; break; default: - snd_printk(KERN_ERR "WSS irq # %d not valid\n", chip->irq); + dev_err(chip->card->dev, "WSS irq # %d not valid\n", chip->irq); goto __skip_resources; } @@ -1083,12 +1090,12 @@ static int snd_miro_configure(struct snd_miro *chip) dma_bits = 0x03; break; default: - snd_printk(KERN_ERR "WSS dma1 # %d not valid\n", chip->dma1); + dev_err(chip->card->dev, "WSS dma1 # %d not valid\n", chip->dma1); goto __skip_resources; } if (chip->dma1 == chip->dma2) { - snd_printk(KERN_ERR "don't want to share dmas\n"); + dev_err(chip->card->dev, "don't want to share dmas\n"); return -EBUSY; } @@ -1097,7 +1104,7 @@ static int snd_miro_configure(struct snd_miro *chip) case 1: break; default: - snd_printk(KERN_ERR "WSS dma2 # %d not valid\n", chip->dma2); + dev_err(chip->card->dev, "WSS dma2 # %d not valid\n", chip->dma2); goto __skip_resources; } dma_bits |= 0x04; @@ -1125,8 +1132,8 @@ static int snd_miro_configure(struct snd_miro *chip) mpu_port_bits = 0x00; break; default: - snd_printk(KERN_ERR "MPU-401 port 0x%lx not valid\n", - chip->mpu_port); + dev_err(chip->card->dev, "MPU-401 port 0x%lx not valid\n", + chip->mpu_port); goto __skip_mpu; } @@ -1144,8 +1151,8 @@ static int snd_miro_configure(struct snd_miro *chip) mpu_irq_bits = 0x01; break; default: - snd_printk(KERN_ERR "MPU-401 irq # %d not valid\n", - chip->mpu_irq); + dev_err(chip->card->dev, "MPU-401 irq # %d not valid\n", + chip->mpu_irq); goto __skip_mpu; } @@ -1208,6 +1215,7 @@ static int snd_card_miro_aci_detect(struct snd_card *card, miro->aci = aci; + aci->card = card; mutex_init(&aci->aci_mutex); /* get ACI port from OPTi9xx MC 4 */ @@ -1218,37 +1226,37 @@ static int snd_card_miro_aci_detect(struct snd_card *card, miro->res_aci_port = devm_request_region(card->dev, aci->aci_port, 3, "miro aci"); if (miro->res_aci_port == NULL) { - snd_printk(KERN_ERR "aci i/o area 0x%lx-0x%lx already used.\n", - aci->aci_port, aci->aci_port+2); + dev_err(card->dev, "aci i/o area 0x%lx-0x%lx already used.\n", + aci->aci_port, aci->aci_port+2); return -ENOMEM; } /* force ACI into a known state */ for (i = 0; i < 3; i++) if (snd_aci_cmd(aci, ACI_ERROR_OP, -1, -1) < 0) { - snd_printk(KERN_ERR "can't force aci into known state.\n"); + dev_err(card->dev, "can't force aci into known state.\n"); return -ENXIO; } aci->aci_vendor = snd_aci_cmd(aci, ACI_READ_IDCODE, -1, -1); aci->aci_product = snd_aci_cmd(aci, ACI_READ_IDCODE, -1, -1); if (aci->aci_vendor < 0 || aci->aci_product < 0) { - snd_printk(KERN_ERR "can't read aci id on 0x%lx.\n", - aci->aci_port); + dev_err(card->dev, "can't read aci id on 0x%lx.\n", + aci->aci_port); return -ENXIO; } aci->aci_version = snd_aci_cmd(aci, ACI_READ_VERSION, -1, -1); if (aci->aci_version < 0) { - snd_printk(KERN_ERR "can't read aci version on 0x%lx.\n", - aci->aci_port); + dev_err(card->dev, "can't read aci version on 0x%lx.\n", + aci->aci_port); return -ENXIO; } if (snd_aci_cmd(aci, ACI_INIT, -1, -1) < 0 || snd_aci_cmd(aci, ACI_ERROR_OP, ACI_ERROR_OP, ACI_ERROR_OP) < 0 || snd_aci_cmd(aci, ACI_ERROR_OP, ACI_ERROR_OP, ACI_ERROR_OP) < 0) { - snd_printk(KERN_ERR "can't initialize aci.\n"); + dev_err(card->dev, "can't initialize aci.\n"); return -ENXIO; } @@ -1268,14 +1276,14 @@ static int snd_miro_probe(struct snd_card *card) miro->mc_base_size, "miro (OPTi9xx MC)"); if (miro->res_mc_base == NULL) { - snd_printk(KERN_ERR "request for OPTI9xx MC failed\n"); + dev_err(card->dev, "request for OPTI9xx MC failed\n"); return -ENOMEM; } } error = snd_card_miro_aci_detect(card, miro); if (error < 0) { - snd_printk(KERN_ERR "unable to detect aci chip\n"); + dev_err(card->dev, "unable to detect aci chip\n"); return -ENODEV; } @@ -1335,11 +1343,11 @@ static int snd_miro_probe(struct snd_card *card) default: sprintf(card->shortname, "unknown miro"); - snd_printk(KERN_INFO "unknown miro aci id\n"); + dev_info(card->dev, "unknown miro aci id\n"); break; } } else { - snd_printk(KERN_INFO "found unsupported aci card\n"); + dev_info(card->dev, "found unsupported aci card\n"); sprintf(card->shortname, "unknown Cardinal Technologies"); } @@ -1355,8 +1363,8 @@ static int snd_miro_probe(struct snd_card *card) error = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, mpu_port, 0, miro->mpu_irq, &rmidi); if (error < 0) - snd_printk(KERN_WARNING "no MPU-401 device at 0x%lx?\n", - mpu_port); + dev_warn(card->dev, "no MPU-401 device at 0x%lx?\n", + mpu_port); } if (fm_port > 0 && fm_port != SNDRV_AUTO_PORT) { @@ -1365,8 +1373,8 @@ static int snd_miro_probe(struct snd_card *card) if (snd_opl4_create(card, fm_port, fm_port - 8, 2, &opl3, &opl4) < 0) - snd_printk(KERN_WARNING "no OPL4 device at 0x%lx\n", - fm_port); + dev_warn(card->dev, "no OPL4 device at 0x%lx\n", + fm_port); } error = snd_set_aci_init_values(miro); @@ -1410,14 +1418,14 @@ static int snd_miro_isa_probe(struct device *devptr, unsigned int n) error = snd_card_miro_detect(card, miro); if (error < 0) { - snd_printk(KERN_ERR "unable to detect OPTi9xx chip\n"); + dev_err(card->dev, "unable to detect OPTi9xx chip\n"); return -ENODEV; } if (port == SNDRV_AUTO_PORT) { port = snd_legacy_find_free_ioport(possible_ports, 4); if (port < 0) { - snd_printk(KERN_ERR "unable to find a free WSS port\n"); + dev_err(card->dev, "unable to find a free WSS port\n"); return -EBUSY; } } @@ -1425,8 +1433,8 @@ static int snd_miro_isa_probe(struct device *devptr, unsigned int n) if (mpu_port == SNDRV_AUTO_PORT) { mpu_port = snd_legacy_find_free_ioport(possible_mpu_ports, 2); if (mpu_port < 0) { - snd_printk(KERN_ERR - "unable to find a free MPU401 port\n"); + dev_err(card->dev, + "unable to find a free MPU401 port\n"); return -EBUSY; } } @@ -1434,29 +1442,29 @@ static int snd_miro_isa_probe(struct device *devptr, unsigned int n) if (irq == SNDRV_AUTO_IRQ) { irq = snd_legacy_find_free_irq(possible_irqs); if (irq < 0) { - snd_printk(KERN_ERR "unable to find a free IRQ\n"); + dev_err(card->dev, "unable to find a free IRQ\n"); return -EBUSY; } } if (mpu_irq == SNDRV_AUTO_IRQ) { mpu_irq = snd_legacy_find_free_irq(possible_mpu_irqs); if (mpu_irq < 0) { - snd_printk(KERN_ERR - "unable to find a free MPU401 IRQ\n"); + dev_err(card->dev, + "unable to find a free MPU401 IRQ\n"); return -EBUSY; } } if (dma1 == SNDRV_AUTO_DMA) { dma1 = snd_legacy_find_free_dma(possible_dma1s); if (dma1 < 0) { - snd_printk(KERN_ERR "unable to find a free DMA1\n"); + dev_err(card->dev, "unable to find a free DMA1\n"); return -EBUSY; } } if (dma2 == SNDRV_AUTO_DMA) { dma2 = snd_legacy_find_free_dma(possible_dma2s[dma1 % 4]); if (dma2 < 0) { - snd_printk(KERN_ERR "unable to find a free DMA2\n"); + dev_err(card->dev, "unable to find a free DMA2\n"); return -EBUSY; } } @@ -1505,14 +1513,14 @@ static int snd_card_miro_pnp(struct snd_miro *chip, err = pnp_activate_dev(pdev); if (err < 0) { - snd_printk(KERN_ERR "AUDIO pnp configure failure: %d\n", err); + dev_err(chip->card->dev, "AUDIO pnp configure failure: %d\n", err); return err; } err = pnp_activate_dev(devmc); if (err < 0) { - snd_printk(KERN_ERR "MC pnp configure failure: %d\n", - err); + dev_err(chip->card->dev, "MC pnp configure failure: %d\n", + err); return err; } @@ -1533,7 +1541,7 @@ static int snd_card_miro_pnp(struct snd_miro *chip, if (mpu_port > 0) { err = pnp_activate_dev(devmpu); if (err < 0) { - snd_printk(KERN_ERR "MPU401 pnp configure failure\n"); + dev_err(chip->card->dev, "MPU401 pnp configure failure\n"); mpu_port = -1; return err; } @@ -1560,6 +1568,7 @@ static int snd_miro_pnp_probe(struct pnp_card_link *pcard, return err; miro = card->private_data; + miro->card = card; err = snd_card_miro_pnp(miro, pcard, pid); if (err) @@ -1572,7 +1581,7 @@ static int snd_miro_pnp_probe(struct pnp_card_link *pcard, err = snd_miro_opti_check(card, miro); if (err) { - snd_printk(KERN_ERR "OPTI chip not found\n"); + dev_err(card->dev, "OPTI chip not found\n"); return err; } diff --git a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c index c33f67dd51331a..220ea1952c1eb8 100644 --- a/sound/isa/opti9xx/opti92x-ad1848.c +++ b/sound/isa/opti9xx/opti92x-ad1848.c @@ -109,6 +109,7 @@ MODULE_PARM_DESC(dma2, "2nd dma # for opti9xx driver."); #endif /* OPTi93X */ struct snd_opti9xx { + struct snd_card *card; unsigned short hardware; unsigned char password; char name[7]; @@ -218,7 +219,7 @@ static int snd_opti9xx_init(struct snd_opti9xx *chip, #endif /* OPTi93X */ default: - snd_printk(KERN_ERR "chip %d not supported\n", hardware); + dev_err(chip->card->dev, "chip %d not supported\n", hardware); return -ENODEV; } return 0; @@ -261,7 +262,7 @@ static unsigned char snd_opti9xx_read(struct snd_opti9xx *chip, #endif /* OPTi93X */ default: - snd_printk(KERN_ERR "chip %d not supported\n", chip->hardware); + dev_err(chip->card->dev, "chip %d not supported\n", chip->hardware); } spin_unlock_irqrestore(&chip->lock, flags); @@ -304,7 +305,7 @@ static void snd_opti9xx_write(struct snd_opti9xx *chip, unsigned char reg, #endif /* OPTi93X */ default: - snd_printk(KERN_ERR "chip %d not supported\n", chip->hardware); + dev_err(chip->card->dev, "chip %d not supported\n", chip->hardware); } spin_unlock_irqrestore(&chip->lock, flags); @@ -400,7 +401,7 @@ static int snd_opti9xx_configure(struct snd_opti9xx *chip, #endif /* OPTi93X */ default: - snd_printk(KERN_ERR "chip %d not supported\n", chip->hardware); + dev_err(chip->card->dev, "chip %d not supported\n", chip->hardware); return -EINVAL; } @@ -423,7 +424,7 @@ static int snd_opti9xx_configure(struct snd_opti9xx *chip, wss_base_bits = 0x02; break; default: - snd_printk(KERN_WARNING "WSS port 0x%lx not valid\n", port); + dev_warn(chip->card->dev, "WSS port 0x%lx not valid\n", port); goto __skip_base; } snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(1), wss_base_bits << 4, 0x30); @@ -448,7 +449,7 @@ static int snd_opti9xx_configure(struct snd_opti9xx *chip, irq_bits = 0x04; break; default: - snd_printk(KERN_WARNING "WSS irq # %d not valid\n", irq); + dev_warn(chip->card->dev, "WSS irq # %d not valid\n", irq); goto __skip_resources; } @@ -463,13 +464,13 @@ static int snd_opti9xx_configure(struct snd_opti9xx *chip, dma_bits = 0x03; break; default: - snd_printk(KERN_WARNING "WSS dma1 # %d not valid\n", dma1); + dev_warn(chip->card->dev, "WSS dma1 # %d not valid\n", dma1); goto __skip_resources; } #if defined(CS4231) || defined(OPTi93X) if (dma1 == dma2) { - snd_printk(KERN_ERR "don't want to share dmas\n"); + dev_err(chip->card->dev, "don't want to share dmas\n"); return -EBUSY; } @@ -478,7 +479,7 @@ static int snd_opti9xx_configure(struct snd_opti9xx *chip, case 1: break; default: - snd_printk(KERN_WARNING "WSS dma2 # %d not valid\n", dma2); + dev_warn(chip->card->dev, "WSS dma2 # %d not valid\n", dma2); goto __skip_resources; } dma_bits |= 0x04; @@ -509,8 +510,8 @@ static int snd_opti9xx_configure(struct snd_opti9xx *chip, mpu_port_bits = 0x00; break; default: - snd_printk(KERN_WARNING - "MPU-401 port 0x%lx not valid\n", mpu_port); + dev_warn(chip->card->dev, + "MPU-401 port 0x%lx not valid\n", mpu_port); goto __skip_mpu; } @@ -528,8 +529,8 @@ static int snd_opti9xx_configure(struct snd_opti9xx *chip, mpu_irq_bits = 0x01; break; default: - snd_printk(KERN_WARNING "MPU-401 irq # %d not valid\n", - mpu_irq); + dev_warn(chip->card->dev, "MPU-401 irq # %d not valid\n", + mpu_irq); goto __skip_mpu; } @@ -603,7 +604,7 @@ static int snd_opti93x_mixer(struct snd_wss *chip) strcpy(id2.name, "CD Playback Switch"); err = snd_ctl_rename_id(card, &id1, &id2); if (err < 0) { - snd_printk(KERN_ERR "Cannot rename opti93x control\n"); + dev_err(card->dev, "Cannot rename opti93x control\n"); return err; } /* reassign AUX1 switch to FM */ @@ -611,7 +612,7 @@ static int snd_opti93x_mixer(struct snd_wss *chip) strcpy(id2.name, "FM Playback Switch"); err = snd_ctl_rename_id(card, &id1, &id2); if (err < 0) { - snd_printk(KERN_ERR "Cannot rename opti93x control\n"); + dev_err(card->dev, "Cannot rename opti93x control\n"); return err; } /* remove AUX1 volume */ @@ -740,7 +741,7 @@ static int snd_card_opti9xx_pnp(struct snd_opti9xx *chip, err = pnp_activate_dev(pdev); if (err < 0) { - snd_printk(KERN_ERR "AUDIO pnp configure failure: %d\n", err); + dev_err(chip->card->dev, "AUDIO pnp configure failure: %d\n", err); return err; } @@ -757,7 +758,7 @@ static int snd_card_opti9xx_pnp(struct snd_opti9xx *chip, err = pnp_activate_dev(devmc); if (err < 0) { - snd_printk(KERN_ERR "MC pnp configure failure: %d\n", err); + dev_err(chip->card->dev, "MC pnp configure failure: %d\n", err); return err; } @@ -781,7 +782,7 @@ static int snd_card_opti9xx_pnp(struct snd_opti9xx *chip, if (devmpu && mpu_port > 0) { err = pnp_activate_dev(devmpu); if (err < 0) { - snd_printk(KERN_ERR "MPU401 pnp configure failure\n"); + dev_err(chip->card->dev, "MPU401 pnp configure failure\n"); mpu_port = -1; } else { mpu_port = pnp_port_start(devmpu, 0); @@ -811,7 +812,7 @@ static int snd_opti9xx_probe(struct snd_card *card) if (port == SNDRV_AUTO_PORT) { port = snd_legacy_find_free_ioport(possible_ports, 4); if (port < 0) { - snd_printk(KERN_ERR "unable to find a free WSS port\n"); + dev_err(card->dev, "unable to find a free WSS port\n"); return -EBUSY; } } @@ -850,7 +851,7 @@ static int snd_opti9xx_probe(struct snd_card *card) error = devm_request_irq(card->dev, irq, snd_opti93x_interrupt, 0, DEV_NAME" - WSS", chip); if (error < 0) { - snd_printk(KERN_ERR "opti9xx: can't grab IRQ %d\n", irq); + dev_err(card->dev, "opti9xx: can't grab IRQ %d\n", irq); return error; } #endif @@ -876,8 +877,8 @@ static int snd_opti9xx_probe(struct snd_card *card) error = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, mpu_port, 0, mpu_irq, &rmidi); if (error) - snd_printk(KERN_WARNING "no MPU-401 device at 0x%lx?\n", - mpu_port); + dev_warn(card->dev, "no MPU-401 device at 0x%lx?\n", + mpu_port); } if (fm_port > 0 && fm_port != SNDRV_AUTO_PORT) { @@ -900,8 +901,8 @@ static int snd_opti9xx_probe(struct snd_card *card) #endif /* !OPTi93X */ if (!opl3 && snd_opl3_create(card, fm_port, fm_port + 2, OPL3_HW_AUTO, 0, &opl3) < 0) { - snd_printk(KERN_WARNING "no OPL device at 0x%lx-0x%lx\n", - fm_port, fm_port + 4 - 1); + dev_warn(card->dev, "no OPL device at 0x%lx-0x%lx\n", + fm_port, fm_port + 4 - 1); } if (opl3) { error = snd_opl3_hwdep_new(opl3, 0, 1, &synth); @@ -958,28 +959,28 @@ static int snd_opti9xx_isa_probe(struct device *devptr, if (mpu_port == SNDRV_AUTO_PORT) { mpu_port = snd_legacy_find_free_ioport(possible_mpu_ports, 2); if (mpu_port < 0) { - snd_printk(KERN_ERR "unable to find a free MPU401 port\n"); + dev_err(devptr, "unable to find a free MPU401 port\n"); return -EBUSY; } } if (irq == SNDRV_AUTO_IRQ) { irq = snd_legacy_find_free_irq(possible_irqs); if (irq < 0) { - snd_printk(KERN_ERR "unable to find a free IRQ\n"); + dev_err(devptr, "unable to find a free IRQ\n"); return -EBUSY; } } if (mpu_irq == SNDRV_AUTO_IRQ) { mpu_irq = snd_legacy_find_free_irq(possible_mpu_irqs); if (mpu_irq < 0) { - snd_printk(KERN_ERR "unable to find a free MPU401 IRQ\n"); + dev_err(devptr, "unable to find a free MPU401 IRQ\n"); return -EBUSY; } } if (dma1 == SNDRV_AUTO_DMA) { dma1 = snd_legacy_find_free_dma(possible_dma1s); if (dma1 < 0) { - snd_printk(KERN_ERR "unable to find a free DMA1\n"); + dev_err(devptr, "unable to find a free DMA1\n"); return -EBUSY; } } @@ -987,7 +988,7 @@ static int snd_opti9xx_isa_probe(struct device *devptr, if (dma2 == SNDRV_AUTO_DMA) { dma2 = snd_legacy_find_free_dma(possible_dma2s[dma1 % 4]); if (dma2 < 0) { - snd_printk(KERN_ERR "unable to find a free DMA2\n"); + dev_err(devptr, "unable to find a free DMA2\n"); return -EBUSY; } } @@ -1076,6 +1077,7 @@ static int snd_opti9xx_pnp_probe(struct pnp_card_link *pcard, if (error < 0) return error; chip = card->private_data; + chip->card = card; hw = snd_card_opti9xx_pnp(chip, pcard, pid); switch (hw) { @@ -1097,7 +1099,7 @@ static int snd_opti9xx_pnp_probe(struct pnp_card_link *pcard, return error; error = snd_opti9xx_read_check(card, chip); if (error) { - snd_printk(KERN_ERR "OPTI chip not found\n"); + dev_err(card->dev, "OPTI chip not found\n"); return error; } error = snd_opti9xx_probe(card); diff --git a/sound/isa/sb/emu8000.c b/sound/isa/sb/emu8000.c index af478c36ce5b1f..52884e6b9193ad 100644 --- a/sound/isa/sb/emu8000.c +++ b/sound/isa/sb/emu8000.c @@ -160,8 +160,8 @@ snd_emu8000_detect(struct snd_emu8000 *emu) if ((EMU8000_HWCF2_READ(emu) & 0x0003) != 0x0003) return -ENODEV; - snd_printdd("EMU8000 [0x%lx]: Synth chip found\n", - emu->port1); + dev_dbg(emu->card->dev, "EMU8000 [0x%lx]: Synth chip found\n", + emu->port1); return 0; } @@ -652,7 +652,7 @@ snd_emu8000_load_chorus_fx(struct snd_emu8000 *emu, int mode, const void __user { struct soundfont_chorus_fx rec; if (mode < SNDRV_EMU8000_CHORUS_PREDEFINED || mode >= SNDRV_EMU8000_CHORUS_NUMBERS) { - snd_printk(KERN_WARNING "invalid chorus mode %d for uploading\n", mode); + dev_warn(emu->card->dev, "invalid chorus mode %d for uploading\n", mode); return -EINVAL; } if (len < (long)sizeof(rec) || copy_from_user(&rec, buf, sizeof(rec))) @@ -780,7 +780,7 @@ snd_emu8000_load_reverb_fx(struct snd_emu8000 *emu, int mode, const void __user struct soundfont_reverb_fx rec; if (mode < SNDRV_EMU8000_REVERB_PREDEFINED || mode >= SNDRV_EMU8000_REVERB_NUMBERS) { - snd_printk(KERN_WARNING "invalid reverb mode %d for uploading\n", mode); + dev_warn(emu->card->dev, "invalid reverb mode %d for uploading\n", mode); return -EINVAL; } if (len < (long)sizeof(rec) || copy_from_user(&rec, buf, sizeof(rec))) @@ -1072,7 +1072,8 @@ snd_emu8000_new(struct snd_card *card, int index, long port, int seq_ports, if (!devm_request_region(card->dev, hw->port1, 4, "Emu8000-1") || !devm_request_region(card->dev, hw->port2, 4, "Emu8000-2") || !devm_request_region(card->dev, hw->port3, 4, "Emu8000-3")) { - snd_printk(KERN_ERR "sbawe: can't grab ports 0x%lx, 0x%lx, 0x%lx\n", hw->port1, hw->port2, hw->port3); + dev_err(card->dev, "sbawe: can't grab ports 0x%lx, 0x%lx, 0x%lx\n", + hw->port1, hw->port2, hw->port3); return -EBUSY; } hw->mem_size = 0; diff --git a/sound/isa/sb/emu8000_patch.c b/sound/isa/sb/emu8000_patch.c index ab4f988f080dc7..d60174ec8b3996 100644 --- a/sound/isa/sb/emu8000_patch.c +++ b/sound/isa/sb/emu8000_patch.c @@ -157,7 +157,6 @@ snd_emu8000_sample_new(struct snd_emux *rec, struct snd_sf_sample *sp, sp->block = snd_util_mem_alloc(hdr, truesize * 2); if (sp->block == NULL) { - /*snd_printd("EMU8000: out of memory\n");*/ /* not ENOMEM (for compatibility) */ return -ENOSPC; } diff --git a/sound/isa/sb/emu8000_synth.c b/sound/isa/sb/emu8000_synth.c index 0edfb6875278dc..9bec85ec55b47a 100644 --- a/sound/isa/sb/emu8000_synth.c +++ b/sound/isa/sb/emu8000_synth.c @@ -45,7 +45,7 @@ static int snd_emu8000_probe(struct device *_dev) emu->num_ports = hw->seq_ports; if (hw->memhdr) { - snd_printk(KERN_ERR "memhdr is already initialized!?\n"); + dev_err(hw->card->dev, "memhdr is already initialized!?\n"); snd_util_memhdr_free(hw->memhdr); } hw->memhdr = snd_util_memhdr_new(hw->mem_size); diff --git a/sound/isa/sb/jazz16.c b/sound/isa/sb/jazz16.c index 64936c91717018..b28490973892f0 100644 --- a/sound/isa/sb/jazz16.c +++ b/sound/isa/sb/jazz16.c @@ -75,13 +75,14 @@ static irqreturn_t jazz16_interrupt(int irq, void *chip) return snd_sb8dsp_interrupt(chip); } -static int jazz16_configure_ports(unsigned long port, +static int jazz16_configure_ports(struct snd_card *card, + unsigned long port, unsigned long mpu_port, int idx) { unsigned char val; if (!request_region(0x201, 1, "jazz16 config")) { - snd_printk(KERN_ERR "config port region is already in use.\n"); + dev_err(card->dev, "config port region is already in use.\n"); return -EBUSY; } outb(SB_JAZZ16_WAKEUP - idx, 0x201); @@ -96,15 +97,15 @@ static int jazz16_configure_ports(unsigned long port, return 0; } -static int jazz16_detect_board(unsigned long port, +static int jazz16_detect_board(struct snd_card *card, unsigned long port, unsigned long mpu_port) { int err; int val; - struct snd_sb chip; + struct snd_sb chip = {}; if (!request_region(port, 0x10, "jazz16")) { - snd_printk(KERN_ERR "I/O port region is already in use.\n"); + dev_err(card->dev, "I/O port region is already in use.\n"); return -EBUSY; } /* just to call snd_sbdsp_command/reset/get_byte() */ @@ -113,7 +114,7 @@ static int jazz16_detect_board(unsigned long port, err = snd_sbdsp_reset(&chip); if (err < 0) for (val = 0; val < 4; val++) { - err = jazz16_configure_ports(port, mpu_port, val); + err = jazz16_configure_ports(card, port, mpu_port, val); if (err < 0) break; @@ -143,8 +144,8 @@ static int jazz16_detect_board(unsigned long port, } snd_sbdsp_get_byte(&chip); err = snd_sbdsp_get_byte(&chip); - snd_printd("Media Vision Jazz16 board detected: rev 0x%x, model 0x%x\n", - val, err); + dev_dbg(card->dev, "Media Vision Jazz16 board detected: rev 0x%x, model 0x%x\n", + val, err); err = 0; @@ -185,31 +186,31 @@ static int snd_jazz16_match(struct device *devptr, unsigned int dev) if (!enable[dev]) return 0; if (port[dev] == SNDRV_AUTO_PORT) { - snd_printk(KERN_ERR "please specify port\n"); + dev_err(devptr, "please specify port\n"); return 0; } else if (port[dev] == 0x200 || (port[dev] & ~0x270)) { - snd_printk(KERN_ERR "incorrect port specified\n"); + dev_err(devptr, "incorrect port specified\n"); return 0; } if (dma8[dev] != SNDRV_AUTO_DMA && dma8[dev] != 1 && dma8[dev] != 3) { - snd_printk(KERN_ERR "dma8 must be 1 or 3\n"); + dev_err(devptr, "dma8 must be 1 or 3\n"); return 0; } if (dma16[dev] != SNDRV_AUTO_DMA && dma16[dev] != 5 && dma16[dev] != 7) { - snd_printk(KERN_ERR "dma16 must be 5 or 7\n"); + dev_err(devptr, "dma16 must be 5 or 7\n"); return 0; } if (mpu_port[dev] != SNDRV_AUTO_PORT && (mpu_port[dev] & ~0x030) != 0x300) { - snd_printk(KERN_ERR "incorrect mpu_port specified\n"); + dev_err(devptr, "incorrect mpu_port specified\n"); return 0; } if (mpu_irq[dev] != SNDRV_AUTO_DMA && mpu_irq[dev] != 2 && mpu_irq[dev] != 3 && mpu_irq[dev] != 5 && mpu_irq[dev] != 7) { - snd_printk(KERN_ERR "mpu_irq must be 2, 3, 5 or 7\n"); + dev_err(devptr, "mpu_irq must be 2, 3, 5 or 7\n"); return 0; } return 1; @@ -237,7 +238,7 @@ static int snd_jazz16_probe(struct device *devptr, unsigned int dev) if (xirq == SNDRV_AUTO_IRQ) { xirq = snd_legacy_find_free_irq(possible_irqs); if (xirq < 0) { - snd_printk(KERN_ERR "unable to find a free IRQ\n"); + dev_err(devptr, "unable to find a free IRQ\n"); return -EBUSY; } } @@ -245,7 +246,7 @@ static int snd_jazz16_probe(struct device *devptr, unsigned int dev) if (xdma8 == SNDRV_AUTO_DMA) { xdma8 = snd_legacy_find_free_dma(possible_dmas8); if (xdma8 < 0) { - snd_printk(KERN_ERR "unable to find a free DMA8\n"); + dev_err(devptr, "unable to find a free DMA8\n"); return -EBUSY; } } @@ -253,7 +254,7 @@ static int snd_jazz16_probe(struct device *devptr, unsigned int dev) if (xdma16 == SNDRV_AUTO_DMA) { xdma16 = snd_legacy_find_free_dma(possible_dmas16); if (xdma16 < 0) { - snd_printk(KERN_ERR "unable to find a free DMA16\n"); + dev_err(devptr, "unable to find a free DMA16\n"); return -EBUSY; } } @@ -261,9 +262,9 @@ static int snd_jazz16_probe(struct device *devptr, unsigned int dev) xmpu_port = mpu_port[dev]; if (xmpu_port == SNDRV_AUTO_PORT) xmpu_port = 0; - err = jazz16_detect_board(port[dev], xmpu_port); + err = jazz16_detect_board(card, port[dev], xmpu_port); if (err < 0) { - printk(KERN_ERR "Media Vision Jazz16 board not detected\n"); + dev_err(devptr, "Media Vision Jazz16 board not detected\n"); return err; } err = snd_sbdsp_create(card, port[dev], irq[dev], @@ -279,7 +280,7 @@ static int snd_jazz16_probe(struct device *devptr, unsigned int dev) xmpu_irq = 0; err = jazz16_configure_board(chip, xmpu_irq); if (err < 0) { - printk(KERN_ERR "Media Vision Jazz16 configuration failed\n"); + dev_err(devptr, "Media Vision Jazz16 configuration failed\n"); return err; } @@ -301,8 +302,8 @@ static int snd_jazz16_probe(struct device *devptr, unsigned int dev) err = snd_opl3_create(card, chip->port, chip->port + 2, OPL3_HW_AUTO, 1, &opl3); if (err < 0) - snd_printk(KERN_WARNING "no OPL device at 0x%lx-0x%lx\n", - chip->port, chip->port + 2); + dev_warn(devptr, "no OPL device at 0x%lx-0x%lx\n", + chip->port, chip->port + 2); else { err = snd_opl3_hwdep_new(opl3, 0, 1, NULL); if (err < 0) @@ -317,8 +318,8 @@ static int snd_jazz16_probe(struct device *devptr, unsigned int dev) mpu_port[dev], 0, mpu_irq[dev], NULL) < 0) - snd_printk(KERN_ERR "no MPU-401 device at 0x%lx\n", - mpu_port[dev]); + dev_err(devptr, "no MPU-401 device at 0x%lx\n", + mpu_port[dev]); } err = snd_card_register(card); diff --git a/sound/isa/sb/sb16.c b/sound/isa/sb/sb16.c index e89b095aa282db..2f7505ad855c45 100644 --- a/sound/isa/sb/sb16.c +++ b/sound/isa/sb/sb16.c @@ -21,12 +21,6 @@ #define SNDRV_LEGACY_FIND_FREE_DMA #include -#ifdef SNDRV_SBAWE -#define PFX "sbawe: " -#else -#define PFX "sb16: " -#endif - MODULE_AUTHOR("Jaroslav Kysela "); MODULE_LICENSE("GPL"); #ifndef SNDRV_SBAWE @@ -246,7 +240,7 @@ static int snd_card_sb16_pnp(int dev, struct snd_card_sb16 *acard, err = pnp_activate_dev(pdev); if (err < 0) { - snd_printk(KERN_ERR PFX "AUDIO pnp configure failure\n"); + dev_err(&pdev->dev, "AUDIO pnp configure failure\n"); return err; } port[dev] = pnp_port_start(pdev, 0); @@ -255,10 +249,10 @@ static int snd_card_sb16_pnp(int dev, struct snd_card_sb16 *acard, dma8[dev] = pnp_dma(pdev, 0); dma16[dev] = pnp_dma(pdev, 1); irq[dev] = pnp_irq(pdev, 0); - snd_printdd("pnp SB16: port=0x%lx, mpu port=0x%lx, fm port=0x%lx\n", - port[dev], mpu_port[dev], fm_port[dev]); - snd_printdd("pnp SB16: dma1=%i, dma2=%i, irq=%i\n", - dma8[dev], dma16[dev], irq[dev]); + dev_dbg(&pdev->dev, "pnp SB16: port=0x%lx, mpu port=0x%lx, fm port=0x%lx\n", + port[dev], mpu_port[dev], fm_port[dev]); + dev_dbg(&pdev->dev, "pnp SB16: dma1=%i, dma2=%i, irq=%i\n", + dma8[dev], dma16[dev], irq[dev]); #ifdef SNDRV_SBAWE_EMU8000 /* WaveTable initialization */ pdev = acard->devwt; @@ -268,13 +262,13 @@ static int snd_card_sb16_pnp(int dev, struct snd_card_sb16 *acard, goto __wt_error; } awe_port[dev] = pnp_port_start(pdev, 0); - snd_printdd("pnp SB16: wavetable port=0x%llx\n", - (unsigned long long)pnp_port_start(pdev, 0)); + dev_dbg(&pdev->dev, "pnp SB16: wavetable port=0x%llx\n", + (unsigned long long)pnp_port_start(pdev, 0)); } else { __wt_error: if (pdev) { pnp_release_card_device(pdev); - snd_printk(KERN_ERR PFX "WaveTable pnp configure failure\n"); + dev_err(&pdev->dev, "WaveTable pnp configure failure\n"); } acard->devwt = NULL; awe_port[dev] = -1; @@ -329,7 +323,7 @@ static int snd_sb16_probe(struct snd_card *card, int dev) acard->chip = chip; if (chip->hardware != SB_HW_16) { - snd_printk(KERN_ERR PFX "SB 16 chip was not detected at 0x%lx\n", port[dev]); + dev_err(card->dev, "SB 16 chip was not detected at 0x%lx\n", port[dev]); return -ENODEV; } chip->mpu_port = mpu_port[dev]; @@ -379,8 +373,8 @@ static int snd_sb16_probe(struct snd_card *card, int dev) OPL3_HW_OPL3, acard->fm_res != NULL || fm_port[dev] == port[dev], &opl3) < 0) { - snd_printk(KERN_ERR PFX "no OPL device at 0x%lx-0x%lx\n", - fm_port[dev], fm_port[dev] + 2); + dev_err(card->dev, "no OPL device at 0x%lx-0x%lx\n", + fm_port[dev], fm_port[dev] + 2); } else { #ifdef SNDRV_SBAWE_EMU8000 int seqdev = awe_port[dev] > 0 ? 2 : 1; @@ -405,7 +399,9 @@ static int snd_sb16_probe(struct snd_card *card, int dev) chip->csp = xcsp->private_data; chip->hardware = SB_HW_16CSP; } else { - snd_printk(KERN_INFO PFX "warning - CSP chip not detected on soundcard #%i\n", dev + 1); + dev_info(card->dev, + "warning - CSP chip not detected on soundcard #%i\n", + dev + 1); } } #endif @@ -414,7 +410,9 @@ static int snd_sb16_probe(struct snd_card *card, int dev) err = snd_emu8000_new(card, 1, awe_port[dev], seq_ports[dev], NULL); if (err < 0) { - snd_printk(KERN_ERR PFX "fatal error - EMU-8000 synthesizer not detected at 0x%lx\n", awe_port[dev]); + dev_err(card->dev, + "fatal error - EMU-8000 synthesizer not detected at 0x%lx\n", + awe_port[dev]); return err; } @@ -502,21 +500,21 @@ static int snd_sb16_isa_probe(struct device *pdev, unsigned int dev) if (irq[dev] == SNDRV_AUTO_IRQ) { irq[dev] = snd_legacy_find_free_irq(possible_irqs); if (irq[dev] < 0) { - snd_printk(KERN_ERR PFX "unable to find a free IRQ\n"); + dev_err(pdev, "unable to find a free IRQ\n"); return -EBUSY; } } if (dma8[dev] == SNDRV_AUTO_DMA) { dma8[dev] = snd_legacy_find_free_dma(possible_dmas8); if (dma8[dev] < 0) { - snd_printk(KERN_ERR PFX "unable to find a free 8-bit DMA\n"); + dev_err(pdev, "unable to find a free 8-bit DMA\n"); return -EBUSY; } } if (dma16[dev] == SNDRV_AUTO_DMA) { dma16[dev] = snd_legacy_find_free_dma(possible_dmas16); if (dma16[dev] < 0) { - snd_printk(KERN_ERR PFX "unable to find a free 16-bit DMA\n"); + dev_err(pdev, "unable to find a free 16-bit DMA\n"); return -EBUSY; } } diff --git a/sound/isa/sb/sb16_csp.c b/sound/isa/sb/sb16_csp.c index fdb992733bde10..071ba85f76bb83 100644 --- a/sound/isa/sb/sb16_csp.c +++ b/sound/isa/sb/sb16_csp.c @@ -296,6 +296,7 @@ static int snd_sb_csp_riff_load(struct snd_sb_csp * p, struct snd_sb_csp_microcode __user * mcode) { struct snd_sb_csp_mc_header info; + struct device *dev = p->chip->card->dev; unsigned char __user *data_ptr; unsigned char __user *data_end; @@ -316,7 +317,7 @@ static int snd_sb_csp_riff_load(struct snd_sb_csp * p, return -EFAULT; if ((le32_to_cpu(file_h.name) != RIFF_HEADER) || (le32_to_cpu(file_h.len) >= SNDRV_SB_CSP_MAX_MICROCODE_FILE_SIZE - sizeof(file_h))) { - snd_printd("%s: Invalid RIFF header\n", __func__); + dev_dbg(dev, "%s: Invalid RIFF header\n", __func__); return -EINVAL; } data_ptr += sizeof(file_h); @@ -325,7 +326,7 @@ static int snd_sb_csp_riff_load(struct snd_sb_csp * p, if (copy_from_user(&item_type, data_ptr, sizeof(item_type))) return -EFAULT; if (le32_to_cpu(item_type) != CSP__HEADER) { - snd_printd("%s: Invalid RIFF file type\n", __func__); + dev_dbg(dev, "%s: Invalid RIFF file type\n", __func__); return -EINVAL; } data_ptr += sizeof (item_type); @@ -380,7 +381,7 @@ static int snd_sb_csp_riff_load(struct snd_sb_csp * p, return -EFAULT; if (le32_to_cpu(code_h.name) != MAIN_HEADER) { - snd_printd("%s: Missing 'main' microcode\n", __func__); + dev_dbg(dev, "%s: Missing 'main' microcode\n", __func__); return -EINVAL; } data_ptr += sizeof(code_h); @@ -423,9 +424,9 @@ static int snd_sb_csp_riff_load(struct snd_sb_csp * p, default: /* other codecs are unsupported */ p->acc_format = p->acc_width = p->acc_rates = 0; p->mode = 0; - snd_printd("%s: Unsupported CSP codec type: 0x%04x\n", - __func__, - le16_to_cpu(funcdesc_h.VOC_type)); + dev_dbg(dev, "%s: Unsupported CSP codec type: 0x%04x\n", + __func__, + le16_to_cpu(funcdesc_h.VOC_type)); return -EINVAL; } p->acc_channels = le16_to_cpu(funcdesc_h.flags_stereo_mono); @@ -443,7 +444,7 @@ static int snd_sb_csp_riff_load(struct snd_sb_csp * p, return 0; } } - snd_printd("%s: Function #%d not found\n", __func__, info.func_req); + dev_dbg(dev, "%s: Function #%d not found\n", __func__, info.func_req); return -EINVAL; } @@ -597,7 +598,9 @@ static int get_version(struct snd_sb *chip) static int snd_sb_csp_check_version(struct snd_sb_csp * p) { if (p->version < 0x10 || p->version > 0x1f) { - snd_printd("%s: Invalid CSP version: 0x%x\n", __func__, p->version); + dev_dbg(p->chip->card->dev, + "%s: Invalid CSP version: 0x%x\n", + __func__, p->version); return 1; } return 0; @@ -616,7 +619,7 @@ static int snd_sb_csp_load(struct snd_sb_csp * p, const unsigned char *buf, int spin_lock_irqsave(&p->chip->reg_lock, flags); snd_sbdsp_command(p->chip, 0x01); /* CSP download command */ if (snd_sbdsp_get_byte(p->chip)) { - snd_printd("%s: Download command failed\n", __func__); + dev_dbg(p->chip->card->dev, "%s: Download command failed\n", __func__); goto __fail; } /* Send CSP low byte (size - 1) */ @@ -643,7 +646,9 @@ static int snd_sb_csp_load(struct snd_sb_csp * p, const unsigned char *buf, int udelay (10); } if (status != 0x55) { - snd_printd("%s: Microcode initialization failed\n", __func__); + dev_dbg(p->chip->card->dev, + "%s: Microcode initialization failed\n", + __func__); goto __fail; } } else { @@ -788,25 +793,26 @@ static int snd_sb_csp_autoload(struct snd_sb_csp * p, snd_pcm_format_t pcm_sfmt, */ static int snd_sb_csp_start(struct snd_sb_csp * p, int sample_width, int channels) { + struct device *dev = p->chip->card->dev; unsigned char s_type; /* sample type */ unsigned char mixL, mixR; int result = -EIO; unsigned long flags; if (!(p->running & (SNDRV_SB_CSP_ST_LOADED | SNDRV_SB_CSP_ST_AUTO))) { - snd_printd("%s: Microcode not loaded\n", __func__); + dev_dbg(dev, "%s: Microcode not loaded\n", __func__); return -ENXIO; } if (p->running & SNDRV_SB_CSP_ST_RUNNING) { - snd_printd("%s: CSP already running\n", __func__); + dev_dbg(dev, "%s: CSP already running\n", __func__); return -EBUSY; } if (!(sample_width & p->acc_width)) { - snd_printd("%s: Unsupported PCM sample width\n", __func__); + dev_dbg(dev, "%s: Unsupported PCM sample width\n", __func__); return -EINVAL; } if (!(channels & p->acc_channels)) { - snd_printd("%s: Invalid number of channels\n", __func__); + dev_dbg(dev, "%s: Invalid number of channels\n", __func__); return -EINVAL; } @@ -829,11 +835,11 @@ static int snd_sb_csp_start(struct snd_sb_csp * p, int sample_width, int channel s_type |= 0x22; /* 00dX 00dX (d = 1 if 8 bit samples) */ if (set_codec_parameter(p->chip, 0x81, s_type)) { - snd_printd("%s: Set sample type command failed\n", __func__); + dev_dbg(dev, "%s: Set sample type command failed\n", __func__); goto __fail; } if (set_codec_parameter(p->chip, 0x80, 0x00)) { - snd_printd("%s: Codec start command failed\n", __func__); + dev_dbg(dev, "%s: Codec start command failed\n", __func__); goto __fail; } p->run_width = sample_width; diff --git a/sound/isa/sb/sb16_main.c b/sound/isa/sb/sb16_main.c index a9b87e159b2d11..74db115250030e 100644 --- a/sound/isa/sb/sb16_main.c +++ b/sound/isa/sb/sb16_main.c @@ -733,7 +733,6 @@ int snd_sb16dsp_configure(struct snd_sb * chip) unsigned char realirq, realdma, realmpureg; /* note: mpu register should be present only on SB16 Vibra soundcards */ - // printk(KERN_DEBUG "codec->irq=%i, codec->dma8=%i, codec->dma16=%i\n", chip->irq, chip->dma8, chip->dma16); spin_lock_irqsave(&chip->mixer_lock, flags); mpureg = snd_sbmixer_read(chip, SB_DSP4_MPUSETUP) & ~0x06; spin_unlock_irqrestore(&chip->mixer_lock, flags); @@ -807,9 +806,15 @@ int snd_sb16dsp_configure(struct snd_sb * chip) spin_unlock_irqrestore(&chip->mixer_lock, flags); if ((~realirq) & irqreg || (~realdma) & dmareg) { - snd_printk(KERN_ERR "SB16 [0x%lx]: unable to set DMA & IRQ (PnP device?)\n", chip->port); - snd_printk(KERN_ERR "SB16 [0x%lx]: wanted: irqreg=0x%x, dmareg=0x%x, mpureg = 0x%x\n", chip->port, realirq, realdma, realmpureg); - snd_printk(KERN_ERR "SB16 [0x%lx]: got: irqreg=0x%x, dmareg=0x%x, mpureg = 0x%x\n", chip->port, irqreg, dmareg, mpureg); + dev_err(chip->card->dev, + "SB16 [0x%lx]: unable to set DMA & IRQ (PnP device?)\n", + chip->port); + dev_err(chip->card->dev, + "SB16 [0x%lx]: wanted: irqreg=0x%x, dmareg=0x%x, mpureg = 0x%x\n", + chip->port, realirq, realdma, realmpureg); + dev_err(chip->card->dev, + "SB16 [0x%lx]: got: irqreg=0x%x, dmareg=0x%x, mpureg = 0x%x\n", + chip->port, irqreg, dmareg, mpureg); return -ENODEV; } return 0; diff --git a/sound/isa/sb/sb8.c b/sound/isa/sb/sb8.c index e5ef1777161fed..8726778c815eed 100644 --- a/sound/isa/sb/sb8.c +++ b/sound/isa/sb/sb8.c @@ -123,11 +123,11 @@ static int snd_sb8_probe(struct device *pdev, unsigned int dev) if (chip->hardware >= SB_HW_16) { if (chip->hardware == SB_HW_ALS100) - snd_printk(KERN_WARNING "ALS100 chip detected at 0x%lx, try snd-als100 module\n", - port[dev]); + dev_warn(pdev, "ALS100 chip detected at 0x%lx, try snd-als100 module\n", + port[dev]); else - snd_printk(KERN_WARNING "SB 16 chip detected at 0x%lx, try snd-sb16 module\n", - port[dev]); + dev_warn(pdev, "SB 16 chip detected at 0x%lx, try snd-sb16 module\n", + port[dev]); return -ENODEV; } @@ -143,12 +143,12 @@ static int snd_sb8_probe(struct device *pdev, unsigned int dev) err = snd_opl3_create(card, chip->port + 8, 0, OPL3_HW_AUTO, 1, &opl3); if (err < 0) - snd_printk(KERN_WARNING "sb8: no OPL device at 0x%lx\n", chip->port + 8); + dev_warn(pdev, "sb8: no OPL device at 0x%lx\n", chip->port + 8); } else { err = snd_opl3_create(card, chip->port, chip->port + 2, OPL3_HW_AUTO, 1, &opl3); if (err < 0) { - snd_printk(KERN_WARNING "sb8: no OPL device at 0x%lx-0x%lx\n", + dev_warn(pdev, "sb8: no OPL device at 0x%lx-0x%lx\n", chip->port, chip->port + 2); } } diff --git a/sound/isa/sb/sb_common.c b/sound/isa/sb/sb_common.c index c0e319d1421091..a4d5bf3d145f48 100644 --- a/sound/isa/sb/sb_common.c +++ b/sound/isa/sb/sb_common.c @@ -31,14 +31,14 @@ int snd_sbdsp_command(struct snd_sb *chip, unsigned char val) { int i; #ifdef IO_DEBUG - snd_printk(KERN_DEBUG "command 0x%x\n", val); + dev_dbg(chip->card->dev, "command 0x%x\n", val); #endif for (i = BUSY_LOOPS; i; i--) if ((inb(SBP(chip, STATUS)) & 0x80) == 0) { outb(val, SBP(chip, COMMAND)); return 1; } - snd_printd("%s [0x%lx]: timeout (0x%x)\n", __func__, chip->port, val); + dev_dbg(chip->card->dev, "%s [0x%lx]: timeout (0x%x)\n", __func__, chip->port, val); return 0; } @@ -50,12 +50,12 @@ int snd_sbdsp_get_byte(struct snd_sb *chip) if (inb(SBP(chip, DATA_AVAIL)) & 0x80) { val = inb(SBP(chip, READ)); #ifdef IO_DEBUG - snd_printk(KERN_DEBUG "get_byte 0x%x\n", val); + dev_dbg(chip->card->dev, "get_byte 0x%x\n", val); #endif return val; } } - snd_printd("%s [0x%lx]: timeout\n", __func__, chip->port); + dev_dbg(chip->card->dev, "%s [0x%lx]: timeout\n", __func__, chip->port); return -ENODEV; } @@ -74,7 +74,8 @@ int snd_sbdsp_reset(struct snd_sb *chip) else break; } - snd_printdd("%s [0x%lx] failed...\n", __func__, chip->port); + if (chip->card) + dev_dbg(chip->card->dev, "%s [0x%lx] failed...\n", __func__, chip->port); return -ENODEV; } @@ -112,8 +113,8 @@ static int snd_sbdsp_probe(struct snd_sb * chip) spin_unlock_irqrestore(&chip->reg_lock, flags); major = version >> 8; minor = version & 0xff; - snd_printdd("SB [0x%lx]: DSP chip found, version = %i.%i\n", - chip->port, major, minor); + dev_dbg(chip->card->dev, "SB [0x%lx]: DSP chip found, version = %i.%i\n", + chip->port, major, minor); switch (chip->hardware) { case SB_HW_AUTO: @@ -140,8 +141,8 @@ static int snd_sbdsp_probe(struct snd_sb * chip) str = "16"; break; default: - snd_printk(KERN_INFO "SB [0x%lx]: unknown DSP chip version %i.%i\n", - chip->port, major, minor); + dev_info(chip->card->dev, "SB [0x%lx]: unknown DSP chip version %i.%i\n", + chip->port, major, minor); return -ENODEV; } break; @@ -200,7 +201,7 @@ int snd_sbdsp_create(struct snd_card *card, hardware == SB_HW_CS5530) ? IRQF_SHARED : 0, "SoundBlaster", (void *) chip)) { - snd_printk(KERN_ERR "sb: can't grab irq %d\n", irq); + dev_err(card->dev, "sb: can't grab irq %d\n", irq); return -EBUSY; } chip->irq = irq; @@ -212,14 +213,14 @@ int snd_sbdsp_create(struct snd_card *card, chip->res_port = devm_request_region(card->dev, port, 16, "SoundBlaster"); if (!chip->res_port) { - snd_printk(KERN_ERR "sb: can't grab port 0x%lx\n", port); + dev_err(card->dev, "sb: can't grab port 0x%lx\n", port); return -EBUSY; } #ifdef CONFIG_ISA if (dma8 >= 0 && snd_devm_request_dma(card->dev, dma8, "SoundBlaster - 8bit")) { - snd_printk(KERN_ERR "sb: can't grab DMA8 %d\n", dma8); + dev_err(card->dev, "sb: can't grab DMA8 %d\n", dma8); return -EBUSY; } chip->dma8 = dma8; @@ -229,7 +230,7 @@ int snd_sbdsp_create(struct snd_card *card, dma16 = -1; } else if (snd_devm_request_dma(card->dev, dma16, "SoundBlaster - 16bit")) { - snd_printk(KERN_ERR "sb: can't grab DMA16 %d\n", dma16); + dev_err(card->dev, "sb: can't grab DMA16 %d\n", dma16); return -EBUSY; } } diff --git a/sound/isa/sb/sb_mixer.c b/sound/isa/sb/sb_mixer.c index fffd681e5bf7e3..9d23b7a4570bf3 100644 --- a/sound/isa/sb/sb_mixer.c +++ b/sound/isa/sb/sb_mixer.c @@ -20,7 +20,7 @@ void snd_sbmixer_write(struct snd_sb *chip, unsigned char reg, unsigned char dat outb(data, SBP(chip, MIXER_DATA)); udelay(10); #ifdef IO_DEBUG - snd_printk(KERN_DEBUG "mixer_write 0x%x 0x%x\n", reg, data); + dev_dbg(chip->card->dev, "mixer_write 0x%x 0x%x\n", reg, data); #endif } @@ -33,7 +33,7 @@ unsigned char snd_sbmixer_read(struct snd_sb *chip, unsigned char reg) result = inb(SBP(chip, MIXER_DATA)); udelay(10); #ifdef IO_DEBUG - snd_printk(KERN_DEBUG "mixer_read 0x%x 0x%x\n", reg, result); + dev_dbg(chip->card->dev, "mixer_read 0x%x 0x%x\n", reg, result); #endif return result; } diff --git a/sound/isa/sc6000.c b/sound/isa/sc6000.c index 60398fced046b0..3115c32b4061b7 100644 --- a/sound/isa/sc6000.c +++ b/sound/isa/sc6000.c @@ -204,7 +204,7 @@ static int sc6000_read(char __iomem *vport) } -static int sc6000_write(char __iomem *vport, int cmd) +static int sc6000_write(struct device *devptr, char __iomem *vport, int cmd) { unsigned char val; int loop = 500000; @@ -221,18 +221,19 @@ static int sc6000_write(char __iomem *vport, int cmd) cpu_relax(); } while (loop--); - snd_printk(KERN_ERR "DSP Command (0x%x) timeout.\n", cmd); + dev_err(devptr, "DSP Command (0x%x) timeout.\n", cmd); return -EIO; } -static int sc6000_dsp_get_answer(char __iomem *vport, int command, +static int sc6000_dsp_get_answer(struct device *devptr, + char __iomem *vport, int command, char *data, int data_len) { int len = 0; - if (sc6000_write(vport, command)) { - snd_printk(KERN_ERR "CMD 0x%x: failed!\n", command); + if (sc6000_write(devptr, vport, command)) { + dev_err(devptr, "CMD 0x%x: failed!\n", command); return -EIO; } @@ -265,82 +266,86 @@ static int sc6000_dsp_reset(char __iomem *vport) } /* detection and initialization */ -static int sc6000_hw_cfg_write(char __iomem *vport, const int *cfg) +static int sc6000_hw_cfg_write(struct device *devptr, + char __iomem *vport, const int *cfg) { - if (sc6000_write(vport, COMMAND_6C) < 0) { - snd_printk(KERN_WARNING "CMD 0x%x: failed!\n", COMMAND_6C); + if (sc6000_write(devptr, vport, COMMAND_6C) < 0) { + dev_warn(devptr, "CMD 0x%x: failed!\n", COMMAND_6C); return -EIO; } - if (sc6000_write(vport, COMMAND_5C) < 0) { - snd_printk(KERN_ERR "CMD 0x%x: failed!\n", COMMAND_5C); + if (sc6000_write(devptr, vport, COMMAND_5C) < 0) { + dev_err(devptr, "CMD 0x%x: failed!\n", COMMAND_5C); return -EIO; } - if (sc6000_write(vport, cfg[0]) < 0) { - snd_printk(KERN_ERR "DATA 0x%x: failed!\n", cfg[0]); + if (sc6000_write(devptr, vport, cfg[0]) < 0) { + dev_err(devptr, "DATA 0x%x: failed!\n", cfg[0]); return -EIO; } - if (sc6000_write(vport, cfg[1]) < 0) { - snd_printk(KERN_ERR "DATA 0x%x: failed!\n", cfg[1]); + if (sc6000_write(devptr, vport, cfg[1]) < 0) { + dev_err(devptr, "DATA 0x%x: failed!\n", cfg[1]); return -EIO; } - if (sc6000_write(vport, COMMAND_C5) < 0) { - snd_printk(KERN_ERR "CMD 0x%x: failed!\n", COMMAND_C5); + if (sc6000_write(devptr, vport, COMMAND_C5) < 0) { + dev_err(devptr, "CMD 0x%x: failed!\n", COMMAND_C5); return -EIO; } return 0; } -static int sc6000_cfg_write(char __iomem *vport, unsigned char softcfg) +static int sc6000_cfg_write(struct device *devptr, + char __iomem *vport, unsigned char softcfg) { - if (sc6000_write(vport, WRITE_MDIRQ_CFG)) { - snd_printk(KERN_ERR "CMD 0x%x: failed!\n", WRITE_MDIRQ_CFG); + if (sc6000_write(devptr, vport, WRITE_MDIRQ_CFG)) { + dev_err(devptr, "CMD 0x%x: failed!\n", WRITE_MDIRQ_CFG); return -EIO; } - if (sc6000_write(vport, softcfg)) { - snd_printk(KERN_ERR "sc6000_cfg_write: failed!\n"); + if (sc6000_write(devptr, vport, softcfg)) { + dev_err(devptr, "%s: failed!\n", __func__); return -EIO; } return 0; } -static int sc6000_setup_board(char __iomem *vport, int config) +static int sc6000_setup_board(struct device *devptr, + char __iomem *vport, int config) { int loop = 10; do { - if (sc6000_write(vport, COMMAND_88)) { - snd_printk(KERN_ERR "CMD 0x%x: failed!\n", - COMMAND_88); + if (sc6000_write(devptr, vport, COMMAND_88)) { + dev_err(devptr, "CMD 0x%x: failed!\n", + COMMAND_88); return -EIO; } } while ((sc6000_wait_data(vport) < 0) && loop--); if (sc6000_read(vport) < 0) { - snd_printk(KERN_ERR "sc6000_read after CMD 0x%x: failed\n", - COMMAND_88); + dev_err(devptr, "sc6000_read after CMD 0x%x: failed\n", + COMMAND_88); return -EIO; } - if (sc6000_cfg_write(vport, config)) + if (sc6000_cfg_write(devptr, vport, config)) return -ENODEV; return 0; } -static int sc6000_init_mss(char __iomem *vport, int config, +static int sc6000_init_mss(struct device *devptr, + char __iomem *vport, int config, char __iomem *vmss_port, int mss_config) { - if (sc6000_write(vport, DSP_INIT_MSS)) { - snd_printk(KERN_ERR "sc6000_init_mss [0x%x]: failed!\n", - DSP_INIT_MSS); + if (sc6000_write(devptr, vport, DSP_INIT_MSS)) { + dev_err(devptr, "%s [0x%x]: failed!\n", __func__, + DSP_INIT_MSS); return -EIO; } msleep(10); - if (sc6000_cfg_write(vport, config)) + if (sc6000_cfg_write(devptr, vport, config)) return -EIO; iowrite8(mss_config, vmss_port); @@ -348,7 +353,8 @@ static int sc6000_init_mss(char __iomem *vport, int config, return 0; } -static void sc6000_hw_cfg_encode(char __iomem *vport, int *cfg, +static void sc6000_hw_cfg_encode(struct device *devptr, + char __iomem *vport, int *cfg, long xport, long xmpu, long xmss_port, int joystick) { @@ -367,10 +373,11 @@ static void sc6000_hw_cfg_encode(char __iomem *vport, int *cfg, cfg[0] |= 0x02; cfg[1] |= 0x80; /* enable WSS system */ cfg[1] &= ~0x40; /* disable IDE */ - snd_printd("hw cfg %x, %x\n", cfg[0], cfg[1]); + dev_dbg(devptr, "hw cfg %x, %x\n", cfg[0], cfg[1]); } -static int sc6000_init_board(char __iomem *vport, +static int sc6000_init_board(struct device *devptr, + char __iomem *vport, char __iomem *vmss_port, int dev) { char answer[15]; @@ -384,14 +391,14 @@ static int sc6000_init_board(char __iomem *vport, err = sc6000_dsp_reset(vport); if (err < 0) { - snd_printk(KERN_ERR "sc6000_dsp_reset: failed!\n"); + dev_err(devptr, "sc6000_dsp_reset: failed!\n"); return err; } memset(answer, 0, sizeof(answer)); - err = sc6000_dsp_get_answer(vport, GET_DSP_COPYRIGHT, answer, 15); + err = sc6000_dsp_get_answer(devptr, vport, GET_DSP_COPYRIGHT, answer, 15); if (err <= 0) { - snd_printk(KERN_ERR "sc6000_dsp_copyright: failed!\n"); + dev_err(devptr, "sc6000_dsp_copyright: failed!\n"); return -ENODEV; } /* @@ -399,52 +406,52 @@ static int sc6000_init_board(char __iomem *vport, * if we have something different, we have to be warned. */ if (strncmp("SC-6000", answer, 7)) - snd_printk(KERN_WARNING "Warning: non SC-6000 audio card!\n"); + dev_warn(devptr, "Warning: non SC-6000 audio card!\n"); - if (sc6000_dsp_get_answer(vport, GET_DSP_VERSION, version, 2) < 2) { - snd_printk(KERN_ERR "sc6000_dsp_version: failed!\n"); + if (sc6000_dsp_get_answer(devptr, vport, GET_DSP_VERSION, version, 2) < 2) { + dev_err(devptr, "sc6000_dsp_version: failed!\n"); return -ENODEV; } - printk(KERN_INFO PFX "Detected model: %s, DSP version %d.%d\n", + dev_info(devptr, "Detected model: %s, DSP version %d.%d\n", answer, version[0], version[1]); /* set configuration */ - sc6000_write(vport, COMMAND_5C); + sc6000_write(devptr, vport, COMMAND_5C); if (sc6000_read(vport) < 0) old = 1; if (!old) { int cfg[2]; - sc6000_hw_cfg_encode(vport, &cfg[0], port[dev], mpu_port[dev], + sc6000_hw_cfg_encode(devptr, + vport, &cfg[0], port[dev], mpu_port[dev], mss_port[dev], joystick[dev]); - if (sc6000_hw_cfg_write(vport, cfg) < 0) { - snd_printk(KERN_ERR "sc6000_hw_cfg_write: failed!\n"); + if (sc6000_hw_cfg_write(devptr, vport, cfg) < 0) { + dev_err(devptr, "sc6000_hw_cfg_write: failed!\n"); return -EIO; } } - err = sc6000_setup_board(vport, config); + err = sc6000_setup_board(devptr, vport, config); if (err < 0) { - snd_printk(KERN_ERR "sc6000_setup_board: failed!\n"); + dev_err(devptr, "sc6000_setup_board: failed!\n"); return -ENODEV; } sc6000_dsp_reset(vport); if (!old) { - sc6000_write(vport, COMMAND_60); - sc6000_write(vport, 0x02); + sc6000_write(devptr, vport, COMMAND_60); + sc6000_write(devptr, vport, 0x02); sc6000_dsp_reset(vport); } - err = sc6000_setup_board(vport, config); + err = sc6000_setup_board(devptr, vport, config); if (err < 0) { - snd_printk(KERN_ERR "sc6000_setup_board: failed!\n"); + dev_err(devptr, "sc6000_setup_board: failed!\n"); return -ENODEV; } - err = sc6000_init_mss(vport, config, vmss_port, mss_config); + err = sc6000_init_mss(devptr, vport, config, vmss_port, mss_config); if (err < 0) { - snd_printk(KERN_ERR "Cannot initialize " - "Microsoft Sound System mode.\n"); + dev_err(devptr, "Cannot initialize Microsoft Sound System mode.\n"); return -ENODEV; } @@ -491,39 +498,39 @@ static int snd_sc6000_match(struct device *devptr, unsigned int dev) if (!enable[dev]) return 0; if (port[dev] == SNDRV_AUTO_PORT) { - printk(KERN_ERR PFX "specify IO port\n"); + dev_err(devptr, "specify IO port\n"); return 0; } if (mss_port[dev] == SNDRV_AUTO_PORT) { - printk(KERN_ERR PFX "specify MSS port\n"); + dev_err(devptr, "specify MSS port\n"); return 0; } if (port[dev] != 0x220 && port[dev] != 0x240) { - printk(KERN_ERR PFX "Port must be 0x220 or 0x240\n"); + dev_err(devptr, "Port must be 0x220 or 0x240\n"); return 0; } if (mss_port[dev] != 0x530 && mss_port[dev] != 0xe80) { - printk(KERN_ERR PFX "MSS port must be 0x530 or 0xe80\n"); + dev_err(devptr, "MSS port must be 0x530 or 0xe80\n"); return 0; } if (irq[dev] != SNDRV_AUTO_IRQ && !sc6000_irq_to_softcfg(irq[dev])) { - printk(KERN_ERR PFX "invalid IRQ %d\n", irq[dev]); + dev_err(devptr, "invalid IRQ %d\n", irq[dev]); return 0; } if (dma[dev] != SNDRV_AUTO_DMA && !sc6000_dma_to_softcfg(dma[dev])) { - printk(KERN_ERR PFX "invalid DMA %d\n", dma[dev]); + dev_err(devptr, "invalid DMA %d\n", dma[dev]); return 0; } if (mpu_port[dev] != SNDRV_AUTO_PORT && (mpu_port[dev] & ~0x30L) != 0x300) { - printk(KERN_ERR PFX "invalid MPU-401 port %lx\n", + dev_err(devptr, "invalid MPU-401 port %lx\n", mpu_port[dev]); return 0; } if (mpu_port[dev] != SNDRV_AUTO_PORT && mpu_irq[dev] != SNDRV_AUTO_IRQ && mpu_irq[dev] != 0 && !sc6000_mpu_irq_to_softcfg(mpu_irq[dev])) { - printk(KERN_ERR PFX "invalid MPU-401 IRQ %d\n", mpu_irq[dev]); + dev_err(devptr, "invalid MPU-401 IRQ %d\n", mpu_irq[dev]); return 0; } return 1; @@ -534,7 +541,7 @@ static void snd_sc6000_free(struct snd_card *card) char __iomem *vport = (char __force __iomem *)card->private_data; if (vport) - sc6000_setup_board(vport, 0); + sc6000_setup_board(card->dev, vport, 0); } static int __snd_sc6000_probe(struct device *devptr, unsigned int dev) @@ -558,7 +565,7 @@ static int __snd_sc6000_probe(struct device *devptr, unsigned int dev) if (xirq == SNDRV_AUTO_IRQ) { xirq = snd_legacy_find_free_irq(possible_irqs); if (xirq < 0) { - snd_printk(KERN_ERR PFX "unable to find a free IRQ\n"); + dev_err(devptr, "unable to find a free IRQ\n"); return -EBUSY; } } @@ -566,42 +573,39 @@ static int __snd_sc6000_probe(struct device *devptr, unsigned int dev) if (xdma == SNDRV_AUTO_DMA) { xdma = snd_legacy_find_free_dma(possible_dmas); if (xdma < 0) { - snd_printk(KERN_ERR PFX "unable to find a free DMA\n"); + dev_err(devptr, "unable to find a free DMA\n"); return -EBUSY; } } if (!devm_request_region(devptr, port[dev], 0x10, DRV_NAME)) { - snd_printk(KERN_ERR PFX - "I/O port region is already in use.\n"); + dev_err(devptr, "I/O port region is already in use.\n"); return -EBUSY; } vport = devm_ioport_map(devptr, port[dev], 0x10); if (!vport) { - snd_printk(KERN_ERR PFX - "I/O port cannot be iomapped.\n"); + dev_err(devptr, "I/O port cannot be iomapped.\n"); return -EBUSY; } card->private_data = (void __force *)vport; /* to make it marked as used */ if (!devm_request_region(devptr, mss_port[dev], 4, DRV_NAME)) { - snd_printk(KERN_ERR PFX - "SC-6000 port I/O port region is already in use.\n"); + dev_err(devptr, + "SC-6000 port I/O port region is already in use.\n"); return -EBUSY; } vmss_port = devm_ioport_map(devptr, mss_port[dev], 4); if (!vmss_port) { - snd_printk(KERN_ERR PFX - "MSS port I/O cannot be iomapped.\n"); + dev_err(devptr, "MSS port I/O cannot be iomapped.\n"); return -EBUSY; } - snd_printd("Initializing BASE[0x%lx] IRQ[%d] DMA[%d] MIRQ[%d]\n", - port[dev], xirq, xdma, - mpu_irq[dev] == SNDRV_AUTO_IRQ ? 0 : mpu_irq[dev]); + dev_dbg(devptr, "Initializing BASE[0x%lx] IRQ[%d] DMA[%d] MIRQ[%d]\n", + port[dev], xirq, xdma, + mpu_irq[dev] == SNDRV_AUTO_IRQ ? 0 : mpu_irq[dev]); - err = sc6000_init_board(vport, vmss_port, dev); + err = sc6000_init_board(devptr, vport, vmss_port, dev); if (err < 0) return err; card->private_free = snd_sc6000_free; @@ -613,25 +617,24 @@ static int __snd_sc6000_probe(struct device *devptr, unsigned int dev) err = snd_wss_pcm(chip, 0); if (err < 0) { - snd_printk(KERN_ERR PFX - "error creating new WSS PCM device\n"); + dev_err(devptr, "error creating new WSS PCM device\n"); return err; } err = snd_wss_mixer(chip); if (err < 0) { - snd_printk(KERN_ERR PFX "error creating new WSS mixer\n"); + dev_err(devptr, "error creating new WSS mixer\n"); return err; } err = snd_sc6000_mixer(chip); if (err < 0) { - snd_printk(KERN_ERR PFX "the mixer rewrite failed\n"); + dev_err(devptr, "the mixer rewrite failed\n"); return err; } if (snd_opl3_create(card, 0x388, 0x388 + 2, OPL3_HW_AUTO, 0, &opl3) < 0) { - snd_printk(KERN_ERR PFX "no OPL device at 0x%x-0x%x ?\n", - 0x388, 0x388 + 2); + dev_err(devptr, "no OPL device at 0x%x-0x%x ?\n", + 0x388, 0x388 + 2); } else { err = snd_opl3_hwdep_new(opl3, 0, 1, NULL); if (err < 0) @@ -645,8 +648,8 @@ static int __snd_sc6000_probe(struct device *devptr, unsigned int dev) MPU401_HW_MPU401, mpu_port[dev], 0, mpu_irq[dev], NULL) < 0) - snd_printk(KERN_ERR "no MPU-401 device at 0x%lx ?\n", - mpu_port[dev]); + dev_err(devptr, "no MPU-401 device at 0x%lx ?\n", + mpu_port[dev]); } strcpy(card->driver, DRV_NAME); diff --git a/sound/isa/sscape.c b/sound/isa/sscape.c index cc56fafd27b125..09120e38f4c272 100644 --- a/sound/isa/sscape.c +++ b/sound/isa/sscape.c @@ -138,6 +138,7 @@ struct soundscape { struct snd_wss *chip; unsigned char midi_vol; + struct device *dev; }; #define INVALID_IRQ ((unsigned)-1) @@ -161,9 +162,9 @@ static struct snd_dma_buffer *get_dmabuf(struct soundscape *s, if (snd_dma_alloc_pages_fallback(SNDRV_DMA_TYPE_DEV, s->chip->card->dev, size, buf) < 0) { - snd_printk(KERN_ERR "sscape: Failed to allocate " - "%lu bytes for DMA\n", - size); + dev_err(s->dev, + "sscape: Failed to allocate %lu bytes for DMA\n", + size); return NULL; } } @@ -463,8 +464,7 @@ static int upload_dma_data(struct soundscape *s, const unsigned char *data, */ spin_unlock_irqrestore(&s->lock, flags); - snd_printk(KERN_ERR - "sscape: DMA upload has timed out\n"); + dev_err(s->dev, "sscape: DMA upload has timed out\n"); ret = -EAGAIN; goto _release_dma; } @@ -487,12 +487,11 @@ static int upload_dma_data(struct soundscape *s, const unsigned char *data, */ ret = 0; if (!obp_startup_ack(s, 5000)) { - snd_printk(KERN_ERR "sscape: No response " - "from on-board processor after upload\n"); + dev_err(s->dev, + "sscape: No response from on-board processor after upload\n"); ret = -EAGAIN; } else if (!host_startup_ack(s, 5000)) { - snd_printk(KERN_ERR - "sscape: SoundScape failed to initialise\n"); + dev_err(s->dev, "sscape: SoundScape failed to initialise\n"); ret = -EAGAIN; } @@ -521,7 +520,7 @@ static int sscape_upload_bootblock(struct snd_card *card) ret = request_firmware(&init_fw, "scope.cod", card->dev); if (ret < 0) { - snd_printk(KERN_ERR "sscape: Error loading scope.cod"); + dev_err(card->dev, "sscape: Error loading scope.cod"); return ret; } ret = upload_dma_data(sscape, init_fw->data, init_fw->size); @@ -539,8 +538,8 @@ static int sscape_upload_bootblock(struct snd_card *card) data &= 0xf; if (ret == 0 && data > 7) { - snd_printk(KERN_ERR - "sscape: timeout reading firmware version\n"); + dev_err(card->dev, + "sscape: timeout reading firmware version\n"); ret = -EAGAIN; } @@ -561,14 +560,14 @@ static int sscape_upload_microcode(struct snd_card *card, int version) err = request_firmware(&init_fw, name, card->dev); if (err < 0) { - snd_printk(KERN_ERR "sscape: Error loading sndscape.co%d", - version); + dev_err(card->dev, "sscape: Error loading sndscape.co%d", + version); return err; } err = upload_dma_data(sscape, init_fw->data, init_fw->size); if (err == 0) - snd_printk(KERN_INFO "sscape: MIDI firmware loaded %zu KBs\n", - init_fw->size >> 10); + dev_info(card->dev, "sscape: MIDI firmware loaded %zu KBs\n", + init_fw->size >> 10); release_firmware(init_fw); @@ -783,8 +782,8 @@ static int detect_sscape(struct soundscape *s, long wss_io) static int mpu401_open(struct snd_mpu401 *mpu) { if (!verify_mpu401(mpu)) { - snd_printk(KERN_ERR "sscape: MIDI disabled, " - "please load firmware\n"); + dev_err(mpu->rmidi->card->dev, + "sscape: MIDI disabled, please load firmware\n"); return -ENODEV; } @@ -871,22 +870,22 @@ static int create_ad1845(struct snd_card *card, unsigned port, err = snd_wss_pcm(chip, 0); if (err < 0) { - snd_printk(KERN_ERR "sscape: No PCM device " - "for AD1845 chip\n"); + dev_err(card->dev, + "sscape: No PCM device for AD1845 chip\n"); goto _error; } err = snd_wss_mixer(chip); if (err < 0) { - snd_printk(KERN_ERR "sscape: No mixer device " - "for AD1845 chip\n"); + dev_err(card->dev, + "sscape: No mixer device for AD1845 chip\n"); goto _error; } if (chip->hardware != WSS_HW_AD1848) { err = snd_wss_timer(chip, 0); if (err < 0) { - snd_printk(KERN_ERR "sscape: No timer device " - "for AD1845 chip\n"); + dev_err(card->dev, + "sscape: No timer device for AD1845 chip\n"); goto _error; } } @@ -895,8 +894,8 @@ static int create_ad1845(struct snd_card *card, unsigned port, err = snd_ctl_add(card, snd_ctl_new1(&midi_mixer_ctl, chip)); if (err < 0) { - snd_printk(KERN_ERR "sscape: Could not create " - "MIDI mixer control\n"); + dev_err(card->dev, + "sscape: Could not create MIDI mixer control\n"); goto _error; } } @@ -932,8 +931,8 @@ static int create_sscape(int dev, struct snd_card *card) */ io_res = devm_request_region(card->dev, port[dev], 8, "SoundScape"); if (!io_res) { - snd_printk(KERN_ERR - "sscape: can't grab port 0x%lx\n", port[dev]); + dev_err(card->dev, + "sscape: can't grab port 0x%lx\n", port[dev]); return -EBUSY; } wss_res = NULL; @@ -941,8 +940,8 @@ static int create_sscape(int dev, struct snd_card *card) wss_res = devm_request_region(card->dev, wss_port[dev], 4, "SoundScape"); if (!wss_res) { - snd_printk(KERN_ERR "sscape: can't grab port 0x%lx\n", - wss_port[dev]); + dev_err(card->dev, "sscape: can't grab port 0x%lx\n", + wss_port[dev]); return -EBUSY; } } @@ -952,7 +951,7 @@ static int create_sscape(int dev, struct snd_card *card) */ err = snd_devm_request_dma(card->dev, dma[dev], "SoundScape"); if (err < 0) { - snd_printk(KERN_ERR "sscape: can't grab DMA %d\n", dma[dev]); + dev_err(card->dev, "sscape: can't grab DMA %d\n", dma[dev]); return err; } @@ -962,7 +961,7 @@ static int create_sscape(int dev, struct snd_card *card) sscape->io_base = port[dev]; if (!detect_sscape(sscape, wss_port[dev])) { - printk(KERN_ERR "sscape: hardware not detected at 0x%x\n", + dev_err(card->dev, "sscape: hardware not detected at 0x%x\n", sscape->io_base); return -ENODEV; } @@ -985,21 +984,21 @@ static int create_sscape(int dev, struct snd_card *card) break; } - printk(KERN_INFO "sscape: %s card detected at 0x%x, using IRQ %d, DMA %d\n", - name, sscape->io_base, irq[dev], dma[dev]); + dev_info(card->dev, "sscape: %s card detected at 0x%x, using IRQ %d, DMA %d\n", + name, sscape->io_base, irq[dev], dma[dev]); /* * Check that the user didn't pass us garbage data ... */ irq_cfg = get_irq_config(sscape->type, irq[dev]); if (irq_cfg == INVALID_IRQ) { - snd_printk(KERN_ERR "sscape: Invalid IRQ %d\n", irq[dev]); + dev_err(card->dev, "sscape: Invalid IRQ %d\n", irq[dev]); return -ENXIO; } mpu_irq_cfg = get_irq_config(sscape->type, mpu_irq[dev]); if (mpu_irq_cfg == INVALID_IRQ) { - snd_printk(KERN_ERR "sscape: Invalid IRQ %d\n", mpu_irq[dev]); + dev_err(card->dev, "sscape: Invalid IRQ %d\n", mpu_irq[dev]); return -ENXIO; } @@ -1043,9 +1042,9 @@ static int create_sscape(int dev, struct snd_card *card) err = create_ad1845(card, wss_port[dev], irq[dev], dma[dev], dma2[dev]); if (err < 0) { - snd_printk(KERN_ERR - "sscape: No AD1845 device at 0x%lx, IRQ %d\n", - wss_port[dev], irq[dev]); + dev_err(card->dev, + "sscape: No AD1845 device at 0x%lx, IRQ %d\n", + wss_port[dev], irq[dev]); return err; } strcpy(card->driver, "SoundScape"); @@ -1065,9 +1064,9 @@ static int create_sscape(int dev, struct snd_card *card) err = create_mpu401(card, MIDI_DEVNUM, port[dev], mpu_irq[dev]); if (err < 0) { - snd_printk(KERN_ERR "sscape: Failed to create " - "MPU-401 device at 0x%lx\n", - port[dev]); + dev_err(card->dev, + "sscape: Failed to create MPU-401 device at 0x%lx\n", + port[dev]); return err; } @@ -1110,9 +1109,8 @@ static int snd_sscape_match(struct device *pdev, unsigned int i) if (irq[i] == SNDRV_AUTO_IRQ || mpu_irq[i] == SNDRV_AUTO_IRQ || dma[i] == SNDRV_AUTO_DMA) { - printk(KERN_INFO - "sscape: insufficient parameters, " - "need IO, IRQ, MPU-IRQ and DMA\n"); + dev_info(pdev, + "sscape: insufficient parameters, need IO, IRQ, MPU-IRQ and DMA\n"); return 0; } @@ -1131,6 +1129,7 @@ static int snd_sscape_probe(struct device *pdev, unsigned int dev) return ret; sscape = get_card_soundscape(card); + sscape->dev = pdev; sscape->type = SSCAPE; dma[dev] &= 0x03; @@ -1141,7 +1140,7 @@ static int snd_sscape_probe(struct device *pdev, unsigned int dev) ret = snd_card_register(card); if (ret < 0) { - snd_printk(KERN_ERR "sscape: Failed to register sound card\n"); + dev_err(pdev, "sscape: Failed to register sound card\n"); return ret; } dev_set_drvdata(pdev, card); @@ -1194,7 +1193,7 @@ static int sscape_pnp_detect(struct pnp_card_link *pcard, if (!pnp_is_active(dev)) { if (pnp_activate_dev(dev) < 0) { - snd_printk(KERN_INFO "sscape: device is inactive\n"); + dev_info(&dev->dev, "sscape: device is inactive\n"); return -EBUSY; } } @@ -1210,6 +1209,7 @@ static int sscape_pnp_detect(struct pnp_card_link *pcard, return ret; sscape = get_card_soundscape(card); + sscape->dev = card->dev; /* * Identify card model ... @@ -1240,7 +1240,7 @@ static int sscape_pnp_detect(struct pnp_card_link *pcard, ret = snd_card_register(card); if (ret < 0) { - snd_printk(KERN_ERR "sscape: Failed to register sound card\n"); + dev_err(card->dev, "sscape: Failed to register sound card\n"); return ret; } diff --git a/sound/isa/wavefront/wavefront.c b/sound/isa/wavefront/wavefront.c index e6e46a0266b070..621ab420a60f98 100644 --- a/sound/isa/wavefront/wavefront.c +++ b/sound/isa/wavefront/wavefront.c @@ -140,7 +140,7 @@ snd_wavefront_pnp (int dev, snd_wavefront_card_t *acard, struct pnp_card_link *c err = pnp_activate_dev(pdev); if (err < 0) { - snd_printk(KERN_ERR "PnP WSS pnp configure failure\n"); + dev_err(&pdev->dev, "PnP WSS pnp configure failure\n"); return err; } @@ -156,7 +156,7 @@ snd_wavefront_pnp (int dev, snd_wavefront_card_t *acard, struct pnp_card_link *c err = pnp_activate_dev(pdev); if (err < 0) { - snd_printk(KERN_ERR "PnP ICS2115 pnp configure failure\n"); + dev_err(&pdev->dev, "PnP ICS2115 pnp configure failure\n"); return err; } @@ -174,26 +174,27 @@ snd_wavefront_pnp (int dev, snd_wavefront_card_t *acard, struct pnp_card_link *c err = pnp_activate_dev(pdev); if (err < 0) { - snd_printk(KERN_ERR "PnP MPU401 pnp configure failure\n"); + dev_err(&pdev->dev, "PnP MPU401 pnp configure failure\n"); cs4232_mpu_port[dev] = SNDRV_AUTO_PORT; } else { cs4232_mpu_port[dev] = pnp_port_start(pdev, 0); cs4232_mpu_irq[dev] = pnp_irq(pdev, 0); } - snd_printk (KERN_INFO "CS4232 MPU: port=0x%lx, irq=%i\n", - cs4232_mpu_port[dev], - cs4232_mpu_irq[dev]); + dev_info(&pdev->dev, "CS4232 MPU: port=0x%lx, irq=%i\n", + cs4232_mpu_port[dev], + cs4232_mpu_irq[dev]); } - snd_printdd ("CS4232: pcm port=0x%lx, fm port=0x%lx, dma1=%i, dma2=%i, irq=%i\nICS2115: port=0x%lx, irq=%i\n", - cs4232_pcm_port[dev], - fm_port[dev], - dma1[dev], - dma2[dev], - cs4232_pcm_irq[dev], - ics2115_port[dev], - ics2115_irq[dev]); + dev_dbg(&pdev->dev, + "CS4232: pcm port=0x%lx, fm port=0x%lx, dma1=%i, dma2=%i, irq=%i\nICS2115: port=0x%lx, irq=%i\n", + cs4232_pcm_port[dev], + fm_port[dev], + dma1[dev], + dma2[dev], + cs4232_pcm_irq[dev], + ics2115_port[dev], + ics2115_irq[dev]); return 0; } @@ -251,7 +252,7 @@ static struct snd_hwdep *snd_wavefront_new_fx(struct snd_card *card, struct snd_hwdep *fx_processor; if (snd_wavefront_fx_start (&acard->wavefront)) { - snd_printk (KERN_ERR "cannot initialize YSS225 FX processor"); + dev_err(card->dev, "cannot initialize YSS225 FX processor"); return NULL; } @@ -282,7 +283,7 @@ static struct snd_rawmidi *snd_wavefront_new_midi(struct snd_card *card, first = 0; acard->wavefront.midi.base = port; if (snd_wavefront_midi_start (acard)) { - snd_printk (KERN_ERR "cannot initialize MIDI interface\n"); + dev_err(card->dev, "cannot initialize MIDI interface\n"); return NULL; } } @@ -349,7 +350,7 @@ snd_wavefront_probe (struct snd_card *card, int dev) cs4232_pcm_irq[dev], dma1[dev], dma2[dev], WSS_HW_DETECT, 0, &chip); if (err < 0) { - snd_printk(KERN_ERR "can't allocate WSS device\n"); + dev_err(card->dev, "can't allocate WSS device\n"); return err; } @@ -369,7 +370,7 @@ snd_wavefront_probe (struct snd_card *card, int dev) err = snd_opl3_create(card, fm_port[dev], fm_port[dev] + 2, OPL3_HW_OPL3_CS, 0, &opl3); if (err < 0) { - snd_printk (KERN_ERR "can't allocate or detect OPL3 synth\n"); + dev_err(card->dev, "can't allocate or detect OPL3 synth\n"); return err; } @@ -385,14 +386,14 @@ snd_wavefront_probe (struct snd_card *card, int dev) devm_request_region(card->dev, ics2115_port[dev], 16, "ICS2115"); if (acard->wavefront.res_base == NULL) { - snd_printk(KERN_ERR "unable to grab ICS2115 i/o region 0x%lx-0x%lx\n", - ics2115_port[dev], ics2115_port[dev] + 16 - 1); + dev_err(card->dev, "unable to grab ICS2115 i/o region 0x%lx-0x%lx\n", + ics2115_port[dev], ics2115_port[dev] + 16 - 1); return -EBUSY; } if (devm_request_irq(card->dev, ics2115_irq[dev], snd_wavefront_ics2115_interrupt, 0, "ICS2115", acard)) { - snd_printk(KERN_ERR "unable to use ICS2115 IRQ %d\n", ics2115_irq[dev]); + dev_err(card->dev, "unable to use ICS2115 IRQ %d\n", ics2115_irq[dev]); return -EBUSY; } @@ -402,7 +403,7 @@ snd_wavefront_probe (struct snd_card *card, int dev) wavefront_synth = snd_wavefront_new_synth(card, hw_dev, acard); if (wavefront_synth == NULL) { - snd_printk (KERN_ERR "can't create WaveFront synth device\n"); + dev_err(card->dev, "can't create WaveFront synth device\n"); return -ENOMEM; } @@ -414,7 +415,7 @@ snd_wavefront_probe (struct snd_card *card, int dev) err = snd_wss_mixer(chip); if (err < 0) { - snd_printk (KERN_ERR "can't allocate mixer device\n"); + dev_err(card->dev, "can't allocate mixer device\n"); return err; } @@ -425,7 +426,7 @@ snd_wavefront_probe (struct snd_card *card, int dev) cs4232_mpu_port[dev], 0, cs4232_mpu_irq[dev], NULL); if (err < 0) { - snd_printk (KERN_ERR "can't allocate CS4232 MPU-401 device\n"); + dev_err(card->dev, "can't allocate CS4232 MPU-401 device\n"); return err; } midi_dev++; @@ -441,7 +442,7 @@ snd_wavefront_probe (struct snd_card *card, int dev) ics2115_port[dev], internal_mpu); if (ics2115_internal_rmidi == NULL) { - snd_printk (KERN_ERR "can't setup ICS2115 internal MIDI device\n"); + dev_err(card->dev, "can't setup ICS2115 internal MIDI device\n"); return -ENOMEM; } midi_dev++; @@ -457,7 +458,7 @@ snd_wavefront_probe (struct snd_card *card, int dev) ics2115_port[dev], external_mpu); if (ics2115_external_rmidi == NULL) { - snd_printk (KERN_ERR "can't setup ICS2115 external MIDI device\n"); + dev_err(card->dev, "can't setup ICS2115 external MIDI device\n"); return -ENOMEM; } midi_dev++; @@ -471,7 +472,7 @@ snd_wavefront_probe (struct snd_card *card, int dev) acard, ics2115_port[dev]); if (fx_processor == NULL) { - snd_printk (KERN_ERR "can't setup FX device\n"); + dev_err(card->dev, "can't setup FX device\n"); return -ENOMEM; } @@ -525,11 +526,11 @@ static int snd_wavefront_isa_match(struct device *pdev, return 0; #endif if (cs4232_pcm_port[dev] == SNDRV_AUTO_PORT) { - snd_printk(KERN_ERR "specify CS4232 port\n"); + dev_err(pdev, "specify CS4232 port\n"); return 0; } if (ics2115_port[dev] == SNDRV_AUTO_PORT) { - snd_printk(KERN_ERR "specify ICS2115 port\n"); + dev_err(pdev, "specify ICS2115 port\n"); return 0; } return 1; @@ -585,7 +586,7 @@ static int snd_wavefront_pnp_detect(struct pnp_card_link *pcard, if (snd_wavefront_pnp (dev, card->private_data, pcard, pid) < 0) { if (cs4232_pcm_port[dev] == SNDRV_AUTO_PORT) { - snd_printk (KERN_ERR "isapnp detection failed\n"); + dev_err(card->dev, "isapnp detection failed\n"); return -ENODEV; } } diff --git a/sound/isa/wavefront/wavefront_fx.c b/sound/isa/wavefront/wavefront_fx.c index 0273b7dfaf1252..beca35ce04f3b1 100644 --- a/sound/isa/wavefront/wavefront_fx.c +++ b/sound/isa/wavefront/wavefront_fx.c @@ -38,7 +38,7 @@ wavefront_fx_idle (snd_wavefront_t *dev) } if (x & 0x80) { - snd_printk ("FX device never idle.\n"); + dev_err(dev->card->dev, "FX device never idle.\n"); return 0; } @@ -64,14 +64,14 @@ wavefront_fx_memset (snd_wavefront_t *dev, unsigned short *data) { if (page < 0 || page > 7) { - snd_printk ("FX memset: " - "page must be >= 0 and <= 7\n"); + dev_err(dev->card->dev, + "FX memset: page must be >= 0 and <= 7\n"); return -EINVAL; } if (addr < 0 || addr > 0x7f) { - snd_printk ("FX memset: " - "addr must be >= 0 and <= 7f\n"); + dev_err(dev->card->dev, + "FX memset: addr must be >= 0 and <= 7f\n"); return -EINVAL; } @@ -83,7 +83,7 @@ wavefront_fx_memset (snd_wavefront_t *dev, outb ((data[0] >> 8), dev->fx_dsp_msb); outb ((data[0] & 0xff), dev->fx_dsp_lsb); - snd_printk ("FX: addr %d:%x set to 0x%x\n", + dev_err(dev->card->dev, "FX: addr %d:%x set to 0x%x\n", page, addr, data[0]); } else { @@ -102,9 +102,9 @@ wavefront_fx_memset (snd_wavefront_t *dev, } if (i != cnt) { - snd_printk ("FX memset " - "(0x%x, 0x%x, 0x%lx, %d) incomplete\n", - page, addr, (unsigned long) data, cnt); + dev_err(dev->card->dev, + "FX memset (0x%x, 0x%x, 0x%lx, %d) incomplete\n", + page, addr, (unsigned long) data, cnt); return -EIO; } } @@ -123,7 +123,7 @@ snd_wavefront_fx_detect (snd_wavefront_t *dev) */ if (inb (dev->fx_status) & 0x80) { - snd_printk ("Hmm, probably a Maui or Tropez.\n"); + dev_err(dev->card->dev, "Hmm, probably a Maui or Tropez.\n"); return -1; } @@ -180,15 +180,15 @@ snd_wavefront_fx_ioctl (struct snd_hwdep *sdev, struct file *file, case WFFX_MEMSET: if (r.data[2] <= 0) { - snd_printk ("cannot write " - "<= 0 bytes to FX\n"); + dev_err(dev->card->dev, + "cannot write <= 0 bytes to FX\n"); return -EIO; } else if (r.data[2] == 1) { pd = (unsigned short *) &r.data[3]; } else { if (r.data[2] > 256) { - snd_printk ("cannot write " - "> 512 bytes to FX\n"); + dev_err(dev->card->dev, + "cannot write > 512 bytes to FX\n"); return -EIO; } page_data = memdup_array_user((unsigned char __user *) @@ -208,8 +208,8 @@ snd_wavefront_fx_ioctl (struct snd_hwdep *sdev, struct file *file, break; default: - snd_printk ("FX: ioctl %d not yet supported\n", - r.request); + dev_err(dev->card->dev, "FX: ioctl %d not yet supported\n", + r.request); return -ENOTTY; } return err; @@ -254,8 +254,8 @@ snd_wavefront_fx_start (snd_wavefront_t *dev) goto out; } } else { - snd_printk(KERN_ERR "invalid address" - " in register data\n"); + dev_err(dev->card->dev, + "invalid address in register data\n"); err = -1; goto out; } diff --git a/sound/isa/wavefront/wavefront_midi.c b/sound/isa/wavefront/wavefront_midi.c index 72e775ac7ad7f5..ead8cbe638ded3 100644 --- a/sound/isa/wavefront/wavefront_midi.c +++ b/sound/isa/wavefront/wavefront_midi.c @@ -501,7 +501,8 @@ snd_wavefront_midi_start (snd_wavefront_card_t *card) for (i = 0; i < 30000 && !output_ready (midi); i++); if (!output_ready (midi)) { - snd_printk ("MIDI interface not ready for command\n"); + dev_err(card->wavefront.card->dev, + "MIDI interface not ready for command\n"); return -1; } @@ -523,7 +524,8 @@ snd_wavefront_midi_start (snd_wavefront_card_t *card) } if (!ok) { - snd_printk ("cannot set UART mode for MIDI interface"); + dev_err(card->wavefront.card->dev, + "cannot set UART mode for MIDI interface"); dev->interrupts_are_midi = 0; return -1; } @@ -531,7 +533,8 @@ snd_wavefront_midi_start (snd_wavefront_card_t *card) /* Route external MIDI to WaveFront synth (by default) */ if (snd_wavefront_cmd (dev, WFC_MISYNTH_ON, rbuf, wbuf)) { - snd_printk ("can't enable MIDI-IN-2-synth routing.\n"); + dev_warn(card->wavefront.card->dev, + "can't enable MIDI-IN-2-synth routing.\n"); /* XXX error ? */ } @@ -547,14 +550,16 @@ snd_wavefront_midi_start (snd_wavefront_card_t *card) */ if (snd_wavefront_cmd (dev, WFC_VMIDI_OFF, rbuf, wbuf)) { - snd_printk ("virtual MIDI mode not disabled\n"); + dev_warn(card->wavefront.card->dev, + "virtual MIDI mode not disabled\n"); return 0; /* We're OK, but missing the external MIDI dev */ } snd_wavefront_midi_enable_virtual (card); if (snd_wavefront_cmd (dev, WFC_VMIDI_ON, rbuf, wbuf)) { - snd_printk ("cannot enable virtual MIDI mode.\n"); + dev_warn(card->wavefront.card->dev, + "cannot enable virtual MIDI mode.\n"); snd_wavefront_midi_disable_virtual (card); } return 0; diff --git a/sound/isa/wavefront/wavefront_synth.c b/sound/isa/wavefront/wavefront_synth.c index 13ce96148fa3b2..bd679e2da154e2 100644 --- a/sound/isa/wavefront/wavefront_synth.c +++ b/sound/isa/wavefront/wavefront_synth.c @@ -116,7 +116,7 @@ MODULE_PARM_DESC(osrun_time, "how many seconds to wait for the ICS2115 OS"); #define DPRINT(cond, ...) \ if ((dev->debug & (cond)) == (cond)) { \ - snd_printk (__VA_ARGS__); \ + pr_debug(__VA_ARGS__); \ } #else #define DPRINT(cond, args...) @@ -341,7 +341,7 @@ snd_wavefront_cmd (snd_wavefront_t *dev, wfcmd = wavefront_get_command(cmd); if (!wfcmd) { - snd_printk ("command 0x%x not supported.\n", + dev_err(dev->card->dev, "command 0x%x not supported.\n", cmd); return 1; } @@ -623,7 +623,7 @@ wavefront_get_sample_status (snd_wavefront_t *dev, int assume_rom) /* check sample status */ if (snd_wavefront_cmd (dev, WFC_GET_NSAMPLES, rbuf, wbuf)) { - snd_printk ("cannot request sample count.\n"); + dev_err(dev->card->dev, "cannot request sample count.\n"); return -1; } @@ -635,8 +635,8 @@ wavefront_get_sample_status (snd_wavefront_t *dev, int assume_rom) wbuf[1] = i >> 7; if (snd_wavefront_cmd (dev, WFC_IDENTIFY_SAMPLE_TYPE, rbuf, wbuf)) { - snd_printk(KERN_WARNING "cannot identify sample " - "type of slot %d\n", i); + dev_warn(dev->card->dev, + "cannot identify sample type of slot %d\n", i); dev->sample_status[i] = WF_ST_EMPTY; continue; } @@ -661,9 +661,9 @@ wavefront_get_sample_status (snd_wavefront_t *dev, int assume_rom) break; default: - snd_printk ("unknown sample type for " - "slot %d (0x%x)\n", - i, rbuf[0]); + dev_err(dev->card->dev, + "unknown sample type for slot %d (0x%x)\n", + i, rbuf[0]); } if (rbuf[0] != WF_ST_EMPTY) { @@ -671,9 +671,10 @@ wavefront_get_sample_status (snd_wavefront_t *dev, int assume_rom) } } - snd_printk ("%d samples used (%d real, %d aliases, %d multi), " - "%d empty\n", dev->samples_used, sc_real, sc_alias, sc_multi, - WF_MAX_SAMPLE - dev->samples_used); + dev_info(dev->card->dev, + "%d samples used (%d real, %d aliases, %d multi), %d empty\n", + dev->samples_used, sc_real, sc_alias, sc_multi, + WF_MAX_SAMPLE - dev->samples_used); return (0); @@ -706,8 +707,8 @@ wavefront_get_patch_status (snd_wavefront_t *dev) } else if (x == 3) { /* Bad patch number */ dev->patch_status[i] = 0; } else { - snd_printk ("upload patch " - "error 0x%x\n", x); + dev_err(dev->card->dev, + "upload patch error 0x%x\n", x); dev->patch_status[i] = 0; return 1; } @@ -724,7 +725,8 @@ wavefront_get_patch_status (snd_wavefront_t *dev) } } - snd_printk ("%d patch slots filled, %d in use\n", cnt, cnt2); + dev_info(dev->card->dev, "%d patch slots filled, %d in use\n", + cnt, cnt2); return (0); } @@ -760,8 +762,8 @@ wavefront_get_program_status (snd_wavefront_t *dev) } else if (x == 1) { /* Bad program number */ dev->prog_status[i] = 0; } else { - snd_printk ("upload program " - "error 0x%x\n", x); + dev_err(dev->card->dev, + "upload program error 0x%x\n", x); dev->prog_status[i] = 0; } } @@ -772,7 +774,7 @@ wavefront_get_program_status (snd_wavefront_t *dev) } } - snd_printk ("%d programs slots in use\n", cnt); + dev_info(dev->card->dev, "%d programs slots in use\n", cnt); return (0); } @@ -796,7 +798,7 @@ wavefront_send_patch (snd_wavefront_t *dev, wavefront_patch_info *header) munge_buf ((unsigned char *)&header->hdr.p, bptr, WF_PATCH_BYTES); if (snd_wavefront_cmd (dev, WFC_DOWNLOAD_PATCH, NULL, buf)) { - snd_printk ("download patch failed\n"); + dev_err(dev->card->dev, "download patch failed\n"); return -EIO; } @@ -837,7 +839,7 @@ wavefront_send_program (snd_wavefront_t *dev, wavefront_patch_info *header) munge_buf ((unsigned char *)&header->hdr.pr, &buf[1], WF_PROGRAM_BYTES); if (snd_wavefront_cmd (dev, WFC_DOWNLOAD_PROGRAM, NULL, buf)) { - snd_printk ("download patch failed\n"); + dev_err(dev->card->dev, "download patch failed\n"); return -EIO; } @@ -851,7 +853,7 @@ wavefront_freemem (snd_wavefront_t *dev) char rbuf[8]; if (snd_wavefront_cmd (dev, WFC_REPORT_FREE_MEMORY, rbuf, NULL)) { - snd_printk ("can't get memory stats.\n"); + dev_err(dev->card->dev, "can't get memory stats.\n"); return -1; } else { return demunge_int32 (rbuf, 4); @@ -901,7 +903,7 @@ wavefront_send_sample (snd_wavefront_t *dev, x = wavefront_find_free_sample(dev); if (x < 0) return -ENOMEM; - snd_printk ("unspecified sample => %d\n", x); + dev_info(dev->card->dev, "unspecified sample => %d\n", x); header->number = x; } @@ -935,9 +937,9 @@ wavefront_send_sample (snd_wavefront_t *dev, if (dev->rom_samples_rdonly) { if (dev->sample_status[header->number] & WF_SLOT_ROM) { - snd_printk ("sample slot %d " - "write protected\n", - header->number); + dev_err(dev->card->dev, + "sample slot %d write protected\n", + header->number); return -EACCES; } } @@ -949,9 +951,9 @@ wavefront_send_sample (snd_wavefront_t *dev, dev->freemem = wavefront_freemem (dev); if (dev->freemem < (int)header->size) { - snd_printk ("insufficient memory to " - "load %d byte sample.\n", - header->size); + dev_err(dev->card->dev, + "insufficient memory to load %d byte sample.\n", + header->size); return -ENOMEM; } @@ -960,8 +962,8 @@ wavefront_send_sample (snd_wavefront_t *dev, skip = WF_GET_CHANNEL(&header->hdr.s); if (skip > 0 && header->hdr.s.SampleResolution != LINEAR_16BIT) { - snd_printk ("channel selection only " - "possible on 16-bit samples"); + dev_err(dev->card->dev, + "channel selection only possible on 16-bit samples"); return -EINVAL; } @@ -1057,8 +1059,8 @@ wavefront_send_sample (snd_wavefront_t *dev, header->size ? WFC_DOWNLOAD_SAMPLE : WFC_DOWNLOAD_SAMPLE_HEADER, NULL, sample_hdr)) { - snd_printk ("sample %sdownload refused.\n", - header->size ? "" : "header "); + dev_err(dev->card->dev, "sample %sdownload refused.\n", + header->size ? "" : "header "); return -EIO; } @@ -1083,8 +1085,8 @@ wavefront_send_sample (snd_wavefront_t *dev, } if (snd_wavefront_cmd (dev, WFC_DOWNLOAD_BLOCK, NULL, NULL)) { - snd_printk ("download block " - "request refused.\n"); + dev_err(dev->card->dev, + "download block request refused.\n"); return -EIO; } @@ -1145,13 +1147,13 @@ wavefront_send_sample (snd_wavefront_t *dev, dma_ack = wavefront_read(dev); if (dma_ack != WF_DMA_ACK) { if (dma_ack == -1) { - snd_printk ("upload sample " - "DMA ack timeout\n"); + dev_err(dev->card->dev, + "upload sample DMA ack timeout\n"); return -EIO; } else { - snd_printk ("upload sample " - "DMA ack error 0x%x\n", - dma_ack); + dev_err(dev->card->dev, + "upload sample DMA ack error 0x%x\n", + dma_ack); return -EIO; } } @@ -1195,7 +1197,7 @@ wavefront_send_alias (snd_wavefront_t *dev, wavefront_patch_info *header) munge_int32 (*(&header->hdr.a.FrequencyBias+1), &alias_hdr[23], 2); if (snd_wavefront_cmd (dev, WFC_DOWNLOAD_SAMPLE_ALIAS, NULL, alias_hdr)) { - snd_printk ("download alias failed.\n"); + dev_err(dev->card->dev, "download alias failed.\n"); return -EIO; } @@ -1248,7 +1250,7 @@ wavefront_send_multisample (snd_wavefront_t *dev, wavefront_patch_info *header) if (snd_wavefront_cmd (dev, WFC_DOWNLOAD_MULTISAMPLE, (unsigned char *) (long) ((num_samples*2)+3), msample_hdr)) { - snd_printk ("download of multisample failed.\n"); + dev_err(dev->card->dev, "download of multisample failed.\n"); kfree(msample_hdr); return -EIO; } @@ -1271,7 +1273,7 @@ wavefront_fetch_multisample (snd_wavefront_t *dev, munge_int32 (header->number, number, 2); if (snd_wavefront_cmd (dev, WFC_UPLOAD_MULTISAMPLE, log_ns, number)) { - snd_printk ("upload multisample failed.\n"); + dev_err(dev->card->dev, "upload multisample failed.\n"); return -EIO; } @@ -1290,16 +1292,16 @@ wavefront_fetch_multisample (snd_wavefront_t *dev, val = wavefront_read(dev); if (val == -1) { - snd_printk ("upload multisample failed " - "during sample loop.\n"); + dev_err(dev->card->dev, + "upload multisample failed during sample loop.\n"); return -EIO; } d[0] = val; val = wavefront_read(dev); if (val == -1) { - snd_printk ("upload multisample failed " - "during sample loop.\n"); + dev_err(dev->card->dev, + "upload multisample failed during sample loop.\n"); return -EIO; } d[1] = val; @@ -1334,7 +1336,7 @@ wavefront_send_drum (snd_wavefront_t *dev, wavefront_patch_info *header) } if (snd_wavefront_cmd (dev, WFC_DOWNLOAD_EDRUM_PROGRAM, NULL, drumbuf)) { - snd_printk ("download drum failed.\n"); + dev_err(dev->card->dev, "download drum failed.\n"); return -EIO; } @@ -1352,7 +1354,7 @@ wavefront_find_free_sample (snd_wavefront_t *dev) return i; } } - snd_printk ("no free sample slots!\n"); + dev_err(dev->card->dev, "no free sample slots!\n"); return -1; } @@ -1368,7 +1370,7 @@ wavefront_find_free_patch (snd_wavefront_t *dev) return i; } } - snd_printk ("no free patch slots!\n"); + dev_err(dev->card->dev, "no free patch slots!\n"); return -1; } #endif @@ -1385,7 +1387,7 @@ wavefront_load_patch (snd_wavefront_t *dev, const char __user *addr) if (copy_from_user (header, addr, sizeof(wavefront_patch_info) - sizeof(wavefront_any))) { - snd_printk ("bad address for load patch.\n"); + dev_err(dev->card->dev, "bad address for load patch.\n"); err = -EFAULT; goto __error; } @@ -1463,8 +1465,8 @@ wavefront_load_patch (snd_wavefront_t *dev, const char __user *addr) break; default: - snd_printk ("unknown patch type %d.\n", - header->subkey); + dev_err(dev->card->dev, "unknown patch type %d.\n", + header->subkey); err = -EINVAL; break; } @@ -1527,13 +1529,13 @@ wavefront_synth_control (snd_wavefront_card_t *acard, switch (wc->cmd) { case WFC_DISABLE_INTERRUPTS: - snd_printk ("interrupts disabled.\n"); + dev_dbg(dev->card->dev, "interrupts disabled.\n"); outb (0x80|0x20, dev->control_port); dev->interrupts_are_midi = 1; return 0; case WFC_ENABLE_INTERRUPTS: - snd_printk ("interrupts enabled.\n"); + dev_dbg(dev->card->dev, "interrupts enabled.\n"); outb (0x80|0x40|0x20, dev->control_port); dev->interrupts_are_midi = 1; return 0; @@ -1550,7 +1552,7 @@ wavefront_synth_control (snd_wavefront_card_t *acard, case WFC_IDENTIFY_SLOT_TYPE: i = wc->wbuf[0] | (wc->wbuf[1] << 7); if (i <0 || i >= WF_MAX_SAMPLE) { - snd_printk ("invalid slot ID %d\n", + dev_err(dev->card->dev, "invalid slot ID %d\n", i); wc->status = EINVAL; return -EINVAL; @@ -1561,7 +1563,7 @@ wavefront_synth_control (snd_wavefront_card_t *acard, case WFC_DEBUG_DRIVER: dev->debug = wc->wbuf[0]; - snd_printk ("debug = 0x%x\n", dev->debug); + dev_dbg(dev->card->dev, "debug = 0x%x\n", dev->debug); return 0; case WFC_UPLOAD_PATCH: @@ -1578,8 +1580,8 @@ wavefront_synth_control (snd_wavefront_card_t *acard, return 0; case WFC_UPLOAD_SAMPLE_ALIAS: - snd_printk ("support for sample alias upload " - "being considered.\n"); + dev_err(dev->card->dev, + "support for sample alias upload being considered.\n"); wc->status = EINVAL; return -EINVAL; } @@ -1620,9 +1622,8 @@ wavefront_synth_control (snd_wavefront_card_t *acard, break; case WFC_UPLOAD_SAMPLE_ALIAS: - snd_printk ("support for " - "sample aliases still " - "being considered.\n"); + dev_err(dev->card->dev, + "support for sample aliases still being considered.\n"); break; case WFC_VMIDI_OFF: @@ -1760,7 +1761,7 @@ snd_wavefront_internal_interrupt (snd_wavefront_card_t *card) */ static int -snd_wavefront_interrupt_bits (int irq) +snd_wavefront_interrupt_bits(snd_wavefront_t *dev, int irq) { int bits; @@ -1780,7 +1781,7 @@ snd_wavefront_interrupt_bits (int irq) break; default: - snd_printk ("invalid IRQ %d\n", irq); + dev_err(dev->card->dev, "invalid IRQ %d\n", irq); bits = -1; } @@ -1815,7 +1816,7 @@ wavefront_reset_to_cleanliness (snd_wavefront_t *dev) /* IRQ already checked */ - bits = snd_wavefront_interrupt_bits (dev->irq); + bits = snd_wavefront_interrupt_bits(dev, dev->irq); /* try reset of port */ @@ -1885,7 +1886,7 @@ wavefront_reset_to_cleanliness (snd_wavefront_t *dev) */ if (!dev->irq_ok) { - snd_printk ("intr not received after h/w un-reset.\n"); + dev_err(dev->card->dev, "intr not received after h/w un-reset.\n"); goto gone_bad; } @@ -1909,18 +1910,18 @@ wavefront_reset_to_cleanliness (snd_wavefront_t *dev) dev->data_port, ramcheck_time*HZ); if (!dev->irq_ok) { - snd_printk ("post-RAM-check interrupt not received.\n"); + dev_err(dev->card->dev, "post-RAM-check interrupt not received.\n"); goto gone_bad; } if (!wavefront_wait (dev, STAT_CAN_READ)) { - snd_printk ("no response to HW version cmd.\n"); + dev_err(dev->card->dev, "no response to HW version cmd.\n"); goto gone_bad; } hwv[0] = wavefront_read(dev); if (hwv[0] == -1) { - snd_printk ("board not responding correctly.\n"); + dev_err(dev->card->dev, "board not responding correctly.\n"); goto gone_bad; } @@ -1932,11 +1933,11 @@ wavefront_reset_to_cleanliness (snd_wavefront_t *dev) hwv[0] = wavefront_read(dev); if (hwv[0] == -1) { - snd_printk ("on-board RAM test failed " - "(bad error code).\n"); + dev_err(dev->card->dev, + "on-board RAM test failed (bad error code).\n"); } else { - snd_printk ("on-board RAM test failed " - "(error code: 0x%x).\n", + dev_err(dev->card->dev, + "on-board RAM test failed (error code: 0x%x).\n", hwv[0]); } goto gone_bad; @@ -1946,12 +1947,12 @@ wavefront_reset_to_cleanliness (snd_wavefront_t *dev) hwv[1] = wavefront_read(dev); if (hwv[1] == -1) { - snd_printk ("incorrect h/w response.\n"); + dev_err(dev->card->dev, "incorrect h/w response.\n"); goto gone_bad; } - snd_printk ("hardware version %d.%d\n", - hwv[0], hwv[1]); + dev_info(dev->card->dev, "hardware version %d.%d\n", + hwv[0], hwv[1]); return 0; @@ -1971,7 +1972,7 @@ wavefront_download_firmware (snd_wavefront_t *dev, char *path) err = request_firmware(&firmware, path, dev->card->dev); if (err < 0) { - snd_printk(KERN_ERR "firmware (%s) download failed!!!\n", path); + dev_err(dev->card->dev, "firmware (%s) download failed!!!\n", path); return 1; } @@ -1982,16 +1983,16 @@ wavefront_download_firmware (snd_wavefront_t *dev, char *path) if (section_length == 0) break; if (section_length < 0 || section_length > WF_SECTION_MAX) { - snd_printk(KERN_ERR - "invalid firmware section length %d\n", - section_length); + dev_err(dev->card->dev, + "invalid firmware section length %d\n", + section_length); goto failure; } buf++; len++; if (firmware->size < len + section_length) { - snd_printk(KERN_ERR "firmware section read error.\n"); + dev_err(dev->card->dev, "firmware section read error.\n"); goto failure; } @@ -2008,15 +2009,14 @@ wavefront_download_firmware (snd_wavefront_t *dev, char *path) /* get ACK */ if (!wavefront_wait(dev, STAT_CAN_READ)) { - snd_printk(KERN_ERR "time out for firmware ACK.\n"); + dev_err(dev->card->dev, "time out for firmware ACK.\n"); goto failure; } err = inb(dev->data_port); if (err != WF_ACK) { - snd_printk(KERN_ERR - "download of section #%d not " - "acknowledged, ack = 0x%x\n", - section_cnt_downloaded + 1, err); + dev_err(dev->card->dev, + "download of section #%d not acknowledged, ack = 0x%x\n", + section_cnt_downloaded + 1, err); goto failure; } @@ -2028,7 +2028,7 @@ wavefront_download_firmware (snd_wavefront_t *dev, char *path) failure: release_firmware(firmware); - snd_printk(KERN_ERR "firmware download failed!!!\n"); + dev_err(dev->card->dev, "firmware download failed!!!\n"); return 1; } @@ -2040,7 +2040,7 @@ wavefront_do_reset (snd_wavefront_t *dev) char voices[1]; if (wavefront_reset_to_cleanliness (dev)) { - snd_printk ("hw reset failed.\n"); + dev_err(dev->card->dev, "hw reset failed.\n"); goto gone_bad; } @@ -2064,7 +2064,7 @@ wavefront_do_reset (snd_wavefront_t *dev) (osrun_time*HZ)); if (!dev->irq_ok) { - snd_printk ("no post-OS interrupt.\n"); + dev_err(dev->card->dev, "no post-OS interrupt.\n"); goto gone_bad; } @@ -2074,7 +2074,7 @@ wavefront_do_reset (snd_wavefront_t *dev) dev->data_port, (10*HZ)); if (!dev->irq_ok) { - snd_printk ("no post-OS interrupt(2).\n"); + dev_err(dev->card->dev, "no post-OS interrupt(2).\n"); goto gone_bad; } @@ -2094,20 +2094,20 @@ wavefront_do_reset (snd_wavefront_t *dev) if (dev->freemem < 0) goto gone_bad; - snd_printk ("available DRAM %dk\n", dev->freemem / 1024); + dev_info(dev->card->dev, "available DRAM %dk\n", dev->freemem / 1024); if (wavefront_write (dev, 0xf0) || wavefront_write (dev, 1) || (wavefront_read (dev) < 0)) { dev->debug = 0; - snd_printk ("MPU emulation mode not set.\n"); + dev_err(dev->card->dev, "MPU emulation mode not set.\n"); goto gone_bad; } voices[0] = 32; if (snd_wavefront_cmd (dev, WFC_SET_NVOICES, NULL, voices)) { - snd_printk ("cannot set number of voices to 32.\n"); + dev_err(dev->card->dev, "cannot set number of voices to 32.\n"); goto gone_bad; } @@ -2187,8 +2187,8 @@ snd_wavefront_detect (snd_wavefront_card_t *card) dev->fw_version[0] = rbuf[0]; dev->fw_version[1] = rbuf[1]; - snd_printk ("firmware %d.%d already loaded.\n", - rbuf[0], rbuf[1]); + dev_info(dev->card->dev, "firmware %d.%d already loaded.\n", + rbuf[0], rbuf[1]); /* check that a command actually works */ @@ -2197,22 +2197,24 @@ snd_wavefront_detect (snd_wavefront_card_t *card) dev->hw_version[0] = rbuf[0]; dev->hw_version[1] = rbuf[1]; } else { - snd_printk ("not raw, but no " - "hardware version!\n"); + dev_err(dev->card->dev, + "not raw, but no hardware version!\n"); return -1; } if (!wf_raw) { return 0; } else { - snd_printk ("reloading firmware as you requested.\n"); + dev_info(dev->card->dev, + "reloading firmware as you requested.\n"); dev->israw = 1; } } else { dev->israw = 1; - snd_printk ("no response to firmware probe, assume raw.\n"); + dev_info(dev->card->dev, + "no response to firmware probe, assume raw.\n"); } diff --git a/sound/isa/wss/wss_lib.c b/sound/isa/wss/wss_lib.c index 026061b55ee945..9c655789574d0a 100644 --- a/sound/isa/wss/wss_lib.c +++ b/sound/isa/wss/wss_lib.c @@ -187,15 +187,16 @@ void snd_wss_out(struct snd_wss *chip, unsigned char reg, unsigned char value) snd_wss_wait(chip); #ifdef CONFIG_SND_DEBUG if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) - snd_printk(KERN_DEBUG "out: auto calibration time out " - "- reg = 0x%x, value = 0x%x\n", reg, value); + dev_dbg(chip->card->dev, + "out: auto calibration time out - reg = 0x%x, value = 0x%x\n", + reg, value); #endif wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | reg); wss_outb(chip, CS4231P(REG), value); chip->image[reg] = value; mb(); - snd_printdd("codec out - reg 0x%x = 0x%x\n", - chip->mce_bit | reg, value); + dev_dbg(chip->card->dev, "codec out - reg 0x%x = 0x%x\n", + chip->mce_bit | reg, value); } EXPORT_SYMBOL(snd_wss_out); @@ -204,8 +205,8 @@ unsigned char snd_wss_in(struct snd_wss *chip, unsigned char reg) snd_wss_wait(chip); #ifdef CONFIG_SND_DEBUG if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) - snd_printk(KERN_DEBUG "in: auto calibration time out " - "- reg = 0x%x\n", reg); + dev_dbg(chip->card->dev, + "in: auto calibration time out - reg = 0x%x\n", reg); #endif wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | reg); mb(); @@ -222,7 +223,7 @@ void snd_cs4236_ext_out(struct snd_wss *chip, unsigned char reg, wss_outb(chip, CS4231P(REG), val); chip->eimage[CS4236_REG(reg)] = val; #if 0 - printk(KERN_DEBUG "ext out : reg = 0x%x, val = 0x%x\n", reg, val); + dev_dbg(chip->card->dev, "ext out : reg = 0x%x, val = 0x%x\n", reg, val); #endif } EXPORT_SYMBOL(snd_cs4236_ext_out); @@ -238,8 +239,8 @@ unsigned char snd_cs4236_ext_in(struct snd_wss *chip, unsigned char reg) { unsigned char res; res = wss_inb(chip, CS4231P(REG)); - printk(KERN_DEBUG "ext in : reg = 0x%x, val = 0x%x\n", - reg, res); + dev_dbg(chip->card->dev, "ext in : reg = 0x%x, val = 0x%x\n", + reg, res); return res; } #endif @@ -250,87 +251,87 @@ EXPORT_SYMBOL(snd_cs4236_ext_in); static void snd_wss_debug(struct snd_wss *chip) { - printk(KERN_DEBUG + dev_dbg(chip->card->dev, "CS4231 REGS: INDEX = 0x%02x " " STATUS = 0x%02x\n", wss_inb(chip, CS4231P(REGSEL)), wss_inb(chip, CS4231P(STATUS))); - printk(KERN_DEBUG + dev_dbg(chip->card->dev, " 0x00: left input = 0x%02x " " 0x10: alt 1 (CFIG 2) = 0x%02x\n", snd_wss_in(chip, 0x00), snd_wss_in(chip, 0x10)); - printk(KERN_DEBUG + dev_dbg(chip->card->dev, " 0x01: right input = 0x%02x " " 0x11: alt 2 (CFIG 3) = 0x%02x\n", snd_wss_in(chip, 0x01), snd_wss_in(chip, 0x11)); - printk(KERN_DEBUG + dev_dbg(chip->card->dev, " 0x02: GF1 left input = 0x%02x " " 0x12: left line in = 0x%02x\n", snd_wss_in(chip, 0x02), snd_wss_in(chip, 0x12)); - printk(KERN_DEBUG + dev_dbg(chip->card->dev, " 0x03: GF1 right input = 0x%02x " " 0x13: right line in = 0x%02x\n", snd_wss_in(chip, 0x03), snd_wss_in(chip, 0x13)); - printk(KERN_DEBUG + dev_dbg(chip->card->dev, " 0x04: CD left input = 0x%02x " " 0x14: timer low = 0x%02x\n", snd_wss_in(chip, 0x04), snd_wss_in(chip, 0x14)); - printk(KERN_DEBUG + dev_dbg(chip->card->dev, " 0x05: CD right input = 0x%02x " " 0x15: timer high = 0x%02x\n", snd_wss_in(chip, 0x05), snd_wss_in(chip, 0x15)); - printk(KERN_DEBUG + dev_dbg(chip->card->dev, " 0x06: left output = 0x%02x " " 0x16: left MIC (PnP) = 0x%02x\n", snd_wss_in(chip, 0x06), snd_wss_in(chip, 0x16)); - printk(KERN_DEBUG + dev_dbg(chip->card->dev, " 0x07: right output = 0x%02x " " 0x17: right MIC (PnP) = 0x%02x\n", snd_wss_in(chip, 0x07), snd_wss_in(chip, 0x17)); - printk(KERN_DEBUG + dev_dbg(chip->card->dev, " 0x08: playback format = 0x%02x " " 0x18: IRQ status = 0x%02x\n", snd_wss_in(chip, 0x08), snd_wss_in(chip, 0x18)); - printk(KERN_DEBUG + dev_dbg(chip->card->dev, " 0x09: iface (CFIG 1) = 0x%02x " " 0x19: left line out = 0x%02x\n", snd_wss_in(chip, 0x09), snd_wss_in(chip, 0x19)); - printk(KERN_DEBUG + dev_dbg(chip->card->dev, " 0x0a: pin control = 0x%02x " " 0x1a: mono control = 0x%02x\n", snd_wss_in(chip, 0x0a), snd_wss_in(chip, 0x1a)); - printk(KERN_DEBUG + dev_dbg(chip->card->dev, " 0x0b: init & status = 0x%02x " " 0x1b: right line out = 0x%02x\n", snd_wss_in(chip, 0x0b), snd_wss_in(chip, 0x1b)); - printk(KERN_DEBUG + dev_dbg(chip->card->dev, " 0x0c: revision & mode = 0x%02x " " 0x1c: record format = 0x%02x\n", snd_wss_in(chip, 0x0c), snd_wss_in(chip, 0x1c)); - printk(KERN_DEBUG + dev_dbg(chip->card->dev, " 0x0d: loopback = 0x%02x " " 0x1d: var freq (PnP) = 0x%02x\n", snd_wss_in(chip, 0x0d), snd_wss_in(chip, 0x1d)); - printk(KERN_DEBUG + dev_dbg(chip->card->dev, " 0x0e: ply upr count = 0x%02x " " 0x1e: ply lwr count = 0x%02x\n", snd_wss_in(chip, 0x0e), snd_wss_in(chip, 0x1e)); - printk(KERN_DEBUG + dev_dbg(chip->card->dev, " 0x0f: rec upr count = 0x%02x " " 0x1f: rec lwr count = 0x%02x\n", snd_wss_in(chip, 0x0f), @@ -365,16 +366,16 @@ void snd_wss_mce_up(struct snd_wss *chip) snd_wss_wait(chip); #ifdef CONFIG_SND_DEBUG if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) - snd_printk(KERN_DEBUG - "mce_up - auto calibration time out (0)\n"); + dev_dbg(chip->card->dev, + "mce_up - auto calibration time out (0)\n"); #endif spin_lock_irqsave(&chip->reg_lock, flags); chip->mce_bit |= CS4231_MCE; timeout = wss_inb(chip, CS4231P(REGSEL)); if (timeout == 0x80) - snd_printk(KERN_DEBUG "mce_up [0x%lx]: " - "serious init problem - codec still busy\n", - chip->port); + dev_dbg(chip->card->dev, + "mce_up [0x%lx]: serious init problem - codec still busy\n", + chip->port); if (!(timeout & CS4231_MCE)) wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | (timeout & 0x1f)); @@ -393,9 +394,9 @@ void snd_wss_mce_down(struct snd_wss *chip) #ifdef CONFIG_SND_DEBUG if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) - snd_printk(KERN_DEBUG "mce_down [0x%lx] - " - "auto calibration time out (0)\n", - (long)CS4231P(REGSEL)); + dev_dbg(chip->card->dev, + "mce_down [0x%lx] - auto calibration time out (0)\n", + (long)CS4231P(REGSEL)); #endif spin_lock_irqsave(&chip->reg_lock, flags); chip->mce_bit &= ~CS4231_MCE; @@ -403,9 +404,9 @@ void snd_wss_mce_down(struct snd_wss *chip) wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | (timeout & 0x1f)); spin_unlock_irqrestore(&chip->reg_lock, flags); if (timeout == 0x80) - snd_printk(KERN_DEBUG "mce_down [0x%lx]: " - "serious init problem - codec still busy\n", - chip->port); + dev_dbg(chip->card->dev, + "mce_down [0x%lx]: serious init problem - codec still busy\n", + chip->port); if ((timeout & CS4231_MCE) == 0 || !(chip->hardware & hw_mask)) return; @@ -416,7 +417,7 @@ void snd_wss_mce_down(struct snd_wss *chip) */ msleep(1); - snd_printdd("(1) jiffies = %lu\n", jiffies); + dev_dbg(chip->card->dev, "(1) jiffies = %lu\n", jiffies); /* check condition up to 250 ms */ end_time = jiffies + msecs_to_jiffies(250); @@ -424,27 +425,29 @@ void snd_wss_mce_down(struct snd_wss *chip) CS4231_CALIB_IN_PROGRESS) { if (time_after(jiffies, end_time)) { - snd_printk(KERN_ERR "mce_down - " - "auto calibration time out (2)\n"); + dev_err(chip->card->dev, + "mce_down - auto calibration time out (2)\n"); return; } msleep(1); } - snd_printdd("(2) jiffies = %lu\n", jiffies); + dev_dbg(chip->card->dev, "(2) jiffies = %lu\n", jiffies); /* check condition up to 100 ms */ end_time = jiffies + msecs_to_jiffies(100); while (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) { if (time_after(jiffies, end_time)) { - snd_printk(KERN_ERR "mce_down - auto calibration time out (3)\n"); + dev_err(chip->card->dev, + "mce_down - auto calibration time out (3)\n"); return; } msleep(1); } - snd_printdd("(3) jiffies = %lu\n", jiffies); - snd_printd("mce_down - exit = 0x%x\n", wss_inb(chip, CS4231P(REGSEL))); + dev_dbg(chip->card->dev, "(3) jiffies = %lu\n", jiffies); + dev_dbg(chip->card->dev, "mce_down - exit = 0x%x\n", + wss_inb(chip, CS4231P(REGSEL))); } EXPORT_SYMBOL(snd_wss_mce_down); @@ -543,7 +546,7 @@ static unsigned char snd_wss_get_format(struct snd_wss *chip, if (channels > 1) rformat |= CS4231_STEREO; #if 0 - snd_printk(KERN_DEBUG "get_format: 0x%x (mode=0x%x)\n", format, mode); + dev_dbg(chip->card->dev, "get_format: 0x%x (mode=0x%x)\n", format, mode); #endif return rformat; } @@ -793,7 +796,7 @@ static void snd_wss_init(struct snd_wss *chip) snd_wss_mce_down(chip); #ifdef SNDRV_DEBUG_MCE - snd_printk(KERN_DEBUG "init: (1)\n"); + dev_dbg(chip->card->dev, "init: (1)\n"); #endif snd_wss_mce_up(chip); spin_lock_irqsave(&chip->reg_lock, flags); @@ -808,7 +811,7 @@ static void snd_wss_init(struct snd_wss *chip) snd_wss_mce_down(chip); #ifdef SNDRV_DEBUG_MCE - snd_printk(KERN_DEBUG "init: (2)\n"); + dev_dbg(chip->card->dev, "init: (2)\n"); #endif snd_wss_mce_up(chip); @@ -821,8 +824,8 @@ static void snd_wss_init(struct snd_wss *chip) snd_wss_mce_down(chip); #ifdef SNDRV_DEBUG_MCE - snd_printk(KERN_DEBUG "init: (3) - afei = 0x%x\n", - chip->image[CS4231_ALT_FEATURE_1]); + dev_dbg(chip->card->dev, "init: (3) - afei = 0x%x\n", + chip->image[CS4231_ALT_FEATURE_1]); #endif spin_lock_irqsave(&chip->reg_lock, flags); @@ -838,7 +841,7 @@ static void snd_wss_init(struct snd_wss *chip) snd_wss_mce_down(chip); #ifdef SNDRV_DEBUG_MCE - snd_printk(KERN_DEBUG "init: (4)\n"); + dev_dbg(chip->card->dev, "init: (4)\n"); #endif snd_wss_mce_up(chip); @@ -851,7 +854,7 @@ static void snd_wss_init(struct snd_wss *chip) snd_wss_calibrate_mute(chip, 0); #ifdef SNDRV_DEBUG_MCE - snd_printk(KERN_DEBUG "init: (5)\n"); + dev_dbg(chip->card->dev, "init: (5)\n"); #endif } @@ -1256,12 +1259,13 @@ static int snd_wss_probe(struct snd_wss *chip) break; /* this is valid value */ } } - snd_printdd("wss: port = 0x%lx, id = 0x%x\n", chip->port, id); + dev_dbg(chip->card->dev, "wss: port = 0x%lx, id = 0x%x\n", + chip->port, id); if (id != 0x0a) return -ENODEV; /* no valid device found */ rev = snd_wss_in(chip, CS4231_VERSION) & 0xe7; - snd_printdd("CS4231: VERSION (I25) = 0x%x\n", rev); + dev_dbg(chip->card->dev, "CS4231: VERSION (I25) = 0x%x\n", rev); if (rev == 0x80) { unsigned char tmp = snd_wss_in(chip, 23); snd_wss_out(chip, 23, ~tmp); @@ -1280,8 +1284,8 @@ static int snd_wss_probe(struct snd_wss *chip) } else if (rev == 0x03) { chip->hardware = WSS_HW_CS4236B; } else { - snd_printk(KERN_ERR - "unknown CS chip with version 0x%x\n", rev); + dev_err(chip->card->dev, + "unknown CS chip with version 0x%x\n", rev); return -ENODEV; /* unknown CS4231 chip? */ } } @@ -1340,7 +1344,9 @@ static int snd_wss_probe(struct snd_wss *chip) snd_cs4236_ext_out(chip, CS4236_VERSION, 0xff); id = snd_cs4236_ext_in(chip, CS4236_VERSION); snd_cs4236_ext_out(chip, CS4236_VERSION, rev); - snd_printdd("CS4231: ext version; rev = 0x%x, id = 0x%x\n", rev, id); + dev_dbg(chip->card->dev, + "CS4231: ext version; rev = 0x%x, id = 0x%x\n", + rev, id); if ((id & 0x1f) == 0x1d) { /* CS4235 */ chip->hardware = WSS_HW_CS4235; switch (id >> 5) { @@ -1349,10 +1355,9 @@ static int snd_wss_probe(struct snd_wss *chip) case 6: break; default: - snd_printk(KERN_WARNING - "unknown CS4235 chip " - "(enhanced version = 0x%x)\n", - id); + dev_warn(chip->card->dev, + "unknown CS4235 chip (enhanced version = 0x%x)\n", + id); } } else if ((id & 0x1f) == 0x0b) { /* CS4236/B */ switch (id >> 5) { @@ -1363,10 +1368,9 @@ static int snd_wss_probe(struct snd_wss *chip) chip->hardware = WSS_HW_CS4236B; break; default: - snd_printk(KERN_WARNING - "unknown CS4236 chip " - "(enhanced version = 0x%x)\n", - id); + dev_warn(chip->card->dev, + "unknown CS4236 chip (enhanced version = 0x%x)\n", + id); } } else if ((id & 0x1f) == 0x08) { /* CS4237B */ chip->hardware = WSS_HW_CS4237B; @@ -1377,10 +1381,9 @@ static int snd_wss_probe(struct snd_wss *chip) case 7: break; default: - snd_printk(KERN_WARNING - "unknown CS4237B chip " - "(enhanced version = 0x%x)\n", - id); + dev_warn(chip->card->dev, + "unknown CS4237B chip (enhanced version = 0x%x)\n", + id); } } else if ((id & 0x1f) == 0x09) { /* CS4238B */ chip->hardware = WSS_HW_CS4238B; @@ -1390,10 +1393,9 @@ static int snd_wss_probe(struct snd_wss *chip) case 7: break; default: - snd_printk(KERN_WARNING - "unknown CS4238B chip " - "(enhanced version = 0x%x)\n", - id); + dev_warn(chip->card->dev, + "unknown CS4238B chip (enhanced version = 0x%x)\n", + id); } } else if ((id & 0x1f) == 0x1e) { /* CS4239 */ chip->hardware = WSS_HW_CS4239; @@ -1403,15 +1405,14 @@ static int snd_wss_probe(struct snd_wss *chip) case 6: break; default: - snd_printk(KERN_WARNING - "unknown CS4239 chip " - "(enhanced version = 0x%x)\n", - id); + dev_warn(chip->card->dev, + "unknown CS4239 chip (enhanced version = 0x%x)\n", + id); } } else { - snd_printk(KERN_WARNING - "unknown CS4236/CS423xB chip " - "(enhanced version = 0x%x)\n", id); + dev_warn(chip->card->dev, + "unknown CS4236/CS423xB chip (enhanced version = 0x%x)\n", + id); } } } @@ -1644,8 +1645,9 @@ static void snd_wss_resume(struct snd_wss *chip) wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | (timeout & 0x1f)); spin_unlock_irqrestore(&chip->reg_lock, flags); if (timeout == 0x80) - snd_printk(KERN_ERR "down [0x%lx]: serious init problem " - "- codec still busy\n", chip->port); + dev_err(chip->card->dev + "down [0x%lx]: serious init problem - codec still busy\n", + chip->port); if ((timeout & CS4231_MCE) == 0 || !(chip->hardware & (WSS_HW_CS4231_MASK | WSS_HW_CS4232_MASK))) { return; @@ -1757,7 +1759,7 @@ int snd_wss_create(struct snd_card *card, chip->res_port = devm_request_region(card->dev, port, 4, "WSS"); if (!chip->res_port) { - snd_printk(KERN_ERR "wss: can't grab port 0x%lx\n", port); + dev_err(chip->card->dev, "wss: can't grab port 0x%lx\n", port); return -EBUSY; } chip->port = port; @@ -1765,7 +1767,7 @@ int snd_wss_create(struct snd_card *card, chip->res_cport = devm_request_region(card->dev, cport, 8, "CS4232 Control"); if (!chip->res_cport) { - snd_printk(KERN_ERR + dev_err(chip->card->dev, "wss: can't grab control port 0x%lx\n", cport); return -ENODEV; } @@ -1774,20 +1776,20 @@ int snd_wss_create(struct snd_card *card, if (!(hwshare & WSS_HWSHARE_IRQ)) if (devm_request_irq(card->dev, irq, snd_wss_interrupt, 0, "WSS", (void *) chip)) { - snd_printk(KERN_ERR "wss: can't grab IRQ %d\n", irq); + dev_err(chip->card->dev, "wss: can't grab IRQ %d\n", irq); return -EBUSY; } chip->irq = irq; card->sync_irq = chip->irq; if (!(hwshare & WSS_HWSHARE_DMA1) && snd_devm_request_dma(card->dev, dma1, "WSS - 1")) { - snd_printk(KERN_ERR "wss: can't grab DMA1 %d\n", dma1); + dev_err(chip->card->dev, "wss: can't grab DMA1 %d\n", dma1); return -EBUSY; } chip->dma1 = dma1; if (!(hwshare & WSS_HWSHARE_DMA2) && dma1 != dma2 && dma2 >= 0 && snd_devm_request_dma(card->dev, dma2, "WSS - 2")) { - snd_printk(KERN_ERR "wss: can't grab DMA2 %d\n", dma2); + dev_err(chip->card->dev, "wss: can't grab DMA2 %d\n", dma2); return -EBUSY; } if (dma1 == dma2 || dma2 < 0) { @@ -1810,8 +1812,8 @@ int snd_wss_create(struct snd_card *card, #if 0 if (chip->hardware & WSS_HW_CS4232_MASK) { if (chip->res_cport == NULL) - snd_printk(KERN_ERR "CS4232 control port features are " - "not accessible\n"); + dev_err(chip->card->dev, + "CS4232 control port features are not accessible\n"); } #endif diff --git a/sound/pci/asihpi/asihpi.c b/sound/pci/asihpi/asihpi.c index 001786e2aba130..fdd4fe16225fcb 100644 --- a/sound/pci/asihpi/asihpi.c +++ b/sound/pci/asihpi/asihpi.c @@ -36,19 +36,10 @@ MODULE_AUTHOR("AudioScience inc. "); MODULE_DESCRIPTION("AudioScience ALSA ASI5xxx ASI6xxx ASI87xx ASI89xx " HPI_VER_STRING); -#if defined CONFIG_SND_DEBUG_VERBOSE -/** - * snd_printddd - very verbose debug printk - * @format: format string - * - * Works like snd_printk() for debugging purposes. - * Ignored when CONFIG_SND_DEBUG_VERBOSE is not set. - * Must set snd module debug parameter to 3 to enable at runtime. - */ -#define snd_printddd(format, args...) \ - __snd_printk(3, __FILE__, __LINE__, format, ##args) +#ifdef ASIHPI_VERBOSE_DEBUG +#define asihpi_dbg(format, args...) pr_debug(format, ##args) #else -#define snd_printddd(format, args...) do { } while (0) +#define asihpi_dbg(format, args...) do { } while (0) #endif static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* index 0-MAX */ @@ -260,8 +251,7 @@ static inline u16 hpi_stream_group_reset(u32 h_stream) static u16 handle_error(u16 err, int line, char *filename) { if (err) - printk(KERN_WARNING - "in file %s, line %d: HPI error %d\n", + pr_warn("in file %s, line %d: HPI error %d\n", filename, line, err); return err; } @@ -273,16 +263,18 @@ static u16 handle_error(u16 err, int line, char *filename) static void print_hwparams(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *p) { + struct device *dev = substream->pcm->card->dev; char name[16]; + snd_pcm_debug_name(substream, name, sizeof(name)); - snd_printdd("%s HWPARAMS\n", name); - snd_printdd(" samplerate=%dHz channels=%d format=%d subformat=%d\n", + dev_dbg(dev, "%s HWPARAMS\n", name); + dev_dbg(dev, " samplerate=%dHz channels=%d format=%d subformat=%d\n", params_rate(p), params_channels(p), params_format(p), params_subformat(p)); - snd_printdd(" buffer=%dB period=%dB period_size=%dB periods=%d\n", + dev_dbg(dev, " buffer=%dB period=%dB period_size=%dB periods=%d\n", params_buffer_bytes(p), params_period_bytes(p), params_period_size(p), params_periods(p)); - snd_printdd(" buffer_size=%d access=%d data_rate=%dB/s\n", + dev_dbg(dev, " buffer_size=%d access=%d data_rate=%dB/s\n", params_buffer_size(p), params_access(p), params_rate(p) * params_channels(p) * snd_pcm_format_width(params_format(p)) / 8); @@ -317,7 +309,8 @@ static const snd_pcm_format_t hpi_to_alsa_formats[] = { }; -static int snd_card_asihpi_format_alsa2hpi(snd_pcm_format_t alsa_format, +static int snd_card_asihpi_format_alsa2hpi(struct snd_card_asihpi *asihpi, + snd_pcm_format_t alsa_format, u16 *hpi_format) { u16 format; @@ -330,8 +323,8 @@ static int snd_card_asihpi_format_alsa2hpi(snd_pcm_format_t alsa_format, } } - snd_printd(KERN_WARNING "failed match for alsa format %d\n", - alsa_format); + dev_dbg(asihpi->card->dev, "failed match for alsa format %d\n", + alsa_format); *hpi_format = 0; return -EINVAL; } @@ -439,7 +432,7 @@ static int snd_card_asihpi_pcm_hw_params(struct snd_pcm_substream *substream, unsigned int bytes_per_sec; print_hwparams(substream, params); - err = snd_card_asihpi_format_alsa2hpi(params_format(params), &format); + err = snd_card_asihpi_format_alsa2hpi(card, params_format(params), &format); if (err) return err; @@ -461,13 +454,13 @@ static int snd_card_asihpi_pcm_hw_params(struct snd_pcm_substream *substream, err = hpi_stream_host_buffer_attach(dpcm->h_stream, params_buffer_bytes(params), runtime->dma_addr); if (err == 0) { - snd_printdd( + dev_dbg(card->card->dev, "stream_host_buffer_attach success %u %lu\n", params_buffer_bytes(params), (unsigned long)runtime->dma_addr); } else { - snd_printd("stream_host_buffer_attach error %d\n", - err); + dev_dbg(card->card->dev, + "stream_host_buffer_attach error %d\n", err); return -ENOMEM; } @@ -569,7 +562,7 @@ static int snd_card_asihpi_trigger(struct snd_pcm_substream *substream, switch (cmd) { case SNDRV_PCM_TRIGGER_START: - snd_printdd("%s trigger start\n", name); + dev_dbg(card->card->dev, "%s trigger start\n", name); snd_pcm_group_for_each_entry(s, substream) { struct snd_pcm_runtime *runtime = s->runtime; struct snd_card_asihpi_pcm *ds = runtime->private_data; @@ -590,7 +583,7 @@ static int snd_card_asihpi_trigger(struct snd_pcm_substream *substream, * data?? */ unsigned int preload = ds->period_bytes * 1; - snd_printddd("%d preload %d\n", s->number, preload); + asihpi_dbg("%d preload %d\n", s->number, preload); hpi_handle_error(hpi_outstream_write_buf( ds->h_stream, &runtime->dma_area[0], @@ -600,7 +593,7 @@ static int snd_card_asihpi_trigger(struct snd_pcm_substream *substream, } if (card->support_grouping) { - snd_printdd("%d group\n", s->number); + dev_dbg(card->card->dev, "%d group\n", s->number); e = hpi_stream_group_add( dpcm->h_stream, ds->h_stream); @@ -621,7 +614,7 @@ static int snd_card_asihpi_trigger(struct snd_pcm_substream *substream, break; case SNDRV_PCM_TRIGGER_STOP: - snd_printdd("%s trigger stop\n", name); + dev_dbg(card->card->dev, "%s trigger stop\n", name); card->pcm_stop(substream); snd_pcm_group_for_each_entry(s, substream) { if (snd_pcm_substream_chip(s) != card) @@ -635,7 +628,7 @@ static int snd_card_asihpi_trigger(struct snd_pcm_substream *substream, __snd_pcm_set_state(s->runtime, SNDRV_PCM_STATE_SETUP); if (card->support_grouping) { - snd_printdd("%d group\n", s->number); + dev_dbg(card->card->dev, "%d group\n", s->number); snd_pcm_trigger_done(s, substream); } else break; @@ -652,17 +645,17 @@ static int snd_card_asihpi_trigger(struct snd_pcm_substream *substream, break; case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - snd_printdd("%s trigger pause release\n", name); + dev_dbg(card->card->dev, "%s trigger pause release\n", name); card->pcm_start(substream); hpi_handle_error(hpi_stream_start(dpcm->h_stream)); break; case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - snd_printdd("%s trigger pause push\n", name); + dev_dbg(card->card->dev, "%s trigger pause push\n", name); card->pcm_stop(substream); hpi_handle_error(hpi_stream_stop(dpcm->h_stream)); break; default: - snd_printd(KERN_ERR "\tINVALID\n"); + dev_dbg(card->card->dev, "\tINVALID\n"); return -EINVAL; } @@ -760,12 +753,13 @@ static void snd_card_asihpi_timer_function(struct timer_list *t) if (state == HPI_STATE_STOPPED) { if (bytes_avail == 0) { hpi_handle_error(hpi_stream_start(ds->h_stream)); - snd_printdd("P%d start\n", s->number); + dev_dbg(card->card->dev, + "P%d start\n", s->number); ds->drained_count = 0; } } else if (state == HPI_STATE_DRAINED) { - snd_printd(KERN_WARNING "P%d drained\n", - s->number); + dev_dbg(card->card->dev, + "P%d drained\n", s->number); ds->drained_count++; if (ds->drained_count > 20) { snd_pcm_stop_xrun(s); @@ -790,7 +784,7 @@ static void snd_card_asihpi_timer_function(struct timer_list *t) newdata); } - snd_printddd( + asihpi_dbg( "timer1, %s, %d, S=%d, elap=%d, rw=%d, dsp=%d, left=%d, aux=%d, space=%d, hw_ptr=%ld, appl_ptr=%ld\n", name, s->number, state, ds->pcm_buf_elapsed_dma_ofs, @@ -821,7 +815,7 @@ static void snd_card_asihpi_timer_function(struct timer_list *t) next_jiffies = max(next_jiffies, 1U); dpcm->timer.expires = jiffies + next_jiffies; - snd_printddd("timer2, jif=%d, buf_pos=%d, newdata=%d, xfer=%d\n", + asihpi_dbg("timer2, jif=%d, buf_pos=%d, newdata=%d, xfer=%d\n", next_jiffies, pcm_buf_dma_ofs, newdata, xfercount); snd_pcm_group_for_each_entry(s, substream) { @@ -854,7 +848,7 @@ static void snd_card_asihpi_timer_function(struct timer_list *t) } if (s->stream == SNDRV_PCM_STREAM_PLAYBACK) { - snd_printddd("write1, P=%d, xfer=%d, buf_ofs=%d\n", + asihpi_dbg("write1, P=%d, xfer=%d, buf_ofs=%d\n", s->number, xfer1, buf_ofs); hpi_handle_error( hpi_outstream_write_buf( @@ -864,7 +858,7 @@ static void snd_card_asihpi_timer_function(struct timer_list *t) if (xfer2) { pd = s->runtime->dma_area; - snd_printddd("write2, P=%d, xfer=%d, buf_ofs=%d\n", + asihpi_dbg("write2, P=%d, xfer=%d, buf_ofs=%d\n", s->number, xfercount - xfer1, buf_ofs); hpi_handle_error( @@ -874,7 +868,7 @@ static void snd_card_asihpi_timer_function(struct timer_list *t) &ds->format)); } } else { - snd_printddd("read1, C=%d, xfer=%d\n", + asihpi_dbg("read1, C=%d, xfer=%d\n", s->number, xfer1); hpi_handle_error( hpi_instream_read_buf( @@ -882,7 +876,7 @@ static void snd_card_asihpi_timer_function(struct timer_list *t) pd, xfer1)); if (xfer2) { pd = s->runtime->dma_area; - snd_printddd("read2, C=%d, xfer=%d\n", + asihpi_dbg("read2, C=%d, xfer=%d\n", s->number, xfer2); hpi_handle_error( hpi_instream_read_buf( @@ -919,8 +913,6 @@ static int snd_card_asihpi_playback_prepare(struct snd_pcm_substream * struct snd_pcm_runtime *runtime = substream->runtime; struct snd_card_asihpi_pcm *dpcm = runtime->private_data; - snd_printdd("P%d prepare\n", substream->number); - hpi_handle_error(hpi_outstream_reset(dpcm->h_stream)); dpcm->pcm_buf_host_rw_ofs = 0; dpcm->pcm_buf_dma_ofs = 0; @@ -938,7 +930,7 @@ snd_card_asihpi_playback_pointer(struct snd_pcm_substream *substream) snd_pcm_debug_name(substream, name, sizeof(name)); ptr = bytes_to_frames(runtime, dpcm->pcm_buf_dma_ofs % dpcm->buffer_bytes); - snd_printddd("%s, pointer=%ld\n", name, (unsigned long)ptr); + asihpi_dbg("%s, pointer=%ld\n", name, (unsigned long)ptr); return ptr; } @@ -1060,8 +1052,6 @@ static int snd_card_asihpi_playback_open(struct snd_pcm_substream *substream) snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, card->update_interval_frames, UINT_MAX); - snd_printdd("playback open\n"); - return 0; } @@ -1071,8 +1061,6 @@ static int snd_card_asihpi_playback_close(struct snd_pcm_substream *substream) struct snd_card_asihpi_pcm *dpcm = runtime->private_data; hpi_handle_error(hpi_outstream_close(dpcm->h_stream)); - snd_printdd("playback close\n"); - return 0; } @@ -1095,7 +1083,7 @@ snd_card_asihpi_capture_pointer(struct snd_pcm_substream *substream) char name[16]; snd_pcm_debug_name(substream, name, sizeof(name)); - snd_printddd("%s, pointer=%d\n", name, dpcm->pcm_buf_dma_ofs); + asihpi_dbg("%s, pointer=%d\n", name, dpcm->pcm_buf_dma_ofs); /* NOTE Unlike playback can't use actual samples_played for the capture position, because those samples aren't yet in the local buffer available for reading. @@ -1113,7 +1101,6 @@ static int snd_card_asihpi_capture_prepare(struct snd_pcm_substream *substream) dpcm->pcm_buf_dma_ofs = 0; dpcm->pcm_buf_elapsed_dma_ofs = 0; - snd_printdd("Capture Prepare %d\n", substream->number); return 0; } @@ -1162,8 +1149,9 @@ static int snd_card_asihpi_capture_open(struct snd_pcm_substream *substream) if (dpcm == NULL) return -ENOMEM; - snd_printdd("capture open adapter %d stream %d\n", - card->hpi->adapter->index, substream->number); + + dev_dbg(card->card->dev, "capture open adapter %d stream %d\n", + card->hpi->adapter->index, substream->number); err = hpi_handle_error( hpi_instream_open(card->hpi->adapter->index, @@ -1413,8 +1401,6 @@ static void asihpi_ctl_init(struct snd_kcontrol_new *snd_control, hpi_ctl->src_node_index, dir, name); } - /* printk(KERN_INFO "Adding %s %d to %d ", hpi_ctl->name, - hpi_ctl->wSrcNodeType, hpi_ctl->wDstNodeType); */ } /*------------------------------------------------------------ @@ -2175,9 +2161,8 @@ static int snd_asihpi_mux_get(struct snd_kcontrol *kcontrol, return 0; } } - snd_printd(KERN_WARNING - "Control %x failed to match mux source %hu %hu\n", - h_control, source_type, source_index); + pr_warn("%s: Control %x failed to match mux source %hu %hu\n", + __func__, h_control, source_type, source_index); ucontrol->value.enumerated.item[0] = 0; return 0; } diff --git a/sound/pci/asihpi/hpimsgx.c b/sound/pci/asihpi/hpimsgx.c index d0caef2994818e..b68e6bfbbfbab5 100644 --- a/sound/pci/asihpi/hpimsgx.c +++ b/sound/pci/asihpi/hpimsgx.c @@ -708,7 +708,7 @@ static u16 HPIMSGX__init(struct hpi_message *phm, phr->error = HPI_ERROR_PROCESSING_MESSAGE; return phr->error; } - if (hr.error == 0) { + if (hr.error == 0 && hr.u.s.adapter_index < HPI_MAX_ADAPTERS) { /* the adapter was created successfully save the mapping for future use */ hpi_entry_points[hr.u.s.adapter_index] = entry_point_func; diff --git a/sound/pci/asihpi/hpioctl.c b/sound/pci/asihpi/hpioctl.c index 477a5b4b50bcbf..9fb0c8e503dfa5 100644 --- a/sound/pci/asihpi/hpioctl.c +++ b/sound/pci/asihpi/hpioctl.c @@ -356,7 +356,7 @@ int asihpi_adapter_probe(struct pci_dev *pci_dev, memset(&adapter, 0, sizeof(adapter)); - dev_printk(KERN_DEBUG, &pci_dev->dev, + dev_dbg(&pci_dev->dev, "probe %04x:%04x,%04x:%04x,%04x\n", pci_dev->vendor, pci_dev->device, pci_dev->subsystem_vendor, pci_dev->subsystem_device, pci_dev->devfn); diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c index 84989c291cd773..8a895d83800562 100644 --- a/sound/pci/azt3328.c +++ b/sound/pci/azt3328.c @@ -1220,7 +1220,7 @@ snd_azf3328_codec_setfmt(struct snd_azf3328_codec_data *codec, case AZF_FREQ_22050: freq = SOUNDFORMAT_FREQ_22050; break; case AZF_FREQ_32000: freq = SOUNDFORMAT_FREQ_32000; break; default: - snd_printk(KERN_WARNING "unknown bitrate %d, assuming 44.1kHz!\n", bitrate); + pr_warn("azf3328: unknown bitrate %d, assuming 44.1kHz!\n", bitrate); fallthrough; case AZF_FREQ_44100: freq = SOUNDFORMAT_FREQ_44100; break; case AZF_FREQ_48000: freq = SOUNDFORMAT_FREQ_48000; break; diff --git a/sound/pci/emu10k1/emu10k1_patch.c b/sound/pci/emu10k1/emu10k1_patch.c index dbfa89435ac2a4..806b4f95cad160 100644 --- a/sound/pci/emu10k1/emu10k1_patch.c +++ b/sound/pci/emu10k1/emu10k1_patch.c @@ -40,8 +40,9 @@ snd_emu10k1_sample_new(struct snd_emux *rec, struct snd_sf_sample *sp, if (sp->v.mode_flags & (SNDRV_SFNT_SAMPLE_BIDIR_LOOP | SNDRV_SFNT_SAMPLE_REVERSE_LOOP)) { /* should instead return -ENOTSUPP; but compatibility */ - printk(KERN_WARNING "Emu10k1 wavetable patch %d with unsupported loop feature\n", - sp->v.sample); + dev_warn(emu->card->dev, + "Emu10k1 wavetable patch %d with unsupported loop feature\n", + sp->v.sample); } if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS) { diff --git a/sound/pci/hda/cs35l41_hda.c b/sound/pci/hda/cs35l41_hda.c index 4b411ed8c3fe0e..d68bf7591d90c1 100644 --- a/sound/pci/hda/cs35l41_hda.c +++ b/sound/pci/hda/cs35l41_hda.c @@ -133,19 +133,8 @@ static const struct reg_sequence cs35l41_hda_mute[] = { { CS35L41_AMP_DIG_VOL_CTRL, 0x0000A678 }, // AMP_HPF_PCM_EN = 1, AMP_VOL_PCM Mute }; -static void cs35l41_add_controls(struct cs35l41_hda *cs35l41) -{ - struct hda_cs_dsp_ctl_info info; - - info.device_name = cs35l41->amp_name; - info.fw_type = cs35l41->firmware_type; - info.card = cs35l41->codec->card; - - hda_cs_dsp_add_controls(&cs35l41->cs_dsp, &info); -} - static const struct cs_dsp_client_ops client_ops = { - .control_remove = hda_cs_dsp_control_remove, + /* cs_dsp requires the client to provide this even if it is empty */ }; static int cs35l41_request_tuning_param_file(struct cs35l41_hda *cs35l41, char *tuning_filename, @@ -603,8 +592,6 @@ static int cs35l41_init_dsp(struct cs35l41_hda *cs35l41) if (ret) goto err; - cs35l41_add_controls(cs35l41); - cs35l41_hda_apply_calibration(cs35l41); err: diff --git a/sound/pci/hda/cs35l41_hda_spi.c b/sound/pci/hda/cs35l41_hda_spi.c index b76c0dfd5fefc4..f8c356ad0d340f 100644 --- a/sound/pci/hda/cs35l41_hda_spi.c +++ b/sound/pci/hda/cs35l41_hda_spi.c @@ -38,6 +38,7 @@ static const struct spi_device_id cs35l41_hda_spi_id[] = { { "cs35l41-hda", 0 }, {} }; +MODULE_DEVICE_TABLE(spi, cs35l41_hda_spi_id); static const struct acpi_device_id cs35l41_acpi_hda_match[] = { { "CSC3551", 0 }, diff --git a/sound/pci/hda/cs35l56_hda.c b/sound/pci/hda/cs35l56_hda.c index 96d3f13c5abf9f..a9dfd62637cf4c 100644 --- a/sound/pci/hda/cs35l56_hda.c +++ b/sound/pci/hda/cs35l56_hda.c @@ -413,7 +413,7 @@ static void cs35l56_hda_remove_controls(struct cs35l56_hda *cs35l56) } static const struct cs_dsp_client_ops cs35l56_hda_client_ops = { - .control_remove = hda_cs_dsp_control_remove, + /* cs_dsp requires the client to provide this even if it is empty */ }; static int cs35l56_hda_request_firmware_file(struct cs35l56_hda *cs35l56, @@ -559,18 +559,6 @@ static void cs35l56_hda_release_firmware_files(const struct firmware *wmfw_firmw kfree(coeff_filename); } -static void cs35l56_hda_create_dsp_controls_work(struct work_struct *work) -{ - struct cs35l56_hda *cs35l56 = container_of(work, struct cs35l56_hda, control_work); - struct hda_cs_dsp_ctl_info info; - - info.device_name = cs35l56->amp_name; - info.fw_type = HDA_CS_DSP_FW_MISC; - info.card = cs35l56->codec->card; - - hda_cs_dsp_add_controls(&cs35l56->cs_dsp, &info); -} - static void cs35l56_hda_apply_calibration(struct cs35l56_hda *cs35l56) { int ret; @@ -595,26 +583,15 @@ static void cs35l56_hda_fw_load(struct cs35l56_hda *cs35l56) char *wmfw_filename = NULL; unsigned int preloaded_fw_ver; bool firmware_missing; - bool add_dsp_controls_required = false; int ret; - /* - * control_work must be flushed before proceeding, but we can't do that - * here as it would create a deadlock on controls_rwsem so it must be - * performed before queuing dsp_work. - */ - WARN_ON_ONCE(work_busy(&cs35l56->control_work)); - /* * Prepare for a new DSP power-up. If the DSP has had firmware * downloaded previously then it needs to be powered down so that it - * can be updated and if hadn't been patched before then the controls - * will need to be added once firmware download succeeds. + * can be updated. */ if (cs35l56->base.fw_patched) cs_dsp_power_down(&cs35l56->cs_dsp); - else - add_dsp_controls_required = true; cs35l56->base.fw_patched = false; @@ -698,15 +675,6 @@ static void cs35l56_hda_fw_load(struct cs35l56_hda *cs35l56) CS35L56_FIRMWARE_MISSING); cs35l56->base.fw_patched = true; - /* - * Adding controls is deferred to prevent a lock inversion - ALSA takes - * the controls_rwsem when adding a control, the get() / put() - * functions of a control are called holding controls_rwsem and those - * that depend on running firmware wait for dsp_work() to complete. - */ - if (add_dsp_controls_required) - queue_work(system_long_wq, &cs35l56->control_work); - ret = cs_dsp_run(&cs35l56->cs_dsp); if (ret) dev_dbg(cs35l56->base.dev, "%s: cs_dsp_run ret %d\n", __func__, ret); @@ -753,7 +721,6 @@ static int cs35l56_hda_bind(struct device *dev, struct device *master, void *mas strscpy(comp->name, dev_name(dev), sizeof(comp->name)); comp->playback_hook = cs35l56_hda_playback_hook; - flush_work(&cs35l56->control_work); queue_work(system_long_wq, &cs35l56->dsp_work); cs35l56_hda_create_controls(cs35l56); @@ -775,7 +742,6 @@ static void cs35l56_hda_unbind(struct device *dev, struct device *master, void * struct hda_component *comp; cancel_work_sync(&cs35l56->dsp_work); - cancel_work_sync(&cs35l56->control_work); cs35l56_hda_remove_controls(cs35l56); @@ -806,7 +772,6 @@ static int cs35l56_hda_system_suspend(struct device *dev) struct cs35l56_hda *cs35l56 = dev_get_drvdata(dev); cs35l56_hda_wait_dsp_ready(cs35l56); - flush_work(&cs35l56->control_work); if (cs35l56->playing) cs35l56_hda_pause(cs35l56); @@ -1026,7 +991,6 @@ int cs35l56_hda_common_probe(struct cs35l56_hda *cs35l56, int hid, int id) dev_set_drvdata(cs35l56->base.dev, cs35l56); INIT_WORK(&cs35l56->dsp_work, cs35l56_hda_dsp_work); - INIT_WORK(&cs35l56->control_work, cs35l56_hda_create_dsp_controls_work); ret = cs35l56_hda_read_acpi(cs35l56, hid, id); if (ret) diff --git a/sound/pci/hda/cs35l56_hda.h b/sound/pci/hda/cs35l56_hda.h index c40d159507c26d..38d94fb213a50a 100644 --- a/sound/pci/hda/cs35l56_hda.h +++ b/sound/pci/hda/cs35l56_hda.h @@ -23,7 +23,6 @@ struct cs35l56_hda { struct cs35l56_base base; struct hda_codec *codec; struct work_struct dsp_work; - struct work_struct control_work; int index; const char *system_name; diff --git a/sound/pci/hda/hda_controller.h b/sound/pci/hda/hda_controller.h index c2d0109866e62e..68c883f202ca5b 100644 --- a/sound/pci/hda/hda_controller.h +++ b/sound/pci/hda/hda_controller.h @@ -28,7 +28,7 @@ #else #define AZX_DCAPS_I915_COMPONENT 0 /* NOP */ #endif -/* 14 unused */ +#define AZX_DCAPS_AMD_ALLOC_FIX (1 << 14) /* AMD allocation workaround */ #define AZX_DCAPS_CTX_WORKAROUND (1 << 15) /* X-Fi workaround */ #define AZX_DCAPS_POSFIX_LPIB (1 << 16) /* Use LPIB as default */ #define AZX_DCAPS_AMD_WORKAROUND (1 << 17) /* AMD-specific workaround */ diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index ca59534456360d..b79020adce63b1 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -40,6 +40,7 @@ #ifdef CONFIG_X86 /* for snoop control */ +#include #include #include #endif @@ -306,7 +307,7 @@ enum { /* quirks for ATI HDMI with snoop off */ #define AZX_DCAPS_PRESET_ATI_HDMI_NS \ - (AZX_DCAPS_PRESET_ATI_HDMI | AZX_DCAPS_SNOOP_OFF) + (AZX_DCAPS_PRESET_ATI_HDMI | AZX_DCAPS_AMD_ALLOC_FIX) /* quirks for AMD SB */ #define AZX_DCAPS_PRESET_AMD_SB \ @@ -1706,6 +1707,13 @@ static void azx_check_snoop_available(struct azx *chip) if (chip->driver_caps & AZX_DCAPS_SNOOP_OFF) snoop = false; +#ifdef CONFIG_X86 + /* check the presence of DMA ops (i.e. IOMMU), disable snoop conditionally */ + if ((chip->driver_caps & AZX_DCAPS_AMD_ALLOC_FIX) && + !get_dma_ops(chip->card->dev)) + snoop = false; +#endif + chip->snoop = snoop; if (!snoop) { dev_info(chip->card->dev, "Force to non-snoop mode\n"); diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index fe66d4fcc26afc..643e0496b09362 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -1989,6 +1989,8 @@ static int hdmi_add_cvt(struct hda_codec *codec, hda_nid_t cvt_nid) } static const struct snd_pci_quirk force_connect_list[] = { + SND_PCI_QUIRK(0x103c, 0x83e2, "HP EliteDesk 800 G4", 1), + SND_PCI_QUIRK(0x103c, 0x83ef, "HP MP9 G4 Retail System AMS", 1), SND_PCI_QUIRK(0x103c, 0x870f, "HP", 1), SND_PCI_QUIRK(0x103c, 0x871a, "HP", 1), SND_PCI_QUIRK(0x103c, 0x8711, "HP", 1), diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 1645d21d422f33..c573183c69a962 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -11,15 +11,18 @@ */ #include +#include #include #include #include #include #include #include +#include #include #include #include +#include #include #include #include @@ -583,7 +586,6 @@ static void alc_shutup_pins(struct hda_codec *codec) switch (codec->core.vendor_id) { case 0x10ec0236: case 0x10ec0256: - case 0x10ec0257: case 0x19e58326: case 0x10ec0283: case 0x10ec0285: @@ -6856,6 +6858,86 @@ static void comp_generic_fixup(struct hda_codec *cdc, int action, const char *bu } } +static void cs35lxx_autodet_fixup(struct hda_codec *cdc, + const struct hda_fixup *fix, + int action) +{ + struct device *dev = hda_codec_dev(cdc); + struct acpi_device *adev; + struct fwnode_handle *fwnode __free(fwnode_handle) = NULL; + const char *bus = NULL; + static const struct { + const char *hid; + const char *name; + } acpi_ids[] = {{ "CSC3554", "cs35l54-hda" }, + { "CSC3556", "cs35l56-hda" }, + { "CSC3557", "cs35l57-hda" }}; + char *match; + int i, count = 0, count_devindex = 0; + + switch (action) { + case HDA_FIXUP_ACT_PRE_PROBE: + for (i = 0; i < ARRAY_SIZE(acpi_ids); ++i) { + adev = acpi_dev_get_first_match_dev(acpi_ids[i].hid, NULL, -1); + if (adev) + break; + } + if (!adev) { + dev_err(dev, "Failed to find ACPI entry for a Cirrus Amp\n"); + return; + } + + count = i2c_acpi_client_count(adev); + if (count > 0) { + bus = "i2c"; + } else { + count = acpi_spi_count_resources(adev); + if (count > 0) + bus = "spi"; + } + + fwnode = fwnode_handle_get(acpi_fwnode_handle(adev)); + acpi_dev_put(adev); + + if (!bus) { + dev_err(dev, "Did not find any buses for %s\n", acpi_ids[i].hid); + return; + } + + if (!fwnode) { + dev_err(dev, "Could not get fwnode for %s\n", acpi_ids[i].hid); + return; + } + + /* + * When available the cirrus,dev-index property is an accurate + * count of the amps in a system and is used in preference to + * the count of bus devices that can contain additional address + * alias entries. + */ + count_devindex = fwnode_property_count_u32(fwnode, "cirrus,dev-index"); + if (count_devindex > 0) + count = count_devindex; + + match = devm_kasprintf(dev, GFP_KERNEL, "-%%s:00-%s.%%d", acpi_ids[i].name); + if (!match) + return; + dev_info(dev, "Found %d %s on %s (%s)\n", count, acpi_ids[i].hid, bus, match); + comp_generic_fixup(cdc, action, bus, acpi_ids[i].hid, match, count); + + break; + case HDA_FIXUP_ACT_FREE: + /* + * Pass the action on to comp_generic_fixup() so that + * hda_component_manager functions can be called in just once + * place. In this context the bus, hid, match_str or count + * values do not need to be calculated. + */ + comp_generic_fixup(cdc, action, NULL, NULL, NULL, 0); + break; + } +} + static void cs35l41_fixup_i2c_two(struct hda_codec *cdc, const struct hda_fixup *fix, int action) { comp_generic_fixup(cdc, action, "i2c", "CSC3551", "-%s:00-cs35l41-hda.%d", 2); @@ -6888,26 +6970,6 @@ static void alc287_fixup_legion_16ithg6_speakers(struct hda_codec *cdc, const st comp_generic_fixup(cdc, action, "i2c", "CLSA0101", "-%s:00-cs35l41-hda.%d", 2); } -static void cs35l56_fixup_i2c_two(struct hda_codec *cdc, const struct hda_fixup *fix, int action) -{ - comp_generic_fixup(cdc, action, "i2c", "CSC3556", "-%s:00-cs35l56-hda.%d", 2); -} - -static void cs35l56_fixup_i2c_four(struct hda_codec *cdc, const struct hda_fixup *fix, int action) -{ - comp_generic_fixup(cdc, action, "i2c", "CSC3556", "-%s:00-cs35l56-hda.%d", 4); -} - -static void cs35l56_fixup_spi_two(struct hda_codec *cdc, const struct hda_fixup *fix, int action) -{ - comp_generic_fixup(cdc, action, "spi", "CSC3556", "-%s:00-cs35l56-hda.%d", 2); -} - -static void cs35l56_fixup_spi_four(struct hda_codec *cdc, const struct hda_fixup *fix, int action) -{ - comp_generic_fixup(cdc, action, "spi", "CSC3556", "-%s:00-cs35l56-hda.%d", 4); -} - static void alc285_fixup_asus_ga403u(struct hda_codec *cdc, const struct hda_fixup *fix, int action) { /* @@ -6915,7 +6977,7 @@ static void alc285_fixup_asus_ga403u(struct hda_codec *cdc, const struct hda_fix * different codecs and the newer GA403U has a ALC285. */ if (cdc->core.vendor_id == 0x10ec0285) - cs35l56_fixup_i2c_two(cdc, fix, action); + cs35lxx_autodet_fixup(cdc, fix, action); else alc_fixup_inv_dmic(cdc, fix, action); } @@ -7410,6 +7472,7 @@ enum { ALC285_FIXUP_THINKPAD_X1_GEN7, ALC285_FIXUP_THINKPAD_HEADSET_JACK, ALC294_FIXUP_ASUS_ALLY, + ALC294_FIXUP_ASUS_ALLY_X, ALC294_FIXUP_ASUS_ALLY_PINS, ALC294_FIXUP_ASUS_ALLY_VERBS, ALC294_FIXUP_ASUS_ALLY_SPEAKER, @@ -7516,9 +7579,6 @@ enum { ALC256_FIXUP_ACER_SFG16_MICMUTE_LED, ALC256_FIXUP_HEADPHONE_AMP_VOL, ALC245_FIXUP_HP_SPECTRE_X360_EU0XXX, - ALC285_FIXUP_CS35L56_SPI_2, - ALC285_FIXUP_CS35L56_I2C_2, - ALC285_FIXUP_CS35L56_I2C_4, ALC285_FIXUP_ASUS_GA403U, ALC285_FIXUP_ASUS_GA403U_HEADSET_MIC, ALC285_FIXUP_ASUS_GA403U_I2C_SPEAKER2_TO_DAC1, @@ -7528,6 +7588,7 @@ enum { ALC256_FIXUP_CHROME_BOOK, ALC287_FIXUP_LENOVO_14ARP8_LEGION_IAH7, ALC287_FIXUP_LENOVO_SSID_17AA3820, + ALCXXX_FIXUP_CS35LXX, }; /* A special fixup for Lenovo C940 and Yoga Duet 7; @@ -8877,6 +8938,12 @@ static const struct hda_fixup alc269_fixups[] = { .chained = true, .chain_id = ALC294_FIXUP_ASUS_ALLY_PINS }, + [ALC294_FIXUP_ASUS_ALLY_X] = { + .type = HDA_FIXUP_FUNC, + .v.func = tas2781_fixup_i2c, + .chained = true, + .chain_id = ALC294_FIXUP_ASUS_ALLY_PINS + }, [ALC294_FIXUP_ASUS_ALLY_PINS] = { .type = HDA_FIXUP_PINS, .v.pins = (const struct hda_pintbl[]) { @@ -9777,7 +9844,7 @@ static const struct hda_fixup alc269_fixups[] = { }, [ALC245_FIXUP_CS35L56_SPI_4_HP_GPIO_LED] = { .type = HDA_FIXUP_FUNC, - .v.func = cs35l56_fixup_spi_four, + .v.func = cs35lxx_autodet_fixup, .chained = true, .chain_id = ALC285_FIXUP_HP_GPIO_LED, }, @@ -9793,18 +9860,6 @@ static const struct hda_fixup alc269_fixups[] = { .type = HDA_FIXUP_FUNC, .v.func = alc245_fixup_hp_spectre_x360_eu0xxx, }, - [ALC285_FIXUP_CS35L56_SPI_2] = { - .type = HDA_FIXUP_FUNC, - .v.func = cs35l56_fixup_spi_two, - }, - [ALC285_FIXUP_CS35L56_I2C_2] = { - .type = HDA_FIXUP_FUNC, - .v.func = cs35l56_fixup_i2c_two, - }, - [ALC285_FIXUP_CS35L56_I2C_4] = { - .type = HDA_FIXUP_FUNC, - .v.func = cs35l56_fixup_i2c_four, - }, [ALC285_FIXUP_ASUS_GA403U] = { .type = HDA_FIXUP_FUNC, .v.func = alc285_fixup_asus_ga403u, @@ -9833,7 +9888,7 @@ static const struct hda_fixup alc269_fixups[] = { { } }, .chained = true, - .chain_id = ALC285_FIXUP_CS35L56_SPI_2 + .chain_id = ALCXXX_FIXUP_CS35LXX }, [ALC285_FIXUP_ASUS_GA403U_I2C_SPEAKER2_TO_DAC1] = { .type = HDA_FIXUP_FUNC, @@ -9857,6 +9912,10 @@ static const struct hda_fixup alc269_fixups[] = { .type = HDA_FIXUP_FUNC, .v.func = alc287_fixup_lenovo_ssid_17aa3820, }, + [ALCXXX_FIXUP_CS35LXX] = { + .type = HDA_FIXUP_FUNC, + .v.func = cs35lxx_autodet_fixup, + }, }; static const struct snd_pci_quirk alc269_fixup_tbl[] = { @@ -10228,6 +10287,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x103c, 0x8c15, "HP Spectre x360 2-in-1 Laptop 14-eu0xxx", ALC245_FIXUP_HP_SPECTRE_X360_EU0XXX), SND_PCI_QUIRK(0x103c, 0x8c16, "HP Spectre 16", ALC287_FIXUP_CS35L41_I2C_2), SND_PCI_QUIRK(0x103c, 0x8c17, "HP Spectre 16", ALC287_FIXUP_CS35L41_I2C_2), + SND_PCI_QUIRK(0x103c, 0x8c21, "HP Pavilion Plus Laptop 14-ey0XXX", ALC245_FIXUP_HP_X360_MUTE_LEDS), SND_PCI_QUIRK(0x103c, 0x8c46, "HP EliteBook 830 G11", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED), SND_PCI_QUIRK(0x103c, 0x8c47, "HP EliteBook 840 G11", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED), SND_PCI_QUIRK(0x103c, 0x8c48, "HP EliteBook 860 G11", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED), @@ -10271,6 +10331,17 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x103c, 0x8cdf, "HP SnowWhite", ALC287_FIXUP_CS35L41_I2C_2_HP_GPIO_LED), SND_PCI_QUIRK(0x103c, 0x8ce0, "HP SnowWhite", ALC287_FIXUP_CS35L41_I2C_2_HP_GPIO_LED), SND_PCI_QUIRK(0x103c, 0x8cf5, "HP ZBook Studio 16", ALC245_FIXUP_CS35L41_SPI_4_HP_GPIO_LED), + SND_PCI_QUIRK(0x103c, 0x8d01, "HP ZBook Power 14 G12", ALCXXX_FIXUP_CS35LXX), + SND_PCI_QUIRK(0x103c, 0x8d08, "HP EliteBook 1045 14 G12", ALCXXX_FIXUP_CS35LXX), + SND_PCI_QUIRK(0x103c, 0x8d85, "HP EliteBook 1040 14 G12", ALCXXX_FIXUP_CS35LXX), + SND_PCI_QUIRK(0x103c, 0x8d86, "HP Elite x360 1040 14 G12", ALCXXX_FIXUP_CS35LXX), + SND_PCI_QUIRK(0x103c, 0x8d8c, "HP EliteBook 830 13 G12", ALCXXX_FIXUP_CS35LXX), + SND_PCI_QUIRK(0x103c, 0x8d8d, "HP Elite x360 830 13 G12", ALCXXX_FIXUP_CS35LXX), + SND_PCI_QUIRK(0x103c, 0x8d8e, "HP EliteBook 840 14 G12", ALCXXX_FIXUP_CS35LXX), + SND_PCI_QUIRK(0x103c, 0x8d8f, "HP EliteBook 840 14 G12", ALCXXX_FIXUP_CS35LXX), + SND_PCI_QUIRK(0x103c, 0x8d90, "HP EliteBook 860 16 G12", ALCXXX_FIXUP_CS35LXX), + SND_PCI_QUIRK(0x103c, 0x8d91, "HP ZBook Firefly 14 G12", ALCXXX_FIXUP_CS35LXX), + SND_PCI_QUIRK(0x103c, 0x8d92, "HP ZBook Firefly 16 G12", ALCXXX_FIXUP_CS35LXX), SND_PCI_QUIRK(0x1043, 0x103e, "ASUS X540SA", ALC256_FIXUP_ASUS_MIC), SND_PCI_QUIRK(0x1043, 0x103f, "ASUS TX300", ALC282_FIXUP_ASUS_TX300), SND_PCI_QUIRK(0x1043, 0x106d, "Asus K53BE", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), @@ -10313,6 +10384,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1043, 0x1740, "ASUS UX430UA", ALC295_FIXUP_ASUS_DACS), SND_PCI_QUIRK(0x1043, 0x17d1, "ASUS UX431FL", ALC294_FIXUP_ASUS_DUAL_SPK), SND_PCI_QUIRK(0x1043, 0x17f3, "ROG Ally NR2301L/X", ALC294_FIXUP_ASUS_ALLY), + SND_PCI_QUIRK(0x1043, 0x1eb3, "ROG Ally X RC72LA", ALC294_FIXUP_ASUS_ALLY_X), SND_PCI_QUIRK(0x1043, 0x1863, "ASUS UX6404VI/VV", ALC245_FIXUP_CS35L41_SPI_2), SND_PCI_QUIRK(0x1043, 0x1881, "ASUS Zephyrus S/M", ALC294_FIXUP_ASUS_GX502_PINS), SND_PCI_QUIRK(0x1043, 0x18b1, "Asus MJ401TA", ALC256_FIXUP_ASUS_HEADSET_MIC), @@ -10349,14 +10421,14 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1043, 0x1d42, "ASUS Zephyrus G14 2022", ALC289_FIXUP_ASUS_GA401), SND_PCI_QUIRK(0x1043, 0x1d4e, "ASUS TM420", ALC256_FIXUP_ASUS_HPE), SND_PCI_QUIRK(0x1043, 0x1da2, "ASUS UP6502ZA/ZD", ALC245_FIXUP_CS35L41_SPI_2), - SND_PCI_QUIRK(0x1043, 0x1df3, "ASUS UM5606", ALC285_FIXUP_CS35L56_I2C_4), + SND_PCI_QUIRK(0x1043, 0x1df3, "ASUS UM5606", ALCXXX_FIXUP_CS35LXX), SND_PCI_QUIRK(0x1043, 0x1e02, "ASUS UX3402ZA", ALC245_FIXUP_CS35L41_SPI_2), SND_PCI_QUIRK(0x1043, 0x1e11, "ASUS Zephyrus G15", ALC289_FIXUP_ASUS_GA502), SND_PCI_QUIRK(0x1043, 0x1e12, "ASUS UM3402", ALC287_FIXUP_CS35L41_I2C_2), SND_PCI_QUIRK(0x1043, 0x1e51, "ASUS Zephyrus M15", ALC294_FIXUP_ASUS_GU502_PINS), SND_PCI_QUIRK(0x1043, 0x1e5e, "ASUS ROG Strix G513", ALC294_FIXUP_ASUS_G513_PINS), - SND_PCI_QUIRK(0x1043, 0x1e63, "ASUS H7606W", ALC285_FIXUP_CS35L56_I2C_2), - SND_PCI_QUIRK(0x1043, 0x1e83, "ASUS GA605W", ALC285_FIXUP_CS35L56_I2C_2), + SND_PCI_QUIRK(0x1043, 0x1e63, "ASUS H7606W", ALCXXX_FIXUP_CS35LXX), + SND_PCI_QUIRK(0x1043, 0x1e83, "ASUS GA605W", ALCXXX_FIXUP_CS35LXX), SND_PCI_QUIRK(0x1043, 0x1e8e, "ASUS Zephyrus G15", ALC289_FIXUP_ASUS_GA401), SND_PCI_QUIRK(0x1043, 0x1ed3, "ASUS HN7306W", ALC287_FIXUP_CS35L41_I2C_2), SND_PCI_QUIRK(0x1043, 0x1ee2, "ASUS UM6702RA/RC", ALC287_FIXUP_CS35L41_I2C_2), @@ -10678,6 +10750,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x8086, 0x3038, "Intel NUC 13", ALC295_FIXUP_CHROME_BOOK), SND_PCI_QUIRK(0xf111, 0x0001, "Framework Laptop", ALC295_FIXUP_FRAMEWORK_LAPTOP_MIC_NO_PRESENCE), SND_PCI_QUIRK(0xf111, 0x0006, "Framework Laptop", ALC295_FIXUP_FRAMEWORK_LAPTOP_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0xf111, 0x0009, "Framework Laptop", ALC295_FIXUP_FRAMEWORK_LAPTOP_MIC_NO_PRESENCE), #if 0 /* Below is a quirk table taken from the old code. diff --git a/sound/pci/hda/tas2781_hda_i2c.c b/sound/pci/hda/tas2781_hda_i2c.c index 49bd7097d8928a..f58f434e7110ee 100644 --- a/sound/pci/hda/tas2781_hda_i2c.c +++ b/sound/pci/hda/tas2781_hda_i2c.c @@ -2,10 +2,12 @@ // // TAS2781 HDA I2C driver // -// Copyright 2023 Texas Instruments, Inc. +// Copyright 2023 - 2024 Texas Instruments, Inc. // // Author: Shenghao Ding +// Current maintainer: Baojun Xu +#include #include #include #include @@ -519,20 +521,22 @@ static void tas2781_apply_calib(struct tasdevice_priv *tas_priv) static const unsigned char rgno_array[CALIB_MAX] = { 0x74, 0x0c, 0x14, 0x70, 0x7c, }; - unsigned char *data; + int offset = 0; int i, j, rc; + __be32 data; for (i = 0; i < tas_priv->ndev; i++) { - data = tas_priv->cali_data.data + - i * TASDEVICE_SPEAKER_CALIBRATION_SIZE; for (j = 0; j < CALIB_MAX; j++) { + data = cpu_to_be32( + *(uint32_t *)&tas_priv->cali_data.data[offset]); rc = tasdevice_dev_bulk_write(tas_priv, i, TASDEVICE_REG(0, page_array[j], rgno_array[j]), - &(data[4 * j]), 4); + (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; } } } @@ -814,7 +818,7 @@ static int tas2781_hda_i2c_probe(struct i2c_client *clt) } else return -ENODEV; - tas_hda->priv->irq_info.irq = clt->irq; + tas_hda->priv->irq = clt->irq; ret = tas2781_read_acpi(tas_hda->priv, device_name); if (ret) return dev_err_probe(tas_hda->dev, ret, diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index dae3e15ba534de..e4bb99f71c2c9e 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c @@ -703,7 +703,6 @@ static inline void snd_intel8x0_update(struct intel8x0 *chip, struct ichdev *ich if (!(status & ICH_BCIS)) { step = 0; } else if (civ == ichdev->civ) { - // snd_printd("civ same %d\n", civ); step = 1; ichdev->civ++; ichdev->civ &= ICH_REG_LVI_MASK; @@ -711,8 +710,6 @@ static inline void snd_intel8x0_update(struct intel8x0 *chip, struct ichdev *ich step = civ - ichdev->civ; if (step < 0) step += ICH_REG_LVI_MASK + 1; - // if (step != 1) - // snd_printd("step = %d, %d -> %d\n", step, ichdev->civ, civ); ichdev->civ = civ; } diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c index 3d6f5b3cc73e17..38f8de51d6415a 100644 --- a/sound/pci/intel8x0m.c +++ b/sound/pci/intel8x0m.c @@ -423,7 +423,6 @@ static inline void snd_intel8x0m_update(struct intel8x0m *chip, struct ichdev *i civ = igetbyte(chip, port + ICH_REG_OFF_CIV); if (civ == ichdev->civ) { - // snd_printd("civ same %d\n", civ); step = 1; ichdev->civ++; ichdev->civ &= ICH_REG_LVI_MASK; @@ -431,8 +430,6 @@ static inline void snd_intel8x0m_update(struct intel8x0m *chip, struct ichdev *i step = civ - ichdev->civ; if (step < 0) step += ICH_REG_LVI_MASK + 1; - // if (step != 1) - // snd_printd("step = %d, %d -> %d\n", step, ichdev->civ, civ); ichdev->civ = civ; } diff --git a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c index 5c2cac201a281f..e62fb1ad6d77c5 100644 --- a/sound/pci/korg1212/korg1212.c +++ b/sound/pci/korg1212/korg1212.c @@ -28,14 +28,14 @@ // ---------------------------------------------------------------------------- #define K1212_DEBUG_LEVEL 0 #if K1212_DEBUG_LEVEL > 0 -#define K1212_DEBUG_PRINTK(fmt,args...) printk(KERN_DEBUG fmt,##args) +#define K1212_DEBUG_PRINTK(fmt, args...) pr_debug(fmt, ##args) #else -#define K1212_DEBUG_PRINTK(fmt,...) do { } while (0) +#define K1212_DEBUG_PRINTK(fmt, ...) do { } while (0) #endif #if K1212_DEBUG_LEVEL > 1 -#define K1212_DEBUG_PRINTK_VERBOSE(fmt,args...) printk(KERN_DEBUG fmt,##args) +#define K1212_DEBUG_PRINTK_VERBOSE(fmt, args...) pr_debug(fmt, ##args) #else -#define K1212_DEBUG_PRINTK_VERBOSE(fmt,...) +#define K1212_DEBUG_PRINTK_VERBOSE(fmt, ...) #endif // ---------------------------------------------------------------------------- @@ -602,7 +602,7 @@ static void snd_korg1212_timer_func(struct timer_list *t) /* reprogram timer */ mod_timer(&korg1212->timer, jiffies + 1); } else { - snd_printd("korg1212_timer_func timeout\n"); + dev_dbg(korg1212->card->dev, "korg1212_timer_func timeout\n"); korg1212->sharedBufferPtr->cardCommand = 0; korg1212->dsp_stop_is_processed = 1; wake_up(&korg1212->wait); @@ -1131,7 +1131,7 @@ static irqreturn_t snd_korg1212_interrupt(int irq, void *dev_id) K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: IRQ DMAE count - %ld, %x, [%s].\n", korg1212->irqcount, doorbellValue, stateName[korg1212->cardState]); - snd_printk(KERN_ERR "korg1212: DMA Error\n"); + dev_err(korg1212->card->dev, "korg1212: DMA Error\n"); korg1212->errorcnt++; korg1212->totalerrorcnt++; korg1212->sharedBufferPtr->cardCommand = 0; @@ -1272,8 +1272,8 @@ static int snd_korg1212_silence(struct snd_korg1212 *korg1212, int pos, int coun #if K1212_DEBUG_LEVEL > 0 if ( (void *) dst < (void *) korg1212->playDataBufsPtr || (void *) dst > (void *) korg1212->playDataBufsPtr[8].bufferData ) { - printk(KERN_DEBUG "K1212_DEBUG: snd_korg1212_silence KERNEL EFAULT dst=%p iter=%d\n", - dst, i); + pr_debug("K1212_DEBUG: %s KERNEL EFAULT dst=%p iter=%d\n", + __func__, dst, i); return -EFAULT; } #endif @@ -1305,7 +1305,8 @@ static int snd_korg1212_copy_to(struct snd_pcm_substream *substream, #if K1212_DEBUG_LEVEL > 0 if ( (void *) src < (void *) korg1212->recordDataBufsPtr || (void *) src > (void *) korg1212->recordDataBufsPtr[8].bufferData ) { - printk(KERN_DEBUG "K1212_DEBUG: snd_korg1212_copy_to KERNEL EFAULT, src=%p dst=%p iter=%d\n", src, dst->kvec.iov_base, i); + pr_debug("K1212_DEBUG: %s KERNEL EFAULT, src=%p dst=%p iter=%d\n", + __func__, src, dst->kvec.iov_base, i); return -EFAULT; } #endif @@ -1330,8 +1331,8 @@ static int snd_korg1212_copy_from(struct snd_pcm_substream *substream, size = korg1212->channels * 2; dst = korg1212->playDataBufsPtr[0].bufferData + pos; - K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: snd_korg1212_copy_from pos=%d size=%d count=%d\n", - pos, size, count); + K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: %s pos=%d size=%d count=%d\n", + __func__, pos, size, count); if (snd_BUG_ON(pos + count > K1212_MAX_SAMPLES)) return -EINVAL; @@ -1340,7 +1341,8 @@ static int snd_korg1212_copy_from(struct snd_pcm_substream *substream, #if K1212_DEBUG_LEVEL > 0 if ( (void *) dst < (void *) korg1212->playDataBufsPtr || (void *) dst > (void *) korg1212->playDataBufsPtr[8].bufferData ) { - printk(KERN_DEBUG "K1212_DEBUG: snd_korg1212_copy_from KERNEL EFAULT, src=%p dst=%p iter=%d\n", src->kvec.iov_base, dst, i); + pr_debug("K1212_DEBUG: %s KERNEL EFAULT, src=%p dst=%p iter=%d\n", + __func__, src->kvec.iov_base, dst, i); return -EFAULT; } #endif @@ -2135,7 +2137,7 @@ static int snd_korg1212_create(struct snd_card *card, struct pci_dev *pci) KBUILD_MODNAME, korg1212); if (err) { - snd_printk(KERN_ERR "korg1212: unable to grab IRQ %d\n", pci->irq); + dev_err(&pci->dev, "korg1212: unable to grab IRQ %d\n", pci->irq); return -EBUSY; } @@ -2232,7 +2234,7 @@ static int snd_korg1212_create(struct snd_card *card, struct pci_dev *pci) err = request_firmware(&dsp_code, "korg/k1212.dsp", &pci->dev); if (err < 0) { - snd_printk(KERN_ERR "firmware not available\n"); + dev_err(&pci->dev, "firmware not available\n"); return err; } diff --git a/sound/pci/lx6464es/lx_core.c b/sound/pci/lx6464es/lx_core.c index b5b0d43bb8dcdd..9d95ecb299aed8 100644 --- a/sound/pci/lx6464es/lx_core.c +++ b/sound/pci/lx6464es/lx_core.c @@ -231,14 +231,14 @@ static void lx_message_dump(struct lx_rmh *rmh) u8 idx = rmh->cmd_idx; int i; - snd_printk(LXRMH "command %s\n", dsp_commands[idx].dcOpName); + pr_debug(LXRMH "command %s\n", dsp_commands[idx].dcOpName); for (i = 0; i != rmh->cmd_len; ++i) - snd_printk(LXRMH "\tcmd[%d] %08x\n", i, rmh->cmd[i]); + pr_debug(LXRMH "\tcmd[%d] %08x\n", i, rmh->cmd[i]); for (i = 0; i != rmh->stat_len; ++i) - snd_printk(LXRMH "\tstat[%d]: %08x\n", i, rmh->stat[i]); - snd_printk("\n"); + pr_debug(LXRMH "\tstat[%d]: %08x\n", i, rmh->stat[i]); + pr_debug("\n"); } #else static inline void lx_message_dump(struct lx_rmh *rmh) diff --git a/sound/pci/lx6464es/lx_core.h b/sound/pci/lx6464es/lx_core.h index 296013c910b7bb..c1113439f7c9dd 100644 --- a/sound/pci/lx6464es/lx_core.h +++ b/sound/pci/lx6464es/lx_core.h @@ -129,21 +129,18 @@ int lx_stream_set_state(struct lx6464es *chip, u32 pipe, static inline int lx_stream_start(struct lx6464es *chip, u32 pipe, int is_capture) { - snd_printdd("->lx_stream_start\n"); return lx_stream_set_state(chip, pipe, is_capture, SSTATE_RUN); } static inline int lx_stream_pause(struct lx6464es *chip, u32 pipe, int is_capture) { - snd_printdd("->lx_stream_pause\n"); return lx_stream_set_state(chip, pipe, is_capture, SSTATE_PAUSE); } static inline int lx_stream_stop(struct lx6464es *chip, u32 pipe, int is_capture) { - snd_printdd("->lx_stream_stop\n"); return lx_stream_set_state(chip, pipe, is_capture, SSTATE_STOP); } diff --git a/sound/pci/riptide/riptide.c b/sound/pci/riptide/riptide.c index 7e80686fb41a33..329816f37b76bd 100644 --- a/sound/pci/riptide/riptide.c +++ b/sound/pci/riptide/riptide.c @@ -380,6 +380,7 @@ struct riptideport { }; struct cmdif { + struct device *dev; struct riptideport *hwport; spinlock_t lock; unsigned int cmdcnt; /* cmd statistics */ @@ -727,7 +728,7 @@ static int loadfirmware(struct cmdif *cif, const unsigned char *img, } } } - snd_printdd("load firmware return %d\n", err); + dev_dbg(cif->dev, "load firmware return %d\n", err); return err; } @@ -740,7 +741,7 @@ alloclbuspath(struct cmdif *cif, unsigned char source, sink = *path & (~SPLIT_PATH); if (sink != E2SINK_MAX) { - snd_printdd("alloc path 0x%x->0x%x\n", source, sink); + dev_dbg(cif->dev, "alloc path 0x%x->0x%x\n", source, sink); SEND_PSEL(cif, source, sink); source = lbusin2out[sink][0]; type = lbusin2out[sink][1]; @@ -778,7 +779,7 @@ freelbuspath(struct cmdif *cif, unsigned char source, const unsigned char *path) sink = *path & (~SPLIT_PATH); if (sink != E2SINK_MAX) { - snd_printdd("free path 0x%x->0x%x\n", source, sink); + dev_dbg(cif->dev, "free path 0x%x->0x%x\n", source, sink); SEND_PCLR(cif, source, sink); source = lbusin2out[sink][0]; } @@ -811,8 +812,8 @@ static int writearm(struct cmdif *cif, u32 addr, u32 data, u32 mask) } else rptr.retlongs[0] &= ~mask; } - snd_printdd("send arm 0x%x 0x%x 0x%x return %d\n", addr, data, mask, - flag); + dev_dbg(cif->dev, "send arm 0x%x 0x%x 0x%x return %d\n", addr, data, mask, + flag); return flag; } @@ -832,14 +833,14 @@ static int sendcmd(struct cmdif *cif, u32 flags, u32 cmd, u32 parm, hwport = cif->hwport; if (cif->errcnt > MAX_ERROR_COUNT) { if (cif->is_reset) { - snd_printk(KERN_ERR - "Riptide: Too many failed cmds, reinitializing\n"); + dev_err(cif->dev, + "Riptide: Too many failed cmds, reinitializing\n"); if (riptide_reset(cif, NULL) == 0) { cif->errcnt = 0; return -EIO; } } - snd_printk(KERN_ERR "Riptide: Initialization failed.\n"); + dev_err(cif->dev, "Riptide: Initialization failed.\n"); return -EINVAL; } if (ret) { @@ -899,21 +900,21 @@ static int sendcmd(struct cmdif *cif, u32 flags, u32 cmd, u32 parm, if (time < cif->cmdtimemin) cif->cmdtimemin = time; if ((cif->cmdcnt) % 1000 == 0) - snd_printdd - ("send cmd %d time: %d mintime: %d maxtime %d err: %d\n", - cif->cmdcnt, cif->cmdtime, cif->cmdtimemin, - cif->cmdtimemax, cif->errcnt); + dev_dbg(cif->dev, + "send cmd %d time: %d mintime: %d maxtime %d err: %d\n", + cif->cmdcnt, cif->cmdtime, cif->cmdtimemin, + cif->cmdtimemax, cif->errcnt); return 0; errout: cif->errcnt++; spin_unlock_irqrestore(&cif->lock, irqflags); - snd_printdd - ("send cmd %d hw: 0x%x flag: 0x%x cmd: 0x%x parm: 0x%x ret: 0x%x 0x%x CMDE: %d DATF: %d failed %d\n", - cif->cmdcnt, (int)((void *)&(cmdport->stat) - (void *)hwport), - flags, cmd, parm, ret ? ret->retlongs[0] : 0, - ret ? ret->retlongs[1] : 0, IS_CMDE(cmdport), IS_DATF(cmdport), - err); + dev_dbg(cif->dev, + "send cmd %d hw: 0x%x flag: 0x%x cmd: 0x%x parm: 0x%x ret: 0x%x 0x%x CMDE: %d DATF: %d failed %d\n", + cif->cmdcnt, (int)((void *)&(cmdport->stat) - (void *)hwport), + flags, cmd, parm, ret ? ret->retlongs[0] : 0, + ret ? ret->retlongs[1] : 0, IS_CMDE(cmdport), IS_DATF(cmdport), + err); return err; } @@ -923,14 +924,14 @@ setmixer(struct cmdif *cif, short num, unsigned short rval, unsigned short lval) union cmdret rptr = CMDRET_ZERO; int i = 0; - snd_printdd("sent mixer %d: 0x%x 0x%x\n", num, rval, lval); + dev_dbg(cif->dev, "sent mixer %d: 0x%x 0x%x\n", num, rval, lval); do { SEND_SDGV(cif, num, num, rval, lval); SEND_RDGV(cif, num, num, &rptr); if (rptr.retwords[0] == lval && rptr.retwords[1] == rval) return 0; } while (i++ < MAX_WRITE_RETRY); - snd_printdd("sent mixer failed\n"); + dev_dbg(cif->dev, "sent mixer failed\n"); return -EIO; } @@ -961,7 +962,7 @@ getsourcesink(struct cmdif *cif, unsigned char source, unsigned char sink, return -EIO; *a = rptr.retbytes[0]; *b = rptr.retbytes[1]; - snd_printdd("getsourcesink 0x%x 0x%x\n", *a, *b); + dev_dbg(cif->dev, "%s 0x%x 0x%x\n", __func__, *a, *b); return 0; } @@ -988,11 +989,11 @@ getsamplerate(struct cmdif *cif, unsigned char *intdec, unsigned int *rate) } if (p[0]) { if (p[1] != p[0]) - snd_printdd("rates differ %d %d\n", p[0], p[1]); + dev_dbg(cif->dev, "rates differ %d %d\n", p[0], p[1]); *rate = (unsigned int)p[0]; } else *rate = (unsigned int)p[1]; - snd_printdd("getsampleformat %d %d %d\n", intdec[0], intdec[1], *rate); + dev_dbg(cif->dev, "getsampleformat %d %d %d\n", intdec[0], intdec[1], *rate); return 0; } @@ -1003,9 +1004,9 @@ setsampleformat(struct cmdif *cif, { unsigned char w, ch, sig, order; - snd_printdd - ("setsampleformat mixer: %d id: %d channels: %d format: %d\n", - mixer, id, channels, format); + dev_dbg(cif->dev, + "%s mixer: %d id: %d channels: %d format: %d\n", + __func__, mixer, id, channels, format); ch = channels == 1; w = snd_pcm_format_width(format) == 8; sig = snd_pcm_format_unsigned(format) != 0; @@ -1013,7 +1014,7 @@ setsampleformat(struct cmdif *cif, if (SEND_SETF(cif, mixer, w, ch, order, sig, id) && SEND_SETF(cif, mixer, w, ch, order, sig, id)) { - snd_printdd("setsampleformat failed\n"); + dev_dbg(cif->dev, "%s failed\n", __func__); return -EIO; } return 0; @@ -1026,8 +1027,8 @@ setsamplerate(struct cmdif *cif, unsigned char *intdec, unsigned int rate) union cmdret rptr = CMDRET_ZERO; int i; - snd_printdd("setsamplerate intdec: %d,%d rate: %d\n", intdec[0], - intdec[1], rate); + dev_dbg(cif->dev, "%s intdec: %d,%d rate: %d\n", __func__, + intdec[0], intdec[1], rate); D = 48000; M = ((rate == 48000) ? 47999 : rate) * 65536; N = M % D; @@ -1042,8 +1043,8 @@ setsamplerate(struct cmdif *cif, unsigned char *intdec, unsigned int rate) rptr.retwords[3] != N && i++ < MAX_WRITE_RETRY); if (i > MAX_WRITE_RETRY) { - snd_printdd("sent samplerate %d: %d failed\n", - *intdec, rate); + dev_dbg(cif->dev, "sent samplerate %d: %d failed\n", + *intdec, rate); return -EIO; } } @@ -1062,7 +1063,7 @@ getmixer(struct cmdif *cif, short num, unsigned short *rval, return -EIO; *rval = rptr.retwords[0]; *lval = rptr.retwords[1]; - snd_printdd("got mixer %d: 0x%x 0x%x\n", num, *rval, *lval); + dev_dbg(cif->dev, "got mixer %d: 0x%x 0x%x\n", num, *rval, *lval); return 0; } @@ -1105,8 +1106,8 @@ static irqreturn_t riptide_handleirq(int irq, void *dev_id) if ((flag & EOS_STATUS) && (data->state == ST_PLAY)) { data->state = ST_STOP; - snd_printk(KERN_ERR - "Riptide: DMA stopped unexpectedly\n"); + dev_err(cif->dev, + "Riptide: DMA stopped unexpectedly\n"); } c->dwStat_Ctl = cpu_to_le32(flag & @@ -1119,11 +1120,11 @@ static irqreturn_t riptide_handleirq(int irq, void *dev_id) period_bytes = frames_to_bytes(runtime, runtime->period_size); - snd_printdd - ("interrupt 0x%x after 0x%lx of 0x%lx frames in period\n", - READ_AUDIO_STATUS(cif->hwport), - bytes_to_frames(runtime, pos), - runtime->period_size); + dev_dbg(cif->dev, + "interrupt 0x%x after 0x%lx of 0x%lx frames in period\n", + READ_AUDIO_STATUS(cif->hwport), + bytes_to_frames(runtime, pos), + runtime->period_size); j = 0; if (pos >= period_bytes) { j++; @@ -1184,23 +1185,23 @@ static int try_to_load_firmware(struct cmdif *cif, struct snd_riptide *chip) break; } if (!timeout) { - snd_printk(KERN_ERR - "Riptide: device not ready, audio status: 0x%x " - "ready: %d gerr: %d\n", - READ_AUDIO_STATUS(cif->hwport), - IS_READY(cif->hwport), IS_GERR(cif->hwport)); + dev_err(cif->dev, + "Riptide: device not ready, audio status: 0x%x ready: %d gerr: %d\n", + READ_AUDIO_STATUS(cif->hwport), + IS_READY(cif->hwport), IS_GERR(cif->hwport)); return -EIO; } else { - snd_printdd - ("Riptide: audio status: 0x%x ready: %d gerr: %d\n", - READ_AUDIO_STATUS(cif->hwport), - IS_READY(cif->hwport), IS_GERR(cif->hwport)); + dev_dbg(cif->dev, + "Riptide: audio status: 0x%x ready: %d gerr: %d\n", + READ_AUDIO_STATUS(cif->hwport), + IS_READY(cif->hwport), IS_GERR(cif->hwport)); } SEND_GETV(cif, &firmware.ret); - snd_printdd("Firmware version: ASIC: %d CODEC %d AUXDSP %d PROG %d\n", - firmware.firmware.ASIC, firmware.firmware.CODEC, - firmware.firmware.AUXDSP, firmware.firmware.PROG); + dev_dbg(cif->dev, + "Firmware version: ASIC: %d CODEC %d AUXDSP %d PROG %d\n", + firmware.firmware.ASIC, firmware.firmware.CODEC, + firmware.firmware.AUXDSP, firmware.firmware.PROG); if (!chip) return 1; @@ -1211,20 +1212,20 @@ static int try_to_load_firmware(struct cmdif *cif, struct snd_riptide *chip) } - snd_printdd("Writing Firmware\n"); + dev_dbg(cif->dev, "Writing Firmware\n"); if (!chip->fw_entry) { err = request_firmware(&chip->fw_entry, "riptide.hex", &chip->pci->dev); if (err) { - snd_printk(KERN_ERR - "Riptide: Firmware not available %d\n", err); + dev_err(cif->dev, + "Riptide: Firmware not available %d\n", err); return -EIO; } } err = loadfirmware(cif, chip->fw_entry->data, chip->fw_entry->size); if (err) { - snd_printk(KERN_ERR - "Riptide: Could not load firmware %d\n", err); + dev_err(cif->dev, + "Riptide: Could not load firmware %d\n", err); return err; } @@ -1257,7 +1258,7 @@ static int riptide_reset(struct cmdif *cif, struct snd_riptide *chip) SEND_SACR(cif, 0, AC97_RESET); SEND_RACR(cif, AC97_RESET, &rptr); - snd_printdd("AC97: 0x%x 0x%x\n", rptr.retlongs[0], rptr.retlongs[1]); + dev_dbg(cif->dev, "AC97: 0x%x 0x%x\n", rptr.retlongs[0], rptr.retlongs[1]); SEND_PLST(cif, 0); SEND_SLST(cif, 0); @@ -1350,11 +1351,11 @@ static snd_pcm_uframes_t snd_riptide_pointer(struct snd_pcm_substream SEND_GPOS(cif, 0, data->id, &rptr); if (data->size && runtime->period_size) { - snd_printdd - ("pointer stream %d position 0x%x(0x%x in buffer) bytes 0x%lx(0x%lx in period) frames\n", - data->id, rptr.retlongs[1], rptr.retlongs[1] % data->size, - bytes_to_frames(runtime, rptr.retlongs[1]), - bytes_to_frames(runtime, + dev_dbg(cif->dev, + "pointer stream %d position 0x%x(0x%x in buffer) bytes 0x%lx(0x%lx in period) frames\n", + data->id, rptr.retlongs[1], rptr.retlongs[1] % data->size, + bytes_to_frames(runtime, rptr.retlongs[1]), + bytes_to_frames(runtime, rptr.retlongs[1]) % runtime->period_size); if (rptr.retlongs[1] > data->pointer) ret = @@ -1365,8 +1366,9 @@ static snd_pcm_uframes_t snd_riptide_pointer(struct snd_pcm_substream bytes_to_frames(runtime, data->pointer % data->size); } else { - snd_printdd("stream not started or strange parms (%d %ld)\n", - data->size, runtime->period_size); + dev_dbg(cif->dev, + "stream not started or strange parms (%d %ld)\n", + data->size, runtime->period_size); ret = bytes_to_frames(runtime, 0); } return ret; @@ -1410,7 +1412,7 @@ static int snd_riptide_trigger(struct snd_pcm_substream *substream, int cmd) udelay(1); } while (i != rptr.retlongs[1] && j++ < MAX_WRITE_RETRY); if (j > MAX_WRITE_RETRY) - snd_printk(KERN_ERR "Riptide: Could not stop stream!"); + dev_err(cif->dev, "Riptide: Could not stop stream!"); break; case SNDRV_PCM_TRIGGER_PAUSE_PUSH: if (!(data->state & ST_PAUSE)) { @@ -1448,8 +1450,8 @@ static int snd_riptide_prepare(struct snd_pcm_substream *substream) if (snd_BUG_ON(!cif || !data)) return -EINVAL; - snd_printdd("prepare id %d ch: %d f:0x%x r:%d\n", data->id, - runtime->channels, runtime->format, runtime->rate); + dev_dbg(cif->dev, "prepare id %d ch: %d f:0x%x r:%d\n", data->id, + runtime->channels, runtime->format, runtime->rate); spin_lock_irq(&chip->lock); channels = runtime->channels; @@ -1469,8 +1471,7 @@ static int snd_riptide_prepare(struct snd_pcm_substream *substream) lbuspath = data->paths.stereo; break; } - snd_printdd("use sgdlist at 0x%p\n", - data->sgdlist.area); + dev_dbg(cif->dev, "use sgdlist at 0x%p\n", data->sgdlist.area); if (data->sgdlist.area) { unsigned int i, j, size, pages, f, pt, period; struct sgd *c, *p = NULL; @@ -1483,9 +1484,9 @@ static int snd_riptide_prepare(struct snd_pcm_substream *substream) pages = DIV_ROUND_UP(size, f); data->size = size; data->pages = pages; - snd_printdd - ("create sgd size: 0x%x pages %d of size 0x%x for period 0x%x\n", - size, pages, f, period); + dev_dbg(cif->dev, + "create sgd size: 0x%x pages %d of size 0x%x for period 0x%x\n", + size, pages, f, period); pt = 0; j = 0; for (i = 0; i < pages; i++) { @@ -1543,17 +1544,18 @@ snd_riptide_hw_params(struct snd_pcm_substream *substream, struct snd_dma_buffer *sgdlist = &data->sgdlist; int err; - snd_printdd("hw params id %d (sgdlist: 0x%p 0x%lx %d)\n", data->id, - sgdlist->area, (unsigned long)sgdlist->addr, - (int)sgdlist->bytes); + dev_dbg(chip->card->dev, "hw params id %d (sgdlist: 0x%p 0x%lx %d)\n", + data->id, sgdlist->area, (unsigned long)sgdlist->addr, + (int)sgdlist->bytes); if (sgdlist->area) snd_dma_free_pages(sgdlist); err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &chip->pci->dev, sizeof(struct sgd) * (DESC_MAX_MASK + 1), sgdlist); if (err < 0) { - snd_printk(KERN_ERR "Riptide: failed to alloc %d dma bytes\n", - (int)sizeof(struct sgd) * (DESC_MAX_MASK + 1)); + dev_err(chip->card->dev, + "Riptide: failed to alloc %d dma bytes\n", + (int)sizeof(struct sgd) * (DESC_MAX_MASK + 1)); return err; } data->sgdbuf = (struct sgd *)sgdlist->area; @@ -1729,13 +1731,13 @@ snd_riptide_codec_write(struct snd_ac97 *ac97, unsigned short reg, if (snd_BUG_ON(!cif)) return; - snd_printdd("Write AC97 reg 0x%x 0x%x\n", reg, val); + dev_dbg(cif->dev, "Write AC97 reg 0x%x 0x%x\n", reg, val); do { SEND_SACR(cif, val, reg); SEND_RACR(cif, reg, &rptr); } while (rptr.retwords[1] != val && i++ < MAX_WRITE_RETRY); if (i > MAX_WRITE_RETRY) - snd_printdd("Write AC97 reg failed\n"); + dev_dbg(cif->dev, "Write AC97 reg failed\n"); } static unsigned short snd_riptide_codec_read(struct snd_ac97 *ac97, @@ -1750,7 +1752,7 @@ static unsigned short snd_riptide_codec_read(struct snd_ac97 *ac97, if (SEND_RACR(cif, reg, &rptr) != 0) SEND_RACR(cif, reg, &rptr); - snd_printdd("Read AC97 reg 0x%x got 0x%x\n", reg, rptr.retwords[1]); + dev_dbg(cif->dev, "Read AC97 reg 0x%x got 0x%x\n", reg, rptr.retwords[1]); return rptr.retwords[1]; } @@ -1768,6 +1770,7 @@ static int snd_riptide_initialize(struct snd_riptide *chip) cif = kzalloc(sizeof(struct cmdif), GFP_KERNEL); if (!cif) return -ENOMEM; + cif->dev = chip->card->dev; cif->hwport = (struct riptideport *)chip->port; spin_lock_init(&cif->lock); chip->cif = cif; @@ -1781,11 +1784,11 @@ static int snd_riptide_initialize(struct snd_riptide *chip) case 0x4310: case 0x4320: case 0x4330: - snd_printdd("Modem enable?\n"); + dev_dbg(cif->dev, "Modem enable?\n"); SEND_SETDPLL(cif); break; } - snd_printdd("Enabling MPU IRQs\n"); + dev_dbg(cif->dev, "Enabling MPU IRQs\n"); if (chip->rmidi) SET_EMPUIRQ(cif->hwport); return err; @@ -1838,8 +1841,8 @@ snd_riptide_create(struct snd_card *card, struct pci_dev *pci) snd_riptide_interrupt, riptide_handleirq, IRQF_SHARED, KBUILD_MODNAME, chip)) { - snd_printk(KERN_ERR "Riptide: unable to grab IRQ %d\n", - pci->irq); + dev_err(&pci->dev, "Riptide: unable to grab IRQ %d\n", + pci->irq); return -EBUSY; } chip->irq = pci->irq; @@ -1987,9 +1990,9 @@ snd_riptide_joystick_probe(struct pci_dev *pci, const struct pci_device_id *id) goto inc_dev; } if (!request_region(joystick_port[dev], 8, "Riptide gameport")) { - snd_printk(KERN_WARNING - "Riptide: cannot grab gameport 0x%x\n", - joystick_port[dev]); + dev_err(&pci->dev, + "Riptide: cannot grab gameport 0x%x\n", + joystick_port[dev]); gameport_free_port(gameport); ret = -EBUSY; goto inc_dev; @@ -2064,9 +2067,9 @@ __snd_card_riptide_probe(struct pci_dev *pci, const struct pci_device_id *pci_id val, MPU401_INFO_IRQ_HOOK, -1, &chip->rmidi); if (err < 0) - snd_printk(KERN_WARNING - "Riptide: Can't Allocate MPU at 0x%x\n", - val); + dev_warn(&pci->dev, + "Riptide: Can't Allocate MPU at 0x%x\n", + val); else chip->mpuaddr = val; } @@ -2076,15 +2079,15 @@ __snd_card_riptide_probe(struct pci_dev *pci, const struct pci_device_id *pci_id err = snd_opl3_create(card, val, val + 2, OPL3_HW_RIPTIDE, 0, &chip->opl3); if (err < 0) - snd_printk(KERN_WARNING - "Riptide: Can't Allocate OPL3 at 0x%x\n", - val); + dev_warn(&pci->dev, + "Riptide: Can't Allocate OPL3 at 0x%x\n", + val); else { chip->opladdr = val; err = snd_opl3_hwdep_new(chip->opl3, 0, 1, NULL); if (err < 0) - snd_printk(KERN_WARNING - "Riptide: Can't Allocate OPL3-HWDEP\n"); + dev_warn(&pci->dev, + "Riptide: Can't Allocate OPL3-HWDEP\n"); } } #ifdef SUPPORT_JOYSTICK diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c index e7d1b43471a291..713ca262a0e979 100644 --- a/sound/pci/rme9652/hdsp.c +++ b/sound/pci/rme9652/hdsp.c @@ -1298,8 +1298,10 @@ static int snd_hdsp_midi_output_possible (struct hdsp *hdsp, int id) static void snd_hdsp_flush_midi_input (struct hdsp *hdsp, int id) { - while (snd_hdsp_midi_input_available (hdsp, id)) - snd_hdsp_midi_read_byte (hdsp, id); + int count = 256; + + while (snd_hdsp_midi_input_available(hdsp, id) && --count) + snd_hdsp_midi_read_byte(hdsp, id); } static int snd_hdsp_midi_output_write (struct hdsp_midi *hmidi) diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index 56d335f0e19609..c3f930a8f78d04 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c @@ -1838,8 +1838,10 @@ static inline int snd_hdspm_midi_output_possible (struct hdspm *hdspm, int id) static void snd_hdspm_flush_midi_input(struct hdspm *hdspm, int id) { - while (snd_hdspm_midi_input_available (hdspm, id)) - snd_hdspm_midi_read_byte (hdspm, id); + int count = 256; + + while (snd_hdspm_midi_input_available(hdspm, id) && --count) + snd_hdspm_midi_read_byte(hdspm, id); } static int snd_hdspm_midi_output_write (struct hdspm_midi *hmidi) diff --git a/sound/pci/trident/trident.h b/sound/pci/trident/trident.h index 9768a7fc2349d1..ed2d4eecc704af 100644 --- a/sound/pci/trident/trident.h +++ b/sound/pci/trident/trident.h @@ -406,7 +406,6 @@ int snd_trident_create_gameport(struct snd_trident *trident); int snd_trident_pcm(struct snd_trident *trident, int device); int snd_trident_foldback_pcm(struct snd_trident *trident, int device); int snd_trident_spdif_pcm(struct snd_trident *trident, int device); -int snd_trident_attach_synthesizer(struct snd_trident * trident); struct snd_trident_voice *snd_trident_alloc_voice(struct snd_trident * trident, int type, int client, int port); void snd_trident_free_voice(struct snd_trident * trident, struct snd_trident_voice *voice); @@ -419,9 +418,5 @@ extern const struct dev_pm_ops snd_trident_pm; struct snd_util_memblk *snd_trident_alloc_pages(struct snd_trident *trident, struct snd_pcm_substream *substream); int snd_trident_free_pages(struct snd_trident *trident, struct snd_util_memblk *blk); -struct snd_util_memblk *snd_trident_synth_alloc(struct snd_trident *trident, unsigned int size); -int snd_trident_synth_free(struct snd_trident *trident, struct snd_util_memblk *blk); -int snd_trident_synth_copy_from_user(struct snd_trident *trident, struct snd_util_memblk *blk, - int offset, const char __user *data, int size); #endif /* __SOUND_TRIDENT_H */ diff --git a/sound/pci/trident/trident_memory.c b/sound/pci/trident/trident_memory.c index 05de2b9f4ed7c2..4a36f194c7f8d9 100644 --- a/sound/pci/trident/trident_memory.c +++ b/sound/pci/trident/trident_memory.c @@ -137,14 +137,14 @@ search_empty(struct snd_util_memhdr *hdr, int size) /* * check if the given pointer is valid for pages */ -static int is_valid_page(unsigned long ptr) +static int is_valid_page(struct snd_trident *trident, unsigned long ptr) { if (ptr & ~0x3fffffffUL) { - snd_printk(KERN_ERR "max memory size is 1GB!!\n"); + dev_err(trident->card->dev, "max memory size is 1GB!!\n"); return 0; } if (ptr & (SNDRV_TRIDENT_PAGE_SIZE-1)) { - snd_printk(KERN_ERR "page is not aligned\n"); + dev_err(trident->card->dev, "page is not aligned\n"); return 0; } return 1; @@ -184,7 +184,7 @@ snd_trident_alloc_sg_pages(struct snd_trident *trident, for (page = firstpg(blk); page <= lastpg(blk); page++, idx++) { unsigned long ofs = idx << PAGE_SHIFT; dma_addr_t addr = snd_pcm_sgbuf_get_addr(substream, ofs); - if (! is_valid_page(addr)) { + if (!is_valid_page(trident, addr)) { __snd_util_mem_free(hdr, blk); mutex_unlock(&hdr->block_mutex); return NULL; @@ -227,7 +227,7 @@ snd_trident_alloc_cont_pages(struct snd_trident *trident, addr = runtime->dma_addr; for (page = firstpg(blk); page <= lastpg(blk); page++, addr += SNDRV_TRIDENT_PAGE_SIZE) { - if (! is_valid_page(addr)) { + if (!is_valid_page(trident, addr)) { __snd_util_mem_free(hdr, blk); mutex_unlock(&hdr->block_mutex); return NULL; diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf.c b/sound/pcmcia/pdaudiocf/pdaudiocf.c index 8363ec08df5d96..49446074661468 100644 --- a/sound/pcmcia/pdaudiocf/pdaudiocf.c +++ b/sound/pcmcia/pdaudiocf/pdaudiocf.c @@ -85,14 +85,13 @@ static int snd_pdacf_probe(struct pcmcia_device *link) .dev_free = snd_pdacf_dev_free, }; - snd_printdd(KERN_DEBUG "pdacf_attach called\n"); /* find an empty slot from the card list */ for (i = 0; i < SNDRV_CARDS; i++) { if (! card_list[i]) break; } if (i >= SNDRV_CARDS) { - snd_printk(KERN_ERR "pdacf: too many cards found\n"); + dev_err(&link->dev, "pdacf: too many cards found\n"); return -EINVAL; } if (! enable[i]) @@ -102,7 +101,7 @@ static int snd_pdacf_probe(struct pcmcia_device *link) err = snd_card_new(&link->dev, index[i], id[i], THIS_MODULE, 0, &card); if (err < 0) { - snd_printk(KERN_ERR "pdacf: cannot create a card instance\n"); + dev_err(&link->dev, "pdacf: cannot create a card instance\n"); return err; } @@ -152,7 +151,7 @@ static int snd_pdacf_assign_resources(struct snd_pdacf *pdacf, int port, int irq int err; struct snd_card *card = pdacf->card; - snd_printdd(KERN_DEBUG "pdacf assign resources: port = 0x%x, irq = %d\n", port, irq); + dev_dbg(card->dev, "pdacf assign resources: port = 0x%x, irq = %d\n", port, irq); pdacf->port = port; pdacf->irq = irq; pdacf->chip_status |= PDAUDIOCF_STAT_IS_CONFIGURED; @@ -185,8 +184,6 @@ static void snd_pdacf_detach(struct pcmcia_device *link) { struct snd_pdacf *chip = link->priv; - snd_printdd(KERN_DEBUG "pdacf_detach called\n"); - if (chip->chip_status & PDAUDIOCF_STAT_IS_CONFIGURED) snd_pdacf_powerdown(chip); chip->chip_status |= PDAUDIOCF_STAT_IS_STALE; /* to be sure */ @@ -203,7 +200,6 @@ static int pdacf_config(struct pcmcia_device *link) struct snd_pdacf *pdacf = link->priv; int ret; - snd_printdd(KERN_DEBUG "pdacf_config called\n"); link->config_index = 0x5; link->config_flags |= CONF_ENABLE_IRQ | CONF_ENABLE_PULSE_IRQ; @@ -241,11 +237,8 @@ static int pdacf_suspend(struct pcmcia_device *link) { struct snd_pdacf *chip = link->priv; - snd_printdd(KERN_DEBUG "SUSPEND\n"); - if (chip) { - snd_printdd(KERN_DEBUG "snd_pdacf_suspend calling\n"); + if (chip) snd_pdacf_suspend(chip); - } return 0; } @@ -254,14 +247,10 @@ static int pdacf_resume(struct pcmcia_device *link) { struct snd_pdacf *chip = link->priv; - snd_printdd(KERN_DEBUG "RESUME\n"); if (pcmcia_dev_present(link)) { - if (chip) { - snd_printdd(KERN_DEBUG "calling snd_pdacf_resume\n"); + if (chip) snd_pdacf_resume(chip); - } } - snd_printdd(KERN_DEBUG "resume done!\n"); return 0; } diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf_core.c b/sound/pcmcia/pdaudiocf/pdaudiocf_core.c index 5537c0882aa55d..11aacc7e3f0b03 100644 --- a/sound/pcmcia/pdaudiocf/pdaudiocf_core.c +++ b/sound/pcmcia/pdaudiocf/pdaudiocf_core.c @@ -28,7 +28,7 @@ static unsigned char pdacf_ak4117_read(void *private_data, unsigned char reg) udelay(5); if (--timeout == 0) { spin_unlock_irqrestore(&chip->ak4117_lock, flags); - snd_printk(KERN_ERR "AK4117 ready timeout (read)\n"); + dev_err(chip->card->dev, "AK4117 ready timeout (read)\n"); return 0; } } @@ -38,7 +38,7 @@ static unsigned char pdacf_ak4117_read(void *private_data, unsigned char reg) udelay(5); if (--timeout == 0) { spin_unlock_irqrestore(&chip->ak4117_lock, flags); - snd_printk(KERN_ERR "AK4117 read timeout (read2)\n"); + dev_err(chip->card->dev, "AK4117 read timeout (read2)\n"); return 0; } } @@ -59,7 +59,7 @@ static void pdacf_ak4117_write(void *private_data, unsigned char reg, unsigned c udelay(5); if (--timeout == 0) { spin_unlock_irqrestore(&chip->ak4117_lock, flags); - snd_printk(KERN_ERR "AK4117 ready timeout (write)\n"); + dev_err(chip->card->dev, "AK4117 ready timeout (write)\n"); return; } } @@ -70,21 +70,21 @@ static void pdacf_ak4117_write(void *private_data, unsigned char reg, unsigned c #if 0 void pdacf_dump(struct snd_pdacf *chip) { - printk(KERN_DEBUG "PDAUDIOCF DUMP (0x%lx):\n", chip->port); - printk(KERN_DEBUG "WPD : 0x%x\n", - inw(chip->port + PDAUDIOCF_REG_WDP)); - printk(KERN_DEBUG "RDP : 0x%x\n", - inw(chip->port + PDAUDIOCF_REG_RDP)); - printk(KERN_DEBUG "TCR : 0x%x\n", - inw(chip->port + PDAUDIOCF_REG_TCR)); - printk(KERN_DEBUG "SCR : 0x%x\n", - inw(chip->port + PDAUDIOCF_REG_SCR)); - printk(KERN_DEBUG "ISR : 0x%x\n", - inw(chip->port + PDAUDIOCF_REG_ISR)); - printk(KERN_DEBUG "IER : 0x%x\n", - inw(chip->port + PDAUDIOCF_REG_IER)); - printk(KERN_DEBUG "AK_IFR : 0x%x\n", - inw(chip->port + PDAUDIOCF_REG_AK_IFR)); + dev_dbg(chip->card->dev, "PDAUDIOCF DUMP (0x%lx):\n", chip->port); + dev_dbg(chip->card->dev, "WPD : 0x%x\n", + inw(chip->port + PDAUDIOCF_REG_WDP)); + dev_dbg(chip->card->dev, "RDP : 0x%x\n", + inw(chip->port + PDAUDIOCF_REG_RDP)); + dev_dbg(chip->card->dev, "TCR : 0x%x\n", + inw(chip->port + PDAUDIOCF_REG_TCR)); + dev_dbg(chip->card->dev, "SCR : 0x%x\n", + inw(chip->port + PDAUDIOCF_REG_SCR)); + dev_dbg(chip->card->dev, "ISR : 0x%x\n", + inw(chip->port + PDAUDIOCF_REG_ISR)); + dev_dbg(chip->card->dev, "IER : 0x%x\n", + inw(chip->port + PDAUDIOCF_REG_IER)); + dev_dbg(chip->card->dev, "AK_IFR : 0x%x\n", + inw(chip->port + PDAUDIOCF_REG_AK_IFR)); } #endif diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf_irq.c b/sound/pcmcia/pdaudiocf/pdaudiocf_irq.c index f134b4a4622fb8..af40a2c8789a6b 100644 --- a/sound/pcmcia/pdaudiocf/pdaudiocf_irq.c +++ b/sound/pcmcia/pdaudiocf/pdaudiocf_irq.c @@ -27,7 +27,7 @@ irqreturn_t pdacf_interrupt(int irq, void *dev) stat = inw(chip->port + PDAUDIOCF_REG_ISR); if (stat & (PDAUDIOCF_IRQLVL|PDAUDIOCF_IRQOVR)) { if (stat & PDAUDIOCF_IRQOVR) /* should never happen */ - snd_printk(KERN_ERR "PDAUDIOCF SRAM buffer overrun detected!\n"); + dev_err(chip->card->dev, "PDAUDIOCF SRAM buffer overrun detected!\n"); if (chip->pcm_substream) wake_thread = true; if (!(stat & PDAUDIOCF_IRQAKM)) @@ -257,7 +257,6 @@ irqreturn_t pdacf_threaded_irq(int irq, void *dev) rdp = inw(chip->port + PDAUDIOCF_REG_RDP); wdp = inw(chip->port + PDAUDIOCF_REG_WDP); - /* printk(KERN_DEBUG "TASKLET: rdp = %x, wdp = %x\n", rdp, wdp); */ size = wdp - rdp; if (size < 0) size += 0x10000; diff --git a/sound/pcmcia/vx/vxp_ops.c b/sound/pcmcia/vx/vxp_ops.c index 4176abd73799c4..0bc5c5d9d15742 100644 --- a/sound/pcmcia/vx/vxp_ops.c +++ b/sound/pcmcia/vx/vxp_ops.c @@ -84,7 +84,7 @@ static int vx_check_magic(struct vx_core *chip) return 0; msleep(10); } while (time_after_eq(end_time, jiffies)); - snd_printk(KERN_ERR "cannot find xilinx magic word (%x)\n", c); + dev_err(chip->card->dev, "cannot find xilinx magic word (%x)\n", c); return -EIO; } @@ -153,7 +153,6 @@ static int vxp_load_xilinx_binary(struct vx_core *_chip, const struct firmware * vx_outb(chip, ICR, 0); /* Wait for answer HF2 equal to 1 */ - snd_printdd(KERN_DEBUG "check ISR_HF2\n"); if (vx_check_isr(_chip, ISR_HF2, ISR_HF2, 20) < 0) goto _error; @@ -170,7 +169,9 @@ static int vxp_load_xilinx_binary(struct vx_core *_chip, const struct firmware * goto _error; c = vx_inb(chip, RXL); if (c != (int)data) - snd_printk(KERN_ERR "vxpocket: load xilinx mismatch at %d: 0x%x != 0x%x\n", i, c, (int)data); + dev_err(_chip->card->dev, + "vxpocket: load xilinx mismatch at %d: 0x%x != 0x%x\n", + i, c, (int)data); } /* reset HF1 */ @@ -188,7 +189,8 @@ static int vxp_load_xilinx_binary(struct vx_core *_chip, const struct firmware * c |= (int)vx_inb(chip, RXM) << 8; c |= vx_inb(chip, RXL); - snd_printdd(KERN_DEBUG "xilinx: dsp size received 0x%x, orig 0x%zx\n", c, fw->size); + dev_dbg(_chip->card->dev, + "xilinx: dsp size received 0x%x, orig 0x%zx\n", c, fw->size); vx_outb(chip, ICR, ICR_HF0); diff --git a/sound/pcmcia/vx/vxpocket.c b/sound/pcmcia/vx/vxpocket.c index 7a0f0e73ceb2ed..d2d5f64d63b431 100644 --- a/sound/pcmcia/vx/vxpocket.c +++ b/sound/pcmcia/vx/vxpocket.c @@ -151,7 +151,8 @@ static int snd_vxpocket_assign_resources(struct vx_core *chip, int port, int irq struct snd_card *card = chip->card; struct snd_vxpocket *vxp = to_vxpocket(chip); - snd_printdd(KERN_DEBUG "vxpocket assign resources: port = 0x%x, irq = %d\n", port, irq); + dev_dbg(chip->card->dev, + "vxpocket assign resources: port = 0x%x, irq = %d\n", port, irq); vxp->port = port; sprintf(card->shortname, "Digigram %s", card->driver); @@ -178,13 +179,11 @@ static int vxpocket_config(struct pcmcia_device *link) struct vx_core *chip = link->priv; int ret; - snd_printdd(KERN_DEBUG "vxpocket_config called\n"); - /* redefine hardware record according to the VERSION1 string */ if (!strcmp(link->prod_id[1], "VX-POCKET")) { - snd_printdd("VX-pocket is detected\n"); + dev_dbg(chip->card->dev, "VX-pocket is detected\n"); } else { - snd_printdd("VX-pocket 440 is detected\n"); + dev_dbg(chip->card->dev, "VX-pocket 440 is detected\n"); /* overwrite the hardware information */ chip->hw = &vxp440_hw; chip->type = vxp440_hw.type; @@ -205,8 +204,6 @@ static int vxpocket_config(struct pcmcia_device *link) if (ret) goto failed; - chip->dev = &link->dev; - if (snd_vxpocket_assign_resources(chip, link->resource[0]->start, link->irq) < 0) goto failed; @@ -226,11 +223,8 @@ static int vxp_suspend(struct pcmcia_device *link) { struct vx_core *chip = link->priv; - snd_printdd(KERN_DEBUG "SUSPEND\n"); - if (chip) { - snd_printdd(KERN_DEBUG "snd_vx_suspend calling\n"); + if (chip) snd_vx_suspend(chip); - } return 0; } @@ -239,15 +233,10 @@ static int vxp_resume(struct pcmcia_device *link) { struct vx_core *chip = link->priv; - snd_printdd(KERN_DEBUG "RESUME\n"); if (pcmcia_dev_present(link)) { - //struct snd_vxpocket *vxp = (struct snd_vxpocket *)chip; - if (chip) { - snd_printdd(KERN_DEBUG "calling snd_vx_resume\n"); + if (chip) snd_vx_resume(chip); - } } - snd_printdd(KERN_DEBUG "resume done!\n"); return 0; } @@ -269,7 +258,7 @@ static int vxpocket_probe(struct pcmcia_device *p_dev) break; } if (i >= SNDRV_CARDS) { - snd_printk(KERN_ERR "vxpocket: too many cards found\n"); + dev_err(&p_dev->dev, "vxpocket: too many cards found\n"); return -EINVAL; } if (! enable[i]) @@ -279,7 +268,7 @@ static int vxpocket_probe(struct pcmcia_device *p_dev) err = snd_card_new(&p_dev->dev, index[i], id[i], THIS_MODULE, 0, &card); if (err < 0) { - snd_printk(KERN_ERR "vxpocket: cannot create a card instance\n"); + dev_err(&p_dev->dev, "vxpocket: cannot create a card instance\n"); return err; } diff --git a/sound/ppc/awacs.c b/sound/ppc/awacs.c index 659866cfe3b473..49399a4a290d74 100644 --- a/sound/ppc/awacs.c +++ b/sound/ppc/awacs.c @@ -39,7 +39,7 @@ static void snd_pmac_screamer_wait(struct snd_pmac *chip) while (!(in_le32(&chip->awacs->codec_stat) & MASK_VALID)) { mdelay(1); if (! --timeout) { - snd_printd("snd_pmac_screamer_wait timeout\n"); + dev_dbg(chip->card->dev, "%s timeout\n", __func__); break; } } @@ -58,7 +58,7 @@ snd_pmac_awacs_write(struct snd_pmac *chip, int val) out_le32(&chip->awacs->codec_ctrl, val | (chip->subframe << 22)); while (in_le32(&chip->awacs->codec_ctrl) & MASK_NEWECMD) { if (! --timeout) { - snd_printd("snd_pmac_awacs_write timeout\n"); + dev_dbg(chip->card->dev, "%s timeout\n", __func__); break; } } diff --git a/sound/ppc/daca.c b/sound/ppc/daca.c index 4da9278dd58af1..d5766952f3dbe8 100644 --- a/sound/ppc/daca.c +++ b/sound/ppc/daca.c @@ -69,7 +69,7 @@ static int daca_set_volume(struct pmac_daca *mix) data[1] |= mix->deemphasis ? 0x40 : 0; if (i2c_smbus_write_block_data(mix->i2c.client, DACA_REG_AVOL, 2, data) < 0) { - snd_printk(KERN_ERR "failed to set volume \n"); + dev_err(&mix->i2c.client->dev, "failed to set volume\n"); return -EINVAL; } return 0; diff --git a/sound/ppc/keywest.c b/sound/ppc/keywest.c index 2894d041b2f548..3d3513d9def5cc 100644 --- a/sound/ppc/keywest.c +++ b/sound/ppc/keywest.c @@ -113,7 +113,8 @@ int snd_pmac_tumbler_post_init(void) err = keywest_ctx->init_client(keywest_ctx); if (err < 0) { - snd_printk(KERN_ERR "tumbler: %i :cannot initialize the MCS\n", err); + dev_err(&keywest_ctx->client->dev, + "tumbler: %i :cannot initialize the MCS\n", err); return err; } return 0; @@ -136,7 +137,7 @@ int snd_pmac_keywest_init(struct pmac_keywest *i2c) err = i2c_add_driver(&keywest_driver); if (err) { - snd_printk(KERN_ERR "cannot register keywest i2c driver\n"); + dev_err(&i2c->client->dev, "cannot register keywest i2c driver\n"); i2c_put_adapter(adap); return err; } diff --git a/sound/ppc/pmac.c b/sound/ppc/pmac.c index 84058bbf9d1277..76674c43fa7eb1 100644 --- a/sound/ppc/pmac.c +++ b/sound/ppc/pmac.c @@ -269,7 +269,6 @@ static int snd_pmac_pcm_trigger(struct snd_pmac *chip, struct pmac_stream *rec, case SNDRV_PCM_TRIGGER_SUSPEND: spin_lock(&chip->reg_lock); rec->running = 0; - /*printk(KERN_DEBUG "stopped!!\n");*/ snd_pmac_dma_stop(rec); for (i = 0, cp = rec->cmd.cmds; i < rec->nperiods; i++, cp++) out_le16(&cp->command, DBDMA_STOP); @@ -304,7 +303,6 @@ static snd_pcm_uframes_t snd_pmac_pcm_pointer(struct snd_pmac *chip, } #endif count += rec->cur_period * rec->period_size; - /*printk(KERN_DEBUG "pointer=%d\n", count);*/ return bytes_to_frames(subs->runtime, count); } @@ -384,8 +382,6 @@ static inline void snd_pmac_pcm_dead_xfer(struct pmac_stream *rec, unsigned short req, res ; unsigned int phy ; - /* printk(KERN_WARNING "snd-powermac: DMA died - patching it up!\n"); */ - /* to clear DEAD status we must first clear RUN set it to quiescent to be on the safe side */ (void)in_le32(&rec->dma->status); @@ -456,7 +452,6 @@ static void snd_pmac_pcm_update(struct snd_pmac *chip, struct pmac_stream *rec) if (! (stat & ACTIVE)) break; - /*printk(KERN_DEBUG "update frag %d\n", rec->cur_period);*/ cp->xfer_status = cpu_to_le16(0); cp->req_count = cpu_to_le16(rec->period_size); /*cp->res_count = cpu_to_le16(0);*/ @@ -770,7 +765,6 @@ snd_pmac_ctrl_intr(int irq, void *devid) struct snd_pmac *chip = devid; int ctrl = in_le32(&chip->awacs->control); - /*printk(KERN_DEBUG "pmac: control interrupt.. 0x%x\n", ctrl);*/ if (ctrl & MASK_PORTCHG) { /* do something when headphone is plugged/unplugged? */ if (chip->update_automute) @@ -779,7 +773,7 @@ snd_pmac_ctrl_intr(int irq, void *devid) if (ctrl & MASK_CNTLERR) { int err = (in_le32(&chip->awacs->codec_stat) & MASK_ERRCODE) >> 16; if (err && chip->model <= PMAC_SCREAMER) - snd_printk(KERN_DEBUG "error %x\n", err); + dev_dbg(chip->card->dev, "%s: error %x\n", __func__, err); } /* Writing 1s to the CNTLERR and PORTCHG bits clears them... */ out_le32(&chip->awacs->control, ctrl); @@ -964,9 +958,8 @@ static int snd_pmac_detect(struct snd_pmac *chip) if (prop) { /* partly deprecate snd-powermac, for those machines * that have a layout-id property for now */ - printk(KERN_INFO "snd-powermac no longer handles any " - "machines with a layout-id property " - "in the device-tree, use snd-aoa.\n"); + dev_info(chip->card->dev, + "snd-powermac no longer handles any machines with a layout-id property in the device-tree, use snd-aoa.\n"); of_node_put(sound); of_node_put(chip->node); chip->node = NULL; @@ -1021,7 +1014,7 @@ static int snd_pmac_detect(struct snd_pmac *chip) */ macio = macio_find(chip->node, macio_unknown); if (macio == NULL) - printk(KERN_WARNING "snd-powermac: can't locate macio !\n"); + dev_warn(chip->card->dev, "snd-powermac: can't locate macio !\n"); else { struct pci_dev *pdev = NULL; @@ -1034,8 +1027,8 @@ static int snd_pmac_detect(struct snd_pmac *chip) } } if (chip->pdev == NULL) - printk(KERN_WARNING "snd-powermac: can't locate macio PCI" - " device !\n"); + dev_warn(chip->card->dev, + "snd-powermac: can't locate macio PCI device !\n"); detect_byte_swap(chip); @@ -1125,7 +1118,8 @@ int snd_pmac_add_automute(struct snd_pmac *chip) chip->auto_mute = 1; err = snd_ctl_add(chip->card, snd_ctl_new1(&auto_mute_controls[0], chip)); if (err < 0) { - printk(KERN_ERR "snd-powermac: Failed to add automute control\n"); + dev_err(chip->card->dev, + "snd-powermac: Failed to add automute control\n"); return err; } chip->hp_detect_ctl = snd_ctl_new1(&auto_mute_controls[1], chip); @@ -1180,17 +1174,18 @@ int snd_pmac_new(struct snd_card *card, struct snd_pmac **chip_return) for (i = 0; i < 2; i ++) { if (of_address_to_resource(np->parent, i, &chip->rsrc[i])) { - printk(KERN_ERR "snd: can't translate rsrc " - " %d (%s)\n", i, rnames[i]); + dev_err(chip->card->dev, + "snd: can't translate rsrc %d (%s)\n", + i, rnames[i]); err = -ENODEV; goto __error; } if (request_mem_region(chip->rsrc[i].start, resource_size(&chip->rsrc[i]), rnames[i]) == NULL) { - printk(KERN_ERR "snd: can't request rsrc " - " %d (%s: %pR)\n", - i, rnames[i], &chip->rsrc[i]); + dev_err(chip->card->dev, + "snd: can't request rsrc %d (%s: %pR)\n", + i, rnames[i], &chip->rsrc[i]); err = -ENODEV; goto __error; } @@ -1205,17 +1200,18 @@ int snd_pmac_new(struct snd_card *card, struct snd_pmac **chip_return) for (i = 0; i < 3; i ++) { if (of_address_to_resource(np, i, &chip->rsrc[i])) { - printk(KERN_ERR "snd: can't translate rsrc " - " %d (%s)\n", i, rnames[i]); + dev_err(chip->card->dev, + "snd: can't translate rsrc %d (%s)\n", + i, rnames[i]); err = -ENODEV; goto __error; } if (request_mem_region(chip->rsrc[i].start, resource_size(&chip->rsrc[i]), rnames[i]) == NULL) { - printk(KERN_ERR "snd: can't request rsrc " - " %d (%s: %pR)\n", - i, rnames[i], &chip->rsrc[i]); + dev_err(chip->card->dev, + "snd: can't request rsrc %d (%s: %pR)\n", + i, rnames[i], &chip->rsrc[i]); err = -ENODEV; goto __error; } @@ -1233,8 +1229,8 @@ int snd_pmac_new(struct snd_card *card, struct snd_pmac **chip_return) irq = irq_of_parse_and_map(np, 0); if (request_irq(irq, snd_pmac_ctrl_intr, 0, "PMac", (void*)chip)) { - snd_printk(KERN_ERR "pmac: unable to grab IRQ %d\n", - irq); + dev_err(chip->card->dev, + "pmac: unable to grab IRQ %d\n", irq); err = -EBUSY; goto __error; } @@ -1242,14 +1238,14 @@ int snd_pmac_new(struct snd_card *card, struct snd_pmac **chip_return) } irq = irq_of_parse_and_map(np, 1); if (request_irq(irq, snd_pmac_tx_intr, 0, "PMac Output", (void*)chip)){ - snd_printk(KERN_ERR "pmac: unable to grab IRQ %d\n", irq); + dev_err(chip->card->dev, "pmac: unable to grab IRQ %d\n", irq); err = -EBUSY; goto __error; } chip->tx_irq = irq; irq = irq_of_parse_and_map(np, 2); if (request_irq(irq, snd_pmac_rx_intr, 0, "PMac Input", (void*)chip)) { - snd_printk(KERN_ERR "pmac: unable to grab IRQ %d\n", irq); + dev_err(chip->card->dev, "pmac: unable to grab IRQ %d\n", irq); err = -EBUSY; goto __error; } diff --git a/sound/ppc/powermac.c b/sound/ppc/powermac.c index e17af46abddd56..8e29c92830ad64 100644 --- a/sound/ppc/powermac.c +++ b/sound/ppc/powermac.c @@ -104,7 +104,7 @@ static int snd_pmac_probe(struct platform_device *devptr) goto __error; break; default: - snd_printk(KERN_ERR "unsupported hardware %d\n", chip->model); + dev_err(&devptr->dev, "unsupported hardware %d\n", chip->model); err = -EINVAL; goto __error; } diff --git a/sound/ppc/tumbler.c b/sound/ppc/tumbler.c index 12f1e10db1c4b8..3c09660e152217 100644 --- a/sound/ppc/tumbler.c +++ b/sound/ppc/tumbler.c @@ -29,7 +29,7 @@ #undef DEBUG #ifdef DEBUG -#define DBG(fmt...) printk(KERN_DEBUG fmt) +#define DBG(fmt...) pr_debug(fmt) #else #define DBG(fmt...) #endif @@ -230,7 +230,7 @@ static int tumbler_set_master_volume(struct pmac_tumbler *mix) if (i2c_smbus_write_i2c_block_data(mix->i2c.client, TAS_REG_VOL, 6, block) < 0) { - snd_printk(KERN_ERR "failed to set volume \n"); + dev_err(&mix->i2c.client->dev, "failed to set volume\n"); return -EINVAL; } DBG("(I) succeeded to set volume (%u, %u)\n", left_vol, right_vol); @@ -341,7 +341,7 @@ static int tumbler_set_drc(struct pmac_tumbler *mix) if (i2c_smbus_write_i2c_block_data(mix->i2c.client, TAS_REG_DRC, 2, val) < 0) { - snd_printk(KERN_ERR "failed to set DRC\n"); + dev_err(&mix->i2c.client->dev, "failed to set DRC\n"); return -EINVAL; } DBG("(I) succeeded to set DRC (%u, %u)\n", val[0], val[1]); @@ -378,7 +378,7 @@ static int snapper_set_drc(struct pmac_tumbler *mix) if (i2c_smbus_write_i2c_block_data(mix->i2c.client, TAS_REG_DRC, 6, val) < 0) { - snd_printk(KERN_ERR "failed to set DRC\n"); + dev_err(&mix->i2c.client->dev, "failed to set DRC\n"); return -EINVAL; } DBG("(I) succeeded to set DRC (%u, %u)\n", val[0], val[1]); @@ -503,8 +503,8 @@ static int tumbler_set_mono_volume(struct pmac_tumbler *mix, block[i] = (vol >> ((info->bytes - i - 1) * 8)) & 0xff; if (i2c_smbus_write_i2c_block_data(mix->i2c.client, info->reg, info->bytes, block) < 0) { - snd_printk(KERN_ERR "failed to set mono volume %d\n", - info->index); + dev_err(&mix->i2c.client->dev, "failed to set mono volume %d\n", + info->index); return -EINVAL; } return 0; @@ -643,7 +643,8 @@ static int snapper_set_mix_vol1(struct pmac_tumbler *mix, int idx, int ch, int r } if (i2c_smbus_write_i2c_block_data(mix->i2c.client, reg, 9, block) < 0) { - snd_printk(KERN_ERR "failed to set mono volume %d\n", reg); + dev_err(&mix->i2c.client->dev, + "failed to set mono volume %d\n", reg); return -EINVAL; } return 0; @@ -1102,7 +1103,6 @@ static long tumbler_find_device(const char *device, const char *platform, node = find_audio_device(device); if (! node) { DBG("(W) cannot find audio device %s !\n", device); - snd_printdd("cannot find device %s\n", device); return -ENODEV; } @@ -1111,7 +1111,6 @@ static long tumbler_find_device(const char *device, const char *platform, base = of_get_property(node, "reg", NULL); if (!base) { DBG("(E) cannot find address for device %s !\n", device); - snd_printd("cannot find address for device %s\n", device); of_node_put(node); return -ENODEV; } @@ -1232,9 +1231,9 @@ static void tumbler_resume(struct snd_pmac *chip) tumbler_reset_audio(chip); if (mix->i2c.client && mix->i2c.init_client) { if (mix->i2c.init_client(&mix->i2c) < 0) - printk(KERN_ERR "tumbler_init_client error\n"); + dev_err(chip->card->dev, "tumbler_init_client error\n"); } else - printk(KERN_ERR "tumbler: i2c is not initialized\n"); + dev_err(chip->card->dev, "tumbler: i2c is not initialized\n"); if (chip->model == PMAC_TUMBLER) { tumbler_set_mono_volume(mix, &tumbler_pcm_vol_info); tumbler_set_mono_volume(mix, &tumbler_bass_vol_info); diff --git a/sound/sh/aica.c b/sound/sh/aica.c index 3182c634464d42..936cd6e91529c8 100644 --- a/sound/sh/aica.c +++ b/sound/sh/aica.c @@ -75,8 +75,7 @@ static void spu_write_wait(void) /* To ensure hardware failure doesn't wedge kernel */ time_count++; if (time_count > 0x10000) { - snd_printk - ("WARNING: G2 FIFO appears to be blocked.\n"); + pr_warn("WARNING: G2 FIFO appears to be blocked.\n"); break; } } @@ -591,8 +590,8 @@ static int snd_aica_probe(struct platform_device *devptr) if (unlikely(err < 0)) goto freedreamcast; platform_set_drvdata(devptr, dreamcastcard); - snd_printk - ("ALSA Driver for Yamaha AICA Super Intelligent Sound Processor\n"); + dev_info(&devptr->dev, + "ALSA Driver for Yamaha AICA Super Intelligent Sound Processor\n"); return 0; freedreamcast: snd_card_free(dreamcastcard->card); diff --git a/sound/sh/sh_dac_audio.c b/sound/sh/sh_dac_audio.c index 95ba3abd4e47eb..e7b6ce7bd086bd 100644 --- a/sound/sh/sh_dac_audio.c +++ b/sound/sh/sh_dac_audio.c @@ -348,8 +348,8 @@ static int snd_sh_dac_probe(struct platform_device *devptr) err = snd_card_new(&devptr->dev, index, id, THIS_MODULE, 0, &card); if (err < 0) { - snd_printk(KERN_ERR "cannot allocate the card\n"); - return err; + dev_err(&devptr->dev, "cannot allocate the card\n"); + return err; } err = snd_sh_dac_create(card, devptr, &chip); @@ -362,13 +362,13 @@ static int snd_sh_dac_probe(struct platform_device *devptr) strcpy(card->driver, "snd_sh_dac"); strcpy(card->shortname, "SuperH DAC audio driver"); - printk(KERN_INFO "%s %s", card->longname, card->shortname); + dev_info(&devptr->dev, "%s %s\n", card->longname, card->shortname); err = snd_card_register(card); if (err < 0) goto probe_error; - snd_printk(KERN_INFO "ALSA driver for SuperH DAC audio"); + dev_info(&devptr->dev, "ALSA driver for SuperH DAC audio\n"); platform_set_drvdata(devptr, card); return 0; diff --git a/sound/soc/amd/acp/acp-legacy-common.c b/sound/soc/amd/acp/acp-legacy-common.c index 4422cec81e3c4d..3cc083fac83732 100644 --- a/sound/soc/amd/acp/acp-legacy-common.c +++ b/sound/soc/amd/acp/acp-legacy-common.c @@ -270,6 +270,7 @@ static int acp_power_on(struct acp_chip_info *chip) acp_pgfsm_ctrl_reg = ACP63_PGFSM_CONTROL; break; case ACP70_DEV: + case ACP71_DEV: acp_pgfsm_stat_reg = ACP70_PGFSM_STATUS; acp_pgfsm_ctrl_reg = ACP70_PGFSM_CONTROL; break; @@ -321,6 +322,8 @@ int acp_init(struct acp_chip_info *chip) pr_err("ACP reset failed\n"); return ret; } + if (chip->acp_rev >= ACP70_DEV) + writel(0, chip->base + ACP_ZSC_DSP_CTRL); return 0; } EXPORT_SYMBOL_NS_GPL(acp_init, SND_SOC_ACP_COMMON); @@ -334,8 +337,10 @@ int acp_deinit(struct acp_chip_info *chip) if (ret) return ret; - if (chip->acp_rev != ACP70_DEV) + if (chip->acp_rev < ACP70_DEV) writel(0, chip->base + ACP_CONTROL); + else + writel(0x01, chip->base + ACP_ZSC_DSP_CTRL); return 0; } EXPORT_SYMBOL_NS_GPL(acp_deinit, SND_SOC_ACP_COMMON); @@ -456,6 +461,7 @@ void check_acp_config(struct pci_dev *pci, struct acp_chip_info *chip) check_acp6x_config(chip); break; case ACP70_DEV: + case ACP71_DEV: pdm_addr = ACP70_PDM_ADDR; check_acp70_config(chip); break; diff --git a/sound/soc/amd/acp/acp-legacy-mach.c b/sound/soc/amd/acp/acp-legacy-mach.c index 47c3b5f167f59e..0d529e32e552bd 100644 --- a/sound/soc/amd/acp/acp-legacy-mach.c +++ b/sound/soc/amd/acp/acp-legacy-mach.c @@ -227,6 +227,8 @@ static const struct platform_device_id board_ids[] = { }, { } }; +MODULE_DEVICE_TABLE(platform, board_ids); + static struct platform_driver acp_asoc_audio = { .driver = { .pm = &snd_soc_pm_ops, diff --git a/sound/soc/amd/acp/acp-mach-common.c b/sound/soc/amd/acp/acp-mach-common.c index a36300a4ed8a60..e9ff4815c12c8c 100644 --- a/sound/soc/amd/acp/acp-mach-common.c +++ b/sound/soc/amd/acp/acp-mach-common.c @@ -1766,7 +1766,7 @@ int acp_legacy_dai_links_create(struct snd_soc_card *card) } else if (drv_data->platform == ACP63) { links[i].platforms = platform_acp63_component; links[i].num_platforms = ARRAY_SIZE(platform_acp63_component); - } else if (drv_data->platform == ACP70) { + } else if ((drv_data->platform == ACP70) || (drv_data->platform == ACP71)) { links[i].platforms = platform_acp70_component; links[i].num_platforms = ARRAY_SIZE(platform_acp70_component); } else { diff --git a/sound/soc/amd/acp/acp-mach.h b/sound/soc/amd/acp/acp-mach.h index a48546d8d40732..93d9e3886b7ecd 100644 --- a/sound/soc/amd/acp/acp-mach.h +++ b/sound/soc/amd/acp/acp-mach.h @@ -56,6 +56,7 @@ enum platform_end_point { REMBRANDT, ACP63, ACP70, + ACP71, }; struct acp_mach_ops { diff --git a/sound/soc/amd/acp/acp-pci.c b/sound/soc/amd/acp/acp-pci.c index b0304b813cadce..f7450a5bd103e0 100644 --- a/sound/soc/amd/acp/acp-pci.c +++ b/sound/soc/amd/acp/acp-pci.c @@ -95,6 +95,10 @@ static int acp_pci_probe(struct pci_dev *pci, const struct pci_device_id *pci_id chip->name = "acp_asoc_acp70"; chip->acp_rev = ACP70_DEV; break; + case 0x71: + chip->name = "acp_asoc_acp70"; + chip->acp_rev = ACP71_DEV; + break; default: dev_err(dev, "Unsupported device revision:0x%x\n", pci->revision); ret = -EINVAL; diff --git a/sound/soc/amd/acp/acp-sdw-sof-mach.c b/sound/soc/amd/acp/acp-sdw-sof-mach.c index 0995b40d15f366..08f368b3bbc861 100644 --- a/sound/soc/amd/acp/acp-sdw-sof-mach.c +++ b/sound/soc/amd/acp/acp-sdw-sof-mach.c @@ -738,5 +738,4 @@ module_platform_driver(sof_sdw_driver); MODULE_DESCRIPTION("ASoC AMD SoundWire Generic Machine driver"); MODULE_AUTHOR("Vijendar Mukunda acp_rev != ACP70_DEV) { + switch (chip->acp_rev) { + case ACP70_DEV: + case ACP71_DEV: + break; + default: dev_err(&pdev->dev, "Un-supported ACP Revision %d\n", chip->acp_rev); return -ENODEV; } @@ -178,7 +182,11 @@ static int acp_acp70_audio_probe(struct platform_device *pdev) adata->num_dai = ARRAY_SIZE(acp70_dai); adata->rsrc = &rsrc; adata->machines = snd_soc_acpi_amd_acp70_acp_machines; - adata->platform = ACP70; + if (chip->acp_rev == ACP70_DEV) + adata->platform = ACP70; + else + adata->platform = ACP71; + adata->flag = chip->flag; acp_machine_select(adata); diff --git a/sound/soc/amd/acp/amd.h b/sound/soc/amd/acp/amd.h index 87a4813783f911..4f0cd7dd04e5a0 100644 --- a/sound/soc/amd/acp/amd.h +++ b/sound/soc/amd/acp/amd.h @@ -22,6 +22,7 @@ #define ACP6X_DEV 6 #define ACP63_DEV 0x63 #define ACP70_DEV 0x70 +#define ACP71_DEV 0x71 #define DMIC_INSTANCE 0x00 #define I2S_SP_INSTANCE 0x01 @@ -103,6 +104,8 @@ #define ACP70_PGFSM_CONTROL ACP6X_PGFSM_CONTROL #define ACP70_PGFSM_STATUS ACP6X_PGFSM_STATUS +#define ACP_ZSC_DSP_CTRL 0x0001014 +#define ACP_ZSC_STS 0x0001018 #define ACP_SOFT_RST_DONE_MASK 0x00010001 #define ACP_PGFSM_CNTL_POWER_ON_MASK 0xffffffff diff --git a/sound/soc/amd/yc/acp6x-mach.c b/sound/soc/amd/yc/acp6x-mach.c index f4bbfffe9fcb10..0523c16305db12 100644 --- a/sound/soc/amd/yc/acp6x-mach.c +++ b/sound/soc/amd/yc/acp6x-mach.c @@ -220,6 +220,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "21J6"), } }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "21M3"), + } + }, { .driver_data = &acp6x_card, .matches = { @@ -409,6 +416,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = { DMI_MATCH(DMI_BOARD_NAME, "8A43"), } }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "HP"), + DMI_MATCH(DMI_BOARD_NAME, "8A44"), + } + }, { .driver_data = &acp6x_card, .matches = { diff --git a/sound/soc/au1x/db1200.c b/sound/soc/au1x/db1200.c index 83a75a38705b4e..81abe2e184024e 100644 --- a/sound/soc/au1x/db1200.c +++ b/sound/soc/au1x/db1200.c @@ -44,6 +44,7 @@ static const struct platform_device_id db1200_pids[] = { }, {}, }; +MODULE_DEVICE_TABLE(platform, db1200_pids); /*------------------------- AC97 PART ---------------------------*/ diff --git a/sound/soc/codecs/cs-amp-lib.c b/sound/soc/codecs/cs-amp-lib.c index 287ac01a387357..605964af8afad4 100644 --- a/sound/soc/codecs/cs-amp-lib.c +++ b/sound/soc/codecs/cs-amp-lib.c @@ -108,7 +108,7 @@ static efi_status_t cs_amp_get_efi_variable(efi_char16_t *name, KUNIT_STATIC_STUB_REDIRECT(cs_amp_get_efi_variable, name, guid, size, buf); - if (IS_ENABLED(CONFIG_EFI)) + if (efi_rt_services_supported(EFI_RT_SUPPORTED_GET_VARIABLE)) return efi.get_variable(name, guid, &attr, size, buf); return EFI_NOT_FOUND; diff --git a/sound/soc/codecs/cs35l45.c b/sound/soc/codecs/cs35l45.c index 1e9d73bee3b4e2..fa1d9d9151f96e 100644 --- a/sound/soc/codecs/cs35l45.c +++ b/sound/soc/codecs/cs35l45.c @@ -177,7 +177,7 @@ static int cs35l45_activate_ctl(struct snd_soc_component *component, struct snd_kcontrol_volatile *vd; unsigned int index_offset; - kcontrol = snd_soc_component_get_kcontrol_locked(component, ctl_name); + kcontrol = snd_soc_component_get_kcontrol(component, ctl_name); if (!kcontrol) { dev_err(component->dev, "Can't find kcontrol %s\n", ctl_name); return -EINVAL; diff --git a/sound/soc/codecs/cs35l56-sdw.c b/sound/soc/codecs/cs35l56-sdw.c index fc03bb7ecae136..7c9a17fe2195cc 100644 --- a/sound/soc/codecs/cs35l56-sdw.c +++ b/sound/soc/codecs/cs35l56-sdw.c @@ -23,6 +23,79 @@ /* Register addresses are offset when sent over SoundWire */ #define CS35L56_SDW_ADDR_OFFSET 0x8000 +/* Cirrus bus bridge registers */ +#define CS35L56_SDW_MEM_ACCESS_STATUS 0xd0 +#define CS35L56_SDW_MEM_READ_DATA 0xd8 + +#define CS35L56_SDW_LAST_LATE BIT(3) +#define CS35L56_SDW_CMD_IN_PROGRESS BIT(2) +#define CS35L56_SDW_RDATA_RDY BIT(0) + +#define CS35L56_LATE_READ_POLL_US 10 +#define CS35L56_LATE_READ_TIMEOUT_US 1000 + +static int cs35l56_sdw_poll_mem_status(struct sdw_slave *peripheral, + unsigned int mask, + unsigned int match) +{ + int ret, val; + + ret = read_poll_timeout(sdw_read_no_pm, val, + (val < 0) || ((val & mask) == match), + CS35L56_LATE_READ_POLL_US, CS35L56_LATE_READ_TIMEOUT_US, + false, peripheral, CS35L56_SDW_MEM_ACCESS_STATUS); + if (ret < 0) + return ret; + + if (val < 0) + return val; + + return 0; +} + +static int cs35l56_sdw_slow_read(struct sdw_slave *peripheral, unsigned int reg, + u8 *buf, size_t val_size) +{ + int ret, i; + + reg += CS35L56_SDW_ADDR_OFFSET; + + for (i = 0; i < val_size; i += sizeof(u32)) { + /* Poll for bus bridge idle */ + ret = cs35l56_sdw_poll_mem_status(peripheral, + CS35L56_SDW_CMD_IN_PROGRESS, + 0); + if (ret < 0) { + dev_err(&peripheral->dev, "!CMD_IN_PROGRESS fail: %d\n", ret); + return ret; + } + + /* Reading LSByte triggers read of register to holding buffer */ + sdw_read_no_pm(peripheral, reg + i); + + /* Wait for data available */ + ret = cs35l56_sdw_poll_mem_status(peripheral, + CS35L56_SDW_RDATA_RDY, + CS35L56_SDW_RDATA_RDY); + if (ret < 0) { + dev_err(&peripheral->dev, "RDATA_RDY fail: %d\n", ret); + return ret; + } + + /* Read data from buffer */ + ret = sdw_nread_no_pm(peripheral, CS35L56_SDW_MEM_READ_DATA, + sizeof(u32), &buf[i]); + if (ret) { + dev_err(&peripheral->dev, "Late read @%#x failed: %d\n", reg + i, ret); + return ret; + } + + swab32s((u32 *)&buf[i]); + } + + return 0; +} + static int cs35l56_sdw_read_one(struct sdw_slave *peripheral, unsigned int reg, void *buf) { int ret; @@ -48,6 +121,10 @@ static int cs35l56_sdw_read(void *context, const void *reg_buf, int ret; reg = le32_to_cpu(*(const __le32 *)reg_buf); + + if (cs35l56_is_otp_register(reg)) + return cs35l56_sdw_slow_read(peripheral, reg, buf8, val_size); + reg += CS35L56_SDW_ADDR_OFFSET; if (val_size == 4) diff --git a/sound/soc/codecs/cs35l56-shared.c b/sound/soc/codecs/cs35l56-shared.c index e7e8d617da94e4..3744a7c8cea5db 100644 --- a/sound/soc/codecs/cs35l56-shared.c +++ b/sound/soc/codecs/cs35l56-shared.c @@ -36,6 +36,7 @@ static const struct reg_sequence cs35l56_patch[] = { { CS35L56_SWIRE_DP3_CH2_INPUT, 0x00000019 }, { CS35L56_SWIRE_DP3_CH3_INPUT, 0x00000029 }, { CS35L56_SWIRE_DP3_CH4_INPUT, 0x00000028 }, + { CS35L56_IRQ1_MASK_18, 0x1f7df0ff }, /* These are not reset by a soft-reset, so patch to defaults. */ { CS35L56_MAIN_RENDER_USER_MUTE, 0x00000000 }, @@ -450,32 +451,23 @@ static const struct reg_sequence cs35l56_hibernate_seq[] = { REG_SEQ0(CS35L56_DSP_VIRTUAL1_MBOX_1, CS35L56_MBOX_CMD_ALLOW_AUTO_HIBERNATE), }; -static const struct reg_sequence cs35l56_hibernate_wake_seq[] = { - REG_SEQ0(CS35L56_DSP_VIRTUAL1_MBOX_1, CS35L56_MBOX_CMD_WAKEUP), -}; - static void cs35l56_issue_wake_event(struct cs35l56_base *cs35l56_base) { + unsigned int val; + /* * Dummy transactions to trigger I2C/SPI auto-wake. Issue two * transactions to meet the minimum required time from the rising edge * to the last falling edge of wake. * - * It uses bypassed write because we must wake the chip before + * It uses bypassed read because we must wake the chip before * disabling regmap cache-only. - * - * This can NAK on I2C which will terminate the write sequence so the - * single-write sequence is issued twice. */ - regmap_multi_reg_write_bypassed(cs35l56_base->regmap, - cs35l56_hibernate_wake_seq, - ARRAY_SIZE(cs35l56_hibernate_wake_seq)); + regmap_read_bypassed(cs35l56_base->regmap, CS35L56_IRQ1_STATUS, &val); usleep_range(CS35L56_WAKE_HOLD_TIME_US, 2 * CS35L56_WAKE_HOLD_TIME_US); - regmap_multi_reg_write_bypassed(cs35l56_base->regmap, - cs35l56_hibernate_wake_seq, - ARRAY_SIZE(cs35l56_hibernate_wake_seq)); + regmap_read_bypassed(cs35l56_base->regmap, CS35L56_IRQ1_STATUS, &val); cs35l56_wait_control_port_ready(); } diff --git a/sound/soc/codecs/cs35l56.c b/sound/soc/codecs/cs35l56.c index 84c34f5b1a516d..757ade6373ede3 100644 --- a/sound/soc/codecs/cs35l56.c +++ b/sound/soc/codecs/cs35l56.c @@ -1095,6 +1095,11 @@ int cs35l56_system_resume(struct device *dev) } EXPORT_SYMBOL_GPL(cs35l56_system_resume); +static int cs35l56_control_add_nop(struct wm_adsp *dsp, struct cs_dsp_coeff_ctl *cs_ctl) +{ + return 0; +} + static int cs35l56_dsp_init(struct cs35l56_private *cs35l56) { struct wm_adsp *dsp; @@ -1117,6 +1122,12 @@ static int cs35l56_dsp_init(struct cs35l56_private *cs35l56) dsp->fw = 12; dsp->wmfw_optional = true; + /* + * None of the firmware controls need to be exported so add a no-op + * callback that suppresses creating an ALSA control. + */ + dsp->control_add = &cs35l56_control_add_nop; + dev_dbg(cs35l56->base.dev, "DSP system name: '%s'\n", dsp->system_name); ret = wm_halo_init(dsp); diff --git a/sound/soc/codecs/cs43130.c b/sound/soc/codecs/cs43130.c index cb4ca80f36d28a..f8e2fb69ada2d5 100644 --- a/sound/soc/codecs/cs43130.c +++ b/sound/soc/codecs/cs43130.c @@ -1805,7 +1805,7 @@ static struct attribute *hpload_attrs[] = { }; ATTRIBUTE_GROUPS(hpload); -static struct reg_sequence hp_en_cal_seq[] = { +static const struct reg_sequence hp_en_cal_seq[] = { {CS43130_INT_MASK_4, CS43130_INT_MASK_ALL}, {CS43130_HP_MEAS_LOAD_1, 0}, {CS43130_HP_MEAS_LOAD_2, 0}, @@ -1820,7 +1820,7 @@ static struct reg_sequence hp_en_cal_seq[] = { {CS43130_HP_LOAD_1, 0x80}, }; -static struct reg_sequence hp_en_cal_seq2[] = { +static const struct reg_sequence hp_en_cal_seq2[] = { {CS43130_INT_MASK_4, CS43130_INT_MASK_ALL}, {CS43130_HP_MEAS_LOAD_1, 0}, {CS43130_HP_MEAS_LOAD_2, 0}, @@ -1828,7 +1828,7 @@ static struct reg_sequence hp_en_cal_seq2[] = { {CS43130_HP_LOAD_1, 0x80}, }; -static struct reg_sequence hp_dis_cal_seq[] = { +static const struct reg_sequence hp_dis_cal_seq[] = { {CS43130_HP_LOAD_1, 0x80}, {CS43130_DXD1, 0x99}, {CS43130_DXD12, 0}, @@ -1836,12 +1836,12 @@ static struct reg_sequence hp_dis_cal_seq[] = { {CS43130_HP_LOAD_1, 0}, }; -static struct reg_sequence hp_dis_cal_seq2[] = { +static const struct reg_sequence hp_dis_cal_seq2[] = { {CS43130_HP_LOAD_1, 0x80}, {CS43130_HP_LOAD_1, 0}, }; -static struct reg_sequence hp_dc_ch_l_seq[] = { +static const struct reg_sequence hp_dc_ch_l_seq[] = { {CS43130_DXD1, 0x99}, {CS43130_DXD19, 0x0A}, {CS43130_DXD17, 0x93}, @@ -1851,12 +1851,12 @@ static struct reg_sequence hp_dc_ch_l_seq[] = { {CS43130_HP_LOAD_1, 0x81}, }; -static struct reg_sequence hp_dc_ch_l_seq2[] = { +static const struct reg_sequence hp_dc_ch_l_seq2[] = { {CS43130_HP_LOAD_1, 0x80}, {CS43130_HP_LOAD_1, 0x81}, }; -static struct reg_sequence hp_dc_ch_r_seq[] = { +static const struct reg_sequence hp_dc_ch_r_seq[] = { {CS43130_DXD1, 0x99}, {CS43130_DXD19, 0x8A}, {CS43130_DXD17, 0x15}, @@ -1866,12 +1866,12 @@ static struct reg_sequence hp_dc_ch_r_seq[] = { {CS43130_HP_LOAD_1, 0x91}, }; -static struct reg_sequence hp_dc_ch_r_seq2[] = { +static const struct reg_sequence hp_dc_ch_r_seq2[] = { {CS43130_HP_LOAD_1, 0x90}, {CS43130_HP_LOAD_1, 0x91}, }; -static struct reg_sequence hp_ac_ch_l_seq[] = { +static const struct reg_sequence hp_ac_ch_l_seq[] = { {CS43130_DXD1, 0x99}, {CS43130_DXD19, 0x0A}, {CS43130_DXD17, 0x93}, @@ -1881,12 +1881,12 @@ static struct reg_sequence hp_ac_ch_l_seq[] = { {CS43130_HP_LOAD_1, 0x82}, }; -static struct reg_sequence hp_ac_ch_l_seq2[] = { +static const struct reg_sequence hp_ac_ch_l_seq2[] = { {CS43130_HP_LOAD_1, 0x80}, {CS43130_HP_LOAD_1, 0x82}, }; -static struct reg_sequence hp_ac_ch_r_seq[] = { +static const struct reg_sequence hp_ac_ch_r_seq[] = { {CS43130_DXD1, 0x99}, {CS43130_DXD19, 0x8A}, {CS43130_DXD17, 0x15}, @@ -1896,24 +1896,24 @@ static struct reg_sequence hp_ac_ch_r_seq[] = { {CS43130_HP_LOAD_1, 0x92}, }; -static struct reg_sequence hp_ac_ch_r_seq2[] = { +static const struct reg_sequence hp_ac_ch_r_seq2[] = { {CS43130_HP_LOAD_1, 0x90}, {CS43130_HP_LOAD_1, 0x92}, }; -static struct reg_sequence hp_cln_seq[] = { +static const struct reg_sequence hp_cln_seq[] = { {CS43130_INT_MASK_4, CS43130_INT_MASK_ALL}, {CS43130_HP_MEAS_LOAD_1, 0}, {CS43130_HP_MEAS_LOAD_2, 0}, }; struct reg_sequences { - struct reg_sequence *seq; - int size; - unsigned int msk; + const struct reg_sequence *seq; + int size; + unsigned int msk; }; -static struct reg_sequences hpload_seq1[] = { +static const struct reg_sequences hpload_seq1[] = { { .seq = hp_en_cal_seq, .size = ARRAY_SIZE(hp_en_cal_seq), @@ -1951,7 +1951,7 @@ static struct reg_sequences hpload_seq1[] = { }, }; -static struct reg_sequences hpload_seq2[] = { +static const struct reg_sequences hpload_seq2[] = { { .seq = hp_en_cal_seq2, .size = ARRAY_SIZE(hp_en_cal_seq2), @@ -2041,7 +2041,7 @@ static int cs43130_update_hpload(unsigned int msk, int ac_idx, } static int cs43130_hpload_proc(struct cs43130_private *cs43130, - struct reg_sequence *seq, int seq_size, + const struct reg_sequence *seq, int seq_size, unsigned int rslt_msk, int ac_idx) { int ret; @@ -2122,7 +2122,7 @@ static void cs43130_imp_meas(struct work_struct *wk) int i, ret, ac_idx; struct cs43130_private *cs43130; struct snd_soc_component *component; - struct reg_sequences *hpload_seq; + const struct reg_sequences *hpload_seq; cs43130 = container_of(wk, struct cs43130_private, work); component = cs43130->component; diff --git a/sound/soc/codecs/es8326.c b/sound/soc/codecs/es8326.c index 60877116c0ef65..d5362b3be48444 100644 --- a/sound/soc/codecs/es8326.c +++ b/sound/soc/codecs/es8326.c @@ -844,6 +844,8 @@ static void es8326_jack_detect_handler(struct work_struct *work) es8326_disable_micbias(es8326->component); if (es8326->jack->status & SND_JACK_HEADPHONE) { dev_dbg(comp->dev, "Report hp remove event\n"); + snd_soc_jack_report(es8326->jack, 0, + SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_BTN_2); snd_soc_jack_report(es8326->jack, 0, SND_JACK_HEADSET); /* mute adc when mic path switch */ regmap_write(es8326->regmap, ES8326_ADC1_SRC, 0x44); @@ -1068,6 +1070,8 @@ static void es8326_init(struct snd_soc_component *component) regmap_write(es8326->regmap, ES8326_ADC_MUTE, 0x0f); regmap_write(es8326->regmap, ES8326_CLK_DIV_LRCK, 0xff); + regmap_write(es8326->regmap, ES8326_ADC1_SRC, 0x44); + regmap_write(es8326->regmap, ES8326_ADC2_SRC, 0x66); es8326_disable_micbias(es8326->component); msleep(200); diff --git a/sound/soc/codecs/lpass-macro-common.h b/sound/soc/codecs/lpass-macro-common.h index 21cb30ab706d8a..fb4b96cb2b232d 100644 --- a/sound/soc/codecs/lpass-macro-common.h +++ b/sound/soc/codecs/lpass-macro-common.h @@ -49,6 +49,12 @@ static inline void lpass_macro_pds_exit_action(void *pds) static inline const char *lpass_macro_get_codec_version_string(int version) { switch (version) { + case LPASS_CODEC_VERSION_1_0: + return "v1.0"; + case LPASS_CODEC_VERSION_1_1: + return "v1.1"; + case LPASS_CODEC_VERSION_1_2: + return "v1.2"; case LPASS_CODEC_VERSION_2_0: return "v2.0"; case LPASS_CODEC_VERSION_2_1: diff --git a/sound/soc/codecs/lpass-va-macro.c b/sound/soc/codecs/lpass-va-macro.c index b852cc7ffad9d9..8454193ed22a62 100644 --- a/sound/soc/codecs/lpass-va-macro.c +++ b/sound/soc/codecs/lpass-va-macro.c @@ -1472,6 +1472,8 @@ static void va_macro_set_lpass_codec_version(struct va_macro *va) if ((core_id_0 == 0x01) && (core_id_1 == 0x0F)) version = LPASS_CODEC_VERSION_2_0; + if ((core_id_0 == 0x02) && (core_id_1 == 0x0F) && core_id_2 == 0x01) + version = LPASS_CODEC_VERSION_2_0; if ((core_id_0 == 0x02) && (core_id_1 == 0x0E)) version = LPASS_CODEC_VERSION_2_1; if ((core_id_0 == 0x02) && (core_id_1 == 0x0F) && (core_id_2 == 0x50 || core_id_2 == 0x51)) @@ -1483,6 +1485,10 @@ static void va_macro_set_lpass_codec_version(struct va_macro *va) if ((core_id_0 == 0x02) && (core_id_1 == 0x0F) && (core_id_2 == 0x80 || core_id_2 == 0x81)) version = LPASS_CODEC_VERSION_2_8; + if (version == LPASS_CODEC_VERSION_UNKNOWN) + dev_warn(va->dev, "Unknown Codec version, ID: %02x / %02x / %02x\n", + core_id_0, core_id_1, core_id_2); + lpass_macro_set_codec_version(version); dev_dbg(va->dev, "LPASS Codec Version %s\n", lpass_macro_get_codec_version_string(version)); diff --git a/sound/soc/codecs/rt1318.c b/sound/soc/codecs/rt1318.c index 83b29b441be980..e12b1e96a53a5d 100644 --- a/sound/soc/codecs/rt1318.c +++ b/sound/soc/codecs/rt1318.c @@ -30,7 +30,7 @@ #include "rt1318.h" -static struct reg_sequence init_list[] = { +static const struct reg_sequence init_list[] = { { 0x0000C000, 0x01}, { 0x0000F20D, 0x00}, { 0x0000F212, 0x3E}, @@ -254,7 +254,6 @@ static struct reg_sequence init_list[] = { { 0x0000C320, 0x20}, { 0x0000C203, 0x9C}, }; -#define rt1318_INIT_REG_LEN ARRAY_SIZE(init_list) static const struct reg_default rt1318_reg[] = { { 0xc000, 0x00 }, diff --git a/sound/soc/codecs/tas2552.c b/sound/soc/codecs/tas2552.c index 9e68afc0989728..684d52ec660063 100644 --- a/sound/soc/codecs/tas2552.c +++ b/sound/soc/codecs/tas2552.c @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include diff --git a/sound/soc/codecs/tas2764.c b/sound/soc/codecs/tas2764.c index 5eaddf07aadcc7..d482cd194c08c5 100644 --- a/sound/soc/codecs/tas2764.c +++ b/sound/soc/codecs/tas2764.c @@ -10,7 +10,6 @@ #include #include #include -#include #include #include #include diff --git a/sound/soc/codecs/tas2770.c b/sound/soc/codecs/tas2770.c index 5601fba17c9607..9f93b230652a5d 100644 --- a/sound/soc/codecs/tas2770.c +++ b/sound/soc/codecs/tas2770.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include diff --git a/sound/soc/codecs/tas2780.c b/sound/soc/codecs/tas2780.c index 6902bfef185b87..a1963415c93178 100644 --- a/sound/soc/codecs/tas2780.c +++ b/sound/soc/codecs/tas2780.c @@ -7,7 +7,6 @@ #include #include #include -#include #include #include #include diff --git a/sound/soc/codecs/tas2781-comlib.c b/sound/soc/codecs/tas2781-comlib.c index 58abbc098a917b..664c371796d632 100644 --- a/sound/soc/codecs/tas2781-comlib.c +++ b/sound/soc/codecs/tas2781-comlib.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include @@ -411,8 +410,6 @@ EXPORT_SYMBOL_GPL(tasdevice_dsp_remove); void tasdevice_remove(struct tasdevice_priv *tas_priv) { - if (gpio_is_valid(tas_priv->irq_info.irq_gpio)) - gpio_free(tas_priv->irq_info.irq_gpio); mutex_destroy(&tas_priv->codec_lock); } EXPORT_SYMBOL_GPL(tasdevice_remove); diff --git a/sound/soc/codecs/tas2781-fmwlib.c b/sound/soc/codecs/tas2781-fmwlib.c index 8f9a3ae7153e94..f3a7605f071043 100644 --- a/sound/soc/codecs/tas2781-fmwlib.c +++ b/sound/soc/codecs/tas2781-fmwlib.c @@ -13,7 +13,6 @@ #include #include #include -#include #include #include #include diff --git a/sound/soc/codecs/tas2781-i2c.c b/sound/soc/codecs/tas2781-i2c.c index 8a57c045afddf2..eb8732b1bb99fd 100644 --- a/sound/soc/codecs/tas2781-i2c.c +++ b/sound/soc/codecs/tas2781-i2c.c @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include @@ -158,7 +157,7 @@ static int tas2563_digital_gain_get( mutex_lock(&tas_dev->codec_lock); /* Read the primary device */ - ret = tasdevice_dev_bulk_read(tas_dev, 0, reg, data, 4); + ret = tasdevice_dev_bulk_read(tas_dev, 0, reg, data, 4); if (ret) { dev_err(tas_dev->dev, "%s, get AMP vol error\n", __func__); goto out; @@ -204,7 +203,7 @@ static int tas2563_digital_gain_put( vol = clamp(vol, 0, max); mutex_lock(&tas_dev->codec_lock); /* Read the primary device */ - ret = tasdevice_dev_bulk_read(tas_dev, 0, reg, data, 4); + ret = tasdevice_dev_bulk_read(tas_dev, 0, reg, data, 4); if (ret) { dev_err(tas_dev->dev, "%s, get AMP vol error\n", __func__); rc = -1; @@ -424,8 +423,7 @@ static int tasdevice_configuration_put( return ret; } -static int tasdevice_dsp_create_ctrls( - struct tasdevice_priv *tas_priv) +static int tasdevice_dsp_create_ctrls(struct tasdevice_priv *tas_priv) { struct snd_kcontrol_new *dsp_ctrls; char *prog_name, *conf_name; @@ -584,13 +582,13 @@ static const struct snd_soc_dapm_widget tasdevice_dapm_widgets[] = { SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), SND_SOC_DAPM_SPK("SPK", tasdevice_dapm_event), SND_SOC_DAPM_OUTPUT("OUT"), - SND_SOC_DAPM_INPUT("DMIC") + SND_SOC_DAPM_INPUT("DMIC"), }; static const struct snd_soc_dapm_route tasdevice_audio_map[] = { {"SPK", NULL, "ASI"}, {"OUT", NULL, "SPK"}, - {"ASI OUT", NULL, "DMIC"} + {"ASI OUT", NULL, "DMIC"}, }; static int tasdevice_startup(struct snd_pcm_substream *substream, @@ -673,7 +671,7 @@ static const struct snd_soc_dai_ops tasdevice_dai_ops = { static struct snd_soc_dai_driver tasdevice_dai_driver[] = { { - .name = "tas2781_codec", + .name = "tasdev_codec", .id = 0, .playback = { .stream_name = "Playback", @@ -732,8 +730,7 @@ static void tasdevice_deinit(void *context) tas_priv->fw_state = TASDEVICE_DSP_FW_PENDING; } -static void tasdevice_codec_remove( - struct snd_soc_component *codec) +static void tasdevice_codec_remove(struct snd_soc_component *codec) { struct tasdevice_priv *tas_priv = snd_soc_component_get_drvdata(codec); @@ -758,7 +755,7 @@ static void tasdevice_parse_dt(struct tasdevice_priv *tas_priv) { struct i2c_client *client = (struct i2c_client *)tas_priv->client; unsigned int dev_addrs[TASDEVICE_MAX_CHANNELS]; - int rc, i, ndev = 0; + int i, ndev = 0; if (tas_priv->isacpi) { ndev = device_property_read_u32_array(&client->dev, @@ -773,7 +770,7 @@ static void tasdevice_parse_dt(struct tasdevice_priv *tas_priv) "ti,audio-slots", dev_addrs, ndev); } - tas_priv->irq_info.irq_gpio = + tas_priv->irq = acpi_dev_gpio_irq_get(ACPI_COMPANION(&client->dev), 0); } else if (IS_ENABLED(CONFIG_OF)) { struct device_node *np = tas_priv->dev->of_node; @@ -785,7 +782,7 @@ static void tasdevice_parse_dt(struct tasdevice_priv *tas_priv) dev_addrs[ndev++] = addr; } - tas_priv->irq_info.irq_gpio = of_irq_get(np, 0); + tas_priv->irq = of_irq_get(np, 0); } else { ndev = 1; dev_addrs[0] = client->addr; @@ -795,29 +792,12 @@ static void tasdevice_parse_dt(struct tasdevice_priv *tas_priv) tas_priv->tasdevice[i].dev_addr = dev_addrs[i]; tas_priv->reset = devm_gpiod_get_optional(&client->dev, - "reset-gpios", GPIOD_OUT_HIGH); + "reset", GPIOD_OUT_HIGH); if (IS_ERR(tas_priv->reset)) dev_err(tas_priv->dev, "%s Can't get reset GPIO\n", __func__); strcpy(tas_priv->dev_name, tasdevice_id[tas_priv->chip_id].name); - - if (gpio_is_valid(tas_priv->irq_info.irq_gpio)) { - rc = gpio_request(tas_priv->irq_info.irq_gpio, - "AUDEV-IRQ"); - if (!rc) { - gpio_direction_input( - tas_priv->irq_info.irq_gpio); - - tas_priv->irq_info.irq = - gpio_to_irq(tas_priv->irq_info.irq_gpio); - } else - dev_err(tas_priv->dev, "%s: GPIO %d request error\n", - __func__, tas_priv->irq_info.irq_gpio); - } else - dev_err(tas_priv->dev, - "Looking up irq-gpio property failed %d\n", - tas_priv->irq_info.irq_gpio); } static int tasdevice_i2c_probe(struct i2c_client *i2c) diff --git a/sound/soc/codecs/tas5086.c b/sound/soc/codecs/tas5086.c index 4bc1fdd232bb78..b97c0e88571386 100644 --- a/sound/soc/codecs/tas5086.c +++ b/sound/soc/codecs/tas5086.c @@ -463,9 +463,9 @@ static void tas5086_reset(struct tas5086_private *priv) { if (priv->reset) { /* Reset codec - minimum assertion time is 400ns */ - gpiod_direction_output(priv->reset, 1); + gpiod_set_value_cansleep(priv->reset, 1); udelay(1); - gpiod_set_value(priv->reset, 0); + gpiod_set_value_cansleep(priv->reset, 0); /* Codec needs ~15ms to wake up */ msleep(15); @@ -866,9 +866,10 @@ static void tas5086_remove(struct snd_soc_component *component) { struct tas5086_private *priv = snd_soc_component_get_drvdata(component); - if (priv->reset) + if (priv->reset) { /* Set codec to the reset state */ - gpiod_set_value(priv->reset, 1); + gpiod_set_value_cansleep(priv->reset, 1); + } regulator_bulk_disable(ARRAY_SIZE(priv->supplies), priv->supplies); }; diff --git a/sound/soc/codecs/wcd934x.c b/sound/soc/codecs/wcd934x.c index 291d0c80a6fcf1..910852eb9698c1 100644 --- a/sound/soc/codecs/wcd934x.c +++ b/sound/soc/codecs/wcd934x.c @@ -2643,8 +2643,8 @@ static void wcd934x_mbhc_get_result_params(struct wcd934x_codec *wcd934x, s16 c1; s32 x1, d1; int32_t denom; - int minCode_param[] = { - 3277, 1639, 820, 410, 205, 103, 52, 26 + static const int minCode_param[] = { + 3277, 1639, 820, 410, 205, 103, 52, 26 }; regmap_update_bits(wcd934x->regmap, WCD934X_ANA_MBHC_ZDET, 0x20, 0x20); diff --git a/sound/soc/codecs/wcd937x.c b/sound/soc/codecs/wcd937x.c index 13926f4b0d9f16..af296b77a723ad 100644 --- a/sound/soc/codecs/wcd937x.c +++ b/sound/soc/codecs/wcd937x.c @@ -242,10 +242,9 @@ static const struct regmap_irq_chip wcd937x_regmap_irq_chip = { static void wcd937x_reset(struct wcd937x_priv *wcd937x) { - usleep_range(20, 30); - gpiod_set_value(wcd937x->reset_gpio, 1); - + usleep_range(20, 30); + gpiod_set_value(wcd937x->reset_gpio, 0); usleep_range(20, 30); } diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index 9f8549b34e3025..e69283195f362f 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -583,7 +583,7 @@ static void wm_adsp_ctl_work(struct work_struct *work) kfree(kcontrol); } -static int wm_adsp_control_add(struct cs_dsp_coeff_ctl *cs_ctl) +int wm_adsp_control_add(struct cs_dsp_coeff_ctl *cs_ctl) { struct wm_adsp *dsp = container_of(cs_ctl->dsp, struct wm_adsp, cs_dsp); struct cs_dsp *cs_dsp = &dsp->cs_dsp; @@ -658,6 +658,17 @@ static int wm_adsp_control_add(struct cs_dsp_coeff_ctl *cs_ctl) return ret; } +EXPORT_SYMBOL_GPL(wm_adsp_control_add); + +static int wm_adsp_control_add_cb(struct cs_dsp_coeff_ctl *cs_ctl) +{ + struct wm_adsp *dsp = container_of(cs_ctl->dsp, struct wm_adsp, cs_dsp); + + if (dsp->control_add) + return (dsp->control_add)(dsp, cs_ctl); + else + return wm_adsp_control_add(cs_ctl); +} static void wm_adsp_control_remove(struct cs_dsp_coeff_ctl *cs_ctl) { @@ -2072,12 +2083,12 @@ irqreturn_t wm_halo_wdt_expire(int irq, void *data) EXPORT_SYMBOL_GPL(wm_halo_wdt_expire); static const struct cs_dsp_client_ops wm_adsp1_client_ops = { - .control_add = wm_adsp_control_add, + .control_add = wm_adsp_control_add_cb, .control_remove = wm_adsp_control_remove, }; static const struct cs_dsp_client_ops wm_adsp2_client_ops = { - .control_add = wm_adsp_control_add, + .control_add = wm_adsp_control_add_cb, .control_remove = wm_adsp_control_remove, .pre_run = wm_adsp_pre_run, .post_run = wm_adsp_event_post_run, diff --git a/sound/soc/codecs/wm_adsp.h b/sound/soc/codecs/wm_adsp.h index e53dfcf1f78ff7..edc5b02ae76542 100644 --- a/sound/soc/codecs/wm_adsp.h +++ b/sound/soc/codecs/wm_adsp.h @@ -37,6 +37,7 @@ struct wm_adsp { bool wmfw_optional; struct work_struct boot_work; + int (*control_add)(struct wm_adsp *dsp, struct cs_dsp_coeff_ctl *cs_ctl); int (*pre_run)(struct wm_adsp *dsp); bool preloaded; @@ -132,6 +133,8 @@ int wm_adsp_compr_pointer(struct snd_soc_component *component, int wm_adsp_compr_copy(struct snd_soc_component *component, struct snd_compr_stream *stream, char __user *buf, size_t count); + +int wm_adsp_control_add(struct cs_dsp_coeff_ctl *cs_ctl); int wm_adsp_write_ctl(struct wm_adsp *dsp, const char *name, int type, unsigned int alg, void *buf, size_t len); int wm_adsp_read_ctl(struct wm_adsp *dsp, const char *name, int type, diff --git a/sound/soc/fsl/fsl_audmix.c b/sound/soc/fsl/fsl_audmix.c index 1671a3037c6048..f3a24758aedbbe 100644 --- a/sound/soc/fsl/fsl_audmix.c +++ b/sound/soc/fsl/fsl_audmix.c @@ -512,7 +512,6 @@ static void fsl_audmix_remove(struct platform_device *pdev) platform_device_unregister(priv->pdev); } -#ifdef CONFIG_PM static int fsl_audmix_runtime_resume(struct device *dev) { struct fsl_audmix *priv = dev_get_drvdata(dev); @@ -540,14 +539,11 @@ static int fsl_audmix_runtime_suspend(struct device *dev) return 0; } -#endif /* CONFIG_PM */ static const struct dev_pm_ops fsl_audmix_pm = { - SET_RUNTIME_PM_OPS(fsl_audmix_runtime_suspend, - fsl_audmix_runtime_resume, - NULL) - SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, - pm_runtime_force_resume) + RUNTIME_PM_OPS(fsl_audmix_runtime_suspend, fsl_audmix_runtime_resume, + NULL) + SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) }; static struct platform_driver fsl_audmix_driver = { @@ -556,7 +552,7 @@ static struct platform_driver fsl_audmix_driver = { .driver = { .name = "fsl-audmix", .of_match_table = fsl_audmix_ids, - .pm = &fsl_audmix_pm, + .pm = pm_ptr(&fsl_audmix_pm), }, }; module_platform_driver(fsl_audmix_driver); diff --git a/sound/soc/fsl/fsl_mqs.c b/sound/soc/fsl/fsl_mqs.c index c95b84a54dc464..df160834c81b61 100644 --- a/sound/soc/fsl/fsl_mqs.c +++ b/sound/soc/fsl/fsl_mqs.c @@ -265,7 +265,6 @@ static void fsl_mqs_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); } -#ifdef CONFIG_PM static int fsl_mqs_runtime_resume(struct device *dev) { struct fsl_mqs *mqs_priv = dev_get_drvdata(dev); @@ -299,14 +298,10 @@ static int fsl_mqs_runtime_suspend(struct device *dev) return 0; } -#endif static const struct dev_pm_ops fsl_mqs_pm_ops = { - SET_RUNTIME_PM_OPS(fsl_mqs_runtime_suspend, - fsl_mqs_runtime_resume, - NULL) - SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, - pm_runtime_force_resume) + RUNTIME_PM_OPS(fsl_mqs_runtime_suspend, fsl_mqs_runtime_resume, NULL) + SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) }; static const struct fsl_mqs_soc_data fsl_mqs_imx8qm_data = { @@ -390,7 +385,7 @@ static struct platform_driver fsl_mqs_driver = { .driver = { .name = "fsl-mqs", .of_match_table = fsl_mqs_dt_ids, - .pm = &fsl_mqs_pm_ops, + .pm = pm_ptr(&fsl_mqs_pm_ops), }, }; diff --git a/sound/soc/fsl/fsl_rpmsg.c b/sound/soc/fsl/fsl_rpmsg.c index 467d6bc9f95667..be46fbfd487ad6 100644 --- a/sound/soc/fsl/fsl_rpmsg.c +++ b/sound/soc/fsl/fsl_rpmsg.c @@ -286,7 +286,6 @@ static void fsl_rpmsg_remove(struct platform_device *pdev) platform_device_unregister(rpmsg->card_pdev); } -#ifdef CONFIG_PM static int fsl_rpmsg_runtime_resume(struct device *dev) { struct fsl_rpmsg *rpmsg = dev_get_drvdata(dev); @@ -321,12 +320,10 @@ static int fsl_rpmsg_runtime_suspend(struct device *dev) return 0; } -#endif static const struct dev_pm_ops fsl_rpmsg_pm_ops = { - SET_RUNTIME_PM_OPS(fsl_rpmsg_runtime_suspend, - fsl_rpmsg_runtime_resume, - NULL) + RUNTIME_PM_OPS(fsl_rpmsg_runtime_suspend, fsl_rpmsg_runtime_resume, + NULL) }; static struct platform_driver fsl_rpmsg_driver = { @@ -334,7 +331,7 @@ static struct platform_driver fsl_rpmsg_driver = { .remove_new = fsl_rpmsg_remove, .driver = { .name = "fsl_rpmsg", - .pm = &fsl_rpmsg_pm_ops, + .pm = pm_ptr(&fsl_rpmsg_pm_ops), .of_match_table = fsl_rpmsg_ids, }, }; diff --git a/sound/soc/fsl/fsl_spdif.c b/sound/soc/fsl/fsl_spdif.c index a63121c888e02a..eace399cb064cc 100644 --- a/sound/soc/fsl/fsl_spdif.c +++ b/sound/soc/fsl/fsl_spdif.c @@ -1667,7 +1667,6 @@ static void fsl_spdif_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); } -#ifdef CONFIG_PM static int fsl_spdif_runtime_suspend(struct device *dev) { struct fsl_spdif_priv *spdif_priv = dev_get_drvdata(dev); @@ -1739,13 +1738,11 @@ static int fsl_spdif_runtime_resume(struct device *dev) return ret; } -#endif /* CONFIG_PM */ static const struct dev_pm_ops fsl_spdif_pm = { - SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, - pm_runtime_force_resume) - SET_RUNTIME_PM_OPS(fsl_spdif_runtime_suspend, fsl_spdif_runtime_resume, - NULL) + SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) + RUNTIME_PM_OPS(fsl_spdif_runtime_suspend, fsl_spdif_runtime_resume, + NULL) }; static const struct of_device_id fsl_spdif_dt_ids[] = { @@ -1763,7 +1760,7 @@ static struct platform_driver fsl_spdif_driver = { .driver = { .name = "fsl-spdif-dai", .of_match_table = fsl_spdif_dt_ids, - .pm = &fsl_spdif_pm, + .pm = pm_ptr(&fsl_spdif_pm), }, .probe = fsl_spdif_probe, .remove_new = fsl_spdif_remove, diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index 4ca3a16f7ac0d4..c4c1d9c44056a8 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c @@ -1693,7 +1693,6 @@ static void fsl_ssi_remove(struct platform_device *pdev) } } -#ifdef CONFIG_PM_SLEEP static int fsl_ssi_suspend(struct device *dev) { struct fsl_ssi *ssi = dev_get_drvdata(dev); @@ -1723,17 +1722,16 @@ static int fsl_ssi_resume(struct device *dev) return regcache_sync(regs); } -#endif /* CONFIG_PM_SLEEP */ static const struct dev_pm_ops fsl_ssi_pm = { - SET_SYSTEM_SLEEP_PM_OPS(fsl_ssi_suspend, fsl_ssi_resume) + SYSTEM_SLEEP_PM_OPS(fsl_ssi_suspend, fsl_ssi_resume) }; static struct platform_driver fsl_ssi_driver = { .driver = { .name = "fsl-ssi-dai", .of_match_table = fsl_ssi_ids, - .pm = &fsl_ssi_pm, + .pm = pm_sleep_ptr(&fsl_ssi_pm), }, .probe = fsl_ssi_probe, .remove_new = fsl_ssi_remove, diff --git a/sound/soc/fsl/fsl_xcvr.c b/sound/soc/fsl/fsl_xcvr.c index bf9a4e90978ef1..c98e3db74fe710 100644 --- a/sound/soc/fsl/fsl_xcvr.c +++ b/sound/soc/fsl/fsl_xcvr.c @@ -186,7 +186,7 @@ static int fsl_xcvr_activate_ctl(struct snd_soc_dai *dai, const char *name, lockdep_assert_held(&card->snd_card->controls_rwsem); - kctl = snd_soc_card_get_kcontrol_locked(card, name); + kctl = snd_soc_card_get_kcontrol(card, name); if (kctl == NULL) return -ENOENT; diff --git a/sound/soc/fsl/imx-audmux.c b/sound/soc/fsl/imx-audmux.c index 747ab2f1aae3a4..f97ae14dc452ac 100644 --- a/sound/soc/fsl/imx-audmux.c +++ b/sound/soc/fsl/imx-audmux.c @@ -320,7 +320,6 @@ static void imx_audmux_remove(struct platform_device *pdev) audmux_debugfs_remove(); } -#ifdef CONFIG_PM_SLEEP static int imx_audmux_suspend(struct device *dev) { int i; @@ -348,10 +347,9 @@ static int imx_audmux_resume(struct device *dev) return 0; } -#endif /* CONFIG_PM_SLEEP */ static const struct dev_pm_ops imx_audmux_pm = { - SET_SYSTEM_SLEEP_PM_OPS(imx_audmux_suspend, imx_audmux_resume) + SYSTEM_SLEEP_PM_OPS(imx_audmux_suspend, imx_audmux_resume) }; static struct platform_driver imx_audmux_driver = { @@ -359,7 +357,7 @@ static struct platform_driver imx_audmux_driver = { .remove_new = imx_audmux_remove, .driver = { .name = DRIVER_NAME, - .pm = &imx_audmux_pm, + .pm = pm_sleep_ptr(&imx_audmux_pm), .of_match_table = imx_audmux_dt_ids, } }; diff --git a/sound/soc/fsl/imx-pcm-rpmsg.c b/sound/soc/fsl/imx-pcm-rpmsg.c index b0944a07ab470a..22156f99dceeae 100644 --- a/sound/soc/fsl/imx-pcm-rpmsg.c +++ b/sound/soc/fsl/imx-pcm-rpmsg.c @@ -753,7 +753,6 @@ static void imx_rpmsg_pcm_remove(struct platform_device *pdev) destroy_workqueue(info->rpmsg_wq); } -#ifdef CONFIG_PM static int imx_rpmsg_pcm_runtime_resume(struct device *dev) { struct rpmsg_info *info = dev_get_drvdata(dev); @@ -771,9 +770,7 @@ static int imx_rpmsg_pcm_runtime_suspend(struct device *dev) return 0; } -#endif -#ifdef CONFIG_PM_SLEEP static int imx_rpmsg_pcm_suspend(struct device *dev) { struct rpmsg_info *info = dev_get_drvdata(dev); @@ -809,14 +806,11 @@ static int imx_rpmsg_pcm_resume(struct device *dev) return 0; } -#endif /* CONFIG_PM_SLEEP */ static const struct dev_pm_ops imx_rpmsg_pcm_pm_ops = { - SET_RUNTIME_PM_OPS(imx_rpmsg_pcm_runtime_suspend, - imx_rpmsg_pcm_runtime_resume, - NULL) - SET_SYSTEM_SLEEP_PM_OPS(imx_rpmsg_pcm_suspend, - imx_rpmsg_pcm_resume) + RUNTIME_PM_OPS(imx_rpmsg_pcm_runtime_suspend, + imx_rpmsg_pcm_runtime_resume, NULL) + SYSTEM_SLEEP_PM_OPS(imx_rpmsg_pcm_suspend, imx_rpmsg_pcm_resume) }; static const struct platform_device_id imx_rpmsg_pcm_id_table[] = { @@ -832,7 +826,7 @@ static struct platform_driver imx_pcm_rpmsg_driver = { .id_table = imx_rpmsg_pcm_id_table, .driver = { .name = IMX_PCM_DRV_NAME, - .pm = &imx_rpmsg_pcm_pm_ops, + .pm = pm_ptr(&imx_rpmsg_pcm_pm_ops), }, }; module_platform_driver(imx_pcm_rpmsg_driver); diff --git a/sound/soc/generic/test-component.c b/sound/soc/generic/test-component.c index e9e5e235a8a659..df2487b700cca0 100644 --- a/sound/soc/generic/test-component.c +++ b/sound/soc/generic/test-component.c @@ -181,14 +181,6 @@ static int test_dai_trigger(struct snd_pcm_substream *substream, int cmd, struct return 0; } -static int test_dai_bespoke_trigger(struct snd_pcm_substream *substream, - int cmd, struct snd_soc_dai *dai) -{ - mile_stone(dai); - - return 0; -} - static const u64 test_dai_formats = /* * Select below from Sound Card, not auto @@ -228,7 +220,6 @@ static const struct snd_soc_dai_ops test_verbose_ops = { .hw_params = test_dai_hw_params, .hw_free = test_dai_hw_free, .trigger = test_dai_trigger, - .bespoke_trigger = test_dai_bespoke_trigger, .auto_selectable_formats = &test_dai_formats, .num_auto_selectable_formats = 1, }; diff --git a/sound/soc/intel/Kconfig b/sound/soc/intel/Kconfig index 38b61dfd1487fb..a32fb0a8d7d7cc 100644 --- a/sound/soc/intel/Kconfig +++ b/sound/soc/intel/Kconfig @@ -67,126 +67,6 @@ config SND_SST_ATOM_HIFI2_PLATFORM_ACPI Baytrail/Cherrytrail. If you want to enable SOF on Baytrail/Cherrytrail, you need to deselect this option first. -config SND_SOC_INTEL_SKYLAKE - tristate "All Skylake/SST Platforms" - depends on PCI && ACPI - depends on COMMON_CLK - select SND_SOC_INTEL_SKL - select SND_SOC_INTEL_APL - select SND_SOC_INTEL_KBL - select SND_SOC_INTEL_GLK - select SND_SOC_INTEL_CNL - select SND_SOC_INTEL_CFL - help - This is a backwards-compatible option to select all devices - supported by the Intel SST/Skylake driver. This option is no - longer recommended and will be deprecated when the SOF - driver is introduced. Distributions should explicitly - select which platform uses this driver. - -config SND_SOC_INTEL_SKL - tristate "Skylake Platforms" - depends on PCI && ACPI - depends on COMMON_CLK - select SND_SOC_INTEL_SKYLAKE_FAMILY - help - If you have a Intel Skylake platform with the DSP enabled - in the BIOS then enable this option by saying Y or m. - -config SND_SOC_INTEL_APL - tristate "Broxton/ApolloLake Platforms" - depends on PCI && ACPI - depends on COMMON_CLK - select SND_SOC_INTEL_SKYLAKE_FAMILY - help - If you have a Intel Broxton/ApolloLake platform with the DSP - enabled in the BIOS then enable this option by saying Y or m. - -config SND_SOC_INTEL_KBL - tristate "Kabylake Platforms" - depends on PCI && ACPI - depends on COMMON_CLK - select SND_SOC_INTEL_SKYLAKE_FAMILY - help - If you have a Intel Kabylake platform with the DSP - enabled in the BIOS then enable this option by saying Y or m. - -config SND_SOC_INTEL_GLK - tristate "GeminiLake Platforms" - depends on PCI && ACPI - depends on COMMON_CLK - select SND_SOC_INTEL_SKYLAKE_FAMILY - help - If you have a Intel GeminiLake platform with the DSP - enabled in the BIOS then enable this option by saying Y or m. - -config SND_SOC_INTEL_CNL - tristate "CannonLake/WhiskyLake Platforms" - depends on PCI && ACPI - depends on COMMON_CLK - select SND_SOC_INTEL_SKYLAKE_FAMILY - help - If you have a Intel CNL/WHL platform with the DSP - enabled in the BIOS then enable this option by saying Y or m. - -config SND_SOC_INTEL_CFL - tristate "CoffeeLake Platforms" - depends on PCI && ACPI - depends on COMMON_CLK - select SND_SOC_INTEL_SKYLAKE_FAMILY - help - If you have a Intel CoffeeLake platform with the DSP - enabled in the BIOS then enable this option by saying Y or m. - -config SND_SOC_INTEL_CML_H - tristate "CometLake-H Platforms" - depends on PCI && ACPI - depends on COMMON_CLK - select SND_SOC_INTEL_SKYLAKE_FAMILY - help - If you have a Intel CometLake-H platform with the DSP - enabled in the BIOS then enable this option by saying Y or m. - -config SND_SOC_INTEL_CML_LP - tristate "CometLake-LP Platforms" - depends on PCI && ACPI - depends on COMMON_CLK - select SND_SOC_INTEL_SKYLAKE_FAMILY - help - If you have a Intel CometLake-LP platform with the DSP - enabled in the BIOS then enable this option by saying Y or m. - -config SND_SOC_INTEL_SKYLAKE_FAMILY - tristate - select SND_SOC_INTEL_SKYLAKE_COMMON - -if SND_SOC_INTEL_SKYLAKE_FAMILY - -config SND_SOC_INTEL_SKYLAKE_SSP_CLK - tristate - -config SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC - bool "HDAudio codec support" - help - If you have Intel Skylake or Kabylake with HDAudio codec - and DMIC present then enable this option by saying Y. - -config SND_SOC_INTEL_SKYLAKE_COMMON - tristate - select SND_HDA_EXT_CORE - select SND_HDA_DSP_LOADER - select SND_SOC_TOPOLOGY - select SND_SOC_INTEL_SST - select SND_SOC_HDAC_HDA - select SND_SOC_ACPI_INTEL_MATCH - select SND_INTEL_DSP_CONFIG - help - If you have a Intel Skylake/Broxton/ApolloLake/KabyLake/ - GeminiLake or CannonLake platform with the DSP enabled in the BIOS - then enable this option by saying Y or m. - -endif ## SND_SOC_INTEL_SKYLAKE_FAMILY - endif ## SND_SOC_INTEL_SST_TOPLEVEL if SND_SOC_INTEL_SST_TOPLEVEL || SND_SOC_SOF_INTEL_TOPLEVEL diff --git a/sound/soc/intel/Makefile b/sound/soc/intel/Makefile index d44b2652c707c8..8ecc7047d700a7 100644 --- a/sound/soc/intel/Makefile +++ b/sound/soc/intel/Makefile @@ -5,7 +5,6 @@ obj-$(CONFIG_SND_SOC) += common/ # Platform Support obj-$(CONFIG_SND_SST_ATOM_HIFI2_PLATFORM) += atom/ obj-$(CONFIG_SND_SOC_INTEL_CATPT) += catpt/ -obj-$(CONFIG_SND_SOC_INTEL_SKYLAKE_COMMON) += skylake/ obj-$(CONFIG_SND_SOC_INTEL_KEEMBAY) += keembay/ obj-$(CONFIG_SND_SOC_INTEL_AVS) += avs/ diff --git a/sound/soc/intel/avs/core.c b/sound/soc/intel/avs/core.c index f2dc82a2abc717..da7bac09acb4eb 100644 --- a/sound/soc/intel/avs/core.c +++ b/sound/soc/intel/avs/core.c @@ -422,8 +422,14 @@ static int avs_pci_probe(struct pci_dev *pci, const struct pci_device_id *id) int ret; ret = snd_intel_dsp_driver_probe(pci); - if (ret != SND_INTEL_DSP_DRIVER_ANY && ret != SND_INTEL_DSP_DRIVER_AVS) + switch (ret) { + case SND_INTEL_DSP_DRIVER_ANY: + case SND_INTEL_DSP_DRIVER_SST: + case SND_INTEL_DSP_DRIVER_AVS: + break; + default: return -ENODEV; + } ret = pcim_enable_device(pci); if (ret < 0) diff --git a/sound/soc/intel/boards/Kconfig b/sound/soc/intel/boards/Kconfig index 1a0bfd57d5260d..793a9170513aac 100644 --- a/sound/soc/intel/boards/Kconfig +++ b/sound/soc/intel/boards/Kconfig @@ -252,51 +252,6 @@ config SND_SOC_INTEL_BYT_CHT_NOCODEC_MACH endif ## SND_SST_ATOM_HIFI2_PLATFORM -if SND_SOC_INTEL_SKL - -config SND_SOC_INTEL_SKL_RT286_MACH - tristate "SKL with RT286 I2S mode" - depends on I2C && ACPI - depends on MFD_INTEL_LPSS || COMPILE_TEST - select SND_SOC_RT286 - select SND_SOC_DMIC - select SND_SOC_HDAC_HDMI - help - This adds support for ASoC machine driver for Skylake platforms - with RT286 I2S audio codec. - Say Y or m if you have such a device. - If unsure select "N". - -config SND_SOC_INTEL_SKL_NAU88L25_SSM4567_MACH - tristate "SKL with NAU88L25 and SSM4567 in I2S Mode" - depends on I2C && ACPI - depends on MFD_INTEL_LPSS || COMPILE_TEST - select SND_SOC_NAU8825 - select SND_SOC_SSM4567 - select SND_SOC_DMIC - select SND_SOC_HDAC_HDMI - help - This adds support for ASoC Onboard Codec I2S machine driver. This will - create an alsa sound card for NAU88L25 + SSM4567. - Say Y or m if you have such a device. This is a recommended option. - If unsure select "N". - -config SND_SOC_INTEL_SKL_NAU88L25_MAX98357A_MACH - tristate "SKL with NAU88L25 and MAX98357A in I2S Mode" - depends on I2C && ACPI - depends on MFD_INTEL_LPSS || COMPILE_TEST - select SND_SOC_NAU8825 - select SND_SOC_MAX98357A - select SND_SOC_DMIC - select SND_SOC_HDAC_HDMI - help - This adds support for ASoC Onboard Codec I2S machine driver. This will - create an alsa sound card for NAU88L25 + MAX98357A. - Say Y or m if you have such a device. This is a recommended option. - If unsure select "N". - -endif ## SND_SOC_INTEL_SKL - config SND_SOC_INTEL_DA7219_MAX98357A_GENERIC tristate select SND_SOC_DA7219 @@ -305,36 +260,6 @@ config SND_SOC_INTEL_DA7219_MAX98357A_GENERIC select SND_SOC_HDAC_HDMI select SND_SOC_INTEL_HDA_DSP_COMMON -if SND_SOC_INTEL_APL - -config SND_SOC_INTEL_BXT_DA7219_MAX98357A_MACH - tristate "Broxton with DA7219 and MAX98357A in I2S Mode" - depends on I2C && ACPI - depends on MFD_INTEL_LPSS || COMPILE_TEST - depends on SND_HDA_CODEC_HDMI - select SND_SOC_INTEL_DA7219_MAX98357A_GENERIC - help - This adds support for ASoC machine driver for Broxton-P platforms - with DA7219 + MAX98357A I2S audio codec. - Say Y or m if you have such a device. This is a recommended option. - If unsure select "N". - -config SND_SOC_INTEL_BXT_RT298_MACH - tristate "Broxton with RT298 I2S mode" - depends on I2C && ACPI - depends on MFD_INTEL_LPSS || COMPILE_TEST - select SND_SOC_RT298 - select SND_SOC_DMIC - select SND_SOC_HDAC_HDMI - select SND_SOC_INTEL_HDA_DSP_COMMON - help - This adds support for ASoC machine driver for Broxton platforms - with RT286 I2S audio codec. - Say Y or m if you have such a device. This is a recommended option. - If unsure select "N". - -endif ## SND_SOC_INTEL_APL - if SND_SOC_SOF_APOLLOLAKE config SND_SOC_INTEL_SOF_WM8804_MACH @@ -351,79 +276,6 @@ config SND_SOC_INTEL_SOF_WM8804_MACH endif ## SND_SOC_SOF_APOLLOLAKE -if SND_SOC_INTEL_KBL - -config SND_SOC_INTEL_KBL_RT5663_MAX98927_MACH - tristate "KBL with RT5663 and MAX98927 in I2S Mode" - depends on I2C && ACPI - depends on MFD_INTEL_LPSS || COMPILE_TEST - select SND_SOC_RT5663 - select SND_SOC_MAX98927 - select SND_SOC_DMIC - select SND_SOC_HDAC_HDMI - select SND_SOC_INTEL_SKYLAKE_SSP_CLK - help - This adds support for ASoC Onboard Codec I2S machine driver. This will - create an alsa sound card for RT5663 + MAX98927. - Say Y or m if you have such a device. This is a recommended option. - If unsure select "N". - -config SND_SOC_INTEL_KBL_RT5663_RT5514_MAX98927_MACH - tristate "KBL with RT5663, RT5514 and MAX98927 in I2S Mode" - depends on I2C && ACPI - depends on MFD_INTEL_LPSS || COMPILE_TEST - depends on SPI - select SND_SOC_RT5663 - select SND_SOC_RT5514 - select SND_SOC_RT5514_SPI - select SND_SOC_MAX98927 - select SND_SOC_HDAC_HDMI - select SND_SOC_INTEL_SKYLAKE_SSP_CLK - help - This adds support for ASoC Onboard Codec I2S machine driver. This will - create an alsa sound card for RT5663 + RT5514 + MAX98927. - Say Y or m if you have such a device. This is a recommended option. - If unsure select "N". - -config SND_SOC_INTEL_KBL_DA7219_MAX98357A_MACH - tristate "KBL with DA7219 and MAX98357A in I2S Mode" - depends on I2C && ACPI - depends on MFD_INTEL_LPSS || COMPILE_TEST - select SND_SOC_INTEL_DA7219_MAX98357A_GENERIC - help - This adds support for ASoC Onboard Codec I2S machine driver. This will - create an alsa sound card for DA7219 + MAX98357A I2S audio codec. - Say Y if you have such a device. - -config SND_SOC_INTEL_KBL_DA7219_MAX98927_MACH - tristate "KBL with DA7219 and MAX98927 in I2S Mode" - depends on I2C && ACPI - depends on MFD_INTEL_LPSS || COMPILE_TEST - select SND_SOC_DA7219 - select SND_SOC_MAX98927 - select SND_SOC_MAX98373_I2C - select SND_SOC_DMIC - select SND_SOC_HDAC_HDMI - help - This adds support for ASoC Onboard Codec I2S machine driver. This will - create an alsa sound card for DA7219 + MAX98927 I2S audio codec. - Say Y if you have such a device. - If unsure select "N". - -config SND_SOC_INTEL_KBL_RT5660_MACH - tristate "KBL with RT5660 in I2S Mode" - depends on I2C && ACPI - depends on MFD_INTEL_LPSS || COMPILE_TEST - depends on GPIOLIB || COMPILE_TEST - select SND_SOC_RT5660 - select SND_SOC_HDAC_HDMI - help - This adds support for ASoC Onboard Codec I2S machine driver. This will - create an alsa sound card for RT5660 I2S audio codec. - Say Y if you have such a device. - -endif ## SND_SOC_INTEL_KBL - if SND_SOC_SOF_GEMINILAKE config SND_SOC_INTEL_GLK_DA7219_MAX98357A_MACH @@ -448,7 +300,7 @@ config SND_SOC_INTEL_GLK_RT5682_MAX98357A_MACH endif ## SND_SOC_SOF_GEMINILAKE -if SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC || SND_SOC_SOF_HDA_AUDIO_CODEC +if SND_SOC_SOF_HDA_AUDIO_CODEC config SND_SOC_INTEL_SKL_HDA_DSP_GENERIC_MACH tristate "Skylake+ with HDA Codecs" @@ -463,7 +315,7 @@ config SND_SOC_INTEL_SKL_HDA_DSP_GENERIC_MACH Say Y or m if you have such a device. This is a recommended option. If unsure select "N". -endif ## SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC || SND_SOC_SOF_HDA_AUDIO_CODEC +endif ## SND_SOC_SOF_HDA_AUDIO_CODEC if SND_SOC_SOF_HDA_LINK || SND_SOC_SOF_BAYTRAIL config SND_SOC_INTEL_SOF_RT5682_MACH diff --git a/sound/soc/intel/boards/Makefile b/sound/soc/intel/boards/Makefile index 5bd8dc2d166a67..9b24de731332bd 100644 --- a/sound/soc/intel/boards/Makefile +++ b/sound/soc/intel/boards/Makefile @@ -3,8 +3,6 @@ snd-soc-hsw-rt5640-y := hsw_rt5640.o snd-soc-sst-bdw-rt5650-mach-y := bdw-rt5650.o snd-soc-sst-bdw-rt5677-mach-y := bdw-rt5677.o snd-soc-bdw-rt286-y := bdw_rt286.o -snd-soc-sst-bxt-da7219_max98357a-y := bxt_da7219_max98357a.o -snd-soc-sst-bxt-rt298-y := bxt_rt298.o snd-soc-sst-sof-pcm512x-y := sof_pcm512x.o snd-soc-sst-sof-wm8804-y := sof_wm8804.o snd-soc-sst-bytcr-rt5640-y := bytcr_rt5640.o @@ -23,15 +21,7 @@ snd-soc-sof_cs42l42-y := sof_cs42l42.o snd-soc-sof_es8336-y := sof_es8336.o snd-soc-sof_nau8825-y := sof_nau8825.o snd-soc-sof_da7219-y := sof_da7219.o -snd-soc-kbl_da7219_max98357a-y := kbl_da7219_max98357a.o -snd-soc-kbl_da7219_max98927-y := kbl_da7219_max98927.o -snd-soc-kbl_rt5663_max98927-y := kbl_rt5663_max98927.o -snd-soc-kbl_rt5663_rt5514_max98927-y := kbl_rt5663_rt5514_max98927.o -snd-soc-kbl_rt5660-y := kbl_rt5660.o -snd-soc-skl_rt286-y := skl_rt286.o snd-soc-skl_hda_dsp-y := skl_hda_dsp_generic.o skl_hda_dsp_common.o -snd-skl_nau88l25_max98357a-y := skl_nau88l25_max98357a.o -snd-soc-skl_nau88l25_ssm4567-y := skl_nau88l25_ssm4567.o snd-soc-ehl-rt5660-y := ehl_rt5660.o snd-soc-sof-ssp-amp-y := sof_ssp_amp.o snd-soc-sof-sdw-y += sof_sdw.o \ @@ -42,8 +32,6 @@ obj-$(CONFIG_SND_SOC_INTEL_SOF_ES8336_MACH) += snd-soc-sof_es8336.o obj-$(CONFIG_SND_SOC_INTEL_SOF_NAU8825_MACH) += snd-soc-sof_nau8825.o obj-$(CONFIG_SND_SOC_INTEL_SOF_DA7219_MACH) += snd-soc-sof_da7219.o obj-$(CONFIG_SND_SOC_INTEL_HASWELL_MACH) += snd-soc-hsw-rt5640.o -obj-$(CONFIG_SND_SOC_INTEL_BXT_DA7219_MAX98357A_MACH) += snd-soc-sst-bxt-da7219_max98357a.o -obj-$(CONFIG_SND_SOC_INTEL_BXT_RT298_MACH) += snd-soc-sst-bxt-rt298.o obj-$(CONFIG_SND_SOC_INTEL_SOF_PCM512x_MACH) += snd-soc-sst-sof-pcm512x.o obj-$(CONFIG_SND_SOC_INTEL_SOF_WM8804_MACH) += snd-soc-sst-sof-wm8804.o obj-$(CONFIG_SND_SOC_INTEL_BROADWELL_MACH) += snd-soc-bdw-rt286.o @@ -60,14 +48,6 @@ obj-$(CONFIG_SND_SOC_INTEL_BYT_CHT_CX2072X_MACH) += snd-soc-sst-byt-cht-cx2072x. obj-$(CONFIG_SND_SOC_INTEL_BYT_CHT_DA7213_MACH) += snd-soc-sst-byt-cht-da7213.o obj-$(CONFIG_SND_SOC_INTEL_BYT_CHT_ES8316_MACH) += snd-soc-sst-byt-cht-es8316.o obj-$(CONFIG_SND_SOC_INTEL_BYT_CHT_NOCODEC_MACH) += snd-soc-sst-byt-cht-nocodec.o -obj-$(CONFIG_SND_SOC_INTEL_KBL_DA7219_MAX98357A_MACH) += snd-soc-kbl_da7219_max98357a.o -obj-$(CONFIG_SND_SOC_INTEL_KBL_DA7219_MAX98927_MACH) += snd-soc-kbl_da7219_max98927.o -obj-$(CONFIG_SND_SOC_INTEL_KBL_RT5663_MAX98927_MACH) += snd-soc-kbl_rt5663_max98927.o -obj-$(CONFIG_SND_SOC_INTEL_KBL_RT5663_RT5514_MAX98927_MACH) += snd-soc-kbl_rt5663_rt5514_max98927.o -obj-$(CONFIG_SND_SOC_INTEL_KBL_RT5660_MACH) += snd-soc-kbl_rt5660.o -obj-$(CONFIG_SND_SOC_INTEL_SKL_RT286_MACH) += snd-soc-skl_rt286.o -obj-$(CONFIG_SND_SOC_INTEL_SKL_NAU88L25_MAX98357A_MACH) += snd-skl_nau88l25_max98357a.o -obj-$(CONFIG_SND_SOC_INTEL_SKL_NAU88L25_SSM4567_MACH) += snd-soc-skl_nau88l25_ssm4567.o obj-$(CONFIG_SND_SOC_INTEL_SKL_HDA_DSP_GENERIC_MACH) += snd-soc-skl_hda_dsp.o obj-$(CONFIG_SND_SOC_INTEL_EHL_RT5660_MACH) += snd-soc-ehl-rt5660.o obj-$(CONFIG_SND_SOC_INTEL_SOUNDWIRE_SOF_MACH) += snd-soc-sof-sdw.o diff --git a/sound/soc/intel/boards/bxt_da7219_max98357a.c b/sound/soc/intel/boards/bxt_da7219_max98357a.c deleted file mode 100644 index e1082bfe5ca9a0..00000000000000 --- a/sound/soc/intel/boards/bxt_da7219_max98357a.c +++ /dev/null @@ -1,720 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Intel Broxton-P I2S Machine Driver - * - * Copyright (C) 2016, Intel Corporation - * - * Modified from: - * Intel Skylake I2S Machine driver - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "../../codecs/hdac_hdmi.h" -#include "../../codecs/da7219.h" -#include "../common/soc-intel-quirks.h" -#include "hda_dsp_common.h" - -#define BXT_DIALOG_CODEC_DAI "da7219-hifi" -#define BXT_MAXIM_CODEC_DAI "HiFi" -#define DUAL_CHANNEL 2 -#define QUAD_CHANNEL 4 - -static struct snd_soc_jack broxton_headset; -static struct snd_soc_jack broxton_hdmi[3]; - -struct bxt_hdmi_pcm { - struct list_head head; - struct snd_soc_dai *codec_dai; - int device; -}; - -struct bxt_card_private { - struct list_head hdmi_pcm_list; - bool common_hdmi_codec_drv; -}; - -enum { - BXT_DPCM_AUDIO_PB = 0, - BXT_DPCM_AUDIO_CP, - BXT_DPCM_AUDIO_HS_PB, - BXT_DPCM_AUDIO_REF_CP, - BXT_DPCM_AUDIO_DMIC_CP, - BXT_DPCM_AUDIO_HDMI1_PB, - BXT_DPCM_AUDIO_HDMI2_PB, - BXT_DPCM_AUDIO_HDMI3_PB, -}; - -static int platform_clock_control(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *k, int event) -{ - int ret = 0; - struct snd_soc_dapm_context *dapm = w->dapm; - struct snd_soc_card *card = dapm->card; - struct snd_soc_dai *codec_dai; - - codec_dai = snd_soc_card_get_codec_dai(card, BXT_DIALOG_CODEC_DAI); - if (!codec_dai) { - dev_err(card->dev, "Codec dai not found; Unable to set/unset codec pll\n"); - return -EIO; - } - - if (SND_SOC_DAPM_EVENT_OFF(event)) { - ret = snd_soc_dai_set_pll(codec_dai, 0, - DA7219_SYSCLK_MCLK, 0, 0); - if (ret) - dev_err(card->dev, "failed to stop PLL: %d\n", ret); - } else if(SND_SOC_DAPM_EVENT_ON(event)) { - ret = snd_soc_dai_set_pll(codec_dai, 0, - DA7219_SYSCLK_PLL_SRM, 0, DA7219_PLL_FREQ_OUT_98304); - if (ret) - dev_err(card->dev, "failed to start PLL: %d\n", ret); - } - - return ret; -} - -static const struct snd_kcontrol_new broxton_controls[] = { - SOC_DAPM_PIN_SWITCH("Headphone Jack"), - SOC_DAPM_PIN_SWITCH("Headset Mic"), - SOC_DAPM_PIN_SWITCH("Line Out"), - SOC_DAPM_PIN_SWITCH("Spk"), -}; - -static const struct snd_soc_dapm_widget broxton_widgets[] = { - SND_SOC_DAPM_HP("Headphone Jack", NULL), - SND_SOC_DAPM_MIC("Headset Mic", NULL), - SND_SOC_DAPM_LINE("Line Out", NULL), - SND_SOC_DAPM_MIC("SoC DMIC", NULL), - SND_SOC_DAPM_SPK("HDMI1", NULL), - SND_SOC_DAPM_SPK("HDMI2", NULL), - SND_SOC_DAPM_SPK("HDMI3", NULL), - SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0, - platform_clock_control, SND_SOC_DAPM_POST_PMD|SND_SOC_DAPM_PRE_PMU), - SND_SOC_DAPM_SPK("Spk", NULL), -}; - -static const struct snd_soc_dapm_route audio_map[] = { - /* HP jack connectors - unknown if we have jack detection */ - {"Headphone Jack", NULL, "HPL"}, - {"Headphone Jack", NULL, "HPR"}, - - /* other jacks */ - {"MIC", NULL, "Headset Mic"}, - - /* digital mics */ - {"DMic", NULL, "SoC DMIC"}, - - /* CODEC BE connections */ - {"HDMI1", NULL, "hif5-0 Output"}, - {"HDMI2", NULL, "hif6-0 Output"}, - {"HDMI2", NULL, "hif7-0 Output"}, - - {"hifi3", NULL, "iDisp3 Tx"}, - {"iDisp3 Tx", NULL, "iDisp3_out"}, - {"hifi2", NULL, "iDisp2 Tx"}, - {"iDisp2 Tx", NULL, "iDisp2_out"}, - {"hifi1", NULL, "iDisp1 Tx"}, - {"iDisp1 Tx", NULL, "iDisp1_out"}, - - /* DMIC */ - {"dmic01_hifi", NULL, "DMIC01 Rx"}, - {"DMIC01 Rx", NULL, "DMIC AIF"}, - - { "Headphone Jack", NULL, "Platform Clock" }, - { "Headset Mic", NULL, "Platform Clock" }, - { "Line Out", NULL, "Platform Clock" }, - - /* speaker */ - {"Spk", NULL, "Speaker"}, - - {"HiFi Playback", NULL, "ssp5 Tx"}, - {"ssp5 Tx", NULL, "codec0_out"}, - - {"Playback", NULL, "ssp1 Tx"}, - {"ssp1 Tx", NULL, "codec1_out"}, - - {"codec0_in", NULL, "ssp1 Rx"}, - {"ssp1 Rx", NULL, "Capture"}, -}; - -static struct snd_soc_jack_pin jack_pins[] = { - { - .pin = "Headphone Jack", - .mask = SND_JACK_HEADPHONE, - }, - { - .pin = "Headset Mic", - .mask = SND_JACK_MICROPHONE, - }, - { - .pin = "Line Out", - .mask = SND_JACK_LINEOUT, - }, -}; - -static int broxton_ssp_fixup(struct snd_soc_pcm_runtime *rtd, - struct snd_pcm_hw_params *params) -{ - struct snd_interval *rate = hw_param_interval(params, - SNDRV_PCM_HW_PARAM_RATE); - struct snd_interval *chan = hw_param_interval(params, - SNDRV_PCM_HW_PARAM_CHANNELS); - struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); - - /* The ADSP will convert the FE rate to 48k, stereo */ - rate->min = rate->max = 48000; - chan->min = chan->max = DUAL_CHANNEL; - - /* set SSP to 24 bit */ - snd_mask_none(fmt); - snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S24_LE); - - return 0; -} - -static int broxton_da7219_codec_init(struct snd_soc_pcm_runtime *rtd) -{ - int ret; - struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); - struct snd_soc_component *component = snd_soc_rtd_to_codec(rtd, 0)->component; - int clk_freq; - - /* Configure sysclk for codec */ - clk_freq = 19200000; - - ret = snd_soc_dai_set_sysclk(codec_dai, DA7219_CLKSRC_MCLK, clk_freq, - SND_SOC_CLOCK_IN); - - if (ret) { - dev_err(rtd->dev, "can't set codec sysclk configuration\n"); - return ret; - } - - /* - * Headset buttons map to the google Reference headset. - * These can be configured by userspace. - */ - ret = snd_soc_card_jack_new_pins(rtd->card, "Headset Jack", - SND_JACK_HEADSET | SND_JACK_BTN_0 | SND_JACK_BTN_1 | - SND_JACK_BTN_2 | SND_JACK_BTN_3 | SND_JACK_LINEOUT, - &broxton_headset, - jack_pins, - ARRAY_SIZE(jack_pins)); - if (ret) { - dev_err(rtd->dev, "Headset Jack creation failed: %d\n", ret); - return ret; - } - - snd_jack_set_key(broxton_headset.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE); - snd_jack_set_key(broxton_headset.jack, SND_JACK_BTN_1, KEY_VOLUMEUP); - snd_jack_set_key(broxton_headset.jack, SND_JACK_BTN_2, KEY_VOLUMEDOWN); - snd_jack_set_key(broxton_headset.jack, SND_JACK_BTN_3, - KEY_VOICECOMMAND); - - snd_soc_component_set_jack(component, &broxton_headset, NULL); - - snd_soc_dapm_ignore_suspend(&rtd->card->dapm, "SoC DMIC"); - - return ret; -} - -static int broxton_hdmi_init(struct snd_soc_pcm_runtime *rtd) -{ - struct bxt_card_private *ctx = snd_soc_card_get_drvdata(rtd->card); - struct snd_soc_dai *dai = snd_soc_rtd_to_codec(rtd, 0); - struct bxt_hdmi_pcm *pcm; - - pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL); - if (!pcm) - return -ENOMEM; - - pcm->device = BXT_DPCM_AUDIO_HDMI1_PB + dai->id; - pcm->codec_dai = dai; - - list_add_tail(&pcm->head, &ctx->hdmi_pcm_list); - - return 0; -} - -static int broxton_da7219_fe_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_dapm_context *dapm; - struct snd_soc_component *component = snd_soc_rtd_to_cpu(rtd, 0)->component; - - dapm = snd_soc_component_get_dapm(component); - snd_soc_dapm_ignore_suspend(dapm, "Reference Capture"); - - return 0; -} - -static const unsigned int rates[] = { - 48000, -}; - -static const struct snd_pcm_hw_constraint_list constraints_rates = { - .count = ARRAY_SIZE(rates), - .list = rates, - .mask = 0, -}; - -static const unsigned int channels[] = { - DUAL_CHANNEL, -}; - -static const struct snd_pcm_hw_constraint_list constraints_channels = { - .count = ARRAY_SIZE(channels), - .list = channels, - .mask = 0, -}; - -static const unsigned int channels_quad[] = { - QUAD_CHANNEL, -}; - -static const struct snd_pcm_hw_constraint_list constraints_channels_quad = { - .count = ARRAY_SIZE(channels_quad), - .list = channels_quad, - .mask = 0, -}; - -static int bxt_fe_startup(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - - /* - * On this platform for PCM device we support, - * 48Khz - * stereo - * 16 bit audio - */ - - runtime->hw.channels_max = DUAL_CHANNEL; - snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, - &constraints_channels); - - runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE; - snd_pcm_hw_constraint_msbits(runtime, 0, 16, 16); - - snd_pcm_hw_constraint_list(runtime, 0, - SNDRV_PCM_HW_PARAM_RATE, &constraints_rates); - - return 0; -} - -static const struct snd_soc_ops broxton_da7219_fe_ops = { - .startup = bxt_fe_startup, -}; - -static int broxton_dmic_fixup(struct snd_soc_pcm_runtime *rtd, - struct snd_pcm_hw_params *params) -{ - struct snd_interval *chan = hw_param_interval(params, - SNDRV_PCM_HW_PARAM_CHANNELS); - if (params_channels(params) == 2) - chan->min = chan->max = 2; - else - chan->min = chan->max = 4; - - return 0; -} - -static int broxton_dmic_startup(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - - runtime->hw.channels_min = runtime->hw.channels_max = QUAD_CHANNEL; - snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, - &constraints_channels_quad); - - return snd_pcm_hw_constraint_list(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_RATE, &constraints_rates); -} - -static const struct snd_soc_ops broxton_dmic_ops = { - .startup = broxton_dmic_startup, -}; - -static const unsigned int rates_16000[] = { - 16000, -}; - -static const struct snd_pcm_hw_constraint_list constraints_16000 = { - .count = ARRAY_SIZE(rates_16000), - .list = rates_16000, -}; - -static const unsigned int ch_mono[] = { - 1, -}; - -static const struct snd_pcm_hw_constraint_list constraints_refcap = { - .count = ARRAY_SIZE(ch_mono), - .list = ch_mono, -}; - -static int broxton_refcap_startup(struct snd_pcm_substream *substream) -{ - substream->runtime->hw.channels_max = 1; - snd_pcm_hw_constraint_list(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_CHANNELS, - &constraints_refcap); - - return snd_pcm_hw_constraint_list(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_RATE, - &constraints_16000); -}; - -static const struct snd_soc_ops broxton_refcap_ops = { - .startup = broxton_refcap_startup, -}; - -/* broxton digital audio interface glue - connects codec <--> CPU */ -SND_SOC_DAILINK_DEF(dummy, - DAILINK_COMP_ARRAY(COMP_DUMMY())); - -SND_SOC_DAILINK_DEF(system, - DAILINK_COMP_ARRAY(COMP_CPU("System Pin"))); - -SND_SOC_DAILINK_DEF(system2, - DAILINK_COMP_ARRAY(COMP_CPU("System Pin2"))); - -SND_SOC_DAILINK_DEF(reference, - DAILINK_COMP_ARRAY(COMP_CPU("Reference Pin"))); - -SND_SOC_DAILINK_DEF(dmic, - DAILINK_COMP_ARRAY(COMP_CPU("DMIC Pin"))); - -SND_SOC_DAILINK_DEF(hdmi1, - DAILINK_COMP_ARRAY(COMP_CPU("HDMI1 Pin"))); - -SND_SOC_DAILINK_DEF(hdmi2, - DAILINK_COMP_ARRAY(COMP_CPU("HDMI2 Pin"))); - -SND_SOC_DAILINK_DEF(hdmi3, - DAILINK_COMP_ARRAY(COMP_CPU("HDMI3 Pin"))); - - /* Back End DAI */ -SND_SOC_DAILINK_DEF(ssp5_pin, - DAILINK_COMP_ARRAY(COMP_CPU("SSP5 Pin"))); -SND_SOC_DAILINK_DEF(ssp5_codec, - DAILINK_COMP_ARRAY(COMP_CODEC("MX98357A:00", - BXT_MAXIM_CODEC_DAI))); - -SND_SOC_DAILINK_DEF(ssp1_pin, - DAILINK_COMP_ARRAY(COMP_CPU("SSP1 Pin"))); -SND_SOC_DAILINK_DEF(ssp1_codec, - DAILINK_COMP_ARRAY(COMP_CODEC("i2c-DLGS7219:00", - BXT_DIALOG_CODEC_DAI))); - -SND_SOC_DAILINK_DEF(dmic_pin, - DAILINK_COMP_ARRAY(COMP_CPU("DMIC01 Pin"))); - -SND_SOC_DAILINK_DEF(dmic16k_pin, - DAILINK_COMP_ARRAY(COMP_CPU("DMIC16k Pin"))); - -SND_SOC_DAILINK_DEF(dmic_codec, - DAILINK_COMP_ARRAY(COMP_CODEC("dmic-codec", "dmic-hifi"))); - -SND_SOC_DAILINK_DEF(idisp1_pin, - DAILINK_COMP_ARRAY(COMP_CPU("iDisp1 Pin"))); -SND_SOC_DAILINK_DEF(idisp1_codec, - DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi1"))); - -SND_SOC_DAILINK_DEF(idisp2_pin, - DAILINK_COMP_ARRAY(COMP_CPU("iDisp2 Pin"))); -SND_SOC_DAILINK_DEF(idisp2_codec, - DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", - "intel-hdmi-hifi2"))); - -SND_SOC_DAILINK_DEF(idisp3_pin, - DAILINK_COMP_ARRAY(COMP_CPU("iDisp3 Pin"))); -SND_SOC_DAILINK_DEF(idisp3_codec, - DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", - "intel-hdmi-hifi3"))); - -SND_SOC_DAILINK_DEF(platform, - DAILINK_COMP_ARRAY(COMP_PLATFORM("0000:00:0e.0"))); - -static struct snd_soc_dai_link broxton_dais[] = { - /* Front End DAI links */ - [BXT_DPCM_AUDIO_PB] = - { - .name = "Bxt Audio Port", - .stream_name = "Audio", - .dynamic = 1, - .nonatomic = 1, - .init = broxton_da7219_fe_init, - .trigger = { - SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .dpcm_playback = 1, - .ops = &broxton_da7219_fe_ops, - SND_SOC_DAILINK_REG(system, dummy, platform), - }, - [BXT_DPCM_AUDIO_CP] = - { - .name = "Bxt Audio Capture Port", - .stream_name = "Audio Record", - .dynamic = 1, - .nonatomic = 1, - .trigger = { - SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .dpcm_capture = 1, - .ops = &broxton_da7219_fe_ops, - SND_SOC_DAILINK_REG(system, dummy, platform), - }, - [BXT_DPCM_AUDIO_HS_PB] = { - .name = "Bxt Audio Headset Playback", - .stream_name = "Headset Playback", - .dynamic = 1, - .nonatomic = 1, - .trigger = { - SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .dpcm_playback = 1, - .ops = &broxton_da7219_fe_ops, - SND_SOC_DAILINK_REG(system2, dummy, platform), - }, - [BXT_DPCM_AUDIO_REF_CP] = - { - .name = "Bxt Audio Reference cap", - .stream_name = "Refcap", - .init = NULL, - .dpcm_capture = 1, - .nonatomic = 1, - .dynamic = 1, - .ops = &broxton_refcap_ops, - SND_SOC_DAILINK_REG(reference, dummy, platform), - }, - [BXT_DPCM_AUDIO_DMIC_CP] = - { - .name = "Bxt Audio DMIC cap", - .stream_name = "dmiccap", - .init = NULL, - .dpcm_capture = 1, - .nonatomic = 1, - .dynamic = 1, - .ops = &broxton_dmic_ops, - SND_SOC_DAILINK_REG(dmic, dummy, platform), - }, - [BXT_DPCM_AUDIO_HDMI1_PB] = - { - .name = "Bxt HDMI Port1", - .stream_name = "Hdmi1", - .dpcm_playback = 1, - .init = NULL, - .nonatomic = 1, - .dynamic = 1, - SND_SOC_DAILINK_REG(hdmi1, dummy, platform), - }, - [BXT_DPCM_AUDIO_HDMI2_PB] = - { - .name = "Bxt HDMI Port2", - .stream_name = "Hdmi2", - .dpcm_playback = 1, - .init = NULL, - .nonatomic = 1, - .dynamic = 1, - SND_SOC_DAILINK_REG(hdmi2, dummy, platform), - }, - [BXT_DPCM_AUDIO_HDMI3_PB] = - { - .name = "Bxt HDMI Port3", - .stream_name = "Hdmi3", - .dpcm_playback = 1, - .init = NULL, - .nonatomic = 1, - .dynamic = 1, - SND_SOC_DAILINK_REG(hdmi3, dummy, platform), - }, - /* Back End DAI links */ - { - /* SSP5 - Codec */ - .name = "SSP5-Codec", - .id = 0, - .no_pcm = 1, - .dai_fmt = SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBC_CFC, - .ignore_pmdown_time = 1, - .be_hw_params_fixup = broxton_ssp_fixup, - .dpcm_playback = 1, - SND_SOC_DAILINK_REG(ssp5_pin, ssp5_codec, platform), - }, - { - /* SSP1 - Codec */ - .name = "SSP1-Codec", - .id = 1, - .no_pcm = 1, - .init = broxton_da7219_codec_init, - .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBC_CFC, - .ignore_pmdown_time = 1, - .be_hw_params_fixup = broxton_ssp_fixup, - .dpcm_playback = 1, - .dpcm_capture = 1, - SND_SOC_DAILINK_REG(ssp1_pin, ssp1_codec, platform), - }, - { - .name = "dmic01", - .id = 2, - .ignore_suspend = 1, - .be_hw_params_fixup = broxton_dmic_fixup, - .dpcm_capture = 1, - .no_pcm = 1, - SND_SOC_DAILINK_REG(dmic_pin, dmic_codec, platform), - }, - { - .name = "iDisp1", - .id = 3, - .init = broxton_hdmi_init, - .dpcm_playback = 1, - .no_pcm = 1, - SND_SOC_DAILINK_REG(idisp1_pin, idisp1_codec, platform), - }, - { - .name = "iDisp2", - .id = 4, - .init = broxton_hdmi_init, - .dpcm_playback = 1, - .no_pcm = 1, - SND_SOC_DAILINK_REG(idisp2_pin, idisp2_codec, platform), - }, - { - .name = "iDisp3", - .id = 5, - .init = broxton_hdmi_init, - .dpcm_playback = 1, - .no_pcm = 1, - SND_SOC_DAILINK_REG(idisp3_pin, idisp3_codec, platform), - }, - { - .name = "dmic16k", - .id = 6, - .be_hw_params_fixup = broxton_dmic_fixup, - .dpcm_capture = 1, - .no_pcm = 1, - SND_SOC_DAILINK_REG(dmic16k_pin, dmic_codec, platform), - }, -}; - -#define NAME_SIZE 32 -static int bxt_card_late_probe(struct snd_soc_card *card) -{ - struct bxt_card_private *ctx = snd_soc_card_get_drvdata(card); - struct bxt_hdmi_pcm *pcm; - struct snd_soc_component *component = NULL; - int err, i = 0; - char jack_name[NAME_SIZE]; - - if (list_empty(&ctx->hdmi_pcm_list)) - return -EINVAL; - - if (ctx->common_hdmi_codec_drv) { - pcm = list_first_entry(&ctx->hdmi_pcm_list, struct bxt_hdmi_pcm, - head); - component = pcm->codec_dai->component; - return hda_dsp_hdmi_build_controls(card, component); - } - - list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) { - component = pcm->codec_dai->component; - snprintf(jack_name, sizeof(jack_name), - "HDMI/DP, pcm=%d Jack", pcm->device); - err = snd_soc_card_jack_new(card, jack_name, - SND_JACK_AVOUT, &broxton_hdmi[i]); - - if (err) - return err; - - err = hdac_hdmi_jack_init(pcm->codec_dai, pcm->device, - &broxton_hdmi[i]); - if (err < 0) - return err; - - i++; - } - - return hdac_hdmi_jack_port_init(component, &card->dapm); -} - -/* broxton audio machine driver for SPT + da7219 */ -static struct snd_soc_card broxton_audio_card = { - .name = "bxtda7219max", - .owner = THIS_MODULE, - .dai_link = broxton_dais, - .num_links = ARRAY_SIZE(broxton_dais), - .controls = broxton_controls, - .num_controls = ARRAY_SIZE(broxton_controls), - .dapm_widgets = broxton_widgets, - .num_dapm_widgets = ARRAY_SIZE(broxton_widgets), - .dapm_routes = audio_map, - .num_dapm_routes = ARRAY_SIZE(audio_map), - .fully_routed = true, - .disable_route_checks = true, - .late_probe = bxt_card_late_probe, -}; - -static int broxton_audio_probe(struct platform_device *pdev) -{ - struct bxt_card_private *ctx; - struct snd_soc_acpi_mach *mach; - const char *platform_name; - int ret; - - ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); - if (!ctx) - return -ENOMEM; - - INIT_LIST_HEAD(&ctx->hdmi_pcm_list); - - broxton_audio_card.dev = &pdev->dev; - snd_soc_card_set_drvdata(&broxton_audio_card, ctx); - - /* override platform name, if required */ - mach = pdev->dev.platform_data; - platform_name = mach->mach_params.platform; - - ret = snd_soc_fixup_dai_links_platform_name(&broxton_audio_card, - platform_name); - if (ret) - return ret; - - ctx->common_hdmi_codec_drv = mach->mach_params.common_hdmi_codec_drv; - - return devm_snd_soc_register_card(&pdev->dev, &broxton_audio_card); -} - -static const struct platform_device_id bxt_board_ids[] = { - { .name = "bxt_da7219_mx98357a" }, - { } -}; -MODULE_DEVICE_TABLE(platform, bxt_board_ids); - -static struct platform_driver broxton_audio = { - .probe = broxton_audio_probe, - .driver = { - .name = "bxt_da7219_max98357a", - .pm = &snd_soc_pm_ops, - }, - .id_table = bxt_board_ids, -}; -module_platform_driver(broxton_audio) - -/* Module information */ -MODULE_DESCRIPTION("Audio Machine driver-DA7219 & MAX98357A in I2S mode"); -MODULE_AUTHOR("Sathyanarayana Nujella "); -MODULE_AUTHOR("Rohit Ainapure "); -MODULE_AUTHOR("Harsha Priya "); -MODULE_AUTHOR("Conrad Cooke "); -MODULE_AUTHOR("Naveen Manohar "); -MODULE_AUTHOR("Mac Chiang "); -MODULE_AUTHOR("Brent Lu "); -MODULE_LICENSE("GPL v2"); -MODULE_IMPORT_NS(SND_SOC_INTEL_HDA_DSP_COMMON); diff --git a/sound/soc/intel/boards/bxt_rt298.c b/sound/soc/intel/boards/bxt_rt298.c deleted file mode 100644 index dce6a2086f2a45..00000000000000 --- a/sound/soc/intel/boards/bxt_rt298.c +++ /dev/null @@ -1,670 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Intel Broxton-P I2S Machine Driver - * - * Copyright (C) 2014-2016, Intel Corporation - * - * Modified from: - * Intel Skylake I2S Machine driver - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include "../../codecs/hdac_hdmi.h" -#include "../../codecs/rt298.h" -#include "hda_dsp_common.h" - -/* Headset jack detection DAPM pins */ -static struct snd_soc_jack broxton_headset; -static struct snd_soc_jack broxton_hdmi[3]; - -struct bxt_hdmi_pcm { - struct list_head head; - struct snd_soc_dai *codec_dai; - int device; -}; - -struct bxt_rt286_private { - struct list_head hdmi_pcm_list; - bool common_hdmi_codec_drv; -}; - -enum { - BXT_DPCM_AUDIO_PB = 0, - BXT_DPCM_AUDIO_CP, - BXT_DPCM_AUDIO_REF_CP, - BXT_DPCM_AUDIO_DMIC_CP, - BXT_DPCM_AUDIO_HDMI1_PB, - BXT_DPCM_AUDIO_HDMI2_PB, - BXT_DPCM_AUDIO_HDMI3_PB, -}; - -static struct snd_soc_jack_pin broxton_headset_pins[] = { - { - .pin = "Mic Jack", - .mask = SND_JACK_MICROPHONE, - }, - { - .pin = "Headphone Jack", - .mask = SND_JACK_HEADPHONE, - }, -}; - -static const struct snd_kcontrol_new broxton_controls[] = { - SOC_DAPM_PIN_SWITCH("Speaker"), - SOC_DAPM_PIN_SWITCH("Headphone Jack"), - SOC_DAPM_PIN_SWITCH("Mic Jack"), -}; - -static const struct snd_soc_dapm_widget broxton_widgets[] = { - SND_SOC_DAPM_HP("Headphone Jack", NULL), - SND_SOC_DAPM_SPK("Speaker", NULL), - SND_SOC_DAPM_MIC("Mic Jack", NULL), - SND_SOC_DAPM_MIC("DMIC2", NULL), - SND_SOC_DAPM_MIC("SoC DMIC", NULL), - SND_SOC_DAPM_SPK("HDMI1", NULL), - SND_SOC_DAPM_SPK("HDMI2", NULL), - SND_SOC_DAPM_SPK("HDMI3", NULL), -}; - -static const struct snd_soc_dapm_route broxton_rt298_map[] = { - /* speaker */ - {"Speaker", NULL, "SPOR"}, - {"Speaker", NULL, "SPOL"}, - - /* HP jack connectors - unknown if we have jack detect */ - {"Headphone Jack", NULL, "HPO Pin"}, - - /* other jacks */ - {"MIC1", NULL, "Mic Jack"}, - - /* digital mics */ - {"DMIC1 Pin", NULL, "DMIC2"}, - {"DMic", NULL, "SoC DMIC"}, - - {"HDMI1", NULL, "hif5-0 Output"}, - {"HDMI2", NULL, "hif6-0 Output"}, - {"HDMI2", NULL, "hif7-0 Output"}, - - /* CODEC BE connections */ - { "AIF1 Playback", NULL, "ssp5 Tx"}, - { "ssp5 Tx", NULL, "codec0_out"}, - { "ssp5 Tx", NULL, "codec1_out"}, - - { "codec0_in", NULL, "ssp5 Rx" }, - { "ssp5 Rx", NULL, "AIF1 Capture" }, - - { "dmic01_hifi", NULL, "DMIC01 Rx" }, - { "DMIC01 Rx", NULL, "Capture" }, - - { "hifi3", NULL, "iDisp3 Tx"}, - { "iDisp3 Tx", NULL, "iDisp3_out"}, - { "hifi2", NULL, "iDisp2 Tx"}, - { "iDisp2 Tx", NULL, "iDisp2_out"}, - { "hifi1", NULL, "iDisp1 Tx"}, - { "iDisp1 Tx", NULL, "iDisp1_out"}, -}; - -static const struct snd_soc_dapm_route geminilake_rt298_map[] = { - /* speaker */ - {"Speaker", NULL, "SPOR"}, - {"Speaker", NULL, "SPOL"}, - - /* HP jack connectors - unknown if we have jack detect */ - {"Headphone Jack", NULL, "HPO Pin"}, - - /* other jacks */ - {"MIC1", NULL, "Mic Jack"}, - - /* digital mics */ - {"DMIC1 Pin", NULL, "DMIC2"}, - {"DMic", NULL, "SoC DMIC"}, - - {"HDMI1", NULL, "hif5-0 Output"}, - {"HDMI2", NULL, "hif6-0 Output"}, - {"HDMI2", NULL, "hif7-0 Output"}, - - /* CODEC BE connections */ - { "AIF1 Playback", NULL, "ssp2 Tx"}, - { "ssp2 Tx", NULL, "codec0_out"}, - { "ssp2 Tx", NULL, "codec1_out"}, - - { "codec0_in", NULL, "ssp2 Rx" }, - { "ssp2 Rx", NULL, "AIF1 Capture" }, - - { "dmic01_hifi", NULL, "DMIC01 Rx" }, - { "DMIC01 Rx", NULL, "Capture" }, - - { "dmic_voice", NULL, "DMIC16k Rx" }, - { "DMIC16k Rx", NULL, "Capture" }, - - { "hifi3", NULL, "iDisp3 Tx"}, - { "iDisp3 Tx", NULL, "iDisp3_out"}, - { "hifi2", NULL, "iDisp2 Tx"}, - { "iDisp2 Tx", NULL, "iDisp2_out"}, - { "hifi1", NULL, "iDisp1 Tx"}, - { "iDisp1 Tx", NULL, "iDisp1_out"}, -}; - -static int broxton_rt298_fe_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_dapm_context *dapm; - struct snd_soc_component *component = snd_soc_rtd_to_cpu(rtd, 0)->component; - - dapm = snd_soc_component_get_dapm(component); - snd_soc_dapm_ignore_suspend(dapm, "Reference Capture"); - - return 0; -} - -static int broxton_rt298_codec_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_component *component = snd_soc_rtd_to_codec(rtd, 0)->component; - int ret = 0; - - ret = snd_soc_card_jack_new_pins(rtd->card, "Headset", - SND_JACK_HEADSET | SND_JACK_BTN_0, - &broxton_headset, - broxton_headset_pins, ARRAY_SIZE(broxton_headset_pins)); - - if (ret) - return ret; - - snd_soc_component_set_jack(component, &broxton_headset, NULL); - - snd_soc_dapm_ignore_suspend(&rtd->card->dapm, "SoC DMIC"); - - return 0; -} - -static int broxton_hdmi_init(struct snd_soc_pcm_runtime *rtd) -{ - struct bxt_rt286_private *ctx = snd_soc_card_get_drvdata(rtd->card); - struct snd_soc_dai *dai = snd_soc_rtd_to_codec(rtd, 0); - struct bxt_hdmi_pcm *pcm; - - pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL); - if (!pcm) - return -ENOMEM; - - pcm->device = BXT_DPCM_AUDIO_HDMI1_PB + dai->id; - pcm->codec_dai = dai; - - list_add_tail(&pcm->head, &ctx->hdmi_pcm_list); - - return 0; -} - -static int broxton_ssp5_fixup(struct snd_soc_pcm_runtime *rtd, - struct snd_pcm_hw_params *params) -{ - struct snd_interval *rate = hw_param_interval(params, - SNDRV_PCM_HW_PARAM_RATE); - struct snd_interval *chan = hw_param_interval(params, - SNDRV_PCM_HW_PARAM_CHANNELS); - struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); - - /* The ADSP will convert the FE rate to 48k, stereo */ - rate->min = rate->max = 48000; - chan->min = chan->max = 2; - - /* set SSP5 to 24 bit */ - snd_mask_none(fmt); - snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S24_LE); - - return 0; -} - -static int broxton_rt298_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); - struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); - int ret; - - ret = snd_soc_dai_set_sysclk(codec_dai, RT298_SCLK_S_PLL, - 19200000, SND_SOC_CLOCK_IN); - if (ret < 0) { - dev_err(rtd->dev, "can't set codec sysclk configuration\n"); - return ret; - } - - return ret; -} - -static const struct snd_soc_ops broxton_rt298_ops = { - .hw_params = broxton_rt298_hw_params, -}; - -static const unsigned int rates[] = { - 48000, -}; - -static const struct snd_pcm_hw_constraint_list constraints_rates = { - .count = ARRAY_SIZE(rates), - .list = rates, - .mask = 0, -}; - -static int broxton_dmic_fixup(struct snd_soc_pcm_runtime *rtd, - struct snd_pcm_hw_params *params) -{ - struct snd_interval *chan = hw_param_interval(params, - SNDRV_PCM_HW_PARAM_CHANNELS); - chan->min = chan->max = 4; - - return 0; -} - -static const unsigned int channels_dmic[] = { - 1, 2, 3, 4, -}; - -static const struct snd_pcm_hw_constraint_list constraints_dmic_channels = { - .count = ARRAY_SIZE(channels_dmic), - .list = channels_dmic, - .mask = 0, -}; - -static int broxton_dmic_startup(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - - runtime->hw.channels_max = 4; - snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, - &constraints_dmic_channels); - - return snd_pcm_hw_constraint_list(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_RATE, &constraints_rates); -} - -static const struct snd_soc_ops broxton_dmic_ops = { - .startup = broxton_dmic_startup, -}; - -static const unsigned int channels[] = { - 2, -}; - -static const struct snd_pcm_hw_constraint_list constraints_channels = { - .count = ARRAY_SIZE(channels), - .list = channels, - .mask = 0, -}; - -static int bxt_fe_startup(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - - /* - * on this platform for PCM device we support: - * 48Khz - * stereo - * 16-bit audio - */ - - runtime->hw.channels_max = 2; - snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, - &constraints_channels); - - runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE; - snd_pcm_hw_constraint_msbits(runtime, 0, 16, 16); - snd_pcm_hw_constraint_list(runtime, 0, - SNDRV_PCM_HW_PARAM_RATE, &constraints_rates); - - return 0; -} - -static const struct snd_soc_ops broxton_rt286_fe_ops = { - .startup = bxt_fe_startup, -}; - -SND_SOC_DAILINK_DEF(dummy, - DAILINK_COMP_ARRAY(COMP_DUMMY())); - -SND_SOC_DAILINK_DEF(system, - DAILINK_COMP_ARRAY(COMP_CPU("System Pin"))); - -SND_SOC_DAILINK_DEF(reference, - DAILINK_COMP_ARRAY(COMP_CPU("Reference Pin"))); - -SND_SOC_DAILINK_DEF(dmic, - DAILINK_COMP_ARRAY(COMP_CPU("DMIC Pin"))); - -SND_SOC_DAILINK_DEF(hdmi1, - DAILINK_COMP_ARRAY(COMP_CPU("HDMI1 Pin"))); - -SND_SOC_DAILINK_DEF(hdmi2, - DAILINK_COMP_ARRAY(COMP_CPU("HDMI2 Pin"))); - -SND_SOC_DAILINK_DEF(hdmi3, - DAILINK_COMP_ARRAY(COMP_CPU("HDMI3 Pin"))); - -SND_SOC_DAILINK_DEF(ssp5_pin, - DAILINK_COMP_ARRAY(COMP_CPU("SSP5 Pin"))); -SND_SOC_DAILINK_DEF(ssp5_codec, - DAILINK_COMP_ARRAY(COMP_CODEC("i2c-INT343A:00", - "rt298-aif1"))); - -SND_SOC_DAILINK_DEF(dmic_pin, - DAILINK_COMP_ARRAY(COMP_CPU("DMIC01 Pin"))); - -SND_SOC_DAILINK_DEF(dmic_codec, - DAILINK_COMP_ARRAY(COMP_CODEC("dmic-codec", - "dmic-hifi"))); - -SND_SOC_DAILINK_DEF(dmic16k, - DAILINK_COMP_ARRAY(COMP_CPU("DMIC16k Pin"))); - -SND_SOC_DAILINK_DEF(idisp1_pin, - DAILINK_COMP_ARRAY(COMP_CPU("iDisp1 Pin"))); -SND_SOC_DAILINK_DEF(idisp1_codec, - DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", - "intel-hdmi-hifi1"))); - -SND_SOC_DAILINK_DEF(idisp2_pin, - DAILINK_COMP_ARRAY(COMP_CPU("iDisp2 Pin"))); -SND_SOC_DAILINK_DEF(idisp2_codec, - DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", - "intel-hdmi-hifi2"))); - -SND_SOC_DAILINK_DEF(idisp3_pin, - DAILINK_COMP_ARRAY(COMP_CPU("iDisp3 Pin"))); -SND_SOC_DAILINK_DEF(idisp3_codec, - DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", - "intel-hdmi-hifi3"))); - -SND_SOC_DAILINK_DEF(platform, - DAILINK_COMP_ARRAY(COMP_PLATFORM("0000:00:0e.0"))); - -/* broxton digital audio interface glue - connects codec <--> CPU */ -static struct snd_soc_dai_link broxton_rt298_dais[] = { - /* Front End DAI links */ - [BXT_DPCM_AUDIO_PB] = - { - .name = "Bxt Audio Port", - .stream_name = "Audio", - .nonatomic = 1, - .dynamic = 1, - .init = broxton_rt298_fe_init, - .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .dpcm_playback = 1, - .ops = &broxton_rt286_fe_ops, - SND_SOC_DAILINK_REG(system, dummy, platform), - }, - [BXT_DPCM_AUDIO_CP] = - { - .name = "Bxt Audio Capture Port", - .stream_name = "Audio Record", - .nonatomic = 1, - .dynamic = 1, - .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .dpcm_capture = 1, - .ops = &broxton_rt286_fe_ops, - SND_SOC_DAILINK_REG(system, dummy, platform), - }, - [BXT_DPCM_AUDIO_REF_CP] = - { - .name = "Bxt Audio Reference cap", - .stream_name = "refcap", - .init = NULL, - .dpcm_capture = 1, - .nonatomic = 1, - .dynamic = 1, - SND_SOC_DAILINK_REG(reference, dummy, platform), - }, - [BXT_DPCM_AUDIO_DMIC_CP] = - { - .name = "Bxt Audio DMIC cap", - .stream_name = "dmiccap", - .init = NULL, - .dpcm_capture = 1, - .nonatomic = 1, - .dynamic = 1, - .ops = &broxton_dmic_ops, - SND_SOC_DAILINK_REG(dmic, dummy, platform), - }, - [BXT_DPCM_AUDIO_HDMI1_PB] = - { - .name = "Bxt HDMI Port1", - .stream_name = "Hdmi1", - .dpcm_playback = 1, - .init = NULL, - .nonatomic = 1, - .dynamic = 1, - SND_SOC_DAILINK_REG(hdmi1, dummy, platform), - }, - [BXT_DPCM_AUDIO_HDMI2_PB] = - { - .name = "Bxt HDMI Port2", - .stream_name = "Hdmi2", - .dpcm_playback = 1, - .init = NULL, - .nonatomic = 1, - .dynamic = 1, - SND_SOC_DAILINK_REG(hdmi2, dummy, platform), - }, - [BXT_DPCM_AUDIO_HDMI3_PB] = - { - .name = "Bxt HDMI Port3", - .stream_name = "Hdmi3", - .dpcm_playback = 1, - .init = NULL, - .nonatomic = 1, - .dynamic = 1, - SND_SOC_DAILINK_REG(hdmi3, dummy, platform), - }, - /* Back End DAI links */ - { - /* SSP5 - Codec */ - .name = "SSP5-Codec", - .id = 0, - .no_pcm = 1, - .init = broxton_rt298_codec_init, - .dai_fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBC_CFC, - .ignore_pmdown_time = 1, - .be_hw_params_fixup = broxton_ssp5_fixup, - .ops = &broxton_rt298_ops, - .dpcm_playback = 1, - .dpcm_capture = 1, - SND_SOC_DAILINK_REG(ssp5_pin, ssp5_codec, platform), - }, - { - .name = "dmic01", - .id = 1, - .be_hw_params_fixup = broxton_dmic_fixup, - .ignore_suspend = 1, - .dpcm_capture = 1, - .no_pcm = 1, - SND_SOC_DAILINK_REG(dmic_pin, dmic_codec, platform), - }, - { - .name = "dmic16k", - .id = 2, - .be_hw_params_fixup = broxton_dmic_fixup, - .ignore_suspend = 1, - .dpcm_capture = 1, - .no_pcm = 1, - SND_SOC_DAILINK_REG(dmic16k, dmic_codec, platform), - }, - { - .name = "iDisp1", - .id = 3, - .init = broxton_hdmi_init, - .dpcm_playback = 1, - .no_pcm = 1, - SND_SOC_DAILINK_REG(idisp1_pin, idisp1_codec, platform), - }, - { - .name = "iDisp2", - .id = 4, - .init = broxton_hdmi_init, - .dpcm_playback = 1, - .no_pcm = 1, - SND_SOC_DAILINK_REG(idisp2_pin, idisp2_codec, platform), - }, - { - .name = "iDisp3", - .id = 5, - .init = broxton_hdmi_init, - .dpcm_playback = 1, - .no_pcm = 1, - SND_SOC_DAILINK_REG(idisp3_pin, idisp3_codec, platform), - }, -}; - -#define NAME_SIZE 32 -static int bxt_card_late_probe(struct snd_soc_card *card) -{ - struct bxt_rt286_private *ctx = snd_soc_card_get_drvdata(card); - struct bxt_hdmi_pcm *pcm; - struct snd_soc_component *component = NULL; - int err, i = 0; - char jack_name[NAME_SIZE]; - - if (list_empty(&ctx->hdmi_pcm_list)) - return -EINVAL; - - if (ctx->common_hdmi_codec_drv) { - pcm = list_first_entry(&ctx->hdmi_pcm_list, struct bxt_hdmi_pcm, - head); - component = pcm->codec_dai->component; - return hda_dsp_hdmi_build_controls(card, component); - } - - list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) { - component = pcm->codec_dai->component; - snprintf(jack_name, sizeof(jack_name), - "HDMI/DP, pcm=%d Jack", pcm->device); - err = snd_soc_card_jack_new(card, jack_name, - SND_JACK_AVOUT, &broxton_hdmi[i]); - - if (err) - return err; - - err = hdac_hdmi_jack_init(pcm->codec_dai, pcm->device, - &broxton_hdmi[i]); - if (err < 0) - return err; - - i++; - } - - return hdac_hdmi_jack_port_init(component, &card->dapm); -} - - -/* broxton audio machine driver for SPT + RT298S */ -static struct snd_soc_card broxton_rt298 = { - .name = "broxton-rt298", - .owner = THIS_MODULE, - .dai_link = broxton_rt298_dais, - .num_links = ARRAY_SIZE(broxton_rt298_dais), - .controls = broxton_controls, - .num_controls = ARRAY_SIZE(broxton_controls), - .dapm_widgets = broxton_widgets, - .num_dapm_widgets = ARRAY_SIZE(broxton_widgets), - .dapm_routes = broxton_rt298_map, - .num_dapm_routes = ARRAY_SIZE(broxton_rt298_map), - .fully_routed = true, - .disable_route_checks = true, - .late_probe = bxt_card_late_probe, - -}; - -static struct snd_soc_card geminilake_rt298 = { - .name = "geminilake-rt298", - .owner = THIS_MODULE, - .dai_link = broxton_rt298_dais, - .num_links = ARRAY_SIZE(broxton_rt298_dais), - .controls = broxton_controls, - .num_controls = ARRAY_SIZE(broxton_controls), - .dapm_widgets = broxton_widgets, - .num_dapm_widgets = ARRAY_SIZE(broxton_widgets), - .dapm_routes = geminilake_rt298_map, - .num_dapm_routes = ARRAY_SIZE(geminilake_rt298_map), - .fully_routed = true, - .late_probe = bxt_card_late_probe, -}; - -static int broxton_audio_probe(struct platform_device *pdev) -{ - struct bxt_rt286_private *ctx; - struct snd_soc_card *card = - (struct snd_soc_card *)pdev->id_entry->driver_data; - struct snd_soc_acpi_mach *mach; - const char *platform_name; - int ret; - int i; - - for (i = 0; i < ARRAY_SIZE(broxton_rt298_dais); i++) { - if (card->dai_link[i].codecs->name && - !strncmp(card->dai_link[i].codecs->name, "i2c-INT343A:00", - I2C_NAME_SIZE)) { - if (!strncmp(card->name, "broxton-rt298", - PLATFORM_NAME_SIZE)) { - card->dai_link[i].name = "SSP5-Codec"; - card->dai_link[i].cpus->dai_name = "SSP5 Pin"; - } else if (!strncmp(card->name, "geminilake-rt298", - PLATFORM_NAME_SIZE)) { - card->dai_link[i].name = "SSP2-Codec"; - card->dai_link[i].cpus->dai_name = "SSP2 Pin"; - } - } - } - - ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); - if (!ctx) - return -ENOMEM; - - INIT_LIST_HEAD(&ctx->hdmi_pcm_list); - - card->dev = &pdev->dev; - snd_soc_card_set_drvdata(card, ctx); - - /* override platform name, if required */ - mach = pdev->dev.platform_data; - platform_name = mach->mach_params.platform; - - ret = snd_soc_fixup_dai_links_platform_name(card, - platform_name); - if (ret) - return ret; - - ctx->common_hdmi_codec_drv = mach->mach_params.common_hdmi_codec_drv; - - return devm_snd_soc_register_card(&pdev->dev, card); -} - -static const struct platform_device_id bxt_board_ids[] = { - { .name = "bxt_alc298s_i2s", .driver_data = - (unsigned long)&broxton_rt298 }, - { .name = "glk_alc298s_i2s", .driver_data = - (unsigned long)&geminilake_rt298 }, - {} -}; -MODULE_DEVICE_TABLE(platform, bxt_board_ids); - -static struct platform_driver broxton_audio = { - .probe = broxton_audio_probe, - .driver = { - .name = "bxt_alc298s_i2s", - .pm = &snd_soc_pm_ops, - }, - .id_table = bxt_board_ids, -}; -module_platform_driver(broxton_audio) - -/* Module information */ -MODULE_AUTHOR("Ramesh Babu "); -MODULE_AUTHOR("Senthilnathan Veppur "); -MODULE_DESCRIPTION("Intel SST Audio for Broxton"); -MODULE_LICENSE("GPL v2"); -MODULE_IMPORT_NS(SND_SOC_INTEL_HDA_DSP_COMMON); diff --git a/sound/soc/intel/boards/kbl_da7219_max98357a.c b/sound/soc/intel/boards/kbl_da7219_max98357a.c deleted file mode 100644 index 154f6a74ed151f..00000000000000 --- a/sound/soc/intel/boards/kbl_da7219_max98357a.c +++ /dev/null @@ -1,688 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -// Copyright(c) 2017-18 Intel Corporation. - -/* - * Intel Kabylake I2S Machine Driver with MAX98357A & DA7219 Codecs - * - * Modified from: - * Intel Kabylake I2S Machine driver supporting MAXIM98927 and - * RT5663 codecs - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include "../../codecs/da7219.h" -#include "../../codecs/hdac_hdmi.h" - -#define KBL_DIALOG_CODEC_DAI "da7219-hifi" -#define KBL_MAXIM_CODEC_DAI "HiFi" -#define MAXIM_DEV0_NAME "MX98357A:00" -#define DUAL_CHANNEL 2 -#define QUAD_CHANNEL 4 - -static struct snd_soc_card *kabylake_audio_card; -static struct snd_soc_jack skylake_hdmi[3]; - -struct kbl_hdmi_pcm { - struct list_head head; - struct snd_soc_dai *codec_dai; - int device; -}; - -struct kbl_codec_private { - struct snd_soc_jack kabylake_headset; - struct list_head hdmi_pcm_list; -}; - -enum { - KBL_DPCM_AUDIO_PB = 0, - KBL_DPCM_AUDIO_CP, - KBL_DPCM_AUDIO_REF_CP, - KBL_DPCM_AUDIO_DMIC_CP, - KBL_DPCM_AUDIO_HDMI1_PB, - KBL_DPCM_AUDIO_HDMI2_PB, - KBL_DPCM_AUDIO_HDMI3_PB, -}; - -static int platform_clock_control(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *k, int event) -{ - struct snd_soc_dapm_context *dapm = w->dapm; - struct snd_soc_card *card = dapm->card; - struct snd_soc_dai *codec_dai; - int ret = 0; - - codec_dai = snd_soc_card_get_codec_dai(card, KBL_DIALOG_CODEC_DAI); - if (!codec_dai) { - dev_err(card->dev, "Codec dai not found; Unable to set/unset codec pll\n"); - return -EIO; - } - - if (SND_SOC_DAPM_EVENT_OFF(event)) { - ret = snd_soc_dai_set_pll(codec_dai, 0, - DA7219_SYSCLK_MCLK, 0, 0); - if (ret) - dev_err(card->dev, "failed to stop PLL: %d\n", ret); - } else if (SND_SOC_DAPM_EVENT_ON(event)) { - ret = snd_soc_dai_set_pll(codec_dai, 0, DA7219_SYSCLK_PLL_SRM, - 0, DA7219_PLL_FREQ_OUT_98304); - if (ret) - dev_err(card->dev, "failed to start PLL: %d\n", ret); - } - - return ret; -} - -static const struct snd_kcontrol_new kabylake_controls[] = { - SOC_DAPM_PIN_SWITCH("Headphone Jack"), - SOC_DAPM_PIN_SWITCH("Headset Mic"), - SOC_DAPM_PIN_SWITCH("Spk"), - SOC_DAPM_PIN_SWITCH("Line Out"), -}; - -static const struct snd_soc_dapm_widget kabylake_widgets[] = { - SND_SOC_DAPM_HP("Headphone Jack", NULL), - SND_SOC_DAPM_MIC("Headset Mic", NULL), - SND_SOC_DAPM_SPK("Spk", NULL), - SND_SOC_DAPM_LINE("Line Out", NULL), - SND_SOC_DAPM_MIC("SoC DMIC", NULL), - SND_SOC_DAPM_SPK("HDMI1", NULL), - SND_SOC_DAPM_SPK("HDMI2", NULL), - SND_SOC_DAPM_SPK("HDMI3", NULL), - SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0, - platform_clock_control, SND_SOC_DAPM_PRE_PMU | - SND_SOC_DAPM_POST_PMD), -}; - -static struct snd_soc_jack_pin jack_pins[] = { - { - .pin = "Headphone Jack", - .mask = SND_JACK_HEADPHONE, - }, - { - .pin = "Headset Mic", - .mask = SND_JACK_MICROPHONE, - }, - { - .pin = "Line Out", - .mask = SND_JACK_LINEOUT, - }, -}; - -static const struct snd_soc_dapm_route kabylake_map[] = { - { "Headphone Jack", NULL, "HPL" }, - { "Headphone Jack", NULL, "HPR" }, - - /* speaker */ - { "Spk", NULL, "Speaker" }, - - /* other jacks */ - { "MIC", NULL, "Headset Mic" }, - { "DMic", NULL, "SoC DMIC" }, - - {"HDMI1", NULL, "hif5-0 Output"}, - {"HDMI2", NULL, "hif6-0 Output"}, - {"HDMI3", NULL, "hif7-0 Output"}, - - /* CODEC BE connections */ - { "HiFi Playback", NULL, "ssp0 Tx" }, - { "ssp0 Tx", NULL, "codec0_out" }, - - { "Playback", NULL, "ssp1 Tx" }, - { "ssp1 Tx", NULL, "codec1_out" }, - - { "codec0_in", NULL, "ssp1 Rx" }, - { "ssp1 Rx", NULL, "Capture" }, - - /* DMIC */ - { "dmic01_hifi", NULL, "DMIC01 Rx" }, - { "DMIC01 Rx", NULL, "DMIC AIF" }, - - { "hifi1", NULL, "iDisp1 Tx" }, - { "iDisp1 Tx", NULL, "iDisp1_out" }, - { "hifi2", NULL, "iDisp2 Tx" }, - { "iDisp2 Tx", NULL, "iDisp2_out" }, - { "hifi3", NULL, "iDisp3 Tx"}, - { "iDisp3 Tx", NULL, "iDisp3_out"}, - - { "Headphone Jack", NULL, "Platform Clock" }, - { "Headset Mic", NULL, "Platform Clock" }, - { "Line Out", NULL, "Platform Clock" }, -}; - -static int kabylake_ssp_fixup(struct snd_soc_pcm_runtime *rtd, - struct snd_pcm_hw_params *params) -{ - struct snd_interval *rate = hw_param_interval(params, - SNDRV_PCM_HW_PARAM_RATE); - struct snd_interval *chan = hw_param_interval(params, - SNDRV_PCM_HW_PARAM_CHANNELS); - struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); - - /* The ADSP will convert the FE rate to 48k, stereo */ - rate->min = rate->max = 48000; - chan->min = chan->max = DUAL_CHANNEL; - - /* set SSP to 24 bit */ - snd_mask_none(fmt); - snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S24_LE); - - return 0; -} - -static int kabylake_da7219_codec_init(struct snd_soc_pcm_runtime *rtd) -{ - struct kbl_codec_private *ctx = snd_soc_card_get_drvdata(rtd->card); - struct snd_soc_component *component = snd_soc_rtd_to_codec(rtd, 0)->component; - struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); - struct snd_soc_jack *jack; - int ret; - - /* Configure sysclk for codec */ - ret = snd_soc_dai_set_sysclk(codec_dai, DA7219_CLKSRC_MCLK, 24576000, - SND_SOC_CLOCK_IN); - if (ret) { - dev_err(rtd->dev, "can't set codec sysclk configuration\n"); - return ret; - } - - /* - * Headset buttons map to the google Reference headset. - * These can be configured by userspace. - */ - ret = snd_soc_card_jack_new_pins(kabylake_audio_card, "Headset Jack", - SND_JACK_HEADSET | SND_JACK_BTN_0 | SND_JACK_BTN_1 | - SND_JACK_BTN_2 | SND_JACK_BTN_3 | SND_JACK_LINEOUT, - &ctx->kabylake_headset, - jack_pins, - ARRAY_SIZE(jack_pins)); - if (ret) { - dev_err(rtd->dev, "Headset Jack creation failed: %d\n", ret); - return ret; - } - - jack = &ctx->kabylake_headset; - - snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_PLAYPAUSE); - snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOLUMEUP); - snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEDOWN); - snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOICECOMMAND); - snd_soc_component_set_jack(component, &ctx->kabylake_headset, NULL); - - ret = snd_soc_dapm_ignore_suspend(&rtd->card->dapm, "SoC DMIC"); - if (ret) - dev_err(rtd->dev, "SoC DMIC - Ignore suspend failed %d\n", ret); - - return ret; -} - -static int kabylake_hdmi_init(struct snd_soc_pcm_runtime *rtd, int device) -{ - struct kbl_codec_private *ctx = snd_soc_card_get_drvdata(rtd->card); - struct snd_soc_dai *dai = snd_soc_rtd_to_codec(rtd, 0); - struct kbl_hdmi_pcm *pcm; - - pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL); - if (!pcm) - return -ENOMEM; - - pcm->device = device; - pcm->codec_dai = dai; - - list_add_tail(&pcm->head, &ctx->hdmi_pcm_list); - - return 0; -} - -static int kabylake_hdmi1_init(struct snd_soc_pcm_runtime *rtd) -{ - return kabylake_hdmi_init(rtd, KBL_DPCM_AUDIO_HDMI1_PB); -} - -static int kabylake_hdmi2_init(struct snd_soc_pcm_runtime *rtd) -{ - return kabylake_hdmi_init(rtd, KBL_DPCM_AUDIO_HDMI2_PB); -} - -static int kabylake_hdmi3_init(struct snd_soc_pcm_runtime *rtd) -{ - return kabylake_hdmi_init(rtd, KBL_DPCM_AUDIO_HDMI3_PB); -} - -static int kabylake_da7219_fe_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_dapm_context *dapm; - struct snd_soc_component *component = snd_soc_rtd_to_cpu(rtd, 0)->component; - - dapm = snd_soc_component_get_dapm(component); - snd_soc_dapm_ignore_suspend(dapm, "Reference Capture"); - - return 0; -} - -static const unsigned int rates[] = { - 48000, -}; - -static const struct snd_pcm_hw_constraint_list constraints_rates = { - .count = ARRAY_SIZE(rates), - .list = rates, - .mask = 0, -}; - -static const unsigned int channels[] = { - DUAL_CHANNEL, -}; - -static const struct snd_pcm_hw_constraint_list constraints_channels = { - .count = ARRAY_SIZE(channels), - .list = channels, - .mask = 0, -}; - -static unsigned int channels_quad[] = { - QUAD_CHANNEL, -}; - -static struct snd_pcm_hw_constraint_list constraints_channels_quad = { - .count = ARRAY_SIZE(channels_quad), - .list = channels_quad, - .mask = 0, -}; - -static int kbl_fe_startup(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - - /* - * On this platform for PCM device we support, - * 48Khz - * stereo - * 16 bit audio - */ - - runtime->hw.channels_max = DUAL_CHANNEL; - snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, - &constraints_channels); - - runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE; - snd_pcm_hw_constraint_msbits(runtime, 0, 16, 16); - - snd_pcm_hw_constraint_list(runtime, 0, - SNDRV_PCM_HW_PARAM_RATE, &constraints_rates); - - return 0; -} - -static const struct snd_soc_ops kabylake_da7219_fe_ops = { - .startup = kbl_fe_startup, -}; - -static int kabylake_dmic_fixup(struct snd_soc_pcm_runtime *rtd, - struct snd_pcm_hw_params *params) -{ - struct snd_interval *chan = hw_param_interval(params, - SNDRV_PCM_HW_PARAM_CHANNELS); - - /* - * set BE channel constraint as user FE channels - */ - - if (params_channels(params) == 2) - chan->min = chan->max = 2; - else - chan->min = chan->max = 4; - - return 0; -} - -static int kabylake_dmic_startup(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - - runtime->hw.channels_min = runtime->hw.channels_max = QUAD_CHANNEL; - snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, - &constraints_channels_quad); - - return snd_pcm_hw_constraint_list(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_RATE, &constraints_rates); -} - -static const struct snd_soc_ops kabylake_dmic_ops = { - .startup = kabylake_dmic_startup, -}; - -static unsigned int rates_16000[] = { - 16000, -}; - -static const struct snd_pcm_hw_constraint_list constraints_16000 = { - .count = ARRAY_SIZE(rates_16000), - .list = rates_16000, -}; - -static const unsigned int ch_mono[] = { - 1, -}; - -static const struct snd_pcm_hw_constraint_list constraints_refcap = { - .count = ARRAY_SIZE(ch_mono), - .list = ch_mono, -}; - -static int kabylake_refcap_startup(struct snd_pcm_substream *substream) -{ - substream->runtime->hw.channels_max = 1; - snd_pcm_hw_constraint_list(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_CHANNELS, - &constraints_refcap); - - return snd_pcm_hw_constraint_list(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_RATE, - &constraints_16000); -} - -static const struct snd_soc_ops skylake_refcap_ops = { - .startup = kabylake_refcap_startup, -}; - -SND_SOC_DAILINK_DEF(dummy, - DAILINK_COMP_ARRAY(COMP_DUMMY())); - -SND_SOC_DAILINK_DEF(system, - DAILINK_COMP_ARRAY(COMP_CPU("System Pin"))); - -SND_SOC_DAILINK_DEF(reference, - DAILINK_COMP_ARRAY(COMP_CPU("Reference Pin"))); - -SND_SOC_DAILINK_DEF(dmic, - DAILINK_COMP_ARRAY(COMP_CPU("DMIC Pin"))); - -SND_SOC_DAILINK_DEF(hdmi1, - DAILINK_COMP_ARRAY(COMP_CPU("HDMI1 Pin"))); - -SND_SOC_DAILINK_DEF(hdmi2, - DAILINK_COMP_ARRAY(COMP_CPU("HDMI2 Pin"))); - -SND_SOC_DAILINK_DEF(hdmi3, - DAILINK_COMP_ARRAY(COMP_CPU("HDMI3 Pin"))); - -SND_SOC_DAILINK_DEF(ssp0_pin, - DAILINK_COMP_ARRAY(COMP_CPU("SSP0 Pin"))); -SND_SOC_DAILINK_DEF(ssp0_codec, - DAILINK_COMP_ARRAY(COMP_CODEC(MAXIM_DEV0_NAME, - KBL_MAXIM_CODEC_DAI))); - -SND_SOC_DAILINK_DEF(ssp1_pin, - DAILINK_COMP_ARRAY(COMP_CPU("SSP1 Pin"))); -SND_SOC_DAILINK_DEF(ssp1_codec, - DAILINK_COMP_ARRAY(COMP_CODEC("i2c-DLGS7219:00", - KBL_DIALOG_CODEC_DAI))); - -SND_SOC_DAILINK_DEF(dmic_pin, - DAILINK_COMP_ARRAY(COMP_CPU("DMIC01 Pin"))); -SND_SOC_DAILINK_DEF(dmic_codec, - DAILINK_COMP_ARRAY(COMP_CODEC("dmic-codec", "dmic-hifi"))); - -SND_SOC_DAILINK_DEF(idisp1_pin, - DAILINK_COMP_ARRAY(COMP_CPU("iDisp1 Pin"))); -SND_SOC_DAILINK_DEF(idisp1_codec, - DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", - "intel-hdmi-hifi1"))); - -SND_SOC_DAILINK_DEF(idisp2_pin, - DAILINK_COMP_ARRAY(COMP_CPU("iDisp2 Pin"))); -SND_SOC_DAILINK_DEF(idisp2_codec, - DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi2"))); - -SND_SOC_DAILINK_DEF(idisp3_pin, - DAILINK_COMP_ARRAY(COMP_CPU("iDisp3 Pin"))); -SND_SOC_DAILINK_DEF(idisp3_codec, - DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi3"))); - -SND_SOC_DAILINK_DEF(platform, - DAILINK_COMP_ARRAY(COMP_PLATFORM("0000:00:1f.3"))); - -/* kabylake digital audio interface glue - connects codec <--> CPU */ -static struct snd_soc_dai_link kabylake_dais[] = { - /* Front End DAI links */ - [KBL_DPCM_AUDIO_PB] = { - .name = "Kbl Audio Port", - .stream_name = "Audio", - .dynamic = 1, - .nonatomic = 1, - .init = kabylake_da7219_fe_init, - .trigger = { - SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .dpcm_playback = 1, - .ops = &kabylake_da7219_fe_ops, - SND_SOC_DAILINK_REG(system, dummy, platform), - }, - [KBL_DPCM_AUDIO_CP] = { - .name = "Kbl Audio Capture Port", - .stream_name = "Audio Record", - .dynamic = 1, - .nonatomic = 1, - .trigger = { - SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .dpcm_capture = 1, - .ops = &kabylake_da7219_fe_ops, - SND_SOC_DAILINK_REG(system, dummy, platform), - }, - [KBL_DPCM_AUDIO_REF_CP] = { - .name = "Kbl Audio Reference cap", - .stream_name = "Wake on Voice", - .init = NULL, - .dpcm_capture = 1, - .nonatomic = 1, - .dynamic = 1, - .ops = &skylake_refcap_ops, - SND_SOC_DAILINK_REG(reference, dummy, platform), - }, - [KBL_DPCM_AUDIO_DMIC_CP] = { - .name = "Kbl Audio DMIC cap", - .stream_name = "dmiccap", - .init = NULL, - .dpcm_capture = 1, - .nonatomic = 1, - .dynamic = 1, - .ops = &kabylake_dmic_ops, - SND_SOC_DAILINK_REG(dmic, dummy, platform), - }, - [KBL_DPCM_AUDIO_HDMI1_PB] = { - .name = "Kbl HDMI Port1", - .stream_name = "Hdmi1", - .dpcm_playback = 1, - .init = NULL, - .trigger = { - SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .nonatomic = 1, - .dynamic = 1, - SND_SOC_DAILINK_REG(hdmi1, dummy, platform), - }, - [KBL_DPCM_AUDIO_HDMI2_PB] = { - .name = "Kbl HDMI Port2", - .stream_name = "Hdmi2", - .dpcm_playback = 1, - .init = NULL, - .trigger = { - SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .nonatomic = 1, - .dynamic = 1, - SND_SOC_DAILINK_REG(hdmi2, dummy, platform), - }, - [KBL_DPCM_AUDIO_HDMI3_PB] = { - .name = "Kbl HDMI Port3", - .stream_name = "Hdmi3", - .trigger = { - SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .dpcm_playback = 1, - .init = NULL, - .nonatomic = 1, - .dynamic = 1, - SND_SOC_DAILINK_REG(hdmi3, dummy, platform), - }, - - /* Back End DAI links */ - { - /* SSP0 - Codec */ - .name = "SSP0-Codec", - .id = 0, - .no_pcm = 1, - .dai_fmt = SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBC_CFC, - .ignore_pmdown_time = 1, - .be_hw_params_fixup = kabylake_ssp_fixup, - .dpcm_playback = 1, - SND_SOC_DAILINK_REG(ssp0_pin, ssp0_codec, platform), - }, - { - /* SSP1 - Codec */ - .name = "SSP1-Codec", - .id = 1, - .no_pcm = 1, - .init = kabylake_da7219_codec_init, - .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBC_CFC, - .ignore_pmdown_time = 1, - .be_hw_params_fixup = kabylake_ssp_fixup, - .dpcm_playback = 1, - .dpcm_capture = 1, - SND_SOC_DAILINK_REG(ssp1_pin, ssp1_codec, platform), - }, - { - .name = "dmic01", - .id = 2, - .be_hw_params_fixup = kabylake_dmic_fixup, - .ignore_suspend = 1, - .dpcm_capture = 1, - .no_pcm = 1, - SND_SOC_DAILINK_REG(dmic_pin, dmic_codec, platform), - }, - { - .name = "iDisp1", - .id = 3, - .dpcm_playback = 1, - .init = kabylake_hdmi1_init, - .no_pcm = 1, - SND_SOC_DAILINK_REG(idisp1_pin, idisp1_codec, platform), - }, - { - .name = "iDisp2", - .id = 4, - .init = kabylake_hdmi2_init, - .dpcm_playback = 1, - .no_pcm = 1, - SND_SOC_DAILINK_REG(idisp2_pin, idisp2_codec, platform), - }, - { - .name = "iDisp3", - .id = 5, - .init = kabylake_hdmi3_init, - .dpcm_playback = 1, - .no_pcm = 1, - SND_SOC_DAILINK_REG(idisp3_pin, idisp3_codec, platform), - }, -}; - -#define NAME_SIZE 32 -static int kabylake_card_late_probe(struct snd_soc_card *card) -{ - struct kbl_codec_private *ctx = snd_soc_card_get_drvdata(card); - struct kbl_hdmi_pcm *pcm; - struct snd_soc_component *component = NULL; - int err, i = 0; - char jack_name[NAME_SIZE]; - - list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) { - component = pcm->codec_dai->component; - snprintf(jack_name, sizeof(jack_name), - "HDMI/DP, pcm=%d Jack", pcm->device); - err = snd_soc_card_jack_new(card, jack_name, - SND_JACK_AVOUT, &skylake_hdmi[i]); - - if (err) - return err; - - err = hdac_hdmi_jack_init(pcm->codec_dai, pcm->device, - &skylake_hdmi[i]); - if (err < 0) - return err; - - i++; - - } - - if (!component) - return -EINVAL; - - return hdac_hdmi_jack_port_init(component, &card->dapm); -} - -/* kabylake audio machine driver for SPT + DA7219 */ -static struct snd_soc_card kabylake_audio_card_da7219_m98357a = { - .name = "kblda7219max", - .owner = THIS_MODULE, - .dai_link = kabylake_dais, - .num_links = ARRAY_SIZE(kabylake_dais), - .controls = kabylake_controls, - .num_controls = ARRAY_SIZE(kabylake_controls), - .dapm_widgets = kabylake_widgets, - .num_dapm_widgets = ARRAY_SIZE(kabylake_widgets), - .dapm_routes = kabylake_map, - .num_dapm_routes = ARRAY_SIZE(kabylake_map), - .fully_routed = true, - .disable_route_checks = true, - .late_probe = kabylake_card_late_probe, -}; - -static int kabylake_audio_probe(struct platform_device *pdev) -{ - struct kbl_codec_private *ctx; - - ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); - if (!ctx) - return -ENOMEM; - - INIT_LIST_HEAD(&ctx->hdmi_pcm_list); - - kabylake_audio_card = - (struct snd_soc_card *)pdev->id_entry->driver_data; - - kabylake_audio_card->dev = &pdev->dev; - snd_soc_card_set_drvdata(kabylake_audio_card, ctx); - return devm_snd_soc_register_card(&pdev->dev, kabylake_audio_card); -} - -static const struct platform_device_id kbl_board_ids[] = { - { - .name = "kbl_da7219_mx98357a", - .driver_data = - (kernel_ulong_t)&kabylake_audio_card_da7219_m98357a, - }, - { } -}; -MODULE_DEVICE_TABLE(platform, kbl_board_ids); - -static struct platform_driver kabylake_audio = { - .probe = kabylake_audio_probe, - .driver = { - .name = "kbl_da7219_max98357a", - .pm = &snd_soc_pm_ops, - }, - .id_table = kbl_board_ids, -}; - -module_platform_driver(kabylake_audio) - -/* Module information */ -MODULE_DESCRIPTION("Audio Machine driver-DA7219 & MAX98357A in I2S mode"); -MODULE_AUTHOR("Naveen Manohar "); -MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/intel/boards/kbl_da7219_max98927.c b/sound/soc/intel/boards/kbl_da7219_max98927.c deleted file mode 100644 index 02ed77a07e23d6..00000000000000 --- a/sound/soc/intel/boards/kbl_da7219_max98927.c +++ /dev/null @@ -1,1175 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -// Copyright(c) 2018 Intel Corporation. - -/* - * Intel Kabylake I2S Machine Driver with MAX98927, MAX98373 & DA7219 Codecs - * - * Modified from: - * Intel Kabylake I2S Machine driver supporting MAX98927 and - * RT5663 codecs - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include "../../codecs/da7219.h" -#include "../../codecs/hdac_hdmi.h" - -#define KBL_DIALOG_CODEC_DAI "da7219-hifi" -#define MAX98927_CODEC_DAI "max98927-aif1" -#define MAX98927_DEV0_NAME "i2c-MX98927:00" -#define MAX98927_DEV1_NAME "i2c-MX98927:01" - -#define MAX98373_CODEC_DAI "max98373-aif1" -#define MAX98373_DEV0_NAME "i2c-MX98373:00" -#define MAX98373_DEV1_NAME "i2c-MX98373:01" - - -#define DUAL_CHANNEL 2 -#define QUAD_CHANNEL 4 -#define NAME_SIZE 32 - -static struct snd_soc_card *kabylake_audio_card; -static struct snd_soc_jack kabylake_hdmi[3]; - -struct kbl_hdmi_pcm { - struct list_head head; - struct snd_soc_dai *codec_dai; - int device; -}; - -struct kbl_codec_private { - struct snd_soc_jack kabylake_headset; - struct list_head hdmi_pcm_list; -}; - -enum { - KBL_DPCM_AUDIO_PB = 0, - KBL_DPCM_AUDIO_ECHO_REF_CP, - KBL_DPCM_AUDIO_REF_CP, - KBL_DPCM_AUDIO_DMIC_CP, - KBL_DPCM_AUDIO_HDMI1_PB, - KBL_DPCM_AUDIO_HDMI2_PB, - KBL_DPCM_AUDIO_HDMI3_PB, - KBL_DPCM_AUDIO_HS_PB, - KBL_DPCM_AUDIO_CP, -}; - -static int platform_clock_control(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *k, int event) -{ - struct snd_soc_dapm_context *dapm = w->dapm; - struct snd_soc_card *card = dapm->card; - struct snd_soc_dai *codec_dai; - int ret = 0; - - codec_dai = snd_soc_card_get_codec_dai(card, KBL_DIALOG_CODEC_DAI); - if (!codec_dai) { - dev_err(card->dev, "Codec dai not found; Unable to set/unset codec pll\n"); - return -EIO; - } - - /* Configure sysclk for codec */ - ret = snd_soc_dai_set_sysclk(codec_dai, DA7219_CLKSRC_MCLK, 24576000, - SND_SOC_CLOCK_IN); - if (ret) { - dev_err(card->dev, "can't set codec sysclk configuration\n"); - return ret; - } - - if (SND_SOC_DAPM_EVENT_OFF(event)) { - ret = snd_soc_dai_set_pll(codec_dai, 0, - DA7219_SYSCLK_MCLK, 0, 0); - if (ret) - dev_err(card->dev, "failed to stop PLL: %d\n", ret); - } else if (SND_SOC_DAPM_EVENT_ON(event)) { - ret = snd_soc_dai_set_pll(codec_dai, 0, DA7219_SYSCLK_PLL_SRM, - 0, DA7219_PLL_FREQ_OUT_98304); - if (ret) - dev_err(card->dev, "failed to start PLL: %d\n", ret); - } - - return ret; -} - -static const struct snd_kcontrol_new kabylake_controls[] = { - SOC_DAPM_PIN_SWITCH("Headphone Jack"), - SOC_DAPM_PIN_SWITCH("Headset Mic"), - SOC_DAPM_PIN_SWITCH("Left Spk"), - SOC_DAPM_PIN_SWITCH("Right Spk"), - SOC_DAPM_PIN_SWITCH("Line Out"), -}; - -static const struct snd_soc_dapm_widget kabylake_widgets[] = { - SND_SOC_DAPM_HP("Headphone Jack", NULL), - SND_SOC_DAPM_MIC("Headset Mic", NULL), - SND_SOC_DAPM_SPK("Left Spk", NULL), - SND_SOC_DAPM_SPK("Right Spk", NULL), - SND_SOC_DAPM_LINE("Line Out", NULL), - SND_SOC_DAPM_MIC("SoC DMIC", NULL), - SND_SOC_DAPM_SPK("HDMI1", NULL), - SND_SOC_DAPM_SPK("HDMI2", NULL), - SND_SOC_DAPM_SPK("HDMI3", NULL), - SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0, - platform_clock_control, SND_SOC_DAPM_PRE_PMU | - SND_SOC_DAPM_POST_PMD), -}; - -static struct snd_soc_jack_pin jack_pins[] = { - { - .pin = "Headphone Jack", - .mask = SND_JACK_HEADPHONE, - }, - { - .pin = "Headset Mic", - .mask = SND_JACK_MICROPHONE, - }, - { - .pin = "Line Out", - .mask = SND_JACK_MICROPHONE, - }, -}; - -static const struct snd_soc_dapm_route kabylake_map[] = { - /* speaker */ - { "Left Spk", NULL, "Left BE_OUT" }, - { "Right Spk", NULL, "Right BE_OUT" }, - - /* other jacks */ - { "DMic", NULL, "SoC DMIC" }, - - {"HDMI1", NULL, "hif5-0 Output"}, - {"HDMI2", NULL, "hif6-0 Output"}, - {"HDMI3", NULL, "hif7-0 Output"}, - - /* CODEC BE connections */ - { "Left HiFi Playback", NULL, "ssp0 Tx" }, - { "Right HiFi Playback", NULL, "ssp0 Tx" }, - { "ssp0 Tx", NULL, "spk_out" }, - - /* IV feedback path */ - { "codec0_fb_in", NULL, "ssp0 Rx"}, - { "ssp0 Rx", NULL, "Left HiFi Capture" }, - { "ssp0 Rx", NULL, "Right HiFi Capture" }, - - /* AEC capture path */ - { "echo_ref_out", NULL, "ssp0 Rx" }, - - /* DMIC */ - { "dmic01_hifi", NULL, "DMIC01 Rx" }, - { "DMIC01 Rx", NULL, "DMIC AIF" }, - - { "hifi1", NULL, "iDisp1 Tx" }, - { "iDisp1 Tx", NULL, "iDisp1_out" }, - { "hifi2", NULL, "iDisp2 Tx" }, - { "iDisp2 Tx", NULL, "iDisp2_out" }, - { "hifi3", NULL, "iDisp3 Tx"}, - { "iDisp3 Tx", NULL, "iDisp3_out"}, -}; - -static const struct snd_soc_dapm_route kabylake_ssp1_map[] = { - { "Headphone Jack", NULL, "HPL" }, - { "Headphone Jack", NULL, "HPR" }, - - /* other jacks */ - { "MIC", NULL, "Headset Mic" }, - - /* CODEC BE connections */ - { "Playback", NULL, "ssp1 Tx" }, - { "ssp1 Tx", NULL, "codec1_out" }, - - { "hs_in", NULL, "ssp1 Rx" }, - { "ssp1 Rx", NULL, "Capture" }, - - { "Headphone Jack", NULL, "Platform Clock" }, - { "Headset Mic", NULL, "Platform Clock" }, - { "Line Out", NULL, "Platform Clock" }, -}; - -static int kabylake_ssp0_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *runtime = snd_soc_substream_to_rtd(substream); - struct snd_soc_dai *codec_dai; - int ret, j; - - for_each_rtd_codec_dais(runtime, j, codec_dai) { - - if (!strcmp(codec_dai->component->name, MAX98927_DEV0_NAME)) { - ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x30, 3, 8, 16); - if (ret < 0) { - dev_err(runtime->dev, "DEV0 TDM slot err:%d\n", ret); - return ret; - } - } - if (!strcmp(codec_dai->component->name, MAX98927_DEV1_NAME)) { - ret = snd_soc_dai_set_tdm_slot(codec_dai, 0xC0, 3, 8, 16); - if (ret < 0) { - dev_err(runtime->dev, "DEV1 TDM slot err:%d\n", ret); - return ret; - } - } - if (!strcmp(codec_dai->component->name, MAX98373_DEV0_NAME)) { - ret = snd_soc_dai_set_tdm_slot(codec_dai, - 0x30, 3, 8, 16); - if (ret < 0) { - dev_err(runtime->dev, - "DEV0 TDM slot err:%d\n", ret); - return ret; - } - } - if (!strcmp(codec_dai->component->name, MAX98373_DEV1_NAME)) { - ret = snd_soc_dai_set_tdm_slot(codec_dai, - 0xC0, 3, 8, 16); - if (ret < 0) { - dev_err(runtime->dev, - "DEV1 TDM slot err:%d\n", ret); - return ret; - } - } - } - - return 0; -} - -static int kabylake_ssp0_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); - struct snd_soc_dai *codec_dai; - int j, ret; - - for_each_rtd_codec_dais(rtd, j, codec_dai) { - const char *name = codec_dai->component->name; - struct snd_soc_component *component = codec_dai->component; - struct snd_soc_dapm_context *dapm = - snd_soc_component_get_dapm(component); - char pin_name[20]; - - if (strcmp(name, MAX98927_DEV0_NAME) && - strcmp(name, MAX98927_DEV1_NAME) && - strcmp(name, MAX98373_DEV0_NAME) && - strcmp(name, MAX98373_DEV1_NAME)) - continue; - - snprintf(pin_name, ARRAY_SIZE(pin_name), "%s Spk", - codec_dai->component->name_prefix); - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - ret = snd_soc_dapm_enable_pin(dapm, pin_name); - if (ret) { - dev_err(rtd->dev, "failed to enable %s: %d\n", - pin_name, ret); - return ret; - } - snd_soc_dapm_sync(dapm); - break; - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - ret = snd_soc_dapm_disable_pin(dapm, pin_name); - if (ret) { - dev_err(rtd->dev, "failed to disable %s: %d\n", - pin_name, ret); - return ret; - } - snd_soc_dapm_sync(dapm); - break; - } - } - - return 0; -} - -static const struct snd_soc_ops kabylake_ssp0_ops = { - .hw_params = kabylake_ssp0_hw_params, - .trigger = kabylake_ssp0_trigger, -}; - -static int kabylake_ssp_fixup(struct snd_soc_pcm_runtime *rtd, - struct snd_pcm_hw_params *params) -{ - struct snd_interval *rate = hw_param_interval(params, - SNDRV_PCM_HW_PARAM_RATE); - struct snd_interval *chan = hw_param_interval(params, - SNDRV_PCM_HW_PARAM_CHANNELS); - struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); - struct snd_soc_dpcm *dpcm, *rtd_dpcm = NULL; - - /* - * The following loop will be called only for playback stream - * In this platform, there is only one playback device on every SSP - */ - for_each_dpcm_fe(rtd, SNDRV_PCM_STREAM_PLAYBACK, dpcm) { - rtd_dpcm = dpcm; - break; - } - - /* - * This following loop will be called only for capture stream - * In this platform, there is only one capture device on every SSP - */ - for_each_dpcm_fe(rtd, SNDRV_PCM_STREAM_CAPTURE, dpcm) { - rtd_dpcm = dpcm; - break; - } - - if (!rtd_dpcm) - return -EINVAL; - - /* - * The above 2 loops are mutually exclusive based on the stream direction, - * thus rtd_dpcm variable will never be overwritten - */ - - /* - * The ADSP will convert the FE rate to 48k, stereo, 24 bit - */ - if (!strcmp(rtd_dpcm->fe->dai_link->name, "Kbl Audio Port") || - !strcmp(rtd_dpcm->fe->dai_link->name, "Kbl Audio Headset Playback") || - !strcmp(rtd_dpcm->fe->dai_link->name, "Kbl Audio Capture Port")) { - rate->min = rate->max = 48000; - chan->min = chan->max = 2; - snd_mask_none(fmt); - snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S24_LE); - } - - /* - * The speaker on the SSP0 supports S16_LE and not S24_LE. - * thus changing the mask here - */ - if (!strcmp(rtd_dpcm->be->dai_link->name, "SSP0-Codec")) - snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S16_LE); - - return 0; -} - -static int kabylake_da7219_codec_init(struct snd_soc_pcm_runtime *rtd) -{ - struct kbl_codec_private *ctx = snd_soc_card_get_drvdata(rtd->card); - struct snd_soc_component *component = snd_soc_rtd_to_codec(rtd, 0)->component; - struct snd_soc_jack *jack; - struct snd_soc_card *card = rtd->card; - int ret; - - - ret = snd_soc_dapm_add_routes(&card->dapm, - kabylake_ssp1_map, - ARRAY_SIZE(kabylake_ssp1_map)); - - if (ret) - return ret; - - /* - * Headset buttons map to the google Reference headset. - * These can be configured by userspace. - */ - ret = snd_soc_card_jack_new_pins(kabylake_audio_card, "Headset Jack", - SND_JACK_HEADSET | SND_JACK_BTN_0 | SND_JACK_BTN_1 | - SND_JACK_BTN_2 | SND_JACK_BTN_3 | SND_JACK_LINEOUT, - &ctx->kabylake_headset, - jack_pins, - ARRAY_SIZE(jack_pins)); - if (ret) { - dev_err(rtd->dev, "Headset Jack creation failed: %d\n", ret); - return ret; - } - - jack = &ctx->kabylake_headset; - snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_PLAYPAUSE); - snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOLUMEUP); - snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEDOWN); - snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOICECOMMAND); - - snd_soc_component_set_jack(component, &ctx->kabylake_headset, NULL); - - return 0; -} - -static int kabylake_dmic_init(struct snd_soc_pcm_runtime *rtd) -{ - int ret; - ret = snd_soc_dapm_ignore_suspend(&rtd->card->dapm, "SoC DMIC"); - if (ret) - dev_err(rtd->dev, "SoC DMIC - Ignore suspend failed %d\n", ret); - - return ret; -} - -static int kabylake_hdmi_init(struct snd_soc_pcm_runtime *rtd, int device) -{ - struct kbl_codec_private *ctx = snd_soc_card_get_drvdata(rtd->card); - struct snd_soc_dai *dai = snd_soc_rtd_to_codec(rtd, 0); - struct kbl_hdmi_pcm *pcm; - - pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL); - if (!pcm) - return -ENOMEM; - - pcm->device = device; - pcm->codec_dai = dai; - - list_add_tail(&pcm->head, &ctx->hdmi_pcm_list); - - return 0; -} - -static int kabylake_hdmi1_init(struct snd_soc_pcm_runtime *rtd) -{ - return kabylake_hdmi_init(rtd, KBL_DPCM_AUDIO_HDMI1_PB); -} - -static int kabylake_hdmi2_init(struct snd_soc_pcm_runtime *rtd) -{ - return kabylake_hdmi_init(rtd, KBL_DPCM_AUDIO_HDMI2_PB); -} - -static int kabylake_hdmi3_init(struct snd_soc_pcm_runtime *rtd) -{ - return kabylake_hdmi_init(rtd, KBL_DPCM_AUDIO_HDMI3_PB); -} - -static int kabylake_da7219_fe_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_dapm_context *dapm; - struct snd_soc_component *component = snd_soc_rtd_to_cpu(rtd, 0)->component; - - dapm = snd_soc_component_get_dapm(component); - snd_soc_dapm_ignore_suspend(dapm, "Reference Capture"); - - return 0; -} - -static const unsigned int rates[] = { - 48000, -}; - -static const struct snd_pcm_hw_constraint_list constraints_rates = { - .count = ARRAY_SIZE(rates), - .list = rates, - .mask = 0, -}; - -static const unsigned int channels[] = { - DUAL_CHANNEL, -}; - -static const struct snd_pcm_hw_constraint_list constraints_channels = { - .count = ARRAY_SIZE(channels), - .list = channels, - .mask = 0, -}; - -static unsigned int channels_quad[] = { - QUAD_CHANNEL, -}; - -static struct snd_pcm_hw_constraint_list constraints_channels_quad = { - .count = ARRAY_SIZE(channels_quad), - .list = channels_quad, - .mask = 0, -}; - -static int kbl_fe_startup(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - - /* - * On this platform for PCM device we support, - * 48Khz - * stereo - * 16 bit audio - */ - - runtime->hw.channels_max = DUAL_CHANNEL; - snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, - &constraints_channels); - - runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE; - snd_pcm_hw_constraint_msbits(runtime, 0, 16, 16); - - snd_pcm_hw_constraint_list(runtime, 0, - SNDRV_PCM_HW_PARAM_RATE, &constraints_rates); - - return 0; -} - -static const struct snd_soc_ops kabylake_da7219_fe_ops = { - .startup = kbl_fe_startup, -}; - -static int kabylake_dmic_fixup(struct snd_soc_pcm_runtime *rtd, - struct snd_pcm_hw_params *params) -{ - struct snd_interval *chan = hw_param_interval(params, - SNDRV_PCM_HW_PARAM_CHANNELS); - - /* - * set BE channel constraint as user FE channels - */ - - if (params_channels(params) == 2) - chan->min = chan->max = 2; - else - chan->min = chan->max = 4; - - return 0; -} - -static int kabylake_dmic_startup(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - - runtime->hw.channels_min = runtime->hw.channels_max = QUAD_CHANNEL; - snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, - &constraints_channels_quad); - - return snd_pcm_hw_constraint_list(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_RATE, &constraints_rates); -} - -static const struct snd_soc_ops kabylake_dmic_ops = { - .startup = kabylake_dmic_startup, -}; - -static const unsigned int rates_16000[] = { - 16000, -}; - -static const struct snd_pcm_hw_constraint_list constraints_16000 = { - .count = ARRAY_SIZE(rates_16000), - .list = rates_16000, -}; - -static const unsigned int ch_mono[] = { - 1, -}; -static const struct snd_pcm_hw_constraint_list constraints_refcap = { - .count = ARRAY_SIZE(ch_mono), - .list = ch_mono, -}; - -static int kabylake_refcap_startup(struct snd_pcm_substream *substream) -{ - substream->runtime->hw.channels_max = 1; - snd_pcm_hw_constraint_list(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_CHANNELS, - &constraints_refcap); - - return snd_pcm_hw_constraint_list(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_RATE, - &constraints_16000); -} - - -static const struct snd_soc_ops skylake_refcap_ops = { - .startup = kabylake_refcap_startup, -}; - -static struct snd_soc_codec_conf max98927_codec_conf[] = { - - { - .dlc = COMP_CODEC_CONF(MAX98927_DEV0_NAME), - .name_prefix = "Right", - }, - - { - .dlc = COMP_CODEC_CONF(MAX98927_DEV1_NAME), - .name_prefix = "Left", - }, -}; - -static struct snd_soc_codec_conf max98373_codec_conf[] = { - - { - .dlc = COMP_CODEC_CONF(MAX98373_DEV0_NAME), - .name_prefix = "Right", - }, - - { - .dlc = COMP_CODEC_CONF(MAX98373_DEV1_NAME), - .name_prefix = "Left", - }, -}; - -static struct snd_soc_dai_link_component max98373_ssp0_codec_components[] = { - { /* Left */ - .name = MAX98373_DEV0_NAME, - .dai_name = MAX98373_CODEC_DAI, - }, - - { /* For Right */ - .name = MAX98373_DEV1_NAME, - .dai_name = MAX98373_CODEC_DAI, - }, - -}; - -SND_SOC_DAILINK_DEF(dummy, - DAILINK_COMP_ARRAY(COMP_DUMMY())); - -SND_SOC_DAILINK_DEF(system, - DAILINK_COMP_ARRAY(COMP_CPU("System Pin"))); - -SND_SOC_DAILINK_DEF(echoref, - DAILINK_COMP_ARRAY(COMP_CPU("Echoref Pin"))); - -SND_SOC_DAILINK_DEF(reference, - DAILINK_COMP_ARRAY(COMP_CPU("Reference Pin"))); - -SND_SOC_DAILINK_DEF(dmic, - DAILINK_COMP_ARRAY(COMP_CPU("DMIC Pin"))); - -SND_SOC_DAILINK_DEF(hdmi1, - DAILINK_COMP_ARRAY(COMP_CPU("HDMI1 Pin"))); - -SND_SOC_DAILINK_DEF(hdmi2, - DAILINK_COMP_ARRAY(COMP_CPU("HDMI2 Pin"))); - -SND_SOC_DAILINK_DEF(hdmi3, - DAILINK_COMP_ARRAY(COMP_CPU("HDMI3 Pin"))); - -SND_SOC_DAILINK_DEF(system2, - DAILINK_COMP_ARRAY(COMP_CPU("System Pin2"))); - -SND_SOC_DAILINK_DEF(ssp0_pin, - DAILINK_COMP_ARRAY(COMP_CPU("SSP0 Pin"))); -SND_SOC_DAILINK_DEF(ssp0_codec, - DAILINK_COMP_ARRAY( - /* Left */ COMP_CODEC(MAX98927_DEV0_NAME, MAX98927_CODEC_DAI), - /* For Right */ COMP_CODEC(MAX98927_DEV1_NAME, MAX98927_CODEC_DAI))); - -SND_SOC_DAILINK_DEF(ssp1_pin, - DAILINK_COMP_ARRAY(COMP_CPU("SSP1 Pin"))); -SND_SOC_DAILINK_DEF(ssp1_codec, - DAILINK_COMP_ARRAY(COMP_CODEC("i2c-DLGS7219:00", - KBL_DIALOG_CODEC_DAI))); - -SND_SOC_DAILINK_DEF(dmic_pin, - DAILINK_COMP_ARRAY(COMP_CPU("DMIC01 Pin"))); -SND_SOC_DAILINK_DEF(dmic_codec, - DAILINK_COMP_ARRAY(COMP_CODEC("dmic-codec", "dmic-hifi"))); - -SND_SOC_DAILINK_DEF(idisp1_pin, - DAILINK_COMP_ARRAY(COMP_CPU("iDisp1 Pin"))); -SND_SOC_DAILINK_DEF(idisp1_codec, - DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi1"))); - -SND_SOC_DAILINK_DEF(idisp2_pin, - DAILINK_COMP_ARRAY(COMP_CPU("iDisp2 Pin"))); -SND_SOC_DAILINK_DEF(idisp2_codec, - DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi2"))); - -SND_SOC_DAILINK_DEF(idisp3_pin, - DAILINK_COMP_ARRAY(COMP_CPU("iDisp3 Pin"))); -SND_SOC_DAILINK_DEF(idisp3_codec, - DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi3"))); - -SND_SOC_DAILINK_DEF(platform, - DAILINK_COMP_ARRAY(COMP_PLATFORM("0000:00:1f.3"))); - -/* kabylake digital audio interface glue - connects codec <--> CPU */ -static struct snd_soc_dai_link kabylake_dais[] = { - /* Front End DAI links */ - [KBL_DPCM_AUDIO_PB] = { - .name = "Kbl Audio Port", - .stream_name = "Audio", - .dynamic = 1, - .nonatomic = 1, - .init = kabylake_da7219_fe_init, - .trigger = { - SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .dpcm_playback = 1, - .ops = &kabylake_da7219_fe_ops, - SND_SOC_DAILINK_REG(system, dummy, platform), - }, - [KBL_DPCM_AUDIO_ECHO_REF_CP] = { - .name = "Kbl Audio Echo Reference cap", - .stream_name = "Echoreference Capture", - .init = NULL, - .dpcm_capture = 1, - .nonatomic = 1, - SND_SOC_DAILINK_REG(echoref, dummy, platform), - }, - [KBL_DPCM_AUDIO_REF_CP] = { - .name = "Kbl Audio Reference cap", - .stream_name = "Wake on Voice", - .init = NULL, - .dpcm_capture = 1, - .nonatomic = 1, - .dynamic = 1, - .ops = &skylake_refcap_ops, - SND_SOC_DAILINK_REG(reference, dummy, platform), - }, - [KBL_DPCM_AUDIO_DMIC_CP] = { - .name = "Kbl Audio DMIC cap", - .stream_name = "dmiccap", - .init = NULL, - .dpcm_capture = 1, - .nonatomic = 1, - .dynamic = 1, - .ops = &kabylake_dmic_ops, - SND_SOC_DAILINK_REG(dmic, dummy, platform), - }, - [KBL_DPCM_AUDIO_HDMI1_PB] = { - .name = "Kbl HDMI Port1", - .stream_name = "Hdmi1", - .dpcm_playback = 1, - .init = NULL, - .trigger = { - SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .nonatomic = 1, - .dynamic = 1, - SND_SOC_DAILINK_REG(hdmi1, dummy, platform), - }, - [KBL_DPCM_AUDIO_HDMI2_PB] = { - .name = "Kbl HDMI Port2", - .stream_name = "Hdmi2", - .dpcm_playback = 1, - .init = NULL, - .trigger = { - SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .nonatomic = 1, - .dynamic = 1, - SND_SOC_DAILINK_REG(hdmi2, dummy, platform), - }, - [KBL_DPCM_AUDIO_HDMI3_PB] = { - .name = "Kbl HDMI Port3", - .stream_name = "Hdmi3", - .trigger = { - SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .dpcm_playback = 1, - .init = NULL, - .nonatomic = 1, - .dynamic = 1, - SND_SOC_DAILINK_REG(hdmi3, dummy, platform), - }, - [KBL_DPCM_AUDIO_HS_PB] = { - .name = "Kbl Audio Headset Playback", - .stream_name = "Headset Audio", - .dpcm_playback = 1, - .nonatomic = 1, - .dynamic = 1, - .init = kabylake_da7219_fe_init, - .trigger = { - SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .ops = &kabylake_da7219_fe_ops, - SND_SOC_DAILINK_REG(system2, dummy, platform), - }, - [KBL_DPCM_AUDIO_CP] = { - .name = "Kbl Audio Capture Port", - .stream_name = "Audio Record", - .dynamic = 1, - .nonatomic = 1, - .trigger = { - SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .dpcm_capture = 1, - .ops = &kabylake_da7219_fe_ops, - SND_SOC_DAILINK_REG(system, dummy, platform), - }, - - /* Back End DAI links */ - { - /* SSP0 - Codec */ - .name = "SSP0-Codec", - .id = 0, - .no_pcm = 1, - .dai_fmt = SND_SOC_DAIFMT_DSP_B | - SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBC_CFC, - .dpcm_playback = 1, - .dpcm_capture = 1, - .ignore_pmdown_time = 1, - .be_hw_params_fixup = kabylake_ssp_fixup, - .ops = &kabylake_ssp0_ops, - SND_SOC_DAILINK_REG(ssp0_pin, ssp0_codec, platform), - }, - { - /* SSP1 - Codec */ - .name = "SSP1-Codec", - .id = 1, - .no_pcm = 1, - .init = kabylake_da7219_codec_init, - .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBC_CFC, - .ignore_pmdown_time = 1, - .be_hw_params_fixup = kabylake_ssp_fixup, - .dpcm_playback = 1, - .dpcm_capture = 1, - SND_SOC_DAILINK_REG(ssp1_pin, ssp1_codec, platform), - }, - { - .name = "dmic01", - .id = 2, - .init = kabylake_dmic_init, - .be_hw_params_fixup = kabylake_dmic_fixup, - .ignore_suspend = 1, - .dpcm_capture = 1, - .no_pcm = 1, - SND_SOC_DAILINK_REG(dmic_pin, dmic_codec, platform), - }, - { - .name = "iDisp1", - .id = 3, - .dpcm_playback = 1, - .init = kabylake_hdmi1_init, - .no_pcm = 1, - SND_SOC_DAILINK_REG(idisp1_pin, idisp1_codec, platform), - }, - { - .name = "iDisp2", - .id = 4, - .init = kabylake_hdmi2_init, - .dpcm_playback = 1, - .no_pcm = 1, - SND_SOC_DAILINK_REG(idisp2_pin, idisp2_codec, platform), - }, - { - .name = "iDisp3", - .id = 5, - .init = kabylake_hdmi3_init, - .dpcm_playback = 1, - .no_pcm = 1, - SND_SOC_DAILINK_REG(idisp3_pin, idisp3_codec, platform), - }, -}; - -/* kabylake digital audio interface glue - connects codec <--> CPU */ -static struct snd_soc_dai_link kabylake_max98_927_373_dais[] = { - /* Front End DAI links */ - [KBL_DPCM_AUDIO_PB] = { - .name = "Kbl Audio Port", - .stream_name = "Audio", - .dynamic = 1, - .nonatomic = 1, - .init = kabylake_da7219_fe_init, - .trigger = { - SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .dpcm_playback = 1, - .ops = &kabylake_da7219_fe_ops, - SND_SOC_DAILINK_REG(system, dummy, platform), - }, - [KBL_DPCM_AUDIO_ECHO_REF_CP] = { - .name = "Kbl Audio Echo Reference cap", - .stream_name = "Echoreference Capture", - .init = NULL, - .dpcm_capture = 1, - .nonatomic = 1, - SND_SOC_DAILINK_REG(echoref, dummy, platform), - }, - [KBL_DPCM_AUDIO_REF_CP] = { - .name = "Kbl Audio Reference cap", - .stream_name = "Wake on Voice", - .init = NULL, - .dpcm_capture = 1, - .nonatomic = 1, - .dynamic = 1, - .ops = &skylake_refcap_ops, - SND_SOC_DAILINK_REG(reference, dummy, platform), - }, - [KBL_DPCM_AUDIO_DMIC_CP] = { - .name = "Kbl Audio DMIC cap", - .stream_name = "dmiccap", - .init = NULL, - .dpcm_capture = 1, - .nonatomic = 1, - .dynamic = 1, - .ops = &kabylake_dmic_ops, - SND_SOC_DAILINK_REG(dmic, dummy, platform), - }, - [KBL_DPCM_AUDIO_HDMI1_PB] = { - .name = "Kbl HDMI Port1", - .stream_name = "Hdmi1", - .dpcm_playback = 1, - .init = NULL, - .trigger = { - SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .nonatomic = 1, - .dynamic = 1, - SND_SOC_DAILINK_REG(hdmi1, dummy, platform), - }, - [KBL_DPCM_AUDIO_HDMI2_PB] = { - .name = "Kbl HDMI Port2", - .stream_name = "Hdmi2", - .dpcm_playback = 1, - .init = NULL, - .trigger = { - SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .nonatomic = 1, - .dynamic = 1, - SND_SOC_DAILINK_REG(hdmi2, dummy, platform), - }, - [KBL_DPCM_AUDIO_HDMI3_PB] = { - .name = "Kbl HDMI Port3", - .stream_name = "Hdmi3", - .trigger = { - SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .dpcm_playback = 1, - .init = NULL, - .nonatomic = 1, - .dynamic = 1, - SND_SOC_DAILINK_REG(hdmi3, dummy, platform), - }, - - /* Back End DAI links */ - { - /* SSP0 - Codec */ - .name = "SSP0-Codec", - .id = 0, - .no_pcm = 1, - .dai_fmt = SND_SOC_DAIFMT_DSP_B | - SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBC_CFC, - .dpcm_playback = 1, - .dpcm_capture = 1, - .ignore_pmdown_time = 1, - .be_hw_params_fixup = kabylake_ssp_fixup, - .ops = &kabylake_ssp0_ops, - SND_SOC_DAILINK_REG(ssp0_pin, ssp0_codec), - }, - { - .name = "dmic01", - .id = 1, - .init = kabylake_dmic_init, - .be_hw_params_fixup = kabylake_dmic_fixup, - .ignore_suspend = 1, - .dpcm_capture = 1, - .no_pcm = 1, - SND_SOC_DAILINK_REG(dmic_pin, dmic_codec, platform), - }, - { - .name = "iDisp1", - .id = 2, - .dpcm_playback = 1, - .init = kabylake_hdmi1_init, - .no_pcm = 1, - SND_SOC_DAILINK_REG(idisp1_pin, idisp1_codec, platform), - }, - { - .name = "iDisp2", - .id = 3, - .init = kabylake_hdmi2_init, - .dpcm_playback = 1, - .no_pcm = 1, - SND_SOC_DAILINK_REG(idisp2_pin, idisp2_codec, platform), - }, - { - .name = "iDisp3", - .id = 4, - .init = kabylake_hdmi3_init, - .dpcm_playback = 1, - .no_pcm = 1, - SND_SOC_DAILINK_REG(idisp3_pin, idisp3_codec, platform), - }, -}; - -static int kabylake_card_late_probe(struct snd_soc_card *card) -{ - struct kbl_codec_private *ctx = snd_soc_card_get_drvdata(card); - struct kbl_hdmi_pcm *pcm; - struct snd_soc_dapm_context *dapm = &card->dapm; - struct snd_soc_component *component = NULL; - int err, i = 0; - char jack_name[NAME_SIZE]; - - list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) { - component = pcm->codec_dai->component; - snprintf(jack_name, sizeof(jack_name), - "HDMI/DP, pcm=%d Jack", pcm->device); - err = snd_soc_card_jack_new(card, jack_name, - SND_JACK_AVOUT, &kabylake_hdmi[i]); - - if (err) - return err; - - err = hdac_hdmi_jack_init(pcm->codec_dai, pcm->device, - &kabylake_hdmi[i]); - if (err < 0) - return err; - - i++; - } - - if (!component) - return -EINVAL; - - - err = hdac_hdmi_jack_port_init(component, &card->dapm); - - if (err < 0) - return err; - - err = snd_soc_dapm_disable_pin(dapm, "Left Spk"); - if (err) { - dev_err(card->dev, "failed to disable Left Spk: %d\n", err); - return err; - } - - err = snd_soc_dapm_disable_pin(dapm, "Right Spk"); - if (err) { - dev_err(card->dev, "failed to disable Right Spk: %d\n", err); - return err; - } - - return snd_soc_dapm_sync(dapm); -} - -/* kabylake audio machine driver for SPT + DA7219 */ -static struct snd_soc_card kbl_audio_card_da7219_m98927 = { - .name = "kblda7219m98927", - .owner = THIS_MODULE, - .dai_link = kabylake_dais, - .num_links = ARRAY_SIZE(kabylake_dais), - .controls = kabylake_controls, - .num_controls = ARRAY_SIZE(kabylake_controls), - .dapm_widgets = kabylake_widgets, - .num_dapm_widgets = ARRAY_SIZE(kabylake_widgets), - .dapm_routes = kabylake_map, - .num_dapm_routes = ARRAY_SIZE(kabylake_map), - .codec_conf = max98927_codec_conf, - .num_configs = ARRAY_SIZE(max98927_codec_conf), - .fully_routed = true, - .disable_route_checks = true, - .late_probe = kabylake_card_late_probe, -}; - -/* kabylake audio machine driver for Maxim98927 */ -static struct snd_soc_card kbl_audio_card_max98927 = { - .name = "kblmax98927", - .owner = THIS_MODULE, - .dai_link = kabylake_max98_927_373_dais, - .num_links = ARRAY_SIZE(kabylake_max98_927_373_dais), - .controls = kabylake_controls, - .num_controls = ARRAY_SIZE(kabylake_controls), - .dapm_widgets = kabylake_widgets, - .num_dapm_widgets = ARRAY_SIZE(kabylake_widgets), - .dapm_routes = kabylake_map, - .num_dapm_routes = ARRAY_SIZE(kabylake_map), - .codec_conf = max98927_codec_conf, - .num_configs = ARRAY_SIZE(max98927_codec_conf), - .fully_routed = true, - .disable_route_checks = true, - .late_probe = kabylake_card_late_probe, -}; - -static struct snd_soc_card kbl_audio_card_da7219_m98373 = { - .name = "kblda7219m98373", - .owner = THIS_MODULE, - .dai_link = kabylake_dais, - .num_links = ARRAY_SIZE(kabylake_dais), - .controls = kabylake_controls, - .num_controls = ARRAY_SIZE(kabylake_controls), - .dapm_widgets = kabylake_widgets, - .num_dapm_widgets = ARRAY_SIZE(kabylake_widgets), - .dapm_routes = kabylake_map, - .num_dapm_routes = ARRAY_SIZE(kabylake_map), - .codec_conf = max98373_codec_conf, - .num_configs = ARRAY_SIZE(max98373_codec_conf), - .fully_routed = true, - .disable_route_checks = true, - .late_probe = kabylake_card_late_probe, -}; - -static struct snd_soc_card kbl_audio_card_max98373 = { - .name = "kblmax98373", - .owner = THIS_MODULE, - .dai_link = kabylake_max98_927_373_dais, - .num_links = ARRAY_SIZE(kabylake_max98_927_373_dais), - .controls = kabylake_controls, - .num_controls = ARRAY_SIZE(kabylake_controls), - .dapm_widgets = kabylake_widgets, - .num_dapm_widgets = ARRAY_SIZE(kabylake_widgets), - .dapm_routes = kabylake_map, - .num_dapm_routes = ARRAY_SIZE(kabylake_map), - .codec_conf = max98373_codec_conf, - .num_configs = ARRAY_SIZE(max98373_codec_conf), - .fully_routed = true, - .disable_route_checks = true, - .late_probe = kabylake_card_late_probe, -}; - -static int kabylake_audio_probe(struct platform_device *pdev) -{ - struct kbl_codec_private *ctx; - struct snd_soc_dai_link *kbl_dai_link; - struct snd_soc_dai_link_component **codecs; - int i; - - ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); - if (!ctx) - return -ENOMEM; - - INIT_LIST_HEAD(&ctx->hdmi_pcm_list); - - kabylake_audio_card = - (struct snd_soc_card *)pdev->id_entry->driver_data; - - kbl_dai_link = kabylake_audio_card->dai_link; - - /* Update codecs for SSP0 with max98373 codec info */ - if (!strcmp(pdev->name, "kbl_da7219_max98373") || - (!strcmp(pdev->name, "kbl_max98373"))) { - for (i = 0; i < kabylake_audio_card->num_links; ++i) { - if (strcmp(kbl_dai_link[i].name, "SSP0-Codec")) - continue; - - codecs = &(kbl_dai_link[i].codecs); - *codecs = max98373_ssp0_codec_components; - kbl_dai_link[i].num_codecs = - ARRAY_SIZE(max98373_ssp0_codec_components); - break; - } - } - kabylake_audio_card->dev = &pdev->dev; - snd_soc_card_set_drvdata(kabylake_audio_card, ctx); - - return devm_snd_soc_register_card(&pdev->dev, kabylake_audio_card); -} - -static const struct platform_device_id kbl_board_ids[] = { - { - .name = "kbl_da7219_max98927", - .driver_data = - (kernel_ulong_t)&kbl_audio_card_da7219_m98927, - }, - { - .name = "kbl_max98927", - .driver_data = - (kernel_ulong_t)&kbl_audio_card_max98927, - }, - { - .name = "kbl_da7219_max98373", - .driver_data = - (kernel_ulong_t)&kbl_audio_card_da7219_m98373, - }, - { - .name = "kbl_max98373", - .driver_data = - (kernel_ulong_t)&kbl_audio_card_max98373, - }, - { } -}; -MODULE_DEVICE_TABLE(platform, kbl_board_ids); - -static struct platform_driver kabylake_audio = { - .probe = kabylake_audio_probe, - .driver = { - .name = "kbl_da7219_max98_927_373", - .pm = &snd_soc_pm_ops, - }, - .id_table = kbl_board_ids, -}; - -module_platform_driver(kabylake_audio) - -/* Module information */ -MODULE_DESCRIPTION("Audio KabyLake Machine driver for MAX98927/MAX98373 & DA7219"); -MODULE_AUTHOR("Mac Chiang "); -MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/intel/boards/kbl_rt5660.c b/sound/soc/intel/boards/kbl_rt5660.c deleted file mode 100644 index 66885cb36f2489..00000000000000 --- a/sound/soc/intel/boards/kbl_rt5660.c +++ /dev/null @@ -1,567 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -// Copyright(c) 2018-19 Canonical Corporation. - -/* - * Intel Kabylake I2S Machine Driver with RT5660 Codec - * - * Modified from: - * Intel Kabylake I2S Machine driver supporting MAXIM98357a and - * DA7219 codecs - * Also referred to: - * Intel Broadwell I2S Machine driver supporting RT5677 codec - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../../codecs/hdac_hdmi.h" -#include "../../codecs/rt5660.h" - -#define KBL_RT5660_CODEC_DAI "rt5660-aif1" -#define DUAL_CHANNEL 2 - -static struct snd_soc_card *kabylake_audio_card; -static struct snd_soc_jack skylake_hdmi[3]; -static struct snd_soc_jack lineout_jack; -static struct snd_soc_jack mic_jack; - -struct kbl_hdmi_pcm { - struct list_head head; - struct snd_soc_dai *codec_dai; - int device; -}; - -struct kbl_codec_private { - struct gpio_desc *gpio_lo_mute; - struct list_head hdmi_pcm_list; -}; - -enum { - KBL_DPCM_AUDIO_PB = 0, - KBL_DPCM_AUDIO_CP, - KBL_DPCM_AUDIO_HDMI1_PB, - KBL_DPCM_AUDIO_HDMI2_PB, - KBL_DPCM_AUDIO_HDMI3_PB, -}; - -#define GPIO_LINEOUT_MUTE_INDEX 0 -#define GPIO_LINEOUT_DET_INDEX 3 -#define GPIO_LINEIN_DET_INDEX 4 - -static const struct acpi_gpio_params lineout_mute_gpio = { GPIO_LINEOUT_MUTE_INDEX, 0, true }; -static const struct acpi_gpio_params lineout_det_gpio = { GPIO_LINEOUT_DET_INDEX, 0, false }; -static const struct acpi_gpio_params mic_det_gpio = { GPIO_LINEIN_DET_INDEX, 0, false }; - - -static const struct acpi_gpio_mapping acpi_rt5660_gpios[] = { - { "lineout-mute-gpios", &lineout_mute_gpio, 1 }, - { "lineout-det-gpios", &lineout_det_gpio, 1 }, - { "mic-det-gpios", &mic_det_gpio, 1 }, - { NULL }, -}; - -static struct snd_soc_jack_pin lineout_jack_pin = { - .pin = "Line Out", - .mask = SND_JACK_LINEOUT, -}; - -static struct snd_soc_jack_pin mic_jack_pin = { - .pin = "Line In", - .mask = SND_JACK_MICROPHONE, -}; - -static struct snd_soc_jack_gpio lineout_jack_gpio = { - .name = "lineout-det", - .report = SND_JACK_LINEOUT, - .debounce_time = 200, -}; - -static struct snd_soc_jack_gpio mic_jack_gpio = { - .name = "mic-det", - .report = SND_JACK_MICROPHONE, - .debounce_time = 200, -}; - -static int kabylake_5660_event_lineout(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *k, int event) -{ - struct snd_soc_dapm_context *dapm = w->dapm; - struct kbl_codec_private *priv = snd_soc_card_get_drvdata(dapm->card); - - gpiod_set_value_cansleep(priv->gpio_lo_mute, - !(SND_SOC_DAPM_EVENT_ON(event))); - - return 0; -} - -static const struct snd_kcontrol_new kabylake_rt5660_controls[] = { - SOC_DAPM_PIN_SWITCH("Line In"), - SOC_DAPM_PIN_SWITCH("Line Out"), -}; - -static const struct snd_soc_dapm_widget kabylake_rt5660_widgets[] = { - SND_SOC_DAPM_MIC("Line In", NULL), - SND_SOC_DAPM_LINE("Line Out", kabylake_5660_event_lineout), -}; - -static const struct snd_soc_dapm_route kabylake_rt5660_map[] = { - /* other jacks */ - {"IN1P", NULL, "Line In"}, - {"IN2P", NULL, "Line In"}, - {"Line Out", NULL, "LOUTR"}, - {"Line Out", NULL, "LOUTL"}, - - /* CODEC BE connections */ - { "AIF1 Playback", NULL, "ssp0 Tx"}, - { "ssp0 Tx", NULL, "codec0_out"}, - - { "codec0_in", NULL, "ssp0 Rx" }, - { "ssp0 Rx", NULL, "AIF1 Capture" }, - - { "hifi1", NULL, "iDisp1 Tx"}, - { "iDisp1 Tx", NULL, "iDisp1_out"}, - { "hifi2", NULL, "iDisp2 Tx"}, - { "iDisp2 Tx", NULL, "iDisp2_out"}, - { "hifi3", NULL, "iDisp3 Tx"}, - { "iDisp3 Tx", NULL, "iDisp3_out"}, -}; - -static int kabylake_ssp0_fixup(struct snd_soc_pcm_runtime *rtd, - struct snd_pcm_hw_params *params) -{ - struct snd_interval *rate = hw_param_interval(params, - SNDRV_PCM_HW_PARAM_RATE); - struct snd_interval *chan = hw_param_interval(params, - SNDRV_PCM_HW_PARAM_CHANNELS); - struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); - - /* The ADSP will convert the FE rate to 48k, stereo */ - rate->min = rate->max = 48000; - chan->min = chan->max = DUAL_CHANNEL; - - /* set SSP0 to 24 bit */ - snd_mask_none(fmt); - snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S24_LE); - - return 0; -} - -static int kabylake_rt5660_codec_init(struct snd_soc_pcm_runtime *rtd) -{ - int ret; - struct kbl_codec_private *ctx = snd_soc_card_get_drvdata(rtd->card); - struct snd_soc_component *component = snd_soc_rtd_to_codec(rtd, 0)->component; - struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); - - ret = devm_acpi_dev_add_driver_gpios(component->dev, acpi_rt5660_gpios); - if (ret) - dev_warn(component->dev, "Failed to add driver gpios\n"); - - /* Request rt5660 GPIO for lineout mute control, return if fails */ - ctx->gpio_lo_mute = gpiod_get(component->dev, "lineout-mute", - GPIOD_OUT_HIGH); - if (IS_ERR(ctx->gpio_lo_mute)) { - dev_err(component->dev, "Can't find GPIO_MUTE# gpio\n"); - return PTR_ERR(ctx->gpio_lo_mute); - } - - /* Create and initialize headphone jack, this jack is not mandatory, don't return if fails */ - ret = snd_soc_card_jack_new_pins(rtd->card, "Lineout Jack", - SND_JACK_LINEOUT, &lineout_jack, - &lineout_jack_pin, 1); - if (ret) - dev_warn(component->dev, "Can't create Lineout jack\n"); - else { - lineout_jack_gpio.gpiod_dev = component->dev; - ret = snd_soc_jack_add_gpios(&lineout_jack, 1, - &lineout_jack_gpio); - if (ret) - dev_warn(component->dev, "Can't add Lineout jack gpio\n"); - } - - /* Create and initialize mic jack, this jack is not mandatory, don't return if fails */ - ret = snd_soc_card_jack_new_pins(rtd->card, "Mic Jack", - SND_JACK_MICROPHONE, &mic_jack, - &mic_jack_pin, 1); - if (ret) - dev_warn(component->dev, "Can't create mic jack\n"); - else { - mic_jack_gpio.gpiod_dev = component->dev; - ret = snd_soc_jack_add_gpios(&mic_jack, 1, &mic_jack_gpio); - if (ret) - dev_warn(component->dev, "Can't add mic jack gpio\n"); - } - - /* Here we enable some dapms in advance to reduce the pop noise for recording via line-in */ - snd_soc_dapm_force_enable_pin(dapm, "MICBIAS1"); - snd_soc_dapm_force_enable_pin(dapm, "BST1"); - snd_soc_dapm_force_enable_pin(dapm, "BST2"); - - return 0; -} - -static void kabylake_rt5660_codec_exit(struct snd_soc_pcm_runtime *rtd) -{ - struct kbl_codec_private *ctx = snd_soc_card_get_drvdata(rtd->card); - - /* - * The .exit() can be reached without going through the .init() - * so explicitly test if the gpiod is valid - */ - if (!IS_ERR_OR_NULL(ctx->gpio_lo_mute)) - gpiod_put(ctx->gpio_lo_mute); -} - -static int kabylake_hdmi_init(struct snd_soc_pcm_runtime *rtd, int device) -{ - struct kbl_codec_private *ctx = snd_soc_card_get_drvdata(rtd->card); - struct snd_soc_dai *dai = snd_soc_rtd_to_codec(rtd, 0); - struct kbl_hdmi_pcm *pcm; - - pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL); - if (!pcm) - return -ENOMEM; - - pcm->device = device; - pcm->codec_dai = dai; - - list_add_tail(&pcm->head, &ctx->hdmi_pcm_list); - - return 0; -} - -static int kabylake_hdmi1_init(struct snd_soc_pcm_runtime *rtd) -{ - return kabylake_hdmi_init(rtd, KBL_DPCM_AUDIO_HDMI1_PB); -} - -static int kabylake_hdmi2_init(struct snd_soc_pcm_runtime *rtd) -{ - return kabylake_hdmi_init(rtd, KBL_DPCM_AUDIO_HDMI2_PB); -} - -static int kabylake_hdmi3_init(struct snd_soc_pcm_runtime *rtd) -{ - return kabylake_hdmi_init(rtd, KBL_DPCM_AUDIO_HDMI3_PB); -} - -static int kabylake_rt5660_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); - struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); - int ret; - - ret = snd_soc_dai_set_sysclk(codec_dai, - RT5660_SCLK_S_PLL1, params_rate(params) * 512, - SND_SOC_CLOCK_IN); - if (ret < 0) { - dev_err(rtd->dev, "snd_soc_dai_set_sysclk err = %d\n", ret); - return ret; - } - - ret = snd_soc_dai_set_pll(codec_dai, 0, - RT5660_PLL1_S_BCLK, - params_rate(params) * 50, - params_rate(params) * 512); - if (ret < 0) - dev_err(codec_dai->dev, "can't set codec pll: %d\n", ret); - - return ret; -} - -static const struct snd_soc_ops kabylake_rt5660_ops = { - .hw_params = kabylake_rt5660_hw_params, -}; - -static const unsigned int rates[] = { - 48000, -}; - -static const struct snd_pcm_hw_constraint_list constraints_rates = { - .count = ARRAY_SIZE(rates), - .list = rates, - .mask = 0, -}; - -static const unsigned int channels[] = { - DUAL_CHANNEL, -}; - -static const struct snd_pcm_hw_constraint_list constraints_channels = { - .count = ARRAY_SIZE(channels), - .list = channels, - .mask = 0, -}; - -static int kbl_fe_startup(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - - /* - * On this platform for PCM device we support, - * 48Khz - * stereo - * 16 bit audio - */ - - runtime->hw.channels_max = DUAL_CHANNEL; - snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, - &constraints_channels); - - runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE; - snd_pcm_hw_constraint_msbits(runtime, 0, 16, 16); - - snd_pcm_hw_constraint_list(runtime, 0, - SNDRV_PCM_HW_PARAM_RATE, &constraints_rates); - - return 0; -} - -static const struct snd_soc_ops kabylake_rt5660_fe_ops = { - .startup = kbl_fe_startup, -}; - -SND_SOC_DAILINK_DEF(dummy, - DAILINK_COMP_ARRAY(COMP_DUMMY())); - -SND_SOC_DAILINK_DEF(system, - DAILINK_COMP_ARRAY(COMP_CPU("System Pin"))); - -SND_SOC_DAILINK_DEF(hdmi1, - DAILINK_COMP_ARRAY(COMP_CPU("HDMI1 Pin"))); - -SND_SOC_DAILINK_DEF(hdmi2, - DAILINK_COMP_ARRAY(COMP_CPU("HDMI2 Pin"))); - -SND_SOC_DAILINK_DEF(hdmi3, - DAILINK_COMP_ARRAY(COMP_CPU("HDMI3 Pin"))); - -SND_SOC_DAILINK_DEF(ssp0_pin, - DAILINK_COMP_ARRAY(COMP_CPU("SSP0 Pin"))); -SND_SOC_DAILINK_DEF(ssp0_codec, - DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10EC3277:00", KBL_RT5660_CODEC_DAI))); - -SND_SOC_DAILINK_DEF(idisp1_pin, - DAILINK_COMP_ARRAY(COMP_CPU("iDisp1 Pin"))); -SND_SOC_DAILINK_DEF(idisp1_codec, - DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi1"))); - -SND_SOC_DAILINK_DEF(idisp2_pin, - DAILINK_COMP_ARRAY(COMP_CPU("iDisp2 Pin"))); -SND_SOC_DAILINK_DEF(idisp2_codec, - DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi2"))); - -SND_SOC_DAILINK_DEF(idisp3_pin, - DAILINK_COMP_ARRAY(COMP_CPU("iDisp3 Pin"))); -SND_SOC_DAILINK_DEF(idisp3_codec, - DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi3"))); - -SND_SOC_DAILINK_DEF(platform, - DAILINK_COMP_ARRAY(COMP_PLATFORM("0000:00:1f.3"))); - -/* kabylake digital audio interface glue - connects rt5660 codec <--> CPU */ -static struct snd_soc_dai_link kabylake_rt5660_dais[] = { - /* Front End DAI links */ - [KBL_DPCM_AUDIO_PB] = { - .name = "Kbl Audio Port", - .stream_name = "Audio", - .dynamic = 1, - .nonatomic = 1, - .trigger = { - SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .dpcm_playback = 1, - .ops = &kabylake_rt5660_fe_ops, - SND_SOC_DAILINK_REG(system, dummy, platform), - }, - [KBL_DPCM_AUDIO_CP] = { - .name = "Kbl Audio Capture Port", - .stream_name = "Audio Record", - .dynamic = 1, - .nonatomic = 1, - .trigger = { - SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .dpcm_capture = 1, - .ops = &kabylake_rt5660_fe_ops, - SND_SOC_DAILINK_REG(system, dummy, platform), - }, - [KBL_DPCM_AUDIO_HDMI1_PB] = { - .name = "Kbl HDMI Port1", - .stream_name = "Hdmi1", - .dpcm_playback = 1, - .init = NULL, - .trigger = { - SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .nonatomic = 1, - .dynamic = 1, - SND_SOC_DAILINK_REG(hdmi1, dummy, platform), - }, - [KBL_DPCM_AUDIO_HDMI2_PB] = { - .name = "Kbl HDMI Port2", - .stream_name = "Hdmi2", - .dpcm_playback = 1, - .init = NULL, - .trigger = { - SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .nonatomic = 1, - .dynamic = 1, - SND_SOC_DAILINK_REG(hdmi2, dummy, platform), - }, - [KBL_DPCM_AUDIO_HDMI3_PB] = { - .name = "Kbl HDMI Port3", - .stream_name = "Hdmi3", - .trigger = { - SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .dpcm_playback = 1, - .init = NULL, - .nonatomic = 1, - .dynamic = 1, - SND_SOC_DAILINK_REG(hdmi3, dummy, platform), - }, - - /* Back End DAI links */ - { - /* SSP0 - Codec */ - .name = "SSP0-Codec", - .id = 0, - .no_pcm = 1, - .init = kabylake_rt5660_codec_init, - .exit = kabylake_rt5660_codec_exit, - .dai_fmt = SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBC_CFC, - .ignore_pmdown_time = 1, - .be_hw_params_fixup = kabylake_ssp0_fixup, - .ops = &kabylake_rt5660_ops, - .dpcm_playback = 1, - .dpcm_capture = 1, - SND_SOC_DAILINK_REG(ssp0_pin, ssp0_codec, platform), - }, - { - .name = "iDisp1", - .id = 1, - .dpcm_playback = 1, - .init = kabylake_hdmi1_init, - .no_pcm = 1, - SND_SOC_DAILINK_REG(idisp1_pin, idisp1_codec, platform), - }, - { - .name = "iDisp2", - .id = 2, - .init = kabylake_hdmi2_init, - .dpcm_playback = 1, - .no_pcm = 1, - SND_SOC_DAILINK_REG(idisp2_pin, idisp2_codec, platform), - }, - { - .name = "iDisp3", - .id = 3, - .init = kabylake_hdmi3_init, - .dpcm_playback = 1, - .no_pcm = 1, - SND_SOC_DAILINK_REG(idisp3_pin, idisp3_codec, platform), - }, -}; - - -#define NAME_SIZE 32 -static int kabylake_card_late_probe(struct snd_soc_card *card) -{ - struct kbl_codec_private *ctx = snd_soc_card_get_drvdata(card); - struct kbl_hdmi_pcm *pcm; - struct snd_soc_component *component = NULL; - int err, i = 0; - char jack_name[NAME_SIZE]; - - list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) { - component = pcm->codec_dai->component; - snprintf(jack_name, sizeof(jack_name), - "HDMI/DP, pcm=%d Jack", pcm->device); - err = snd_soc_card_jack_new(card, jack_name, - SND_JACK_AVOUT, &skylake_hdmi[i]); - - if (err) - return err; - - err = hdac_hdmi_jack_init(pcm->codec_dai, pcm->device, - &skylake_hdmi[i]); - if (err < 0) - return err; - - i++; - - } - - if (!component) - return -EINVAL; - - return hdac_hdmi_jack_port_init(component, &card->dapm); -} - -/* kabylake audio machine driver for rt5660 */ -static struct snd_soc_card kabylake_audio_card_rt5660 = { - .name = "kblrt5660", - .owner = THIS_MODULE, - .dai_link = kabylake_rt5660_dais, - .num_links = ARRAY_SIZE(kabylake_rt5660_dais), - .controls = kabylake_rt5660_controls, - .num_controls = ARRAY_SIZE(kabylake_rt5660_controls), - .dapm_widgets = kabylake_rt5660_widgets, - .num_dapm_widgets = ARRAY_SIZE(kabylake_rt5660_widgets), - .dapm_routes = kabylake_rt5660_map, - .num_dapm_routes = ARRAY_SIZE(kabylake_rt5660_map), - .fully_routed = true, - .disable_route_checks = true, - .late_probe = kabylake_card_late_probe, -}; - -static int kabylake_audio_probe(struct platform_device *pdev) -{ - struct kbl_codec_private *ctx; - - ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); - if (!ctx) - return -ENOMEM; - - INIT_LIST_HEAD(&ctx->hdmi_pcm_list); - - kabylake_audio_card = - (struct snd_soc_card *)pdev->id_entry->driver_data; - - kabylake_audio_card->dev = &pdev->dev; - snd_soc_card_set_drvdata(kabylake_audio_card, ctx); - return devm_snd_soc_register_card(&pdev->dev, kabylake_audio_card); -} - -static const struct platform_device_id kbl_board_ids[] = { - { - .name = "kbl_rt5660", - .driver_data = - (kernel_ulong_t)&kabylake_audio_card_rt5660, - }, - { } -}; -MODULE_DEVICE_TABLE(platform, kbl_board_ids); - -static struct platform_driver kabylake_audio = { - .probe = kabylake_audio_probe, - .driver = { - .name = "kbl_rt5660", - .pm = &snd_soc_pm_ops, - }, - .id_table = kbl_board_ids, -}; - -module_platform_driver(kabylake_audio) - -/* Module information */ -MODULE_DESCRIPTION("Audio Machine driver-RT5660 in I2S mode"); -MODULE_AUTHOR("Hui Wang "); -MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/intel/boards/kbl_rt5663_max98927.c b/sound/soc/intel/boards/kbl_rt5663_max98927.c deleted file mode 100644 index 9da89436a917b0..00000000000000 --- a/sound/soc/intel/boards/kbl_rt5663_max98927.c +++ /dev/null @@ -1,1073 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Intel Kabylake I2S Machine Driver with MAXIM98927 - * and RT5663 Codecs - * - * Copyright (C) 2017, Intel Corporation - * - * Modified from: - * Intel Skylake I2S Machine driver - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "../../codecs/rt5663.h" -#include "../../codecs/hdac_hdmi.h" -#include -#include -#include - -#define KBL_REALTEK_CODEC_DAI "rt5663-aif" -#define KBL_MAXIM_CODEC_DAI "max98927-aif1" -#define DMIC_CH(p) p->list[p->count-1] -#define MAXIM_DEV0_NAME "i2c-MX98927:00" -#define MAXIM_DEV1_NAME "i2c-MX98927:01" - -static struct snd_soc_card *kabylake_audio_card; -static const struct snd_pcm_hw_constraint_list *dmic_constraints; -static struct snd_soc_jack skylake_hdmi[3]; - -struct kbl_hdmi_pcm { - struct list_head head; - struct snd_soc_dai *codec_dai; - int device; -}; - -struct kbl_rt5663_private { - struct snd_soc_jack kabylake_headset; - struct list_head hdmi_pcm_list; - struct clk *mclk; - struct clk *sclk; -}; - -enum { - KBL_DPCM_AUDIO_PB = 0, - KBL_DPCM_AUDIO_CP, - KBL_DPCM_AUDIO_HS_PB, - KBL_DPCM_AUDIO_ECHO_REF_CP, - KBL_DPCM_AUDIO_REF_CP, - KBL_DPCM_AUDIO_DMIC_CP, - KBL_DPCM_AUDIO_HDMI1_PB, - KBL_DPCM_AUDIO_HDMI2_PB, - KBL_DPCM_AUDIO_HDMI3_PB, -}; - -static const struct snd_kcontrol_new kabylake_controls[] = { - SOC_DAPM_PIN_SWITCH("Headphone Jack"), - SOC_DAPM_PIN_SWITCH("Headset Mic"), - SOC_DAPM_PIN_SWITCH("Left Spk"), - SOC_DAPM_PIN_SWITCH("Right Spk"), -}; - -static int platform_clock_control(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *k, int event) -{ - struct snd_soc_dapm_context *dapm = w->dapm; - struct snd_soc_card *card = dapm->card; - struct kbl_rt5663_private *priv = snd_soc_card_get_drvdata(card); - int ret = 0; - - /* - * MCLK/SCLK need to be ON early for a successful synchronization of - * codec internal clock. And the clocks are turned off during - * POST_PMD after the stream is stopped. - */ - switch (event) { - case SND_SOC_DAPM_PRE_PMU: - /* Enable MCLK */ - ret = clk_set_rate(priv->mclk, 24000000); - if (ret < 0) { - dev_err(card->dev, "Can't set rate for mclk, err: %d\n", - ret); - return ret; - } - - ret = clk_prepare_enable(priv->mclk); - if (ret < 0) { - dev_err(card->dev, "Can't enable mclk, err: %d\n", ret); - return ret; - } - - /* Enable SCLK */ - ret = clk_set_rate(priv->sclk, 3072000); - if (ret < 0) { - dev_err(card->dev, "Can't set rate for sclk, err: %d\n", - ret); - clk_disable_unprepare(priv->mclk); - return ret; - } - - ret = clk_prepare_enable(priv->sclk); - if (ret < 0) { - dev_err(card->dev, "Can't enable sclk, err: %d\n", ret); - clk_disable_unprepare(priv->mclk); - } - break; - case SND_SOC_DAPM_POST_PMD: - clk_disable_unprepare(priv->mclk); - clk_disable_unprepare(priv->sclk); - break; - default: - return 0; - } - - return 0; -} - -static const struct snd_soc_dapm_widget kabylake_widgets[] = { - SND_SOC_DAPM_HP("Headphone Jack", NULL), - SND_SOC_DAPM_MIC("Headset Mic", NULL), - SND_SOC_DAPM_SPK("Left Spk", NULL), - SND_SOC_DAPM_SPK("Right Spk", NULL), - SND_SOC_DAPM_MIC("SoC DMIC", NULL), - SND_SOC_DAPM_SPK("HDMI1", NULL), - SND_SOC_DAPM_SPK("HDMI2", NULL), - SND_SOC_DAPM_SPK("HDMI3", NULL), - SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0, - platform_clock_control, SND_SOC_DAPM_PRE_PMU | - SND_SOC_DAPM_POST_PMD), -}; - -static const struct snd_soc_dapm_route kabylake_map[] = { - /* HP jack connectors - unknown if we have jack detection */ - { "Headphone Jack", NULL, "Platform Clock" }, - { "Headphone Jack", NULL, "HPOL" }, - { "Headphone Jack", NULL, "HPOR" }, - - /* speaker */ - { "Left Spk", NULL, "Left BE_OUT" }, - { "Right Spk", NULL, "Right BE_OUT" }, - - /* other jacks */ - { "Headset Mic", NULL, "Platform Clock" }, - { "IN1P", NULL, "Headset Mic" }, - { "IN1N", NULL, "Headset Mic" }, - { "DMic", NULL, "SoC DMIC" }, - - {"HDMI1", NULL, "hif5-0 Output"}, - {"HDMI2", NULL, "hif6-0 Output"}, - {"HDMI3", NULL, "hif7-0 Output"}, - - /* CODEC BE connections */ - { "Left HiFi Playback", NULL, "ssp0 Tx" }, - { "Right HiFi Playback", NULL, "ssp0 Tx" }, - { "ssp0 Tx", NULL, "spk_out" }, - - { "AIF Playback", NULL, "ssp1 Tx" }, - { "ssp1 Tx", NULL, "codec1_out" }, - - { "hs_in", NULL, "ssp1 Rx" }, - { "ssp1 Rx", NULL, "AIF Capture" }, - - /* IV feedback path */ - { "codec0_fb_in", NULL, "ssp0 Rx"}, - { "ssp0 Rx", NULL, "Left HiFi Capture" }, - { "ssp0 Rx", NULL, "Right HiFi Capture" }, - - /* DMIC */ - { "dmic01_hifi", NULL, "DMIC01 Rx" }, - { "DMIC01 Rx", NULL, "DMIC AIF" }, - - { "hifi3", NULL, "iDisp3 Tx"}, - { "iDisp3 Tx", NULL, "iDisp3_out"}, - { "hifi2", NULL, "iDisp2 Tx"}, - { "iDisp2 Tx", NULL, "iDisp2_out"}, - { "hifi1", NULL, "iDisp1 Tx"}, - { "iDisp1 Tx", NULL, "iDisp1_out"}, -}; - -enum { - KBL_DPCM_AUDIO_5663_PB = 0, - KBL_DPCM_AUDIO_5663_CP, - KBL_DPCM_AUDIO_5663_HDMI1_PB, - KBL_DPCM_AUDIO_5663_HDMI2_PB, -}; - -static const struct snd_kcontrol_new kabylake_5663_controls[] = { - SOC_DAPM_PIN_SWITCH("Headphone Jack"), - SOC_DAPM_PIN_SWITCH("Headset Mic"), -}; - -static const struct snd_soc_dapm_widget kabylake_5663_widgets[] = { - SND_SOC_DAPM_HP("Headphone Jack", NULL), - SND_SOC_DAPM_MIC("Headset Mic", NULL), - SND_SOC_DAPM_SPK("HDMI1", NULL), - SND_SOC_DAPM_SPK("HDMI2", NULL), - SND_SOC_DAPM_SPK("HDMI3", NULL), - SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0, - platform_clock_control, SND_SOC_DAPM_PRE_PMU | - SND_SOC_DAPM_POST_PMD), -}; - -static struct snd_soc_jack_pin jack_pins[] = { - { - .pin = "Headphone Jack", - .mask = SND_JACK_HEADPHONE, - }, - { - .pin = "Headset Mic", - .mask = SND_JACK_MICROPHONE, - }, -}; - -static const struct snd_soc_dapm_route kabylake_5663_map[] = { - { "Headphone Jack", NULL, "Platform Clock" }, - { "Headphone Jack", NULL, "HPOL" }, - { "Headphone Jack", NULL, "HPOR" }, - - /* other jacks */ - { "Headset Mic", NULL, "Platform Clock" }, - { "IN1P", NULL, "Headset Mic" }, - { "IN1N", NULL, "Headset Mic" }, - - {"HDMI1", NULL, "hif5-0 Output"}, - {"HDMI2", NULL, "hif6-0 Output"}, - {"HDMI3", NULL, "hif7-0 Output"}, - - /* CODEC BE connections */ - { "AIF Playback", NULL, "ssp1 Tx" }, - { "ssp1 Tx", NULL, "codec1_out" }, - - { "codec0_in", NULL, "ssp1 Rx" }, - { "ssp1 Rx", NULL, "AIF Capture" }, - - { "hifi2", NULL, "iDisp2 Tx"}, - { "iDisp2 Tx", NULL, "iDisp2_out"}, - { "hifi1", NULL, "iDisp1 Tx"}, - { "iDisp1 Tx", NULL, "iDisp1_out"}, -}; - -static struct snd_soc_codec_conf max98927_codec_conf[] = { - { - .dlc = COMP_CODEC_CONF(MAXIM_DEV0_NAME), - .name_prefix = "Right", - }, - { - .dlc = COMP_CODEC_CONF(MAXIM_DEV1_NAME), - .name_prefix = "Left", - }, -}; - -static int kabylake_rt5663_fe_init(struct snd_soc_pcm_runtime *rtd) -{ - int ret; - struct snd_soc_dapm_context *dapm; - struct snd_soc_component *component = snd_soc_rtd_to_cpu(rtd, 0)->component; - - dapm = snd_soc_component_get_dapm(component); - ret = snd_soc_dapm_ignore_suspend(dapm, "Reference Capture"); - if (ret) { - dev_err(rtd->dev, "Ref Cap ignore suspend failed %d\n", ret); - return ret; - } - - return ret; -} - -static int kabylake_rt5663_codec_init(struct snd_soc_pcm_runtime *rtd) -{ - int ret; - struct kbl_rt5663_private *ctx = snd_soc_card_get_drvdata(rtd->card); - struct snd_soc_component *component = snd_soc_rtd_to_codec(rtd, 0)->component; - struct snd_soc_jack *jack; - - /* - * Headset buttons map to the google Reference headset. - * These can be configured by userspace. - */ - ret = snd_soc_card_jack_new_pins(kabylake_audio_card, "Headset Jack", - SND_JACK_HEADSET | SND_JACK_BTN_0 | SND_JACK_BTN_1 | - SND_JACK_BTN_2 | SND_JACK_BTN_3, - &ctx->kabylake_headset, - jack_pins, - ARRAY_SIZE(jack_pins)); - if (ret) { - dev_err(rtd->dev, "Headset Jack creation failed %d\n", ret); - return ret; - } - - jack = &ctx->kabylake_headset; - snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_PLAYPAUSE); - snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOICECOMMAND); - snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP); - snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN); - - snd_soc_component_set_jack(component, &ctx->kabylake_headset, NULL); - - return ret; -} - -static int kabylake_rt5663_max98927_codec_init(struct snd_soc_pcm_runtime *rtd) -{ - int ret; - - ret = kabylake_rt5663_codec_init(rtd); - if (ret) - return ret; - - ret = snd_soc_dapm_ignore_suspend(&rtd->card->dapm, "SoC DMIC"); - if (ret) { - dev_err(rtd->dev, "SoC DMIC ignore suspend failed %d\n", ret); - return ret; - } - - return ret; -} - -static int kabylake_hdmi_init(struct snd_soc_pcm_runtime *rtd, int device) -{ - struct kbl_rt5663_private *ctx = snd_soc_card_get_drvdata(rtd->card); - struct snd_soc_dai *dai = snd_soc_rtd_to_codec(rtd, 0); - struct kbl_hdmi_pcm *pcm; - - pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL); - if (!pcm) - return -ENOMEM; - - pcm->device = device; - pcm->codec_dai = dai; - - list_add_tail(&pcm->head, &ctx->hdmi_pcm_list); - - return 0; -} - -static int kabylake_hdmi1_init(struct snd_soc_pcm_runtime *rtd) -{ - return kabylake_hdmi_init(rtd, KBL_DPCM_AUDIO_HDMI1_PB); -} - -static int kabylake_hdmi2_init(struct snd_soc_pcm_runtime *rtd) -{ - return kabylake_hdmi_init(rtd, KBL_DPCM_AUDIO_HDMI2_PB); -} - -static int kabylake_hdmi3_init(struct snd_soc_pcm_runtime *rtd) -{ - return kabylake_hdmi_init(rtd, KBL_DPCM_AUDIO_HDMI3_PB); -} - -static int kabylake_5663_hdmi1_init(struct snd_soc_pcm_runtime *rtd) -{ - return kabylake_hdmi_init(rtd, KBL_DPCM_AUDIO_5663_HDMI1_PB); -} - -static int kabylake_5663_hdmi2_init(struct snd_soc_pcm_runtime *rtd) -{ - return kabylake_hdmi_init(rtd, KBL_DPCM_AUDIO_5663_HDMI2_PB); -} - -static unsigned int rates[] = { - 48000, -}; - -static const struct snd_pcm_hw_constraint_list constraints_rates = { - .count = ARRAY_SIZE(rates), - .list = rates, - .mask = 0, -}; - -static unsigned int channels[] = { - 2, -}; - -static const struct snd_pcm_hw_constraint_list constraints_channels = { - .count = ARRAY_SIZE(channels), - .list = channels, - .mask = 0, -}; - -static int kbl_fe_startup(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - - /* - * On this platform for PCM device we support, - * 48Khz - * stereo - * 16 bit audio - */ - - runtime->hw.channels_max = 2; - snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, - &constraints_channels); - - runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE; - snd_pcm_hw_constraint_msbits(runtime, 0, 16, 16); - - snd_pcm_hw_constraint_list(runtime, 0, - SNDRV_PCM_HW_PARAM_RATE, &constraints_rates); - - return 0; -} - -static const struct snd_soc_ops kabylake_rt5663_fe_ops = { - .startup = kbl_fe_startup, -}; - -static int kabylake_ssp_fixup(struct snd_soc_pcm_runtime *rtd, - struct snd_pcm_hw_params *params) -{ - struct snd_interval *rate = hw_param_interval(params, - SNDRV_PCM_HW_PARAM_RATE); - struct snd_interval *chan = hw_param_interval(params, - SNDRV_PCM_HW_PARAM_CHANNELS); - struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); - struct snd_soc_dpcm *dpcm, *rtd_dpcm = NULL; - - /* - * The following loop will be called only for playback stream - * In this platform, there is only one playback device on every SSP - */ - for_each_dpcm_fe(rtd, SNDRV_PCM_STREAM_PLAYBACK, dpcm) { - rtd_dpcm = dpcm; - break; - } - - /* - * This following loop will be called only for capture stream - * In this platform, there is only one capture device on every SSP - */ - for_each_dpcm_fe(rtd, SNDRV_PCM_STREAM_CAPTURE, dpcm) { - rtd_dpcm = dpcm; - break; - } - - if (!rtd_dpcm) - return -EINVAL; - - /* - * The above 2 loops are mutually exclusive based on the stream direction, - * thus rtd_dpcm variable will never be overwritten - */ - - /* - * The ADSP will convert the FE rate to 48k, stereo, 24 bit - */ - if (!strcmp(rtd_dpcm->fe->dai_link->name, "Kbl Audio Port") || - !strcmp(rtd_dpcm->fe->dai_link->name, "Kbl Audio Headset Playback") || - !strcmp(rtd_dpcm->fe->dai_link->name, "Kbl Audio Capture Port")) { - rate->min = rate->max = 48000; - chan->min = chan->max = 2; - snd_mask_none(fmt); - snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S24_LE); - } - /* - * The speaker on the SSP0 supports S16_LE and not S24_LE. - * thus changing the mask here - */ - if (!strcmp(rtd_dpcm->be->dai_link->name, "SSP0-Codec")) - snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S16_LE); - - return 0; -} - -static int kabylake_rt5663_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); - struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); - int ret; - - /* use ASRC for internal clocks, as PLL rate isn't multiple of BCLK */ - rt5663_sel_asrc_clk_src(codec_dai->component, - RT5663_DA_STEREO_FILTER | RT5663_AD_STEREO_FILTER, - RT5663_CLK_SEL_I2S1_ASRC); - - ret = snd_soc_dai_set_sysclk(codec_dai, - RT5663_SCLK_S_MCLK, 24576000, SND_SOC_CLOCK_IN); - if (ret < 0) - dev_err(rtd->dev, "snd_soc_dai_set_sysclk err = %d\n", ret); - - return ret; -} - -static const struct snd_soc_ops kabylake_rt5663_ops = { - .hw_params = kabylake_rt5663_hw_params, -}; - -static int kabylake_dmic_fixup(struct snd_soc_pcm_runtime *rtd, - struct snd_pcm_hw_params *params) -{ - struct snd_interval *chan = hw_param_interval(params, - SNDRV_PCM_HW_PARAM_CHANNELS); - - if (params_channels(params) == 2 || DMIC_CH(dmic_constraints) == 2) - chan->min = chan->max = 2; - else - chan->min = chan->max = 4; - - return 0; -} - -static int kabylake_ssp0_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); - struct snd_soc_dai *codec_dai; - int ret = 0, j; - - for_each_rtd_codec_dais(rtd, j, codec_dai) { - if (!strcmp(codec_dai->component->name, MAXIM_DEV0_NAME)) { - /* - * Use channel 4 and 5 for the first amp - */ - ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x30, 3, 8, 16); - if (ret < 0) { - dev_err(rtd->dev, "set TDM slot err:%d\n", ret); - return ret; - } - } - if (!strcmp(codec_dai->component->name, MAXIM_DEV1_NAME)) { - /* - * Use channel 6 and 7 for the second amp - */ - ret = snd_soc_dai_set_tdm_slot(codec_dai, 0xC0, 3, 8, 16); - if (ret < 0) { - dev_err(rtd->dev, "set TDM slot err:%d\n", ret); - return ret; - } - } - } - return ret; -} - -static const struct snd_soc_ops kabylake_ssp0_ops = { - .hw_params = kabylake_ssp0_hw_params, -}; - -static unsigned int channels_dmic[] = { - 2, 4, -}; - -static struct snd_pcm_hw_constraint_list constraints_dmic_channels = { - .count = ARRAY_SIZE(channels_dmic), - .list = channels_dmic, - .mask = 0, -}; - -static const unsigned int dmic_2ch[] = { - 2, -}; - -static const struct snd_pcm_hw_constraint_list constraints_dmic_2ch = { - .count = ARRAY_SIZE(dmic_2ch), - .list = dmic_2ch, - .mask = 0, -}; - -static int kabylake_dmic_startup(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - - runtime->hw.channels_max = DMIC_CH(dmic_constraints); - snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, - dmic_constraints); - - return snd_pcm_hw_constraint_list(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_RATE, &constraints_rates); -} - -static const struct snd_soc_ops kabylake_dmic_ops = { - .startup = kabylake_dmic_startup, -}; - -static unsigned int rates_16000[] = { - 16000, -}; - -static const struct snd_pcm_hw_constraint_list constraints_16000 = { - .count = ARRAY_SIZE(rates_16000), - .list = rates_16000, -}; - -static const unsigned int ch_mono[] = { - 1, -}; - -static const struct snd_pcm_hw_constraint_list constraints_refcap = { - .count = ARRAY_SIZE(ch_mono), - .list = ch_mono, -}; - -static int kabylake_refcap_startup(struct snd_pcm_substream *substream) -{ - substream->runtime->hw.channels_max = 1; - snd_pcm_hw_constraint_list(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_CHANNELS, - &constraints_refcap); - - return snd_pcm_hw_constraint_list(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_RATE, - &constraints_16000); -} - -static const struct snd_soc_ops skylake_refcap_ops = { - .startup = kabylake_refcap_startup, -}; - -SND_SOC_DAILINK_DEF(dummy, - DAILINK_COMP_ARRAY(COMP_DUMMY())); - -SND_SOC_DAILINK_DEF(system, - DAILINK_COMP_ARRAY(COMP_CPU("System Pin"))); - -SND_SOC_DAILINK_DEF(system2, - DAILINK_COMP_ARRAY(COMP_CPU("System Pin2"))); - -SND_SOC_DAILINK_DEF(echoref, - DAILINK_COMP_ARRAY(COMP_CPU("Echoref Pin"))); - -SND_SOC_DAILINK_DEF(reference, - DAILINK_COMP_ARRAY(COMP_CPU("Reference Pin"))); - -SND_SOC_DAILINK_DEF(dmic, - DAILINK_COMP_ARRAY(COMP_CPU("DMIC Pin"))); - -SND_SOC_DAILINK_DEF(hdmi1, - DAILINK_COMP_ARRAY(COMP_CPU("HDMI1 Pin"))); - -SND_SOC_DAILINK_DEF(hdmi2, - DAILINK_COMP_ARRAY(COMP_CPU("HDMI2 Pin"))); - -SND_SOC_DAILINK_DEF(hdmi3, - DAILINK_COMP_ARRAY(COMP_CPU("HDMI3 Pin"))); - -SND_SOC_DAILINK_DEF(ssp0_pin, - DAILINK_COMP_ARRAY(COMP_CPU("SSP0 Pin"))); -SND_SOC_DAILINK_DEF(ssp0_codec, - DAILINK_COMP_ARRAY( - /* Left */ COMP_CODEC(MAXIM_DEV0_NAME, KBL_MAXIM_CODEC_DAI), - /* Right */ COMP_CODEC(MAXIM_DEV1_NAME, KBL_MAXIM_CODEC_DAI))); - -SND_SOC_DAILINK_DEF(ssp1_pin, - DAILINK_COMP_ARRAY(COMP_CPU("SSP1 Pin"))); -SND_SOC_DAILINK_DEF(ssp1_codec, - DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10EC5663:00", - KBL_REALTEK_CODEC_DAI))); - -SND_SOC_DAILINK_DEF(dmic01_pin, - DAILINK_COMP_ARRAY(COMP_CPU("DMIC01 Pin"))); -SND_SOC_DAILINK_DEF(dmic_codec, - DAILINK_COMP_ARRAY(COMP_CODEC("dmic-codec", "dmic-hifi"))); - -SND_SOC_DAILINK_DEF(idisp1_pin, - DAILINK_COMP_ARRAY(COMP_CPU("iDisp1 Pin"))); -SND_SOC_DAILINK_DEF(idisp1_codec, - DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi1"))); - -SND_SOC_DAILINK_DEF(idisp2_pin, - DAILINK_COMP_ARRAY(COMP_CPU("iDisp2 Pin"))); -SND_SOC_DAILINK_DEF(idisp2_codec, - DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi2"))); - -SND_SOC_DAILINK_DEF(idisp3_pin, - DAILINK_COMP_ARRAY(COMP_CPU("iDisp3 Pin"))); -SND_SOC_DAILINK_DEF(idisp3_codec, - DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi3"))); - -SND_SOC_DAILINK_DEF(platform, - DAILINK_COMP_ARRAY(COMP_PLATFORM("0000:00:1f.3"))); - -/* kabylake digital audio interface glue - connects codec <--> CPU */ -static struct snd_soc_dai_link kabylake_dais[] = { - /* Front End DAI links */ - [KBL_DPCM_AUDIO_PB] = { - .name = "Kbl Audio Port", - .stream_name = "Audio", - .dynamic = 1, - .nonatomic = 1, - .init = kabylake_rt5663_fe_init, - .trigger = { - SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .dpcm_playback = 1, - .ops = &kabylake_rt5663_fe_ops, - SND_SOC_DAILINK_REG(system, dummy, platform), - }, - [KBL_DPCM_AUDIO_CP] = { - .name = "Kbl Audio Capture Port", - .stream_name = "Audio Record", - .dynamic = 1, - .nonatomic = 1, - .trigger = { - SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .dpcm_capture = 1, - .ops = &kabylake_rt5663_fe_ops, - SND_SOC_DAILINK_REG(system, dummy, platform), - }, - [KBL_DPCM_AUDIO_HS_PB] = { - .name = "Kbl Audio Headset Playback", - .stream_name = "Headset Audio", - .dpcm_playback = 1, - .nonatomic = 1, - .dynamic = 1, - SND_SOC_DAILINK_REG(system2, dummy, platform), - }, - [KBL_DPCM_AUDIO_ECHO_REF_CP] = { - .name = "Kbl Audio Echo Reference cap", - .stream_name = "Echoreference Capture", - .init = NULL, - .dpcm_capture = 1, - .nonatomic = 1, - SND_SOC_DAILINK_REG(echoref, dummy, platform), - }, - [KBL_DPCM_AUDIO_REF_CP] = { - .name = "Kbl Audio Reference cap", - .stream_name = "Wake on Voice", - .init = NULL, - .dpcm_capture = 1, - .nonatomic = 1, - .dynamic = 1, - .ops = &skylake_refcap_ops, - SND_SOC_DAILINK_REG(reference, dummy, platform), - }, - [KBL_DPCM_AUDIO_DMIC_CP] = { - .name = "Kbl Audio DMIC cap", - .stream_name = "dmiccap", - .init = NULL, - .dpcm_capture = 1, - .nonatomic = 1, - .dynamic = 1, - .ops = &kabylake_dmic_ops, - SND_SOC_DAILINK_REG(dmic, dummy, platform), - }, - [KBL_DPCM_AUDIO_HDMI1_PB] = { - .name = "Kbl HDMI Port1", - .stream_name = "Hdmi1", - .dpcm_playback = 1, - .init = NULL, - .trigger = { - SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .nonatomic = 1, - .dynamic = 1, - SND_SOC_DAILINK_REG(hdmi1, dummy, platform), - }, - [KBL_DPCM_AUDIO_HDMI2_PB] = { - .name = "Kbl HDMI Port2", - .stream_name = "Hdmi2", - .dpcm_playback = 1, - .init = NULL, - .trigger = { - SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .nonatomic = 1, - .dynamic = 1, - SND_SOC_DAILINK_REG(hdmi2, dummy, platform), - }, - [KBL_DPCM_AUDIO_HDMI3_PB] = { - .name = "Kbl HDMI Port3", - .stream_name = "Hdmi3", - .trigger = { - SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .dpcm_playback = 1, - .init = NULL, - .nonatomic = 1, - .dynamic = 1, - SND_SOC_DAILINK_REG(hdmi3, dummy, platform), - }, - - /* Back End DAI links */ - { - /* SSP0 - Codec */ - .name = "SSP0-Codec", - .id = 0, - .no_pcm = 1, - .dai_fmt = SND_SOC_DAIFMT_DSP_B | - SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBC_CFC, - .ignore_pmdown_time = 1, - .be_hw_params_fixup = kabylake_ssp_fixup, - .dpcm_playback = 1, - .ops = &kabylake_ssp0_ops, - SND_SOC_DAILINK_REG(ssp0_pin, ssp0_codec, platform), - }, - { - /* SSP1 - Codec */ - .name = "SSP1-Codec", - .id = 1, - .no_pcm = 1, - .init = kabylake_rt5663_max98927_codec_init, - .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBC_CFC, - .ignore_pmdown_time = 1, - .be_hw_params_fixup = kabylake_ssp_fixup, - .ops = &kabylake_rt5663_ops, - .dpcm_playback = 1, - .dpcm_capture = 1, - SND_SOC_DAILINK_REG(ssp1_pin, ssp1_codec, platform), - }, - { - .name = "dmic01", - .id = 2, - .be_hw_params_fixup = kabylake_dmic_fixup, - .ignore_suspend = 1, - .dpcm_capture = 1, - .no_pcm = 1, - SND_SOC_DAILINK_REG(dmic01_pin, dmic_codec, platform), - }, - { - .name = "iDisp1", - .id = 3, - .dpcm_playback = 1, - .init = kabylake_hdmi1_init, - .no_pcm = 1, - SND_SOC_DAILINK_REG(idisp1_pin, idisp1_codec, platform), - }, - { - .name = "iDisp2", - .id = 4, - .init = kabylake_hdmi2_init, - .dpcm_playback = 1, - .no_pcm = 1, - SND_SOC_DAILINK_REG(idisp2_pin, idisp2_codec, platform), - }, - { - .name = "iDisp3", - .id = 5, - .init = kabylake_hdmi3_init, - .dpcm_playback = 1, - .no_pcm = 1, - SND_SOC_DAILINK_REG(idisp3_pin, idisp3_codec, platform), - }, -}; - -static struct snd_soc_dai_link kabylake_5663_dais[] = { - /* Front End DAI links */ - [KBL_DPCM_AUDIO_5663_PB] = { - .name = "Kbl Audio Port", - .stream_name = "Audio", - .dynamic = 1, - .nonatomic = 1, - .trigger = { - SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .dpcm_playback = 1, - .ops = &kabylake_rt5663_fe_ops, - SND_SOC_DAILINK_REG(system, dummy, platform), - }, - [KBL_DPCM_AUDIO_5663_CP] = { - .name = "Kbl Audio Capture Port", - .stream_name = "Audio Record", - .dynamic = 1, - .nonatomic = 1, - .trigger = { - SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .dpcm_capture = 1, - .ops = &kabylake_rt5663_fe_ops, - SND_SOC_DAILINK_REG(system, dummy, platform), - }, - [KBL_DPCM_AUDIO_5663_HDMI1_PB] = { - .name = "Kbl HDMI Port1", - .stream_name = "Hdmi1", - .dpcm_playback = 1, - .init = NULL, - .trigger = { - SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .nonatomic = 1, - .dynamic = 1, - SND_SOC_DAILINK_REG(hdmi1, dummy, platform), - }, - [KBL_DPCM_AUDIO_5663_HDMI2_PB] = { - .name = "Kbl HDMI Port2", - .stream_name = "Hdmi2", - .dpcm_playback = 1, - .init = NULL, - .trigger = { - SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .nonatomic = 1, - .dynamic = 1, - SND_SOC_DAILINK_REG(hdmi2, dummy, platform), - }, - - /* Back End DAI links */ - { - /* SSP1 - Codec */ - .name = "SSP1-Codec", - .id = 0, - .no_pcm = 1, - .init = kabylake_rt5663_codec_init, - .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBC_CFC, - .ignore_pmdown_time = 1, - .be_hw_params_fixup = kabylake_ssp_fixup, - .ops = &kabylake_rt5663_ops, - .dpcm_playback = 1, - .dpcm_capture = 1, - SND_SOC_DAILINK_REG(ssp1_pin, ssp1_codec, platform), - }, - { - .name = "iDisp1", - .id = 1, - .dpcm_playback = 1, - .init = kabylake_5663_hdmi1_init, - .no_pcm = 1, - SND_SOC_DAILINK_REG(idisp1_pin, idisp1_codec, platform), - }, - { - .name = "iDisp2", - .id = 2, - .init = kabylake_5663_hdmi2_init, - .dpcm_playback = 1, - .no_pcm = 1, - SND_SOC_DAILINK_REG(idisp2_pin, idisp2_codec, platform), - }, -}; - -#define NAME_SIZE 32 -static int kabylake_card_late_probe(struct snd_soc_card *card) -{ - struct kbl_rt5663_private *ctx = snd_soc_card_get_drvdata(card); - struct kbl_hdmi_pcm *pcm; - struct snd_soc_component *component = NULL; - int err, i = 0; - char jack_name[NAME_SIZE]; - - list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) { - component = pcm->codec_dai->component; - snprintf(jack_name, sizeof(jack_name), - "HDMI/DP, pcm=%d Jack", pcm->device); - err = snd_soc_card_jack_new(card, jack_name, - SND_JACK_AVOUT, &skylake_hdmi[i]); - - if (err) - return err; - - err = hdac_hdmi_jack_init(pcm->codec_dai, pcm->device, - &skylake_hdmi[i]); - if (err < 0) - return err; - - i++; - } - - if (!component) - return -EINVAL; - - return hdac_hdmi_jack_port_init(component, &card->dapm); -} - -/* kabylake audio machine driver for SPT + RT5663 */ -static struct snd_soc_card kabylake_audio_card_rt5663_m98927 = { - .name = "kblrt5663max", - .owner = THIS_MODULE, - .dai_link = kabylake_dais, - .num_links = ARRAY_SIZE(kabylake_dais), - .controls = kabylake_controls, - .num_controls = ARRAY_SIZE(kabylake_controls), - .dapm_widgets = kabylake_widgets, - .num_dapm_widgets = ARRAY_SIZE(kabylake_widgets), - .dapm_routes = kabylake_map, - .num_dapm_routes = ARRAY_SIZE(kabylake_map), - .codec_conf = max98927_codec_conf, - .num_configs = ARRAY_SIZE(max98927_codec_conf), - .fully_routed = true, - .disable_route_checks = true, - .late_probe = kabylake_card_late_probe, -}; - -/* kabylake audio machine driver for RT5663 */ -static struct snd_soc_card kabylake_audio_card_rt5663 = { - .name = "kblrt5663", - .owner = THIS_MODULE, - .dai_link = kabylake_5663_dais, - .num_links = ARRAY_SIZE(kabylake_5663_dais), - .controls = kabylake_5663_controls, - .num_controls = ARRAY_SIZE(kabylake_5663_controls), - .dapm_widgets = kabylake_5663_widgets, - .num_dapm_widgets = ARRAY_SIZE(kabylake_5663_widgets), - .dapm_routes = kabylake_5663_map, - .num_dapm_routes = ARRAY_SIZE(kabylake_5663_map), - .fully_routed = true, - .disable_route_checks = true, - .late_probe = kabylake_card_late_probe, -}; - -static int kabylake_audio_probe(struct platform_device *pdev) -{ - struct kbl_rt5663_private *ctx; - struct snd_soc_acpi_mach *mach; - int ret; - - ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); - if (!ctx) - return -ENOMEM; - - INIT_LIST_HEAD(&ctx->hdmi_pcm_list); - - kabylake_audio_card = - (struct snd_soc_card *)pdev->id_entry->driver_data; - - kabylake_audio_card->dev = &pdev->dev; - snd_soc_card_set_drvdata(kabylake_audio_card, ctx); - - mach = pdev->dev.platform_data; - if (mach) - dmic_constraints = mach->mach_params.dmic_num == 2 ? - &constraints_dmic_2ch : &constraints_dmic_channels; - - ctx->mclk = devm_clk_get(&pdev->dev, "ssp1_mclk"); - if (IS_ERR(ctx->mclk)) { - ret = PTR_ERR(ctx->mclk); - if (ret == -ENOENT) { - dev_info(&pdev->dev, - "Failed to get ssp1_sclk, defer probe\n"); - return -EPROBE_DEFER; - } - - dev_err(&pdev->dev, "Failed to get ssp1_mclk with err:%d\n", - ret); - return ret; - } - - ctx->sclk = devm_clk_get(&pdev->dev, "ssp1_sclk"); - if (IS_ERR(ctx->sclk)) { - ret = PTR_ERR(ctx->sclk); - if (ret == -ENOENT) { - dev_info(&pdev->dev, - "Failed to get ssp1_sclk, defer probe\n"); - return -EPROBE_DEFER; - } - - dev_err(&pdev->dev, "Failed to get ssp1_sclk with err:%d\n", - ret); - return ret; - } - - return devm_snd_soc_register_card(&pdev->dev, kabylake_audio_card); -} - -static const struct platform_device_id kbl_board_ids[] = { - { - .name = "kbl_rt5663", - .driver_data = (kernel_ulong_t)&kabylake_audio_card_rt5663, - }, - { - .name = "kbl_rt5663_m98927", - .driver_data = - (kernel_ulong_t)&kabylake_audio_card_rt5663_m98927, - }, - { } -}; -MODULE_DEVICE_TABLE(platform, kbl_board_ids); - -static struct platform_driver kabylake_audio = { - .probe = kabylake_audio_probe, - .driver = { - .name = "kbl_rt5663_m98927", - .pm = &snd_soc_pm_ops, - }, - .id_table = kbl_board_ids, -}; - -module_platform_driver(kabylake_audio) - -/* Module information */ -MODULE_DESCRIPTION("Audio Machine driver-RT5663 & MAX98927 in I2S mode"); -MODULE_AUTHOR("Naveen M "); -MODULE_AUTHOR("Harsha Priya "); -MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c b/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c deleted file mode 100644 index a32ce8f972f398..00000000000000 --- a/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c +++ /dev/null @@ -1,869 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Intel Kabylake I2S Machine Driver with MAXIM98927 - * RT5514 and RT5663 Codecs - * - * Copyright (C) 2017, Intel Corporation - * - * Modified from: - * Intel Kabylake I2S Machine driver supporting MAXIM98927 and - * RT5663 codecs - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "../../codecs/rt5514.h" -#include "../../codecs/rt5663.h" -#include "../../codecs/hdac_hdmi.h" -#include -#include -#include - -#define KBL_REALTEK_CODEC_DAI "rt5663-aif" -#define KBL_REALTEK_DMIC_CODEC_DAI "rt5514-aif1" -#define KBL_MAXIM_CODEC_DAI "max98927-aif1" -#define MAXIM_DEV0_NAME "i2c-MX98927:00" -#define MAXIM_DEV1_NAME "i2c-MX98927:01" -#define RT5514_DEV_NAME "i2c-10EC5514:00" -#define RT5663_DEV_NAME "i2c-10EC5663:00" -#define RT5514_AIF1_BCLK_FREQ (48000 * 8 * 16) -#define RT5514_AIF1_SYSCLK_FREQ 12288000 -#define NAME_SIZE 32 - -#define DMIC_CH(p) p->list[p->count-1] - - -static struct snd_soc_card kabylake_audio_card; -static const struct snd_pcm_hw_constraint_list *dmic_constraints; - -struct kbl_hdmi_pcm { - struct list_head head; - struct snd_soc_dai *codec_dai; - int device; -}; - -struct kbl_codec_private { - struct snd_soc_jack kabylake_headset; - struct list_head hdmi_pcm_list; - struct snd_soc_jack kabylake_hdmi[2]; - struct clk *mclk; - struct clk *sclk; -}; - -enum { - KBL_DPCM_AUDIO_PB = 0, - KBL_DPCM_AUDIO_CP, - KBL_DPCM_AUDIO_HS_PB, - KBL_DPCM_AUDIO_ECHO_REF_CP, - KBL_DPCM_AUDIO_DMIC_CP, - KBL_DPCM_AUDIO_RT5514_DSP, - KBL_DPCM_AUDIO_HDMI1_PB, - KBL_DPCM_AUDIO_HDMI2_PB, -}; - -static const struct snd_kcontrol_new kabylake_controls[] = { - SOC_DAPM_PIN_SWITCH("Headphone Jack"), - SOC_DAPM_PIN_SWITCH("Headset Mic"), - SOC_DAPM_PIN_SWITCH("Left Spk"), - SOC_DAPM_PIN_SWITCH("Right Spk"), - SOC_DAPM_PIN_SWITCH("DMIC"), -}; - -static int platform_clock_control(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *k, int event) -{ - struct snd_soc_dapm_context *dapm = w->dapm; - struct snd_soc_card *card = dapm->card; - struct kbl_codec_private *priv = snd_soc_card_get_drvdata(card); - int ret = 0; - - /* - * MCLK/SCLK need to be ON early for a successful synchronization of - * codec internal clock. And the clocks are turned off during - * POST_PMD after the stream is stopped. - */ - switch (event) { - case SND_SOC_DAPM_PRE_PMU: - /* Enable MCLK */ - ret = clk_set_rate(priv->mclk, 24000000); - if (ret < 0) { - dev_err(card->dev, "Can't set rate for mclk, err: %d\n", - ret); - return ret; - } - - ret = clk_prepare_enable(priv->mclk); - if (ret < 0) { - dev_err(card->dev, "Can't enable mclk, err: %d\n", ret); - return ret; - } - - /* Enable SCLK */ - ret = clk_set_rate(priv->sclk, 3072000); - if (ret < 0) { - dev_err(card->dev, "Can't set rate for sclk, err: %d\n", - ret); - clk_disable_unprepare(priv->mclk); - return ret; - } - - ret = clk_prepare_enable(priv->sclk); - if (ret < 0) { - dev_err(card->dev, "Can't enable sclk, err: %d\n", ret); - clk_disable_unprepare(priv->mclk); - } - break; - case SND_SOC_DAPM_POST_PMD: - clk_disable_unprepare(priv->mclk); - clk_disable_unprepare(priv->sclk); - break; - default: - return 0; - } - - return 0; -} - -static const struct snd_soc_dapm_widget kabylake_widgets[] = { - SND_SOC_DAPM_HP("Headphone Jack", NULL), - SND_SOC_DAPM_MIC("Headset Mic", NULL), - SND_SOC_DAPM_SPK("Left Spk", NULL), - SND_SOC_DAPM_SPK("Right Spk", NULL), - SND_SOC_DAPM_MIC("DMIC", NULL), - SND_SOC_DAPM_SPK("HDMI1", NULL), - SND_SOC_DAPM_SPK("HDMI2", NULL), - SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0, - platform_clock_control, SND_SOC_DAPM_PRE_PMU | - SND_SOC_DAPM_POST_PMD), - -}; - -static struct snd_soc_jack_pin jack_pins[] = { - { - .pin = "Headphone Jack", - .mask = SND_JACK_HEADPHONE, - }, - { - .pin = "Headset Mic", - .mask = SND_JACK_MICROPHONE, - }, -}; - -static const struct snd_soc_dapm_route kabylake_map[] = { - /* Headphones */ - { "Headphone Jack", NULL, "Platform Clock" }, - { "Headphone Jack", NULL, "HPOL" }, - { "Headphone Jack", NULL, "HPOR" }, - - /* speaker */ - { "Left Spk", NULL, "Left BE_OUT" }, - { "Right Spk", NULL, "Right BE_OUT" }, - - /* other jacks */ - { "Headset Mic", NULL, "Platform Clock" }, - { "IN1P", NULL, "Headset Mic" }, - { "IN1N", NULL, "Headset Mic" }, - - /* CODEC BE connections */ - { "Left HiFi Playback", NULL, "ssp0 Tx" }, - { "Right HiFi Playback", NULL, "ssp0 Tx" }, - { "ssp0 Tx", NULL, "spk_out" }, - - { "AIF Playback", NULL, "ssp1 Tx" }, - { "ssp1 Tx", NULL, "codec1_out" }, - - { "hs_in", NULL, "ssp1 Rx" }, - { "ssp1 Rx", NULL, "AIF Capture" }, - - { "codec1_in", NULL, "ssp0 Rx" }, - { "ssp0 Rx", NULL, "AIF1 Capture" }, - - /* IV feedback path */ - { "codec0_fb_in", NULL, "ssp0 Rx"}, - { "ssp0 Rx", NULL, "Left HiFi Capture" }, - { "ssp0 Rx", NULL, "Right HiFi Capture" }, - - /* DMIC */ - { "DMIC1L", NULL, "DMIC" }, - { "DMIC1R", NULL, "DMIC" }, - { "DMIC2L", NULL, "DMIC" }, - { "DMIC2R", NULL, "DMIC" }, - - { "hifi2", NULL, "iDisp2 Tx" }, - { "iDisp2 Tx", NULL, "iDisp2_out" }, - { "hifi1", NULL, "iDisp1 Tx" }, - { "iDisp1 Tx", NULL, "iDisp1_out" }, -}; - -static struct snd_soc_codec_conf max98927_codec_conf[] = { - { - .dlc = COMP_CODEC_CONF(MAXIM_DEV0_NAME), - .name_prefix = "Right", - }, - { - .dlc = COMP_CODEC_CONF(MAXIM_DEV1_NAME), - .name_prefix = "Left", - }, -}; - - -static int kabylake_rt5663_fe_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_dapm_context *dapm; - struct snd_soc_component *component = snd_soc_rtd_to_cpu(rtd, 0)->component; - int ret; - - dapm = snd_soc_component_get_dapm(component); - ret = snd_soc_dapm_ignore_suspend(dapm, "Reference Capture"); - if (ret) - dev_err(rtd->dev, "Ref Cap -Ignore suspend failed = %d\n", ret); - - return ret; -} - -static int kabylake_rt5663_codec_init(struct snd_soc_pcm_runtime *rtd) -{ - int ret; - struct kbl_codec_private *ctx = snd_soc_card_get_drvdata(rtd->card); - struct snd_soc_component *component = snd_soc_rtd_to_codec(rtd, 0)->component; - struct snd_soc_jack *jack; - - /* - * Headset buttons map to the google Reference headset. - * These can be configured by userspace. - */ - ret = snd_soc_card_jack_new_pins(&kabylake_audio_card, "Headset Jack", - SND_JACK_HEADSET | SND_JACK_BTN_0 | SND_JACK_BTN_1 | - SND_JACK_BTN_2 | SND_JACK_BTN_3, - &ctx->kabylake_headset, - jack_pins, - ARRAY_SIZE(jack_pins)); - if (ret) { - dev_err(rtd->dev, "Headset Jack creation failed %d\n", ret); - return ret; - } - - jack = &ctx->kabylake_headset; - snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_PLAYPAUSE); - snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOICECOMMAND); - snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP); - snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN); - - snd_soc_component_set_jack(component, &ctx->kabylake_headset, NULL); - - ret = snd_soc_dapm_ignore_suspend(&rtd->card->dapm, "DMIC"); - if (ret) - dev_err(rtd->dev, "DMIC - Ignore suspend failed = %d\n", ret); - - return ret; -} - -static int kabylake_hdmi_init(struct snd_soc_pcm_runtime *rtd, int device) -{ - struct kbl_codec_private *ctx = snd_soc_card_get_drvdata(rtd->card); - struct snd_soc_dai *dai = snd_soc_rtd_to_codec(rtd, 0); - struct kbl_hdmi_pcm *pcm; - - pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL); - if (!pcm) - return -ENOMEM; - - pcm->device = device; - pcm->codec_dai = dai; - - list_add_tail(&pcm->head, &ctx->hdmi_pcm_list); - - return 0; -} - -static int kabylake_hdmi1_init(struct snd_soc_pcm_runtime *rtd) -{ - return kabylake_hdmi_init(rtd, KBL_DPCM_AUDIO_HDMI1_PB); -} - -static int kabylake_hdmi2_init(struct snd_soc_pcm_runtime *rtd) -{ - return kabylake_hdmi_init(rtd, KBL_DPCM_AUDIO_HDMI2_PB); -} - -static const unsigned int rates[] = { - 48000, -}; - -static const struct snd_pcm_hw_constraint_list constraints_rates = { - .count = ARRAY_SIZE(rates), - .list = rates, - .mask = 0, -}; - -static const unsigned int channels[] = { - 2, -}; - -static const struct snd_pcm_hw_constraint_list constraints_channels = { - .count = ARRAY_SIZE(channels), - .list = channels, - .mask = 0, -}; - -static int kbl_fe_startup(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - - /* - * On this platform for PCM device we support, - * 48Khz - * stereo - * 16 bit audio - */ - - runtime->hw.channels_max = 2; - snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, - &constraints_channels); - - runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE; - snd_pcm_hw_constraint_msbits(runtime, 0, 16, 16); - - snd_pcm_hw_constraint_list(runtime, 0, - SNDRV_PCM_HW_PARAM_RATE, &constraints_rates); - - return 0; -} - -static const struct snd_soc_ops kabylake_rt5663_fe_ops = { - .startup = kbl_fe_startup, -}; - -static int kabylake_ssp_fixup(struct snd_soc_pcm_runtime *rtd, - struct snd_pcm_hw_params *params) -{ - struct snd_interval *rate = hw_param_interval(params, - SNDRV_PCM_HW_PARAM_RATE); - struct snd_interval *chan = hw_param_interval(params, - SNDRV_PCM_HW_PARAM_CHANNELS); - struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); - struct snd_soc_dpcm *dpcm, *rtd_dpcm = NULL; - - /* - * The following loop will be called only for playback stream - * In this platform, there is only one playback device on every SSP - */ - for_each_dpcm_fe(rtd, SNDRV_PCM_STREAM_PLAYBACK, dpcm) { - rtd_dpcm = dpcm; - break; - } - - /* - * This following loop will be called only for capture stream - * In this platform, there is only one capture device on every SSP - */ - for_each_dpcm_fe(rtd, SNDRV_PCM_STREAM_CAPTURE, dpcm) { - rtd_dpcm = dpcm; - break; - } - - if (!rtd_dpcm) - return -EINVAL; - - /* - * The above 2 loops are mutually exclusive based on the stream direction, - * thus rtd_dpcm variable will never be overwritten - */ - - /* - * The ADSP will convert the FE rate to 48k, stereo, 24 bit - */ - if (!strcmp(rtd_dpcm->fe->dai_link->name, "Kbl Audio Port") || - !strcmp(rtd_dpcm->fe->dai_link->name, "Kbl Audio Headset Playback") || - !strcmp(rtd_dpcm->fe->dai_link->name, "Kbl Audio Capture Port")) { - rate->min = rate->max = 48000; - chan->min = chan->max = 2; - snd_mask_none(fmt); - snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S24_LE); - } else if (!strcmp(rtd_dpcm->fe->dai_link->name, "Kbl Audio DMIC cap")) { - if (params_channels(params) == 2 || - DMIC_CH(dmic_constraints) == 2) - chan->min = chan->max = 2; - else - chan->min = chan->max = 4; - } - /* - * The speaker on the SSP0 supports S16_LE and not S24_LE. - * thus changing the mask here - */ - if (!strcmp(rtd_dpcm->be->dai_link->name, "SSP0-Codec")) - snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S16_LE); - - return 0; -} - -static int kabylake_rt5663_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); - struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); - int ret; - - /* use ASRC for internal clocks, as PLL rate isn't multiple of BCLK */ - rt5663_sel_asrc_clk_src(codec_dai->component, - RT5663_DA_STEREO_FILTER | RT5663_AD_STEREO_FILTER, - RT5663_CLK_SEL_I2S1_ASRC); - - ret = snd_soc_dai_set_sysclk(codec_dai, - RT5663_SCLK_S_MCLK, 24576000, SND_SOC_CLOCK_IN); - if (ret < 0) - dev_err(rtd->dev, "snd_soc_dai_set_sysclk err = %d\n", ret); - - return ret; -} - -static const struct snd_soc_ops kabylake_rt5663_ops = { - .hw_params = kabylake_rt5663_hw_params, -}; - -static int kabylake_ssp0_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); - struct snd_soc_dai *codec_dai; - int ret = 0, j; - - for_each_rtd_codec_dais(rtd, j, codec_dai) { - if (!strcmp(codec_dai->component->name, RT5514_DEV_NAME)) { - ret = snd_soc_dai_set_tdm_slot(codec_dai, 0xF, 0, 8, 16); - if (ret < 0) { - dev_err(rtd->dev, "set TDM slot err:%d\n", ret); - return ret; - } - - ret = snd_soc_dai_set_sysclk(codec_dai, - RT5514_SCLK_S_MCLK, 24576000, SND_SOC_CLOCK_IN); - if (ret < 0) { - dev_err(rtd->dev, "set sysclk err: %d\n", ret); - return ret; - } - } - if (!strcmp(codec_dai->component->name, MAXIM_DEV0_NAME)) { - ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x30, 3, 8, 16); - if (ret < 0) { - dev_err(rtd->dev, "DEV0 TDM slot err:%d\n", ret); - return ret; - } - } - - if (!strcmp(codec_dai->component->name, MAXIM_DEV1_NAME)) { - ret = snd_soc_dai_set_tdm_slot(codec_dai, 0xC0, 3, 8, 16); - if (ret < 0) { - dev_err(rtd->dev, "DEV1 TDM slot err:%d\n", ret); - return ret; - } - } - } - return ret; -} - -static const struct snd_soc_ops kabylake_ssp0_ops = { - .hw_params = kabylake_ssp0_hw_params, -}; - -static const unsigned int channels_dmic[] = { - 4, -}; - -static const struct snd_pcm_hw_constraint_list constraints_dmic_channels = { - .count = ARRAY_SIZE(channels_dmic), - .list = channels_dmic, - .mask = 0, -}; - -static const unsigned int dmic_2ch[] = { - 2, -}; - -static const struct snd_pcm_hw_constraint_list constraints_dmic_2ch = { - .count = ARRAY_SIZE(dmic_2ch), - .list = dmic_2ch, - .mask = 0, -}; - -static int kabylake_dmic_startup(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - - runtime->hw.channels_max = DMIC_CH(dmic_constraints); - snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, - dmic_constraints); - - runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE; - snd_pcm_hw_constraint_msbits(runtime, 0, 16, 16); - - return snd_pcm_hw_constraint_list(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_RATE, &constraints_rates); -} - -static const struct snd_soc_ops kabylake_dmic_ops = { - .startup = kabylake_dmic_startup, -}; - -SND_SOC_DAILINK_DEF(dummy, - DAILINK_COMP_ARRAY(COMP_DUMMY())); - -SND_SOC_DAILINK_DEF(system, - DAILINK_COMP_ARRAY(COMP_CPU("System Pin"))); - -SND_SOC_DAILINK_DEF(system2, - DAILINK_COMP_ARRAY(COMP_CPU("System Pin2"))); - -SND_SOC_DAILINK_DEF(echoref, - DAILINK_COMP_ARRAY(COMP_CPU("Echoref Pin"))); - -SND_SOC_DAILINK_DEF(spi_cpu, - DAILINK_COMP_ARRAY(COMP_CPU("spi-PRP0001:00"))); -SND_SOC_DAILINK_DEF(spi_platform, - DAILINK_COMP_ARRAY(COMP_PLATFORM("spi-PRP0001:00"))); - -SND_SOC_DAILINK_DEF(dmic, - DAILINK_COMP_ARRAY(COMP_CPU("DMIC Pin"))); - -SND_SOC_DAILINK_DEF(hdmi1, - DAILINK_COMP_ARRAY(COMP_CPU("HDMI1 Pin"))); - -SND_SOC_DAILINK_DEF(hdmi2, - DAILINK_COMP_ARRAY(COMP_CPU("HDMI2 Pin"))); - -SND_SOC_DAILINK_DEF(ssp0_pin, - DAILINK_COMP_ARRAY(COMP_CPU("SSP0 Pin"))); -SND_SOC_DAILINK_DEF(ssp0_codec, - DAILINK_COMP_ARRAY( - /* Left */ COMP_CODEC(MAXIM_DEV0_NAME, KBL_MAXIM_CODEC_DAI), - /* Right */COMP_CODEC(MAXIM_DEV1_NAME, KBL_MAXIM_CODEC_DAI), - /* dmic */ COMP_CODEC(RT5514_DEV_NAME, KBL_REALTEK_DMIC_CODEC_DAI))); - -SND_SOC_DAILINK_DEF(ssp1_pin, - DAILINK_COMP_ARRAY(COMP_CPU("SSP1 Pin"))); -SND_SOC_DAILINK_DEF(ssp1_codec, - DAILINK_COMP_ARRAY(COMP_CODEC(RT5663_DEV_NAME, KBL_REALTEK_CODEC_DAI))); - -SND_SOC_DAILINK_DEF(idisp1_pin, - DAILINK_COMP_ARRAY(COMP_CPU("iDisp1 Pin"))); -SND_SOC_DAILINK_DEF(idisp1_codec, - DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi1"))); - -SND_SOC_DAILINK_DEF(idisp2_pin, - DAILINK_COMP_ARRAY(COMP_CPU("iDisp2 Pin"))); -SND_SOC_DAILINK_DEF(idisp2_codec, - DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi2"))); - -SND_SOC_DAILINK_DEF(platform, - DAILINK_COMP_ARRAY(COMP_PLATFORM("0000:00:1f.3"))); - -/* kabylake digital audio interface glue - connects codec <--> CPU */ -static struct snd_soc_dai_link kabylake_dais[] = { - /* Front End DAI links */ - [KBL_DPCM_AUDIO_PB] = { - .name = "Kbl Audio Port", - .stream_name = "Audio", - .dynamic = 1, - .nonatomic = 1, - .init = kabylake_rt5663_fe_init, - .trigger = { - SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .dpcm_playback = 1, - .ops = &kabylake_rt5663_fe_ops, - SND_SOC_DAILINK_REG(system, dummy, platform), - }, - [KBL_DPCM_AUDIO_CP] = { - .name = "Kbl Audio Capture Port", - .stream_name = "Audio Record", - .dynamic = 1, - .nonatomic = 1, - .trigger = { - SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .dpcm_capture = 1, - .ops = &kabylake_rt5663_fe_ops, - SND_SOC_DAILINK_REG(system, dummy, platform), - }, - [KBL_DPCM_AUDIO_HS_PB] = { - .name = "Kbl Audio Headset Playback", - .stream_name = "Headset Audio", - .dpcm_playback = 1, - .nonatomic = 1, - .dynamic = 1, - SND_SOC_DAILINK_REG(system2, dummy, platform), - }, - [KBL_DPCM_AUDIO_ECHO_REF_CP] = { - .name = "Kbl Audio Echo Reference cap", - .stream_name = "Echoreference Capture", - .init = NULL, - .dpcm_capture = 1, - .nonatomic = 1, - SND_SOC_DAILINK_REG(echoref, dummy, platform), - }, - [KBL_DPCM_AUDIO_RT5514_DSP] = { - .name = "rt5514 dsp", - .stream_name = "Wake on Voice", - SND_SOC_DAILINK_REG(spi_cpu, dummy, spi_platform), - }, - [KBL_DPCM_AUDIO_DMIC_CP] = { - .name = "Kbl Audio DMIC cap", - .stream_name = "dmiccap", - .init = NULL, - .dpcm_capture = 1, - .nonatomic = 1, - .dynamic = 1, - .ops = &kabylake_dmic_ops, - SND_SOC_DAILINK_REG(dmic, dummy, platform), - }, - [KBL_DPCM_AUDIO_HDMI1_PB] = { - .name = "Kbl HDMI Port1", - .stream_name = "Hdmi1", - .dpcm_playback = 1, - .init = NULL, - .trigger = { - SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .nonatomic = 1, - .dynamic = 1, - SND_SOC_DAILINK_REG(hdmi1, dummy, platform), - }, - [KBL_DPCM_AUDIO_HDMI2_PB] = { - .name = "Kbl HDMI Port2", - .stream_name = "Hdmi2", - .dpcm_playback = 1, - .init = NULL, - .trigger = { - SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .nonatomic = 1, - .dynamic = 1, - SND_SOC_DAILINK_REG(hdmi2, dummy, platform), - }, - /* Back End DAI links */ - /* single Back end dai for both max speakers and dmic */ - { - /* SSP0 - Codec */ - .name = "SSP0-Codec", - .id = 0, - .no_pcm = 1, - .dai_fmt = SND_SOC_DAIFMT_DSP_B | - SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBC_CFC, - .ignore_pmdown_time = 1, - .be_hw_params_fixup = kabylake_ssp_fixup, - .dpcm_playback = 1, - .dpcm_capture = 1, - .ops = &kabylake_ssp0_ops, - SND_SOC_DAILINK_REG(ssp0_pin, ssp0_codec, platform), - }, - { - .name = "SSP1-Codec", - .id = 1, - .no_pcm = 1, - .init = kabylake_rt5663_codec_init, - .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBC_CFC, - .ignore_pmdown_time = 1, - .be_hw_params_fixup = kabylake_ssp_fixup, - .ops = &kabylake_rt5663_ops, - .dpcm_playback = 1, - .dpcm_capture = 1, - SND_SOC_DAILINK_REG(ssp1_pin, ssp1_codec, platform), - }, - { - .name = "iDisp1", - .id = 3, - .dpcm_playback = 1, - .init = kabylake_hdmi1_init, - .no_pcm = 1, - SND_SOC_DAILINK_REG(idisp1_pin, idisp1_codec, platform), - }, - { - .name = "iDisp2", - .id = 4, - .init = kabylake_hdmi2_init, - .dpcm_playback = 1, - .no_pcm = 1, - SND_SOC_DAILINK_REG(idisp2_pin, idisp2_codec, platform), - }, -}; - -static int kabylake_set_bias_level(struct snd_soc_card *card, - struct snd_soc_dapm_context *dapm, enum snd_soc_bias_level level) -{ - struct snd_soc_component *component = dapm->component; - struct kbl_codec_private *priv = snd_soc_card_get_drvdata(card); - int ret = 0; - - if (!component || strcmp(component->name, RT5514_DEV_NAME)) - return 0; - - if (IS_ERR(priv->mclk)) - return 0; - - /* - * It's required to control mclk directly in the set_bias_level - * function for rt5514 codec or the recording function could - * break. - */ - switch (level) { - case SND_SOC_BIAS_PREPARE: - if (dapm->bias_level == SND_SOC_BIAS_ON) { - if (!__clk_is_enabled(priv->mclk)) - return 0; - dev_dbg(card->dev, "Disable mclk"); - clk_disable_unprepare(priv->mclk); - } else { - dev_dbg(card->dev, "Enable mclk"); - ret = clk_set_rate(priv->mclk, 24000000); - if (ret) { - dev_err(card->dev, "Can't set rate for mclk, err: %d\n", - ret); - return ret; - } - - ret = clk_prepare_enable(priv->mclk); - if (ret) { - dev_err(card->dev, "Can't enable mclk, err: %d\n", - ret); - - /* mclk is already enabled in FW */ - ret = 0; - } - } - break; - default: - break; - } - - return ret; -} - -static int kabylake_card_late_probe(struct snd_soc_card *card) -{ - struct kbl_codec_private *ctx = snd_soc_card_get_drvdata(card); - struct kbl_hdmi_pcm *pcm; - struct snd_soc_component *component = NULL; - int err, i = 0; - char jack_name[NAME_SIZE]; - - list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) { - component = pcm->codec_dai->component; - snprintf(jack_name, sizeof(jack_name), - "HDMI/DP,pcm=%d Jack", pcm->device); - err = snd_soc_card_jack_new(card, jack_name, - SND_JACK_AVOUT, &ctx->kabylake_hdmi[i]); - - if (err) - return err; - err = hdac_hdmi_jack_init(pcm->codec_dai, pcm->device, - &ctx->kabylake_hdmi[i]); - if (err < 0) - return err; - i++; - } - - if (!component) - return -EINVAL; - - return hdac_hdmi_jack_port_init(component, &card->dapm); -} - -/* - * kabylake audio machine driver for MAX98927 + RT5514 + RT5663 - */ -static struct snd_soc_card kabylake_audio_card = { - .name = "kbl-r5514-5663-max", - .owner = THIS_MODULE, - .dai_link = kabylake_dais, - .num_links = ARRAY_SIZE(kabylake_dais), - .set_bias_level = kabylake_set_bias_level, - .controls = kabylake_controls, - .num_controls = ARRAY_SIZE(kabylake_controls), - .dapm_widgets = kabylake_widgets, - .num_dapm_widgets = ARRAY_SIZE(kabylake_widgets), - .dapm_routes = kabylake_map, - .num_dapm_routes = ARRAY_SIZE(kabylake_map), - .codec_conf = max98927_codec_conf, - .num_configs = ARRAY_SIZE(max98927_codec_conf), - .fully_routed = true, - .disable_route_checks = true, - .late_probe = kabylake_card_late_probe, -}; - -static int kabylake_audio_probe(struct platform_device *pdev) -{ - struct kbl_codec_private *ctx; - struct snd_soc_acpi_mach *mach; - int ret; - - ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); - if (!ctx) - return -ENOMEM; - - INIT_LIST_HEAD(&ctx->hdmi_pcm_list); - - kabylake_audio_card.dev = &pdev->dev; - snd_soc_card_set_drvdata(&kabylake_audio_card, ctx); - - mach = pdev->dev.platform_data; - if (mach) - dmic_constraints = mach->mach_params.dmic_num == 2 ? - &constraints_dmic_2ch : &constraints_dmic_channels; - - ctx->mclk = devm_clk_get(&pdev->dev, "ssp1_mclk"); - if (IS_ERR(ctx->mclk)) { - ret = PTR_ERR(ctx->mclk); - if (ret == -ENOENT) { - dev_info(&pdev->dev, - "Failed to get ssp1_mclk, defer probe\n"); - return -EPROBE_DEFER; - } - - dev_err(&pdev->dev, "Failed to get ssp1_mclk with err:%d\n", - ret); - return ret; - } - - ctx->sclk = devm_clk_get(&pdev->dev, "ssp1_sclk"); - if (IS_ERR(ctx->sclk)) { - ret = PTR_ERR(ctx->sclk); - if (ret == -ENOENT) { - dev_info(&pdev->dev, - "Failed to get ssp1_sclk, defer probe\n"); - return -EPROBE_DEFER; - } - - dev_err(&pdev->dev, "Failed to get ssp1_sclk with err:%d\n", - ret); - return ret; - } - - return devm_snd_soc_register_card(&pdev->dev, &kabylake_audio_card); -} - -static const struct platform_device_id kbl_board_ids[] = { - { .name = "kbl_r5514_5663_max" }, - { } -}; -MODULE_DEVICE_TABLE(platform, kbl_board_ids); - -static struct platform_driver kabylake_audio = { - .probe = kabylake_audio_probe, - .driver = { - .name = "kbl_r5514_5663_max", - .pm = &snd_soc_pm_ops, - }, - .id_table = kbl_board_ids, -}; - -module_platform_driver(kabylake_audio) - -/* Module information */ -MODULE_DESCRIPTION("Audio Machine driver-RT5663 RT5514 & MAX98927"); -MODULE_AUTHOR("Harsha Priya "); -MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/intel/boards/skl_nau88l25_max98357a.c b/sound/soc/intel/boards/skl_nau88l25_max98357a.c deleted file mode 100644 index 91fe9834aab42c..00000000000000 --- a/sound/soc/intel/boards/skl_nau88l25_max98357a.c +++ /dev/null @@ -1,704 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Intel Skylake I2S Machine Driver with MAXIM98357A - * and NAU88L25 - * - * Copyright (C) 2015, Intel Corporation - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include "../../codecs/nau8825.h" -#include "../../codecs/hdac_hdmi.h" - -#define SKL_NUVOTON_CODEC_DAI "nau8825-hifi" -#define SKL_MAXIM_CODEC_DAI "HiFi" -#define DMIC_CH(p) p->list[p->count-1] - -static struct snd_soc_jack skylake_headset; -static struct snd_soc_card skylake_audio_card; -static const struct snd_pcm_hw_constraint_list *dmic_constraints; -static struct snd_soc_jack skylake_hdmi[3]; - -struct skl_hdmi_pcm { - struct list_head head; - struct snd_soc_dai *codec_dai; - int device; -}; - -struct skl_nau8825_private { - struct list_head hdmi_pcm_list; -}; - -enum { - SKL_DPCM_AUDIO_PB = 0, - SKL_DPCM_AUDIO_CP, - SKL_DPCM_AUDIO_REF_CP, - SKL_DPCM_AUDIO_DMIC_CP, - SKL_DPCM_AUDIO_HDMI1_PB, - SKL_DPCM_AUDIO_HDMI2_PB, - SKL_DPCM_AUDIO_HDMI3_PB, -}; - -static int platform_clock_control(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *k, int event) -{ - struct snd_soc_dapm_context *dapm = w->dapm; - struct snd_soc_card *card = dapm->card; - struct snd_soc_dai *codec_dai; - int ret; - - codec_dai = snd_soc_card_get_codec_dai(card, SKL_NUVOTON_CODEC_DAI); - if (!codec_dai) { - dev_err(card->dev, "Codec dai not found; Unable to set platform clock\n"); - return -EIO; - } - - if (SND_SOC_DAPM_EVENT_ON(event)) { - ret = snd_soc_dai_set_sysclk(codec_dai, - NAU8825_CLK_MCLK, 24000000, SND_SOC_CLOCK_IN); - if (ret < 0) { - dev_err(card->dev, "set sysclk err = %d\n", ret); - return -EIO; - } - } else { - ret = snd_soc_dai_set_sysclk(codec_dai, - NAU8825_CLK_INTERNAL, 0, SND_SOC_CLOCK_IN); - if (ret < 0) { - dev_err(card->dev, "set sysclk err = %d\n", ret); - return -EIO; - } - } - - return ret; -} - -static const struct snd_kcontrol_new skylake_controls[] = { - SOC_DAPM_PIN_SWITCH("Headphone Jack"), - SOC_DAPM_PIN_SWITCH("Headset Mic"), - SOC_DAPM_PIN_SWITCH("Spk"), -}; - -static const struct snd_soc_dapm_widget skylake_widgets[] = { - SND_SOC_DAPM_HP("Headphone Jack", NULL), - SND_SOC_DAPM_MIC("Headset Mic", NULL), - SND_SOC_DAPM_SPK("Spk", NULL), - SND_SOC_DAPM_MIC("SoC DMIC", NULL), - SND_SOC_DAPM_SPK("DP1", NULL), - SND_SOC_DAPM_SPK("DP2", NULL), - SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0, - platform_clock_control, SND_SOC_DAPM_PRE_PMU | - SND_SOC_DAPM_POST_PMD), -}; - -static struct snd_soc_jack_pin jack_pins[] = { - { - .pin = "Headphone Jack", - .mask = SND_JACK_HEADPHONE, - }, - { - .pin = "Headset Mic", - .mask = SND_JACK_MICROPHONE, - }, -}; - -static const struct snd_soc_dapm_route skylake_map[] = { - /* HP jack connectors - unknown if we have jack detection */ - { "Headphone Jack", NULL, "HPOL" }, - { "Headphone Jack", NULL, "HPOR" }, - - /* speaker */ - { "Spk", NULL, "Speaker" }, - - /* other jacks */ - { "MIC", NULL, "Headset Mic" }, - { "DMic", NULL, "SoC DMIC" }, - - /* CODEC BE connections */ - { "HiFi Playback", NULL, "ssp0 Tx" }, - { "ssp0 Tx", NULL, "codec0_out" }, - - { "Playback", NULL, "ssp1 Tx" }, - { "ssp1 Tx", NULL, "codec1_out" }, - - { "codec0_in", NULL, "ssp1 Rx" }, - { "ssp1 Rx", NULL, "Capture" }, - - /* DMIC */ - { "dmic01_hifi", NULL, "DMIC01 Rx" }, - { "DMIC01 Rx", NULL, "DMIC AIF" }, - - { "hifi3", NULL, "iDisp3 Tx"}, - { "iDisp3 Tx", NULL, "iDisp3_out"}, - { "hifi2", NULL, "iDisp2 Tx"}, - { "iDisp2 Tx", NULL, "iDisp2_out"}, - { "hifi1", NULL, "iDisp1 Tx"}, - { "iDisp1 Tx", NULL, "iDisp1_out"}, - - { "Headphone Jack", NULL, "Platform Clock" }, - { "Headset Mic", NULL, "Platform Clock" }, -}; - -static int skylake_ssp_fixup(struct snd_soc_pcm_runtime *rtd, - struct snd_pcm_hw_params *params) -{ - struct snd_interval *rate = hw_param_interval(params, - SNDRV_PCM_HW_PARAM_RATE); - struct snd_interval *chan = hw_param_interval(params, - SNDRV_PCM_HW_PARAM_CHANNELS); - struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); - - /* The ADSP will convert the FE rate to 48k, stereo */ - rate->min = rate->max = 48000; - chan->min = chan->max = 2; - - /* set SSP0 to 24 bit */ - snd_mask_none(fmt); - snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S24_LE); - - return 0; -} - -static int skylake_nau8825_codec_init(struct snd_soc_pcm_runtime *rtd) -{ - int ret; - struct snd_soc_component *component = snd_soc_rtd_to_codec(rtd, 0)->component; - - /* - * Headset buttons map to the google Reference headset. - * These can be configured by userspace. - */ - ret = snd_soc_card_jack_new_pins(&skylake_audio_card, "Headset Jack", - SND_JACK_HEADSET | SND_JACK_BTN_0 | SND_JACK_BTN_1 | - SND_JACK_BTN_2 | SND_JACK_BTN_3, &skylake_headset, - jack_pins, - ARRAY_SIZE(jack_pins)); - if (ret) { - dev_err(rtd->dev, "Headset Jack creation failed %d\n", ret); - return ret; - } - - nau8825_enable_jack_detect(component, &skylake_headset); - - snd_soc_dapm_ignore_suspend(&rtd->card->dapm, "SoC DMIC"); - - return ret; -} - -static int skylake_hdmi1_init(struct snd_soc_pcm_runtime *rtd) -{ - struct skl_nau8825_private *ctx = snd_soc_card_get_drvdata(rtd->card); - struct snd_soc_dai *dai = snd_soc_rtd_to_codec(rtd, 0); - struct skl_hdmi_pcm *pcm; - - pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL); - if (!pcm) - return -ENOMEM; - - pcm->device = SKL_DPCM_AUDIO_HDMI1_PB; - pcm->codec_dai = dai; - - list_add_tail(&pcm->head, &ctx->hdmi_pcm_list); - - return 0; -} - -static int skylake_hdmi2_init(struct snd_soc_pcm_runtime *rtd) -{ - struct skl_nau8825_private *ctx = snd_soc_card_get_drvdata(rtd->card); - struct snd_soc_dai *dai = snd_soc_rtd_to_codec(rtd, 0); - struct skl_hdmi_pcm *pcm; - - pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL); - if (!pcm) - return -ENOMEM; - - pcm->device = SKL_DPCM_AUDIO_HDMI2_PB; - pcm->codec_dai = dai; - - list_add_tail(&pcm->head, &ctx->hdmi_pcm_list); - - return 0; -} - -static int skylake_hdmi3_init(struct snd_soc_pcm_runtime *rtd) -{ - struct skl_nau8825_private *ctx = snd_soc_card_get_drvdata(rtd->card); - struct snd_soc_dai *dai = snd_soc_rtd_to_codec(rtd, 0); - struct skl_hdmi_pcm *pcm; - - pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL); - if (!pcm) - return -ENOMEM; - - pcm->device = SKL_DPCM_AUDIO_HDMI3_PB; - pcm->codec_dai = dai; - - list_add_tail(&pcm->head, &ctx->hdmi_pcm_list); - - return 0; -} - -static int skylake_nau8825_fe_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_dapm_context *dapm; - struct snd_soc_component *component = snd_soc_rtd_to_cpu(rtd, 0)->component; - - dapm = snd_soc_component_get_dapm(component); - snd_soc_dapm_ignore_suspend(dapm, "Reference Capture"); - - return 0; -} - -static const unsigned int rates[] = { - 48000, -}; - -static const struct snd_pcm_hw_constraint_list constraints_rates = { - .count = ARRAY_SIZE(rates), - .list = rates, - .mask = 0, -}; - -static const unsigned int channels[] = { - 2, -}; - -static const struct snd_pcm_hw_constraint_list constraints_channels = { - .count = ARRAY_SIZE(channels), - .list = channels, - .mask = 0, -}; - -static int skl_fe_startup(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - - /* - * On this platform for PCM device we support, - * 48Khz - * stereo - * 16 bit audio - */ - - runtime->hw.channels_max = 2; - snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, - &constraints_channels); - - runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE; - snd_pcm_hw_constraint_msbits(runtime, 0, 16, 16); - - snd_pcm_hw_constraint_list(runtime, 0, - SNDRV_PCM_HW_PARAM_RATE, &constraints_rates); - - return 0; -} - -static const struct snd_soc_ops skylake_nau8825_fe_ops = { - .startup = skl_fe_startup, -}; - -static int skylake_nau8825_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); - struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); - int ret; - - ret = snd_soc_dai_set_sysclk(codec_dai, - NAU8825_CLK_MCLK, 24000000, SND_SOC_CLOCK_IN); - - if (ret < 0) - dev_err(rtd->dev, "snd_soc_dai_set_sysclk err = %d\n", ret); - - return ret; -} - -static const struct snd_soc_ops skylake_nau8825_ops = { - .hw_params = skylake_nau8825_hw_params, -}; - -static int skylake_dmic_fixup(struct snd_soc_pcm_runtime *rtd, - struct snd_pcm_hw_params *params) -{ - struct snd_interval *chan = hw_param_interval(params, - SNDRV_PCM_HW_PARAM_CHANNELS); - - if (params_channels(params) == 2 || DMIC_CH(dmic_constraints) == 2) - chan->min = chan->max = 2; - else - chan->min = chan->max = 4; - - return 0; -} - -static const unsigned int channels_dmic[] = { - 2, 4, -}; - -static const struct snd_pcm_hw_constraint_list constraints_dmic_channels = { - .count = ARRAY_SIZE(channels_dmic), - .list = channels_dmic, - .mask = 0, -}; - -static const unsigned int dmic_2ch[] = { - 2, -}; - -static const struct snd_pcm_hw_constraint_list constraints_dmic_2ch = { - .count = ARRAY_SIZE(dmic_2ch), - .list = dmic_2ch, - .mask = 0, -}; - -static int skylake_dmic_startup(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - - runtime->hw.channels_max = DMIC_CH(dmic_constraints); - snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, - dmic_constraints); - - return snd_pcm_hw_constraint_list(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_RATE, &constraints_rates); -} - -static const struct snd_soc_ops skylake_dmic_ops = { - .startup = skylake_dmic_startup, -}; - -static const unsigned int rates_16000[] = { - 16000, -}; - -static const struct snd_pcm_hw_constraint_list constraints_16000 = { - .count = ARRAY_SIZE(rates_16000), - .list = rates_16000, -}; - -static const unsigned int ch_mono[] = { - 1, -}; - -static const struct snd_pcm_hw_constraint_list constraints_refcap = { - .count = ARRAY_SIZE(ch_mono), - .list = ch_mono, -}; - -static int skylake_refcap_startup(struct snd_pcm_substream *substream) -{ - substream->runtime->hw.channels_max = 1; - snd_pcm_hw_constraint_list(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_CHANNELS, - &constraints_refcap); - - return snd_pcm_hw_constraint_list(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_RATE, - &constraints_16000); -} - -static const struct snd_soc_ops skylake_refcap_ops = { - .startup = skylake_refcap_startup, -}; - -SND_SOC_DAILINK_DEF(dummy, - DAILINK_COMP_ARRAY(COMP_DUMMY())); - -SND_SOC_DAILINK_DEF(system, - DAILINK_COMP_ARRAY(COMP_CPU("System Pin"))); - -SND_SOC_DAILINK_DEF(reference, - DAILINK_COMP_ARRAY(COMP_CPU("Reference Pin"))); - -SND_SOC_DAILINK_DEF(dmic, - DAILINK_COMP_ARRAY(COMP_CPU("DMIC Pin"))); - -SND_SOC_DAILINK_DEF(hdmi1, - DAILINK_COMP_ARRAY(COMP_CPU("HDMI1 Pin"))); - -SND_SOC_DAILINK_DEF(hdmi2, - DAILINK_COMP_ARRAY(COMP_CPU("HDMI2 Pin"))); - -SND_SOC_DAILINK_DEF(hdmi3, - DAILINK_COMP_ARRAY(COMP_CPU("HDMI3 Pin"))); - -SND_SOC_DAILINK_DEF(ssp0_pin, - DAILINK_COMP_ARRAY(COMP_CPU("SSP0 Pin"))); -SND_SOC_DAILINK_DEF(ssp0_codec, - DAILINK_COMP_ARRAY(COMP_CODEC("MX98357A:00", SKL_MAXIM_CODEC_DAI))); - -SND_SOC_DAILINK_DEF(ssp1_pin, - DAILINK_COMP_ARRAY(COMP_CPU("SSP1 Pin"))); -SND_SOC_DAILINK_DEF(ssp1_codec, - DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10508825:00", - SKL_NUVOTON_CODEC_DAI))); - -SND_SOC_DAILINK_DEF(dmic_pin, - DAILINK_COMP_ARRAY(COMP_CPU("DMIC01 Pin"))); -SND_SOC_DAILINK_DEF(dmic_codec, - DAILINK_COMP_ARRAY(COMP_CODEC("dmic-codec", "dmic-hifi"))); - -SND_SOC_DAILINK_DEF(idisp1_pin, - DAILINK_COMP_ARRAY(COMP_CPU("iDisp1 Pin"))); -SND_SOC_DAILINK_DEF(idisp1_codec, - DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi1"))); - -SND_SOC_DAILINK_DEF(idisp2_pin, - DAILINK_COMP_ARRAY(COMP_CPU("iDisp2 Pin"))); -SND_SOC_DAILINK_DEF(idisp2_codec, - DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi2"))); - -SND_SOC_DAILINK_DEF(idisp3_pin, - DAILINK_COMP_ARRAY(COMP_CPU("iDisp3 Pin"))); -SND_SOC_DAILINK_DEF(idisp3_codec, - DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi3"))); - -SND_SOC_DAILINK_DEF(platform, - DAILINK_COMP_ARRAY(COMP_PLATFORM("0000:00:1f.3"))); - -/* skylake digital audio interface glue - connects codec <--> CPU */ -static struct snd_soc_dai_link skylake_dais[] = { - /* Front End DAI links */ - [SKL_DPCM_AUDIO_PB] = { - .name = "Skl Audio Port", - .stream_name = "Audio", - .dynamic = 1, - .nonatomic = 1, - .init = skylake_nau8825_fe_init, - .trigger = { - SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .dpcm_playback = 1, - .ops = &skylake_nau8825_fe_ops, - SND_SOC_DAILINK_REG(system, dummy, platform), - }, - [SKL_DPCM_AUDIO_CP] = { - .name = "Skl Audio Capture Port", - .stream_name = "Audio Record", - .dynamic = 1, - .nonatomic = 1, - .trigger = { - SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .dpcm_capture = 1, - .ops = &skylake_nau8825_fe_ops, - SND_SOC_DAILINK_REG(system, dummy, platform), - }, - [SKL_DPCM_AUDIO_REF_CP] = { - .name = "Skl Audio Reference cap", - .stream_name = "Wake on Voice", - .init = NULL, - .dpcm_capture = 1, - .nonatomic = 1, - .dynamic = 1, - .ops = &skylake_refcap_ops, - SND_SOC_DAILINK_REG(reference, dummy, platform), - }, - [SKL_DPCM_AUDIO_DMIC_CP] = { - .name = "Skl Audio DMIC cap", - .stream_name = "dmiccap", - .init = NULL, - .dpcm_capture = 1, - .nonatomic = 1, - .dynamic = 1, - .ops = &skylake_dmic_ops, - SND_SOC_DAILINK_REG(dmic, dummy, platform), - }, - [SKL_DPCM_AUDIO_HDMI1_PB] = { - .name = "Skl HDMI Port1", - .stream_name = "Hdmi1", - .dpcm_playback = 1, - .init = NULL, - .trigger = { - SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .nonatomic = 1, - .dynamic = 1, - SND_SOC_DAILINK_REG(hdmi1, dummy, platform), - }, - [SKL_DPCM_AUDIO_HDMI2_PB] = { - .name = "Skl HDMI Port2", - .stream_name = "Hdmi2", - .dpcm_playback = 1, - .init = NULL, - .trigger = { - SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .nonatomic = 1, - .dynamic = 1, - SND_SOC_DAILINK_REG(hdmi2, dummy, platform), - }, - [SKL_DPCM_AUDIO_HDMI3_PB] = { - .name = "Skl HDMI Port3", - .stream_name = "Hdmi3", - .trigger = { - SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .dpcm_playback = 1, - .init = NULL, - .nonatomic = 1, - .dynamic = 1, - SND_SOC_DAILINK_REG(hdmi3, dummy, platform), - }, - - /* Back End DAI links */ - { - /* SSP0 - Codec */ - .name = "SSP0-Codec", - .id = 0, - .no_pcm = 1, - .dai_fmt = SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBC_CFC, - .ignore_pmdown_time = 1, - .be_hw_params_fixup = skylake_ssp_fixup, - .dpcm_playback = 1, - SND_SOC_DAILINK_REG(ssp0_pin, ssp0_codec, platform), - }, - { - /* SSP1 - Codec */ - .name = "SSP1-Codec", - .id = 1, - .no_pcm = 1, - .init = skylake_nau8825_codec_init, - .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBC_CFC, - .ignore_pmdown_time = 1, - .be_hw_params_fixup = skylake_ssp_fixup, - .ops = &skylake_nau8825_ops, - .dpcm_playback = 1, - .dpcm_capture = 1, - SND_SOC_DAILINK_REG(ssp1_pin, ssp1_codec, platform), - }, - { - .name = "dmic01", - .id = 2, - .be_hw_params_fixup = skylake_dmic_fixup, - .ignore_suspend = 1, - .dpcm_capture = 1, - .no_pcm = 1, - SND_SOC_DAILINK_REG(dmic_pin, dmic_codec, platform), - }, - { - .name = "iDisp1", - .id = 3, - .dpcm_playback = 1, - .init = skylake_hdmi1_init, - .no_pcm = 1, - SND_SOC_DAILINK_REG(idisp1_pin, idisp1_codec, platform), - }, - { - .name = "iDisp2", - .id = 4, - .init = skylake_hdmi2_init, - .dpcm_playback = 1, - .no_pcm = 1, - SND_SOC_DAILINK_REG(idisp2_pin, idisp2_codec, platform), - }, - { - .name = "iDisp3", - .id = 5, - .init = skylake_hdmi3_init, - .dpcm_playback = 1, - .no_pcm = 1, - SND_SOC_DAILINK_REG(idisp3_pin, idisp3_codec, platform), - }, -}; - -#define NAME_SIZE 32 -static int skylake_card_late_probe(struct snd_soc_card *card) -{ - struct skl_nau8825_private *ctx = snd_soc_card_get_drvdata(card); - struct skl_hdmi_pcm *pcm; - struct snd_soc_component *component = NULL; - int err, i = 0; - char jack_name[NAME_SIZE]; - - list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) { - component = pcm->codec_dai->component; - snprintf(jack_name, sizeof(jack_name), - "HDMI/DP, pcm=%d Jack", pcm->device); - err = snd_soc_card_jack_new(card, jack_name, - SND_JACK_AVOUT, - &skylake_hdmi[i]); - - if (err) - return err; - - err = hdac_hdmi_jack_init(pcm->codec_dai, pcm->device, - &skylake_hdmi[i]); - if (err < 0) - return err; - - i++; - } - - if (!component) - return -EINVAL; - - return hdac_hdmi_jack_port_init(component, &card->dapm); -} - -/* skylake audio machine driver for SPT + NAU88L25 */ -static struct snd_soc_card skylake_audio_card = { - .name = "sklnau8825max", - .owner = THIS_MODULE, - .dai_link = skylake_dais, - .num_links = ARRAY_SIZE(skylake_dais), - .controls = skylake_controls, - .num_controls = ARRAY_SIZE(skylake_controls), - .dapm_widgets = skylake_widgets, - .num_dapm_widgets = ARRAY_SIZE(skylake_widgets), - .dapm_routes = skylake_map, - .num_dapm_routes = ARRAY_SIZE(skylake_map), - .fully_routed = true, - .disable_route_checks = true, - .late_probe = skylake_card_late_probe, -}; - -static int skylake_audio_probe(struct platform_device *pdev) -{ - struct skl_nau8825_private *ctx; - struct snd_soc_acpi_mach *mach; - - ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); - if (!ctx) - return -ENOMEM; - - INIT_LIST_HEAD(&ctx->hdmi_pcm_list); - - skylake_audio_card.dev = &pdev->dev; - snd_soc_card_set_drvdata(&skylake_audio_card, ctx); - - mach = pdev->dev.platform_data; - if (mach) - dmic_constraints = mach->mach_params.dmic_num == 2 ? - &constraints_dmic_2ch : &constraints_dmic_channels; - - return devm_snd_soc_register_card(&pdev->dev, &skylake_audio_card); -} - -static const struct platform_device_id skl_board_ids[] = { - { .name = "skl_n88l25_m98357a" }, - { .name = "kbl_n88l25_m98357a" }, - { } -}; -MODULE_DEVICE_TABLE(platform, skl_board_ids); - -static struct platform_driver skylake_audio = { - .probe = skylake_audio_probe, - .driver = { - .name = "skl_n88l25_m98357a", - .pm = &snd_soc_pm_ops, - }, - .id_table = skl_board_ids, -}; - -module_platform_driver(skylake_audio) - -/* Module information */ -MODULE_DESCRIPTION("Audio Machine driver-NAU88L25 & MAX98357A in I2S mode"); -MODULE_AUTHOR("Rohit Ainapure -#include -#include -#include -#include -#include -#include -#include -#include "../../codecs/nau8825.h" -#include "../../codecs/hdac_hdmi.h" - -#define SKL_NUVOTON_CODEC_DAI "nau8825-hifi" -#define SKL_SSM_CODEC_DAI "ssm4567-hifi" -#define DMIC_CH(p) p->list[p->count-1] - -static struct snd_soc_jack skylake_headset; -static struct snd_soc_card skylake_audio_card; -static const struct snd_pcm_hw_constraint_list *dmic_constraints; -static struct snd_soc_jack skylake_hdmi[3]; - -struct skl_hdmi_pcm { - struct list_head head; - struct snd_soc_dai *codec_dai; - int device; -}; - -struct skl_nau88125_private { - struct list_head hdmi_pcm_list; -}; -enum { - SKL_DPCM_AUDIO_PB = 0, - SKL_DPCM_AUDIO_CP, - SKL_DPCM_AUDIO_REF_CP, - SKL_DPCM_AUDIO_DMIC_CP, - SKL_DPCM_AUDIO_HDMI1_PB, - SKL_DPCM_AUDIO_HDMI2_PB, - SKL_DPCM_AUDIO_HDMI3_PB, -}; - -static const struct snd_kcontrol_new skylake_controls[] = { - SOC_DAPM_PIN_SWITCH("Headphone Jack"), - SOC_DAPM_PIN_SWITCH("Headset Mic"), - SOC_DAPM_PIN_SWITCH("Left Speaker"), - SOC_DAPM_PIN_SWITCH("Right Speaker"), -}; - -static int platform_clock_control(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *k, int event) -{ - struct snd_soc_dapm_context *dapm = w->dapm; - struct snd_soc_card *card = dapm->card; - struct snd_soc_dai *codec_dai; - int ret; - - codec_dai = snd_soc_card_get_codec_dai(card, SKL_NUVOTON_CODEC_DAI); - if (!codec_dai) { - dev_err(card->dev, "Codec dai not found\n"); - return -EIO; - } - - if (SND_SOC_DAPM_EVENT_ON(event)) { - ret = snd_soc_dai_set_sysclk(codec_dai, - NAU8825_CLK_MCLK, 24000000, SND_SOC_CLOCK_IN); - if (ret < 0) { - dev_err(card->dev, "set sysclk err = %d\n", ret); - return -EIO; - } - } else { - ret = snd_soc_dai_set_sysclk(codec_dai, - NAU8825_CLK_INTERNAL, 0, SND_SOC_CLOCK_IN); - if (ret < 0) { - dev_err(card->dev, "set sysclk err = %d\n", ret); - return -EIO; - } - } - return ret; -} - -static const struct snd_soc_dapm_widget skylake_widgets[] = { - SND_SOC_DAPM_HP("Headphone Jack", NULL), - SND_SOC_DAPM_MIC("Headset Mic", NULL), - SND_SOC_DAPM_SPK("Left Speaker", NULL), - SND_SOC_DAPM_SPK("Right Speaker", NULL), - SND_SOC_DAPM_MIC("SoC DMIC", NULL), - SND_SOC_DAPM_SPK("DP1", NULL), - SND_SOC_DAPM_SPK("DP2", NULL), - SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0, - platform_clock_control, SND_SOC_DAPM_PRE_PMU | - SND_SOC_DAPM_POST_PMD), -}; - -static struct snd_soc_jack_pin jack_pins[] = { - { - .pin = "Headphone Jack", - .mask = SND_JACK_HEADPHONE, - }, - { - .pin = "Headset Mic", - .mask = SND_JACK_MICROPHONE, - }, -}; - -static const struct snd_soc_dapm_route skylake_map[] = { - /* HP jack connectors - unknown if we have jack detection */ - {"Headphone Jack", NULL, "HPOL"}, - {"Headphone Jack", NULL, "HPOR"}, - - /* speaker */ - {"Left Speaker", NULL, "Left OUT"}, - {"Right Speaker", NULL, "Right OUT"}, - - /* other jacks */ - {"MIC", NULL, "Headset Mic"}, - {"DMic", NULL, "SoC DMIC"}, - - /* CODEC BE connections */ - { "Left Playback", NULL, "ssp0 Tx"}, - { "Right Playback", NULL, "ssp0 Tx"}, - { "ssp0 Tx", NULL, "codec0_out"}, - - /* IV feedback path */ - { "codec0_lp_in", NULL, "ssp0 Rx"}, - { "ssp0 Rx", NULL, "Left Capture Sense" }, - { "ssp0 Rx", NULL, "Right Capture Sense" }, - - { "Playback", NULL, "ssp1 Tx"}, - { "ssp1 Tx", NULL, "codec1_out"}, - - { "codec0_in", NULL, "ssp1 Rx" }, - { "ssp1 Rx", NULL, "Capture" }, - - /* DMIC */ - { "dmic01_hifi", NULL, "DMIC01 Rx" }, - { "DMIC01 Rx", NULL, "DMIC AIF" }, - - { "hifi3", NULL, "iDisp3 Tx"}, - { "iDisp3 Tx", NULL, "iDisp3_out"}, - { "hifi2", NULL, "iDisp2 Tx"}, - { "iDisp2 Tx", NULL, "iDisp2_out"}, - { "hifi1", NULL, "iDisp1 Tx"}, - { "iDisp1 Tx", NULL, "iDisp1_out"}, - - { "Headphone Jack", NULL, "Platform Clock" }, - { "Headset Mic", NULL, "Platform Clock" }, -}; - -static struct snd_soc_codec_conf ssm4567_codec_conf[] = { - { - .dlc = COMP_CODEC_CONF("i2c-INT343B:00"), - .name_prefix = "Left", - }, - { - .dlc = COMP_CODEC_CONF("i2c-INT343B:01"), - .name_prefix = "Right", - }, -}; - -static int skylake_ssm4567_codec_init(struct snd_soc_pcm_runtime *rtd) -{ - int ret; - - /* Slot 1 for left */ - ret = snd_soc_dai_set_tdm_slot(snd_soc_rtd_to_codec(rtd, 0), 0x01, 0x01, 2, 48); - if (ret < 0) - return ret; - - /* Slot 2 for right */ - ret = snd_soc_dai_set_tdm_slot(snd_soc_rtd_to_codec(rtd, 1), 0x02, 0x02, 2, 48); - if (ret < 0) - return ret; - - return ret; -} - -static int skylake_nau8825_codec_init(struct snd_soc_pcm_runtime *rtd) -{ - int ret; - struct snd_soc_component *component = snd_soc_rtd_to_codec(rtd, 0)->component; - - /* - * 4 buttons here map to the google Reference headset - * The use of these buttons can be decided by the user space. - */ - ret = snd_soc_card_jack_new_pins(&skylake_audio_card, "Headset Jack", - SND_JACK_HEADSET | SND_JACK_BTN_0 | SND_JACK_BTN_1 | - SND_JACK_BTN_2 | SND_JACK_BTN_3, &skylake_headset, - jack_pins, - ARRAY_SIZE(jack_pins)); - if (ret) { - dev_err(rtd->dev, "Headset Jack creation failed %d\n", ret); - return ret; - } - - nau8825_enable_jack_detect(component, &skylake_headset); - - snd_soc_dapm_ignore_suspend(&rtd->card->dapm, "SoC DMIC"); - - return ret; -} - -static int skylake_hdmi1_init(struct snd_soc_pcm_runtime *rtd) -{ - struct skl_nau88125_private *ctx = snd_soc_card_get_drvdata(rtd->card); - struct snd_soc_dai *dai = snd_soc_rtd_to_codec(rtd, 0); - struct skl_hdmi_pcm *pcm; - - pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL); - if (!pcm) - return -ENOMEM; - - pcm->device = SKL_DPCM_AUDIO_HDMI1_PB; - pcm->codec_dai = dai; - - list_add_tail(&pcm->head, &ctx->hdmi_pcm_list); - - return 0; -} - -static int skylake_hdmi2_init(struct snd_soc_pcm_runtime *rtd) -{ - struct skl_nau88125_private *ctx = snd_soc_card_get_drvdata(rtd->card); - struct snd_soc_dai *dai = snd_soc_rtd_to_codec(rtd, 0); - struct skl_hdmi_pcm *pcm; - - pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL); - if (!pcm) - return -ENOMEM; - - pcm->device = SKL_DPCM_AUDIO_HDMI2_PB; - pcm->codec_dai = dai; - - list_add_tail(&pcm->head, &ctx->hdmi_pcm_list); - - return 0; -} - - -static int skylake_hdmi3_init(struct snd_soc_pcm_runtime *rtd) -{ - struct skl_nau88125_private *ctx = snd_soc_card_get_drvdata(rtd->card); - struct snd_soc_dai *dai = snd_soc_rtd_to_codec(rtd, 0); - struct skl_hdmi_pcm *pcm; - - pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL); - if (!pcm) - return -ENOMEM; - - pcm->device = SKL_DPCM_AUDIO_HDMI3_PB; - pcm->codec_dai = dai; - - list_add_tail(&pcm->head, &ctx->hdmi_pcm_list); - - return 0; -} - -static int skylake_nau8825_fe_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_dapm_context *dapm; - struct snd_soc_component *component = snd_soc_rtd_to_cpu(rtd, 0)->component; - - dapm = snd_soc_component_get_dapm(component); - snd_soc_dapm_ignore_suspend(dapm, "Reference Capture"); - - return 0; -} - -static const unsigned int rates[] = { - 48000, -}; - -static const struct snd_pcm_hw_constraint_list constraints_rates = { - .count = ARRAY_SIZE(rates), - .list = rates, - .mask = 0, -}; - -static const unsigned int channels[] = { - 2, -}; - -static const struct snd_pcm_hw_constraint_list constraints_channels = { - .count = ARRAY_SIZE(channels), - .list = channels, - .mask = 0, -}; - -static int skl_fe_startup(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - - /* - * on this platform for PCM device we support, - * 48Khz - * stereo - * 16 bit audio - */ - - runtime->hw.channels_max = 2; - snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, - &constraints_channels); - - runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE; - snd_pcm_hw_constraint_msbits(runtime, 0, 16, 16); - - snd_pcm_hw_constraint_list(runtime, 0, - SNDRV_PCM_HW_PARAM_RATE, &constraints_rates); - - return 0; -} - -static const struct snd_soc_ops skylake_nau8825_fe_ops = { - .startup = skl_fe_startup, -}; - -static int skylake_ssp_fixup(struct snd_soc_pcm_runtime *rtd, - struct snd_pcm_hw_params *params) -{ - struct snd_interval *rate = hw_param_interval(params, - SNDRV_PCM_HW_PARAM_RATE); - struct snd_interval *chan = hw_param_interval(params, - SNDRV_PCM_HW_PARAM_CHANNELS); - struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); - - /* The ADSP will convert the FE rate to 48k, stereo */ - rate->min = rate->max = 48000; - chan->min = chan->max = 2; - - /* set SSP0 to 24 bit */ - snd_mask_none(fmt); - snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S24_LE); - return 0; -} - -static int skylake_dmic_fixup(struct snd_soc_pcm_runtime *rtd, - struct snd_pcm_hw_params *params) -{ - struct snd_interval *chan = hw_param_interval(params, - SNDRV_PCM_HW_PARAM_CHANNELS); - if (params_channels(params) == 2 || DMIC_CH(dmic_constraints) == 2) - chan->min = chan->max = 2; - else - chan->min = chan->max = 4; - - return 0; -} - -static int skylake_nau8825_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); - struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); - int ret; - - ret = snd_soc_dai_set_sysclk(codec_dai, - NAU8825_CLK_MCLK, 24000000, SND_SOC_CLOCK_IN); - - if (ret < 0) - dev_err(rtd->dev, "snd_soc_dai_set_sysclk err = %d\n", ret); - - return ret; -} - -static const struct snd_soc_ops skylake_nau8825_ops = { - .hw_params = skylake_nau8825_hw_params, -}; - -static const unsigned int channels_dmic[] = { - 2, 4, -}; - -static const struct snd_pcm_hw_constraint_list constraints_dmic_channels = { - .count = ARRAY_SIZE(channels_dmic), - .list = channels_dmic, - .mask = 0, -}; - -static const unsigned int dmic_2ch[] = { - 2, -}; - -static const struct snd_pcm_hw_constraint_list constraints_dmic_2ch = { - .count = ARRAY_SIZE(dmic_2ch), - .list = dmic_2ch, - .mask = 0, -}; - -static int skylake_dmic_startup(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - - runtime->hw.channels_max = DMIC_CH(dmic_constraints); - snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, - dmic_constraints); - - return snd_pcm_hw_constraint_list(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_RATE, &constraints_rates); -} - -static const struct snd_soc_ops skylake_dmic_ops = { - .startup = skylake_dmic_startup, -}; - -static const unsigned int rates_16000[] = { - 16000, -}; - -static const struct snd_pcm_hw_constraint_list constraints_16000 = { - .count = ARRAY_SIZE(rates_16000), - .list = rates_16000, -}; - -static const unsigned int ch_mono[] = { - 1, -}; - -static const struct snd_pcm_hw_constraint_list constraints_refcap = { - .count = ARRAY_SIZE(ch_mono), - .list = ch_mono, -}; - -static int skylake_refcap_startup(struct snd_pcm_substream *substream) -{ - substream->runtime->hw.channels_max = 1; - snd_pcm_hw_constraint_list(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_CHANNELS, - &constraints_refcap); - - return snd_pcm_hw_constraint_list(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_RATE, - &constraints_16000); -} - -static const struct snd_soc_ops skylake_refcap_ops = { - .startup = skylake_refcap_startup, -}; - -SND_SOC_DAILINK_DEF(dummy, - DAILINK_COMP_ARRAY(COMP_DUMMY())); - -SND_SOC_DAILINK_DEF(system, - DAILINK_COMP_ARRAY(COMP_CPU("System Pin"))); - -SND_SOC_DAILINK_DEF(reference, - DAILINK_COMP_ARRAY(COMP_CPU("Reference Pin"))); - -SND_SOC_DAILINK_DEF(dmic, - DAILINK_COMP_ARRAY(COMP_CPU("DMIC Pin"))); - -SND_SOC_DAILINK_DEF(hdmi1, - DAILINK_COMP_ARRAY(COMP_CPU("HDMI1 Pin"))); - -SND_SOC_DAILINK_DEF(hdmi2, - DAILINK_COMP_ARRAY(COMP_CPU("HDMI2 Pin"))); - -SND_SOC_DAILINK_DEF(hdmi3, - DAILINK_COMP_ARRAY(COMP_CPU("HDMI3 Pin"))); - -SND_SOC_DAILINK_DEF(ssp0_pin, - DAILINK_COMP_ARRAY(COMP_CPU("SSP0 Pin"))); -SND_SOC_DAILINK_DEF(ssp0_codec, - DAILINK_COMP_ARRAY( - /* Left */ COMP_CODEC("i2c-INT343B:00", SKL_SSM_CODEC_DAI), - /* Right */ COMP_CODEC("i2c-INT343B:01", SKL_SSM_CODEC_DAI))); - -SND_SOC_DAILINK_DEF(ssp1_pin, - DAILINK_COMP_ARRAY(COMP_CPU("SSP1 Pin"))); -SND_SOC_DAILINK_DEF(ssp1_codec, - DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10508825:00", SKL_NUVOTON_CODEC_DAI))); - -SND_SOC_DAILINK_DEF(dmic01_pin, - DAILINK_COMP_ARRAY(COMP_CPU("DMIC01 Pin"))); -SND_SOC_DAILINK_DEF(dmic_codec, - DAILINK_COMP_ARRAY(COMP_CODEC("dmic-codec", "dmic-hifi"))); - -SND_SOC_DAILINK_DEF(idisp1_pin, - DAILINK_COMP_ARRAY(COMP_CPU("iDisp1 Pin"))); -SND_SOC_DAILINK_DEF(idisp1_codec, - DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi1"))); - -SND_SOC_DAILINK_DEF(idisp2_pin, - DAILINK_COMP_ARRAY(COMP_CPU("iDisp2 Pin"))); -SND_SOC_DAILINK_DEF(idisp2_codec, - DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi2"))); - -SND_SOC_DAILINK_DEF(idisp3_pin, - DAILINK_COMP_ARRAY(COMP_CPU("iDisp3 Pin"))); -SND_SOC_DAILINK_DEF(idisp3_codec, - DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi3"))); - -SND_SOC_DAILINK_DEF(platform, - DAILINK_COMP_ARRAY(COMP_PLATFORM("0000:00:1f.3"))); - -/* skylake digital audio interface glue - connects codec <--> CPU */ -static struct snd_soc_dai_link skylake_dais[] = { - /* Front End DAI links */ - [SKL_DPCM_AUDIO_PB] = { - .name = "Skl Audio Port", - .stream_name = "Audio", - .dynamic = 1, - .nonatomic = 1, - .init = skylake_nau8825_fe_init, - .trigger = { - SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .dpcm_playback = 1, - .ops = &skylake_nau8825_fe_ops, - SND_SOC_DAILINK_REG(system, dummy, platform), - }, - [SKL_DPCM_AUDIO_CP] = { - .name = "Skl Audio Capture Port", - .stream_name = "Audio Record", - .dynamic = 1, - .nonatomic = 1, - .trigger = { - SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .dpcm_capture = 1, - .ops = &skylake_nau8825_fe_ops, - SND_SOC_DAILINK_REG(system, dummy, platform), - }, - [SKL_DPCM_AUDIO_REF_CP] = { - .name = "Skl Audio Reference cap", - .stream_name = "Wake on Voice", - .init = NULL, - .dpcm_capture = 1, - .nonatomic = 1, - .dynamic = 1, - .ops = &skylake_refcap_ops, - SND_SOC_DAILINK_REG(reference, dummy, platform), - }, - [SKL_DPCM_AUDIO_DMIC_CP] = { - .name = "Skl Audio DMIC cap", - .stream_name = "dmiccap", - .init = NULL, - .dpcm_capture = 1, - .nonatomic = 1, - .dynamic = 1, - .ops = &skylake_dmic_ops, - SND_SOC_DAILINK_REG(dmic, dummy, platform), - }, - [SKL_DPCM_AUDIO_HDMI1_PB] = { - .name = "Skl HDMI Port1", - .stream_name = "Hdmi1", - .dpcm_playback = 1, - .init = NULL, - .trigger = { - SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .nonatomic = 1, - .dynamic = 1, - SND_SOC_DAILINK_REG(hdmi1, dummy, platform), - }, - [SKL_DPCM_AUDIO_HDMI2_PB] = { - .name = "Skl HDMI Port2", - .stream_name = "Hdmi2", - .dpcm_playback = 1, - .init = NULL, - .trigger = { - SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .nonatomic = 1, - .dynamic = 1, - SND_SOC_DAILINK_REG(hdmi2, dummy, platform), - }, - [SKL_DPCM_AUDIO_HDMI3_PB] = { - .name = "Skl HDMI Port3", - .stream_name = "Hdmi3", - .trigger = { - SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .dpcm_playback = 1, - .init = NULL, - .nonatomic = 1, - .dynamic = 1, - SND_SOC_DAILINK_REG(hdmi3, dummy, platform), - }, - - /* Back End DAI links */ - { - /* SSP0 - Codec */ - .name = "SSP0-Codec", - .id = 0, - .no_pcm = 1, - .dai_fmt = SND_SOC_DAIFMT_DSP_A | - SND_SOC_DAIFMT_IB_NF | - SND_SOC_DAIFMT_CBC_CFC, - .init = skylake_ssm4567_codec_init, - .ignore_pmdown_time = 1, - .be_hw_params_fixup = skylake_ssp_fixup, - .dpcm_playback = 1, - .dpcm_capture = 1, - SND_SOC_DAILINK_REG(ssp0_pin, ssp0_codec, platform), - }, - { - /* SSP1 - Codec */ - .name = "SSP1-Codec", - .id = 1, - .no_pcm = 1, - .init = skylake_nau8825_codec_init, - .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBC_CFC, - .ignore_pmdown_time = 1, - .be_hw_params_fixup = skylake_ssp_fixup, - .ops = &skylake_nau8825_ops, - .dpcm_playback = 1, - .dpcm_capture = 1, - SND_SOC_DAILINK_REG(ssp1_pin, ssp1_codec, platform), - }, - { - .name = "dmic01", - .id = 2, - .ignore_suspend = 1, - .be_hw_params_fixup = skylake_dmic_fixup, - .dpcm_capture = 1, - .no_pcm = 1, - SND_SOC_DAILINK_REG(dmic01_pin, dmic_codec, platform), - }, - { - .name = "iDisp1", - .id = 3, - .dpcm_playback = 1, - .init = skylake_hdmi1_init, - .no_pcm = 1, - SND_SOC_DAILINK_REG(idisp1_pin, idisp1_codec, platform), - }, - { - .name = "iDisp2", - .id = 4, - .init = skylake_hdmi2_init, - .dpcm_playback = 1, - .no_pcm = 1, - SND_SOC_DAILINK_REG(idisp2_pin, idisp2_codec, platform), - }, - { - .name = "iDisp3", - .id = 5, - .init = skylake_hdmi3_init, - .dpcm_playback = 1, - .no_pcm = 1, - SND_SOC_DAILINK_REG(idisp3_pin, idisp3_codec, platform), - }, -}; - -#define NAME_SIZE 32 -static int skylake_card_late_probe(struct snd_soc_card *card) -{ - struct skl_nau88125_private *ctx = snd_soc_card_get_drvdata(card); - struct skl_hdmi_pcm *pcm; - struct snd_soc_component *component = NULL; - int err, i = 0; - char jack_name[NAME_SIZE]; - - list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) { - component = pcm->codec_dai->component; - snprintf(jack_name, sizeof(jack_name), - "HDMI/DP, pcm=%d Jack", pcm->device); - err = snd_soc_card_jack_new(card, jack_name, - SND_JACK_AVOUT, - &skylake_hdmi[i]); - - if (err) - return err; - - err = hdac_hdmi_jack_init(pcm->codec_dai, pcm->device, - &skylake_hdmi[i]); - if (err < 0) - return err; - - i++; - } - - if (!component) - return -EINVAL; - - return hdac_hdmi_jack_port_init(component, &card->dapm); -} - -/* skylake audio machine driver for SPT + NAU88L25 */ -static struct snd_soc_card skylake_audio_card = { - .name = "sklnau8825adi", - .owner = THIS_MODULE, - .dai_link = skylake_dais, - .num_links = ARRAY_SIZE(skylake_dais), - .controls = skylake_controls, - .num_controls = ARRAY_SIZE(skylake_controls), - .dapm_widgets = skylake_widgets, - .num_dapm_widgets = ARRAY_SIZE(skylake_widgets), - .dapm_routes = skylake_map, - .num_dapm_routes = ARRAY_SIZE(skylake_map), - .codec_conf = ssm4567_codec_conf, - .num_configs = ARRAY_SIZE(ssm4567_codec_conf), - .fully_routed = true, - .disable_route_checks = true, - .late_probe = skylake_card_late_probe, -}; - -static int skylake_audio_probe(struct platform_device *pdev) -{ - struct skl_nau88125_private *ctx; - struct snd_soc_acpi_mach *mach; - - ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); - if (!ctx) - return -ENOMEM; - - INIT_LIST_HEAD(&ctx->hdmi_pcm_list); - - skylake_audio_card.dev = &pdev->dev; - snd_soc_card_set_drvdata(&skylake_audio_card, ctx); - - mach = pdev->dev.platform_data; - if (mach) - dmic_constraints = mach->mach_params.dmic_num == 2 ? - &constraints_dmic_2ch : &constraints_dmic_channels; - - return devm_snd_soc_register_card(&pdev->dev, &skylake_audio_card); -} - -static const struct platform_device_id skl_board_ids[] = { - { .name = "skl_n88l25_s4567" }, - { .name = "kbl_n88l25_s4567" }, - { } -}; -MODULE_DEVICE_TABLE(platform, skl_board_ids); - -static struct platform_driver skylake_audio = { - .probe = skylake_audio_probe, - .driver = { - .name = "skl_n88l25_s4567", - .pm = &snd_soc_pm_ops, - }, - .id_table = skl_board_ids, -}; - -module_platform_driver(skylake_audio) - -/* Module information */ -MODULE_AUTHOR("Conrad Cooke "); -MODULE_AUTHOR("Harsha Priya "); -MODULE_AUTHOR("Naveen M "); -MODULE_AUTHOR("Sathya Prakash M R "); -MODULE_AUTHOR("Yong Zhi "); -MODULE_DESCRIPTION("Intel Audio Machine driver for SKL with NAU88L25 and SSM4567 in I2S Mode"); -MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/intel/boards/skl_rt286.c b/sound/soc/intel/boards/skl_rt286.c deleted file mode 100644 index 3ea03f8144036e..00000000000000 --- a/sound/soc/intel/boards/skl_rt286.c +++ /dev/null @@ -1,568 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Intel Skylake I2S Machine Driver - * - * Copyright (C) 2014-2015, Intel Corporation - * - * Modified from: - * Intel Broadwell Wildcatpoint SST Audio - * - * Copyright (C) 2013, Intel Corporation - */ - -#include -#include -#include -#include -#include -#include -#include -#include "../../codecs/rt286.h" -#include "../../codecs/hdac_hdmi.h" - -static struct snd_soc_jack skylake_headset; -static struct snd_soc_jack skylake_hdmi[3]; - -struct skl_hdmi_pcm { - struct list_head head; - struct snd_soc_dai *codec_dai; - int device; -}; - -struct skl_rt286_private { - struct list_head hdmi_pcm_list; -}; - -enum { - SKL_DPCM_AUDIO_PB = 0, - SKL_DPCM_AUDIO_DB_PB, - SKL_DPCM_AUDIO_CP, - SKL_DPCM_AUDIO_REF_CP, - SKL_DPCM_AUDIO_DMIC_CP, - SKL_DPCM_AUDIO_HDMI1_PB, - SKL_DPCM_AUDIO_HDMI2_PB, - SKL_DPCM_AUDIO_HDMI3_PB, -}; - -/* Headset jack detection DAPM pins */ -static struct snd_soc_jack_pin skylake_headset_pins[] = { - { - .pin = "Mic Jack", - .mask = SND_JACK_MICROPHONE, - }, - { - .pin = "Headphone Jack", - .mask = SND_JACK_HEADPHONE, - }, -}; - -static const struct snd_kcontrol_new skylake_controls[] = { - SOC_DAPM_PIN_SWITCH("Speaker"), - SOC_DAPM_PIN_SWITCH("Headphone Jack"), - SOC_DAPM_PIN_SWITCH("Mic Jack"), -}; - -static const struct snd_soc_dapm_widget skylake_widgets[] = { - SND_SOC_DAPM_HP("Headphone Jack", NULL), - SND_SOC_DAPM_SPK("Speaker", NULL), - SND_SOC_DAPM_MIC("Mic Jack", NULL), - SND_SOC_DAPM_MIC("DMIC2", NULL), - SND_SOC_DAPM_MIC("SoC DMIC", NULL), - SND_SOC_DAPM_SPK("HDMI1", NULL), - SND_SOC_DAPM_SPK("HDMI2", NULL), - SND_SOC_DAPM_SPK("HDMI3", NULL), -}; - -static const struct snd_soc_dapm_route skylake_rt286_map[] = { - /* speaker */ - {"Speaker", NULL, "SPOR"}, - {"Speaker", NULL, "SPOL"}, - - /* HP jack connectors - unknown if we have jack deteck */ - {"Headphone Jack", NULL, "HPO Pin"}, - - /* other jacks */ - {"MIC1", NULL, "Mic Jack"}, - - /* digital mics */ - {"DMIC1 Pin", NULL, "DMIC2"}, - {"DMic", NULL, "SoC DMIC"}, - - /* CODEC BE connections */ - { "AIF1 Playback", NULL, "ssp0 Tx"}, - { "ssp0 Tx", NULL, "codec0_out"}, - { "ssp0 Tx", NULL, "codec1_out"}, - - { "codec0_in", NULL, "ssp0 Rx" }, - { "codec1_in", NULL, "ssp0 Rx" }, - { "ssp0 Rx", NULL, "AIF1 Capture" }, - - { "dmic01_hifi", NULL, "DMIC01 Rx" }, - { "DMIC01 Rx", NULL, "DMIC AIF" }, - - { "hifi3", NULL, "iDisp3 Tx"}, - { "iDisp3 Tx", NULL, "iDisp3_out"}, - { "hifi2", NULL, "iDisp2 Tx"}, - { "iDisp2 Tx", NULL, "iDisp2_out"}, - { "hifi1", NULL, "iDisp1 Tx"}, - { "iDisp1 Tx", NULL, "iDisp1_out"}, - -}; - -static int skylake_rt286_fe_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_dapm_context *dapm; - struct snd_soc_component *component = snd_soc_rtd_to_cpu(rtd, 0)->component; - - dapm = snd_soc_component_get_dapm(component); - snd_soc_dapm_ignore_suspend(dapm, "Reference Capture"); - - return 0; -} - -static int skylake_rt286_codec_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_component *component = snd_soc_rtd_to_codec(rtd, 0)->component; - int ret; - - ret = snd_soc_card_jack_new_pins(rtd->card, "Headset", - SND_JACK_HEADSET | SND_JACK_BTN_0, - &skylake_headset, - skylake_headset_pins, ARRAY_SIZE(skylake_headset_pins)); - - if (ret) - return ret; - - snd_soc_component_set_jack(component, &skylake_headset, NULL); - - snd_soc_dapm_ignore_suspend(&rtd->card->dapm, "SoC DMIC"); - - return 0; -} - -static int skylake_hdmi_init(struct snd_soc_pcm_runtime *rtd) -{ - struct skl_rt286_private *ctx = snd_soc_card_get_drvdata(rtd->card); - struct snd_soc_dai *dai = snd_soc_rtd_to_codec(rtd, 0); - struct skl_hdmi_pcm *pcm; - - pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL); - if (!pcm) - return -ENOMEM; - - pcm->device = SKL_DPCM_AUDIO_HDMI1_PB + dai->id; - pcm->codec_dai = dai; - - list_add_tail(&pcm->head, &ctx->hdmi_pcm_list); - - return 0; -} - -static const unsigned int rates[] = { - 48000, -}; - -static const struct snd_pcm_hw_constraint_list constraints_rates = { - .count = ARRAY_SIZE(rates), - .list = rates, - .mask = 0, -}; - -static const unsigned int channels[] = { - 2, -}; - -static const struct snd_pcm_hw_constraint_list constraints_channels = { - .count = ARRAY_SIZE(channels), - .list = channels, - .mask = 0, -}; - -static int skl_fe_startup(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - - /* - * on this platform for PCM device we support, - * 48Khz - * stereo - * 16 bit audio - */ - - runtime->hw.channels_max = 2; - snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, - &constraints_channels); - - runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE; - snd_pcm_hw_constraint_msbits(runtime, 0, 16, 16); - - snd_pcm_hw_constraint_list(runtime, 0, - SNDRV_PCM_HW_PARAM_RATE, &constraints_rates); - - return 0; -} - -static const struct snd_soc_ops skylake_rt286_fe_ops = { - .startup = skl_fe_startup, -}; - -static int skylake_ssp0_fixup(struct snd_soc_pcm_runtime *rtd, - struct snd_pcm_hw_params *params) -{ - struct snd_interval *rate = hw_param_interval(params, - SNDRV_PCM_HW_PARAM_RATE); - struct snd_interval *chan = hw_param_interval(params, - SNDRV_PCM_HW_PARAM_CHANNELS); - struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); - - /* The output is 48KHz, stereo, 16bits */ - rate->min = rate->max = 48000; - chan->min = chan->max = 2; - - /* set SSP0 to 24 bit */ - snd_mask_none(fmt); - snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S24_LE); - return 0; -} - -static int skylake_rt286_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); - struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); - int ret; - - ret = snd_soc_dai_set_sysclk(codec_dai, RT286_SCLK_S_PLL, 24000000, - SND_SOC_CLOCK_IN); - if (ret < 0) - dev_err(rtd->dev, "set codec sysclk failed: %d\n", ret); - - return ret; -} - -static const struct snd_soc_ops skylake_rt286_ops = { - .hw_params = skylake_rt286_hw_params, -}; - -static int skylake_dmic_fixup(struct snd_soc_pcm_runtime *rtd, - struct snd_pcm_hw_params *params) -{ - struct snd_interval *chan = hw_param_interval(params, - SNDRV_PCM_HW_PARAM_CHANNELS); - if (params_channels(params) == 2) - chan->min = chan->max = 2; - else - chan->min = chan->max = 4; - - return 0; -} - -static const unsigned int channels_dmic[] = { - 2, 4, -}; - -static const struct snd_pcm_hw_constraint_list constraints_dmic_channels = { - .count = ARRAY_SIZE(channels_dmic), - .list = channels_dmic, - .mask = 0, -}; - -static int skylake_dmic_startup(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - - runtime->hw.channels_max = 4; - snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, - &constraints_dmic_channels); - - return snd_pcm_hw_constraint_list(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_RATE, &constraints_rates); -} - -static const struct snd_soc_ops skylake_dmic_ops = { - .startup = skylake_dmic_startup, -}; - -SND_SOC_DAILINK_DEF(dummy, - DAILINK_COMP_ARRAY(COMP_DUMMY())); - -SND_SOC_DAILINK_DEF(system, - DAILINK_COMP_ARRAY(COMP_CPU("System Pin"))); - -SND_SOC_DAILINK_DEF(deepbuffer, - DAILINK_COMP_ARRAY(COMP_CPU("Deepbuffer Pin"))); - -SND_SOC_DAILINK_DEF(reference, - DAILINK_COMP_ARRAY(COMP_CPU("Reference Pin"))); - -SND_SOC_DAILINK_DEF(dmic, - DAILINK_COMP_ARRAY(COMP_CPU("DMIC Pin"))); - -SND_SOC_DAILINK_DEF(hdmi1, - DAILINK_COMP_ARRAY(COMP_CPU("HDMI1 Pin"))); - -SND_SOC_DAILINK_DEF(hdmi2, - DAILINK_COMP_ARRAY(COMP_CPU("HDMI2 Pin"))); - -SND_SOC_DAILINK_DEF(hdmi3, - DAILINK_COMP_ARRAY(COMP_CPU("HDMI3 Pin"))); - -SND_SOC_DAILINK_DEF(ssp0_pin, - DAILINK_COMP_ARRAY(COMP_CPU("SSP0 Pin"))); -SND_SOC_DAILINK_DEF(ssp0_codec, - DAILINK_COMP_ARRAY(COMP_CODEC("i2c-INT343A:00", "rt286-aif1"))); - -SND_SOC_DAILINK_DEF(dmic01_pin, - DAILINK_COMP_ARRAY(COMP_CPU("DMIC01 Pin"))); -SND_SOC_DAILINK_DEF(dmic_codec, - DAILINK_COMP_ARRAY(COMP_CODEC("dmic-codec", "dmic-hifi"))); - -SND_SOC_DAILINK_DEF(idisp1_pin, - DAILINK_COMP_ARRAY(COMP_CPU("iDisp1 Pin"))); -SND_SOC_DAILINK_DEF(idisp1_codec, - DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi1"))); - -SND_SOC_DAILINK_DEF(idisp2_pin, - DAILINK_COMP_ARRAY(COMP_CPU("iDisp2 Pin"))); -SND_SOC_DAILINK_DEF(idisp2_codec, - DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi2"))); - -SND_SOC_DAILINK_DEF(idisp3_pin, - DAILINK_COMP_ARRAY(COMP_CPU("iDisp3 Pin"))); -SND_SOC_DAILINK_DEF(idisp3_codec, - DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi3"))); - -SND_SOC_DAILINK_DEF(platform, - DAILINK_COMP_ARRAY(COMP_PLATFORM("0000:00:1f.3"))); - -/* skylake digital audio interface glue - connects codec <--> CPU */ -static struct snd_soc_dai_link skylake_rt286_dais[] = { - /* Front End DAI links */ - [SKL_DPCM_AUDIO_PB] = { - .name = "Skl Audio Port", - .stream_name = "Audio", - .nonatomic = 1, - .dynamic = 1, - .init = skylake_rt286_fe_init, - .trigger = { - SND_SOC_DPCM_TRIGGER_POST, - SND_SOC_DPCM_TRIGGER_POST - }, - .dpcm_playback = 1, - .ops = &skylake_rt286_fe_ops, - SND_SOC_DAILINK_REG(system, dummy, platform), - }, - [SKL_DPCM_AUDIO_DB_PB] = { - .name = "Skl Deepbuffer Port", - .stream_name = "Deep Buffer Audio", - .nonatomic = 1, - .dynamic = 1, - .trigger = { - SND_SOC_DPCM_TRIGGER_POST, - SND_SOC_DPCM_TRIGGER_POST - }, - .dpcm_playback = 1, - .ops = &skylake_rt286_fe_ops, - SND_SOC_DAILINK_REG(deepbuffer, dummy, platform), - }, - [SKL_DPCM_AUDIO_CP] = { - .name = "Skl Audio Capture Port", - .stream_name = "Audio Record", - .nonatomic = 1, - .dynamic = 1, - .trigger = { - SND_SOC_DPCM_TRIGGER_POST, - SND_SOC_DPCM_TRIGGER_POST - }, - .dpcm_capture = 1, - .ops = &skylake_rt286_fe_ops, - SND_SOC_DAILINK_REG(system, dummy, platform), - }, - [SKL_DPCM_AUDIO_REF_CP] = { - .name = "Skl Audio Reference cap", - .stream_name = "refcap", - .init = NULL, - .dpcm_capture = 1, - .nonatomic = 1, - .dynamic = 1, - SND_SOC_DAILINK_REG(reference, dummy, platform), - }, - [SKL_DPCM_AUDIO_DMIC_CP] = { - .name = "Skl Audio DMIC cap", - .stream_name = "dmiccap", - .init = NULL, - .dpcm_capture = 1, - .nonatomic = 1, - .dynamic = 1, - .ops = &skylake_dmic_ops, - SND_SOC_DAILINK_REG(dmic, dummy, platform), - }, - [SKL_DPCM_AUDIO_HDMI1_PB] = { - .name = "Skl HDMI Port1", - .stream_name = "Hdmi1", - .dpcm_playback = 1, - .init = NULL, - .nonatomic = 1, - .dynamic = 1, - SND_SOC_DAILINK_REG(hdmi1, dummy, platform), - }, - [SKL_DPCM_AUDIO_HDMI2_PB] = { - .name = "Skl HDMI Port2", - .stream_name = "Hdmi2", - .dpcm_playback = 1, - .init = NULL, - .nonatomic = 1, - .dynamic = 1, - SND_SOC_DAILINK_REG(hdmi2, dummy, platform), - }, - [SKL_DPCM_AUDIO_HDMI3_PB] = { - .name = "Skl HDMI Port3", - .stream_name = "Hdmi3", - .dpcm_playback = 1, - .init = NULL, - .nonatomic = 1, - .dynamic = 1, - SND_SOC_DAILINK_REG(hdmi3, dummy, platform), - }, - - /* Back End DAI links */ - { - /* SSP0 - Codec */ - .name = "SSP0-Codec", - .id = 0, - .no_pcm = 1, - .init = skylake_rt286_codec_init, - .dai_fmt = SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBC_CFC, - .ignore_pmdown_time = 1, - .be_hw_params_fixup = skylake_ssp0_fixup, - .ops = &skylake_rt286_ops, - .dpcm_playback = 1, - .dpcm_capture = 1, - SND_SOC_DAILINK_REG(ssp0_pin, ssp0_codec, platform), - }, - { - .name = "dmic01", - .id = 1, - .be_hw_params_fixup = skylake_dmic_fixup, - .ignore_suspend = 1, - .dpcm_capture = 1, - .no_pcm = 1, - SND_SOC_DAILINK_REG(dmic01_pin, dmic_codec, platform), - }, - { - .name = "iDisp1", - .id = 2, - .init = skylake_hdmi_init, - .dpcm_playback = 1, - .no_pcm = 1, - SND_SOC_DAILINK_REG(idisp1_pin, idisp1_codec, platform), - }, - { - .name = "iDisp2", - .id = 3, - .init = skylake_hdmi_init, - .dpcm_playback = 1, - .no_pcm = 1, - SND_SOC_DAILINK_REG(idisp2_pin, idisp2_codec, platform), - }, - { - .name = "iDisp3", - .id = 4, - .init = skylake_hdmi_init, - .dpcm_playback = 1, - .no_pcm = 1, - SND_SOC_DAILINK_REG(idisp3_pin, idisp3_codec, platform), - }, -}; - -#define NAME_SIZE 32 -static int skylake_card_late_probe(struct snd_soc_card *card) -{ - struct skl_rt286_private *ctx = snd_soc_card_get_drvdata(card); - struct skl_hdmi_pcm *pcm; - struct snd_soc_component *component = NULL; - int err, i = 0; - char jack_name[NAME_SIZE]; - - list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) { - component = pcm->codec_dai->component; - snprintf(jack_name, sizeof(jack_name), - "HDMI/DP, pcm=%d Jack", pcm->device); - err = snd_soc_card_jack_new(card, jack_name, - SND_JACK_AVOUT, &skylake_hdmi[i]); - - if (err) - return err; - - err = hdac_hdmi_jack_init(pcm->codec_dai, pcm->device, - &skylake_hdmi[i]); - if (err < 0) - return err; - - i++; - } - - if (!component) - return -EINVAL; - - return hdac_hdmi_jack_port_init(component, &card->dapm); -} - -/* skylake audio machine driver for SPT + RT286S */ -static struct snd_soc_card skylake_rt286 = { - .name = "skylake-rt286", - .owner = THIS_MODULE, - .dai_link = skylake_rt286_dais, - .num_links = ARRAY_SIZE(skylake_rt286_dais), - .controls = skylake_controls, - .num_controls = ARRAY_SIZE(skylake_controls), - .dapm_widgets = skylake_widgets, - .num_dapm_widgets = ARRAY_SIZE(skylake_widgets), - .dapm_routes = skylake_rt286_map, - .num_dapm_routes = ARRAY_SIZE(skylake_rt286_map), - .fully_routed = true, - .disable_route_checks = true, - .late_probe = skylake_card_late_probe, -}; - -static int skylake_audio_probe(struct platform_device *pdev) -{ - struct skl_rt286_private *ctx; - - ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); - if (!ctx) - return -ENOMEM; - - INIT_LIST_HEAD(&ctx->hdmi_pcm_list); - - skylake_rt286.dev = &pdev->dev; - snd_soc_card_set_drvdata(&skylake_rt286, ctx); - - return devm_snd_soc_register_card(&pdev->dev, &skylake_rt286); -} - -static const struct platform_device_id skl_board_ids[] = { - { .name = "skl_alc286s_i2s" }, - { .name = "kbl_alc286s_i2s" }, - { } -}; -MODULE_DEVICE_TABLE(platform, skl_board_ids); - -static struct platform_driver skylake_audio = { - .probe = skylake_audio_probe, - .driver = { - .name = "skl_alc286s_i2s", - .pm = &snd_soc_pm_ops, - }, - .id_table = skl_board_ids, - -}; - -module_platform_driver(skylake_audio) - -/* Module information */ -MODULE_AUTHOR("Omair Mohammed Abdullah "); -MODULE_DESCRIPTION("Intel SST Audio for Skylake"); -MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/intel/common/soc-acpi-intel-cnl-match.c b/sound/soc/intel/common/soc-acpi-intel-cnl-match.c index 3df89e4511da74..8bbb1052faf232 100644 --- a/sound/soc/intel/common/soc-acpi-intel-cnl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-cnl-match.c @@ -8,7 +8,6 @@ #include #include -#include "../skylake/skl.h" #include "soc-acpi-intel-sdw-mockup-match.h" static const struct snd_soc_acpi_codecs essx_83x6 = { @@ -16,16 +15,11 @@ static const struct snd_soc_acpi_codecs essx_83x6 = { .codecs = { "ESSX8316", "ESSX8326", "ESSX8336"}, }; -static struct skl_machine_pdata cnl_pdata = { - .use_tplg_pcm = true, -}; - struct snd_soc_acpi_mach snd_soc_acpi_intel_cnl_machines[] = { { .id = "INT34C2", .drv_name = "cnl_rt274", .fw_filename = "intel/dsp_fw_cnl.bin", - .pdata = &cnl_pdata, .sof_tplg_filename = "sof-cnl-rt274.tplg", }, { diff --git a/sound/soc/intel/common/soc-acpi-intel-ehl-match.c b/sound/soc/intel/common/soc-acpi-intel-ehl-match.c index 84639c41a2683f..78255d56b08c43 100644 --- a/sound/soc/intel/common/soc-acpi-intel-ehl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-ehl-match.c @@ -8,7 +8,6 @@ #include #include -#include "../skylake/skl.h" struct snd_soc_acpi_mach snd_soc_acpi_intel_ehl_machines[] = { { diff --git a/sound/soc/intel/common/soc-acpi-intel-icl-match.c b/sound/soc/intel/common/soc-acpi-intel-icl-match.c index 39875d67dcd1d3..6ce75fbb842e14 100644 --- a/sound/soc/intel/common/soc-acpi-intel-icl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-icl-match.c @@ -8,23 +8,17 @@ #include #include -#include "../skylake/skl.h" static const struct snd_soc_acpi_codecs essx_83x6 = { .num_codecs = 3, .codecs = { "ESSX8316", "ESSX8326", "ESSX8336"}, }; -static struct skl_machine_pdata icl_pdata = { - .use_tplg_pcm = true, -}; - struct snd_soc_acpi_mach snd_soc_acpi_intel_icl_machines[] = { { .id = "INT34C2", .drv_name = "icl_rt274", .fw_filename = "intel/dsp_fw_icl.bin", - .pdata = &icl_pdata, .sof_tplg_filename = "sof-icl-rt274.tplg", }, { diff --git a/sound/soc/intel/common/soc-acpi-intel-kbl-match.c b/sound/soc/intel/common/soc-acpi-intel-kbl-match.c index 4e817f559d3884..d4c158d8441b80 100644 --- a/sound/soc/intel/common/soc-acpi-intel-kbl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-kbl-match.c @@ -8,9 +8,6 @@ #include #include -#include "../skylake/skl.h" - -static struct skl_machine_pdata skl_dmic_data; static const struct snd_soc_acpi_codecs kbl_codecs = { .num_codecs = 1, @@ -54,7 +51,6 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_kbl_machines[] = { .fw_filename = "intel/dsp_fw_kbl.bin", .machine_quirk = snd_soc_acpi_codec_list, .quirk_data = &kbl_codecs, - .pdata = &skl_dmic_data, }, { .id = "MX98357A", @@ -62,7 +58,6 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_kbl_machines[] = { .fw_filename = "intel/dsp_fw_kbl.bin", .machine_quirk = snd_soc_acpi_codec_list, .quirk_data = &kbl_codecs, - .pdata = &skl_dmic_data, }, { .id = "MX98927", @@ -70,7 +65,6 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_kbl_machines[] = { .fw_filename = "intel/dsp_fw_kbl.bin", .machine_quirk = snd_soc_acpi_codec_list, .quirk_data = &kbl_5663_5514_codecs, - .pdata = &skl_dmic_data, }, { .id = "MX98927", @@ -78,7 +72,6 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_kbl_machines[] = { .fw_filename = "intel/dsp_fw_kbl.bin", .machine_quirk = snd_soc_acpi_codec_list, .quirk_data = &kbl_poppy_codecs, - .pdata = &skl_dmic_data, }, { .id = "10EC5663", @@ -91,7 +84,6 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_kbl_machines[] = { .fw_filename = "intel/dsp_fw_kbl.bin", .machine_quirk = snd_soc_acpi_codec_list, .quirk_data = &kbl_7219_98357_codecs, - .pdata = &skl_dmic_data, }, { .id = "DLGS7219", @@ -99,7 +91,6 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_kbl_machines[] = { .fw_filename = "intel/dsp_fw_kbl.bin", .machine_quirk = snd_soc_acpi_codec_list, .quirk_data = &kbl_7219_98927_codecs, - .pdata = &skl_dmic_data }, { .id = "10EC5660", @@ -117,13 +108,11 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_kbl_machines[] = { .fw_filename = "intel/dsp_fw_kbl.bin", .machine_quirk = snd_soc_acpi_codec_list, .quirk_data = &kbl_7219_98373_codecs, - .pdata = &skl_dmic_data }, { .id = "MX98373", .drv_name = "kbl_max98373", .fw_filename = "intel/dsp_fw_kbl.bin", - .pdata = &skl_dmic_data }, {}, }; diff --git a/sound/soc/intel/common/soc-acpi-intel-skl-match.c b/sound/soc/intel/common/soc-acpi-intel-skl-match.c index 75302e95674244..ee646320291855 100644 --- a/sound/soc/intel/common/soc-acpi-intel-skl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-skl-match.c @@ -8,9 +8,6 @@ #include #include -#include "../skylake/skl.h" - -static struct skl_machine_pdata skl_dmic_data; static const struct snd_soc_acpi_codecs skl_codecs = { .num_codecs = 1, @@ -29,7 +26,6 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_skl_machines[] = { .fw_filename = "intel/dsp_fw_release.bin", .machine_quirk = snd_soc_acpi_codec_list, .quirk_data = &skl_codecs, - .pdata = &skl_dmic_data, }, { .id = "MX98357A", @@ -37,7 +33,6 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_skl_machines[] = { .fw_filename = "intel/dsp_fw_release.bin", .machine_quirk = snd_soc_acpi_codec_list, .quirk_data = &skl_codecs, - .pdata = &skl_dmic_data, }, {}, }; diff --git a/sound/soc/intel/skylake/Makefile b/sound/soc/intel/skylake/Makefile deleted file mode 100644 index ad9be6168428e8..00000000000000 --- a/sound/soc/intel/skylake/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -snd-soc-skl-y := skl.o skl-pcm.o skl-nhlt.o skl-messages.o skl-topology.o \ - skl-sst-ipc.o skl-sst-dsp.o cnl-sst-dsp.o skl-sst-cldma.o \ - skl-sst.o bxt-sst.o cnl-sst.o skl-sst-utils.o - -ifdef CONFIG_DEBUG_FS - snd-soc-skl-y += skl-debug.o -endif - -obj-$(CONFIG_SND_SOC_INTEL_SKYLAKE_COMMON) += snd-soc-skl.o - -#Skylake Clock device support -snd-soc-skl-ssp-clk-y := skl-ssp-clk.o - -obj-$(CONFIG_SND_SOC_INTEL_SKYLAKE_SSP_CLK) += snd-soc-skl-ssp-clk.o diff --git a/sound/soc/intel/skylake/bxt-sst.c b/sound/soc/intel/skylake/bxt-sst.c deleted file mode 100644 index fd4fdcb95224ab..00000000000000 --- a/sound/soc/intel/skylake/bxt-sst.c +++ /dev/null @@ -1,629 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * bxt-sst.c - DSP library functions for BXT platform - * - * Copyright (C) 2015-16 Intel Corp - * Author:Rafal Redzimski - * Jeeja KP - */ - -#include -#include -#include -#include - -#include "../common/sst-dsp.h" -#include "../common/sst-dsp-priv.h" -#include "skl.h" - -#define BXT_BASEFW_TIMEOUT 3000 -#define BXT_ROM_INIT_TIMEOUT 70 -#define BXT_IPC_PURGE_FW 0x01004000 - -#define BXT_ROM_INIT 0x5 -#define BXT_ADSP_SRAM0_BASE 0x80000 - -/* Firmware status window */ -#define BXT_ADSP_FW_STATUS BXT_ADSP_SRAM0_BASE -#define BXT_ADSP_ERROR_CODE (BXT_ADSP_FW_STATUS + 0x4) - -#define BXT_ADSP_SRAM1_BASE 0xA0000 - -#define BXT_INSTANCE_ID 0 -#define BXT_BASE_FW_MODULE_ID 0 - -#define BXT_ADSP_FW_BIN_HDR_OFFSET 0x2000 - -/* Delay before scheduling D0i3 entry */ -#define BXT_D0I3_DELAY 5000 - -static unsigned int bxt_get_errorcode(struct sst_dsp *ctx) -{ - return sst_dsp_shim_read(ctx, BXT_ADSP_ERROR_CODE); -} - -static int -bxt_load_library(struct sst_dsp *ctx, struct skl_lib_info *linfo, int lib_count) -{ - struct snd_dma_buffer dmab; - struct skl_dev *skl = ctx->thread_context; - struct firmware stripped_fw; - int ret = 0, i, dma_id, stream_tag; - - /* library indices start from 1 to N. 0 represents base FW */ - for (i = 1; i < lib_count; i++) { - ret = skl_prepare_lib_load(skl, &skl->lib_info[i], &stripped_fw, - BXT_ADSP_FW_BIN_HDR_OFFSET, i); - if (ret < 0) - goto load_library_failed; - - stream_tag = ctx->dsp_ops.prepare(ctx->dev, 0x40, - stripped_fw.size, &dmab); - if (stream_tag <= 0) { - dev_err(ctx->dev, "Lib prepare DMA err: %x\n", - stream_tag); - ret = stream_tag; - goto load_library_failed; - } - - dma_id = stream_tag - 1; - memcpy(dmab.area, stripped_fw.data, stripped_fw.size); - - ctx->dsp_ops.trigger(ctx->dev, true, stream_tag); - ret = skl_sst_ipc_load_library(&skl->ipc, dma_id, i, true); - if (ret < 0) - dev_err(ctx->dev, "IPC Load Lib for %s fail: %d\n", - linfo[i].name, ret); - - ctx->dsp_ops.trigger(ctx->dev, false, stream_tag); - ctx->dsp_ops.cleanup(ctx->dev, &dmab, stream_tag); - } - - return ret; - -load_library_failed: - skl_release_library(linfo, lib_count); - return ret; -} - -/* - * First boot sequence has some extra steps. Core 0 waits for power - * status on core 1, so power up core 1 also momentarily, keep it in - * reset/stall and then turn it off - */ -static int sst_bxt_prepare_fw(struct sst_dsp *ctx, - const void *fwdata, u32 fwsize) -{ - int stream_tag, ret; - - stream_tag = ctx->dsp_ops.prepare(ctx->dev, 0x40, fwsize, &ctx->dmab); - if (stream_tag <= 0) { - dev_err(ctx->dev, "Failed to prepare DMA FW loading err: %x\n", - stream_tag); - return stream_tag; - } - - ctx->dsp_ops.stream_tag = stream_tag; - memcpy(ctx->dmab.area, fwdata, fwsize); - - /* Step 1: Power up core 0 and core1 */ - ret = skl_dsp_core_power_up(ctx, SKL_DSP_CORE0_MASK | - SKL_DSP_CORE_MASK(1)); - if (ret < 0) { - dev_err(ctx->dev, "dsp core0/1 power up failed\n"); - goto base_fw_load_failed; - } - - /* Step 2: Purge FW request */ - sst_dsp_shim_write(ctx, SKL_ADSP_REG_HIPCI, SKL_ADSP_REG_HIPCI_BUSY | - (BXT_IPC_PURGE_FW | ((stream_tag - 1) << 9))); - - /* Step 3: Unset core0 reset state & unstall/run core0 */ - ret = skl_dsp_start_core(ctx, SKL_DSP_CORE0_MASK); - if (ret < 0) { - dev_err(ctx->dev, "Start dsp core failed ret: %d\n", ret); - ret = -EIO; - goto base_fw_load_failed; - } - - /* Step 4: Wait for DONE Bit */ - ret = sst_dsp_register_poll(ctx, SKL_ADSP_REG_HIPCIE, - SKL_ADSP_REG_HIPCIE_DONE, - SKL_ADSP_REG_HIPCIE_DONE, - BXT_INIT_TIMEOUT, "HIPCIE Done"); - if (ret < 0) { - dev_err(ctx->dev, "Timeout for Purge Request%d\n", ret); - goto base_fw_load_failed; - } - - /* Step 5: power down core1 */ - ret = skl_dsp_core_power_down(ctx, SKL_DSP_CORE_MASK(1)); - if (ret < 0) { - dev_err(ctx->dev, "dsp core1 power down failed\n"); - goto base_fw_load_failed; - } - - /* Step 6: Enable Interrupt */ - skl_ipc_int_enable(ctx); - skl_ipc_op_int_enable(ctx); - - /* Step 7: Wait for ROM init */ - ret = sst_dsp_register_poll(ctx, BXT_ADSP_FW_STATUS, SKL_FW_STS_MASK, - SKL_FW_INIT, BXT_ROM_INIT_TIMEOUT, "ROM Load"); - if (ret < 0) { - dev_err(ctx->dev, "Timeout for ROM init, ret:%d\n", ret); - goto base_fw_load_failed; - } - - return ret; - -base_fw_load_failed: - ctx->dsp_ops.cleanup(ctx->dev, &ctx->dmab, stream_tag); - skl_dsp_core_power_down(ctx, SKL_DSP_CORE_MASK(1)); - skl_dsp_disable_core(ctx, SKL_DSP_CORE0_MASK); - return ret; -} - -static int sst_transfer_fw_host_dma(struct sst_dsp *ctx) -{ - int ret; - - ctx->dsp_ops.trigger(ctx->dev, true, ctx->dsp_ops.stream_tag); - ret = sst_dsp_register_poll(ctx, BXT_ADSP_FW_STATUS, SKL_FW_STS_MASK, - BXT_ROM_INIT, BXT_BASEFW_TIMEOUT, "Firmware boot"); - - ctx->dsp_ops.trigger(ctx->dev, false, ctx->dsp_ops.stream_tag); - ctx->dsp_ops.cleanup(ctx->dev, &ctx->dmab, ctx->dsp_ops.stream_tag); - - return ret; -} - -static int bxt_load_base_firmware(struct sst_dsp *ctx) -{ - struct firmware stripped_fw; - struct skl_dev *skl = ctx->thread_context; - int ret, i; - - if (ctx->fw == NULL) { - ret = request_firmware(&ctx->fw, ctx->fw_name, ctx->dev); - if (ret < 0) { - dev_err(ctx->dev, "Request firmware failed %d\n", ret); - return ret; - } - } - - /* prase uuids on first boot */ - if (skl->is_first_boot) { - ret = snd_skl_parse_uuids(ctx, ctx->fw, BXT_ADSP_FW_BIN_HDR_OFFSET, 0); - if (ret < 0) - goto sst_load_base_firmware_failed; - } - - stripped_fw.data = ctx->fw->data; - stripped_fw.size = ctx->fw->size; - skl_dsp_strip_extended_manifest(&stripped_fw); - - - for (i = 0; i < BXT_FW_ROM_INIT_RETRY; i++) { - ret = sst_bxt_prepare_fw(ctx, stripped_fw.data, stripped_fw.size); - if (ret == 0) - break; - } - - if (ret < 0) { - dev_err(ctx->dev, "Error code=0x%x: FW status=0x%x\n", - sst_dsp_shim_read(ctx, BXT_ADSP_ERROR_CODE), - sst_dsp_shim_read(ctx, BXT_ADSP_FW_STATUS)); - - dev_err(ctx->dev, "Core En/ROM load fail:%d\n", ret); - goto sst_load_base_firmware_failed; - } - - ret = sst_transfer_fw_host_dma(ctx); - if (ret < 0) { - dev_err(ctx->dev, "Transfer firmware failed %d\n", ret); - dev_info(ctx->dev, "Error code=0x%x: FW status=0x%x\n", - sst_dsp_shim_read(ctx, BXT_ADSP_ERROR_CODE), - sst_dsp_shim_read(ctx, BXT_ADSP_FW_STATUS)); - - skl_dsp_disable_core(ctx, SKL_DSP_CORE0_MASK); - } else { - dev_dbg(ctx->dev, "Firmware download successful\n"); - ret = wait_event_timeout(skl->boot_wait, skl->boot_complete, - msecs_to_jiffies(SKL_IPC_BOOT_MSECS)); - if (ret == 0) { - dev_err(ctx->dev, "DSP boot fail, FW Ready timeout\n"); - skl_dsp_disable_core(ctx, SKL_DSP_CORE0_MASK); - ret = -EIO; - } else { - ret = 0; - skl->fw_loaded = true; - } - } - - return ret; - -sst_load_base_firmware_failed: - release_firmware(ctx->fw); - ctx->fw = NULL; - return ret; -} - -/* - * Decide the D0i3 state that can be targeted based on the usecase - * ref counts and DSP state - * - * Decision Matrix: (X= dont care; state = target state) - * - * DSP state != SKL_DSP_RUNNING ; state = no d0i3 - * - * DSP state == SKL_DSP_RUNNING , the following matrix applies - * non_d0i3 >0; streaming =X; non_streaming =X; state = no d0i3 - * non_d0i3 =X; streaming =0; non_streaming =0; state = no d0i3 - * non_d0i3 =0; streaming >0; non_streaming =X; state = streaming d0i3 - * non_d0i3 =0; streaming =0; non_streaming =X; state = non-streaming d0i3 - */ -static int bxt_d0i3_target_state(struct sst_dsp *ctx) -{ - struct skl_dev *skl = ctx->thread_context; - struct skl_d0i3_data *d0i3 = &skl->d0i3; - - if (skl->cores.state[SKL_DSP_CORE0_ID] != SKL_DSP_RUNNING) - return SKL_DSP_D0I3_NONE; - - if (d0i3->non_d0i3) - return SKL_DSP_D0I3_NONE; - else if (d0i3->streaming) - return SKL_DSP_D0I3_STREAMING; - else if (d0i3->non_streaming) - return SKL_DSP_D0I3_NON_STREAMING; - else - return SKL_DSP_D0I3_NONE; -} - -static void bxt_set_dsp_D0i3(struct work_struct *work) -{ - int ret; - struct skl_ipc_d0ix_msg msg; - struct skl_dev *skl = container_of(work, - struct skl_dev, d0i3.work.work); - struct sst_dsp *ctx = skl->dsp; - struct skl_d0i3_data *d0i3 = &skl->d0i3; - int target_state; - - dev_dbg(ctx->dev, "In %s:\n", __func__); - - /* D0i3 entry allowed only if core 0 alone is running */ - if (skl_dsp_get_enabled_cores(ctx) != SKL_DSP_CORE0_MASK) { - dev_warn(ctx->dev, - "D0i3 allowed when only core0 running:Exit\n"); - return; - } - - target_state = bxt_d0i3_target_state(ctx); - if (target_state == SKL_DSP_D0I3_NONE) - return; - - msg.instance_id = 0; - msg.module_id = 0; - msg.wake = 1; - msg.streaming = 0; - if (target_state == SKL_DSP_D0I3_STREAMING) - msg.streaming = 1; - - ret = skl_ipc_set_d0ix(&skl->ipc, &msg); - - if (ret < 0) { - dev_err(ctx->dev, "Failed to set DSP to D0i3 state\n"); - return; - } - - /* Set Vendor specific register D0I3C.I3 to enable D0i3*/ - if (skl->update_d0i3c) - skl->update_d0i3c(skl->dev, true); - - d0i3->state = target_state; - skl->cores.state[SKL_DSP_CORE0_ID] = SKL_DSP_RUNNING_D0I3; -} - -static int bxt_schedule_dsp_D0i3(struct sst_dsp *ctx) -{ - struct skl_dev *skl = ctx->thread_context; - struct skl_d0i3_data *d0i3 = &skl->d0i3; - - /* Schedule D0i3 only if the usecase ref counts are appropriate */ - if (bxt_d0i3_target_state(ctx) != SKL_DSP_D0I3_NONE) { - - dev_dbg(ctx->dev, "%s: Schedule D0i3\n", __func__); - - schedule_delayed_work(&d0i3->work, - msecs_to_jiffies(BXT_D0I3_DELAY)); - } - - return 0; -} - -static int bxt_set_dsp_D0i0(struct sst_dsp *ctx) -{ - int ret; - struct skl_ipc_d0ix_msg msg; - struct skl_dev *skl = ctx->thread_context; - - dev_dbg(ctx->dev, "In %s:\n", __func__); - - /* First Cancel any pending attempt to put DSP to D0i3 */ - cancel_delayed_work_sync(&skl->d0i3.work); - - /* If DSP is currently in D0i3, bring it to D0i0 */ - if (skl->cores.state[SKL_DSP_CORE0_ID] != SKL_DSP_RUNNING_D0I3) - return 0; - - dev_dbg(ctx->dev, "Set DSP to D0i0\n"); - - msg.instance_id = 0; - msg.module_id = 0; - msg.streaming = 0; - msg.wake = 0; - - if (skl->d0i3.state == SKL_DSP_D0I3_STREAMING) - msg.streaming = 1; - - /* Clear Vendor specific register D0I3C.I3 to disable D0i3*/ - if (skl->update_d0i3c) - skl->update_d0i3c(skl->dev, false); - - ret = skl_ipc_set_d0ix(&skl->ipc, &msg); - if (ret < 0) { - dev_err(ctx->dev, "Failed to set DSP to D0i0\n"); - return ret; - } - - skl->cores.state[SKL_DSP_CORE0_ID] = SKL_DSP_RUNNING; - skl->d0i3.state = SKL_DSP_D0I3_NONE; - - return 0; -} - -static int bxt_set_dsp_D0(struct sst_dsp *ctx, unsigned int core_id) -{ - struct skl_dev *skl = ctx->thread_context; - int ret; - struct skl_ipc_dxstate_info dx; - unsigned int core_mask = SKL_DSP_CORE_MASK(core_id); - - if (skl->fw_loaded == false) { - skl->boot_complete = false; - ret = bxt_load_base_firmware(ctx); - if (ret < 0) { - dev_err(ctx->dev, "reload fw failed: %d\n", ret); - return ret; - } - - if (skl->lib_count > 1) { - ret = bxt_load_library(ctx, skl->lib_info, - skl->lib_count); - if (ret < 0) { - dev_err(ctx->dev, "reload libs failed: %d\n", ret); - return ret; - } - } - skl->cores.state[core_id] = SKL_DSP_RUNNING; - return ret; - } - - /* If core 0 is being turned on, turn on core 1 as well */ - if (core_id == SKL_DSP_CORE0_ID) - ret = skl_dsp_core_power_up(ctx, core_mask | - SKL_DSP_CORE_MASK(1)); - else - ret = skl_dsp_core_power_up(ctx, core_mask); - - if (ret < 0) - goto err; - - if (core_id == SKL_DSP_CORE0_ID) { - - /* - * Enable interrupt after SPA is set and before - * DSP is unstalled - */ - skl_ipc_int_enable(ctx); - skl_ipc_op_int_enable(ctx); - skl->boot_complete = false; - } - - ret = skl_dsp_start_core(ctx, core_mask); - if (ret < 0) - goto err; - - if (core_id == SKL_DSP_CORE0_ID) { - ret = wait_event_timeout(skl->boot_wait, - skl->boot_complete, - msecs_to_jiffies(SKL_IPC_BOOT_MSECS)); - - /* If core 1 was turned on for booting core 0, turn it off */ - skl_dsp_core_power_down(ctx, SKL_DSP_CORE_MASK(1)); - if (ret == 0) { - dev_err(ctx->dev, "%s: DSP boot timeout\n", __func__); - dev_err(ctx->dev, "Error code=0x%x: FW status=0x%x\n", - sst_dsp_shim_read(ctx, BXT_ADSP_ERROR_CODE), - sst_dsp_shim_read(ctx, BXT_ADSP_FW_STATUS)); - dev_err(ctx->dev, "Failed to set core0 to D0 state\n"); - ret = -EIO; - goto err; - } - } - - /* Tell FW if additional core in now On */ - - if (core_id != SKL_DSP_CORE0_ID) { - dx.core_mask = core_mask; - dx.dx_mask = core_mask; - - ret = skl_ipc_set_dx(&skl->ipc, BXT_INSTANCE_ID, - BXT_BASE_FW_MODULE_ID, &dx); - if (ret < 0) { - dev_err(ctx->dev, "IPC set_dx for core %d fail: %d\n", - core_id, ret); - goto err; - } - } - - skl->cores.state[core_id] = SKL_DSP_RUNNING; - return 0; -err: - if (core_id == SKL_DSP_CORE0_ID) - core_mask |= SKL_DSP_CORE_MASK(1); - skl_dsp_disable_core(ctx, core_mask); - - return ret; -} - -static int bxt_set_dsp_D3(struct sst_dsp *ctx, unsigned int core_id) -{ - int ret; - struct skl_ipc_dxstate_info dx; - struct skl_dev *skl = ctx->thread_context; - unsigned int core_mask = SKL_DSP_CORE_MASK(core_id); - - dx.core_mask = core_mask; - dx.dx_mask = SKL_IPC_D3_MASK; - - dev_dbg(ctx->dev, "core mask=%x dx_mask=%x\n", - dx.core_mask, dx.dx_mask); - - ret = skl_ipc_set_dx(&skl->ipc, BXT_INSTANCE_ID, - BXT_BASE_FW_MODULE_ID, &dx); - if (ret < 0) { - dev_err(ctx->dev, - "Failed to set DSP to D3:core id = %d;Continue reset\n", - core_id); - /* - * In case of D3 failure, re-download the firmware, so set - * fw_loaded to false. - */ - skl->fw_loaded = false; - } - - if (core_id == SKL_DSP_CORE0_ID) { - /* disable Interrupt */ - skl_ipc_op_int_disable(ctx); - skl_ipc_int_disable(ctx); - } - ret = skl_dsp_disable_core(ctx, core_mask); - if (ret < 0) { - dev_err(ctx->dev, "Failed to disable core %d\n", ret); - return ret; - } - skl->cores.state[core_id] = SKL_DSP_RESET; - return 0; -} - -static const struct skl_dsp_fw_ops bxt_fw_ops = { - .set_state_D0 = bxt_set_dsp_D0, - .set_state_D3 = bxt_set_dsp_D3, - .set_state_D0i3 = bxt_schedule_dsp_D0i3, - .set_state_D0i0 = bxt_set_dsp_D0i0, - .load_fw = bxt_load_base_firmware, - .get_fw_errcode = bxt_get_errorcode, - .load_library = bxt_load_library, -}; - -static struct sst_ops skl_ops = { - .irq_handler = skl_dsp_sst_interrupt, - .write = sst_shim32_write, - .read = sst_shim32_read, - .free = skl_dsp_free, -}; - -static struct sst_dsp_device skl_dev = { - .thread = skl_dsp_irq_thread_handler, - .ops = &skl_ops, -}; - -int bxt_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, - const char *fw_name, struct skl_dsp_loader_ops dsp_ops, - struct skl_dev **dsp) -{ - struct skl_dev *skl; - struct sst_dsp *sst; - int ret; - - ret = skl_sst_ctx_init(dev, irq, fw_name, dsp_ops, dsp, &skl_dev); - if (ret < 0) { - dev_err(dev, "%s: no device\n", __func__); - return ret; - } - - skl = *dsp; - sst = skl->dsp; - sst->fw_ops = bxt_fw_ops; - sst->addr.lpe = mmio_base; - sst->addr.shim = mmio_base; - sst->addr.sram0_base = BXT_ADSP_SRAM0_BASE; - sst->addr.sram1_base = BXT_ADSP_SRAM1_BASE; - sst->addr.w0_stat_sz = SKL_ADSP_W0_STAT_SZ; - sst->addr.w0_up_sz = SKL_ADSP_W0_UP_SZ; - - sst_dsp_mailbox_init(sst, (BXT_ADSP_SRAM0_BASE + SKL_ADSP_W0_STAT_SZ), - SKL_ADSP_W0_UP_SZ, BXT_ADSP_SRAM1_BASE, SKL_ADSP_W1_SZ); - - ret = skl_ipc_init(dev, skl); - if (ret) { - skl_dsp_free(sst); - return ret; - } - - /* set the D0i3 check */ - skl->ipc.ops.check_dsp_lp_on = skl_ipc_check_D0i0; - - skl->boot_complete = false; - init_waitqueue_head(&skl->boot_wait); - INIT_DELAYED_WORK(&skl->d0i3.work, bxt_set_dsp_D0i3); - skl->d0i3.state = SKL_DSP_D0I3_NONE; - - return skl_dsp_acquire_irq(sst); -} -EXPORT_SYMBOL_GPL(bxt_sst_dsp_init); - -int bxt_sst_init_fw(struct device *dev, struct skl_dev *skl) -{ - int ret; - struct sst_dsp *sst = skl->dsp; - - ret = sst->fw_ops.load_fw(sst); - if (ret < 0) { - dev_err(dev, "Load base fw failed: %x\n", ret); - return ret; - } - - skl_dsp_init_core_state(sst); - - if (skl->lib_count > 1) { - ret = sst->fw_ops.load_library(sst, skl->lib_info, - skl->lib_count); - if (ret < 0) { - dev_err(dev, "Load Library failed : %x\n", ret); - return ret; - } - } - skl->is_first_boot = false; - - return 0; -} -EXPORT_SYMBOL_GPL(bxt_sst_init_fw); - -void bxt_sst_dsp_cleanup(struct device *dev, struct skl_dev *skl) -{ - - skl_release_library(skl->lib_info, skl->lib_count); - if (skl->dsp->fw) - release_firmware(skl->dsp->fw); - skl_freeup_uuid_list(skl); - skl_ipc_free(&skl->ipc); - skl->dsp->ops->free(skl->dsp); -} -EXPORT_SYMBOL_GPL(bxt_sst_dsp_cleanup); - -MODULE_LICENSE("GPL v2"); -MODULE_DESCRIPTION("Intel Broxton IPC driver"); diff --git a/sound/soc/intel/skylake/cnl-sst-dsp.c b/sound/soc/intel/skylake/cnl-sst-dsp.c deleted file mode 100644 index 3ef1b194add1d2..00000000000000 --- a/sound/soc/intel/skylake/cnl-sst-dsp.c +++ /dev/null @@ -1,266 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * cnl-sst-dsp.c - CNL SST library generic function - * - * Copyright (C) 2016-17, Intel Corporation. - * Author: Guneshwor Singh - * - * Modified from: - * SKL SST library generic function - * Copyright (C) 2014-15, Intel Corporation. - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ -#include -#include "../common/sst-dsp.h" -#include "../common/sst-ipc.h" -#include "../common/sst-dsp-priv.h" -#include "cnl-sst-dsp.h" - -/* various timeout values */ -#define CNL_DSP_PU_TO 50 -#define CNL_DSP_PD_TO 50 -#define CNL_DSP_RESET_TO 50 - -static int -cnl_dsp_core_set_reset_state(struct sst_dsp *ctx, unsigned int core_mask) -{ - /* update bits */ - sst_dsp_shim_update_bits_unlocked(ctx, - CNL_ADSP_REG_ADSPCS, CNL_ADSPCS_CRST(core_mask), - CNL_ADSPCS_CRST(core_mask)); - - /* poll with timeout to check if operation successful */ - return sst_dsp_register_poll(ctx, - CNL_ADSP_REG_ADSPCS, - CNL_ADSPCS_CRST(core_mask), - CNL_ADSPCS_CRST(core_mask), - CNL_DSP_RESET_TO, - "Set reset"); -} - -static int -cnl_dsp_core_unset_reset_state(struct sst_dsp *ctx, unsigned int core_mask) -{ - /* update bits */ - sst_dsp_shim_update_bits_unlocked(ctx, CNL_ADSP_REG_ADSPCS, - CNL_ADSPCS_CRST(core_mask), 0); - - /* poll with timeout to check if operation successful */ - return sst_dsp_register_poll(ctx, - CNL_ADSP_REG_ADSPCS, - CNL_ADSPCS_CRST(core_mask), - 0, - CNL_DSP_RESET_TO, - "Unset reset"); -} - -static bool is_cnl_dsp_core_enable(struct sst_dsp *ctx, unsigned int core_mask) -{ - int val; - bool is_enable; - - val = sst_dsp_shim_read_unlocked(ctx, CNL_ADSP_REG_ADSPCS); - - is_enable = (val & CNL_ADSPCS_CPA(core_mask)) && - (val & CNL_ADSPCS_SPA(core_mask)) && - !(val & CNL_ADSPCS_CRST(core_mask)) && - !(val & CNL_ADSPCS_CSTALL(core_mask)); - - dev_dbg(ctx->dev, "DSP core(s) enabled? %d: core_mask %#x\n", - is_enable, core_mask); - - return is_enable; -} - -static int cnl_dsp_reset_core(struct sst_dsp *ctx, unsigned int core_mask) -{ - /* stall core */ - sst_dsp_shim_update_bits_unlocked(ctx, CNL_ADSP_REG_ADSPCS, - CNL_ADSPCS_CSTALL(core_mask), - CNL_ADSPCS_CSTALL(core_mask)); - - /* set reset state */ - return cnl_dsp_core_set_reset_state(ctx, core_mask); -} - -static int cnl_dsp_start_core(struct sst_dsp *ctx, unsigned int core_mask) -{ - int ret; - - /* unset reset state */ - ret = cnl_dsp_core_unset_reset_state(ctx, core_mask); - if (ret < 0) - return ret; - - /* run core */ - sst_dsp_shim_update_bits_unlocked(ctx, CNL_ADSP_REG_ADSPCS, - CNL_ADSPCS_CSTALL(core_mask), 0); - - if (!is_cnl_dsp_core_enable(ctx, core_mask)) { - cnl_dsp_reset_core(ctx, core_mask); - dev_err(ctx->dev, "DSP core mask %#x enable failed\n", - core_mask); - ret = -EIO; - } - - return ret; -} - -static int cnl_dsp_core_power_up(struct sst_dsp *ctx, unsigned int core_mask) -{ - /* update bits */ - sst_dsp_shim_update_bits_unlocked(ctx, CNL_ADSP_REG_ADSPCS, - CNL_ADSPCS_SPA(core_mask), - CNL_ADSPCS_SPA(core_mask)); - - /* poll with timeout to check if operation successful */ - return sst_dsp_register_poll(ctx, CNL_ADSP_REG_ADSPCS, - CNL_ADSPCS_CPA(core_mask), - CNL_ADSPCS_CPA(core_mask), - CNL_DSP_PU_TO, - "Power up"); -} - -static int cnl_dsp_core_power_down(struct sst_dsp *ctx, unsigned int core_mask) -{ - /* update bits */ - sst_dsp_shim_update_bits_unlocked(ctx, CNL_ADSP_REG_ADSPCS, - CNL_ADSPCS_SPA(core_mask), 0); - - /* poll with timeout to check if operation successful */ - return sst_dsp_register_poll(ctx, - CNL_ADSP_REG_ADSPCS, - CNL_ADSPCS_CPA(core_mask), - 0, - CNL_DSP_PD_TO, - "Power down"); -} - -int cnl_dsp_enable_core(struct sst_dsp *ctx, unsigned int core_mask) -{ - int ret; - - /* power up */ - ret = cnl_dsp_core_power_up(ctx, core_mask); - if (ret < 0) { - dev_dbg(ctx->dev, "DSP core mask %#x power up failed", - core_mask); - return ret; - } - - return cnl_dsp_start_core(ctx, core_mask); -} - -int cnl_dsp_disable_core(struct sst_dsp *ctx, unsigned int core_mask) -{ - int ret; - - ret = cnl_dsp_reset_core(ctx, core_mask); - if (ret < 0) { - dev_err(ctx->dev, "DSP core mask %#x reset failed\n", - core_mask); - return ret; - } - - /* power down core*/ - ret = cnl_dsp_core_power_down(ctx, core_mask); - if (ret < 0) { - dev_err(ctx->dev, "DSP core mask %#x power down failed\n", - core_mask); - return ret; - } - - if (is_cnl_dsp_core_enable(ctx, core_mask)) { - dev_err(ctx->dev, "DSP core mask %#x disable failed\n", - core_mask); - ret = -EIO; - } - - return ret; -} - -irqreturn_t cnl_dsp_sst_interrupt(int irq, void *dev_id) -{ - struct sst_dsp *ctx = dev_id; - u32 val; - irqreturn_t ret = IRQ_NONE; - - spin_lock(&ctx->spinlock); - - val = sst_dsp_shim_read_unlocked(ctx, CNL_ADSP_REG_ADSPIS); - ctx->intr_status = val; - - if (val == 0xffffffff) { - spin_unlock(&ctx->spinlock); - return IRQ_NONE; - } - - if (val & CNL_ADSPIS_IPC) { - cnl_ipc_int_disable(ctx); - ret = IRQ_WAKE_THREAD; - } - - spin_unlock(&ctx->spinlock); - - return ret; -} - -void cnl_dsp_free(struct sst_dsp *dsp) -{ - cnl_ipc_int_disable(dsp); - - free_irq(dsp->irq, dsp); - cnl_ipc_op_int_disable(dsp); - cnl_dsp_disable_core(dsp, SKL_DSP_CORE0_MASK); -} -EXPORT_SYMBOL_GPL(cnl_dsp_free); - -void cnl_ipc_int_enable(struct sst_dsp *ctx) -{ - sst_dsp_shim_update_bits(ctx, CNL_ADSP_REG_ADSPIC, - CNL_ADSPIC_IPC, CNL_ADSPIC_IPC); -} - -void cnl_ipc_int_disable(struct sst_dsp *ctx) -{ - sst_dsp_shim_update_bits_unlocked(ctx, CNL_ADSP_REG_ADSPIC, - CNL_ADSPIC_IPC, 0); -} - -void cnl_ipc_op_int_enable(struct sst_dsp *ctx) -{ - /* enable IPC DONE interrupt */ - sst_dsp_shim_update_bits(ctx, CNL_ADSP_REG_HIPCCTL, - CNL_ADSP_REG_HIPCCTL_DONE, - CNL_ADSP_REG_HIPCCTL_DONE); - - /* enable IPC BUSY interrupt */ - sst_dsp_shim_update_bits(ctx, CNL_ADSP_REG_HIPCCTL, - CNL_ADSP_REG_HIPCCTL_BUSY, - CNL_ADSP_REG_HIPCCTL_BUSY); -} - -void cnl_ipc_op_int_disable(struct sst_dsp *ctx) -{ - /* disable IPC DONE interrupt */ - sst_dsp_shim_update_bits(ctx, CNL_ADSP_REG_HIPCCTL, - CNL_ADSP_REG_HIPCCTL_DONE, 0); - - /* disable IPC BUSY interrupt */ - sst_dsp_shim_update_bits(ctx, CNL_ADSP_REG_HIPCCTL, - CNL_ADSP_REG_HIPCCTL_BUSY, 0); -} - -bool cnl_ipc_int_status(struct sst_dsp *ctx) -{ - return sst_dsp_shim_read_unlocked(ctx, CNL_ADSP_REG_ADSPIS) & - CNL_ADSPIS_IPC; -} - -void cnl_ipc_free(struct sst_generic_ipc *ipc) -{ - cnl_ipc_op_int_disable(ipc->dsp); - sst_ipc_fini(ipc); -} diff --git a/sound/soc/intel/skylake/cnl-sst-dsp.h b/sound/soc/intel/skylake/cnl-sst-dsp.h deleted file mode 100644 index d3cf4bd1a070b2..00000000000000 --- a/sound/soc/intel/skylake/cnl-sst-dsp.h +++ /dev/null @@ -1,103 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Cannonlake SST DSP Support - * - * Copyright (C) 2016-17, Intel Corporation. - */ - -#ifndef __CNL_SST_DSP_H__ -#define __CNL_SST_DSP_H__ - -struct sst_dsp; -struct sst_dsp_device; -struct sst_generic_ipc; - -/* Intel HD Audio General DSP Registers */ -#define CNL_ADSP_GEN_BASE 0x0 -#define CNL_ADSP_REG_ADSPCS (CNL_ADSP_GEN_BASE + 0x04) -#define CNL_ADSP_REG_ADSPIC (CNL_ADSP_GEN_BASE + 0x08) -#define CNL_ADSP_REG_ADSPIS (CNL_ADSP_GEN_BASE + 0x0c) - -/* Intel HD Audio Inter-Processor Communication Registers */ -#define CNL_ADSP_IPC_BASE 0xc0 -#define CNL_ADSP_REG_HIPCTDR (CNL_ADSP_IPC_BASE + 0x00) -#define CNL_ADSP_REG_HIPCTDA (CNL_ADSP_IPC_BASE + 0x04) -#define CNL_ADSP_REG_HIPCTDD (CNL_ADSP_IPC_BASE + 0x08) -#define CNL_ADSP_REG_HIPCIDR (CNL_ADSP_IPC_BASE + 0x10) -#define CNL_ADSP_REG_HIPCIDA (CNL_ADSP_IPC_BASE + 0x14) -#define CNL_ADSP_REG_HIPCIDD (CNL_ADSP_IPC_BASE + 0x18) -#define CNL_ADSP_REG_HIPCCTL (CNL_ADSP_IPC_BASE + 0x28) - -/* HIPCTDR */ -#define CNL_ADSP_REG_HIPCTDR_BUSY BIT(31) - -/* HIPCTDA */ -#define CNL_ADSP_REG_HIPCTDA_DONE BIT(31) - -/* HIPCIDR */ -#define CNL_ADSP_REG_HIPCIDR_BUSY BIT(31) - -/* HIPCIDA */ -#define CNL_ADSP_REG_HIPCIDA_DONE BIT(31) - -/* CNL HIPCCTL */ -#define CNL_ADSP_REG_HIPCCTL_DONE BIT(1) -#define CNL_ADSP_REG_HIPCCTL_BUSY BIT(0) - -/* CNL HIPCT */ -#define CNL_ADSP_REG_HIPCT_BUSY BIT(31) - -/* Intel HD Audio SRAM Window 1 */ -#define CNL_ADSP_SRAM1_BASE 0xa0000 - -#define CNL_ADSP_MMIO_LEN 0x10000 - -#define CNL_ADSP_W0_STAT_SZ 0x1000 - -#define CNL_ADSP_W0_UP_SZ 0x1000 - -#define CNL_ADSP_W1_SZ 0x1000 - -#define CNL_FW_STS_MASK 0xf - -#define CNL_ADSPIC_IPC 0x1 -#define CNL_ADSPIS_IPC 0x1 - -#define CNL_DSP_CORES 4 -#define CNL_DSP_CORES_MASK ((1 << CNL_DSP_CORES) - 1) - -/* core reset - asserted high */ -#define CNL_ADSPCS_CRST_SHIFT 0 -#define CNL_ADSPCS_CRST(x) (x << CNL_ADSPCS_CRST_SHIFT) - -/* core run/stall - when set to 1 core is stalled */ -#define CNL_ADSPCS_CSTALL_SHIFT 8 -#define CNL_ADSPCS_CSTALL(x) (x << CNL_ADSPCS_CSTALL_SHIFT) - -/* set power active - when set to 1 turn core on */ -#define CNL_ADSPCS_SPA_SHIFT 16 -#define CNL_ADSPCS_SPA(x) (x << CNL_ADSPCS_SPA_SHIFT) - -/* current power active - power status of cores, set by hardware */ -#define CNL_ADSPCS_CPA_SHIFT 24 -#define CNL_ADSPCS_CPA(x) (x << CNL_ADSPCS_CPA_SHIFT) - -int cnl_dsp_enable_core(struct sst_dsp *ctx, unsigned int core_mask); -int cnl_dsp_disable_core(struct sst_dsp *ctx, unsigned int core_mask); -irqreturn_t cnl_dsp_sst_interrupt(int irq, void *dev_id); -void cnl_dsp_free(struct sst_dsp *dsp); - -void cnl_ipc_int_enable(struct sst_dsp *ctx); -void cnl_ipc_int_disable(struct sst_dsp *ctx); -void cnl_ipc_op_int_enable(struct sst_dsp *ctx); -void cnl_ipc_op_int_disable(struct sst_dsp *ctx); -bool cnl_ipc_int_status(struct sst_dsp *ctx); -void cnl_ipc_free(struct sst_generic_ipc *ipc); - -int cnl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, - const char *fw_name, struct skl_dsp_loader_ops dsp_ops, - struct skl_dev **dsp); -int cnl_sst_init_fw(struct device *dev, struct skl_dev *skl); -void cnl_sst_dsp_cleanup(struct device *dev, struct skl_dev *skl); - -#endif /*__CNL_SST_DSP_H__*/ diff --git a/sound/soc/intel/skylake/cnl-sst.c b/sound/soc/intel/skylake/cnl-sst.c deleted file mode 100644 index 1275c149acc021..00000000000000 --- a/sound/soc/intel/skylake/cnl-sst.c +++ /dev/null @@ -1,508 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * cnl-sst.c - DSP library functions for CNL platform - * - * Copyright (C) 2016-17, Intel Corporation. - * - * Author: Guneshwor Singh - * - * Modified from: - * HDA DSP library functions for SKL platform - * Copyright (C) 2014-15, Intel Corporation. - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ - -#include -#include -#include -#include - -#include "../common/sst-dsp.h" -#include "../common/sst-dsp-priv.h" -#include "../common/sst-ipc.h" -#include "cnl-sst-dsp.h" -#include "skl.h" - -#define CNL_FW_ROM_INIT 0x1 -#define CNL_FW_INIT 0x5 -#define CNL_IPC_PURGE 0x01004000 -#define CNL_INIT_TIMEOUT 300 -#define CNL_BASEFW_TIMEOUT 3000 - -#define CNL_ADSP_SRAM0_BASE 0x80000 - -/* Firmware status window */ -#define CNL_ADSP_FW_STATUS CNL_ADSP_SRAM0_BASE -#define CNL_ADSP_ERROR_CODE (CNL_ADSP_FW_STATUS + 0x4) - -#define CNL_INSTANCE_ID 0 -#define CNL_BASE_FW_MODULE_ID 0 -#define CNL_ADSP_FW_HDR_OFFSET 0x2000 -#define CNL_ROM_CTRL_DMA_ID 0x9 - -static int cnl_prepare_fw(struct sst_dsp *ctx, const void *fwdata, u32 fwsize) -{ - - int ret, stream_tag; - - stream_tag = ctx->dsp_ops.prepare(ctx->dev, 0x40, fwsize, &ctx->dmab); - if (stream_tag <= 0) { - dev_err(ctx->dev, "dma prepare failed: 0%#x\n", stream_tag); - return stream_tag; - } - - ctx->dsp_ops.stream_tag = stream_tag; - memcpy(ctx->dmab.area, fwdata, fwsize); - - ret = skl_dsp_core_power_up(ctx, SKL_DSP_CORE0_MASK); - if (ret < 0) { - dev_err(ctx->dev, "dsp core0 power up failed\n"); - ret = -EIO; - goto base_fw_load_failed; - } - - /* purge FW request */ - sst_dsp_shim_write(ctx, CNL_ADSP_REG_HIPCIDR, - CNL_ADSP_REG_HIPCIDR_BUSY | (CNL_IPC_PURGE | - ((stream_tag - 1) << CNL_ROM_CTRL_DMA_ID))); - - ret = skl_dsp_start_core(ctx, SKL_DSP_CORE0_MASK); - if (ret < 0) { - dev_err(ctx->dev, "Start dsp core failed ret: %d\n", ret); - ret = -EIO; - goto base_fw_load_failed; - } - - ret = sst_dsp_register_poll(ctx, CNL_ADSP_REG_HIPCIDA, - CNL_ADSP_REG_HIPCIDA_DONE, - CNL_ADSP_REG_HIPCIDA_DONE, - BXT_INIT_TIMEOUT, "HIPCIDA Done"); - if (ret < 0) { - dev_err(ctx->dev, "timeout for purge request: %d\n", ret); - goto base_fw_load_failed; - } - - /* enable interrupt */ - cnl_ipc_int_enable(ctx); - cnl_ipc_op_int_enable(ctx); - - ret = sst_dsp_register_poll(ctx, CNL_ADSP_FW_STATUS, CNL_FW_STS_MASK, - CNL_FW_ROM_INIT, CNL_INIT_TIMEOUT, - "rom load"); - if (ret < 0) { - dev_err(ctx->dev, "rom init timeout, ret: %d\n", ret); - goto base_fw_load_failed; - } - - return 0; - -base_fw_load_failed: - ctx->dsp_ops.cleanup(ctx->dev, &ctx->dmab, stream_tag); - cnl_dsp_disable_core(ctx, SKL_DSP_CORE0_MASK); - - return ret; -} - -static int sst_transfer_fw_host_dma(struct sst_dsp *ctx) -{ - int ret; - - ctx->dsp_ops.trigger(ctx->dev, true, ctx->dsp_ops.stream_tag); - ret = sst_dsp_register_poll(ctx, CNL_ADSP_FW_STATUS, CNL_FW_STS_MASK, - CNL_FW_INIT, CNL_BASEFW_TIMEOUT, - "firmware boot"); - - ctx->dsp_ops.trigger(ctx->dev, false, ctx->dsp_ops.stream_tag); - ctx->dsp_ops.cleanup(ctx->dev, &ctx->dmab, ctx->dsp_ops.stream_tag); - - return ret; -} - -static int cnl_load_base_firmware(struct sst_dsp *ctx) -{ - struct firmware stripped_fw; - struct skl_dev *cnl = ctx->thread_context; - int ret, i; - - if (!ctx->fw) { - ret = request_firmware(&ctx->fw, ctx->fw_name, ctx->dev); - if (ret < 0) { - dev_err(ctx->dev, "request firmware failed: %d\n", ret); - goto cnl_load_base_firmware_failed; - } - } - - /* parse uuids if first boot */ - if (cnl->is_first_boot) { - ret = snd_skl_parse_uuids(ctx, ctx->fw, - CNL_ADSP_FW_HDR_OFFSET, 0); - if (ret < 0) - goto cnl_load_base_firmware_failed; - } - - stripped_fw.data = ctx->fw->data; - stripped_fw.size = ctx->fw->size; - skl_dsp_strip_extended_manifest(&stripped_fw); - - for (i = 0; i < BXT_FW_ROM_INIT_RETRY; i++) { - ret = cnl_prepare_fw(ctx, stripped_fw.data, stripped_fw.size); - if (!ret) - break; - dev_dbg(ctx->dev, "prepare firmware failed: %d\n", ret); - } - - if (ret < 0) - goto cnl_load_base_firmware_failed; - - ret = sst_transfer_fw_host_dma(ctx); - if (ret < 0) { - dev_err(ctx->dev, "transfer firmware failed: %d\n", ret); - cnl_dsp_disable_core(ctx, SKL_DSP_CORE0_MASK); - goto cnl_load_base_firmware_failed; - } - - ret = wait_event_timeout(cnl->boot_wait, cnl->boot_complete, - msecs_to_jiffies(SKL_IPC_BOOT_MSECS)); - if (ret == 0) { - dev_err(ctx->dev, "FW ready timed-out\n"); - cnl_dsp_disable_core(ctx, SKL_DSP_CORE0_MASK); - ret = -EIO; - goto cnl_load_base_firmware_failed; - } - - cnl->fw_loaded = true; - - return 0; - -cnl_load_base_firmware_failed: - dev_err(ctx->dev, "firmware load failed: %d\n", ret); - release_firmware(ctx->fw); - ctx->fw = NULL; - - return ret; -} - -static int cnl_set_dsp_D0(struct sst_dsp *ctx, unsigned int core_id) -{ - struct skl_dev *cnl = ctx->thread_context; - unsigned int core_mask = SKL_DSP_CORE_MASK(core_id); - struct skl_ipc_dxstate_info dx; - int ret; - - if (!cnl->fw_loaded) { - cnl->boot_complete = false; - ret = cnl_load_base_firmware(ctx); - if (ret < 0) { - dev_err(ctx->dev, "fw reload failed: %d\n", ret); - return ret; - } - - cnl->cores.state[core_id] = SKL_DSP_RUNNING; - return ret; - } - - ret = cnl_dsp_enable_core(ctx, core_mask); - if (ret < 0) { - dev_err(ctx->dev, "enable dsp core %d failed: %d\n", - core_id, ret); - goto err; - } - - if (core_id == SKL_DSP_CORE0_ID) { - /* enable interrupt */ - cnl_ipc_int_enable(ctx); - cnl_ipc_op_int_enable(ctx); - cnl->boot_complete = false; - - ret = wait_event_timeout(cnl->boot_wait, cnl->boot_complete, - msecs_to_jiffies(SKL_IPC_BOOT_MSECS)); - if (ret == 0) { - dev_err(ctx->dev, - "dsp boot timeout, status=%#x error=%#x\n", - sst_dsp_shim_read(ctx, CNL_ADSP_FW_STATUS), - sst_dsp_shim_read(ctx, CNL_ADSP_ERROR_CODE)); - ret = -ETIMEDOUT; - goto err; - } - } else { - dx.core_mask = core_mask; - dx.dx_mask = core_mask; - - ret = skl_ipc_set_dx(&cnl->ipc, CNL_INSTANCE_ID, - CNL_BASE_FW_MODULE_ID, &dx); - if (ret < 0) { - dev_err(ctx->dev, "set_dx failed, core: %d ret: %d\n", - core_id, ret); - goto err; - } - } - cnl->cores.state[core_id] = SKL_DSP_RUNNING; - - return 0; -err: - cnl_dsp_disable_core(ctx, core_mask); - - return ret; -} - -static int cnl_set_dsp_D3(struct sst_dsp *ctx, unsigned int core_id) -{ - struct skl_dev *cnl = ctx->thread_context; - unsigned int core_mask = SKL_DSP_CORE_MASK(core_id); - struct skl_ipc_dxstate_info dx; - int ret; - - dx.core_mask = core_mask; - dx.dx_mask = SKL_IPC_D3_MASK; - - ret = skl_ipc_set_dx(&cnl->ipc, CNL_INSTANCE_ID, - CNL_BASE_FW_MODULE_ID, &dx); - if (ret < 0) { - dev_err(ctx->dev, - "dsp core %d to d3 failed; continue reset\n", - core_id); - cnl->fw_loaded = false; - } - - /* disable interrupts if core 0 */ - if (core_id == SKL_DSP_CORE0_ID) { - skl_ipc_op_int_disable(ctx); - skl_ipc_int_disable(ctx); - } - - ret = cnl_dsp_disable_core(ctx, core_mask); - if (ret < 0) { - dev_err(ctx->dev, "disable dsp core %d failed: %d\n", - core_id, ret); - return ret; - } - - cnl->cores.state[core_id] = SKL_DSP_RESET; - - return ret; -} - -static unsigned int cnl_get_errno(struct sst_dsp *ctx) -{ - return sst_dsp_shim_read(ctx, CNL_ADSP_ERROR_CODE); -} - -static const struct skl_dsp_fw_ops cnl_fw_ops = { - .set_state_D0 = cnl_set_dsp_D0, - .set_state_D3 = cnl_set_dsp_D3, - .load_fw = cnl_load_base_firmware, - .get_fw_errcode = cnl_get_errno, -}; - -static struct sst_ops cnl_ops = { - .irq_handler = cnl_dsp_sst_interrupt, - .write = sst_shim32_write, - .read = sst_shim32_read, - .free = cnl_dsp_free, -}; - -#define CNL_IPC_GLB_NOTIFY_RSP_SHIFT 29 -#define CNL_IPC_GLB_NOTIFY_RSP_MASK 0x1 -#define CNL_IPC_GLB_NOTIFY_RSP_TYPE(x) (((x) >> CNL_IPC_GLB_NOTIFY_RSP_SHIFT) \ - & CNL_IPC_GLB_NOTIFY_RSP_MASK) - -static irqreturn_t cnl_dsp_irq_thread_handler(int irq, void *context) -{ - struct sst_dsp *dsp = context; - struct skl_dev *cnl = dsp->thread_context; - struct sst_generic_ipc *ipc = &cnl->ipc; - struct skl_ipc_header header = {0}; - u32 hipcida, hipctdr, hipctdd; - int ipc_irq = 0; - - /* here we handle ipc interrupts only */ - if (!(dsp->intr_status & CNL_ADSPIS_IPC)) - return IRQ_NONE; - - hipcida = sst_dsp_shim_read_unlocked(dsp, CNL_ADSP_REG_HIPCIDA); - hipctdr = sst_dsp_shim_read_unlocked(dsp, CNL_ADSP_REG_HIPCTDR); - hipctdd = sst_dsp_shim_read_unlocked(dsp, CNL_ADSP_REG_HIPCTDD); - - /* reply message from dsp */ - if (hipcida & CNL_ADSP_REG_HIPCIDA_DONE) { - sst_dsp_shim_update_bits(dsp, CNL_ADSP_REG_HIPCCTL, - CNL_ADSP_REG_HIPCCTL_DONE, 0); - - /* clear done bit - tell dsp operation is complete */ - sst_dsp_shim_update_bits_forced(dsp, CNL_ADSP_REG_HIPCIDA, - CNL_ADSP_REG_HIPCIDA_DONE, CNL_ADSP_REG_HIPCIDA_DONE); - - ipc_irq = 1; - - /* unmask done interrupt */ - sst_dsp_shim_update_bits(dsp, CNL_ADSP_REG_HIPCCTL, - CNL_ADSP_REG_HIPCCTL_DONE, CNL_ADSP_REG_HIPCCTL_DONE); - } - - /* new message from dsp */ - if (hipctdr & CNL_ADSP_REG_HIPCTDR_BUSY) { - header.primary = hipctdr; - header.extension = hipctdd; - dev_dbg(dsp->dev, "IPC irq: Firmware respond primary:%x", - header.primary); - dev_dbg(dsp->dev, "IPC irq: Firmware respond extension:%x", - header.extension); - - if (CNL_IPC_GLB_NOTIFY_RSP_TYPE(header.primary)) { - /* Handle Immediate reply from DSP Core */ - skl_ipc_process_reply(ipc, header); - } else { - dev_dbg(dsp->dev, "IPC irq: Notification from firmware\n"); - skl_ipc_process_notification(ipc, header); - } - /* clear busy interrupt */ - sst_dsp_shim_update_bits_forced(dsp, CNL_ADSP_REG_HIPCTDR, - CNL_ADSP_REG_HIPCTDR_BUSY, CNL_ADSP_REG_HIPCTDR_BUSY); - - /* set done bit to ack dsp */ - sst_dsp_shim_update_bits_forced(dsp, CNL_ADSP_REG_HIPCTDA, - CNL_ADSP_REG_HIPCTDA_DONE, CNL_ADSP_REG_HIPCTDA_DONE); - ipc_irq = 1; - } - - if (ipc_irq == 0) - return IRQ_NONE; - - cnl_ipc_int_enable(dsp); - - /* continue to send any remaining messages */ - schedule_work(&ipc->kwork); - - return IRQ_HANDLED; -} - -static struct sst_dsp_device cnl_dev = { - .thread = cnl_dsp_irq_thread_handler, - .ops = &cnl_ops, -}; - -static void cnl_ipc_tx_msg(struct sst_generic_ipc *ipc, struct ipc_message *msg) -{ - struct skl_ipc_header *header = (struct skl_ipc_header *)(&msg->tx.header); - - if (msg->tx.size) - sst_dsp_outbox_write(ipc->dsp, msg->tx.data, msg->tx.size); - sst_dsp_shim_write_unlocked(ipc->dsp, CNL_ADSP_REG_HIPCIDD, - header->extension); - sst_dsp_shim_write_unlocked(ipc->dsp, CNL_ADSP_REG_HIPCIDR, - header->primary | CNL_ADSP_REG_HIPCIDR_BUSY); -} - -static bool cnl_ipc_is_dsp_busy(struct sst_dsp *dsp) -{ - u32 hipcidr; - - hipcidr = sst_dsp_shim_read_unlocked(dsp, CNL_ADSP_REG_HIPCIDR); - - return (hipcidr & CNL_ADSP_REG_HIPCIDR_BUSY); -} - -static int cnl_ipc_init(struct device *dev, struct skl_dev *cnl) -{ - struct sst_generic_ipc *ipc; - int err; - - ipc = &cnl->ipc; - ipc->dsp = cnl->dsp; - ipc->dev = dev; - - ipc->tx_data_max_size = CNL_ADSP_W1_SZ; - ipc->rx_data_max_size = CNL_ADSP_W0_UP_SZ; - - err = sst_ipc_init(ipc); - if (err) - return err; - - /* - * overriding tx_msg and is_dsp_busy since - * ipc registers are different for cnl - */ - ipc->ops.tx_msg = cnl_ipc_tx_msg; - ipc->ops.tx_data_copy = skl_ipc_tx_data_copy; - ipc->ops.is_dsp_busy = cnl_ipc_is_dsp_busy; - - return 0; -} - -int cnl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, - const char *fw_name, struct skl_dsp_loader_ops dsp_ops, - struct skl_dev **dsp) -{ - struct skl_dev *cnl; - struct sst_dsp *sst; - int ret; - - ret = skl_sst_ctx_init(dev, irq, fw_name, dsp_ops, dsp, &cnl_dev); - if (ret < 0) { - dev_err(dev, "%s: no device\n", __func__); - return ret; - } - - cnl = *dsp; - sst = cnl->dsp; - sst->fw_ops = cnl_fw_ops; - sst->addr.lpe = mmio_base; - sst->addr.shim = mmio_base; - sst->addr.sram0_base = CNL_ADSP_SRAM0_BASE; - sst->addr.sram1_base = CNL_ADSP_SRAM1_BASE; - sst->addr.w0_stat_sz = CNL_ADSP_W0_STAT_SZ; - sst->addr.w0_up_sz = CNL_ADSP_W0_UP_SZ; - - sst_dsp_mailbox_init(sst, (CNL_ADSP_SRAM0_BASE + CNL_ADSP_W0_STAT_SZ), - CNL_ADSP_W0_UP_SZ, CNL_ADSP_SRAM1_BASE, - CNL_ADSP_W1_SZ); - - ret = cnl_ipc_init(dev, cnl); - if (ret) { - skl_dsp_free(sst); - return ret; - } - - cnl->boot_complete = false; - init_waitqueue_head(&cnl->boot_wait); - - return skl_dsp_acquire_irq(sst); -} -EXPORT_SYMBOL_GPL(cnl_sst_dsp_init); - -int cnl_sst_init_fw(struct device *dev, struct skl_dev *skl) -{ - int ret; - struct sst_dsp *sst = skl->dsp; - - ret = skl->dsp->fw_ops.load_fw(sst); - if (ret < 0) { - dev_err(dev, "load base fw failed: %d", ret); - return ret; - } - - skl_dsp_init_core_state(sst); - - skl->is_first_boot = false; - - return 0; -} -EXPORT_SYMBOL_GPL(cnl_sst_init_fw); - -void cnl_sst_dsp_cleanup(struct device *dev, struct skl_dev *skl) -{ - if (skl->dsp->fw) - release_firmware(skl->dsp->fw); - - skl_freeup_uuid_list(skl); - cnl_ipc_free(&skl->ipc); - - skl->dsp->ops->free(skl->dsp); -} -EXPORT_SYMBOL_GPL(cnl_sst_dsp_cleanup); - -MODULE_LICENSE("GPL v2"); -MODULE_DESCRIPTION("Intel Cannonlake IPC driver"); diff --git a/sound/soc/intel/skylake/skl-debug.c b/sound/soc/intel/skylake/skl-debug.c deleted file mode 100644 index a15aa2ffa68108..00000000000000 --- a/sound/soc/intel/skylake/skl-debug.c +++ /dev/null @@ -1,248 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * skl-debug.c - Debugfs for skl driver - * - * Copyright (C) 2016-17 Intel Corp - */ - -#include -#include -#include -#include "skl.h" -#include "skl-sst-dsp.h" -#include "skl-sst-ipc.h" -#include "skl-topology.h" -#include "../common/sst-dsp.h" -#include "../common/sst-dsp-priv.h" - -#define MOD_BUF PAGE_SIZE -#define FW_REG_BUF PAGE_SIZE -#define FW_REG_SIZE 0x60 - -struct skl_debug { - struct skl_dev *skl; - struct device *dev; - - struct dentry *fs; - struct dentry *modules; - u8 fw_read_buff[FW_REG_BUF]; -}; - -static ssize_t skl_print_pins(struct skl_module_pin *m_pin, char *buf, - int max_pin, ssize_t size, bool direction) -{ - int i; - ssize_t ret = 0; - - for (i = 0; i < max_pin; i++) { - ret += scnprintf(buf + size, MOD_BUF - size, - "%s %d\n\tModule %d\n\tInstance %d\n\t" - "In-used %s\n\tType %s\n" - "\tState %d\n\tIndex %d\n", - direction ? "Input Pin:" : "Output Pin:", - i, m_pin[i].id.module_id, - m_pin[i].id.instance_id, - m_pin[i].in_use ? "Used" : "Unused", - m_pin[i].is_dynamic ? "Dynamic" : "Static", - m_pin[i].pin_state, i); - size += ret; - } - return ret; -} - -static ssize_t skl_print_fmt(struct skl_module_fmt *fmt, char *buf, - ssize_t size, bool direction) -{ - return scnprintf(buf + size, MOD_BUF - size, - "%s\n\tCh %d\n\tFreq %d\n\tBit depth %d\n\t" - "Valid bit depth %d\n\tCh config %#x\n\tInterleaving %d\n\t" - "Sample Type %d\n\tCh Map %#x\n", - direction ? "Input Format:" : "Output Format:", - fmt->channels, fmt->s_freq, fmt->bit_depth, - fmt->valid_bit_depth, fmt->ch_cfg, - fmt->interleaving_style, fmt->sample_type, - fmt->ch_map); -} - -static ssize_t module_read(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct skl_module_cfg *mconfig = file->private_data; - struct skl_module *module = mconfig->module; - struct skl_module_res *res = &module->resources[mconfig->res_idx]; - char *buf; - ssize_t ret; - - buf = kzalloc(MOD_BUF, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - ret = scnprintf(buf, MOD_BUF, "Module:\n\tUUID %pUL\n\tModule id %d\n" - "\tInstance id %d\n\tPvt_id %d\n", mconfig->guid, - mconfig->id.module_id, mconfig->id.instance_id, - mconfig->id.pvt_id); - - ret += scnprintf(buf + ret, MOD_BUF - ret, - "Resources:\n\tCPC %#x\n\tIBS %#x\n\tOBS %#x\t\n", - res->cpc, res->ibs, res->obs); - - ret += scnprintf(buf + ret, MOD_BUF - ret, - "Module data:\n\tCore %d\n\tIn queue %d\n\t" - "Out queue %d\n\tType %s\n", - mconfig->core_id, mconfig->max_in_queue, - mconfig->max_out_queue, - mconfig->is_loadable ? "loadable" : "inbuilt"); - - ret += skl_print_fmt(mconfig->in_fmt, buf, ret, true); - ret += skl_print_fmt(mconfig->out_fmt, buf, ret, false); - - ret += scnprintf(buf + ret, MOD_BUF - ret, - "Fixup:\n\tParams %#x\n\tConverter %#x\n", - mconfig->params_fixup, mconfig->converter); - - ret += scnprintf(buf + ret, MOD_BUF - ret, - "Module Gateway:\n\tType %#x\n\tVbus %#x\n\tHW conn %#x\n\tSlot %#x\n", - mconfig->dev_type, mconfig->vbus_id, - mconfig->hw_conn_type, mconfig->time_slot); - - ret += scnprintf(buf + ret, MOD_BUF - ret, - "Pipeline:\n\tID %d\n\tPriority %d\n\tConn Type %d\n\t" - "Pages %#x\n", mconfig->pipe->ppl_id, - mconfig->pipe->pipe_priority, mconfig->pipe->conn_type, - mconfig->pipe->memory_pages); - - ret += scnprintf(buf + ret, MOD_BUF - ret, - "\tParams:\n\t\tHost DMA %d\n\t\tLink DMA %d\n", - mconfig->pipe->p_params->host_dma_id, - mconfig->pipe->p_params->link_dma_id); - - ret += scnprintf(buf + ret, MOD_BUF - ret, - "\tPCM params:\n\t\tCh %d\n\t\tFreq %d\n\t\tFormat %d\n", - mconfig->pipe->p_params->ch, - mconfig->pipe->p_params->s_freq, - mconfig->pipe->p_params->s_fmt); - - ret += scnprintf(buf + ret, MOD_BUF - ret, - "\tLink %#x\n\tStream %#x\n", - mconfig->pipe->p_params->linktype, - mconfig->pipe->p_params->stream); - - ret += scnprintf(buf + ret, MOD_BUF - ret, - "\tState %d\n\tPassthru %s\n", - mconfig->pipe->state, - mconfig->pipe->passthru ? "true" : "false"); - - ret += skl_print_pins(mconfig->m_in_pin, buf, - mconfig->max_in_queue, ret, true); - ret += skl_print_pins(mconfig->m_out_pin, buf, - mconfig->max_out_queue, ret, false); - - ret += scnprintf(buf + ret, MOD_BUF - ret, - "Other:\n\tDomain %d\n\tHomogeneous Input %s\n\t" - "Homogeneous Output %s\n\tIn Queue Mask %d\n\t" - "Out Queue Mask %d\n\tDMA ID %d\n\tMem Pages %d\n\t" - "Module Type %d\n\tModule State %d\n", - mconfig->domain, - mconfig->homogenous_inputs ? "true" : "false", - mconfig->homogenous_outputs ? "true" : "false", - mconfig->in_queue_mask, mconfig->out_queue_mask, - mconfig->dma_id, mconfig->mem_pages, mconfig->m_state, - mconfig->m_type); - - ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret); - - kfree(buf); - return ret; -} - -static const struct file_operations mcfg_fops = { - .open = simple_open, - .read = module_read, - .llseek = default_llseek, -}; - - -void skl_debug_init_module(struct skl_debug *d, - struct snd_soc_dapm_widget *w, - struct skl_module_cfg *mconfig) -{ - debugfs_create_file(w->name, 0444, d->modules, mconfig, - &mcfg_fops); -} - -static ssize_t fw_softreg_read(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct skl_debug *d = file->private_data; - struct sst_dsp *sst = d->skl->dsp; - size_t w0_stat_sz = sst->addr.w0_stat_sz; - void __iomem *in_base = sst->mailbox.in_base; - void __iomem *fw_reg_addr; - unsigned int offset; - char *tmp; - ssize_t ret = 0; - - tmp = kzalloc(FW_REG_BUF, GFP_KERNEL); - if (!tmp) - return -ENOMEM; - - fw_reg_addr = in_base - w0_stat_sz; - memset(d->fw_read_buff, 0, FW_REG_BUF); - - if (w0_stat_sz > 0) - __ioread32_copy(d->fw_read_buff, fw_reg_addr, w0_stat_sz >> 2); - - for (offset = 0; offset < FW_REG_SIZE; offset += 16) { - ret += scnprintf(tmp + ret, FW_REG_BUF - ret, "%#.4x: ", offset); - hex_dump_to_buffer(d->fw_read_buff + offset, 16, 16, 4, - tmp + ret, FW_REG_BUF - ret, 0); - ret += strlen(tmp + ret); - - /* print newline for each offset */ - if (FW_REG_BUF - ret > 0) - tmp[ret++] = '\n'; - } - - ret = simple_read_from_buffer(user_buf, count, ppos, tmp, ret); - kfree(tmp); - - return ret; -} - -static const struct file_operations soft_regs_ctrl_fops = { - .open = simple_open, - .read = fw_softreg_read, - .llseek = default_llseek, -}; - -struct skl_debug *skl_debugfs_init(struct skl_dev *skl) -{ - struct skl_debug *d; - - d = devm_kzalloc(&skl->pci->dev, sizeof(*d), GFP_KERNEL); - if (!d) - return NULL; - - /* create the debugfs dir with platform component's debugfs as parent */ - d->fs = debugfs_create_dir("dsp", skl->component->debugfs_root); - - d->skl = skl; - d->dev = &skl->pci->dev; - - /* now create the module dir */ - d->modules = debugfs_create_dir("modules", d->fs); - - debugfs_create_file("fw_soft_regs_rd", 0444, d->fs, d, - &soft_regs_ctrl_fops); - - return d; -} - -void skl_debugfs_exit(struct skl_dev *skl) -{ - struct skl_debug *d = skl->debugfs; - - debugfs_remove_recursive(d->fs); - - d = NULL; -} diff --git a/sound/soc/intel/skylake/skl-i2s.h b/sound/soc/intel/skylake/skl-i2s.h deleted file mode 100644 index dfce91e11be1f8..00000000000000 --- a/sound/soc/intel/skylake/skl-i2s.h +++ /dev/null @@ -1,87 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * skl-i2s.h - i2s blob mapping - * - * Copyright (C) 2017 Intel Corp - * Author: Subhransu S. Prusty < subhransu.s.prusty@intel.com> - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ - -#ifndef __SOUND_SOC_SKL_I2S_H -#define __SOUND_SOC_SKL_I2S_H - -#define SKL_I2S_MAX_TIME_SLOTS 8 -#define SKL_MCLK_DIV_CLK_SRC_MASK GENMASK(17, 16) - -#define SKL_MNDSS_DIV_CLK_SRC_MASK GENMASK(21, 20) -#define SKL_SHIFT(x) (ffs(x) - 1) -#define SKL_MCLK_DIV_RATIO_MASK GENMASK(11, 0) - -#define is_legacy_blob(x) (x.signature != 0xEE) -#define ext_to_legacy_blob(i2s_config_blob_ext) \ - ((struct skl_i2s_config_blob_legacy *) i2s_config_blob_ext) - -#define get_clk_src(mclk, mask) \ - ((mclk.mdivctrl & mask) >> SKL_SHIFT(mask)) -struct skl_i2s_config { - u32 ssc0; - u32 ssc1; - u32 sscto; - u32 sspsp; - u32 sstsa; - u32 ssrsa; - u32 ssc2; - u32 sspsp2; - u32 ssc3; - u32 ssioc; -} __packed; - -struct skl_i2s_config_mclk { - u32 mdivctrl; - u32 mdivr; -}; - -struct skl_i2s_config_mclk_ext { - u32 mdivctrl; - u32 mdivr_count; - u32 mdivr[]; -} __packed; - -struct skl_i2s_config_blob_signature { - u32 minor_ver : 8; - u32 major_ver : 8; - u32 resvdz : 8; - u32 signature : 8; -} __packed; - -struct skl_i2s_config_blob_header { - struct skl_i2s_config_blob_signature sig; - u32 size; -}; - -/** - * struct skl_i2s_config_blob_legacy - Structure defines I2S Gateway - * configuration legacy blob - * - * @gtw_attr: Gateway attribute for the I2S Gateway - * @tdm_ts_group: TDM slot mapping against channels in the Gateway. - * @i2s_cfg: I2S HW registers - * @mclk: MCLK clock source and divider values - */ -struct skl_i2s_config_blob_legacy { - u32 gtw_attr; - u32 tdm_ts_group[SKL_I2S_MAX_TIME_SLOTS]; - struct skl_i2s_config i2s_cfg; - struct skl_i2s_config_mclk mclk; -}; - -struct skl_i2s_config_blob_ext { - u32 gtw_attr; - struct skl_i2s_config_blob_header hdr; - u32 tdm_ts_group[SKL_I2S_MAX_TIME_SLOTS]; - struct skl_i2s_config i2s_cfg; - struct skl_i2s_config_mclk_ext mclk; -} __packed; -#endif /* __SOUND_SOC_SKL_I2S_H */ diff --git a/sound/soc/intel/skylake/skl-messages.c b/sound/soc/intel/skylake/skl-messages.c deleted file mode 100644 index fc2eb04da17213..00000000000000 --- a/sound/soc/intel/skylake/skl-messages.c +++ /dev/null @@ -1,1419 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * skl-message.c - HDA DSP interface for FW registration, Pipe and Module - * configurations - * - * Copyright (C) 2015 Intel Corp - * Author:Rafal Redzimski - * Jeeja KP - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ - -#include -#include -#include -#include -#include -#include "skl-sst-dsp.h" -#include "cnl-sst-dsp.h" -#include "skl-sst-ipc.h" -#include "skl.h" -#include "../common/sst-dsp.h" -#include "../common/sst-dsp-priv.h" -#include "skl-topology.h" - -static int skl_alloc_dma_buf(struct device *dev, - struct snd_dma_buffer *dmab, size_t size) -{ - return snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, dev, size, dmab); -} - -static int skl_free_dma_buf(struct device *dev, struct snd_dma_buffer *dmab) -{ - snd_dma_free_pages(dmab); - return 0; -} - -#define SKL_ASTATE_PARAM_ID 4 - -void skl_dsp_set_astate_cfg(struct skl_dev *skl, u32 cnt, void *data) -{ - struct skl_ipc_large_config_msg msg = {0}; - - msg.large_param_id = SKL_ASTATE_PARAM_ID; - msg.param_data_size = (cnt * sizeof(struct skl_astate_param) + - sizeof(cnt)); - - skl_ipc_set_large_config(&skl->ipc, &msg, data); -} - -static int skl_dsp_setup_spib(struct device *dev, unsigned int size, - int stream_tag, int enable) -{ - struct hdac_bus *bus = dev_get_drvdata(dev); - struct hdac_stream *stream = snd_hdac_get_stream(bus, - SNDRV_PCM_STREAM_PLAYBACK, stream_tag); - - if (!stream) - return -EINVAL; - - /* enable/disable SPIB for this hdac stream */ - snd_hdac_stream_spbcap_enable(bus, enable, stream->index); - - /* set the spib value */ - snd_hdac_stream_set_spib(bus, stream, size); - - return 0; -} - -static int skl_dsp_prepare(struct device *dev, unsigned int format, - unsigned int size, struct snd_dma_buffer *dmab) -{ - struct hdac_bus *bus = dev_get_drvdata(dev); - struct hdac_ext_stream *estream; - struct hdac_stream *stream; - struct snd_pcm_substream substream; - int ret; - - if (!bus) - return -ENODEV; - - memset(&substream, 0, sizeof(substream)); - substream.stream = SNDRV_PCM_STREAM_PLAYBACK; - - estream = snd_hdac_ext_stream_assign(bus, &substream, - HDAC_EXT_STREAM_TYPE_HOST); - if (!estream) - return -ENODEV; - - stream = hdac_stream(estream); - - /* assign decouple host dma channel */ - ret = snd_hdac_dsp_prepare(stream, format, size, dmab); - if (ret < 0) - return ret; - - skl_dsp_setup_spib(dev, size, stream->stream_tag, true); - - return stream->stream_tag; -} - -static int skl_dsp_trigger(struct device *dev, bool start, int stream_tag) -{ - struct hdac_bus *bus = dev_get_drvdata(dev); - struct hdac_stream *stream; - - if (!bus) - return -ENODEV; - - stream = snd_hdac_get_stream(bus, - SNDRV_PCM_STREAM_PLAYBACK, stream_tag); - if (!stream) - return -EINVAL; - - snd_hdac_dsp_trigger(stream, start); - - return 0; -} - -static int skl_dsp_cleanup(struct device *dev, - struct snd_dma_buffer *dmab, int stream_tag) -{ - struct hdac_bus *bus = dev_get_drvdata(dev); - struct hdac_stream *stream; - struct hdac_ext_stream *estream; - - if (!bus) - return -ENODEV; - - stream = snd_hdac_get_stream(bus, - SNDRV_PCM_STREAM_PLAYBACK, stream_tag); - if (!stream) - return -EINVAL; - - estream = stream_to_hdac_ext_stream(stream); - skl_dsp_setup_spib(dev, 0, stream_tag, false); - snd_hdac_ext_stream_release(estream, HDAC_EXT_STREAM_TYPE_HOST); - - snd_hdac_dsp_cleanup(stream, dmab); - - return 0; -} - -static struct skl_dsp_loader_ops skl_get_loader_ops(void) -{ - struct skl_dsp_loader_ops loader_ops; - - memset(&loader_ops, 0, sizeof(struct skl_dsp_loader_ops)); - - loader_ops.alloc_dma_buf = skl_alloc_dma_buf; - loader_ops.free_dma_buf = skl_free_dma_buf; - - return loader_ops; -}; - -static struct skl_dsp_loader_ops bxt_get_loader_ops(void) -{ - struct skl_dsp_loader_ops loader_ops; - - memset(&loader_ops, 0, sizeof(loader_ops)); - - loader_ops.alloc_dma_buf = skl_alloc_dma_buf; - loader_ops.free_dma_buf = skl_free_dma_buf; - loader_ops.prepare = skl_dsp_prepare; - loader_ops.trigger = skl_dsp_trigger; - loader_ops.cleanup = skl_dsp_cleanup; - - return loader_ops; -}; - -static const struct skl_dsp_ops dsp_ops[] = { - { - .id = PCI_DEVICE_ID_INTEL_HDA_SKL_LP, - .num_cores = 2, - .loader_ops = skl_get_loader_ops, - .init = skl_sst_dsp_init, - .init_fw = skl_sst_init_fw, - .cleanup = skl_sst_dsp_cleanup - }, - { - .id = PCI_DEVICE_ID_INTEL_HDA_KBL_LP, - .num_cores = 2, - .loader_ops = skl_get_loader_ops, - .init = skl_sst_dsp_init, - .init_fw = skl_sst_init_fw, - .cleanup = skl_sst_dsp_cleanup - }, - { - .id = PCI_DEVICE_ID_INTEL_HDA_APL, - .num_cores = 2, - .loader_ops = bxt_get_loader_ops, - .init = bxt_sst_dsp_init, - .init_fw = bxt_sst_init_fw, - .cleanup = bxt_sst_dsp_cleanup - }, - { - .id = PCI_DEVICE_ID_INTEL_HDA_GML, - .num_cores = 2, - .loader_ops = bxt_get_loader_ops, - .init = bxt_sst_dsp_init, - .init_fw = bxt_sst_init_fw, - .cleanup = bxt_sst_dsp_cleanup - }, - { - .id = PCI_DEVICE_ID_INTEL_HDA_CNL_LP, - .num_cores = 4, - .loader_ops = bxt_get_loader_ops, - .init = cnl_sst_dsp_init, - .init_fw = cnl_sst_init_fw, - .cleanup = cnl_sst_dsp_cleanup - }, - { - .id = PCI_DEVICE_ID_INTEL_HDA_CNL_H, - .num_cores = 4, - .loader_ops = bxt_get_loader_ops, - .init = cnl_sst_dsp_init, - .init_fw = cnl_sst_init_fw, - .cleanup = cnl_sst_dsp_cleanup - }, - { - .id = PCI_DEVICE_ID_INTEL_HDA_CML_LP, - .num_cores = 4, - .loader_ops = bxt_get_loader_ops, - .init = cnl_sst_dsp_init, - .init_fw = cnl_sst_init_fw, - .cleanup = cnl_sst_dsp_cleanup - }, - { - .id = PCI_DEVICE_ID_INTEL_HDA_CML_H, - .num_cores = 4, - .loader_ops = bxt_get_loader_ops, - .init = cnl_sst_dsp_init, - .init_fw = cnl_sst_init_fw, - .cleanup = cnl_sst_dsp_cleanup - }, -}; - -const struct skl_dsp_ops *skl_get_dsp_ops(int pci_id) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(dsp_ops); i++) { - if (dsp_ops[i].id == pci_id) - return &dsp_ops[i]; - } - - return NULL; -} - -int skl_init_dsp(struct skl_dev *skl) -{ - void __iomem *mmio_base; - struct hdac_bus *bus = skl_to_bus(skl); - struct skl_dsp_loader_ops loader_ops; - int irq = bus->irq; - const struct skl_dsp_ops *ops; - struct skl_dsp_cores *cores; - int ret; - - /* enable ppcap interrupt */ - snd_hdac_ext_bus_ppcap_enable(bus, true); - snd_hdac_ext_bus_ppcap_int_enable(bus, true); - - /* read the BAR of the ADSP MMIO */ - mmio_base = pci_ioremap_bar(skl->pci, 4); - if (mmio_base == NULL) { - dev_err(bus->dev, "ioremap error\n"); - return -ENXIO; - } - - ops = skl_get_dsp_ops(skl->pci->device); - if (!ops) { - ret = -EIO; - goto unmap_mmio; - } - - loader_ops = ops->loader_ops(); - ret = ops->init(bus->dev, mmio_base, irq, - skl->fw_name, loader_ops, - &skl); - - if (ret < 0) - goto unmap_mmio; - - skl->dsp_ops = ops; - cores = &skl->cores; - cores->count = ops->num_cores; - - cores->state = kcalloc(cores->count, sizeof(*cores->state), GFP_KERNEL); - if (!cores->state) { - ret = -ENOMEM; - goto unmap_mmio; - } - - cores->usage_count = kcalloc(cores->count, sizeof(*cores->usage_count), - GFP_KERNEL); - if (!cores->usage_count) { - ret = -ENOMEM; - goto free_core_state; - } - - dev_dbg(bus->dev, "dsp registration status=%d\n", ret); - - return 0; - -free_core_state: - kfree(cores->state); - -unmap_mmio: - iounmap(mmio_base); - - return ret; -} - -int skl_free_dsp(struct skl_dev *skl) -{ - struct hdac_bus *bus = skl_to_bus(skl); - - /* disable ppcap interrupt */ - snd_hdac_ext_bus_ppcap_int_enable(bus, false); - - skl->dsp_ops->cleanup(bus->dev, skl); - - kfree(skl->cores.state); - kfree(skl->cores.usage_count); - - if (skl->dsp->addr.lpe) - iounmap(skl->dsp->addr.lpe); - - return 0; -} - -/* - * In the case of "suspend_active" i.e, the Audio IP being active - * during system suspend, immediately excecute any pending D0i3 work - * before suspending. This is needed for the IP to work in low power - * mode during system suspend. In the case of normal suspend, cancel - * any pending D0i3 work. - */ -int skl_suspend_late_dsp(struct skl_dev *skl) -{ - struct delayed_work *dwork; - - if (!skl) - return 0; - - dwork = &skl->d0i3.work; - - if (dwork->work.func) { - if (skl->supend_active) - flush_delayed_work(dwork); - else - cancel_delayed_work_sync(dwork); - } - - return 0; -} - -int skl_suspend_dsp(struct skl_dev *skl) -{ - struct hdac_bus *bus = skl_to_bus(skl); - int ret; - - /* if ppcap is not supported return 0 */ - if (!bus->ppcap) - return 0; - - ret = skl_dsp_sleep(skl->dsp); - if (ret < 0) - return ret; - - /* disable ppcap interrupt */ - snd_hdac_ext_bus_ppcap_int_enable(bus, false); - snd_hdac_ext_bus_ppcap_enable(bus, false); - - return 0; -} - -int skl_resume_dsp(struct skl_dev *skl) -{ - struct hdac_bus *bus = skl_to_bus(skl); - int ret; - - /* if ppcap is not supported return 0 */ - if (!bus->ppcap) - return 0; - - /* enable ppcap interrupt */ - snd_hdac_ext_bus_ppcap_enable(bus, true); - snd_hdac_ext_bus_ppcap_int_enable(bus, true); - - /* check if DSP 1st boot is done */ - if (skl->is_first_boot) - return 0; - - /* - * Disable dynamic clock and power gating during firmware - * and library download - */ - skl->enable_miscbdcge(skl->dev, false); - skl->clock_power_gating(skl->dev, false); - - ret = skl_dsp_wake(skl->dsp); - skl->enable_miscbdcge(skl->dev, true); - skl->clock_power_gating(skl->dev, true); - if (ret < 0) - return ret; - - if (skl->cfg.astate_cfg != NULL) { - skl_dsp_set_astate_cfg(skl, skl->cfg.astate_cfg->count, - skl->cfg.astate_cfg); - } - return ret; -} - -enum skl_bitdepth skl_get_bit_depth(int params) -{ - switch (params) { - case 8: - return SKL_DEPTH_8BIT; - - case 16: - return SKL_DEPTH_16BIT; - - case 24: - return SKL_DEPTH_24BIT; - - case 32: - return SKL_DEPTH_32BIT; - - default: - return SKL_DEPTH_INVALID; - - } -} - -/* - * Each module in DSP expects a base module configuration, which consists of - * PCM format information, which we calculate in driver and resource values - * which are read from widget information passed through topology binary - * This is send when we create a module with INIT_INSTANCE IPC msg - */ -static void skl_set_base_module_format(struct skl_dev *skl, - struct skl_module_cfg *mconfig, - struct skl_base_cfg *base_cfg) -{ - struct skl_module *module = mconfig->module; - struct skl_module_res *res = &module->resources[mconfig->res_idx]; - struct skl_module_iface *fmt = &module->formats[mconfig->fmt_idx]; - struct skl_module_fmt *format = &fmt->inputs[0].fmt; - - base_cfg->audio_fmt.number_of_channels = format->channels; - - base_cfg->audio_fmt.s_freq = format->s_freq; - base_cfg->audio_fmt.bit_depth = format->bit_depth; - base_cfg->audio_fmt.valid_bit_depth = format->valid_bit_depth; - base_cfg->audio_fmt.ch_cfg = format->ch_cfg; - base_cfg->audio_fmt.sample_type = format->sample_type; - - dev_dbg(skl->dev, "bit_depth=%x valid_bd=%x ch_config=%x\n", - format->bit_depth, format->valid_bit_depth, - format->ch_cfg); - - base_cfg->audio_fmt.channel_map = format->ch_map; - - base_cfg->audio_fmt.interleaving = format->interleaving_style; - - base_cfg->cpc = res->cpc; - base_cfg->ibs = res->ibs; - base_cfg->obs = res->obs; - base_cfg->is_pages = res->is_pages; -} - -static void fill_pin_params(struct skl_audio_data_format *pin_fmt, - struct skl_module_fmt *format) -{ - pin_fmt->number_of_channels = format->channels; - pin_fmt->s_freq = format->s_freq; - pin_fmt->bit_depth = format->bit_depth; - pin_fmt->valid_bit_depth = format->valid_bit_depth; - pin_fmt->ch_cfg = format->ch_cfg; - pin_fmt->sample_type = format->sample_type; - pin_fmt->channel_map = format->ch_map; - pin_fmt->interleaving = format->interleaving_style; -} - -/* - * Any module configuration begins with a base module configuration but - * can be followed by a generic extension containing audio format for all - * module's pins that are in use. - */ -static void skl_set_base_ext_module_format(struct skl_dev *skl, - struct skl_module_cfg *mconfig, - struct skl_base_cfg_ext *base_cfg_ext) -{ - struct skl_module *module = mconfig->module; - struct skl_module_pin_resources *pin_res; - struct skl_module_iface *fmt = &module->formats[mconfig->fmt_idx]; - struct skl_module_res *res = &module->resources[mconfig->res_idx]; - struct skl_module_fmt *format; - struct skl_pin_format *pin_fmt; - char *params; - int i; - - base_cfg_ext->nr_input_pins = res->nr_input_pins; - base_cfg_ext->nr_output_pins = res->nr_output_pins; - base_cfg_ext->priv_param_length = - mconfig->formats_config[SKL_PARAM_INIT].caps_size; - - for (i = 0; i < res->nr_input_pins; i++) { - pin_res = &res->input[i]; - pin_fmt = &base_cfg_ext->pins_fmt[i]; - - pin_fmt->pin_idx = pin_res->pin_index; - pin_fmt->buf_size = pin_res->buf_size; - - format = &fmt->inputs[pin_res->pin_index].fmt; - fill_pin_params(&pin_fmt->audio_fmt, format); - } - - for (i = 0; i < res->nr_output_pins; i++) { - pin_res = &res->output[i]; - pin_fmt = &base_cfg_ext->pins_fmt[res->nr_input_pins + i]; - - pin_fmt->pin_idx = pin_res->pin_index; - pin_fmt->buf_size = pin_res->buf_size; - - format = &fmt->outputs[pin_res->pin_index].fmt; - fill_pin_params(&pin_fmt->audio_fmt, format); - } - - if (!base_cfg_ext->priv_param_length) - return; - - params = (char *)base_cfg_ext + sizeof(struct skl_base_cfg_ext); - params += (base_cfg_ext->nr_input_pins + base_cfg_ext->nr_output_pins) * - sizeof(struct skl_pin_format); - - memcpy(params, mconfig->formats_config[SKL_PARAM_INIT].caps, - mconfig->formats_config[SKL_PARAM_INIT].caps_size); -} - -/* - * Copies copier capabilities into copier module and updates copier module - * config size. - */ -static void skl_copy_copier_caps(struct skl_module_cfg *mconfig, - struct skl_cpr_cfg *cpr_mconfig) -{ - if (mconfig->formats_config[SKL_PARAM_INIT].caps_size == 0) - return; - - memcpy(&cpr_mconfig->gtw_cfg.config_data, - mconfig->formats_config[SKL_PARAM_INIT].caps, - mconfig->formats_config[SKL_PARAM_INIT].caps_size); - - cpr_mconfig->gtw_cfg.config_length = - (mconfig->formats_config[SKL_PARAM_INIT].caps_size) / 4; -} - -#define SKL_NON_GATEWAY_CPR_NODE_ID 0xFFFFFFFF -/* - * Calculate the gatewat settings required for copier module, type of - * gateway and index of gateway to use - */ -static u32 skl_get_node_id(struct skl_dev *skl, - struct skl_module_cfg *mconfig) -{ - union skl_connector_node_id node_id = {0}; - union skl_ssp_dma_node ssp_node = {0}; - struct skl_pipe_params *params = mconfig->pipe->p_params; - - switch (mconfig->dev_type) { - case SKL_DEVICE_BT: - node_id.node.dma_type = - (SKL_CONN_SOURCE == mconfig->hw_conn_type) ? - SKL_DMA_I2S_LINK_OUTPUT_CLASS : - SKL_DMA_I2S_LINK_INPUT_CLASS; - node_id.node.vindex = params->host_dma_id + - (mconfig->vbus_id << 3); - break; - - case SKL_DEVICE_I2S: - node_id.node.dma_type = - (SKL_CONN_SOURCE == mconfig->hw_conn_type) ? - SKL_DMA_I2S_LINK_OUTPUT_CLASS : - SKL_DMA_I2S_LINK_INPUT_CLASS; - ssp_node.dma_node.time_slot_index = mconfig->time_slot; - ssp_node.dma_node.i2s_instance = mconfig->vbus_id; - node_id.node.vindex = ssp_node.val; - break; - - case SKL_DEVICE_DMIC: - node_id.node.dma_type = SKL_DMA_DMIC_LINK_INPUT_CLASS; - node_id.node.vindex = mconfig->vbus_id + - (mconfig->time_slot); - break; - - case SKL_DEVICE_HDALINK: - node_id.node.dma_type = - (SKL_CONN_SOURCE == mconfig->hw_conn_type) ? - SKL_DMA_HDA_LINK_OUTPUT_CLASS : - SKL_DMA_HDA_LINK_INPUT_CLASS; - node_id.node.vindex = params->link_dma_id; - break; - - case SKL_DEVICE_HDAHOST: - node_id.node.dma_type = - (SKL_CONN_SOURCE == mconfig->hw_conn_type) ? - SKL_DMA_HDA_HOST_OUTPUT_CLASS : - SKL_DMA_HDA_HOST_INPUT_CLASS; - node_id.node.vindex = params->host_dma_id; - break; - - default: - node_id.val = 0xFFFFFFFF; - break; - } - - return node_id.val; -} - -static void skl_setup_cpr_gateway_cfg(struct skl_dev *skl, - struct skl_module_cfg *mconfig, - struct skl_cpr_cfg *cpr_mconfig) -{ - u32 dma_io_buf; - struct skl_module_res *res; - int res_idx = mconfig->res_idx; - - cpr_mconfig->gtw_cfg.node_id = skl_get_node_id(skl, mconfig); - - if (cpr_mconfig->gtw_cfg.node_id == SKL_NON_GATEWAY_CPR_NODE_ID) { - cpr_mconfig->cpr_feature_mask = 0; - return; - } - - if (skl->nr_modules) { - res = &mconfig->module->resources[mconfig->res_idx]; - cpr_mconfig->gtw_cfg.dma_buffer_size = res->dma_buffer_size; - goto skip_buf_size_calc; - } else { - res = &mconfig->module->resources[res_idx]; - } - - switch (mconfig->hw_conn_type) { - case SKL_CONN_SOURCE: - if (mconfig->dev_type == SKL_DEVICE_HDAHOST) - dma_io_buf = res->ibs; - else - dma_io_buf = res->obs; - break; - - case SKL_CONN_SINK: - if (mconfig->dev_type == SKL_DEVICE_HDAHOST) - dma_io_buf = res->obs; - else - dma_io_buf = res->ibs; - break; - - default: - dev_warn(skl->dev, "wrong connection type: %d\n", - mconfig->hw_conn_type); - return; - } - - cpr_mconfig->gtw_cfg.dma_buffer_size = - mconfig->dma_buffer_size * dma_io_buf; - - /* fallback to 2ms default value */ - if (!cpr_mconfig->gtw_cfg.dma_buffer_size) { - if (mconfig->hw_conn_type == SKL_CONN_SOURCE) - cpr_mconfig->gtw_cfg.dma_buffer_size = 2 * res->obs; - else - cpr_mconfig->gtw_cfg.dma_buffer_size = 2 * res->ibs; - } - -skip_buf_size_calc: - cpr_mconfig->cpr_feature_mask = 0; - cpr_mconfig->gtw_cfg.config_length = 0; - - skl_copy_copier_caps(mconfig, cpr_mconfig); -} - -#define DMA_CONTROL_ID 5 -#define DMA_I2S_BLOB_SIZE 21 - -int skl_dsp_set_dma_control(struct skl_dev *skl, u32 *caps, - u32 caps_size, u32 node_id) -{ - struct skl_dma_control *dma_ctrl; - struct skl_ipc_large_config_msg msg = {0}; - int err = 0; - - - /* - * if blob size zero, then return - */ - if (caps_size == 0) - return 0; - - msg.large_param_id = DMA_CONTROL_ID; - msg.param_data_size = sizeof(struct skl_dma_control) + caps_size; - - dma_ctrl = kzalloc(msg.param_data_size, GFP_KERNEL); - if (dma_ctrl == NULL) - return -ENOMEM; - - dma_ctrl->node_id = node_id; - - /* - * NHLT blob may contain additional configs along with i2s blob. - * firmware expects only the i2s blob size as the config_length. - * So fix to i2s blob size. - * size in dwords. - */ - dma_ctrl->config_length = DMA_I2S_BLOB_SIZE; - - memcpy(dma_ctrl->config_data, caps, caps_size); - - err = skl_ipc_set_large_config(&skl->ipc, &msg, (u32 *)dma_ctrl); - - kfree(dma_ctrl); - return err; -} -EXPORT_SYMBOL_GPL(skl_dsp_set_dma_control); - -static void skl_setup_out_format(struct skl_dev *skl, - struct skl_module_cfg *mconfig, - struct skl_audio_data_format *out_fmt) -{ - struct skl_module *module = mconfig->module; - struct skl_module_iface *fmt = &module->formats[mconfig->fmt_idx]; - struct skl_module_fmt *format = &fmt->outputs[0].fmt; - - out_fmt->number_of_channels = (u8)format->channels; - out_fmt->s_freq = format->s_freq; - out_fmt->bit_depth = format->bit_depth; - out_fmt->valid_bit_depth = format->valid_bit_depth; - out_fmt->ch_cfg = format->ch_cfg; - - out_fmt->channel_map = format->ch_map; - out_fmt->interleaving = format->interleaving_style; - out_fmt->sample_type = format->sample_type; - - dev_dbg(skl->dev, "copier out format chan=%d fre=%d bitdepth=%d\n", - out_fmt->number_of_channels, format->s_freq, format->bit_depth); -} - -/* - * DSP needs SRC module for frequency conversion, SRC takes base module - * configuration and the target frequency as extra parameter passed as src - * config - */ -static void skl_set_src_format(struct skl_dev *skl, - struct skl_module_cfg *mconfig, - struct skl_src_module_cfg *src_mconfig) -{ - struct skl_module *module = mconfig->module; - struct skl_module_iface *iface = &module->formats[mconfig->fmt_idx]; - struct skl_module_fmt *fmt = &iface->outputs[0].fmt; - - skl_set_base_module_format(skl, mconfig, - (struct skl_base_cfg *)src_mconfig); - - src_mconfig->src_cfg = fmt->s_freq; -} - -/* - * DSP needs updown module to do channel conversion. updown module take base - * module configuration and channel configuration - * It also take coefficients and now we have defaults applied here - */ -static void skl_set_updown_mixer_format(struct skl_dev *skl, - struct skl_module_cfg *mconfig, - struct skl_up_down_mixer_cfg *mixer_mconfig) -{ - struct skl_module *module = mconfig->module; - struct skl_module_iface *iface = &module->formats[mconfig->fmt_idx]; - struct skl_module_fmt *fmt = &iface->outputs[0].fmt; - - skl_set_base_module_format(skl, mconfig, - (struct skl_base_cfg *)mixer_mconfig); - mixer_mconfig->out_ch_cfg = fmt->ch_cfg; - mixer_mconfig->ch_map = fmt->ch_map; -} - -/* - * 'copier' is DSP internal module which copies data from Host DMA (HDA host - * dma) or link (hda link, SSP, PDM) - * Here we calculate the copier module parameters, like PCM format, output - * format, gateway settings - * copier_module_config is sent as input buffer with INIT_INSTANCE IPC msg - */ -static void skl_set_copier_format(struct skl_dev *skl, - struct skl_module_cfg *mconfig, - struct skl_cpr_cfg *cpr_mconfig) -{ - struct skl_audio_data_format *out_fmt = &cpr_mconfig->out_fmt; - struct skl_base_cfg *base_cfg = (struct skl_base_cfg *)cpr_mconfig; - - skl_set_base_module_format(skl, mconfig, base_cfg); - - skl_setup_out_format(skl, mconfig, out_fmt); - skl_setup_cpr_gateway_cfg(skl, mconfig, cpr_mconfig); -} - -/* - * Mic select module allows selecting one or many input channels, thus - * acting as a demux. - * - * Mic select module take base module configuration and out-format - * configuration - */ -static void skl_set_base_outfmt_format(struct skl_dev *skl, - struct skl_module_cfg *mconfig, - struct skl_base_outfmt_cfg *base_outfmt_mcfg) -{ - struct skl_audio_data_format *out_fmt = &base_outfmt_mcfg->out_fmt; - struct skl_base_cfg *base_cfg = - (struct skl_base_cfg *)base_outfmt_mcfg; - - skl_set_base_module_format(skl, mconfig, base_cfg); - skl_setup_out_format(skl, mconfig, out_fmt); -} - -static u16 skl_get_module_param_size(struct skl_dev *skl, - struct skl_module_cfg *mconfig) -{ - struct skl_module_res *res; - struct skl_module *module = mconfig->module; - u16 param_size; - - switch (mconfig->m_type) { - case SKL_MODULE_TYPE_COPIER: - param_size = sizeof(struct skl_cpr_cfg); - param_size += mconfig->formats_config[SKL_PARAM_INIT].caps_size; - return param_size; - - case SKL_MODULE_TYPE_SRCINT: - return sizeof(struct skl_src_module_cfg); - - case SKL_MODULE_TYPE_UPDWMIX: - return sizeof(struct skl_up_down_mixer_cfg); - - case SKL_MODULE_TYPE_BASE_OUTFMT: - case SKL_MODULE_TYPE_MIC_SELECT: - return sizeof(struct skl_base_outfmt_cfg); - - case SKL_MODULE_TYPE_MIXER: - case SKL_MODULE_TYPE_KPB: - return sizeof(struct skl_base_cfg); - - case SKL_MODULE_TYPE_ALGO: - default: - res = &module->resources[mconfig->res_idx]; - - param_size = sizeof(struct skl_base_cfg) + sizeof(struct skl_base_cfg_ext); - param_size += (res->nr_input_pins + res->nr_output_pins) * - sizeof(struct skl_pin_format); - param_size += mconfig->formats_config[SKL_PARAM_INIT].caps_size; - - return param_size; - } - - return 0; -} - -/* - * DSP firmware supports various modules like copier, SRC, updown etc. - * These modules required various parameters to be calculated and sent for - * the module initialization to DSP. By default a generic module needs only - * base module format configuration - */ - -static int skl_set_module_format(struct skl_dev *skl, - struct skl_module_cfg *module_config, - u16 *module_config_size, - void **param_data) -{ - u16 param_size; - - param_size = skl_get_module_param_size(skl, module_config); - - *param_data = kzalloc(param_size, GFP_KERNEL); - if (NULL == *param_data) - return -ENOMEM; - - *module_config_size = param_size; - - switch (module_config->m_type) { - case SKL_MODULE_TYPE_COPIER: - skl_set_copier_format(skl, module_config, *param_data); - break; - - case SKL_MODULE_TYPE_SRCINT: - skl_set_src_format(skl, module_config, *param_data); - break; - - case SKL_MODULE_TYPE_UPDWMIX: - skl_set_updown_mixer_format(skl, module_config, *param_data); - break; - - case SKL_MODULE_TYPE_BASE_OUTFMT: - case SKL_MODULE_TYPE_MIC_SELECT: - skl_set_base_outfmt_format(skl, module_config, *param_data); - break; - - case SKL_MODULE_TYPE_MIXER: - case SKL_MODULE_TYPE_KPB: - skl_set_base_module_format(skl, module_config, *param_data); - break; - - case SKL_MODULE_TYPE_ALGO: - default: - skl_set_base_module_format(skl, module_config, *param_data); - skl_set_base_ext_module_format(skl, module_config, - *param_data + - sizeof(struct skl_base_cfg)); - break; - } - - dev_dbg(skl->dev, "Module type=%d id=%d config size: %d bytes\n", - module_config->m_type, module_config->id.module_id, - param_size); - print_hex_dump_debug("Module params:", DUMP_PREFIX_OFFSET, 8, 4, - *param_data, param_size, false); - return 0; -} - -static int skl_get_queue_index(struct skl_module_pin *mpin, - struct skl_module_inst_id id, int max) -{ - int i; - - for (i = 0; i < max; i++) { - if (mpin[i].id.module_id == id.module_id && - mpin[i].id.instance_id == id.instance_id) - return i; - } - - return -EINVAL; -} - -/* - * Allocates queue for each module. - * if dynamic, the pin_index is allocated 0 to max_pin. - * In static, the pin_index is fixed based on module_id and instance id - */ -static int skl_alloc_queue(struct skl_module_pin *mpin, - struct skl_module_cfg *tgt_cfg, int max) -{ - int i; - struct skl_module_inst_id id = tgt_cfg->id; - /* - * if pin in dynamic, find first free pin - * otherwise find match module and instance id pin as topology will - * ensure a unique pin is assigned to this so no need to - * allocate/free - */ - for (i = 0; i < max; i++) { - if (mpin[i].is_dynamic) { - if (!mpin[i].in_use && - mpin[i].pin_state == SKL_PIN_UNBIND) { - - mpin[i].in_use = true; - mpin[i].id.module_id = id.module_id; - mpin[i].id.instance_id = id.instance_id; - mpin[i].id.pvt_id = id.pvt_id; - mpin[i].tgt_mcfg = tgt_cfg; - return i; - } - } else { - if (mpin[i].id.module_id == id.module_id && - mpin[i].id.instance_id == id.instance_id && - mpin[i].pin_state == SKL_PIN_UNBIND) { - - mpin[i].tgt_mcfg = tgt_cfg; - return i; - } - } - } - - return -EINVAL; -} - -static void skl_free_queue(struct skl_module_pin *mpin, int q_index) -{ - if (mpin[q_index].is_dynamic) { - mpin[q_index].in_use = false; - mpin[q_index].id.module_id = 0; - mpin[q_index].id.instance_id = 0; - mpin[q_index].id.pvt_id = 0; - } - mpin[q_index].pin_state = SKL_PIN_UNBIND; - mpin[q_index].tgt_mcfg = NULL; -} - -/* Module state will be set to unint, if all the out pin state is UNBIND */ - -static void skl_clear_module_state(struct skl_module_pin *mpin, int max, - struct skl_module_cfg *mcfg) -{ - int i; - bool found = false; - - for (i = 0; i < max; i++) { - if (mpin[i].pin_state == SKL_PIN_UNBIND) - continue; - found = true; - break; - } - - if (!found) - mcfg->m_state = SKL_MODULE_INIT_DONE; - return; -} - -/* - * A module needs to be instanataited in DSP. A mdoule is present in a - * collection of module referred as a PIPE. - * We first calculate the module format, based on module type and then - * invoke the DSP by sending IPC INIT_INSTANCE using ipc helper - */ -int skl_init_module(struct skl_dev *skl, - struct skl_module_cfg *mconfig) -{ - u16 module_config_size = 0; - void *param_data = NULL; - int ret; - struct skl_ipc_init_instance_msg msg; - - dev_dbg(skl->dev, "%s: module_id = %d instance=%d\n", __func__, - mconfig->id.module_id, mconfig->id.pvt_id); - - if (mconfig->pipe->state != SKL_PIPE_CREATED) { - dev_err(skl->dev, "Pipe not created state= %d pipe_id= %d\n", - mconfig->pipe->state, mconfig->pipe->ppl_id); - return -EIO; - } - - ret = skl_set_module_format(skl, mconfig, - &module_config_size, ¶m_data); - if (ret < 0) { - dev_err(skl->dev, "Failed to set module format ret=%d\n", ret); - return ret; - } - - msg.module_id = mconfig->id.module_id; - msg.instance_id = mconfig->id.pvt_id; - msg.ppl_instance_id = mconfig->pipe->ppl_id; - msg.param_data_size = module_config_size; - msg.core_id = mconfig->core_id; - msg.domain = mconfig->domain; - - ret = skl_ipc_init_instance(&skl->ipc, &msg, param_data); - if (ret < 0) { - dev_err(skl->dev, "Failed to init instance ret=%d\n", ret); - kfree(param_data); - return ret; - } - mconfig->m_state = SKL_MODULE_INIT_DONE; - kfree(param_data); - return ret; -} - -static void skl_dump_bind_info(struct skl_dev *skl, struct skl_module_cfg - *src_module, struct skl_module_cfg *dst_module) -{ - dev_dbg(skl->dev, "%s: src module_id = %d src_instance=%d\n", - __func__, src_module->id.module_id, src_module->id.pvt_id); - dev_dbg(skl->dev, "%s: dst_module=%d dst_instance=%d\n", __func__, - dst_module->id.module_id, dst_module->id.pvt_id); - - dev_dbg(skl->dev, "src_module state = %d dst module state = %d\n", - src_module->m_state, dst_module->m_state); -} - -/* - * On module freeup, we need to unbind the module with modules - * it is already bind. - * Find the pin allocated and unbind then using bind_unbind IPC - */ -int skl_unbind_modules(struct skl_dev *skl, - struct skl_module_cfg *src_mcfg, - struct skl_module_cfg *dst_mcfg) -{ - int ret; - struct skl_ipc_bind_unbind_msg msg; - struct skl_module_inst_id src_id = src_mcfg->id; - struct skl_module_inst_id dst_id = dst_mcfg->id; - int in_max = dst_mcfg->module->max_input_pins; - int out_max = src_mcfg->module->max_output_pins; - int src_index, dst_index, src_pin_state, dst_pin_state; - - skl_dump_bind_info(skl, src_mcfg, dst_mcfg); - - /* get src queue index */ - src_index = skl_get_queue_index(src_mcfg->m_out_pin, dst_id, out_max); - if (src_index < 0) - return 0; - - msg.src_queue = src_index; - - /* get dst queue index */ - dst_index = skl_get_queue_index(dst_mcfg->m_in_pin, src_id, in_max); - if (dst_index < 0) - return 0; - - msg.dst_queue = dst_index; - - src_pin_state = src_mcfg->m_out_pin[src_index].pin_state; - dst_pin_state = dst_mcfg->m_in_pin[dst_index].pin_state; - - if (src_pin_state != SKL_PIN_BIND_DONE || - dst_pin_state != SKL_PIN_BIND_DONE) - return 0; - - msg.module_id = src_mcfg->id.module_id; - msg.instance_id = src_mcfg->id.pvt_id; - msg.dst_module_id = dst_mcfg->id.module_id; - msg.dst_instance_id = dst_mcfg->id.pvt_id; - msg.bind = false; - - ret = skl_ipc_bind_unbind(&skl->ipc, &msg); - if (!ret) { - /* free queue only if unbind is success */ - skl_free_queue(src_mcfg->m_out_pin, src_index); - skl_free_queue(dst_mcfg->m_in_pin, dst_index); - - /* - * check only if src module bind state, bind is - * always from src -> sink - */ - skl_clear_module_state(src_mcfg->m_out_pin, out_max, src_mcfg); - } - - return ret; -} - -#define CPR_SINK_FMT_PARAM_ID 2 - -/* - * Once a module is instantiated it need to be 'bind' with other modules in - * the pipeline. For binding we need to find the module pins which are bind - * together - * This function finds the pins and then sends bund_unbind IPC message to - * DSP using IPC helper - */ -int skl_bind_modules(struct skl_dev *skl, - struct skl_module_cfg *src_mcfg, - struct skl_module_cfg *dst_mcfg) -{ - int ret = 0; - struct skl_ipc_bind_unbind_msg msg; - int in_max = dst_mcfg->module->max_input_pins; - int out_max = src_mcfg->module->max_output_pins; - int src_index, dst_index; - struct skl_module_fmt *format; - struct skl_cpr_pin_fmt pin_fmt; - struct skl_module *module; - struct skl_module_iface *fmt; - - skl_dump_bind_info(skl, src_mcfg, dst_mcfg); - - if (src_mcfg->m_state < SKL_MODULE_INIT_DONE || - dst_mcfg->m_state < SKL_MODULE_INIT_DONE) - return 0; - - src_index = skl_alloc_queue(src_mcfg->m_out_pin, dst_mcfg, out_max); - if (src_index < 0) - return -EINVAL; - - msg.src_queue = src_index; - dst_index = skl_alloc_queue(dst_mcfg->m_in_pin, src_mcfg, in_max); - if (dst_index < 0) { - skl_free_queue(src_mcfg->m_out_pin, src_index); - return -EINVAL; - } - - /* - * Copier module requires the separate large_config_set_ipc to - * configure the pins other than 0 - */ - if (src_mcfg->m_type == SKL_MODULE_TYPE_COPIER && src_index > 0) { - pin_fmt.sink_id = src_index; - module = src_mcfg->module; - fmt = &module->formats[src_mcfg->fmt_idx]; - - /* Input fmt is same as that of src module input cfg */ - format = &fmt->inputs[0].fmt; - fill_pin_params(&(pin_fmt.src_fmt), format); - - format = &fmt->outputs[src_index].fmt; - fill_pin_params(&(pin_fmt.dst_fmt), format); - ret = skl_set_module_params(skl, (void *)&pin_fmt, - sizeof(struct skl_cpr_pin_fmt), - CPR_SINK_FMT_PARAM_ID, src_mcfg); - - if (ret < 0) - goto out; - } - - msg.dst_queue = dst_index; - - dev_dbg(skl->dev, "src queue = %d dst queue =%d\n", - msg.src_queue, msg.dst_queue); - - msg.module_id = src_mcfg->id.module_id; - msg.instance_id = src_mcfg->id.pvt_id; - msg.dst_module_id = dst_mcfg->id.module_id; - msg.dst_instance_id = dst_mcfg->id.pvt_id; - msg.bind = true; - - ret = skl_ipc_bind_unbind(&skl->ipc, &msg); - - if (!ret) { - src_mcfg->m_state = SKL_MODULE_BIND_DONE; - src_mcfg->m_out_pin[src_index].pin_state = SKL_PIN_BIND_DONE; - dst_mcfg->m_in_pin[dst_index].pin_state = SKL_PIN_BIND_DONE; - return ret; - } -out: - /* error case , if IPC fails, clear the queue index */ - skl_free_queue(src_mcfg->m_out_pin, src_index); - skl_free_queue(dst_mcfg->m_in_pin, dst_index); - - return ret; -} - -static int skl_set_pipe_state(struct skl_dev *skl, struct skl_pipe *pipe, - enum skl_ipc_pipeline_state state) -{ - dev_dbg(skl->dev, "%s: pipe_state = %d\n", __func__, state); - - return skl_ipc_set_pipeline_state(&skl->ipc, pipe->ppl_id, state); -} - -/* - * A pipeline is a collection of modules. Before a module in instantiated a - * pipeline needs to be created for it. - * This function creates pipeline, by sending create pipeline IPC messages - * to FW - */ -int skl_create_pipeline(struct skl_dev *skl, struct skl_pipe *pipe) -{ - int ret; - - dev_dbg(skl->dev, "%s: pipe_id = %d\n", __func__, pipe->ppl_id); - - ret = skl_ipc_create_pipeline(&skl->ipc, pipe->memory_pages, - pipe->pipe_priority, pipe->ppl_id, - pipe->lp_mode); - if (ret < 0) { - dev_err(skl->dev, "Failed to create pipeline\n"); - return ret; - } - - pipe->state = SKL_PIPE_CREATED; - - return 0; -} - -/* - * A pipeline needs to be deleted on cleanup. If a pipeline is running, - * then pause it first. Before actual deletion, pipeline should enter - * reset state. Finish the procedure by sending delete pipeline IPC. - * DSP will stop the DMA engines and release resources - */ -int skl_delete_pipe(struct skl_dev *skl, struct skl_pipe *pipe) -{ - int ret; - - dev_dbg(skl->dev, "%s: pipe = %d\n", __func__, pipe->ppl_id); - - /* If pipe was not created in FW, do not try to delete it */ - if (pipe->state < SKL_PIPE_CREATED) - return 0; - - /* If pipe is started, do stop the pipe in FW. */ - if (pipe->state >= SKL_PIPE_STARTED) { - ret = skl_set_pipe_state(skl, pipe, PPL_PAUSED); - if (ret < 0) { - dev_err(skl->dev, "Failed to stop pipeline\n"); - return ret; - } - - pipe->state = SKL_PIPE_PAUSED; - } - - /* reset pipe state before deletion */ - ret = skl_set_pipe_state(skl, pipe, PPL_RESET); - if (ret < 0) { - dev_err(skl->dev, "Failed to reset pipe ret=%d\n", ret); - return ret; - } - - pipe->state = SKL_PIPE_RESET; - - ret = skl_ipc_delete_pipeline(&skl->ipc, pipe->ppl_id); - if (ret < 0) { - dev_err(skl->dev, "Failed to delete pipeline\n"); - return ret; - } - - pipe->state = SKL_PIPE_INVALID; - - return ret; -} - -/* - * A pipeline is also a scheduling entity in DSP which can be run, stopped - * For processing data the pipe need to be run by sending IPC set pipe state - * to DSP - */ -int skl_run_pipe(struct skl_dev *skl, struct skl_pipe *pipe) -{ - int ret; - - dev_dbg(skl->dev, "%s: pipe = %d\n", __func__, pipe->ppl_id); - - /* If pipe was not created in FW, do not try to pause or delete */ - if (pipe->state < SKL_PIPE_CREATED) - return 0; - - /* Pipe has to be paused before it is started */ - ret = skl_set_pipe_state(skl, pipe, PPL_PAUSED); - if (ret < 0) { - dev_err(skl->dev, "Failed to pause pipe\n"); - return ret; - } - - pipe->state = SKL_PIPE_PAUSED; - - ret = skl_set_pipe_state(skl, pipe, PPL_RUNNING); - if (ret < 0) { - dev_err(skl->dev, "Failed to start pipe\n"); - return ret; - } - - pipe->state = SKL_PIPE_STARTED; - - return 0; -} - -/* - * Stop the pipeline by sending set pipe state IPC - * DSP doesnt implement stop so we always send pause message - */ -int skl_stop_pipe(struct skl_dev *skl, struct skl_pipe *pipe) -{ - int ret; - - dev_dbg(skl->dev, "In %s pipe=%d\n", __func__, pipe->ppl_id); - - /* If pipe was not created in FW, do not try to pause or delete */ - if (pipe->state < SKL_PIPE_PAUSED) - return 0; - - ret = skl_set_pipe_state(skl, pipe, PPL_PAUSED); - if (ret < 0) { - dev_dbg(skl->dev, "Failed to stop pipe\n"); - return ret; - } - - pipe->state = SKL_PIPE_PAUSED; - - return 0; -} - -/* - * Reset the pipeline by sending set pipe state IPC this will reset the DMA - * from the DSP side - */ -int skl_reset_pipe(struct skl_dev *skl, struct skl_pipe *pipe) -{ - int ret; - - /* If pipe was not created in FW, do not try to pause or delete */ - if (pipe->state < SKL_PIPE_PAUSED) - return 0; - - ret = skl_set_pipe_state(skl, pipe, PPL_RESET); - if (ret < 0) { - dev_dbg(skl->dev, "Failed to reset pipe ret=%d\n", ret); - return ret; - } - - pipe->state = SKL_PIPE_RESET; - - return 0; -} - -/* Algo parameter set helper function */ -int skl_set_module_params(struct skl_dev *skl, u32 *params, int size, - u32 param_id, struct skl_module_cfg *mcfg) -{ - struct skl_ipc_large_config_msg msg; - - msg.module_id = mcfg->id.module_id; - msg.instance_id = mcfg->id.pvt_id; - msg.param_data_size = size; - msg.large_param_id = param_id; - - return skl_ipc_set_large_config(&skl->ipc, &msg, params); -} - -int skl_get_module_params(struct skl_dev *skl, u32 *params, int size, - u32 param_id, struct skl_module_cfg *mcfg) -{ - struct skl_ipc_large_config_msg msg; - size_t bytes = size; - - msg.module_id = mcfg->id.module_id; - msg.instance_id = mcfg->id.pvt_id; - msg.param_data_size = size; - msg.large_param_id = param_id; - - return skl_ipc_get_large_config(&skl->ipc, &msg, ¶ms, &bytes); -} diff --git a/sound/soc/intel/skylake/skl-nhlt.c b/sound/soc/intel/skylake/skl-nhlt.c deleted file mode 100644 index e617b4c335a433..00000000000000 --- a/sound/soc/intel/skylake/skl-nhlt.c +++ /dev/null @@ -1,269 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * skl-nhlt.c - Intel SKL Platform NHLT parsing - * - * Copyright (C) 2015 Intel Corp - * Author: Sanjiv Kumar - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ -#include -#include -#include "skl.h" -#include "skl-i2s.h" - -static void skl_nhlt_trim_space(char *trim) -{ - char *s = trim; - int cnt; - int i; - - cnt = 0; - for (i = 0; s[i]; i++) { - if (!isspace(s[i])) - s[cnt++] = s[i]; - } - - s[cnt] = '\0'; -} - -int skl_nhlt_update_topology_bin(struct skl_dev *skl) -{ - struct nhlt_acpi_table *nhlt = (struct nhlt_acpi_table *)skl->nhlt; - struct hdac_bus *bus = skl_to_bus(skl); - struct device *dev = bus->dev; - - dev_dbg(dev, "oem_id %.6s, oem_table_id %.8s oem_revision %d\n", - nhlt->header.oem_id, nhlt->header.oem_table_id, - nhlt->header.oem_revision); - - snprintf(skl->tplg_name, sizeof(skl->tplg_name), "%x-%.6s-%.8s-%d%s", - skl->pci_id, nhlt->header.oem_id, nhlt->header.oem_table_id, - nhlt->header.oem_revision, "-tplg.bin"); - - skl_nhlt_trim_space(skl->tplg_name); - - return 0; -} - -static ssize_t platform_id_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct pci_dev *pci = to_pci_dev(dev); - struct hdac_bus *bus = pci_get_drvdata(pci); - struct skl_dev *skl = bus_to_skl(bus); - struct nhlt_acpi_table *nhlt = (struct nhlt_acpi_table *)skl->nhlt; - char platform_id[32]; - - sprintf(platform_id, "%x-%.6s-%.8s-%d", skl->pci_id, - nhlt->header.oem_id, nhlt->header.oem_table_id, - nhlt->header.oem_revision); - - skl_nhlt_trim_space(platform_id); - return sysfs_emit(buf, "%s\n", platform_id); -} - -static DEVICE_ATTR_RO(platform_id); - -int skl_nhlt_create_sysfs(struct skl_dev *skl) -{ - struct device *dev = &skl->pci->dev; - - if (sysfs_create_file(&dev->kobj, &dev_attr_platform_id.attr)) - dev_warn(dev, "Error creating sysfs entry\n"); - - return 0; -} - -void skl_nhlt_remove_sysfs(struct skl_dev *skl) -{ - struct device *dev = &skl->pci->dev; - - if (skl->nhlt) - sysfs_remove_file(&dev->kobj, &dev_attr_platform_id.attr); -} - -/* - * Queries NHLT for all the fmt configuration for a particular endpoint and - * stores all possible rates supported in a rate table for the corresponding - * sclk/sclkfs. - */ -static void skl_get_ssp_clks(struct skl_dev *skl, struct skl_ssp_clk *ssp_clks, - struct nhlt_fmt *fmt, u8 id) -{ - struct skl_i2s_config_blob_ext *i2s_config_ext; - struct skl_i2s_config_blob_legacy *i2s_config; - struct skl_clk_parent_src *parent; - struct skl_ssp_clk *sclk, *sclkfs; - struct nhlt_fmt_cfg *fmt_cfg; - struct wav_fmt_ext *wav_fmt; - unsigned long rate; - int rate_index = 0; - u16 channels, bps; - u8 clk_src; - int i, j; - u32 fs; - - sclk = &ssp_clks[SKL_SCLK_OFS]; - sclkfs = &ssp_clks[SKL_SCLKFS_OFS]; - - if (fmt->fmt_count == 0) - return; - - fmt_cfg = (struct nhlt_fmt_cfg *)fmt->fmt_config; - for (i = 0; i < fmt->fmt_count; i++) { - struct nhlt_fmt_cfg *saved_fmt_cfg = fmt_cfg; - bool present = false; - - wav_fmt = &saved_fmt_cfg->fmt_ext; - - channels = wav_fmt->fmt.channels; - bps = wav_fmt->fmt.bits_per_sample; - fs = wav_fmt->fmt.samples_per_sec; - - /* - * In case of TDM configuration on a ssp, there can - * be more than one blob in which channel masks are - * different for each usecase for a specific rate and bps. - * But the sclk rate will be generated for the total - * number of channels used for that endpoint. - * - * So for the given fs and bps, choose blob which has - * the superset of all channels for that endpoint and - * derive the rate. - */ - for (j = i; j < fmt->fmt_count; j++) { - struct nhlt_fmt_cfg *tmp_fmt_cfg = fmt_cfg; - - wav_fmt = &tmp_fmt_cfg->fmt_ext; - if ((fs == wav_fmt->fmt.samples_per_sec) && - (bps == wav_fmt->fmt.bits_per_sample)) { - channels = max_t(u16, channels, - wav_fmt->fmt.channels); - saved_fmt_cfg = tmp_fmt_cfg; - } - /* Move to the next nhlt_fmt_cfg */ - tmp_fmt_cfg = (struct nhlt_fmt_cfg *)(tmp_fmt_cfg->config.caps + - tmp_fmt_cfg->config.size); - } - - rate = channels * bps * fs; - - /* check if the rate is added already to the given SSP's sclk */ - for (j = 0; (j < SKL_MAX_CLK_RATES) && - (sclk[id].rate_cfg[j].rate != 0); j++) { - if (sclk[id].rate_cfg[j].rate == rate) { - present = true; - break; - } - } - - /* Fill rate and parent for sclk/sclkfs */ - if (!present) { - struct nhlt_fmt_cfg *first_fmt_cfg; - - first_fmt_cfg = (struct nhlt_fmt_cfg *)fmt->fmt_config; - i2s_config_ext = (struct skl_i2s_config_blob_ext *) - first_fmt_cfg->config.caps; - - /* MCLK Divider Source Select */ - if (is_legacy_blob(i2s_config_ext->hdr.sig)) { - i2s_config = ext_to_legacy_blob(i2s_config_ext); - clk_src = get_clk_src(i2s_config->mclk, - SKL_MNDSS_DIV_CLK_SRC_MASK); - } else { - clk_src = get_clk_src(i2s_config_ext->mclk, - SKL_MNDSS_DIV_CLK_SRC_MASK); - } - - parent = skl_get_parent_clk(clk_src); - - /* Move to the next nhlt_fmt_cfg */ - fmt_cfg = (struct nhlt_fmt_cfg *)(fmt_cfg->config.caps + - fmt_cfg->config.size); - /* - * Do not copy the config data if there is no parent - * clock available for this clock source select - */ - if (!parent) - continue; - - sclk[id].rate_cfg[rate_index].rate = rate; - sclk[id].rate_cfg[rate_index].config = saved_fmt_cfg; - sclkfs[id].rate_cfg[rate_index].rate = rate; - sclkfs[id].rate_cfg[rate_index].config = saved_fmt_cfg; - sclk[id].parent_name = parent->name; - sclkfs[id].parent_name = parent->name; - - rate_index++; - } - } -} - -static void skl_get_mclk(struct skl_dev *skl, struct skl_ssp_clk *mclk, - struct nhlt_fmt *fmt, u8 id) -{ - struct skl_i2s_config_blob_ext *i2s_config_ext; - struct skl_i2s_config_blob_legacy *i2s_config; - struct nhlt_fmt_cfg *fmt_cfg; - struct skl_clk_parent_src *parent; - u32 clkdiv, div_ratio; - u8 clk_src; - - fmt_cfg = (struct nhlt_fmt_cfg *)fmt->fmt_config; - i2s_config_ext = (struct skl_i2s_config_blob_ext *)fmt_cfg->config.caps; - - /* MCLK Divider Source Select and divider */ - if (is_legacy_blob(i2s_config_ext->hdr.sig)) { - i2s_config = ext_to_legacy_blob(i2s_config_ext); - clk_src = get_clk_src(i2s_config->mclk, - SKL_MCLK_DIV_CLK_SRC_MASK); - clkdiv = i2s_config->mclk.mdivr & - SKL_MCLK_DIV_RATIO_MASK; - } else { - clk_src = get_clk_src(i2s_config_ext->mclk, - SKL_MCLK_DIV_CLK_SRC_MASK); - clkdiv = i2s_config_ext->mclk.mdivr[0] & - SKL_MCLK_DIV_RATIO_MASK; - } - - /* bypass divider */ - div_ratio = 1; - - if (clkdiv != SKL_MCLK_DIV_RATIO_MASK) - /* Divider is 2 + clkdiv */ - div_ratio = clkdiv + 2; - - /* Calculate MCLK rate from source using div value */ - parent = skl_get_parent_clk(clk_src); - if (!parent) - return; - - mclk[id].rate_cfg[0].rate = parent->rate/div_ratio; - mclk[id].rate_cfg[0].config = fmt_cfg; - mclk[id].parent_name = parent->name; -} - -void skl_get_clks(struct skl_dev *skl, struct skl_ssp_clk *ssp_clks) -{ - struct nhlt_acpi_table *nhlt = (struct nhlt_acpi_table *)skl->nhlt; - struct nhlt_endpoint *epnt; - struct nhlt_fmt *fmt; - int i; - u8 id; - - epnt = (struct nhlt_endpoint *)nhlt->desc; - for (i = 0; i < nhlt->endpoint_count; i++) { - if (epnt->linktype == NHLT_LINK_SSP) { - id = epnt->virtual_bus_id; - - fmt = (struct nhlt_fmt *)(epnt->config.caps - + epnt->config.size); - - skl_get_ssp_clks(skl, ssp_clks, fmt, id); - skl_get_mclk(skl, ssp_clks, fmt, id); - } - epnt = (struct nhlt_endpoint *)((u8 *)epnt + epnt->length); - } -} diff --git a/sound/soc/intel/skylake/skl-pcm.c b/sound/soc/intel/skylake/skl-pcm.c deleted file mode 100644 index 613b27b8da134d..00000000000000 --- a/sound/soc/intel/skylake/skl-pcm.c +++ /dev/null @@ -1,1507 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * skl-pcm.c -ASoC HDA Platform driver file implementing PCM functionality - * - * Copyright (C) 2014-2015 Intel Corp - * Author: Jeeja KP - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ - -#include -#include -#include -#include -#include -#include -#include "skl.h" -#include "skl-topology.h" -#include "skl-sst-dsp.h" -#include "skl-sst-ipc.h" - -#define HDA_MONO 1 -#define HDA_STEREO 2 -#define HDA_QUAD 4 -#define HDA_MAX 8 - -static const struct snd_pcm_hardware azx_pcm_hw = { - .info = (SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_RESUME | - SNDRV_PCM_INFO_SYNC_START | - SNDRV_PCM_INFO_HAS_WALL_CLOCK | /* legacy */ - SNDRV_PCM_INFO_HAS_LINK_ATIME | - SNDRV_PCM_INFO_NO_PERIOD_WAKEUP), - .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S32_LE | - SNDRV_PCM_FMTBIT_S24_LE, - .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_16000 | - SNDRV_PCM_RATE_8000, - .rate_min = 8000, - .rate_max = 48000, - .channels_min = 1, - .channels_max = 8, - .buffer_bytes_max = AZX_MAX_BUF_SIZE, - .period_bytes_min = 128, - .period_bytes_max = AZX_MAX_BUF_SIZE / 2, - .periods_min = 2, - .periods_max = AZX_MAX_FRAG, - .fifo_size = 0, -}; - -static inline -struct hdac_ext_stream *get_hdac_ext_stream(struct snd_pcm_substream *substream) -{ - return substream->runtime->private_data; -} - -static struct hdac_bus *get_bus_ctx(struct snd_pcm_substream *substream) -{ - struct hdac_ext_stream *stream = get_hdac_ext_stream(substream); - struct hdac_stream *hstream = hdac_stream(stream); - struct hdac_bus *bus = hstream->bus; - return bus; -} - -static int skl_substream_alloc_pages(struct hdac_bus *bus, - struct snd_pcm_substream *substream, - size_t size) -{ - struct hdac_ext_stream *stream = get_hdac_ext_stream(substream); - - hdac_stream(stream)->bufsize = 0; - hdac_stream(stream)->period_bytes = 0; - hdac_stream(stream)->format_val = 0; - - return 0; -} - -static void skl_set_pcm_constrains(struct hdac_bus *bus, - struct snd_pcm_runtime *runtime) -{ - snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); - - /* avoid wrap-around with wall-clock */ - snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_TIME, - 20, 178000000); -} - -static enum hdac_ext_stream_type skl_get_host_stream_type(struct hdac_bus *bus) -{ - if (bus->ppcap) - return HDAC_EXT_STREAM_TYPE_HOST; - else - return HDAC_EXT_STREAM_TYPE_COUPLED; -} - -/* - * check if the stream opened is marked as ignore_suspend by machine, if so - * then enable suspend_active refcount - * - * The count supend_active does not need lock as it is used in open/close - * and suspend context - */ -static void skl_set_suspend_active(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai, bool enable) -{ - struct hdac_bus *bus = dev_get_drvdata(dai->dev); - struct snd_soc_dapm_widget *w; - struct skl_dev *skl = bus_to_skl(bus); - - w = snd_soc_dai_get_widget(dai, substream->stream); - - if (w->ignore_suspend && enable) - skl->supend_active++; - else if (w->ignore_suspend && !enable) - skl->supend_active--; -} - -int skl_pcm_host_dma_prepare(struct device *dev, struct skl_pipe_params *params) -{ - struct hdac_bus *bus = dev_get_drvdata(dev); - unsigned int format_val; - struct hdac_stream *hstream; - struct hdac_ext_stream *stream; - unsigned int bits; - int err; - - hstream = snd_hdac_get_stream(bus, params->stream, - params->host_dma_id + 1); - if (!hstream) - return -EINVAL; - - stream = stream_to_hdac_ext_stream(hstream); - snd_hdac_ext_stream_decouple(bus, stream, true); - - bits = snd_hdac_stream_format_bits(params->format, SNDRV_PCM_SUBFORMAT_STD, - params->host_bps); - format_val = snd_hdac_stream_format(params->ch, bits, params->s_freq); - - dev_dbg(dev, "format_val=%d, rate=%d, ch=%d, format=%d\n", - format_val, params->s_freq, params->ch, params->format); - - snd_hdac_stream_reset(hdac_stream(stream)); - err = snd_hdac_stream_set_params(hdac_stream(stream), format_val); - if (err < 0) - return err; - - err = snd_hdac_ext_host_stream_setup(stream, false); - if (err < 0) - return err; - - hdac_stream(stream)->prepared = 1; - - return 0; -} - -int skl_pcm_link_dma_prepare(struct device *dev, struct skl_pipe_params *params) -{ - struct hdac_bus *bus = dev_get_drvdata(dev); - unsigned int format_val; - struct hdac_stream *hstream; - struct hdac_ext_stream *stream; - struct hdac_ext_link *link; - unsigned char stream_tag; - unsigned int bits; - - hstream = snd_hdac_get_stream(bus, params->stream, - params->link_dma_id + 1); - if (!hstream) - return -EINVAL; - - stream = stream_to_hdac_ext_stream(hstream); - snd_hdac_ext_stream_decouple(bus, stream, true); - - bits = snd_hdac_stream_format_bits(params->format, SNDRV_PCM_SUBFORMAT_STD, - params->link_bps); - format_val = snd_hdac_stream_format(params->ch, bits, params->s_freq); - - dev_dbg(dev, "format_val=%d, rate=%d, ch=%d, format=%d\n", - format_val, params->s_freq, params->ch, params->format); - - snd_hdac_ext_stream_reset(stream); - - snd_hdac_ext_stream_setup(stream, format_val); - - stream_tag = hstream->stream_tag; - if (stream->hstream.direction == SNDRV_PCM_STREAM_PLAYBACK) { - list_for_each_entry(link, &bus->hlink_list, list) { - if (link->index == params->link_index) - snd_hdac_ext_bus_link_set_stream_id(link, - stream_tag); - } - } - - stream->link_prepared = 1; - - return 0; -} - -static int skl_pcm_open(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct hdac_bus *bus = dev_get_drvdata(dai->dev); - struct hdac_ext_stream *stream; - struct snd_pcm_runtime *runtime = substream->runtime; - struct skl_dma_params *dma_params; - struct skl_dev *skl = get_skl_ctx(dai->dev); - struct skl_module_cfg *mconfig; - - dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name); - - stream = snd_hdac_ext_stream_assign(bus, substream, - skl_get_host_stream_type(bus)); - if (stream == NULL) - return -EBUSY; - - skl_set_pcm_constrains(bus, runtime); - - /* - * disable WALLCLOCK timestamps for capture streams - * until we figure out how to handle digital inputs - */ - if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { - runtime->hw.info &= ~SNDRV_PCM_INFO_HAS_WALL_CLOCK; /* legacy */ - runtime->hw.info &= ~SNDRV_PCM_INFO_HAS_LINK_ATIME; - } - - runtime->private_data = stream; - - dma_params = kzalloc(sizeof(*dma_params), GFP_KERNEL); - if (!dma_params) - return -ENOMEM; - - dma_params->stream_tag = hdac_stream(stream)->stream_tag; - snd_soc_dai_set_dma_data(dai, substream, dma_params); - - dev_dbg(dai->dev, "stream tag set in dma params=%d\n", - dma_params->stream_tag); - skl_set_suspend_active(substream, dai, true); - snd_pcm_set_sync(substream); - - mconfig = skl_tplg_fe_get_cpr_module(dai, substream->stream); - if (!mconfig) { - kfree(dma_params); - return -EINVAL; - } - - skl_tplg_d0i3_get(skl, mconfig->d0i3_caps); - - return 0; -} - -static int skl_pcm_prepare(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct skl_dev *skl = get_skl_ctx(dai->dev); - struct skl_module_cfg *mconfig; - int ret; - - dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name); - - mconfig = skl_tplg_fe_get_cpr_module(dai, substream->stream); - - /* - * In case of XRUN recovery or in the case when the application - * calls prepare another time, reset the FW pipe to clean state - */ - if (mconfig && - (substream->runtime->state == SNDRV_PCM_STATE_XRUN || - mconfig->pipe->state == SKL_PIPE_CREATED || - mconfig->pipe->state == SKL_PIPE_PAUSED)) { - - ret = skl_reset_pipe(skl, mconfig->pipe); - - if (ret < 0) - return ret; - - ret = skl_pcm_host_dma_prepare(dai->dev, - mconfig->pipe->p_params); - if (ret < 0) - return ret; - } - - return 0; -} - -static int skl_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct hdac_bus *bus = dev_get_drvdata(dai->dev); - struct hdac_ext_stream *stream = get_hdac_ext_stream(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct skl_pipe_params p_params = {0}; - struct skl_module_cfg *m_cfg; - int ret, dma_id; - - dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name); - ret = skl_substream_alloc_pages(bus, substream, - params_buffer_bytes(params)); - if (ret < 0) - return ret; - - dev_dbg(dai->dev, "format_val, rate=%d, ch=%d, format=%d\n", - runtime->rate, runtime->channels, runtime->format); - - dma_id = hdac_stream(stream)->stream_tag - 1; - dev_dbg(dai->dev, "dma_id=%d\n", dma_id); - - p_params.s_fmt = snd_pcm_format_width(params_format(params)); - p_params.s_cont = snd_pcm_format_physical_width(params_format(params)); - p_params.ch = params_channels(params); - p_params.s_freq = params_rate(params); - p_params.host_dma_id = dma_id; - p_params.stream = substream->stream; - p_params.format = params_format(params); - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - p_params.host_bps = dai->driver->playback.sig_bits; - else - p_params.host_bps = dai->driver->capture.sig_bits; - - - m_cfg = skl_tplg_fe_get_cpr_module(dai, p_params.stream); - if (m_cfg) - skl_tplg_update_pipe_params(dai->dev, m_cfg, &p_params); - - return 0; -} - -static void skl_pcm_close(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct hdac_ext_stream *stream = get_hdac_ext_stream(substream); - struct hdac_bus *bus = dev_get_drvdata(dai->dev); - struct skl_dma_params *dma_params = NULL; - struct skl_dev *skl = bus_to_skl(bus); - struct skl_module_cfg *mconfig; - - dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name); - - snd_hdac_ext_stream_release(stream, skl_get_host_stream_type(bus)); - - dma_params = snd_soc_dai_get_dma_data(dai, substream); - /* - * now we should set this to NULL as we are freeing by the - * dma_params - */ - snd_soc_dai_set_dma_data(dai, substream, NULL); - skl_set_suspend_active(substream, dai, false); - - /* - * check if close is for "Reference Pin" and set back the - * CGCTL.MISCBDCGE if disabled by driver - */ - if (!strncmp(dai->name, "Reference Pin", 13) && - skl->miscbdcg_disabled) { - skl->enable_miscbdcge(dai->dev, true); - skl->miscbdcg_disabled = false; - } - - mconfig = skl_tplg_fe_get_cpr_module(dai, substream->stream); - if (mconfig) - skl_tplg_d0i3_put(skl, mconfig->d0i3_caps); - - kfree(dma_params); -} - -static int skl_pcm_hw_free(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct hdac_ext_stream *stream = get_hdac_ext_stream(substream); - struct skl_dev *skl = get_skl_ctx(dai->dev); - struct skl_module_cfg *mconfig; - int ret; - - dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name); - - mconfig = skl_tplg_fe_get_cpr_module(dai, substream->stream); - - if (mconfig) { - ret = skl_reset_pipe(skl, mconfig->pipe); - if (ret < 0) - dev_err(dai->dev, "%s:Reset failed ret =%d", - __func__, ret); - } - - snd_hdac_stream_cleanup(hdac_stream(stream)); - hdac_stream(stream)->prepared = 0; - - return 0; -} - -static int skl_be_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct skl_pipe_params p_params = {0}; - - p_params.s_fmt = snd_pcm_format_width(params_format(params)); - p_params.s_cont = snd_pcm_format_physical_width(params_format(params)); - p_params.ch = params_channels(params); - p_params.s_freq = params_rate(params); - p_params.stream = substream->stream; - - return skl_tplg_be_update_params(dai, &p_params); -} - -static int skl_decoupled_trigger(struct snd_pcm_substream *substream, - int cmd) -{ - struct hdac_bus *bus = get_bus_ctx(substream); - struct hdac_ext_stream *stream; - int start; - unsigned long cookie; - struct hdac_stream *hstr; - - stream = get_hdac_ext_stream(substream); - hstr = hdac_stream(stream); - - if (!hstr->prepared) - return -EPIPE; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - case SNDRV_PCM_TRIGGER_RESUME: - start = 1; - break; - - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - case SNDRV_PCM_TRIGGER_SUSPEND: - case SNDRV_PCM_TRIGGER_STOP: - start = 0; - break; - - default: - return -EINVAL; - } - - spin_lock_irqsave(&bus->reg_lock, cookie); - - if (start) { - snd_hdac_stream_start(hdac_stream(stream)); - snd_hdac_stream_timecounter_init(hstr, 0); - } else { - snd_hdac_stream_stop(hdac_stream(stream)); - } - - spin_unlock_irqrestore(&bus->reg_lock, cookie); - - return 0; -} - -static int skl_pcm_trigger(struct snd_pcm_substream *substream, int cmd, - struct snd_soc_dai *dai) -{ - struct skl_dev *skl = get_skl_ctx(dai->dev); - struct skl_module_cfg *mconfig; - struct hdac_bus *bus = get_bus_ctx(substream); - struct hdac_ext_stream *stream = get_hdac_ext_stream(substream); - struct hdac_stream *hstream = hdac_stream(stream); - struct snd_soc_dapm_widget *w; - int ret; - - mconfig = skl_tplg_fe_get_cpr_module(dai, substream->stream); - if (!mconfig) - return -EIO; - - w = snd_soc_dai_get_widget(dai, substream->stream); - - switch (cmd) { - case SNDRV_PCM_TRIGGER_RESUME: - if (!w->ignore_suspend) { - /* - * enable DMA Resume enable bit for the stream, set the - * dpib & lpib position to resume before starting the - * DMA - */ - snd_hdac_stream_drsm_enable(bus, true, hstream->index); - snd_hdac_stream_set_dpibr(bus, hstream, hstream->lpib); - snd_hdac_stream_set_lpib(hstream, hstream->lpib); - } - fallthrough; - - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - /* - * Start HOST DMA and Start FE Pipe.This is to make sure that - * there are no underrun/overrun in the case when the FE - * pipeline is started but there is a delay in starting the - * DMA channel on the host. - */ - ret = skl_decoupled_trigger(substream, cmd); - if (ret < 0) - return ret; - return skl_run_pipe(skl, mconfig->pipe); - - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - case SNDRV_PCM_TRIGGER_SUSPEND: - case SNDRV_PCM_TRIGGER_STOP: - /* - * Stop FE Pipe first and stop DMA. This is to make sure that - * there are no underrun/overrun in the case if there is a delay - * between the two operations. - */ - ret = skl_stop_pipe(skl, mconfig->pipe); - if (ret < 0) - return ret; - - ret = skl_decoupled_trigger(substream, cmd); - if (ret < 0) - return ret; - - if ((cmd == SNDRV_PCM_TRIGGER_SUSPEND) && !w->ignore_suspend) { - /* save the dpib and lpib positions */ - hstream->dpib = readl(bus->remap_addr + - AZX_REG_VS_SDXDPIB_XBASE + - (AZX_REG_VS_SDXDPIB_XINTERVAL * - hstream->index)); - - hstream->lpib = snd_hdac_stream_get_pos_lpib(hstream); - - snd_hdac_ext_stream_decouple(bus, stream, false); - } - break; - - default: - return -EINVAL; - } - - return 0; -} - - -static int skl_link_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct hdac_bus *bus = dev_get_drvdata(dai->dev); - struct hdac_ext_stream *link_dev; - struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); - struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); - struct skl_pipe_params p_params = {0}; - struct hdac_ext_link *link; - int stream_tag; - - link_dev = snd_hdac_ext_stream_assign(bus, substream, - HDAC_EXT_STREAM_TYPE_LINK); - if (!link_dev) - return -EBUSY; - - snd_soc_dai_set_dma_data(dai, substream, (void *)link_dev); - - link = snd_hdac_ext_bus_get_hlink_by_name(bus, codec_dai->component->name); - if (!link) - return -EINVAL; - - stream_tag = hdac_stream(link_dev)->stream_tag; - - /* set the hdac_stream in the codec dai */ - snd_soc_dai_set_stream(codec_dai, hdac_stream(link_dev), substream->stream); - - p_params.s_fmt = snd_pcm_format_width(params_format(params)); - p_params.s_cont = snd_pcm_format_physical_width(params_format(params)); - p_params.ch = params_channels(params); - p_params.s_freq = params_rate(params); - p_params.stream = substream->stream; - p_params.link_dma_id = stream_tag - 1; - p_params.link_index = link->index; - p_params.format = params_format(params); - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - p_params.link_bps = codec_dai->driver->playback.sig_bits; - else - p_params.link_bps = codec_dai->driver->capture.sig_bits; - - return skl_tplg_be_update_params(dai, &p_params); -} - -static int skl_link_pcm_prepare(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct skl_dev *skl = get_skl_ctx(dai->dev); - struct skl_module_cfg *mconfig = NULL; - - /* In case of XRUN recovery, reset the FW pipe to clean state */ - mconfig = skl_tplg_be_get_cpr_module(dai, substream->stream); - if (mconfig && !mconfig->pipe->passthru && - (substream->runtime->state == SNDRV_PCM_STATE_XRUN)) - skl_reset_pipe(skl, mconfig->pipe); - - return 0; -} - -static int skl_link_pcm_trigger(struct snd_pcm_substream *substream, - int cmd, struct snd_soc_dai *dai) -{ - struct hdac_ext_stream *link_dev = - snd_soc_dai_get_dma_data(dai, substream); - struct hdac_bus *bus = get_bus_ctx(substream); - struct hdac_ext_stream *stream = get_hdac_ext_stream(substream); - - dev_dbg(dai->dev, "In %s cmd=%d\n", __func__, cmd); - switch (cmd) { - case SNDRV_PCM_TRIGGER_RESUME: - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - snd_hdac_ext_stream_start(link_dev); - break; - - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - case SNDRV_PCM_TRIGGER_SUSPEND: - case SNDRV_PCM_TRIGGER_STOP: - snd_hdac_ext_stream_clear(link_dev); - if (cmd == SNDRV_PCM_TRIGGER_SUSPEND) - snd_hdac_ext_stream_decouple(bus, stream, false); - break; - - default: - return -EINVAL; - } - return 0; -} - -static int skl_link_hw_free(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct hdac_bus *bus = dev_get_drvdata(dai->dev); - struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); - struct hdac_ext_stream *link_dev = - snd_soc_dai_get_dma_data(dai, substream); - struct hdac_ext_link *link; - unsigned char stream_tag; - - dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name); - - link_dev->link_prepared = 0; - - link = snd_hdac_ext_bus_get_hlink_by_name(bus, snd_soc_rtd_to_codec(rtd, 0)->component->name); - if (!link) - return -EINVAL; - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - stream_tag = hdac_stream(link_dev)->stream_tag; - snd_hdac_ext_bus_link_clear_stream_id(link, stream_tag); - } - - snd_hdac_ext_stream_release(link_dev, HDAC_EXT_STREAM_TYPE_LINK); - return 0; -} - -static const struct snd_soc_dai_ops skl_pcm_dai_ops = { - .startup = skl_pcm_open, - .shutdown = skl_pcm_close, - .prepare = skl_pcm_prepare, - .hw_params = skl_pcm_hw_params, - .hw_free = skl_pcm_hw_free, - .trigger = skl_pcm_trigger, -}; - -static const struct snd_soc_dai_ops skl_dmic_dai_ops = { - .hw_params = skl_be_hw_params, -}; - -static const struct snd_soc_dai_ops skl_be_ssp_dai_ops = { - .hw_params = skl_be_hw_params, -}; - -static const struct snd_soc_dai_ops skl_link_dai_ops = { - .prepare = skl_link_pcm_prepare, - .hw_params = skl_link_hw_params, - .hw_free = skl_link_hw_free, - .trigger = skl_link_pcm_trigger, -}; - -static struct snd_soc_dai_driver skl_fe_dai[] = { -{ - .name = "System Pin", - .ops = &skl_pcm_dai_ops, - .playback = { - .stream_name = "System Playback", - .channels_min = HDA_MONO, - .channels_max = HDA_STEREO, - .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_8000, - .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE, - .sig_bits = 32, - }, - .capture = { - .stream_name = "System Capture", - .channels_min = HDA_MONO, - .channels_max = HDA_STEREO, - .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_16000, - .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE, - .sig_bits = 32, - }, -}, -{ - .name = "System Pin2", - .ops = &skl_pcm_dai_ops, - .playback = { - .stream_name = "Headset Playback", - .channels_min = HDA_MONO, - .channels_max = HDA_STEREO, - .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_16000 | - SNDRV_PCM_RATE_8000, - .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE, - }, -}, -{ - .name = "Echoref Pin", - .ops = &skl_pcm_dai_ops, - .capture = { - .stream_name = "Echoreference Capture", - .channels_min = HDA_STEREO, - .channels_max = HDA_STEREO, - .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_16000 | - SNDRV_PCM_RATE_8000, - .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE, - }, -}, -{ - .name = "Reference Pin", - .ops = &skl_pcm_dai_ops, - .capture = { - .stream_name = "Reference Capture", - .channels_min = HDA_MONO, - .channels_max = HDA_QUAD, - .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_16000, - .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE, - .sig_bits = 32, - }, -}, -{ - .name = "Deepbuffer Pin", - .ops = &skl_pcm_dai_ops, - .playback = { - .stream_name = "Deepbuffer Playback", - .channels_min = HDA_STEREO, - .channels_max = HDA_STEREO, - .rates = SNDRV_PCM_RATE_48000, - .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE, - .sig_bits = 32, - }, -}, -{ - .name = "LowLatency Pin", - .ops = &skl_pcm_dai_ops, - .playback = { - .stream_name = "Low Latency Playback", - .channels_min = HDA_STEREO, - .channels_max = HDA_STEREO, - .rates = SNDRV_PCM_RATE_48000, - .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE, - .sig_bits = 32, - }, -}, -{ - .name = "DMIC Pin", - .ops = &skl_pcm_dai_ops, - .capture = { - .stream_name = "DMIC Capture", - .channels_min = HDA_MONO, - .channels_max = HDA_QUAD, - .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_16000, - .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE, - .sig_bits = 32, - }, -}, -{ - .name = "HDMI1 Pin", - .ops = &skl_pcm_dai_ops, - .playback = { - .stream_name = "HDMI1 Playback", - .channels_min = HDA_STEREO, - .channels_max = 8, - .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | - SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | - SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 | - SNDRV_PCM_RATE_192000, - .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | - SNDRV_PCM_FMTBIT_S32_LE, - .sig_bits = 32, - }, -}, -{ - .name = "HDMI2 Pin", - .ops = &skl_pcm_dai_ops, - .playback = { - .stream_name = "HDMI2 Playback", - .channels_min = HDA_STEREO, - .channels_max = 8, - .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | - SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | - SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 | - SNDRV_PCM_RATE_192000, - .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | - SNDRV_PCM_FMTBIT_S32_LE, - .sig_bits = 32, - }, -}, -{ - .name = "HDMI3 Pin", - .ops = &skl_pcm_dai_ops, - .playback = { - .stream_name = "HDMI3 Playback", - .channels_min = HDA_STEREO, - .channels_max = 8, - .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | - SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | - SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 | - SNDRV_PCM_RATE_192000, - .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | - SNDRV_PCM_FMTBIT_S32_LE, - .sig_bits = 32, - }, -}, -}; - -/* BE CPU Dais */ -static struct snd_soc_dai_driver skl_platform_dai[] = { -{ - .name = "SSP0 Pin", - .ops = &skl_be_ssp_dai_ops, - .playback = { - .stream_name = "ssp0 Tx", - .channels_min = HDA_STEREO, - .channels_max = HDA_STEREO, - .rates = SNDRV_PCM_RATE_48000, - .formats = SNDRV_PCM_FMTBIT_S16_LE, - }, - .capture = { - .stream_name = "ssp0 Rx", - .channels_min = HDA_STEREO, - .channels_max = HDA_STEREO, - .rates = SNDRV_PCM_RATE_48000, - .formats = SNDRV_PCM_FMTBIT_S16_LE, - }, -}, -{ - .name = "SSP1 Pin", - .ops = &skl_be_ssp_dai_ops, - .playback = { - .stream_name = "ssp1 Tx", - .channels_min = HDA_STEREO, - .channels_max = HDA_STEREO, - .rates = SNDRV_PCM_RATE_48000, - .formats = SNDRV_PCM_FMTBIT_S16_LE, - }, - .capture = { - .stream_name = "ssp1 Rx", - .channels_min = HDA_STEREO, - .channels_max = HDA_STEREO, - .rates = SNDRV_PCM_RATE_48000, - .formats = SNDRV_PCM_FMTBIT_S16_LE, - }, -}, -{ - .name = "SSP2 Pin", - .ops = &skl_be_ssp_dai_ops, - .playback = { - .stream_name = "ssp2 Tx", - .channels_min = HDA_STEREO, - .channels_max = HDA_STEREO, - .rates = SNDRV_PCM_RATE_48000, - .formats = SNDRV_PCM_FMTBIT_S16_LE, - }, - .capture = { - .stream_name = "ssp2 Rx", - .channels_min = HDA_STEREO, - .channels_max = HDA_STEREO, - .rates = SNDRV_PCM_RATE_48000, - .formats = SNDRV_PCM_FMTBIT_S16_LE, - }, -}, -{ - .name = "SSP3 Pin", - .ops = &skl_be_ssp_dai_ops, - .playback = { - .stream_name = "ssp3 Tx", - .channels_min = HDA_STEREO, - .channels_max = HDA_STEREO, - .rates = SNDRV_PCM_RATE_48000, - .formats = SNDRV_PCM_FMTBIT_S16_LE, - }, - .capture = { - .stream_name = "ssp3 Rx", - .channels_min = HDA_STEREO, - .channels_max = HDA_STEREO, - .rates = SNDRV_PCM_RATE_48000, - .formats = SNDRV_PCM_FMTBIT_S16_LE, - }, -}, -{ - .name = "SSP4 Pin", - .ops = &skl_be_ssp_dai_ops, - .playback = { - .stream_name = "ssp4 Tx", - .channels_min = HDA_STEREO, - .channels_max = HDA_STEREO, - .rates = SNDRV_PCM_RATE_48000, - .formats = SNDRV_PCM_FMTBIT_S16_LE, - }, - .capture = { - .stream_name = "ssp4 Rx", - .channels_min = HDA_STEREO, - .channels_max = HDA_STEREO, - .rates = SNDRV_PCM_RATE_48000, - .formats = SNDRV_PCM_FMTBIT_S16_LE, - }, -}, -{ - .name = "SSP5 Pin", - .ops = &skl_be_ssp_dai_ops, - .playback = { - .stream_name = "ssp5 Tx", - .channels_min = HDA_STEREO, - .channels_max = HDA_STEREO, - .rates = SNDRV_PCM_RATE_48000, - .formats = SNDRV_PCM_FMTBIT_S16_LE, - }, - .capture = { - .stream_name = "ssp5 Rx", - .channels_min = HDA_STEREO, - .channels_max = HDA_STEREO, - .rates = SNDRV_PCM_RATE_48000, - .formats = SNDRV_PCM_FMTBIT_S16_LE, - }, -}, -{ - .name = "iDisp1 Pin", - .ops = &skl_link_dai_ops, - .playback = { - .stream_name = "iDisp1 Tx", - .channels_min = HDA_STEREO, - .channels_max = 8, - .rates = SNDRV_PCM_RATE_8000|SNDRV_PCM_RATE_16000|SNDRV_PCM_RATE_48000, - .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE | - SNDRV_PCM_FMTBIT_S24_LE, - }, -}, -{ - .name = "iDisp2 Pin", - .ops = &skl_link_dai_ops, - .playback = { - .stream_name = "iDisp2 Tx", - .channels_min = HDA_STEREO, - .channels_max = 8, - .rates = SNDRV_PCM_RATE_8000|SNDRV_PCM_RATE_16000| - SNDRV_PCM_RATE_48000, - .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE | - SNDRV_PCM_FMTBIT_S24_LE, - }, -}, -{ - .name = "iDisp3 Pin", - .ops = &skl_link_dai_ops, - .playback = { - .stream_name = "iDisp3 Tx", - .channels_min = HDA_STEREO, - .channels_max = 8, - .rates = SNDRV_PCM_RATE_8000|SNDRV_PCM_RATE_16000| - SNDRV_PCM_RATE_48000, - .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE | - SNDRV_PCM_FMTBIT_S24_LE, - }, -}, -{ - .name = "DMIC01 Pin", - .ops = &skl_dmic_dai_ops, - .capture = { - .stream_name = "DMIC01 Rx", - .channels_min = HDA_MONO, - .channels_max = HDA_QUAD, - .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_16000, - .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE, - }, -}, -{ - .name = "DMIC16k Pin", - .ops = &skl_dmic_dai_ops, - .capture = { - .stream_name = "DMIC16k Rx", - .channels_min = HDA_MONO, - .channels_max = HDA_QUAD, - .rates = SNDRV_PCM_RATE_16000, - .formats = SNDRV_PCM_FMTBIT_S16_LE, - }, -}, -{ - .name = "Analog CPU DAI", - .ops = &skl_link_dai_ops, - .playback = { - .stream_name = "Analog CPU Playback", - .channels_min = HDA_MONO, - .channels_max = HDA_MAX, - .rates = SNDRV_PCM_RATE_8000_192000, - .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | - SNDRV_PCM_FMTBIT_S32_LE, - }, - .capture = { - .stream_name = "Analog CPU Capture", - .channels_min = HDA_MONO, - .channels_max = HDA_MAX, - .rates = SNDRV_PCM_RATE_8000_192000, - .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | - SNDRV_PCM_FMTBIT_S32_LE, - }, -}, -{ - .name = "Alt Analog CPU DAI", - .ops = &skl_link_dai_ops, - .playback = { - .stream_name = "Alt Analog CPU Playback", - .channels_min = HDA_MONO, - .channels_max = HDA_MAX, - .rates = SNDRV_PCM_RATE_8000_192000, - .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | - SNDRV_PCM_FMTBIT_S32_LE, - }, - .capture = { - .stream_name = "Alt Analog CPU Capture", - .channels_min = HDA_MONO, - .channels_max = HDA_MAX, - .rates = SNDRV_PCM_RATE_8000_192000, - .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | - SNDRV_PCM_FMTBIT_S32_LE, - }, -}, -{ - .name = "Digital CPU DAI", - .ops = &skl_link_dai_ops, - .playback = { - .stream_name = "Digital CPU Playback", - .channels_min = HDA_MONO, - .channels_max = HDA_MAX, - .rates = SNDRV_PCM_RATE_8000_192000, - .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | - SNDRV_PCM_FMTBIT_S32_LE, - }, - .capture = { - .stream_name = "Digital CPU Capture", - .channels_min = HDA_MONO, - .channels_max = HDA_MAX, - .rates = SNDRV_PCM_RATE_8000_192000, - .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | - SNDRV_PCM_FMTBIT_S32_LE, - }, -}, -}; - -int skl_dai_load(struct snd_soc_component *cmp, int index, - struct snd_soc_dai_driver *dai_drv, - struct snd_soc_tplg_pcm *pcm, struct snd_soc_dai *dai) -{ - dai_drv->ops = &skl_pcm_dai_ops; - - return 0; -} - -static int skl_platform_soc_open(struct snd_soc_component *component, - struct snd_pcm_substream *substream) -{ - struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); - struct snd_soc_dai_link *dai_link = rtd->dai_link; - - dev_dbg(snd_soc_rtd_to_cpu(rtd, 0)->dev, "In %s:%s\n", __func__, - dai_link->cpus->dai_name); - - snd_soc_set_runtime_hwparams(substream, &azx_pcm_hw); - - return 0; -} - -static int skl_coupled_trigger(struct snd_pcm_substream *substream, - int cmd) -{ - struct hdac_bus *bus = get_bus_ctx(substream); - struct hdac_ext_stream *stream; - struct snd_pcm_substream *s; - bool start; - int sbits = 0; - unsigned long cookie; - struct hdac_stream *hstr; - - stream = get_hdac_ext_stream(substream); - hstr = hdac_stream(stream); - - dev_dbg(bus->dev, "In %s cmd=%d\n", __func__, cmd); - - if (!hstr->prepared) - return -EPIPE; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - case SNDRV_PCM_TRIGGER_RESUME: - start = true; - break; - - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - case SNDRV_PCM_TRIGGER_SUSPEND: - case SNDRV_PCM_TRIGGER_STOP: - start = false; - break; - - default: - return -EINVAL; - } - - snd_pcm_group_for_each_entry(s, substream) { - if (s->pcm->card != substream->pcm->card) - continue; - stream = get_hdac_ext_stream(s); - sbits |= 1 << hdac_stream(stream)->index; - snd_pcm_trigger_done(s, substream); - } - - spin_lock_irqsave(&bus->reg_lock, cookie); - - /* first, set SYNC bits of corresponding streams */ - snd_hdac_stream_sync_trigger(hstr, true, sbits, AZX_REG_SSYNC); - - snd_pcm_group_for_each_entry(s, substream) { - if (s->pcm->card != substream->pcm->card) - continue; - stream = get_hdac_ext_stream(s); - if (start) - snd_hdac_stream_start(hdac_stream(stream)); - else - snd_hdac_stream_stop(hdac_stream(stream)); - } - spin_unlock_irqrestore(&bus->reg_lock, cookie); - - snd_hdac_stream_sync(hstr, start, sbits); - - spin_lock_irqsave(&bus->reg_lock, cookie); - - /* reset SYNC bits */ - snd_hdac_stream_sync_trigger(hstr, false, sbits, AZX_REG_SSYNC); - if (start) - snd_hdac_stream_timecounter_init(hstr, sbits); - spin_unlock_irqrestore(&bus->reg_lock, cookie); - - return 0; -} - -static int skl_platform_soc_trigger(struct snd_soc_component *component, - struct snd_pcm_substream *substream, - int cmd) -{ - struct hdac_bus *bus = get_bus_ctx(substream); - - if (!bus->ppcap) - return skl_coupled_trigger(substream, cmd); - - return 0; -} - -static snd_pcm_uframes_t skl_platform_soc_pointer( - struct snd_soc_component *component, - struct snd_pcm_substream *substream) -{ - struct hdac_ext_stream *hstream = get_hdac_ext_stream(substream); - struct hdac_bus *bus = get_bus_ctx(substream); - unsigned int pos; - - /* - * Use DPIB for Playback stream as the periodic DMA Position-in- - * Buffer Writes may be scheduled at the same time or later than - * the MSI and does not guarantee to reflect the Position of the - * last buffer that was transferred. Whereas DPIB register in - * HAD space reflects the actual data that is transferred. - * Use the position buffer for capture, as DPIB write gets - * completed earlier than the actual data written to the DDR. - * - * For capture stream following workaround is required to fix the - * incorrect position reporting. - * - * 1. Wait for 20us before reading the DMA position in buffer once - * the interrupt is generated for stream completion as update happens - * on the HDA frame boundary i.e. 20.833uSec. - * 2. Read DPIB register to flush the DMA position value. This dummy - * read is required to flush DMA position value. - * 3. Read the DMA Position-in-Buffer. This value now will be equal to - * or greater than period boundary. - */ - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - pos = readl(bus->remap_addr + AZX_REG_VS_SDXDPIB_XBASE + - (AZX_REG_VS_SDXDPIB_XINTERVAL * - hdac_stream(hstream)->index)); - } else { - udelay(20); - readl(bus->remap_addr + - AZX_REG_VS_SDXDPIB_XBASE + - (AZX_REG_VS_SDXDPIB_XINTERVAL * - hdac_stream(hstream)->index)); - pos = snd_hdac_stream_get_pos_posbuf(hdac_stream(hstream)); - } - - if (pos >= hdac_stream(hstream)->bufsize) - pos = 0; - - return bytes_to_frames(substream->runtime, pos); -} - -static u64 skl_adjust_codec_delay(struct snd_pcm_substream *substream, - u64 nsec) -{ - struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); - struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); - u64 codec_frames, codec_nsecs; - - if (!codec_dai->driver->ops->delay) - return nsec; - - codec_frames = codec_dai->driver->ops->delay(substream, codec_dai); - codec_nsecs = div_u64(codec_frames * 1000000000LL, - substream->runtime->rate); - - if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) - return nsec + codec_nsecs; - - return (nsec > codec_nsecs) ? nsec - codec_nsecs : 0; -} - -static int skl_platform_soc_get_time_info( - struct snd_soc_component *component, - struct snd_pcm_substream *substream, - struct timespec64 *system_ts, struct timespec64 *audio_ts, - struct snd_pcm_audio_tstamp_config *audio_tstamp_config, - struct snd_pcm_audio_tstamp_report *audio_tstamp_report) -{ - struct hdac_ext_stream *sstream = get_hdac_ext_stream(substream); - struct hdac_stream *hstr = hdac_stream(sstream); - u64 nsec; - - if ((substream->runtime->hw.info & SNDRV_PCM_INFO_HAS_LINK_ATIME) && - (audio_tstamp_config->type_requested == SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK)) { - - snd_pcm_gettime(substream->runtime, system_ts); - - nsec = timecounter_read(&hstr->tc); - if (audio_tstamp_config->report_delay) - nsec = skl_adjust_codec_delay(substream, nsec); - - *audio_ts = ns_to_timespec64(nsec); - - audio_tstamp_report->actual_type = SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK; - audio_tstamp_report->accuracy_report = 1; /* rest of struct is valid */ - audio_tstamp_report->accuracy = 42; /* 24MHzWallClk == 42ns resolution */ - - } else { - audio_tstamp_report->actual_type = SNDRV_PCM_AUDIO_TSTAMP_TYPE_DEFAULT; - } - - return 0; -} - -#define MAX_PREALLOC_SIZE (32 * 1024 * 1024) - -static int skl_platform_soc_new(struct snd_soc_component *component, - struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_dai *dai = snd_soc_rtd_to_cpu(rtd, 0); - struct hdac_bus *bus = dev_get_drvdata(dai->dev); - struct snd_pcm *pcm = rtd->pcm; - unsigned int size; - struct skl_dev *skl = bus_to_skl(bus); - - if (dai->driver->playback.channels_min || - dai->driver->capture.channels_min) { - /* buffer pre-allocation */ - size = CONFIG_SND_HDA_PREALLOC_SIZE * 1024; - if (size > MAX_PREALLOC_SIZE) - size = MAX_PREALLOC_SIZE; - snd_pcm_set_managed_buffer_all(pcm, - SNDRV_DMA_TYPE_DEV_SG, - &skl->pci->dev, - size, MAX_PREALLOC_SIZE); - } - - return 0; -} - -static int skl_get_module_info(struct skl_dev *skl, - struct skl_module_cfg *mconfig) -{ - struct skl_module_inst_id *pin_id; - guid_t *uuid_mod, *uuid_tplg; - struct skl_module *skl_module; - struct uuid_module *module; - int i, ret = -EIO; - - uuid_mod = (guid_t *)mconfig->guid; - - if (list_empty(&skl->uuid_list)) { - dev_err(skl->dev, "Module list is empty\n"); - return -EIO; - } - - for (i = 0; i < skl->nr_modules; i++) { - skl_module = skl->modules[i]; - uuid_tplg = &skl_module->uuid; - if (guid_equal(uuid_mod, uuid_tplg)) { - mconfig->module = skl_module; - ret = 0; - break; - } - } - - if (skl->nr_modules && ret) - return ret; - - ret = -EIO; - list_for_each_entry(module, &skl->uuid_list, list) { - if (guid_equal(uuid_mod, &module->uuid)) { - mconfig->id.module_id = module->id; - mconfig->module->loadable = module->is_loadable; - ret = 0; - } - - for (i = 0; i < MAX_IN_QUEUE; i++) { - pin_id = &mconfig->m_in_pin[i].id; - if (guid_equal(&pin_id->mod_uuid, &module->uuid)) - pin_id->module_id = module->id; - } - - for (i = 0; i < MAX_OUT_QUEUE; i++) { - pin_id = &mconfig->m_out_pin[i].id; - if (guid_equal(&pin_id->mod_uuid, &module->uuid)) - pin_id->module_id = module->id; - } - } - - return ret; -} - -static int skl_populate_modules(struct skl_dev *skl) -{ - struct skl_pipeline *p; - struct skl_pipe_module *m; - struct snd_soc_dapm_widget *w; - struct skl_module_cfg *mconfig; - int ret = 0; - - list_for_each_entry(p, &skl->ppl_list, node) { - list_for_each_entry(m, &p->pipe->w_list, node) { - w = m->w; - mconfig = w->priv; - - ret = skl_get_module_info(skl, mconfig); - if (ret < 0) { - dev_err(skl->dev, - "query module info failed\n"); - return ret; - } - - skl_tplg_add_moduleid_in_bind_params(skl, w); - } - } - - return ret; -} - -static int skl_platform_soc_probe(struct snd_soc_component *component) -{ - struct hdac_bus *bus = dev_get_drvdata(component->dev); - struct skl_dev *skl = bus_to_skl(bus); - const struct skl_dsp_ops *ops; - int ret; - - ret = pm_runtime_resume_and_get(component->dev); - if (ret < 0 && ret != -EACCES) - return ret; - - if (bus->ppcap) { - skl->component = component; - - /* init debugfs */ - skl->debugfs = skl_debugfs_init(skl); - - ret = skl_tplg_init(component, bus); - if (ret < 0) { - dev_err(component->dev, "Failed to init topology!\n"); - return ret; - } - - /* load the firmwares, since all is set */ - ops = skl_get_dsp_ops(skl->pci->device); - if (!ops) - return -EIO; - - /* - * Disable dynamic clock and power gating during firmware - * and library download - */ - skl->enable_miscbdcge(component->dev, false); - skl->clock_power_gating(component->dev, false); - - ret = ops->init_fw(component->dev, skl); - skl->enable_miscbdcge(component->dev, true); - skl->clock_power_gating(component->dev, true); - if (ret < 0) { - dev_err(component->dev, "Failed to boot first fw: %d\n", ret); - return ret; - } - skl_populate_modules(skl); - skl->update_d0i3c = skl_update_d0i3c; - - if (skl->cfg.astate_cfg != NULL) { - skl_dsp_set_astate_cfg(skl, - skl->cfg.astate_cfg->count, - skl->cfg.astate_cfg); - } - } - pm_runtime_mark_last_busy(component->dev); - pm_runtime_put_autosuspend(component->dev); - - return 0; -} - -static void skl_platform_soc_remove(struct snd_soc_component *component) -{ - struct hdac_bus *bus = dev_get_drvdata(component->dev); - struct skl_dev *skl = bus_to_skl(bus); - - skl_tplg_exit(component, bus); - - skl_debugfs_exit(skl); -} - -static const struct snd_soc_component_driver skl_component = { - .name = "pcm", - .probe = skl_platform_soc_probe, - .remove = skl_platform_soc_remove, - .open = skl_platform_soc_open, - .trigger = skl_platform_soc_trigger, - .pointer = skl_platform_soc_pointer, - .get_time_info = skl_platform_soc_get_time_info, - .pcm_construct = skl_platform_soc_new, - .module_get_upon_open = 1, /* increment refcount when a pcm is opened */ -}; - -int skl_platform_register(struct device *dev) -{ - int ret; - struct snd_soc_dai_driver *dais; - int num_dais = ARRAY_SIZE(skl_platform_dai); - struct hdac_bus *bus = dev_get_drvdata(dev); - struct skl_dev *skl = bus_to_skl(bus); - - skl->dais = kmemdup(skl_platform_dai, sizeof(skl_platform_dai), - GFP_KERNEL); - if (!skl->dais) { - ret = -ENOMEM; - goto err; - } - - if (!skl->use_tplg_pcm) { - dais = krealloc(skl->dais, sizeof(skl_fe_dai) + - sizeof(skl_platform_dai), GFP_KERNEL); - if (!dais) { - kfree(skl->dais); - ret = -ENOMEM; - goto err; - } - - skl->dais = dais; - memcpy(&skl->dais[ARRAY_SIZE(skl_platform_dai)], skl_fe_dai, - sizeof(skl_fe_dai)); - num_dais += ARRAY_SIZE(skl_fe_dai); - } - - ret = devm_snd_soc_register_component(dev, &skl_component, - skl->dais, num_dais); - if (ret) { - kfree(skl->dais); - dev_err(dev, "soc component registration failed %d\n", ret); - } -err: - return ret; -} - -int skl_platform_unregister(struct device *dev) -{ - struct hdac_bus *bus = dev_get_drvdata(dev); - struct skl_dev *skl = bus_to_skl(bus); - struct skl_module_deferred_bind *modules, *tmp; - - list_for_each_entry_safe(modules, tmp, &skl->bind_list, node) { - list_del(&modules->node); - kfree(modules); - } - - kfree(skl->dais); - - return 0; -} diff --git a/sound/soc/intel/skylake/skl-ssp-clk.c b/sound/soc/intel/skylake/skl-ssp-clk.c deleted file mode 100644 index 50e93c3707e8be..00000000000000 --- a/sound/soc/intel/skylake/skl-ssp-clk.c +++ /dev/null @@ -1,428 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -// Copyright(c) 2015-17 Intel Corporation - -/* - * skl-ssp-clk.c - ASoC skylake ssp clock driver - */ - -#include -#include -#include -#include -#include -#include -#include -#include "skl.h" -#include "skl-ssp-clk.h" -#include "skl-topology.h" - -#define to_skl_clk(_hw) container_of(_hw, struct skl_clk, hw) - -struct skl_clk_parent { - struct clk_hw *hw; - struct clk_lookup *lookup; -}; - -struct skl_clk { - struct clk_hw hw; - struct clk_lookup *lookup; - unsigned long rate; - struct skl_clk_pdata *pdata; - u32 id; -}; - -struct skl_clk_data { - struct skl_clk_parent parent[SKL_MAX_CLK_SRC]; - struct skl_clk *clk[SKL_MAX_CLK_CNT]; - u8 avail_clk_cnt; -}; - -static int skl_get_clk_type(u32 index) -{ - switch (index) { - case 0 ... (SKL_SCLK_OFS - 1): - return SKL_MCLK; - - case SKL_SCLK_OFS ... (SKL_SCLKFS_OFS - 1): - return SKL_SCLK; - - case SKL_SCLKFS_OFS ... (SKL_MAX_CLK_CNT - 1): - return SKL_SCLK_FS; - - default: - return -EINVAL; - } -} - -static int skl_get_vbus_id(u32 index, u8 clk_type) -{ - switch (clk_type) { - case SKL_MCLK: - return index; - - case SKL_SCLK: - return index - SKL_SCLK_OFS; - - case SKL_SCLK_FS: - return index - SKL_SCLKFS_OFS; - - default: - return -EINVAL; - } -} - -static void skl_fill_clk_ipc(struct skl_clk_rate_cfg_table *rcfg, u8 clk_type) -{ - struct nhlt_fmt_cfg *fmt_cfg; - union skl_clk_ctrl_ipc *ipc; - struct wav_fmt *wfmt; - - if (!rcfg) - return; - - ipc = &rcfg->dma_ctl_ipc; - if (clk_type == SKL_SCLK_FS) { - fmt_cfg = (struct nhlt_fmt_cfg *)rcfg->config; - wfmt = &fmt_cfg->fmt_ext.fmt; - - /* Remove TLV Header size */ - ipc->sclk_fs.hdr.size = sizeof(struct skl_dmactrl_sclkfs_cfg) - - sizeof(struct skl_tlv_hdr); - ipc->sclk_fs.sampling_frequency = wfmt->samples_per_sec; - ipc->sclk_fs.bit_depth = wfmt->bits_per_sample; - ipc->sclk_fs.valid_bit_depth = - fmt_cfg->fmt_ext.sample.valid_bits_per_sample; - ipc->sclk_fs.number_of_channels = wfmt->channels; - } else { - ipc->mclk.hdr.type = DMA_CLK_CONTROLS; - /* Remove TLV Header size */ - ipc->mclk.hdr.size = sizeof(struct skl_dmactrl_mclk_cfg) - - sizeof(struct skl_tlv_hdr); - } -} - -/* Sends dma control IPC to turn the clock ON/OFF */ -static int skl_send_clk_dma_control(struct skl_dev *skl, - struct skl_clk_rate_cfg_table *rcfg, - u32 vbus_id, u8 clk_type, - bool enable) -{ - struct nhlt_specific_cfg *sp_cfg; - u32 i2s_config_size, node_id = 0; - struct nhlt_fmt_cfg *fmt_cfg; - union skl_clk_ctrl_ipc *ipc; - void *i2s_config = NULL; - u8 *data, size; - int ret; - - if (!rcfg) - return -EIO; - - ipc = &rcfg->dma_ctl_ipc; - fmt_cfg = (struct nhlt_fmt_cfg *)rcfg->config; - sp_cfg = &fmt_cfg->config; - - if (clk_type == SKL_SCLK_FS) { - ipc->sclk_fs.hdr.type = - enable ? DMA_TRANSMITION_START : DMA_TRANSMITION_STOP; - data = (u8 *)&ipc->sclk_fs; - size = sizeof(struct skl_dmactrl_sclkfs_cfg); - } else { - /* 1 to enable mclk, 0 to enable sclk */ - if (clk_type == SKL_SCLK) - ipc->mclk.mclk = 0; - else - ipc->mclk.mclk = 1; - - ipc->mclk.keep_running = enable; - ipc->mclk.warm_up_over = enable; - ipc->mclk.clk_stop_over = !enable; - data = (u8 *)&ipc->mclk; - size = sizeof(struct skl_dmactrl_mclk_cfg); - } - - i2s_config_size = sp_cfg->size + size; - i2s_config = kzalloc(i2s_config_size, GFP_KERNEL); - if (!i2s_config) - return -ENOMEM; - - /* copy blob */ - memcpy(i2s_config, sp_cfg->caps, sp_cfg->size); - - /* copy additional dma controls information */ - memcpy(i2s_config + sp_cfg->size, data, size); - - node_id = ((SKL_DMA_I2S_LINK_INPUT_CLASS << 8) | (vbus_id << 4)); - ret = skl_dsp_set_dma_control(skl, (u32 *)i2s_config, - i2s_config_size, node_id); - kfree(i2s_config); - - return ret; -} - -static struct skl_clk_rate_cfg_table *skl_get_rate_cfg( - struct skl_clk_rate_cfg_table *rcfg, - unsigned long rate) -{ - int i; - - for (i = 0; (i < SKL_MAX_CLK_RATES) && rcfg[i].rate; i++) { - if (rcfg[i].rate == rate) - return &rcfg[i]; - } - - return NULL; -} - -static int skl_clk_change_status(struct skl_clk *clkdev, - bool enable) -{ - struct skl_clk_rate_cfg_table *rcfg; - int vbus_id, clk_type; - - clk_type = skl_get_clk_type(clkdev->id); - if (clk_type < 0) - return clk_type; - - vbus_id = skl_get_vbus_id(clkdev->id, clk_type); - if (vbus_id < 0) - return vbus_id; - - rcfg = skl_get_rate_cfg(clkdev->pdata->ssp_clks[clkdev->id].rate_cfg, - clkdev->rate); - if (!rcfg) - return -EINVAL; - - return skl_send_clk_dma_control(clkdev->pdata->pvt_data, rcfg, - vbus_id, clk_type, enable); -} - -static int skl_clk_prepare(struct clk_hw *hw) -{ - struct skl_clk *clkdev = to_skl_clk(hw); - - return skl_clk_change_status(clkdev, true); -} - -static void skl_clk_unprepare(struct clk_hw *hw) -{ - struct skl_clk *clkdev = to_skl_clk(hw); - - skl_clk_change_status(clkdev, false); -} - -static int skl_clk_set_rate(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) -{ - struct skl_clk *clkdev = to_skl_clk(hw); - struct skl_clk_rate_cfg_table *rcfg; - int clk_type; - - if (!rate) - return -EINVAL; - - rcfg = skl_get_rate_cfg(clkdev->pdata->ssp_clks[clkdev->id].rate_cfg, - rate); - if (!rcfg) - return -EINVAL; - - clk_type = skl_get_clk_type(clkdev->id); - if (clk_type < 0) - return clk_type; - - skl_fill_clk_ipc(rcfg, clk_type); - clkdev->rate = rate; - - return 0; -} - -static unsigned long skl_clk_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - struct skl_clk *clkdev = to_skl_clk(hw); - - if (clkdev->rate) - return clkdev->rate; - - return 0; -} - -/* Not supported by clk driver. Implemented to satisfy clk fw */ -static long skl_clk_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *parent_rate) -{ - return rate; -} - -/* - * prepare/unprepare are used instead of enable/disable as IPC will be sent - * in non-atomic context. - */ -static const struct clk_ops skl_clk_ops = { - .prepare = skl_clk_prepare, - .unprepare = skl_clk_unprepare, - .set_rate = skl_clk_set_rate, - .round_rate = skl_clk_round_rate, - .recalc_rate = skl_clk_recalc_rate, -}; - -static void unregister_parent_src_clk(struct skl_clk_parent *pclk, - unsigned int id) -{ - while (id--) { - clkdev_drop(pclk[id].lookup); - clk_hw_unregister_fixed_rate(pclk[id].hw); - } -} - -static void unregister_src_clk(struct skl_clk_data *dclk) -{ - while (dclk->avail_clk_cnt--) - clkdev_drop(dclk->clk[dclk->avail_clk_cnt]->lookup); -} - -static int skl_register_parent_clks(struct device *dev, - struct skl_clk_parent *parent, - struct skl_clk_parent_src *pclk) -{ - int i, ret; - - for (i = 0; i < SKL_MAX_CLK_SRC; i++) { - - /* Register Parent clock */ - parent[i].hw = clk_hw_register_fixed_rate(dev, pclk[i].name, - pclk[i].parent_name, 0, pclk[i].rate); - if (IS_ERR(parent[i].hw)) { - ret = PTR_ERR(parent[i].hw); - goto err; - } - - parent[i].lookup = clkdev_hw_create(parent[i].hw, pclk[i].name, - NULL); - if (!parent[i].lookup) { - clk_hw_unregister_fixed_rate(parent[i].hw); - ret = -ENOMEM; - goto err; - } - } - - return 0; -err: - unregister_parent_src_clk(parent, i); - return ret; -} - -/* Assign fmt_config to clk_data */ -static struct skl_clk *register_skl_clk(struct device *dev, - struct skl_ssp_clk *clk, - struct skl_clk_pdata *clk_pdata, int id) -{ - struct clk_init_data init; - struct skl_clk *clkdev; - int ret; - - clkdev = devm_kzalloc(dev, sizeof(*clkdev), GFP_KERNEL); - if (!clkdev) - return ERR_PTR(-ENOMEM); - - init.name = clk->name; - init.ops = &skl_clk_ops; - init.flags = CLK_SET_RATE_GATE; - init.parent_names = &clk->parent_name; - init.num_parents = 1; - clkdev->hw.init = &init; - clkdev->pdata = clk_pdata; - - clkdev->id = id; - ret = devm_clk_hw_register(dev, &clkdev->hw); - if (ret) { - clkdev = ERR_PTR(ret); - return clkdev; - } - - clkdev->lookup = clkdev_hw_create(&clkdev->hw, init.name, NULL); - if (!clkdev->lookup) - clkdev = ERR_PTR(-ENOMEM); - - return clkdev; -} - -static int skl_clk_dev_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct device *parent_dev = dev->parent; - struct skl_clk_parent_src *parent_clks; - struct skl_clk_pdata *clk_pdata; - struct skl_clk_data *data; - struct skl_ssp_clk *clks; - int ret, i; - - clk_pdata = dev_get_platdata(&pdev->dev); - parent_clks = clk_pdata->parent_clks; - clks = clk_pdata->ssp_clks; - if (!parent_clks || !clks) - return -EIO; - - data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); - if (!data) - return -ENOMEM; - - /* Register Parent clock */ - ret = skl_register_parent_clks(parent_dev, data->parent, parent_clks); - if (ret < 0) - return ret; - - for (i = 0; i < clk_pdata->num_clks; i++) { - /* - * Only register valid clocks - * i.e. for which nhlt entry is present. - */ - if (clks[i].rate_cfg[0].rate == 0) - continue; - - data->clk[data->avail_clk_cnt] = register_skl_clk(dev, - &clks[i], clk_pdata, i); - - if (IS_ERR(data->clk[data->avail_clk_cnt])) { - ret = PTR_ERR(data->clk[data->avail_clk_cnt]); - goto err_unreg_skl_clk; - } - - data->avail_clk_cnt++; - } - - platform_set_drvdata(pdev, data); - - return 0; - -err_unreg_skl_clk: - unregister_src_clk(data); - unregister_parent_src_clk(data->parent, SKL_MAX_CLK_SRC); - - return ret; -} - -static void skl_clk_dev_remove(struct platform_device *pdev) -{ - struct skl_clk_data *data; - - data = platform_get_drvdata(pdev); - unregister_src_clk(data); - unregister_parent_src_clk(data->parent, SKL_MAX_CLK_SRC); -} - -static struct platform_driver skl_clk_driver = { - .driver = { - .name = "skl-ssp-clk", - }, - .probe = skl_clk_dev_probe, - .remove_new = skl_clk_dev_remove, -}; - -module_platform_driver(skl_clk_driver); - -MODULE_DESCRIPTION("Skylake clock driver"); -MODULE_AUTHOR("Jaikrishna Nemallapudi "); -MODULE_AUTHOR("Subhransu S. Prusty "); -MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("platform:skl-ssp-clk"); diff --git a/sound/soc/intel/skylake/skl-ssp-clk.h b/sound/soc/intel/skylake/skl-ssp-clk.h deleted file mode 100644 index b7852c7f277b58..00000000000000 --- a/sound/soc/intel/skylake/skl-ssp-clk.h +++ /dev/null @@ -1,108 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * skl-ssp-clk.h - Skylake ssp clock information and ipc structure - * - * Copyright (C) 2017 Intel Corp - * Author: Jaikrishna Nemallapudi - * Author: Subhransu S. Prusty - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ - -#ifndef SOUND_SOC_SKL_SSP_CLK_H -#define SOUND_SOC_SKL_SSP_CLK_H - -#define SKL_MAX_SSP 6 -/* xtal/cardinal/pll, parent of ssp clocks and mclk */ -#define SKL_MAX_CLK_SRC 3 -#define SKL_MAX_SSP_CLK_TYPES 3 /* mclk, sclk, sclkfs */ - -#define SKL_MAX_CLK_CNT (SKL_MAX_SSP * SKL_MAX_SSP_CLK_TYPES) - -/* Max number of configurations supported for each clock */ -#define SKL_MAX_CLK_RATES 10 - -#define SKL_SCLK_OFS SKL_MAX_SSP -#define SKL_SCLKFS_OFS (SKL_SCLK_OFS + SKL_MAX_SSP) - -enum skl_clk_type { - SKL_MCLK, - SKL_SCLK, - SKL_SCLK_FS, -}; - -enum skl_clk_src_type { - SKL_XTAL, - SKL_CARDINAL, - SKL_PLL, -}; - -struct skl_clk_parent_src { - u8 clk_id; - const char *name; - unsigned long rate; - const char *parent_name; -}; - -struct skl_tlv_hdr { - u32 type; - u32 size; -}; - -struct skl_dmactrl_mclk_cfg { - struct skl_tlv_hdr hdr; - /* DMA Clk TLV params */ - u32 clk_warm_up:16; - u32 mclk:1; - u32 warm_up_over:1; - u32 rsvd0:14; - u32 clk_stop_delay:16; - u32 keep_running:1; - u32 clk_stop_over:1; - u32 rsvd1:14; -}; - -struct skl_dmactrl_sclkfs_cfg { - struct skl_tlv_hdr hdr; - /* DMA SClk&FS TLV params */ - u32 sampling_frequency; - u32 bit_depth; - u32 channel_map; - u32 channel_config; - u32 interleaving_style; - u32 number_of_channels : 8; - u32 valid_bit_depth : 8; - u32 sample_type : 8; - u32 reserved : 8; -}; - -union skl_clk_ctrl_ipc { - struct skl_dmactrl_mclk_cfg mclk; - struct skl_dmactrl_sclkfs_cfg sclk_fs; -}; - -struct skl_clk_rate_cfg_table { - unsigned long rate; - union skl_clk_ctrl_ipc dma_ctl_ipc; - void *config; -}; - -/* - * rate for mclk will be in rates[0]. For sclk and sclkfs, rates[] store - * all possible clocks ssp can generate for that platform. - */ -struct skl_ssp_clk { - const char *name; - const char *parent_name; - struct skl_clk_rate_cfg_table rate_cfg[SKL_MAX_CLK_RATES]; -}; - -struct skl_clk_pdata { - struct skl_clk_parent_src *parent_clks; - int num_clks; - struct skl_ssp_clk *ssp_clks; - void *pvt_data; -}; - -#endif /* SOUND_SOC_SKL_SSP_CLK_H */ diff --git a/sound/soc/intel/skylake/skl-sst-cldma.c b/sound/soc/intel/skylake/skl-sst-cldma.c deleted file mode 100644 index b0204ea00f07f8..00000000000000 --- a/sound/soc/intel/skylake/skl-sst-cldma.c +++ /dev/null @@ -1,373 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * skl-sst-cldma.c - Code Loader DMA handler - * - * Copyright (C) 2015, Intel Corporation. - * Author: Subhransu S. Prusty - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ - -#include -#include -#include -#include -#include -#include "../common/sst-dsp.h" -#include "../common/sst-dsp-priv.h" - -static void skl_cldma_int_enable(struct sst_dsp *ctx) -{ - sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPIC, - SKL_ADSPIC_CL_DMA, SKL_ADSPIC_CL_DMA); -} - -void skl_cldma_int_disable(struct sst_dsp *ctx) -{ - sst_dsp_shim_update_bits_unlocked(ctx, - SKL_ADSP_REG_ADSPIC, SKL_ADSPIC_CL_DMA, 0); -} - -static void skl_cldma_stream_run(struct sst_dsp *ctx, bool enable) -{ - unsigned char val; - int timeout; - - sst_dsp_shim_update_bits_unlocked(ctx, - SKL_ADSP_REG_CL_SD_CTL, - CL_SD_CTL_RUN_MASK, CL_SD_CTL_RUN(enable)); - - udelay(3); - timeout = 300; - do { - /* waiting for hardware to report that the stream Run bit set */ - val = sst_dsp_shim_read(ctx, SKL_ADSP_REG_CL_SD_CTL) & - CL_SD_CTL_RUN_MASK; - if (enable && val) - break; - else if (!enable && !val) - break; - udelay(3); - } while (--timeout); - - if (timeout == 0) - dev_err(ctx->dev, "Failed to set Run bit=%d enable=%d\n", val, enable); -} - -static void skl_cldma_stream_clear(struct sst_dsp *ctx) -{ - /* make sure Run bit is cleared before setting stream register */ - skl_cldma_stream_run(ctx, 0); - - sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_CL_SD_CTL, - CL_SD_CTL_IOCE_MASK, CL_SD_CTL_IOCE(0)); - sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_CL_SD_CTL, - CL_SD_CTL_FEIE_MASK, CL_SD_CTL_FEIE(0)); - sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_CL_SD_CTL, - CL_SD_CTL_DEIE_MASK, CL_SD_CTL_DEIE(0)); - sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_CL_SD_CTL, - CL_SD_CTL_STRM_MASK, CL_SD_CTL_STRM(0)); - - sst_dsp_shim_write(ctx, SKL_ADSP_REG_CL_SD_BDLPL, CL_SD_BDLPLBA(0)); - sst_dsp_shim_write(ctx, SKL_ADSP_REG_CL_SD_BDLPU, 0); - - sst_dsp_shim_write(ctx, SKL_ADSP_REG_CL_SD_CBL, 0); - sst_dsp_shim_write(ctx, SKL_ADSP_REG_CL_SD_LVI, 0); -} - -/* Code loader helper APIs */ -static void skl_cldma_setup_bdle(struct sst_dsp *ctx, - struct snd_dma_buffer *dmab_data, - __le32 **bdlp, int size, int with_ioc) -{ - __le32 *bdl = *bdlp; - int remaining = ctx->cl_dev.bufsize; - int offset = 0; - - ctx->cl_dev.frags = 0; - while (remaining > 0) { - phys_addr_t addr; - int chunk; - - addr = snd_sgbuf_get_addr(dmab_data, offset); - bdl[0] = cpu_to_le32(lower_32_bits(addr)); - bdl[1] = cpu_to_le32(upper_32_bits(addr)); - chunk = snd_sgbuf_get_chunk_size(dmab_data, offset, size); - bdl[2] = cpu_to_le32(chunk); - - remaining -= chunk; - bdl[3] = (remaining > 0) ? 0 : cpu_to_le32(0x01); - - bdl += 4; - offset += chunk; - ctx->cl_dev.frags++; - } -} - -/* - * Setup controller - * Configure the registers to update the dma buffer address and - * enable interrupts. - * Note: Using the channel 1 for transfer - */ -static void skl_cldma_setup_controller(struct sst_dsp *ctx, - struct snd_dma_buffer *dmab_bdl, unsigned int max_size, - u32 count) -{ - skl_cldma_stream_clear(ctx); - sst_dsp_shim_write(ctx, SKL_ADSP_REG_CL_SD_BDLPL, - CL_SD_BDLPLBA(dmab_bdl->addr)); - sst_dsp_shim_write(ctx, SKL_ADSP_REG_CL_SD_BDLPU, - CL_SD_BDLPUBA(dmab_bdl->addr)); - - sst_dsp_shim_write(ctx, SKL_ADSP_REG_CL_SD_CBL, max_size); - sst_dsp_shim_write(ctx, SKL_ADSP_REG_CL_SD_LVI, count - 1); - sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_CL_SD_CTL, - CL_SD_CTL_IOCE_MASK, CL_SD_CTL_IOCE(1)); - sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_CL_SD_CTL, - CL_SD_CTL_FEIE_MASK, CL_SD_CTL_FEIE(1)); - sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_CL_SD_CTL, - CL_SD_CTL_DEIE_MASK, CL_SD_CTL_DEIE(1)); - sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_CL_SD_CTL, - CL_SD_CTL_STRM_MASK, CL_SD_CTL_STRM(FW_CL_STREAM_NUMBER)); -} - -static void skl_cldma_setup_spb(struct sst_dsp *ctx, - unsigned int size, bool enable) -{ - if (enable) - sst_dsp_shim_update_bits_unlocked(ctx, - SKL_ADSP_REG_CL_SPBFIFO_SPBFCCTL, - CL_SPBFIFO_SPBFCCTL_SPIBE_MASK, - CL_SPBFIFO_SPBFCCTL_SPIBE(1)); - - sst_dsp_shim_write_unlocked(ctx, SKL_ADSP_REG_CL_SPBFIFO_SPIB, size); -} - -static void skl_cldma_cleanup_spb(struct sst_dsp *ctx) -{ - sst_dsp_shim_update_bits_unlocked(ctx, - SKL_ADSP_REG_CL_SPBFIFO_SPBFCCTL, - CL_SPBFIFO_SPBFCCTL_SPIBE_MASK, - CL_SPBFIFO_SPBFCCTL_SPIBE(0)); - - sst_dsp_shim_write_unlocked(ctx, SKL_ADSP_REG_CL_SPBFIFO_SPIB, 0); -} - -static void skl_cldma_cleanup(struct sst_dsp *ctx) -{ - skl_cldma_cleanup_spb(ctx); - skl_cldma_stream_clear(ctx); - - ctx->dsp_ops.free_dma_buf(ctx->dev, &ctx->cl_dev.dmab_data); - ctx->dsp_ops.free_dma_buf(ctx->dev, &ctx->cl_dev.dmab_bdl); -} - -int skl_cldma_wait_interruptible(struct sst_dsp *ctx) -{ - int ret = 0; - - if (!wait_event_timeout(ctx->cl_dev.wait_queue, - ctx->cl_dev.wait_condition, - msecs_to_jiffies(SKL_WAIT_TIMEOUT))) { - dev_err(ctx->dev, "%s: Wait timeout\n", __func__); - ret = -EIO; - goto cleanup; - } - - dev_dbg(ctx->dev, "%s: Event wake\n", __func__); - if (ctx->cl_dev.wake_status != SKL_CL_DMA_BUF_COMPLETE) { - dev_err(ctx->dev, "%s: DMA Error\n", __func__); - ret = -EIO; - } - -cleanup: - ctx->cl_dev.wake_status = SKL_CL_DMA_STATUS_NONE; - return ret; -} - -static void skl_cldma_stop(struct sst_dsp *ctx) -{ - skl_cldma_stream_run(ctx, false); -} - -static void skl_cldma_fill_buffer(struct sst_dsp *ctx, unsigned int size, - const void *curr_pos, bool intr_enable, bool trigger) -{ - dev_dbg(ctx->dev, "Size: %x, intr_enable: %d\n", size, intr_enable); - dev_dbg(ctx->dev, "buf_pos_index:%d, trigger:%d\n", - ctx->cl_dev.dma_buffer_offset, trigger); - dev_dbg(ctx->dev, "spib position: %d\n", ctx->cl_dev.curr_spib_pos); - - /* - * Check if the size exceeds buffer boundary. If it exceeds - * max_buffer size, then copy till buffer size and then copy - * remaining buffer from the start of ring buffer. - */ - if (ctx->cl_dev.dma_buffer_offset + size > ctx->cl_dev.bufsize) { - unsigned int size_b = ctx->cl_dev.bufsize - - ctx->cl_dev.dma_buffer_offset; - memcpy(ctx->cl_dev.dmab_data.area + ctx->cl_dev.dma_buffer_offset, - curr_pos, size_b); - size -= size_b; - curr_pos += size_b; - ctx->cl_dev.dma_buffer_offset = 0; - } - - memcpy(ctx->cl_dev.dmab_data.area + ctx->cl_dev.dma_buffer_offset, - curr_pos, size); - - if (ctx->cl_dev.curr_spib_pos == ctx->cl_dev.bufsize) - ctx->cl_dev.dma_buffer_offset = 0; - else - ctx->cl_dev.dma_buffer_offset = ctx->cl_dev.curr_spib_pos; - - ctx->cl_dev.wait_condition = false; - - if (intr_enable) - skl_cldma_int_enable(ctx); - - ctx->cl_dev.ops.cl_setup_spb(ctx, ctx->cl_dev.curr_spib_pos, trigger); - if (trigger) - ctx->cl_dev.ops.cl_trigger(ctx, true); -} - -/* - * The CL dma doesn't have any way to update the transfer status until a BDL - * buffer is fully transferred - * - * So Copying is divided in two parts. - * 1. Interrupt on buffer done where the size to be transferred is more than - * ring buffer size. - * 2. Polling on fw register to identify if data left to transferred doesn't - * fill the ring buffer. Caller takes care of polling the required status - * register to identify the transfer status. - * 3. if wait flag is set, waits for DBL interrupt to copy the next chunk till - * bytes_left is 0. - * if wait flag is not set, doesn't wait for BDL interrupt. after ccopying - * the first chunk return the no of bytes_left to be copied. - */ -static int -skl_cldma_copy_to_buf(struct sst_dsp *ctx, const void *bin, - u32 total_size, bool wait) -{ - int ret; - bool start = true; - unsigned int excess_bytes; - u32 size; - unsigned int bytes_left = total_size; - const void *curr_pos = bin; - - if (total_size <= 0) - return -EINVAL; - - dev_dbg(ctx->dev, "%s: Total binary size: %u\n", __func__, bytes_left); - - while (bytes_left) { - if (bytes_left > ctx->cl_dev.bufsize) { - - /* - * dma transfers only till the write pointer as - * updated in spib - */ - if (ctx->cl_dev.curr_spib_pos == 0) - ctx->cl_dev.curr_spib_pos = ctx->cl_dev.bufsize; - - size = ctx->cl_dev.bufsize; - skl_cldma_fill_buffer(ctx, size, curr_pos, true, start); - - if (wait) { - start = false; - ret = skl_cldma_wait_interruptible(ctx); - if (ret < 0) { - skl_cldma_stop(ctx); - return ret; - } - } - } else { - skl_cldma_int_disable(ctx); - - if ((ctx->cl_dev.curr_spib_pos + bytes_left) - <= ctx->cl_dev.bufsize) { - ctx->cl_dev.curr_spib_pos += bytes_left; - } else { - excess_bytes = bytes_left - - (ctx->cl_dev.bufsize - - ctx->cl_dev.curr_spib_pos); - ctx->cl_dev.curr_spib_pos = excess_bytes; - } - - size = bytes_left; - skl_cldma_fill_buffer(ctx, size, - curr_pos, false, start); - } - bytes_left -= size; - curr_pos = curr_pos + size; - if (!wait) - return bytes_left; - } - - return bytes_left; -} - -void skl_cldma_process_intr(struct sst_dsp *ctx) -{ - u8 cl_dma_intr_status; - - cl_dma_intr_status = - sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_CL_SD_STS); - - if (!(cl_dma_intr_status & SKL_CL_DMA_SD_INT_COMPLETE)) - ctx->cl_dev.wake_status = SKL_CL_DMA_ERR; - else - ctx->cl_dev.wake_status = SKL_CL_DMA_BUF_COMPLETE; - - ctx->cl_dev.wait_condition = true; - wake_up(&ctx->cl_dev.wait_queue); -} - -int skl_cldma_prepare(struct sst_dsp *ctx) -{ - int ret; - __le32 *bdl; - - ctx->cl_dev.bufsize = SKL_MAX_BUFFER_SIZE; - - /* Allocate cl ops */ - ctx->cl_dev.ops.cl_setup_bdle = skl_cldma_setup_bdle; - ctx->cl_dev.ops.cl_setup_controller = skl_cldma_setup_controller; - ctx->cl_dev.ops.cl_setup_spb = skl_cldma_setup_spb; - ctx->cl_dev.ops.cl_cleanup_spb = skl_cldma_cleanup_spb; - ctx->cl_dev.ops.cl_trigger = skl_cldma_stream_run; - ctx->cl_dev.ops.cl_cleanup_controller = skl_cldma_cleanup; - ctx->cl_dev.ops.cl_copy_to_dmabuf = skl_cldma_copy_to_buf; - ctx->cl_dev.ops.cl_stop_dma = skl_cldma_stop; - - /* Allocate buffer*/ - ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV_SG, ctx->dev, ctx->cl_dev.bufsize, - &ctx->cl_dev.dmab_data); - if (ret < 0) { - dev_err(ctx->dev, "Alloc buffer for base fw failed: %x\n", ret); - return ret; - } - - /* Setup Code loader BDL */ - ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, ctx->dev, BDL_SIZE, &ctx->cl_dev.dmab_bdl); - if (ret < 0) { - dev_err(ctx->dev, "Alloc buffer for blde failed: %x\n", ret); - ctx->dsp_ops.free_dma_buf(ctx->dev, &ctx->cl_dev.dmab_data); - return ret; - } - bdl = (__le32 *)ctx->cl_dev.dmab_bdl.area; - - /* Allocate BDLs */ - ctx->cl_dev.ops.cl_setup_bdle(ctx, &ctx->cl_dev.dmab_data, - &bdl, ctx->cl_dev.bufsize, 1); - ctx->cl_dev.ops.cl_setup_controller(ctx, &ctx->cl_dev.dmab_bdl, - ctx->cl_dev.bufsize, ctx->cl_dev.frags); - - ctx->cl_dev.curr_spib_pos = 0; - ctx->cl_dev.dma_buffer_offset = 0; - init_waitqueue_head(&ctx->cl_dev.wait_queue); - - return ret; -} diff --git a/sound/soc/intel/skylake/skl-sst-cldma.h b/sound/soc/intel/skylake/skl-sst-cldma.h deleted file mode 100644 index d5e285a69baa49..00000000000000 --- a/sound/soc/intel/skylake/skl-sst-cldma.h +++ /dev/null @@ -1,243 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Intel Code Loader DMA support - * - * Copyright (C) 2015, Intel Corporation. - */ - -#ifndef SKL_SST_CLDMA_H_ -#define SKL_SST_CLDMA_H_ - -#define FW_CL_STREAM_NUMBER 0x1 - -#define DMA_ADDRESS_128_BITS_ALIGNMENT 7 -#define BDL_ALIGN(x) (x >> DMA_ADDRESS_128_BITS_ALIGNMENT) - -#define SKL_ADSPIC_CL_DMA 0x2 -#define SKL_ADSPIS_CL_DMA 0x2 -#define SKL_CL_DMA_SD_INT_DESC_ERR 0x10 /* Descriptor error interrupt */ -#define SKL_CL_DMA_SD_INT_FIFO_ERR 0x08 /* FIFO error interrupt */ -#define SKL_CL_DMA_SD_INT_COMPLETE 0x04 /* Buffer completion interrupt */ - -/* Intel HD Audio Code Loader DMA Registers */ - -#define HDA_ADSP_LOADER_BASE 0x80 - -/* Stream Registers */ -#define SKL_ADSP_REG_CL_SD_CTL (HDA_ADSP_LOADER_BASE + 0x00) -#define SKL_ADSP_REG_CL_SD_STS (HDA_ADSP_LOADER_BASE + 0x03) -#define SKL_ADSP_REG_CL_SD_LPIB (HDA_ADSP_LOADER_BASE + 0x04) -#define SKL_ADSP_REG_CL_SD_CBL (HDA_ADSP_LOADER_BASE + 0x08) -#define SKL_ADSP_REG_CL_SD_LVI (HDA_ADSP_LOADER_BASE + 0x0c) -#define SKL_ADSP_REG_CL_SD_FIFOW (HDA_ADSP_LOADER_BASE + 0x0e) -#define SKL_ADSP_REG_CL_SD_FIFOSIZE (HDA_ADSP_LOADER_BASE + 0x10) -#define SKL_ADSP_REG_CL_SD_FORMAT (HDA_ADSP_LOADER_BASE + 0x12) -#define SKL_ADSP_REG_CL_SD_FIFOL (HDA_ADSP_LOADER_BASE + 0x14) -#define SKL_ADSP_REG_CL_SD_BDLPL (HDA_ADSP_LOADER_BASE + 0x18) -#define SKL_ADSP_REG_CL_SD_BDLPU (HDA_ADSP_LOADER_BASE + 0x1c) - -/* CL: Software Position Based FIFO Capability Registers */ -#define SKL_ADSP_REG_CL_SPBFIFO (HDA_ADSP_LOADER_BASE + 0x20) -#define SKL_ADSP_REG_CL_SPBFIFO_SPBFCH (SKL_ADSP_REG_CL_SPBFIFO + 0x0) -#define SKL_ADSP_REG_CL_SPBFIFO_SPBFCCTL (SKL_ADSP_REG_CL_SPBFIFO + 0x4) -#define SKL_ADSP_REG_CL_SPBFIFO_SPIB (SKL_ADSP_REG_CL_SPBFIFO + 0x8) -#define SKL_ADSP_REG_CL_SPBFIFO_MAXFIFOS (SKL_ADSP_REG_CL_SPBFIFO + 0xc) - -/* CL: Stream Descriptor x Control */ - -/* Stream Reset */ -#define CL_SD_CTL_SRST_SHIFT 0 -#define CL_SD_CTL_SRST_MASK (1 << CL_SD_CTL_SRST_SHIFT) -#define CL_SD_CTL_SRST(x) \ - ((x << CL_SD_CTL_SRST_SHIFT) & CL_SD_CTL_SRST_MASK) - -/* Stream Run */ -#define CL_SD_CTL_RUN_SHIFT 1 -#define CL_SD_CTL_RUN_MASK (1 << CL_SD_CTL_RUN_SHIFT) -#define CL_SD_CTL_RUN(x) \ - ((x << CL_SD_CTL_RUN_SHIFT) & CL_SD_CTL_RUN_MASK) - -/* Interrupt On Completion Enable */ -#define CL_SD_CTL_IOCE_SHIFT 2 -#define CL_SD_CTL_IOCE_MASK (1 << CL_SD_CTL_IOCE_SHIFT) -#define CL_SD_CTL_IOCE(x) \ - ((x << CL_SD_CTL_IOCE_SHIFT) & CL_SD_CTL_IOCE_MASK) - -/* FIFO Error Interrupt Enable */ -#define CL_SD_CTL_FEIE_SHIFT 3 -#define CL_SD_CTL_FEIE_MASK (1 << CL_SD_CTL_FEIE_SHIFT) -#define CL_SD_CTL_FEIE(x) \ - ((x << CL_SD_CTL_FEIE_SHIFT) & CL_SD_CTL_FEIE_MASK) - -/* Descriptor Error Interrupt Enable */ -#define CL_SD_CTL_DEIE_SHIFT 4 -#define CL_SD_CTL_DEIE_MASK (1 << CL_SD_CTL_DEIE_SHIFT) -#define CL_SD_CTL_DEIE(x) \ - ((x << CL_SD_CTL_DEIE_SHIFT) & CL_SD_CTL_DEIE_MASK) - -/* FIFO Limit Change */ -#define CL_SD_CTL_FIFOLC_SHIFT 5 -#define CL_SD_CTL_FIFOLC_MASK (1 << CL_SD_CTL_FIFOLC_SHIFT) -#define CL_SD_CTL_FIFOLC(x) \ - ((x << CL_SD_CTL_FIFOLC_SHIFT) & CL_SD_CTL_FIFOLC_MASK) - -/* Stripe Control */ -#define CL_SD_CTL_STRIPE_SHIFT 16 -#define CL_SD_CTL_STRIPE_MASK (0x3 << CL_SD_CTL_STRIPE_SHIFT) -#define CL_SD_CTL_STRIPE(x) \ - ((x << CL_SD_CTL_STRIPE_SHIFT) & CL_SD_CTL_STRIPE_MASK) - -/* Traffic Priority */ -#define CL_SD_CTL_TP_SHIFT 18 -#define CL_SD_CTL_TP_MASK (1 << CL_SD_CTL_TP_SHIFT) -#define CL_SD_CTL_TP(x) \ - ((x << CL_SD_CTL_TP_SHIFT) & CL_SD_CTL_TP_MASK) - -/* Bidirectional Direction Control */ -#define CL_SD_CTL_DIR_SHIFT 19 -#define CL_SD_CTL_DIR_MASK (1 << CL_SD_CTL_DIR_SHIFT) -#define CL_SD_CTL_DIR(x) \ - ((x << CL_SD_CTL_DIR_SHIFT) & CL_SD_CTL_DIR_MASK) - -/* Stream Number */ -#define CL_SD_CTL_STRM_SHIFT 20 -#define CL_SD_CTL_STRM_MASK (0xf << CL_SD_CTL_STRM_SHIFT) -#define CL_SD_CTL_STRM(x) \ - ((x << CL_SD_CTL_STRM_SHIFT) & CL_SD_CTL_STRM_MASK) - -/* CL: Stream Descriptor x Status */ - -/* Buffer Completion Interrupt Status */ -#define CL_SD_STS_BCIS(x) CL_SD_CTL_IOCE(x) - -/* FIFO Error */ -#define CL_SD_STS_FIFOE(x) CL_SD_CTL_FEIE(x) - -/* Descriptor Error */ -#define CL_SD_STS_DESE(x) CL_SD_CTL_DEIE(x) - -/* FIFO Ready */ -#define CL_SD_STS_FIFORDY(x) CL_SD_CTL_FIFOLC(x) - - -/* CL: Stream Descriptor x Last Valid Index */ -#define CL_SD_LVI_SHIFT 0 -#define CL_SD_LVI_MASK (0xff << CL_SD_LVI_SHIFT) -#define CL_SD_LVI(x) ((x << CL_SD_LVI_SHIFT) & CL_SD_LVI_MASK) - -/* CL: Stream Descriptor x FIFO Eviction Watermark */ -#define CL_SD_FIFOW_SHIFT 0 -#define CL_SD_FIFOW_MASK (0x7 << CL_SD_FIFOW_SHIFT) -#define CL_SD_FIFOW(x) \ - ((x << CL_SD_FIFOW_SHIFT) & CL_SD_FIFOW_MASK) - -/* CL: Stream Descriptor x Buffer Descriptor List Pointer Lower Base Address */ - -/* Protect Bits */ -#define CL_SD_BDLPLBA_PROT_SHIFT 0 -#define CL_SD_BDLPLBA_PROT_MASK (1 << CL_SD_BDLPLBA_PROT_SHIFT) -#define CL_SD_BDLPLBA_PROT(x) \ - ((x << CL_SD_BDLPLBA_PROT_SHIFT) & CL_SD_BDLPLBA_PROT_MASK) - -/* Buffer Descriptor List Lower Base Address */ -#define CL_SD_BDLPLBA_SHIFT 7 -#define CL_SD_BDLPLBA_MASK (0x1ffffff << CL_SD_BDLPLBA_SHIFT) -#define CL_SD_BDLPLBA(x) \ - ((BDL_ALIGN(lower_32_bits(x)) << CL_SD_BDLPLBA_SHIFT) & CL_SD_BDLPLBA_MASK) - -/* Buffer Descriptor List Upper Base Address */ -#define CL_SD_BDLPUBA_SHIFT 0 -#define CL_SD_BDLPUBA_MASK (0xffffffff << CL_SD_BDLPUBA_SHIFT) -#define CL_SD_BDLPUBA(x) \ - ((upper_32_bits(x) << CL_SD_BDLPUBA_SHIFT) & CL_SD_BDLPUBA_MASK) - -/* - * Code Loader - Software Position Based FIFO - * Capability Registers x Software Position Based FIFO Header - */ - -/* Next Capability Pointer */ -#define CL_SPBFIFO_SPBFCH_PTR_SHIFT 0 -#define CL_SPBFIFO_SPBFCH_PTR_MASK (0xff << CL_SPBFIFO_SPBFCH_PTR_SHIFT) -#define CL_SPBFIFO_SPBFCH_PTR(x) \ - ((x << CL_SPBFIFO_SPBFCH_PTR_SHIFT) & CL_SPBFIFO_SPBFCH_PTR_MASK) - -/* Capability Identifier */ -#define CL_SPBFIFO_SPBFCH_ID_SHIFT 16 -#define CL_SPBFIFO_SPBFCH_ID_MASK (0xfff << CL_SPBFIFO_SPBFCH_ID_SHIFT) -#define CL_SPBFIFO_SPBFCH_ID(x) \ - ((x << CL_SPBFIFO_SPBFCH_ID_SHIFT) & CL_SPBFIFO_SPBFCH_ID_MASK) - -/* Capability Version */ -#define CL_SPBFIFO_SPBFCH_VER_SHIFT 28 -#define CL_SPBFIFO_SPBFCH_VER_MASK (0xf << CL_SPBFIFO_SPBFCH_VER_SHIFT) -#define CL_SPBFIFO_SPBFCH_VER(x) \ - ((x << CL_SPBFIFO_SPBFCH_VER_SHIFT) & CL_SPBFIFO_SPBFCH_VER_MASK) - -/* Software Position in Buffer Enable */ -#define CL_SPBFIFO_SPBFCCTL_SPIBE_SHIFT 0 -#define CL_SPBFIFO_SPBFCCTL_SPIBE_MASK (1 << CL_SPBFIFO_SPBFCCTL_SPIBE_SHIFT) -#define CL_SPBFIFO_SPBFCCTL_SPIBE(x) \ - ((x << CL_SPBFIFO_SPBFCCTL_SPIBE_SHIFT) & CL_SPBFIFO_SPBFCCTL_SPIBE_MASK) - -/* SST IPC SKL defines */ -#define SKL_WAIT_TIMEOUT 500 /* 500 msec */ -#define SKL_MAX_BUFFER_SIZE (32 * PAGE_SIZE) - -enum skl_cl_dma_wake_states { - SKL_CL_DMA_STATUS_NONE = 0, - SKL_CL_DMA_BUF_COMPLETE, - SKL_CL_DMA_ERR, /* TODO: Expand the error states */ -}; - -struct sst_dsp; - -struct skl_cl_dev_ops { - void (*cl_setup_bdle)(struct sst_dsp *ctx, - struct snd_dma_buffer *dmab_data, - __le32 **bdlp, int size, int with_ioc); - void (*cl_setup_controller)(struct sst_dsp *ctx, - struct snd_dma_buffer *dmab_bdl, - unsigned int max_size, u32 page_count); - void (*cl_setup_spb)(struct sst_dsp *ctx, - unsigned int size, bool enable); - void (*cl_cleanup_spb)(struct sst_dsp *ctx); - void (*cl_trigger)(struct sst_dsp *ctx, bool enable); - void (*cl_cleanup_controller)(struct sst_dsp *ctx); - int (*cl_copy_to_dmabuf)(struct sst_dsp *ctx, - const void *bin, u32 size, bool wait); - void (*cl_stop_dma)(struct sst_dsp *ctx); -}; - -/** - * skl_cl_dev - holds information for code loader dma transfer - * - * @dmab_data: buffer pointer - * @dmab_bdl: buffer descriptor list - * @bufsize: ring buffer size - * @frags: Last valid buffer descriptor index in the BDL - * @curr_spib_pos: Current position in ring buffer - * @dma_buffer_offset: dma buffer offset - * @ops: operations supported on CL dma - * @wait_queue: wait queue to wake for wake event - * @wake_status: DMA wake status - * @wait_condition: condition to wait on wait queue - * @cl_dma_lock: for synchronized access to cldma - */ -struct skl_cl_dev { - struct snd_dma_buffer dmab_data; - struct snd_dma_buffer dmab_bdl; - - unsigned int bufsize; - unsigned int frags; - - unsigned int curr_spib_pos; - unsigned int dma_buffer_offset; - struct skl_cl_dev_ops ops; - - wait_queue_head_t wait_queue; - int wake_status; - bool wait_condition; -}; - -#endif /* SKL_SST_CLDMA_H_ */ diff --git a/sound/soc/intel/skylake/skl-sst-dsp.c b/sound/soc/intel/skylake/skl-sst-dsp.c deleted file mode 100644 index 4ae3eae0d1fd07..00000000000000 --- a/sound/soc/intel/skylake/skl-sst-dsp.c +++ /dev/null @@ -1,462 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * skl-sst-dsp.c - SKL SST library generic function - * - * Copyright (C) 2014-15, Intel Corporation. - * Author:Rafal Redzimski - * Jeeja KP - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ -#include - -#include "../common/sst-dsp.h" -#include "../common/sst-ipc.h" -#include "../common/sst-dsp-priv.h" -#include "skl.h" - -/* various timeout values */ -#define SKL_DSP_PU_TO 50 -#define SKL_DSP_PD_TO 50 -#define SKL_DSP_RESET_TO 50 - -void skl_dsp_set_state_locked(struct sst_dsp *ctx, int state) -{ - mutex_lock(&ctx->mutex); - ctx->sst_state = state; - mutex_unlock(&ctx->mutex); -} - -/* - * Initialize core power state and usage count. To be called after - * successful first boot. Hence core 0 will be running and other cores - * will be reset - */ -void skl_dsp_init_core_state(struct sst_dsp *ctx) -{ - struct skl_dev *skl = ctx->thread_context; - int i; - - skl->cores.state[SKL_DSP_CORE0_ID] = SKL_DSP_RUNNING; - skl->cores.usage_count[SKL_DSP_CORE0_ID] = 1; - - for (i = SKL_DSP_CORE0_ID + 1; i < skl->cores.count; i++) { - skl->cores.state[i] = SKL_DSP_RESET; - skl->cores.usage_count[i] = 0; - } -} - -/* Get the mask for all enabled cores */ -unsigned int skl_dsp_get_enabled_cores(struct sst_dsp *ctx) -{ - struct skl_dev *skl = ctx->thread_context; - unsigned int core_mask, en_cores_mask; - u32 val; - - core_mask = SKL_DSP_CORES_MASK(skl->cores.count); - - val = sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS); - - /* Cores having CPA bit set */ - en_cores_mask = (val & SKL_ADSPCS_CPA_MASK(core_mask)) >> - SKL_ADSPCS_CPA_SHIFT; - - /* And cores having CRST bit cleared */ - en_cores_mask &= (~val & SKL_ADSPCS_CRST_MASK(core_mask)) >> - SKL_ADSPCS_CRST_SHIFT; - - /* And cores having CSTALL bit cleared */ - en_cores_mask &= (~val & SKL_ADSPCS_CSTALL_MASK(core_mask)) >> - SKL_ADSPCS_CSTALL_SHIFT; - en_cores_mask &= core_mask; - - dev_dbg(ctx->dev, "DSP enabled cores mask = %x\n", en_cores_mask); - - return en_cores_mask; -} - -static int -skl_dsp_core_set_reset_state(struct sst_dsp *ctx, unsigned int core_mask) -{ - int ret; - - /* update bits */ - sst_dsp_shim_update_bits_unlocked(ctx, - SKL_ADSP_REG_ADSPCS, SKL_ADSPCS_CRST_MASK(core_mask), - SKL_ADSPCS_CRST_MASK(core_mask)); - - /* poll with timeout to check if operation successful */ - ret = sst_dsp_register_poll(ctx, - SKL_ADSP_REG_ADSPCS, - SKL_ADSPCS_CRST_MASK(core_mask), - SKL_ADSPCS_CRST_MASK(core_mask), - SKL_DSP_RESET_TO, - "Set reset"); - if ((sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS) & - SKL_ADSPCS_CRST_MASK(core_mask)) != - SKL_ADSPCS_CRST_MASK(core_mask)) { - dev_err(ctx->dev, "Set reset state failed: core_mask %x\n", - core_mask); - ret = -EIO; - } - - return ret; -} - -int skl_dsp_core_unset_reset_state( - struct sst_dsp *ctx, unsigned int core_mask) -{ - int ret; - - dev_dbg(ctx->dev, "In %s\n", __func__); - - /* update bits */ - sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS, - SKL_ADSPCS_CRST_MASK(core_mask), 0); - - /* poll with timeout to check if operation successful */ - ret = sst_dsp_register_poll(ctx, - SKL_ADSP_REG_ADSPCS, - SKL_ADSPCS_CRST_MASK(core_mask), - 0, - SKL_DSP_RESET_TO, - "Unset reset"); - - if ((sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS) & - SKL_ADSPCS_CRST_MASK(core_mask)) != 0) { - dev_err(ctx->dev, "Unset reset state failed: core_mask %x\n", - core_mask); - ret = -EIO; - } - - return ret; -} - -static bool -is_skl_dsp_core_enable(struct sst_dsp *ctx, unsigned int core_mask) -{ - int val; - bool is_enable; - - val = sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS); - - is_enable = ((val & SKL_ADSPCS_CPA_MASK(core_mask)) && - (val & SKL_ADSPCS_SPA_MASK(core_mask)) && - !(val & SKL_ADSPCS_CRST_MASK(core_mask)) && - !(val & SKL_ADSPCS_CSTALL_MASK(core_mask))); - - dev_dbg(ctx->dev, "DSP core(s) enabled? %d : core_mask %x\n", - is_enable, core_mask); - - return is_enable; -} - -static int skl_dsp_reset_core(struct sst_dsp *ctx, unsigned int core_mask) -{ - /* stall core */ - sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS, - SKL_ADSPCS_CSTALL_MASK(core_mask), - SKL_ADSPCS_CSTALL_MASK(core_mask)); - - /* set reset state */ - return skl_dsp_core_set_reset_state(ctx, core_mask); -} - -int skl_dsp_start_core(struct sst_dsp *ctx, unsigned int core_mask) -{ - int ret; - - /* unset reset state */ - ret = skl_dsp_core_unset_reset_state(ctx, core_mask); - if (ret < 0) - return ret; - - /* run core */ - dev_dbg(ctx->dev, "unstall/run core: core_mask = %x\n", core_mask); - sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS, - SKL_ADSPCS_CSTALL_MASK(core_mask), 0); - - if (!is_skl_dsp_core_enable(ctx, core_mask)) { - skl_dsp_reset_core(ctx, core_mask); - dev_err(ctx->dev, "DSP start core failed: core_mask %x\n", - core_mask); - ret = -EIO; - } - - return ret; -} - -int skl_dsp_core_power_up(struct sst_dsp *ctx, unsigned int core_mask) -{ - int ret; - - /* update bits */ - sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS, - SKL_ADSPCS_SPA_MASK(core_mask), - SKL_ADSPCS_SPA_MASK(core_mask)); - - /* poll with timeout to check if operation successful */ - ret = sst_dsp_register_poll(ctx, - SKL_ADSP_REG_ADSPCS, - SKL_ADSPCS_CPA_MASK(core_mask), - SKL_ADSPCS_CPA_MASK(core_mask), - SKL_DSP_PU_TO, - "Power up"); - - if ((sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS) & - SKL_ADSPCS_CPA_MASK(core_mask)) != - SKL_ADSPCS_CPA_MASK(core_mask)) { - dev_err(ctx->dev, "DSP core power up failed: core_mask %x\n", - core_mask); - ret = -EIO; - } - - return ret; -} - -int skl_dsp_core_power_down(struct sst_dsp *ctx, unsigned int core_mask) -{ - /* update bits */ - sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS, - SKL_ADSPCS_SPA_MASK(core_mask), 0); - - /* poll with timeout to check if operation successful */ - return sst_dsp_register_poll(ctx, - SKL_ADSP_REG_ADSPCS, - SKL_ADSPCS_CPA_MASK(core_mask), - 0, - SKL_DSP_PD_TO, - "Power down"); -} - -int skl_dsp_enable_core(struct sst_dsp *ctx, unsigned int core_mask) -{ - int ret; - - /* power up */ - ret = skl_dsp_core_power_up(ctx, core_mask); - if (ret < 0) { - dev_err(ctx->dev, "dsp core power up failed: core_mask %x\n", - core_mask); - return ret; - } - - return skl_dsp_start_core(ctx, core_mask); -} - -int skl_dsp_disable_core(struct sst_dsp *ctx, unsigned int core_mask) -{ - int ret; - - ret = skl_dsp_reset_core(ctx, core_mask); - if (ret < 0) { - dev_err(ctx->dev, "dsp core reset failed: core_mask %x\n", - core_mask); - return ret; - } - - /* power down core*/ - ret = skl_dsp_core_power_down(ctx, core_mask); - if (ret < 0) { - dev_err(ctx->dev, "dsp core power down fail mask %x: %d\n", - core_mask, ret); - return ret; - } - - if (is_skl_dsp_core_enable(ctx, core_mask)) { - dev_err(ctx->dev, "dsp core disable fail mask %x: %d\n", - core_mask, ret); - ret = -EIO; - } - - return ret; -} - -int skl_dsp_boot(struct sst_dsp *ctx) -{ - int ret; - - if (is_skl_dsp_core_enable(ctx, SKL_DSP_CORE0_MASK)) { - ret = skl_dsp_reset_core(ctx, SKL_DSP_CORE0_MASK); - if (ret < 0) { - dev_err(ctx->dev, "dsp core0 reset fail: %d\n", ret); - return ret; - } - - ret = skl_dsp_start_core(ctx, SKL_DSP_CORE0_MASK); - if (ret < 0) { - dev_err(ctx->dev, "dsp core0 start fail: %d\n", ret); - return ret; - } - } else { - ret = skl_dsp_disable_core(ctx, SKL_DSP_CORE0_MASK); - if (ret < 0) { - dev_err(ctx->dev, "dsp core0 disable fail: %d\n", ret); - return ret; - } - ret = skl_dsp_enable_core(ctx, SKL_DSP_CORE0_MASK); - } - - return ret; -} - -irqreturn_t skl_dsp_sst_interrupt(int irq, void *dev_id) -{ - struct sst_dsp *ctx = dev_id; - u32 val; - irqreturn_t result = IRQ_NONE; - - spin_lock(&ctx->spinlock); - - val = sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPIS); - ctx->intr_status = val; - - if (val == 0xffffffff) { - spin_unlock(&ctx->spinlock); - return IRQ_NONE; - } - - if (val & SKL_ADSPIS_IPC) { - skl_ipc_int_disable(ctx); - result = IRQ_WAKE_THREAD; - } - - if (val & SKL_ADSPIS_CL_DMA) { - skl_cldma_int_disable(ctx); - result = IRQ_WAKE_THREAD; - } - - spin_unlock(&ctx->spinlock); - - return result; -} -/* - * skl_dsp_get_core/skl_dsp_put_core will be called inside DAPM context - * within the dapm mutex. Hence no separate lock is used. - */ -int skl_dsp_get_core(struct sst_dsp *ctx, unsigned int core_id) -{ - struct skl_dev *skl = ctx->thread_context; - int ret = 0; - - if (core_id >= skl->cores.count) { - dev_err(ctx->dev, "invalid core id: %d\n", core_id); - return -EINVAL; - } - - skl->cores.usage_count[core_id]++; - - if (skl->cores.state[core_id] == SKL_DSP_RESET) { - ret = ctx->fw_ops.set_state_D0(ctx, core_id); - if (ret < 0) { - dev_err(ctx->dev, "unable to get core%d\n", core_id); - goto out; - } - } - -out: - dev_dbg(ctx->dev, "core id %d state %d usage_count %d\n", - core_id, skl->cores.state[core_id], - skl->cores.usage_count[core_id]); - - return ret; -} -EXPORT_SYMBOL_GPL(skl_dsp_get_core); - -int skl_dsp_put_core(struct sst_dsp *ctx, unsigned int core_id) -{ - struct skl_dev *skl = ctx->thread_context; - int ret = 0; - - if (core_id >= skl->cores.count) { - dev_err(ctx->dev, "invalid core id: %d\n", core_id); - return -EINVAL; - } - - if ((--skl->cores.usage_count[core_id] == 0) && - (skl->cores.state[core_id] != SKL_DSP_RESET)) { - ret = ctx->fw_ops.set_state_D3(ctx, core_id); - if (ret < 0) { - dev_err(ctx->dev, "unable to put core %d: %d\n", - core_id, ret); - skl->cores.usage_count[core_id]++; - } - } - - dev_dbg(ctx->dev, "core id %d state %d usage_count %d\n", - core_id, skl->cores.state[core_id], - skl->cores.usage_count[core_id]); - - return ret; -} -EXPORT_SYMBOL_GPL(skl_dsp_put_core); - -int skl_dsp_wake(struct sst_dsp *ctx) -{ - return skl_dsp_get_core(ctx, SKL_DSP_CORE0_ID); -} -EXPORT_SYMBOL_GPL(skl_dsp_wake); - -int skl_dsp_sleep(struct sst_dsp *ctx) -{ - return skl_dsp_put_core(ctx, SKL_DSP_CORE0_ID); -} -EXPORT_SYMBOL_GPL(skl_dsp_sleep); - -struct sst_dsp *skl_dsp_ctx_init(struct device *dev, - struct sst_dsp_device *sst_dev, int irq) -{ - int ret; - struct sst_dsp *sst; - - sst = devm_kzalloc(dev, sizeof(*sst), GFP_KERNEL); - if (sst == NULL) - return NULL; - - spin_lock_init(&sst->spinlock); - mutex_init(&sst->mutex); - sst->dev = dev; - sst->sst_dev = sst_dev; - sst->irq = irq; - sst->ops = sst_dev->ops; - sst->thread_context = sst_dev->thread_context; - - /* Initialise SST Audio DSP */ - if (sst->ops->init) { - ret = sst->ops->init(sst); - if (ret < 0) - return NULL; - } - - return sst; -} - -int skl_dsp_acquire_irq(struct sst_dsp *sst) -{ - struct sst_dsp_device *sst_dev = sst->sst_dev; - int ret; - - /* Register the ISR */ - ret = request_threaded_irq(sst->irq, sst->ops->irq_handler, - sst_dev->thread, IRQF_SHARED, "AudioDSP", sst); - if (ret) - dev_err(sst->dev, "unable to grab threaded IRQ %d, disabling device\n", - sst->irq); - - return ret; -} - -void skl_dsp_free(struct sst_dsp *dsp) -{ - skl_ipc_int_disable(dsp); - - free_irq(dsp->irq, dsp); - skl_ipc_op_int_disable(dsp); - skl_dsp_disable_core(dsp, SKL_DSP_CORE0_MASK); -} -EXPORT_SYMBOL_GPL(skl_dsp_free); - -bool is_skl_dsp_running(struct sst_dsp *ctx) -{ - return (ctx->sst_state == SKL_DSP_RUNNING); -} -EXPORT_SYMBOL_GPL(is_skl_dsp_running); diff --git a/sound/soc/intel/skylake/skl-sst-dsp.h b/sound/soc/intel/skylake/skl-sst-dsp.h deleted file mode 100644 index 1df9ef422f61df..00000000000000 --- a/sound/soc/intel/skylake/skl-sst-dsp.h +++ /dev/null @@ -1,256 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Skylake SST DSP Support - * - * Copyright (C) 2014-15, Intel Corporation. - */ - -#ifndef __SKL_SST_DSP_H__ -#define __SKL_SST_DSP_H__ - -#include -#include -#include -#include -#include "skl-sst-cldma.h" - -struct sst_dsp; -struct sst_dsp_device; -struct skl_lib_info; -struct skl_dev; - -/* Intel HD Audio General DSP Registers */ -#define SKL_ADSP_GEN_BASE 0x0 -#define SKL_ADSP_REG_ADSPCS (SKL_ADSP_GEN_BASE + 0x04) -#define SKL_ADSP_REG_ADSPIC (SKL_ADSP_GEN_BASE + 0x08) -#define SKL_ADSP_REG_ADSPIS (SKL_ADSP_GEN_BASE + 0x0C) -#define SKL_ADSP_REG_ADSPIC2 (SKL_ADSP_GEN_BASE + 0x10) -#define SKL_ADSP_REG_ADSPIS2 (SKL_ADSP_GEN_BASE + 0x14) - -/* Intel HD Audio Inter-Processor Communication Registers */ -#define SKL_ADSP_IPC_BASE 0x40 -#define SKL_ADSP_REG_HIPCT (SKL_ADSP_IPC_BASE + 0x00) -#define SKL_ADSP_REG_HIPCTE (SKL_ADSP_IPC_BASE + 0x04) -#define SKL_ADSP_REG_HIPCI (SKL_ADSP_IPC_BASE + 0x08) -#define SKL_ADSP_REG_HIPCIE (SKL_ADSP_IPC_BASE + 0x0C) -#define SKL_ADSP_REG_HIPCCTL (SKL_ADSP_IPC_BASE + 0x10) - -/* HIPCI */ -#define SKL_ADSP_REG_HIPCI_BUSY BIT(31) - -/* HIPCIE */ -#define SKL_ADSP_REG_HIPCIE_DONE BIT(30) - -/* HIPCCTL */ -#define SKL_ADSP_REG_HIPCCTL_DONE BIT(1) -#define SKL_ADSP_REG_HIPCCTL_BUSY BIT(0) - -/* HIPCT */ -#define SKL_ADSP_REG_HIPCT_BUSY BIT(31) - -/* FW base IDs */ -#define SKL_INSTANCE_ID 0 -#define SKL_BASE_FW_MODULE_ID 0 - -/* Intel HD Audio SRAM Window 1 */ -#define SKL_ADSP_SRAM1_BASE 0xA000 - -#define SKL_ADSP_MMIO_LEN 0x10000 - -#define SKL_ADSP_W0_STAT_SZ 0x1000 - -#define SKL_ADSP_W0_UP_SZ 0x1000 - -#define SKL_ADSP_W1_SZ 0x1000 - -#define SKL_FW_STS_MASK 0xf - -#define SKL_FW_INIT 0x1 -#define SKL_FW_RFW_START 0xf -#define BXT_FW_ROM_INIT_RETRY 3 -#define BXT_INIT_TIMEOUT 300 - -#define SKL_ADSPIC_IPC 1 -#define SKL_ADSPIS_IPC 1 - -/* Core ID of core0 */ -#define SKL_DSP_CORE0_ID 0 - -/* Mask for a given core index, c = 0.. number of supported cores - 1 */ -#define SKL_DSP_CORE_MASK(c) BIT(c) - -/* - * Core 0 mask = SKL_DSP_CORE_MASK(0); Defined separately - * since Core0 is primary core and it is used often - */ -#define SKL_DSP_CORE0_MASK BIT(0) - -/* - * Mask for a given number of cores - * nc = number of supported cores - */ -#define SKL_DSP_CORES_MASK(nc) GENMASK((nc - 1), 0) - -/* ADSPCS - Audio DSP Control & Status */ - -/* - * Core Reset - asserted high - * CRST Mask for a given core mask pattern, cm - */ -#define SKL_ADSPCS_CRST_SHIFT 0 -#define SKL_ADSPCS_CRST_MASK(cm) ((cm) << SKL_ADSPCS_CRST_SHIFT) - -/* - * Core run/stall - when set to '1' core is stalled - * CSTALL Mask for a given core mask pattern, cm - */ -#define SKL_ADSPCS_CSTALL_SHIFT 8 -#define SKL_ADSPCS_CSTALL_MASK(cm) ((cm) << SKL_ADSPCS_CSTALL_SHIFT) - -/* - * Set Power Active - when set to '1' turn cores on - * SPA Mask for a given core mask pattern, cm - */ -#define SKL_ADSPCS_SPA_SHIFT 16 -#define SKL_ADSPCS_SPA_MASK(cm) ((cm) << SKL_ADSPCS_SPA_SHIFT) - -/* - * Current Power Active - power status of cores, set by hardware - * CPA Mask for a given core mask pattern, cm - */ -#define SKL_ADSPCS_CPA_SHIFT 24 -#define SKL_ADSPCS_CPA_MASK(cm) ((cm) << SKL_ADSPCS_CPA_SHIFT) - -/* DSP Core state */ -enum skl_dsp_states { - SKL_DSP_RUNNING = 1, - /* Running in D0i3 state; can be in streaming or non-streaming D0i3 */ - SKL_DSP_RUNNING_D0I3, /* Running in D0i3 state*/ - SKL_DSP_RESET, -}; - -/* D0i3 substates */ -enum skl_dsp_d0i3_states { - SKL_DSP_D0I3_NONE = -1, /* No D0i3 */ - SKL_DSP_D0I3_NON_STREAMING = 0, - SKL_DSP_D0I3_STREAMING = 1, -}; - -struct skl_dsp_fw_ops { - int (*load_fw)(struct sst_dsp *ctx); - /* FW module parser/loader */ - int (*load_library)(struct sst_dsp *ctx, - struct skl_lib_info *linfo, int lib_count); - int (*parse_fw)(struct sst_dsp *ctx); - int (*set_state_D0)(struct sst_dsp *ctx, unsigned int core_id); - int (*set_state_D3)(struct sst_dsp *ctx, unsigned int core_id); - int (*set_state_D0i3)(struct sst_dsp *ctx); - int (*set_state_D0i0)(struct sst_dsp *ctx); - unsigned int (*get_fw_errcode)(struct sst_dsp *ctx); - int (*load_mod)(struct sst_dsp *ctx, u16 mod_id, u8 *mod_name); - int (*unload_mod)(struct sst_dsp *ctx, u16 mod_id); - -}; - -struct skl_dsp_loader_ops { - int stream_tag; - - int (*alloc_dma_buf)(struct device *dev, - struct snd_dma_buffer *dmab, size_t size); - int (*free_dma_buf)(struct device *dev, - struct snd_dma_buffer *dmab); - int (*prepare)(struct device *dev, unsigned int format, - unsigned int byte_size, - struct snd_dma_buffer *bufp); - int (*trigger)(struct device *dev, bool start, int stream_tag); - - int (*cleanup)(struct device *dev, struct snd_dma_buffer *dmab, - int stream_tag); -}; - -#define MAX_INSTANCE_BUFF 2 - -struct uuid_module { - guid_t uuid; - int id; - int is_loadable; - int max_instance; - u64 pvt_id[MAX_INSTANCE_BUFF]; - int *instance_id; - - struct list_head list; -}; - -struct skl_load_module_info { - u16 mod_id; - const struct firmware *fw; -}; - -struct skl_module_table { - struct skl_load_module_info *mod_info; - unsigned int usage_cnt; - struct list_head list; -}; - -void skl_cldma_process_intr(struct sst_dsp *ctx); -void skl_cldma_int_disable(struct sst_dsp *ctx); -int skl_cldma_prepare(struct sst_dsp *ctx); -int skl_cldma_wait_interruptible(struct sst_dsp *ctx); - -void skl_dsp_set_state_locked(struct sst_dsp *ctx, int state); -struct sst_dsp *skl_dsp_ctx_init(struct device *dev, - struct sst_dsp_device *sst_dev, int irq); -int skl_dsp_acquire_irq(struct sst_dsp *sst); -bool is_skl_dsp_running(struct sst_dsp *ctx); - -unsigned int skl_dsp_get_enabled_cores(struct sst_dsp *ctx); -void skl_dsp_init_core_state(struct sst_dsp *ctx); -int skl_dsp_enable_core(struct sst_dsp *ctx, unsigned int core_mask); -int skl_dsp_disable_core(struct sst_dsp *ctx, unsigned int core_mask); -int skl_dsp_core_power_up(struct sst_dsp *ctx, unsigned int core_mask); -int skl_dsp_core_power_down(struct sst_dsp *ctx, unsigned int core_mask); -int skl_dsp_core_unset_reset_state(struct sst_dsp *ctx, - unsigned int core_mask); -int skl_dsp_start_core(struct sst_dsp *ctx, unsigned int core_mask); - -irqreturn_t skl_dsp_sst_interrupt(int irq, void *dev_id); -int skl_dsp_wake(struct sst_dsp *ctx); -int skl_dsp_sleep(struct sst_dsp *ctx); -void skl_dsp_free(struct sst_dsp *dsp); - -int skl_dsp_get_core(struct sst_dsp *ctx, unsigned int core_id); -int skl_dsp_put_core(struct sst_dsp *ctx, unsigned int core_id); - -int skl_dsp_boot(struct sst_dsp *ctx); -int skl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, - const char *fw_name, struct skl_dsp_loader_ops dsp_ops, - struct skl_dev **dsp); -int bxt_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, - const char *fw_name, struct skl_dsp_loader_ops dsp_ops, - struct skl_dev **dsp); -int skl_sst_init_fw(struct device *dev, struct skl_dev *skl); -int bxt_sst_init_fw(struct device *dev, struct skl_dev *skl); -void skl_sst_dsp_cleanup(struct device *dev, struct skl_dev *skl); -void bxt_sst_dsp_cleanup(struct device *dev, struct skl_dev *skl); - -int snd_skl_parse_uuids(struct sst_dsp *ctx, const struct firmware *fw, - unsigned int offset, int index); -int skl_get_pvt_id(struct skl_dev *skl, guid_t *uuid_mod, int instance_id); -int skl_put_pvt_id(struct skl_dev *skl, guid_t *uuid_mod, int *pvt_id); -int skl_get_pvt_instance_id_map(struct skl_dev *skl, - int module_id, int instance_id); -void skl_freeup_uuid_list(struct skl_dev *skl); - -int skl_dsp_strip_extended_manifest(struct firmware *fw); - -void skl_dsp_set_astate_cfg(struct skl_dev *skl, u32 cnt, void *data); - -int skl_sst_ctx_init(struct device *dev, int irq, const char *fw_name, - struct skl_dsp_loader_ops dsp_ops, struct skl_dev **dsp, - struct sst_dsp_device *skl_dev); -int skl_prepare_lib_load(struct skl_dev *skl, struct skl_lib_info *linfo, - struct firmware *stripped_fw, - unsigned int hdr_offset, int index); -void skl_release_library(struct skl_lib_info *linfo, int lib_count); - -#endif /*__SKL_SST_DSP_H__*/ diff --git a/sound/soc/intel/skylake/skl-sst-ipc.c b/sound/soc/intel/skylake/skl-sst-ipc.c deleted file mode 100644 index fd9624ad5f72b0..00000000000000 --- a/sound/soc/intel/skylake/skl-sst-ipc.c +++ /dev/null @@ -1,1071 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * skl-sst-ipc.c - Intel skl IPC Support - * - * Copyright (C) 2014-15, Intel Corporation. - */ -#include - -#include "../common/sst-dsp.h" -#include "../common/sst-dsp-priv.h" -#include "skl.h" -#include "skl-sst-dsp.h" -#include "skl-sst-ipc.h" -#include "sound/hdaudio_ext.h" - - -#define IPC_IXC_STATUS_BITS 24 - -/* Global Message - Generic */ -#define IPC_GLB_TYPE_SHIFT 24 -#define IPC_GLB_TYPE_MASK (0xf << IPC_GLB_TYPE_SHIFT) -#define IPC_GLB_TYPE(x) ((x) << IPC_GLB_TYPE_SHIFT) - -/* Global Message - Reply */ -#define IPC_GLB_REPLY_STATUS_SHIFT 24 -#define IPC_GLB_REPLY_STATUS_MASK ((0x1 << IPC_GLB_REPLY_STATUS_SHIFT) - 1) -#define IPC_GLB_REPLY_STATUS(x) ((x) << IPC_GLB_REPLY_STATUS_SHIFT) - -#define IPC_GLB_REPLY_TYPE_SHIFT 29 -#define IPC_GLB_REPLY_TYPE_MASK 0x1F -#define IPC_GLB_REPLY_TYPE(x) (((x) >> IPC_GLB_REPLY_TYPE_SHIFT) \ - & IPC_GLB_RPLY_TYPE_MASK) - -#define IPC_TIMEOUT_MSECS 3000 - -#define IPC_EMPTY_LIST_SIZE 8 - -#define IPC_MSG_TARGET_SHIFT 30 -#define IPC_MSG_TARGET_MASK 0x1 -#define IPC_MSG_TARGET(x) (((x) & IPC_MSG_TARGET_MASK) \ - << IPC_MSG_TARGET_SHIFT) - -#define IPC_MSG_DIR_SHIFT 29 -#define IPC_MSG_DIR_MASK 0x1 -#define IPC_MSG_DIR(x) (((x) & IPC_MSG_DIR_MASK) \ - << IPC_MSG_DIR_SHIFT) -/* Global Notification Message */ -#define IPC_GLB_NOTIFY_TYPE_SHIFT 16 -#define IPC_GLB_NOTIFY_TYPE_MASK 0xFF -#define IPC_GLB_NOTIFY_TYPE(x) (((x) >> IPC_GLB_NOTIFY_TYPE_SHIFT) \ - & IPC_GLB_NOTIFY_TYPE_MASK) - -#define IPC_GLB_NOTIFY_MSG_TYPE_SHIFT 24 -#define IPC_GLB_NOTIFY_MSG_TYPE_MASK 0x1F -#define IPC_GLB_NOTIFY_MSG_TYPE(x) (((x) >> IPC_GLB_NOTIFY_MSG_TYPE_SHIFT) \ - & IPC_GLB_NOTIFY_MSG_TYPE_MASK) - -#define IPC_GLB_NOTIFY_RSP_SHIFT 29 -#define IPC_GLB_NOTIFY_RSP_MASK 0x1 -#define IPC_GLB_NOTIFY_RSP_TYPE(x) (((x) >> IPC_GLB_NOTIFY_RSP_SHIFT) \ - & IPC_GLB_NOTIFY_RSP_MASK) - -/* Pipeline operations */ - -/* Create pipeline message */ -#define IPC_PPL_MEM_SIZE_SHIFT 0 -#define IPC_PPL_MEM_SIZE_MASK 0x7FF -#define IPC_PPL_MEM_SIZE(x) (((x) & IPC_PPL_MEM_SIZE_MASK) \ - << IPC_PPL_MEM_SIZE_SHIFT) - -#define IPC_PPL_TYPE_SHIFT 11 -#define IPC_PPL_TYPE_MASK 0x1F -#define IPC_PPL_TYPE(x) (((x) & IPC_PPL_TYPE_MASK) \ - << IPC_PPL_TYPE_SHIFT) - -#define IPC_INSTANCE_ID_SHIFT 16 -#define IPC_INSTANCE_ID_MASK 0xFF -#define IPC_INSTANCE_ID(x) (((x) & IPC_INSTANCE_ID_MASK) \ - << IPC_INSTANCE_ID_SHIFT) - -#define IPC_PPL_LP_MODE_SHIFT 0 -#define IPC_PPL_LP_MODE_MASK 0x1 -#define IPC_PPL_LP_MODE(x) (((x) & IPC_PPL_LP_MODE_MASK) \ - << IPC_PPL_LP_MODE_SHIFT) - -/* Set pipeline state message */ -#define IPC_PPL_STATE_SHIFT 0 -#define IPC_PPL_STATE_MASK 0x1F -#define IPC_PPL_STATE(x) (((x) & IPC_PPL_STATE_MASK) \ - << IPC_PPL_STATE_SHIFT) - -/* Module operations primary register */ -#define IPC_MOD_ID_SHIFT 0 -#define IPC_MOD_ID_MASK 0xFFFF -#define IPC_MOD_ID(x) (((x) & IPC_MOD_ID_MASK) \ - << IPC_MOD_ID_SHIFT) - -#define IPC_MOD_INSTANCE_ID_SHIFT 16 -#define IPC_MOD_INSTANCE_ID_MASK 0xFF -#define IPC_MOD_INSTANCE_ID(x) (((x) & IPC_MOD_INSTANCE_ID_MASK) \ - << IPC_MOD_INSTANCE_ID_SHIFT) - -/* Init instance message extension register */ -#define IPC_PARAM_BLOCK_SIZE_SHIFT 0 -#define IPC_PARAM_BLOCK_SIZE_MASK 0xFFFF -#define IPC_PARAM_BLOCK_SIZE(x) (((x) & IPC_PARAM_BLOCK_SIZE_MASK) \ - << IPC_PARAM_BLOCK_SIZE_SHIFT) - -#define IPC_PPL_INSTANCE_ID_SHIFT 16 -#define IPC_PPL_INSTANCE_ID_MASK 0xFF -#define IPC_PPL_INSTANCE_ID(x) (((x) & IPC_PPL_INSTANCE_ID_MASK) \ - << IPC_PPL_INSTANCE_ID_SHIFT) - -#define IPC_CORE_ID_SHIFT 24 -#define IPC_CORE_ID_MASK 0x1F -#define IPC_CORE_ID(x) (((x) & IPC_CORE_ID_MASK) \ - << IPC_CORE_ID_SHIFT) - -#define IPC_DOMAIN_SHIFT 28 -#define IPC_DOMAIN_MASK 0x1 -#define IPC_DOMAIN(x) (((x) & IPC_DOMAIN_MASK) \ - << IPC_DOMAIN_SHIFT) - -/* Bind/Unbind message extension register */ -#define IPC_DST_MOD_ID_SHIFT 0 -#define IPC_DST_MOD_ID(x) (((x) & IPC_MOD_ID_MASK) \ - << IPC_DST_MOD_ID_SHIFT) - -#define IPC_DST_MOD_INSTANCE_ID_SHIFT 16 -#define IPC_DST_MOD_INSTANCE_ID(x) (((x) & IPC_MOD_INSTANCE_ID_MASK) \ - << IPC_DST_MOD_INSTANCE_ID_SHIFT) - -#define IPC_DST_QUEUE_SHIFT 24 -#define IPC_DST_QUEUE_MASK 0x7 -#define IPC_DST_QUEUE(x) (((x) & IPC_DST_QUEUE_MASK) \ - << IPC_DST_QUEUE_SHIFT) - -#define IPC_SRC_QUEUE_SHIFT 27 -#define IPC_SRC_QUEUE_MASK 0x7 -#define IPC_SRC_QUEUE(x) (((x) & IPC_SRC_QUEUE_MASK) \ - << IPC_SRC_QUEUE_SHIFT) -/* Load Module count */ -#define IPC_LOAD_MODULE_SHIFT 0 -#define IPC_LOAD_MODULE_MASK 0xFF -#define IPC_LOAD_MODULE_CNT(x) (((x) & IPC_LOAD_MODULE_MASK) \ - << IPC_LOAD_MODULE_SHIFT) - -/* Save pipeline messgae extension register */ -#define IPC_DMA_ID_SHIFT 0 -#define IPC_DMA_ID_MASK 0x1F -#define IPC_DMA_ID(x) (((x) & IPC_DMA_ID_MASK) \ - << IPC_DMA_ID_SHIFT) -/* Large Config message extension register */ -#define IPC_DATA_OFFSET_SZ_SHIFT 0 -#define IPC_DATA_OFFSET_SZ_MASK 0xFFFFF -#define IPC_DATA_OFFSET_SZ(x) (((x) & IPC_DATA_OFFSET_SZ_MASK) \ - << IPC_DATA_OFFSET_SZ_SHIFT) -#define IPC_DATA_OFFSET_SZ_CLEAR ~(IPC_DATA_OFFSET_SZ_MASK \ - << IPC_DATA_OFFSET_SZ_SHIFT) - -#define IPC_LARGE_PARAM_ID_SHIFT 20 -#define IPC_LARGE_PARAM_ID_MASK 0xFF -#define IPC_LARGE_PARAM_ID(x) (((x) & IPC_LARGE_PARAM_ID_MASK) \ - << IPC_LARGE_PARAM_ID_SHIFT) - -#define IPC_FINAL_BLOCK_SHIFT 28 -#define IPC_FINAL_BLOCK_MASK 0x1 -#define IPC_FINAL_BLOCK(x) (((x) & IPC_FINAL_BLOCK_MASK) \ - << IPC_FINAL_BLOCK_SHIFT) - -#define IPC_INITIAL_BLOCK_SHIFT 29 -#define IPC_INITIAL_BLOCK_MASK 0x1 -#define IPC_INITIAL_BLOCK(x) (((x) & IPC_INITIAL_BLOCK_MASK) \ - << IPC_INITIAL_BLOCK_SHIFT) -#define IPC_INITIAL_BLOCK_CLEAR ~(IPC_INITIAL_BLOCK_MASK \ - << IPC_INITIAL_BLOCK_SHIFT) -/* Set D0ix IPC extension register */ -#define IPC_D0IX_WAKE_SHIFT 0 -#define IPC_D0IX_WAKE_MASK 0x1 -#define IPC_D0IX_WAKE(x) (((x) & IPC_D0IX_WAKE_MASK) \ - << IPC_D0IX_WAKE_SHIFT) - -#define IPC_D0IX_STREAMING_SHIFT 1 -#define IPC_D0IX_STREAMING_MASK 0x1 -#define IPC_D0IX_STREAMING(x) (((x) & IPC_D0IX_STREAMING_MASK) \ - << IPC_D0IX_STREAMING_SHIFT) - - -enum skl_ipc_msg_target { - IPC_FW_GEN_MSG = 0, - IPC_MOD_MSG = 1 -}; - -enum skl_ipc_msg_direction { - IPC_MSG_REQUEST = 0, - IPC_MSG_REPLY = 1 -}; - -/* Global Message Types */ -enum skl_ipc_glb_type { - IPC_GLB_GET_FW_VERSION = 0, /* Retrieves firmware version */ - IPC_GLB_LOAD_MULTIPLE_MODS = 15, - IPC_GLB_UNLOAD_MULTIPLE_MODS = 16, - IPC_GLB_CREATE_PPL = 17, - IPC_GLB_DELETE_PPL = 18, - IPC_GLB_SET_PPL_STATE = 19, - IPC_GLB_GET_PPL_STATE = 20, - IPC_GLB_GET_PPL_CONTEXT_SIZE = 21, - IPC_GLB_SAVE_PPL = 22, - IPC_GLB_RESTORE_PPL = 23, - IPC_GLB_LOAD_LIBRARY = 24, - IPC_GLB_NOTIFY = 26, - IPC_GLB_MAX_IPC_MSG_NUMBER = 31 /* Maximum message number */ -}; - -enum skl_ipc_glb_reply { - IPC_GLB_REPLY_SUCCESS = 0, - - IPC_GLB_REPLY_UNKNOWN_MSG_TYPE = 1, - IPC_GLB_REPLY_ERROR_INVALID_PARAM = 2, - - IPC_GLB_REPLY_BUSY = 3, - IPC_GLB_REPLY_PENDING = 4, - IPC_GLB_REPLY_FAILURE = 5, - IPC_GLB_REPLY_INVALID_REQUEST = 6, - - IPC_GLB_REPLY_OUT_OF_MEMORY = 7, - IPC_GLB_REPLY_OUT_OF_MIPS = 8, - - IPC_GLB_REPLY_INVALID_RESOURCE_ID = 9, - IPC_GLB_REPLY_INVALID_RESOURCE_STATE = 10, - - IPC_GLB_REPLY_MOD_MGMT_ERROR = 100, - IPC_GLB_REPLY_MOD_LOAD_CL_FAILED = 101, - IPC_GLB_REPLY_MOD_LOAD_INVALID_HASH = 102, - - IPC_GLB_REPLY_MOD_UNLOAD_INST_EXIST = 103, - IPC_GLB_REPLY_MOD_NOT_INITIALIZED = 104, - - IPC_GLB_REPLY_INVALID_CONFIG_PARAM_ID = 120, - IPC_GLB_REPLY_INVALID_CONFIG_DATA_LEN = 121, - IPC_GLB_REPLY_GATEWAY_NOT_INITIALIZED = 140, - IPC_GLB_REPLY_GATEWAY_NOT_EXIST = 141, - IPC_GLB_REPLY_SCLK_ALREADY_RUNNING = 150, - IPC_GLB_REPLY_MCLK_ALREADY_RUNNING = 151, - - IPC_GLB_REPLY_PPL_NOT_INITIALIZED = 160, - IPC_GLB_REPLY_PPL_NOT_EXIST = 161, - IPC_GLB_REPLY_PPL_SAVE_FAILED = 162, - IPC_GLB_REPLY_PPL_RESTORE_FAILED = 163, - - IPC_MAX_STATUS = ((1<tx.data, tx_data, tx_size); -} - -static bool skl_ipc_is_dsp_busy(struct sst_dsp *dsp) -{ - u32 hipci; - - hipci = sst_dsp_shim_read_unlocked(dsp, SKL_ADSP_REG_HIPCI); - return (hipci & SKL_ADSP_REG_HIPCI_BUSY); -} - -/* Lock to be held by caller */ -static void skl_ipc_tx_msg(struct sst_generic_ipc *ipc, struct ipc_message *msg) -{ - struct skl_ipc_header *header = (struct skl_ipc_header *)(&msg->tx.header); - - if (msg->tx.size) - sst_dsp_outbox_write(ipc->dsp, msg->tx.data, msg->tx.size); - sst_dsp_shim_write_unlocked(ipc->dsp, SKL_ADSP_REG_HIPCIE, - header->extension); - sst_dsp_shim_write_unlocked(ipc->dsp, SKL_ADSP_REG_HIPCI, - header->primary | SKL_ADSP_REG_HIPCI_BUSY); -} - -int skl_ipc_check_D0i0(struct sst_dsp *dsp, bool state) -{ - int ret; - - /* check D0i3 support */ - if (!dsp->fw_ops.set_state_D0i0) - return 0; - - /* Attempt D0i0 or D0i3 based on state */ - if (state) - ret = dsp->fw_ops.set_state_D0i0(dsp); - else - ret = dsp->fw_ops.set_state_D0i3(dsp); - - return ret; -} - -static struct ipc_message *skl_ipc_reply_get_msg(struct sst_generic_ipc *ipc, - u64 ipc_header) -{ - struct ipc_message *msg = NULL; - struct skl_ipc_header *header = (struct skl_ipc_header *)(&ipc_header); - - if (list_empty(&ipc->rx_list)) { - dev_err(ipc->dev, "ipc: rx list is empty but received 0x%x\n", - header->primary); - goto out; - } - - msg = list_first_entry(&ipc->rx_list, struct ipc_message, list); - - list_del(&msg->list); -out: - return msg; - -} - -int skl_ipc_process_notification(struct sst_generic_ipc *ipc, - struct skl_ipc_header header) -{ - struct skl_dev *skl = container_of(ipc, struct skl_dev, ipc); - - if (IPC_GLB_NOTIFY_MSG_TYPE(header.primary)) { - switch (IPC_GLB_NOTIFY_TYPE(header.primary)) { - - case IPC_GLB_NOTIFY_UNDERRUN: - dev_err(ipc->dev, "FW Underrun %x\n", header.primary); - break; - - case IPC_GLB_NOTIFY_RESOURCE_EVENT: - dev_err(ipc->dev, "MCPS Budget Violation: %x\n", - header.primary); - break; - - case IPC_GLB_NOTIFY_FW_READY: - skl->boot_complete = true; - wake_up(&skl->boot_wait); - break; - - case IPC_GLB_NOTIFY_PHRASE_DETECTED: - dev_dbg(ipc->dev, "***** Phrase Detected **********\n"); - - /* - * Per HW recomendation, After phrase detection, - * clear the CGCTL.MISCBDCGE. - * - * This will be set back on stream closure - */ - skl->enable_miscbdcge(ipc->dev, false); - skl->miscbdcg_disabled = true; - break; - - default: - dev_err(ipc->dev, "ipc: Unhandled error msg=%x\n", - header.primary); - break; - } - } - - return 0; -} - -struct skl_ipc_err_map { - const char *msg; - enum skl_ipc_glb_reply reply; - int err; -}; - -static struct skl_ipc_err_map skl_err_map[] = { - {"DSP out of memory", IPC_GLB_REPLY_OUT_OF_MEMORY, -ENOMEM}, - {"DSP busy", IPC_GLB_REPLY_BUSY, -EBUSY}, - {"SCLK already running", IPC_GLB_REPLY_SCLK_ALREADY_RUNNING, - IPC_GLB_REPLY_SCLK_ALREADY_RUNNING}, - {"MCLK already running", IPC_GLB_REPLY_MCLK_ALREADY_RUNNING, - IPC_GLB_REPLY_MCLK_ALREADY_RUNNING}, -}; - -static int skl_ipc_set_reply_error_code(struct sst_generic_ipc *ipc, u32 reply) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(skl_err_map); i++) { - if (skl_err_map[i].reply == reply) - break; - } - - if (i == ARRAY_SIZE(skl_err_map)) { - dev_err(ipc->dev, "ipc FW reply: %d FW Error Code: %u\n", - reply, - ipc->dsp->fw_ops.get_fw_errcode(ipc->dsp)); - return -EINVAL; - } - - if (skl_err_map[i].err < 0) - dev_err(ipc->dev, "ipc FW reply: %s FW Error Code: %u\n", - skl_err_map[i].msg, - ipc->dsp->fw_ops.get_fw_errcode(ipc->dsp)); - else - dev_info(ipc->dev, "ipc FW reply: %s FW Error Code: %u\n", - skl_err_map[i].msg, - ipc->dsp->fw_ops.get_fw_errcode(ipc->dsp)); - - return skl_err_map[i].err; -} - -void skl_ipc_process_reply(struct sst_generic_ipc *ipc, - struct skl_ipc_header header) -{ - struct ipc_message *msg; - u32 reply = header.primary & IPC_GLB_REPLY_STATUS_MASK; - u64 *ipc_header = (u64 *)(&header); - struct skl_dev *skl = container_of(ipc, struct skl_dev, ipc); - unsigned long flags; - - spin_lock_irqsave(&ipc->dsp->spinlock, flags); - msg = skl_ipc_reply_get_msg(ipc, *ipc_header); - spin_unlock_irqrestore(&ipc->dsp->spinlock, flags); - if (msg == NULL) { - dev_dbg(ipc->dev, "ipc: rx list is empty\n"); - return; - } - - msg->rx.header = *ipc_header; - /* first process the header */ - if (reply == IPC_GLB_REPLY_SUCCESS) { - dev_dbg(ipc->dev, "ipc FW reply %x: success\n", header.primary); - /* copy the rx data from the mailbox */ - sst_dsp_inbox_read(ipc->dsp, msg->rx.data, msg->rx.size); - switch (IPC_GLB_NOTIFY_MSG_TYPE(header.primary)) { - case IPC_GLB_LOAD_MULTIPLE_MODS: - case IPC_GLB_LOAD_LIBRARY: - skl->mod_load_complete = true; - skl->mod_load_status = true; - wake_up(&skl->mod_load_wait); - break; - - default: - break; - - } - } else { - msg->errno = skl_ipc_set_reply_error_code(ipc, reply); - switch (IPC_GLB_NOTIFY_MSG_TYPE(header.primary)) { - case IPC_GLB_LOAD_MULTIPLE_MODS: - case IPC_GLB_LOAD_LIBRARY: - skl->mod_load_complete = true; - skl->mod_load_status = false; - wake_up(&skl->mod_load_wait); - break; - - default: - break; - - } - } - - spin_lock_irqsave(&ipc->dsp->spinlock, flags); - sst_ipc_tx_msg_reply_complete(ipc, msg); - spin_unlock_irqrestore(&ipc->dsp->spinlock, flags); -} - -irqreturn_t skl_dsp_irq_thread_handler(int irq, void *context) -{ - struct sst_dsp *dsp = context; - struct skl_dev *skl = dsp->thread_context; - struct sst_generic_ipc *ipc = &skl->ipc; - struct skl_ipc_header header = {0}; - u32 hipcie, hipct, hipcte; - int ipc_irq = 0; - - if (dsp->intr_status & SKL_ADSPIS_CL_DMA) - skl_cldma_process_intr(dsp); - - /* Here we handle IPC interrupts only */ - if (!(dsp->intr_status & SKL_ADSPIS_IPC)) - return IRQ_NONE; - - hipcie = sst_dsp_shim_read_unlocked(dsp, SKL_ADSP_REG_HIPCIE); - hipct = sst_dsp_shim_read_unlocked(dsp, SKL_ADSP_REG_HIPCT); - hipcte = sst_dsp_shim_read_unlocked(dsp, SKL_ADSP_REG_HIPCTE); - - /* reply message from DSP */ - if (hipcie & SKL_ADSP_REG_HIPCIE_DONE) { - sst_dsp_shim_update_bits(dsp, SKL_ADSP_REG_HIPCCTL, - SKL_ADSP_REG_HIPCCTL_DONE, 0); - - /* clear DONE bit - tell DSP we have completed the operation */ - sst_dsp_shim_update_bits_forced(dsp, SKL_ADSP_REG_HIPCIE, - SKL_ADSP_REG_HIPCIE_DONE, SKL_ADSP_REG_HIPCIE_DONE); - - ipc_irq = 1; - - /* unmask Done interrupt */ - sst_dsp_shim_update_bits(dsp, SKL_ADSP_REG_HIPCCTL, - SKL_ADSP_REG_HIPCCTL_DONE, SKL_ADSP_REG_HIPCCTL_DONE); - } - - /* New message from DSP */ - if (hipct & SKL_ADSP_REG_HIPCT_BUSY) { - header.primary = hipct; - header.extension = hipcte; - dev_dbg(dsp->dev, "IPC irq: Firmware respond primary:%x\n", - header.primary); - dev_dbg(dsp->dev, "IPC irq: Firmware respond extension:%x\n", - header.extension); - - if (IPC_GLB_NOTIFY_RSP_TYPE(header.primary)) { - /* Handle Immediate reply from DSP Core */ - skl_ipc_process_reply(ipc, header); - } else { - dev_dbg(dsp->dev, "IPC irq: Notification from firmware\n"); - skl_ipc_process_notification(ipc, header); - } - /* clear busy interrupt */ - sst_dsp_shim_update_bits_forced(dsp, SKL_ADSP_REG_HIPCT, - SKL_ADSP_REG_HIPCT_BUSY, SKL_ADSP_REG_HIPCT_BUSY); - ipc_irq = 1; - } - - if (ipc_irq == 0) - return IRQ_NONE; - - skl_ipc_int_enable(dsp); - - /* continue to send any remaining messages... */ - schedule_work(&ipc->kwork); - - return IRQ_HANDLED; -} - -void skl_ipc_int_enable(struct sst_dsp *ctx) -{ - sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_ADSPIC, - SKL_ADSPIC_IPC, SKL_ADSPIC_IPC); -} - -void skl_ipc_int_disable(struct sst_dsp *ctx) -{ - sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPIC, - SKL_ADSPIC_IPC, 0); -} - -void skl_ipc_op_int_enable(struct sst_dsp *ctx) -{ - /* enable IPC DONE interrupt */ - sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_HIPCCTL, - SKL_ADSP_REG_HIPCCTL_DONE, SKL_ADSP_REG_HIPCCTL_DONE); - - /* Enable IPC BUSY interrupt */ - sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_HIPCCTL, - SKL_ADSP_REG_HIPCCTL_BUSY, SKL_ADSP_REG_HIPCCTL_BUSY); -} - -void skl_ipc_op_int_disable(struct sst_dsp *ctx) -{ - /* disable IPC DONE interrupt */ - sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_HIPCCTL, - SKL_ADSP_REG_HIPCCTL_DONE, 0); - - /* Disable IPC BUSY interrupt */ - sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_HIPCCTL, - SKL_ADSP_REG_HIPCCTL_BUSY, 0); - -} - -bool skl_ipc_int_status(struct sst_dsp *ctx) -{ - return sst_dsp_shim_read_unlocked(ctx, - SKL_ADSP_REG_ADSPIS) & SKL_ADSPIS_IPC; -} - -int skl_ipc_init(struct device *dev, struct skl_dev *skl) -{ - struct sst_generic_ipc *ipc; - int err; - - ipc = &skl->ipc; - ipc->dsp = skl->dsp; - ipc->dev = dev; - - ipc->tx_data_max_size = SKL_ADSP_W1_SZ; - ipc->rx_data_max_size = SKL_ADSP_W0_UP_SZ; - - err = sst_ipc_init(ipc); - if (err) - return err; - - ipc->ops.tx_msg = skl_ipc_tx_msg; - ipc->ops.tx_data_copy = skl_ipc_tx_data_copy; - ipc->ops.is_dsp_busy = skl_ipc_is_dsp_busy; - - return 0; -} - -void skl_ipc_free(struct sst_generic_ipc *ipc) -{ - /* Disable IPC DONE interrupt */ - sst_dsp_shim_update_bits(ipc->dsp, SKL_ADSP_REG_HIPCCTL, - SKL_ADSP_REG_HIPCCTL_DONE, 0); - - /* Disable IPC BUSY interrupt */ - sst_dsp_shim_update_bits(ipc->dsp, SKL_ADSP_REG_HIPCCTL, - SKL_ADSP_REG_HIPCCTL_BUSY, 0); - - sst_ipc_fini(ipc); -} - -int skl_ipc_create_pipeline(struct sst_generic_ipc *ipc, - u16 ppl_mem_size, u8 ppl_type, u8 instance_id, u8 lp_mode) -{ - struct skl_ipc_header header = {0}; - struct sst_ipc_message request = {0}; - int ret; - - header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG); - header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST); - header.primary |= IPC_GLB_TYPE(IPC_GLB_CREATE_PPL); - header.primary |= IPC_INSTANCE_ID(instance_id); - header.primary |= IPC_PPL_TYPE(ppl_type); - header.primary |= IPC_PPL_MEM_SIZE(ppl_mem_size); - - header.extension = IPC_PPL_LP_MODE(lp_mode); - request.header = *(u64 *)(&header); - - dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary); - ret = sst_ipc_tx_message_wait(ipc, request, NULL); - if (ret < 0) { - dev_err(ipc->dev, "ipc: create pipeline fail, err: %d\n", ret); - return ret; - } - - return ret; -} -EXPORT_SYMBOL_GPL(skl_ipc_create_pipeline); - -int skl_ipc_delete_pipeline(struct sst_generic_ipc *ipc, u8 instance_id) -{ - struct skl_ipc_header header = {0}; - struct sst_ipc_message request = {0}; - int ret; - - header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG); - header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST); - header.primary |= IPC_GLB_TYPE(IPC_GLB_DELETE_PPL); - header.primary |= IPC_INSTANCE_ID(instance_id); - request.header = *(u64 *)(&header); - - dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary); - ret = sst_ipc_tx_message_wait(ipc, request, NULL); - if (ret < 0) { - dev_err(ipc->dev, "ipc: delete pipeline failed, err %d\n", ret); - return ret; - } - - return 0; -} -EXPORT_SYMBOL_GPL(skl_ipc_delete_pipeline); - -int skl_ipc_set_pipeline_state(struct sst_generic_ipc *ipc, - u8 instance_id, enum skl_ipc_pipeline_state state) -{ - struct skl_ipc_header header = {0}; - struct sst_ipc_message request = {0}; - int ret; - - header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG); - header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST); - header.primary |= IPC_GLB_TYPE(IPC_GLB_SET_PPL_STATE); - header.primary |= IPC_INSTANCE_ID(instance_id); - header.primary |= IPC_PPL_STATE(state); - request.header = *(u64 *)(&header); - - dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary); - ret = sst_ipc_tx_message_wait(ipc, request, NULL); - if (ret < 0) { - dev_err(ipc->dev, "ipc: set pipeline state failed, err: %d\n", ret); - return ret; - } - return ret; -} -EXPORT_SYMBOL_GPL(skl_ipc_set_pipeline_state); - -int -skl_ipc_save_pipeline(struct sst_generic_ipc *ipc, u8 instance_id, int dma_id) -{ - struct skl_ipc_header header = {0}; - struct sst_ipc_message request = {0}; - int ret; - - header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG); - header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST); - header.primary |= IPC_GLB_TYPE(IPC_GLB_SAVE_PPL); - header.primary |= IPC_INSTANCE_ID(instance_id); - - header.extension = IPC_DMA_ID(dma_id); - request.header = *(u64 *)(&header); - - dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary); - ret = sst_ipc_tx_message_wait(ipc, request, NULL); - if (ret < 0) { - dev_err(ipc->dev, "ipc: save pipeline failed, err: %d\n", ret); - return ret; - } - - return ret; -} -EXPORT_SYMBOL_GPL(skl_ipc_save_pipeline); - -int skl_ipc_restore_pipeline(struct sst_generic_ipc *ipc, u8 instance_id) -{ - struct skl_ipc_header header = {0}; - struct sst_ipc_message request = {0}; - int ret; - - header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG); - header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST); - header.primary |= IPC_GLB_TYPE(IPC_GLB_RESTORE_PPL); - header.primary |= IPC_INSTANCE_ID(instance_id); - request.header = *(u64 *)(&header); - - dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary); - ret = sst_ipc_tx_message_wait(ipc, request, NULL); - if (ret < 0) { - dev_err(ipc->dev, "ipc: restore pipeline failed, err: %d\n", ret); - return ret; - } - - return ret; -} -EXPORT_SYMBOL_GPL(skl_ipc_restore_pipeline); - -int skl_ipc_set_dx(struct sst_generic_ipc *ipc, u8 instance_id, - u16 module_id, struct skl_ipc_dxstate_info *dx) -{ - struct skl_ipc_header header = {0}; - struct sst_ipc_message request; - int ret; - - header.primary = IPC_MSG_TARGET(IPC_MOD_MSG); - header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST); - header.primary |= IPC_GLB_TYPE(IPC_MOD_SET_DX); - header.primary |= IPC_MOD_INSTANCE_ID(instance_id); - header.primary |= IPC_MOD_ID(module_id); - - request.header = *(u64 *)(&header); - request.data = dx; - request.size = sizeof(*dx); - - dev_dbg(ipc->dev, "In %s primary =%x ext=%x\n", __func__, - header.primary, header.extension); - ret = sst_ipc_tx_message_wait(ipc, request, NULL); - if (ret < 0) { - dev_err(ipc->dev, "ipc: set dx failed, err %d\n", ret); - return ret; - } - - return ret; -} -EXPORT_SYMBOL_GPL(skl_ipc_set_dx); - -int skl_ipc_init_instance(struct sst_generic_ipc *ipc, - struct skl_ipc_init_instance_msg *msg, void *param_data) -{ - struct skl_ipc_header header = {0}; - struct sst_ipc_message request; - int ret; - u32 *buffer = (u32 *)param_data; - /* param_block_size must be in dwords */ - u16 param_block_size = msg->param_data_size / sizeof(u32); - - print_hex_dump_debug("Param data:", DUMP_PREFIX_NONE, - 16, 4, buffer, param_block_size, false); - - header.primary = IPC_MSG_TARGET(IPC_MOD_MSG); - header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST); - header.primary |= IPC_GLB_TYPE(IPC_MOD_INIT_INSTANCE); - header.primary |= IPC_MOD_INSTANCE_ID(msg->instance_id); - header.primary |= IPC_MOD_ID(msg->module_id); - - header.extension = IPC_CORE_ID(msg->core_id); - header.extension |= IPC_PPL_INSTANCE_ID(msg->ppl_instance_id); - header.extension |= IPC_PARAM_BLOCK_SIZE(param_block_size); - header.extension |= IPC_DOMAIN(msg->domain); - - request.header = *(u64 *)(&header); - request.data = param_data; - request.size = msg->param_data_size; - - dev_dbg(ipc->dev, "In %s primary =%x ext=%x\n", __func__, - header.primary, header.extension); - ret = sst_ipc_tx_message_wait(ipc, request, NULL); - - if (ret < 0) { - dev_err(ipc->dev, "ipc: init instance failed\n"); - return ret; - } - - return ret; -} -EXPORT_SYMBOL_GPL(skl_ipc_init_instance); - -int skl_ipc_bind_unbind(struct sst_generic_ipc *ipc, - struct skl_ipc_bind_unbind_msg *msg) -{ - struct skl_ipc_header header = {0}; - struct sst_ipc_message request = {0}; - u8 bind_unbind = msg->bind ? IPC_MOD_BIND : IPC_MOD_UNBIND; - int ret; - - header.primary = IPC_MSG_TARGET(IPC_MOD_MSG); - header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST); - header.primary |= IPC_GLB_TYPE(bind_unbind); - header.primary |= IPC_MOD_INSTANCE_ID(msg->instance_id); - header.primary |= IPC_MOD_ID(msg->module_id); - - header.extension = IPC_DST_MOD_ID(msg->dst_module_id); - header.extension |= IPC_DST_MOD_INSTANCE_ID(msg->dst_instance_id); - header.extension |= IPC_DST_QUEUE(msg->dst_queue); - header.extension |= IPC_SRC_QUEUE(msg->src_queue); - request.header = *(u64 *)(&header); - - dev_dbg(ipc->dev, "In %s hdr=%x ext=%x\n", __func__, header.primary, - header.extension); - ret = sst_ipc_tx_message_wait(ipc, request, NULL); - if (ret < 0) { - dev_err(ipc->dev, "ipc: bind/unbind failed\n"); - return ret; - } - - return ret; -} -EXPORT_SYMBOL_GPL(skl_ipc_bind_unbind); - -/* - * In order to load a module we need to send IPC to initiate that. DMA will - * performed to load the module memory. The FW supports multiple module load - * at single shot, so we can send IPC with N modules represented by - * module_cnt - */ -int skl_ipc_load_modules(struct sst_generic_ipc *ipc, - u8 module_cnt, void *data) -{ - struct skl_ipc_header header = {0}; - struct sst_ipc_message request; - int ret; - - header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG); - header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST); - header.primary |= IPC_GLB_TYPE(IPC_GLB_LOAD_MULTIPLE_MODS); - header.primary |= IPC_LOAD_MODULE_CNT(module_cnt); - - request.header = *(u64 *)(&header); - request.data = data; - request.size = sizeof(u16) * module_cnt; - - ret = sst_ipc_tx_message_nowait(ipc, request); - if (ret < 0) - dev_err(ipc->dev, "ipc: load modules failed :%d\n", ret); - - return ret; -} -EXPORT_SYMBOL_GPL(skl_ipc_load_modules); - -int skl_ipc_unload_modules(struct sst_generic_ipc *ipc, u8 module_cnt, - void *data) -{ - struct skl_ipc_header header = {0}; - struct sst_ipc_message request; - int ret; - - header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG); - header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST); - header.primary |= IPC_GLB_TYPE(IPC_GLB_UNLOAD_MULTIPLE_MODS); - header.primary |= IPC_LOAD_MODULE_CNT(module_cnt); - - request.header = *(u64 *)(&header); - request.data = data; - request.size = sizeof(u16) * module_cnt; - - ret = sst_ipc_tx_message_wait(ipc, request, NULL); - if (ret < 0) - dev_err(ipc->dev, "ipc: unload modules failed :%d\n", ret); - - return ret; -} -EXPORT_SYMBOL_GPL(skl_ipc_unload_modules); - -int skl_ipc_set_large_config(struct sst_generic_ipc *ipc, - struct skl_ipc_large_config_msg *msg, u32 *param) -{ - struct skl_ipc_header header = {0}; - struct sst_ipc_message request; - int ret = 0; - size_t sz_remaining, tx_size, data_offset; - - header.primary = IPC_MSG_TARGET(IPC_MOD_MSG); - header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST); - header.primary |= IPC_GLB_TYPE(IPC_MOD_LARGE_CONFIG_SET); - header.primary |= IPC_MOD_INSTANCE_ID(msg->instance_id); - header.primary |= IPC_MOD_ID(msg->module_id); - - header.extension = IPC_DATA_OFFSET_SZ(msg->param_data_size); - header.extension |= IPC_LARGE_PARAM_ID(msg->large_param_id); - header.extension |= IPC_FINAL_BLOCK(0); - header.extension |= IPC_INITIAL_BLOCK(1); - - sz_remaining = msg->param_data_size; - data_offset = 0; - while (sz_remaining != 0) { - tx_size = sz_remaining > SKL_ADSP_W1_SZ - ? SKL_ADSP_W1_SZ : sz_remaining; - if (tx_size == sz_remaining) - header.extension |= IPC_FINAL_BLOCK(1); - - dev_dbg(ipc->dev, "In %s primary=%#x ext=%#x\n", __func__, - header.primary, header.extension); - dev_dbg(ipc->dev, "transmitting offset: %#x, size: %#x\n", - (unsigned)data_offset, (unsigned)tx_size); - - request.header = *(u64 *)(&header); - request.data = ((char *)param) + data_offset; - request.size = tx_size; - ret = sst_ipc_tx_message_wait(ipc, request, NULL); - if (ret < 0) { - dev_err(ipc->dev, - "ipc: set large config fail, err: %d\n", ret); - return ret; - } - sz_remaining -= tx_size; - data_offset = msg->param_data_size - sz_remaining; - - /* clear the fields */ - header.extension &= IPC_INITIAL_BLOCK_CLEAR; - header.extension &= IPC_DATA_OFFSET_SZ_CLEAR; - /* fill the fields */ - header.extension |= IPC_INITIAL_BLOCK(0); - header.extension |= IPC_DATA_OFFSET_SZ(data_offset); - } - - return ret; -} -EXPORT_SYMBOL_GPL(skl_ipc_set_large_config); - -int skl_ipc_get_large_config(struct sst_generic_ipc *ipc, - struct skl_ipc_large_config_msg *msg, - u32 **payload, size_t *bytes) -{ - struct skl_ipc_header header = {0}; - struct sst_ipc_message request, reply = {0}; - unsigned int *buf; - int ret; - - reply.data = kzalloc(SKL_ADSP_W1_SZ, GFP_KERNEL); - if (!reply.data) - return -ENOMEM; - - header.primary = IPC_MSG_TARGET(IPC_MOD_MSG); - header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST); - header.primary |= IPC_GLB_TYPE(IPC_MOD_LARGE_CONFIG_GET); - header.primary |= IPC_MOD_INSTANCE_ID(msg->instance_id); - header.primary |= IPC_MOD_ID(msg->module_id); - - header.extension = IPC_DATA_OFFSET_SZ(msg->param_data_size); - header.extension |= IPC_LARGE_PARAM_ID(msg->large_param_id); - header.extension |= IPC_FINAL_BLOCK(1); - header.extension |= IPC_INITIAL_BLOCK(1); - - request.header = *(u64 *)&header; - request.data = *payload; - request.size = *bytes; - reply.size = SKL_ADSP_W1_SZ; - - ret = sst_ipc_tx_message_wait(ipc, request, &reply); - if (ret < 0) - dev_err(ipc->dev, "ipc: get large config fail, err: %d\n", ret); - - reply.size = (reply.header >> 32) & IPC_DATA_OFFSET_SZ_MASK; - buf = krealloc(reply.data, reply.size, GFP_KERNEL); - if (!buf) { - kfree(reply.data); - return -ENOMEM; - } - *payload = buf; - *bytes = reply.size; - - return ret; -} -EXPORT_SYMBOL_GPL(skl_ipc_get_large_config); - -int skl_sst_ipc_load_library(struct sst_generic_ipc *ipc, - u8 dma_id, u8 table_id, bool wait) -{ - struct skl_ipc_header header = {0}; - struct sst_ipc_message request = {0}; - int ret = 0; - - header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG); - header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST); - header.primary |= IPC_GLB_TYPE(IPC_GLB_LOAD_LIBRARY); - header.primary |= IPC_MOD_INSTANCE_ID(table_id); - header.primary |= IPC_MOD_ID(dma_id); - request.header = *(u64 *)(&header); - - if (wait) - ret = sst_ipc_tx_message_wait(ipc, request, NULL); - else - ret = sst_ipc_tx_message_nowait(ipc, request); - - if (ret < 0) - dev_err(ipc->dev, "ipc: load lib failed\n"); - - return ret; -} -EXPORT_SYMBOL_GPL(skl_sst_ipc_load_library); - -int skl_ipc_set_d0ix(struct sst_generic_ipc *ipc, struct skl_ipc_d0ix_msg *msg) -{ - struct skl_ipc_header header = {0}; - struct sst_ipc_message request = {0}; - int ret; - - header.primary = IPC_MSG_TARGET(IPC_MOD_MSG); - header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST); - header.primary |= IPC_GLB_TYPE(IPC_MOD_SET_D0IX); - header.primary |= IPC_MOD_INSTANCE_ID(msg->instance_id); - header.primary |= IPC_MOD_ID(msg->module_id); - - header.extension = IPC_D0IX_WAKE(msg->wake); - header.extension |= IPC_D0IX_STREAMING(msg->streaming); - request.header = *(u64 *)(&header); - - dev_dbg(ipc->dev, "In %s primary=%x ext=%x\n", __func__, - header.primary, header.extension); - - /* - * Use the nopm IPC here as we dont want it checking for D0iX - */ - ret = sst_ipc_tx_message_nopm(ipc, request, NULL); - if (ret < 0) - dev_err(ipc->dev, "ipc: set d0ix failed, err %d\n", ret); - - return ret; -} -EXPORT_SYMBOL_GPL(skl_ipc_set_d0ix); diff --git a/sound/soc/intel/skylake/skl-sst-ipc.h b/sound/soc/intel/skylake/skl-sst-ipc.h deleted file mode 100644 index aaaab3b3ec428c..00000000000000 --- a/sound/soc/intel/skylake/skl-sst-ipc.h +++ /dev/null @@ -1,169 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Intel SKL IPC Support - * - * Copyright (C) 2014-15, Intel Corporation. - */ - -#ifndef __SKL_IPC_H -#define __SKL_IPC_H - -#include -#include "../common/sst-ipc.h" -#include "skl-sst-dsp.h" - -struct sst_dsp; -struct sst_generic_ipc; - -enum skl_ipc_pipeline_state { - PPL_INVALID_STATE = 0, - PPL_UNINITIALIZED = 1, - PPL_RESET = 2, - PPL_PAUSED = 3, - PPL_RUNNING = 4, - PPL_ERROR_STOP = 5, - PPL_SAVED = 6, - PPL_RESTORED = 7 -}; - -struct skl_ipc_dxstate_info { - u32 core_mask; - u32 dx_mask; -}; - -struct skl_ipc_header { - u32 primary; - u32 extension; -}; - -struct skl_dsp_cores { - unsigned int count; - enum skl_dsp_states *state; - int *usage_count; -}; - -/** - * skl_d0i3_data: skl D0i3 counters data struct - * - * @streaming: Count of usecases that can attempt streaming D0i3 - * @non_streaming: Count of usecases that can attempt non-streaming D0i3 - * @non_d0i3: Count of usecases that cannot attempt D0i3 - * @state: current state - * @work: D0i3 worker thread - */ -struct skl_d0i3_data { - int streaming; - int non_streaming; - int non_d0i3; - enum skl_dsp_d0i3_states state; - struct delayed_work work; -}; - -#define SKL_LIB_NAME_LENGTH 128 -#define SKL_MAX_LIB 16 - -struct skl_lib_info { - char name[SKL_LIB_NAME_LENGTH]; - const struct firmware *fw; -}; - -struct skl_ipc_init_instance_msg { - u32 module_id; - u32 instance_id; - u16 param_data_size; - u8 ppl_instance_id; - u8 core_id; - u8 domain; -}; - -struct skl_ipc_bind_unbind_msg { - u32 module_id; - u32 instance_id; - u32 dst_module_id; - u32 dst_instance_id; - u8 src_queue; - u8 dst_queue; - bool bind; -}; - -struct skl_ipc_large_config_msg { - u32 module_id; - u32 instance_id; - u32 large_param_id; - u32 param_data_size; -}; - -struct skl_ipc_d0ix_msg { - u32 module_id; - u32 instance_id; - u8 streaming; - u8 wake; -}; - -#define SKL_IPC_BOOT_MSECS 3000 - -#define SKL_IPC_D3_MASK 0 -#define SKL_IPC_D0_MASK 3 - -irqreturn_t skl_dsp_irq_thread_handler(int irq, void *context); - -int skl_ipc_create_pipeline(struct sst_generic_ipc *ipc, - u16 ppl_mem_size, u8 ppl_type, u8 instance_id, u8 lp_mode); - -int skl_ipc_delete_pipeline(struct sst_generic_ipc *ipc, u8 instance_id); - -int skl_ipc_set_pipeline_state(struct sst_generic_ipc *ipc, - u8 instance_id, enum skl_ipc_pipeline_state state); - -int skl_ipc_save_pipeline(struct sst_generic_ipc *ipc, - u8 instance_id, int dma_id); - -int skl_ipc_restore_pipeline(struct sst_generic_ipc *ipc, u8 instance_id); - -int skl_ipc_init_instance(struct sst_generic_ipc *ipc, - struct skl_ipc_init_instance_msg *msg, void *param_data); - -int skl_ipc_bind_unbind(struct sst_generic_ipc *ipc, - struct skl_ipc_bind_unbind_msg *msg); - -int skl_ipc_load_modules(struct sst_generic_ipc *ipc, - u8 module_cnt, void *data); - -int skl_ipc_unload_modules(struct sst_generic_ipc *ipc, - u8 module_cnt, void *data); - -int skl_ipc_set_dx(struct sst_generic_ipc *ipc, - u8 instance_id, u16 module_id, struct skl_ipc_dxstate_info *dx); - -int skl_ipc_set_large_config(struct sst_generic_ipc *ipc, - struct skl_ipc_large_config_msg *msg, u32 *param); - -int skl_ipc_get_large_config(struct sst_generic_ipc *ipc, - struct skl_ipc_large_config_msg *msg, - u32 **payload, size_t *bytes); - -int skl_sst_ipc_load_library(struct sst_generic_ipc *ipc, - u8 dma_id, u8 table_id, bool wait); - -int skl_ipc_set_d0ix(struct sst_generic_ipc *ipc, - struct skl_ipc_d0ix_msg *msg); - -int skl_ipc_check_D0i0(struct sst_dsp *dsp, bool state); - -void skl_ipc_int_enable(struct sst_dsp *ctx); -void skl_ipc_op_int_enable(struct sst_dsp *ctx); -void skl_ipc_op_int_disable(struct sst_dsp *ctx); -void skl_ipc_int_disable(struct sst_dsp *ctx); - -bool skl_ipc_int_status(struct sst_dsp *ctx); -void skl_ipc_free(struct sst_generic_ipc *ipc); -int skl_ipc_init(struct device *dev, struct skl_dev *skl); -void skl_clear_module_cnt(struct sst_dsp *ctx); - -void skl_ipc_process_reply(struct sst_generic_ipc *ipc, - struct skl_ipc_header header); -int skl_ipc_process_notification(struct sst_generic_ipc *ipc, - struct skl_ipc_header header); -void skl_ipc_tx_data_copy(struct ipc_message *msg, char *tx_data, - size_t tx_size); -#endif /* __SKL_IPC_H */ diff --git a/sound/soc/intel/skylake/skl-sst-utils.c b/sound/soc/intel/skylake/skl-sst-utils.c deleted file mode 100644 index b776c58dcf47a1..00000000000000 --- a/sound/soc/intel/skylake/skl-sst-utils.c +++ /dev/null @@ -1,425 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * skl-sst-utils.c - SKL sst utils functions - * - * Copyright (C) 2016 Intel Corp - */ - -#include -#include -#include -#include "../common/sst-dsp.h" -#include "../common/sst-dsp-priv.h" -#include "skl.h" - -#define DEFAULT_HASH_SHA256_LEN 32 - -/* FW Extended Manifest Header id = $AE1 */ -#define SKL_EXT_MANIFEST_HEADER_MAGIC 0x31454124 - -union seg_flags { - u32 ul; - struct { - u32 contents : 1; - u32 alloc : 1; - u32 load : 1; - u32 read_only : 1; - u32 code : 1; - u32 data : 1; - u32 _rsvd0 : 2; - u32 type : 4; - u32 _rsvd1 : 4; - u32 length : 16; - } r; -} __packed; - -struct segment_desc { - union seg_flags flags; - u32 v_base_addr; - u32 file_offset; -}; - -struct module_type { - u32 load_type : 4; - u32 auto_start : 1; - u32 domain_ll : 1; - u32 domain_dp : 1; - u32 rsvd : 25; -} __packed; - -struct adsp_module_entry { - u32 struct_id; - u8 name[8]; - u8 uuid[16]; - struct module_type type; - u8 hash1[DEFAULT_HASH_SHA256_LEN]; - u32 entry_point; - u16 cfg_offset; - u16 cfg_count; - u32 affinity_mask; - u16 instance_max_count; - u16 instance_bss_size; - struct segment_desc segments[3]; -} __packed; - -struct adsp_fw_hdr { - u32 id; - u32 len; - u8 name[8]; - u32 preload_page_count; - u32 fw_image_flags; - u32 feature_mask; - u16 major; - u16 minor; - u16 hotfix; - u16 build; - u32 num_modules; - u32 hw_buf_base; - u32 hw_buf_length; - u32 load_offset; -} __packed; - -struct skl_ext_manifest_hdr { - u32 id; - u32 len; - u16 version_major; - u16 version_minor; - u32 entries; -}; - -static int skl_get_pvtid_map(struct uuid_module *module, int instance_id) -{ - int pvt_id; - - for (pvt_id = 0; pvt_id < module->max_instance; pvt_id++) { - if (module->instance_id[pvt_id] == instance_id) - return pvt_id; - } - return -EINVAL; -} - -int skl_get_pvt_instance_id_map(struct skl_dev *skl, - int module_id, int instance_id) -{ - struct uuid_module *module; - - list_for_each_entry(module, &skl->uuid_list, list) { - if (module->id == module_id) - return skl_get_pvtid_map(module, instance_id); - } - - return -EINVAL; -} -EXPORT_SYMBOL_GPL(skl_get_pvt_instance_id_map); - -static inline int skl_getid_32(struct uuid_module *module, u64 *val, - int word1_mask, int word2_mask) -{ - int index, max_inst, pvt_id; - u32 mask_val; - - max_inst = module->max_instance; - mask_val = (u32)(*val >> word1_mask); - - if (mask_val != 0xffffffff) { - index = ffz(mask_val); - pvt_id = index + word1_mask + word2_mask; - if (pvt_id <= (max_inst - 1)) { - *val |= 1ULL << (index + word1_mask); - return pvt_id; - } - } - - return -EINVAL; -} - -static inline int skl_pvtid_128(struct uuid_module *module) -{ - int j, i, word1_mask, word2_mask = 0, pvt_id; - - for (j = 0; j < MAX_INSTANCE_BUFF; j++) { - word1_mask = 0; - - for (i = 0; i < 2; i++) { - pvt_id = skl_getid_32(module, &module->pvt_id[j], - word1_mask, word2_mask); - if (pvt_id >= 0) - return pvt_id; - - word1_mask += 32; - if ((word1_mask + word2_mask) >= module->max_instance) - return -EINVAL; - } - - word2_mask += 64; - if (word2_mask >= module->max_instance) - return -EINVAL; - } - - return -EINVAL; -} - -/** - * skl_get_pvt_id: generate a private id for use as module id - * - * @skl: driver context - * @uuid_mod: module's uuid - * @instance_id: module's instance id - * - * This generates a 128 bit private unique id for a module TYPE so that - * module instance is unique - */ -int skl_get_pvt_id(struct skl_dev *skl, guid_t *uuid_mod, int instance_id) -{ - struct uuid_module *module; - int pvt_id; - - list_for_each_entry(module, &skl->uuid_list, list) { - if (guid_equal(uuid_mod, &module->uuid)) { - - pvt_id = skl_pvtid_128(module); - if (pvt_id >= 0) { - module->instance_id[pvt_id] = instance_id; - - return pvt_id; - } - } - } - - return -EINVAL; -} -EXPORT_SYMBOL_GPL(skl_get_pvt_id); - -/** - * skl_put_pvt_id: free up the private id allocated - * - * @skl: driver context - * @uuid_mod: module's uuid - * @pvt_id: module pvt id - * - * This frees a 128 bit private unique id previously generated - */ -int skl_put_pvt_id(struct skl_dev *skl, guid_t *uuid_mod, int *pvt_id) -{ - int i; - struct uuid_module *module; - - list_for_each_entry(module, &skl->uuid_list, list) { - if (guid_equal(uuid_mod, &module->uuid)) { - - if (*pvt_id != 0) - i = (*pvt_id) / 64; - else - i = 0; - - module->pvt_id[i] &= ~(1 << (*pvt_id)); - *pvt_id = -1; - return 0; - } - } - - return -EINVAL; -} -EXPORT_SYMBOL_GPL(skl_put_pvt_id); - -/* - * Parse the firmware binary to get the UUID, module id - * and loadable flags - */ -int snd_skl_parse_uuids(struct sst_dsp *ctx, const struct firmware *fw, - unsigned int offset, int index) -{ - struct adsp_fw_hdr *adsp_hdr; - struct adsp_module_entry *mod_entry; - int i, num_entry, size; - const char *buf; - struct skl_dev *skl = ctx->thread_context; - struct uuid_module *module; - struct firmware stripped_fw; - unsigned int safe_file; - int ret; - - /* Get the FW pointer to derive ADSP header */ - stripped_fw.data = fw->data; - stripped_fw.size = fw->size; - - skl_dsp_strip_extended_manifest(&stripped_fw); - - buf = stripped_fw.data; - - /* check if we have enough space in file to move to header */ - safe_file = sizeof(*adsp_hdr) + offset; - if (stripped_fw.size <= safe_file) { - dev_err(ctx->dev, "Small fw file size, No space for hdr\n"); - return -EINVAL; - } - - adsp_hdr = (struct adsp_fw_hdr *)(buf + offset); - - /* check 1st module entry is in file */ - safe_file += adsp_hdr->len + sizeof(*mod_entry); - if (stripped_fw.size <= safe_file) { - dev_err(ctx->dev, "Small fw file size, No module entry\n"); - return -EINVAL; - } - - mod_entry = (struct adsp_module_entry *)(buf + offset + adsp_hdr->len); - - num_entry = adsp_hdr->num_modules; - - /* check all entries are in file */ - safe_file += num_entry * sizeof(*mod_entry); - if (stripped_fw.size <= safe_file) { - dev_err(ctx->dev, "Small fw file size, No modules\n"); - return -EINVAL; - } - - - /* - * Read the UUID(GUID) from FW Manifest. - * - * The 16 byte UUID format is: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXX - * Populate the UUID table to store module_id and loadable flags - * for the module. - */ - - for (i = 0; i < num_entry; i++, mod_entry++) { - module = kzalloc(sizeof(*module), GFP_KERNEL); - if (!module) { - ret = -ENOMEM; - goto free_uuid_list; - } - - import_guid(&module->uuid, mod_entry->uuid); - - module->id = (i | (index << 12)); - module->is_loadable = mod_entry->type.load_type; - module->max_instance = mod_entry->instance_max_count; - size = sizeof(int) * mod_entry->instance_max_count; - module->instance_id = devm_kzalloc(ctx->dev, size, GFP_KERNEL); - if (!module->instance_id) { - ret = -ENOMEM; - kfree(module); - goto free_uuid_list; - } - - list_add_tail(&module->list, &skl->uuid_list); - - dev_dbg(ctx->dev, - "Adding uuid :%pUL mod id: %d Loadable: %d\n", - &module->uuid, module->id, module->is_loadable); - } - - return 0; - -free_uuid_list: - skl_freeup_uuid_list(skl); - return ret; -} - -void skl_freeup_uuid_list(struct skl_dev *skl) -{ - struct uuid_module *uuid, *_uuid; - - list_for_each_entry_safe(uuid, _uuid, &skl->uuid_list, list) { - list_del(&uuid->list); - kfree(uuid); - } -} - -/* - * some firmware binary contains some extended manifest. This needs - * to be stripped in that case before we load and use that image. - * - * Get the module id for the module by checking - * the table for the UUID for the module - */ -int skl_dsp_strip_extended_manifest(struct firmware *fw) -{ - struct skl_ext_manifest_hdr *hdr; - - /* check if fw file is greater than header we are looking */ - if (fw->size < sizeof(hdr)) { - pr_err("%s: Firmware file small, no hdr\n", __func__); - return -EINVAL; - } - - hdr = (struct skl_ext_manifest_hdr *)fw->data; - - if (hdr->id == SKL_EXT_MANIFEST_HEADER_MAGIC) { - fw->size -= hdr->len; - fw->data += hdr->len; - } - - return 0; -} - -int skl_sst_ctx_init(struct device *dev, int irq, const char *fw_name, - struct skl_dsp_loader_ops dsp_ops, struct skl_dev **dsp, - struct sst_dsp_device *skl_dev) -{ - struct skl_dev *skl = *dsp; - struct sst_dsp *sst; - - skl->dev = dev; - skl_dev->thread_context = skl; - INIT_LIST_HEAD(&skl->uuid_list); - skl->dsp = skl_dsp_ctx_init(dev, skl_dev, irq); - if (!skl->dsp) { - dev_err(skl->dev, "%s: no device\n", __func__); - return -ENODEV; - } - - sst = skl->dsp; - sst->fw_name = fw_name; - sst->dsp_ops = dsp_ops; - init_waitqueue_head(&skl->mod_load_wait); - INIT_LIST_HEAD(&sst->module_list); - - skl->is_first_boot = true; - - return 0; -} - -int skl_prepare_lib_load(struct skl_dev *skl, struct skl_lib_info *linfo, - struct firmware *stripped_fw, - unsigned int hdr_offset, int index) -{ - int ret; - struct sst_dsp *dsp = skl->dsp; - - if (linfo->fw == NULL) { - ret = request_firmware(&linfo->fw, linfo->name, - skl->dev); - if (ret < 0) { - dev_err(skl->dev, "Request lib %s failed:%d\n", - linfo->name, ret); - return ret; - } - } - - if (skl->is_first_boot) { - ret = snd_skl_parse_uuids(dsp, linfo->fw, hdr_offset, index); - if (ret < 0) - return ret; - } - - stripped_fw->data = linfo->fw->data; - stripped_fw->size = linfo->fw->size; - skl_dsp_strip_extended_manifest(stripped_fw); - - return 0; -} - -void skl_release_library(struct skl_lib_info *linfo, int lib_count) -{ - int i; - - /* library indices start from 1 to N. 0 represents base FW */ - for (i = 1; i < lib_count; i++) { - if (linfo[i].fw) { - release_firmware(linfo[i].fw); - linfo[i].fw = NULL; - } - } -} diff --git a/sound/soc/intel/skylake/skl-sst.c b/sound/soc/intel/skylake/skl-sst.c deleted file mode 100644 index 39d027ac16ec23..00000000000000 --- a/sound/soc/intel/skylake/skl-sst.c +++ /dev/null @@ -1,599 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * skl-sst.c - HDA DSP library functions for SKL platform - * - * Copyright (C) 2014-15, Intel Corporation. - * Author:Rafal Redzimski - * Jeeja KP - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ - -#include -#include -#include -#include -#include -#include "../common/sst-dsp.h" -#include "../common/sst-dsp-priv.h" -#include "../common/sst-ipc.h" -#include "skl.h" - -#define SKL_BASEFW_TIMEOUT 300 -#define SKL_INIT_TIMEOUT 1000 - -/* Intel HD Audio SRAM Window 0*/ -#define SKL_ADSP_SRAM0_BASE 0x8000 - -/* Firmware status window */ -#define SKL_ADSP_FW_STATUS SKL_ADSP_SRAM0_BASE -#define SKL_ADSP_ERROR_CODE (SKL_ADSP_FW_STATUS + 0x4) - -#define SKL_NUM_MODULES 1 - -static bool skl_check_fw_status(struct sst_dsp *ctx, u32 status) -{ - u32 cur_sts; - - cur_sts = sst_dsp_shim_read(ctx, SKL_ADSP_FW_STATUS) & SKL_FW_STS_MASK; - - return (cur_sts == status); -} - -static int skl_transfer_firmware(struct sst_dsp *ctx, - const void *basefw, u32 base_fw_size) -{ - int ret = 0; - - ret = ctx->cl_dev.ops.cl_copy_to_dmabuf(ctx, basefw, base_fw_size, - true); - if (ret < 0) - return ret; - - ret = sst_dsp_register_poll(ctx, - SKL_ADSP_FW_STATUS, - SKL_FW_STS_MASK, - SKL_FW_RFW_START, - SKL_BASEFW_TIMEOUT, - "Firmware boot"); - - ctx->cl_dev.ops.cl_stop_dma(ctx); - - return ret; -} - -#define SKL_ADSP_FW_BIN_HDR_OFFSET 0x284 - -static int skl_load_base_firmware(struct sst_dsp *ctx) -{ - int ret = 0, i; - struct skl_dev *skl = ctx->thread_context; - struct firmware stripped_fw; - u32 reg; - - skl->boot_complete = false; - init_waitqueue_head(&skl->boot_wait); - - if (ctx->fw == NULL) { - ret = request_firmware(&ctx->fw, ctx->fw_name, ctx->dev); - if (ret < 0) { - dev_err(ctx->dev, "Request firmware failed %d\n", ret); - return -EIO; - } - } - - /* prase uuids on first boot */ - if (skl->is_first_boot) { - ret = snd_skl_parse_uuids(ctx, ctx->fw, SKL_ADSP_FW_BIN_HDR_OFFSET, 0); - if (ret < 0) { - dev_err(ctx->dev, "UUID parsing err: %d\n", ret); - release_firmware(ctx->fw); - skl_dsp_disable_core(ctx, SKL_DSP_CORE0_MASK); - return ret; - } - } - - /* check for extended manifest */ - stripped_fw.data = ctx->fw->data; - stripped_fw.size = ctx->fw->size; - - skl_dsp_strip_extended_manifest(&stripped_fw); - - ret = skl_dsp_boot(ctx); - if (ret < 0) { - dev_err(ctx->dev, "Boot dsp core failed ret: %d\n", ret); - goto skl_load_base_firmware_failed; - } - - ret = skl_cldma_prepare(ctx); - if (ret < 0) { - dev_err(ctx->dev, "CL dma prepare failed : %d\n", ret); - goto skl_load_base_firmware_failed; - } - - /* enable Interrupt */ - skl_ipc_int_enable(ctx); - skl_ipc_op_int_enable(ctx); - - /* check ROM Status */ - for (i = SKL_INIT_TIMEOUT; i > 0; --i) { - if (skl_check_fw_status(ctx, SKL_FW_INIT)) { - dev_dbg(ctx->dev, - "ROM loaded, we can continue with FW loading\n"); - break; - } - mdelay(1); - } - if (!i) { - reg = sst_dsp_shim_read(ctx, SKL_ADSP_FW_STATUS); - dev_err(ctx->dev, - "Timeout waiting for ROM init done, reg:0x%x\n", reg); - ret = -EIO; - goto transfer_firmware_failed; - } - - ret = skl_transfer_firmware(ctx, stripped_fw.data, stripped_fw.size); - if (ret < 0) { - dev_err(ctx->dev, "Transfer firmware failed%d\n", ret); - goto transfer_firmware_failed; - } else { - ret = wait_event_timeout(skl->boot_wait, skl->boot_complete, - msecs_to_jiffies(SKL_IPC_BOOT_MSECS)); - if (ret == 0) { - dev_err(ctx->dev, "DSP boot failed, FW Ready timed-out\n"); - ret = -EIO; - goto transfer_firmware_failed; - } - - dev_dbg(ctx->dev, "Download firmware successful%d\n", ret); - skl->fw_loaded = true; - } - return 0; -transfer_firmware_failed: - ctx->cl_dev.ops.cl_cleanup_controller(ctx); -skl_load_base_firmware_failed: - skl_dsp_disable_core(ctx, SKL_DSP_CORE0_MASK); - release_firmware(ctx->fw); - ctx->fw = NULL; - return ret; -} - -static int skl_set_dsp_D0(struct sst_dsp *ctx, unsigned int core_id) -{ - int ret; - struct skl_ipc_dxstate_info dx; - struct skl_dev *skl = ctx->thread_context; - unsigned int core_mask = SKL_DSP_CORE_MASK(core_id); - - /* If core0 is being turned on, we need to load the FW */ - if (core_id == SKL_DSP_CORE0_ID) { - ret = skl_load_base_firmware(ctx); - if (ret < 0) { - dev_err(ctx->dev, "unable to load firmware\n"); - return ret; - } - - /* load libs as they are also lost on D3 */ - if (skl->lib_count > 1) { - ret = ctx->fw_ops.load_library(ctx, skl->lib_info, - skl->lib_count); - if (ret < 0) { - dev_err(ctx->dev, "reload libs failed: %d\n", - ret); - return ret; - } - - } - } - - /* - * If any core other than core 0 is being moved to D0, enable the - * core and send the set dx IPC for the core. - */ - if (core_id != SKL_DSP_CORE0_ID) { - ret = skl_dsp_enable_core(ctx, core_mask); - if (ret < 0) - return ret; - - dx.core_mask = core_mask; - dx.dx_mask = core_mask; - - ret = skl_ipc_set_dx(&skl->ipc, SKL_INSTANCE_ID, - SKL_BASE_FW_MODULE_ID, &dx); - if (ret < 0) { - dev_err(ctx->dev, "Failed to set dsp to D0:core id= %d\n", - core_id); - skl_dsp_disable_core(ctx, core_mask); - } - } - - skl->cores.state[core_id] = SKL_DSP_RUNNING; - - return 0; -} - -static int skl_set_dsp_D3(struct sst_dsp *ctx, unsigned int core_id) -{ - int ret; - struct skl_ipc_dxstate_info dx; - struct skl_dev *skl = ctx->thread_context; - unsigned int core_mask = SKL_DSP_CORE_MASK(core_id); - - dx.core_mask = core_mask; - dx.dx_mask = SKL_IPC_D3_MASK; - - ret = skl_ipc_set_dx(&skl->ipc, SKL_INSTANCE_ID, SKL_BASE_FW_MODULE_ID, &dx); - if (ret < 0) - dev_err(ctx->dev, "set Dx core %d fail: %d\n", core_id, ret); - - if (core_id == SKL_DSP_CORE0_ID) { - /* disable Interrupt */ - ctx->cl_dev.ops.cl_cleanup_controller(ctx); - skl_cldma_int_disable(ctx); - skl_ipc_op_int_disable(ctx); - skl_ipc_int_disable(ctx); - } - - ret = skl_dsp_disable_core(ctx, core_mask); - if (ret < 0) - return ret; - - skl->cores.state[core_id] = SKL_DSP_RESET; - return ret; -} - -static unsigned int skl_get_errorcode(struct sst_dsp *ctx) -{ - return sst_dsp_shim_read(ctx, SKL_ADSP_ERROR_CODE); -} - -/* - * since get/set_module are called from DAPM context, - * we don't need lock for usage count - */ -static int skl_get_module(struct sst_dsp *ctx, u16 mod_id) -{ - struct skl_module_table *module; - - list_for_each_entry(module, &ctx->module_list, list) { - if (module->mod_info->mod_id == mod_id) - return ++module->usage_cnt; - } - - return -EINVAL; -} - -static int skl_put_module(struct sst_dsp *ctx, u16 mod_id) -{ - struct skl_module_table *module; - - list_for_each_entry(module, &ctx->module_list, list) { - if (module->mod_info->mod_id == mod_id) - return --module->usage_cnt; - } - - return -EINVAL; -} - -static struct skl_module_table *skl_fill_module_table(struct sst_dsp *ctx, - char *mod_name, int mod_id) -{ - const struct firmware *fw; - struct skl_module_table *skl_module; - unsigned int size; - int ret; - - ret = request_firmware(&fw, mod_name, ctx->dev); - if (ret < 0) { - dev_err(ctx->dev, "Request Module %s failed :%d\n", - mod_name, ret); - return NULL; - } - - skl_module = devm_kzalloc(ctx->dev, sizeof(*skl_module), GFP_KERNEL); - if (skl_module == NULL) { - release_firmware(fw); - return NULL; - } - - size = sizeof(*skl_module->mod_info); - skl_module->mod_info = devm_kzalloc(ctx->dev, size, GFP_KERNEL); - if (skl_module->mod_info == NULL) { - release_firmware(fw); - return NULL; - } - - skl_module->mod_info->mod_id = mod_id; - skl_module->mod_info->fw = fw; - list_add(&skl_module->list, &ctx->module_list); - - return skl_module; -} - -/* get a module from it's unique ID */ -static struct skl_module_table *skl_module_get_from_id( - struct sst_dsp *ctx, u16 mod_id) -{ - struct skl_module_table *module; - - if (list_empty(&ctx->module_list)) { - dev_err(ctx->dev, "Module list is empty\n"); - return NULL; - } - - list_for_each_entry(module, &ctx->module_list, list) { - if (module->mod_info->mod_id == mod_id) - return module; - } - - return NULL; -} - -static int skl_transfer_module(struct sst_dsp *ctx, const void *data, - u32 size, u16 mod_id, u8 table_id, bool is_module) -{ - int ret, bytes_left, curr_pos; - struct skl_dev *skl = ctx->thread_context; - skl->mod_load_complete = false; - - bytes_left = ctx->cl_dev.ops.cl_copy_to_dmabuf(ctx, data, size, false); - if (bytes_left < 0) - return bytes_left; - - /* check is_module flag to load module or library */ - if (is_module) - ret = skl_ipc_load_modules(&skl->ipc, SKL_NUM_MODULES, &mod_id); - else - ret = skl_sst_ipc_load_library(&skl->ipc, 0, table_id, false); - - if (ret < 0) { - dev_err(ctx->dev, "Failed to Load %s with err %d\n", - is_module ? "module" : "lib", ret); - goto out; - } - - /* - * if bytes_left > 0 then wait for BDL complete interrupt and - * copy the next chunk till bytes_left is 0. if bytes_left is - * zero, then wait for load module IPC reply - */ - while (bytes_left > 0) { - curr_pos = size - bytes_left; - - ret = skl_cldma_wait_interruptible(ctx); - if (ret < 0) - goto out; - - bytes_left = ctx->cl_dev.ops.cl_copy_to_dmabuf(ctx, - data + curr_pos, - bytes_left, false); - } - - ret = wait_event_timeout(skl->mod_load_wait, skl->mod_load_complete, - msecs_to_jiffies(SKL_IPC_BOOT_MSECS)); - if (ret == 0 || !skl->mod_load_status) { - dev_err(ctx->dev, "Module Load failed\n"); - ret = -EIO; - } - -out: - ctx->cl_dev.ops.cl_stop_dma(ctx); - - return ret; -} - -static int -skl_load_library(struct sst_dsp *ctx, struct skl_lib_info *linfo, int lib_count) -{ - struct skl_dev *skl = ctx->thread_context; - struct firmware stripped_fw; - int ret, i; - - /* library indices start from 1 to N. 0 represents base FW */ - for (i = 1; i < lib_count; i++) { - ret = skl_prepare_lib_load(skl, &skl->lib_info[i], &stripped_fw, - SKL_ADSP_FW_BIN_HDR_OFFSET, i); - if (ret < 0) - goto load_library_failed; - ret = skl_transfer_module(ctx, stripped_fw.data, - stripped_fw.size, 0, i, false); - if (ret < 0) - goto load_library_failed; - } - - return 0; - -load_library_failed: - skl_release_library(linfo, lib_count); - return ret; -} - -static int skl_load_module(struct sst_dsp *ctx, u16 mod_id, u8 *guid) -{ - struct skl_module_table *module_entry = NULL; - int ret = 0; - char mod_name[64]; /* guid str = 32 chars + 4 hyphens */ - - snprintf(mod_name, sizeof(mod_name), "intel/dsp_fw_%pUL.bin", guid); - - module_entry = skl_module_get_from_id(ctx, mod_id); - if (module_entry == NULL) { - module_entry = skl_fill_module_table(ctx, mod_name, mod_id); - if (module_entry == NULL) { - dev_err(ctx->dev, "Failed to Load module\n"); - return -EINVAL; - } - } - - if (!module_entry->usage_cnt) { - ret = skl_transfer_module(ctx, module_entry->mod_info->fw->data, - module_entry->mod_info->fw->size, - mod_id, 0, true); - if (ret < 0) { - dev_err(ctx->dev, "Failed to Load module\n"); - return ret; - } - } - - ret = skl_get_module(ctx, mod_id); - - return ret; -} - -static int skl_unload_module(struct sst_dsp *ctx, u16 mod_id) -{ - int usage_cnt; - struct skl_dev *skl = ctx->thread_context; - int ret = 0; - - usage_cnt = skl_put_module(ctx, mod_id); - if (usage_cnt < 0) { - dev_err(ctx->dev, "Module bad usage cnt!:%d\n", usage_cnt); - return -EIO; - } - - /* if module is used by others return, no need to unload */ - if (usage_cnt > 0) - return 0; - - ret = skl_ipc_unload_modules(&skl->ipc, - SKL_NUM_MODULES, &mod_id); - if (ret < 0) { - dev_err(ctx->dev, "Failed to UnLoad module\n"); - skl_get_module(ctx, mod_id); - return ret; - } - - return ret; -} - -void skl_clear_module_cnt(struct sst_dsp *ctx) -{ - struct skl_module_table *module; - - if (list_empty(&ctx->module_list)) - return; - - list_for_each_entry(module, &ctx->module_list, list) { - module->usage_cnt = 0; - } -} -EXPORT_SYMBOL_GPL(skl_clear_module_cnt); - -static void skl_clear_module_table(struct sst_dsp *ctx) -{ - struct skl_module_table *module, *tmp; - - if (list_empty(&ctx->module_list)) - return; - - list_for_each_entry_safe(module, tmp, &ctx->module_list, list) { - list_del(&module->list); - release_firmware(module->mod_info->fw); - } -} - -static const struct skl_dsp_fw_ops skl_fw_ops = { - .set_state_D0 = skl_set_dsp_D0, - .set_state_D3 = skl_set_dsp_D3, - .load_fw = skl_load_base_firmware, - .get_fw_errcode = skl_get_errorcode, - .load_library = skl_load_library, - .load_mod = skl_load_module, - .unload_mod = skl_unload_module, -}; - -static struct sst_ops skl_ops = { - .irq_handler = skl_dsp_sst_interrupt, - .write = sst_shim32_write, - .read = sst_shim32_read, - .free = skl_dsp_free, -}; - -static struct sst_dsp_device skl_dev = { - .thread = skl_dsp_irq_thread_handler, - .ops = &skl_ops, -}; - -int skl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, - const char *fw_name, struct skl_dsp_loader_ops dsp_ops, - struct skl_dev **dsp) -{ - struct skl_dev *skl; - struct sst_dsp *sst; - int ret; - - ret = skl_sst_ctx_init(dev, irq, fw_name, dsp_ops, dsp, &skl_dev); - if (ret < 0) { - dev_err(dev, "%s: no device\n", __func__); - return ret; - } - - skl = *dsp; - sst = skl->dsp; - sst->addr.lpe = mmio_base; - sst->addr.shim = mmio_base; - sst->addr.sram0_base = SKL_ADSP_SRAM0_BASE; - sst->addr.sram1_base = SKL_ADSP_SRAM1_BASE; - sst->addr.w0_stat_sz = SKL_ADSP_W0_STAT_SZ; - sst->addr.w0_up_sz = SKL_ADSP_W0_UP_SZ; - - sst_dsp_mailbox_init(sst, (SKL_ADSP_SRAM0_BASE + SKL_ADSP_W0_STAT_SZ), - SKL_ADSP_W0_UP_SZ, SKL_ADSP_SRAM1_BASE, SKL_ADSP_W1_SZ); - - ret = skl_ipc_init(dev, skl); - if (ret) { - skl_dsp_free(sst); - return ret; - } - - sst->fw_ops = skl_fw_ops; - - return skl_dsp_acquire_irq(sst); -} -EXPORT_SYMBOL_GPL(skl_sst_dsp_init); - -int skl_sst_init_fw(struct device *dev, struct skl_dev *skl) -{ - int ret; - struct sst_dsp *sst = skl->dsp; - - ret = sst->fw_ops.load_fw(sst); - if (ret < 0) { - dev_err(dev, "Load base fw failed : %d\n", ret); - return ret; - } - - skl_dsp_init_core_state(sst); - - if (skl->lib_count > 1) { - ret = sst->fw_ops.load_library(sst, skl->lib_info, - skl->lib_count); - if (ret < 0) { - dev_err(dev, "Load Library failed : %x\n", ret); - return ret; - } - } - skl->is_first_boot = false; - - return 0; -} -EXPORT_SYMBOL_GPL(skl_sst_init_fw); - -void skl_sst_dsp_cleanup(struct device *dev, struct skl_dev *skl) -{ - - if (skl->dsp->fw) - release_firmware(skl->dsp->fw); - skl_clear_module_table(skl->dsp); - skl_freeup_uuid_list(skl); - skl_ipc_free(&skl->ipc); - skl->dsp->ops->free(skl->dsp); - if (skl->boot_complete) { - skl->dsp->cl_dev.ops.cl_cleanup_controller(skl->dsp); - skl_cldma_int_disable(skl->dsp); - } -} -EXPORT_SYMBOL_GPL(skl_sst_dsp_cleanup); - -MODULE_LICENSE("GPL v2"); -MODULE_DESCRIPTION("Intel Skylake IPC driver"); diff --git a/sound/soc/intel/skylake/skl-topology.c b/sound/soc/intel/skylake/skl-topology.c deleted file mode 100644 index 602ef432112218..00000000000000 --- a/sound/soc/intel/skylake/skl-topology.c +++ /dev/null @@ -1,3605 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * skl-topology.c - Implements Platform component ALSA controls/widget - * handlers. - * - * Copyright (C) 2014-2015 Intel Corp - * Author: Jeeja KP - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "skl-sst-dsp.h" -#include "skl-sst-ipc.h" -#include "skl-topology.h" -#include "skl.h" -#include "../common/sst-dsp.h" -#include "../common/sst-dsp-priv.h" - -#define SKL_CH_FIXUP_MASK (1 << 0) -#define SKL_RATE_FIXUP_MASK (1 << 1) -#define SKL_FMT_FIXUP_MASK (1 << 2) -#define SKL_IN_DIR_BIT_MASK BIT(0) -#define SKL_PIN_COUNT_MASK GENMASK(7, 4) - -static const int mic_mono_list[] = { -0, 1, 2, 3, -}; -static const int mic_stereo_list[][SKL_CH_STEREO] = { -{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}, -}; -static const int mic_trio_list[][SKL_CH_TRIO] = { -{0, 1, 2}, {0, 1, 3}, {0, 2, 3}, {1, 2, 3}, -}; -static const int mic_quatro_list[][SKL_CH_QUATRO] = { -{0, 1, 2, 3}, -}; - -#define CHECK_HW_PARAMS(ch, freq, bps, prm_ch, prm_freq, prm_bps) \ - ((ch == prm_ch) && (bps == prm_bps) && (freq == prm_freq)) - -void skl_tplg_d0i3_get(struct skl_dev *skl, enum d0i3_capability caps) -{ - struct skl_d0i3_data *d0i3 = &skl->d0i3; - - switch (caps) { - case SKL_D0I3_NONE: - d0i3->non_d0i3++; - break; - - case SKL_D0I3_STREAMING: - d0i3->streaming++; - break; - - case SKL_D0I3_NON_STREAMING: - d0i3->non_streaming++; - break; - } -} - -void skl_tplg_d0i3_put(struct skl_dev *skl, enum d0i3_capability caps) -{ - struct skl_d0i3_data *d0i3 = &skl->d0i3; - - switch (caps) { - case SKL_D0I3_NONE: - d0i3->non_d0i3--; - break; - - case SKL_D0I3_STREAMING: - d0i3->streaming--; - break; - - case SKL_D0I3_NON_STREAMING: - d0i3->non_streaming--; - break; - } -} - -/* - * SKL DSP driver modelling uses only few DAPM widgets so for rest we will - * ignore. This helpers checks if the SKL driver handles this widget type - */ -static int is_skl_dsp_widget_type(struct snd_soc_dapm_widget *w, - struct device *dev) -{ - if (w->dapm->dev != dev) - return false; - - switch (w->id) { - case snd_soc_dapm_dai_link: - case snd_soc_dapm_dai_in: - case snd_soc_dapm_aif_in: - case snd_soc_dapm_aif_out: - case snd_soc_dapm_dai_out: - case snd_soc_dapm_switch: - case snd_soc_dapm_output: - case snd_soc_dapm_mux: - - return false; - default: - return true; - } -} - -static void skl_dump_mconfig(struct skl_dev *skl, struct skl_module_cfg *mcfg) -{ - struct skl_module_iface *iface = &mcfg->module->formats[mcfg->fmt_idx]; - - dev_dbg(skl->dev, "Dumping config\n"); - dev_dbg(skl->dev, "Input Format:\n"); - dev_dbg(skl->dev, "channels = %d\n", iface->inputs[0].fmt.channels); - dev_dbg(skl->dev, "s_freq = %d\n", iface->inputs[0].fmt.s_freq); - dev_dbg(skl->dev, "ch_cfg = %d\n", iface->inputs[0].fmt.ch_cfg); - dev_dbg(skl->dev, "valid bit depth = %d\n", - iface->inputs[0].fmt.valid_bit_depth); - dev_dbg(skl->dev, "Output Format:\n"); - dev_dbg(skl->dev, "channels = %d\n", iface->outputs[0].fmt.channels); - dev_dbg(skl->dev, "s_freq = %d\n", iface->outputs[0].fmt.s_freq); - dev_dbg(skl->dev, "valid bit depth = %d\n", - iface->outputs[0].fmt.valid_bit_depth); - dev_dbg(skl->dev, "ch_cfg = %d\n", iface->outputs[0].fmt.ch_cfg); -} - -static void skl_tplg_update_chmap(struct skl_module_fmt *fmt, int chs) -{ - int slot_map = 0xFFFFFFFF; - int start_slot = 0; - int i; - - for (i = 0; i < chs; i++) { - /* - * For 2 channels with starting slot as 0, slot map will - * look like 0xFFFFFF10. - */ - slot_map &= (~(0xF << (4 * i)) | (start_slot << (4 * i))); - start_slot++; - } - fmt->ch_map = slot_map; -} - -static void skl_tplg_update_params(struct skl_module_fmt *fmt, - struct skl_pipe_params *params, int fixup) -{ - if (fixup & SKL_RATE_FIXUP_MASK) - fmt->s_freq = params->s_freq; - if (fixup & SKL_CH_FIXUP_MASK) { - fmt->channels = params->ch; - skl_tplg_update_chmap(fmt, fmt->channels); - } - if (fixup & SKL_FMT_FIXUP_MASK) { - fmt->valid_bit_depth = skl_get_bit_depth(params->s_fmt); - - /* - * 16 bit is 16 bit container whereas 24 bit is in 32 bit - * container so update bit depth accordingly - */ - switch (fmt->valid_bit_depth) { - case SKL_DEPTH_16BIT: - fmt->bit_depth = fmt->valid_bit_depth; - break; - - default: - fmt->bit_depth = SKL_DEPTH_32BIT; - break; - } - } - -} - -/* - * A pipeline may have modules which impact the pcm parameters, like SRC, - * channel converter, format converter. - * We need to calculate the output params by applying the 'fixup' - * Topology will tell driver which type of fixup is to be applied by - * supplying the fixup mask, so based on that we calculate the output - * - * Now In FE the pcm hw_params is source/target format. Same is applicable - * for BE with its hw_params invoked. - * here based on FE, BE pipeline and direction we calculate the input and - * outfix and then apply that for a module - */ -static void skl_tplg_update_params_fixup(struct skl_module_cfg *m_cfg, - struct skl_pipe_params *params, bool is_fe) -{ - int in_fixup, out_fixup; - struct skl_module_fmt *in_fmt, *out_fmt; - - /* Fixups will be applied to pin 0 only */ - in_fmt = &m_cfg->module->formats[m_cfg->fmt_idx].inputs[0].fmt; - out_fmt = &m_cfg->module->formats[m_cfg->fmt_idx].outputs[0].fmt; - - if (params->stream == SNDRV_PCM_STREAM_PLAYBACK) { - if (is_fe) { - in_fixup = m_cfg->params_fixup; - out_fixup = (~m_cfg->converter) & - m_cfg->params_fixup; - } else { - out_fixup = m_cfg->params_fixup; - in_fixup = (~m_cfg->converter) & - m_cfg->params_fixup; - } - } else { - if (is_fe) { - out_fixup = m_cfg->params_fixup; - in_fixup = (~m_cfg->converter) & - m_cfg->params_fixup; - } else { - in_fixup = m_cfg->params_fixup; - out_fixup = (~m_cfg->converter) & - m_cfg->params_fixup; - } - } - - skl_tplg_update_params(in_fmt, params, in_fixup); - skl_tplg_update_params(out_fmt, params, out_fixup); -} - -/* - * A module needs input and output buffers, which are dependent upon pcm - * params, so once we have calculate params, we need buffer calculation as - * well. - */ -static void skl_tplg_update_buffer_size(struct skl_dev *skl, - struct skl_module_cfg *mcfg) -{ - int multiplier = 1; - struct skl_module_fmt *in_fmt, *out_fmt; - struct skl_module_res *res; - - /* Since fixups is applied to pin 0 only, ibs, obs needs - * change for pin 0 only - */ - res = &mcfg->module->resources[mcfg->res_idx]; - in_fmt = &mcfg->module->formats[mcfg->fmt_idx].inputs[0].fmt; - out_fmt = &mcfg->module->formats[mcfg->fmt_idx].outputs[0].fmt; - - if (mcfg->m_type == SKL_MODULE_TYPE_SRCINT) - multiplier = 5; - - res->ibs = DIV_ROUND_UP(in_fmt->s_freq, 1000) * - in_fmt->channels * (in_fmt->bit_depth >> 3) * - multiplier; - - res->obs = DIV_ROUND_UP(out_fmt->s_freq, 1000) * - out_fmt->channels * (out_fmt->bit_depth >> 3) * - multiplier; -} - -static u8 skl_tplg_be_dev_type(int dev_type) -{ - int ret; - - switch (dev_type) { - case SKL_DEVICE_BT: - ret = NHLT_DEVICE_BT; - break; - - case SKL_DEVICE_DMIC: - ret = NHLT_DEVICE_DMIC; - break; - - case SKL_DEVICE_I2S: - ret = NHLT_DEVICE_I2S; - break; - - default: - ret = NHLT_DEVICE_INVALID; - break; - } - - return ret; -} - -static int skl_tplg_update_be_blob(struct snd_soc_dapm_widget *w, - struct skl_dev *skl) -{ - struct skl_module_cfg *m_cfg = w->priv; - int link_type, dir; - u32 ch, s_freq, s_fmt, s_cont; - struct nhlt_specific_cfg *cfg; - u8 dev_type = skl_tplg_be_dev_type(m_cfg->dev_type); - int fmt_idx = m_cfg->fmt_idx; - struct skl_module_iface *m_iface = &m_cfg->module->formats[fmt_idx]; - - /* check if we already have blob */ - if (m_cfg->formats_config[SKL_PARAM_INIT].caps_size > 0) - return 0; - - dev_dbg(skl->dev, "Applying default cfg blob\n"); - switch (m_cfg->dev_type) { - case SKL_DEVICE_DMIC: - link_type = NHLT_LINK_DMIC; - dir = SNDRV_PCM_STREAM_CAPTURE; - s_freq = m_iface->inputs[0].fmt.s_freq; - s_fmt = m_iface->inputs[0].fmt.valid_bit_depth; - s_cont = m_iface->inputs[0].fmt.bit_depth; - ch = m_iface->inputs[0].fmt.channels; - break; - - case SKL_DEVICE_I2S: - link_type = NHLT_LINK_SSP; - if (m_cfg->hw_conn_type == SKL_CONN_SOURCE) { - dir = SNDRV_PCM_STREAM_PLAYBACK; - s_freq = m_iface->outputs[0].fmt.s_freq; - s_fmt = m_iface->outputs[0].fmt.valid_bit_depth; - s_cont = m_iface->outputs[0].fmt.bit_depth; - ch = m_iface->outputs[0].fmt.channels; - } else { - dir = SNDRV_PCM_STREAM_CAPTURE; - s_freq = m_iface->inputs[0].fmt.s_freq; - s_fmt = m_iface->inputs[0].fmt.valid_bit_depth; - s_cont = m_iface->inputs[0].fmt.bit_depth; - ch = m_iface->inputs[0].fmt.channels; - } - break; - - default: - return -EINVAL; - } - - /* update the blob based on virtual bus_id and default params */ - cfg = intel_nhlt_get_endpoint_blob(skl->dev, skl->nhlt, m_cfg->vbus_id, - link_type, s_fmt, s_cont, ch, - s_freq, dir, dev_type); - if (cfg) { - m_cfg->formats_config[SKL_PARAM_INIT].caps_size = cfg->size; - m_cfg->formats_config[SKL_PARAM_INIT].caps = (u32 *)&cfg->caps; - } else { - dev_err(skl->dev, "Blob NULL for id %x type %d dirn %d\n", - m_cfg->vbus_id, link_type, dir); - dev_err(skl->dev, "PCM: ch %d, freq %d, fmt %d/%d\n", - ch, s_freq, s_fmt, s_cont); - return -EIO; - } - - return 0; -} - -static void skl_tplg_update_module_params(struct snd_soc_dapm_widget *w, - struct skl_dev *skl) -{ - struct skl_module_cfg *m_cfg = w->priv; - struct skl_pipe_params *params = m_cfg->pipe->p_params; - int p_conn_type = m_cfg->pipe->conn_type; - bool is_fe; - - if (!m_cfg->params_fixup) - return; - - dev_dbg(skl->dev, "Mconfig for widget=%s BEFORE updation\n", - w->name); - - skl_dump_mconfig(skl, m_cfg); - - if (p_conn_type == SKL_PIPE_CONN_TYPE_FE) - is_fe = true; - else - is_fe = false; - - skl_tplg_update_params_fixup(m_cfg, params, is_fe); - skl_tplg_update_buffer_size(skl, m_cfg); - - dev_dbg(skl->dev, "Mconfig for widget=%s AFTER updation\n", - w->name); - - skl_dump_mconfig(skl, m_cfg); -} - -/* - * some modules can have multiple params set from user control and - * need to be set after module is initialized. If set_param flag is - * set module params will be done after module is initialised. - */ -static int skl_tplg_set_module_params(struct snd_soc_dapm_widget *w, - struct skl_dev *skl) -{ - int i, ret; - struct skl_module_cfg *mconfig = w->priv; - const struct snd_kcontrol_new *k; - struct soc_bytes_ext *sb; - struct skl_algo_data *bc; - struct skl_specific_cfg *sp_cfg; - - if (mconfig->formats_config[SKL_PARAM_SET].caps_size > 0 && - mconfig->formats_config[SKL_PARAM_SET].set_params == SKL_PARAM_SET) { - sp_cfg = &mconfig->formats_config[SKL_PARAM_SET]; - ret = skl_set_module_params(skl, sp_cfg->caps, - sp_cfg->caps_size, - sp_cfg->param_id, mconfig); - if (ret < 0) - return ret; - } - - for (i = 0; i < w->num_kcontrols; i++) { - k = &w->kcontrol_news[i]; - if (k->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) { - sb = (void *) k->private_value; - bc = (struct skl_algo_data *)sb->dobj.private; - - if (bc->set_params == SKL_PARAM_SET) { - ret = skl_set_module_params(skl, - (u32 *)bc->params, bc->size, - bc->param_id, mconfig); - if (ret < 0) - return ret; - } - } - } - - return 0; -} - -/* - * some module param can set from user control and this is required as - * when module is initailzed. if module param is required in init it is - * identifed by set_param flag. if set_param flag is not set, then this - * parameter needs to set as part of module init. - */ -static int skl_tplg_set_module_init_data(struct snd_soc_dapm_widget *w) -{ - const struct snd_kcontrol_new *k; - struct soc_bytes_ext *sb; - struct skl_algo_data *bc; - struct skl_module_cfg *mconfig = w->priv; - int i; - - for (i = 0; i < w->num_kcontrols; i++) { - k = &w->kcontrol_news[i]; - if (k->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) { - sb = (struct soc_bytes_ext *)k->private_value; - bc = (struct skl_algo_data *)sb->dobj.private; - - if (bc->set_params != SKL_PARAM_INIT) - continue; - - mconfig->formats_config[SKL_PARAM_INIT].caps = - (u32 *)bc->params; - mconfig->formats_config[SKL_PARAM_INIT].caps_size = - bc->size; - - break; - } - } - - return 0; -} - -static int skl_tplg_module_prepare(struct skl_dev *skl, struct skl_pipe *pipe, - struct snd_soc_dapm_widget *w, struct skl_module_cfg *mcfg) -{ - switch (mcfg->dev_type) { - case SKL_DEVICE_HDAHOST: - return skl_pcm_host_dma_prepare(skl->dev, pipe->p_params); - - case SKL_DEVICE_HDALINK: - return skl_pcm_link_dma_prepare(skl->dev, pipe->p_params); - } - - return 0; -} - -/* - * Inside a pipe instance, we can have various modules. These modules need - * to instantiated in DSP by invoking INIT_MODULE IPC, which is achieved by - * skl_init_module() routine, so invoke that for all modules in a pipeline - */ -static int -skl_tplg_init_pipe_modules(struct skl_dev *skl, struct skl_pipe *pipe) -{ - struct skl_pipe_module *w_module; - struct snd_soc_dapm_widget *w; - struct skl_module_cfg *mconfig; - u8 cfg_idx; - int ret = 0; - - list_for_each_entry(w_module, &pipe->w_list, node) { - guid_t *uuid_mod; - w = w_module->w; - mconfig = w->priv; - - /* check if module ids are populated */ - if (mconfig->id.module_id < 0) { - dev_err(skl->dev, - "module %pUL id not populated\n", - (guid_t *)mconfig->guid); - return -EIO; - } - - cfg_idx = mconfig->pipe->cur_config_idx; - mconfig->fmt_idx = mconfig->mod_cfg[cfg_idx].fmt_idx; - mconfig->res_idx = mconfig->mod_cfg[cfg_idx].res_idx; - - if (mconfig->module->loadable && skl->dsp->fw_ops.load_mod) { - ret = skl->dsp->fw_ops.load_mod(skl->dsp, - mconfig->id.module_id, mconfig->guid); - if (ret < 0) - return ret; - } - - /* prepare the DMA if the module is gateway cpr */ - ret = skl_tplg_module_prepare(skl, pipe, w, mconfig); - if (ret < 0) - return ret; - - /* update blob if blob is null for be with default value */ - skl_tplg_update_be_blob(w, skl); - - /* - * apply fix/conversion to module params based on - * FE/BE params - */ - skl_tplg_update_module_params(w, skl); - uuid_mod = (guid_t *)mconfig->guid; - mconfig->id.pvt_id = skl_get_pvt_id(skl, uuid_mod, - mconfig->id.instance_id); - if (mconfig->id.pvt_id < 0) - return ret; - skl_tplg_set_module_init_data(w); - - ret = skl_dsp_get_core(skl->dsp, mconfig->core_id); - if (ret < 0) { - dev_err(skl->dev, "Failed to wake up core %d ret=%d\n", - mconfig->core_id, ret); - return ret; - } - - ret = skl_init_module(skl, mconfig); - if (ret < 0) { - skl_put_pvt_id(skl, uuid_mod, &mconfig->id.pvt_id); - goto err; - } - - ret = skl_tplg_set_module_params(w, skl); - if (ret < 0) - goto err; - } - - return 0; -err: - skl_dsp_put_core(skl->dsp, mconfig->core_id); - return ret; -} - -static int skl_tplg_unload_pipe_modules(struct skl_dev *skl, - struct skl_pipe *pipe) -{ - int ret = 0; - struct skl_pipe_module *w_module; - struct skl_module_cfg *mconfig; - - list_for_each_entry(w_module, &pipe->w_list, node) { - guid_t *uuid_mod; - mconfig = w_module->w->priv; - uuid_mod = (guid_t *)mconfig->guid; - - if (mconfig->module->loadable && skl->dsp->fw_ops.unload_mod) { - ret = skl->dsp->fw_ops.unload_mod(skl->dsp, - mconfig->id.module_id); - if (ret < 0) - return -EIO; - } - skl_put_pvt_id(skl, uuid_mod, &mconfig->id.pvt_id); - - ret = skl_dsp_put_core(skl->dsp, mconfig->core_id); - if (ret < 0) { - /* don't return; continue with other modules */ - dev_err(skl->dev, "Failed to sleep core %d ret=%d\n", - mconfig->core_id, ret); - } - } - - /* no modules to unload in this path, so return */ - return ret; -} - -static void skl_tplg_set_pipe_config_idx(struct skl_pipe *pipe, int idx) -{ - pipe->cur_config_idx = idx; - pipe->memory_pages = pipe->configs[idx].mem_pages; -} - -/* - * Here, we select pipe format based on the pipe type and pipe - * direction to determine the current config index for the pipeline. - * The config index is then used to select proper module resources. - * Intermediate pipes currently have a fixed format hence we select the - * 0th configuratation by default for such pipes. - */ -static int -skl_tplg_get_pipe_config(struct skl_dev *skl, struct skl_module_cfg *mconfig) -{ - struct skl_pipe *pipe = mconfig->pipe; - struct skl_pipe_params *params = pipe->p_params; - struct skl_path_config *pconfig = &pipe->configs[0]; - struct skl_pipe_fmt *fmt = NULL; - bool in_fmt = false; - int i; - - if (pipe->nr_cfgs == 0) { - skl_tplg_set_pipe_config_idx(pipe, 0); - return 0; - } - - if (pipe->conn_type == SKL_PIPE_CONN_TYPE_NONE || pipe->nr_cfgs == 1) { - dev_dbg(skl->dev, "No conn_type or just 1 pathcfg, taking 0th for %d\n", - pipe->ppl_id); - skl_tplg_set_pipe_config_idx(pipe, 0); - return 0; - } - - if ((pipe->conn_type == SKL_PIPE_CONN_TYPE_FE && - pipe->direction == SNDRV_PCM_STREAM_PLAYBACK) || - (pipe->conn_type == SKL_PIPE_CONN_TYPE_BE && - pipe->direction == SNDRV_PCM_STREAM_CAPTURE)) - in_fmt = true; - - for (i = 0; i < pipe->nr_cfgs; i++) { - pconfig = &pipe->configs[i]; - if (in_fmt) - fmt = &pconfig->in_fmt; - else - fmt = &pconfig->out_fmt; - - if (CHECK_HW_PARAMS(params->ch, params->s_freq, params->s_fmt, - fmt->channels, fmt->freq, fmt->bps)) { - skl_tplg_set_pipe_config_idx(pipe, i); - dev_dbg(skl->dev, "Using pipe config: %d\n", i); - return 0; - } - } - - dev_err(skl->dev, "Invalid pipe config: %d %d %d for pipe: %d\n", - params->ch, params->s_freq, params->s_fmt, pipe->ppl_id); - return -EINVAL; -} - -/* - * Mixer module represents a pipeline. So in the Pre-PMU event of mixer we - * need create the pipeline. So we do following: - * - Create the pipeline - * - Initialize the modules in pipeline - * - finally bind all modules together - */ -static int skl_tplg_mixer_dapm_pre_pmu_event(struct snd_soc_dapm_widget *w, - struct skl_dev *skl) -{ - int ret; - struct skl_module_cfg *mconfig = w->priv; - struct skl_pipe_module *w_module; - struct skl_pipe *s_pipe = mconfig->pipe; - struct skl_module_cfg *src_module = NULL, *dst_module, *module; - struct skl_module_deferred_bind *modules; - - ret = skl_tplg_get_pipe_config(skl, mconfig); - if (ret < 0) - return ret; - - /* - * Create a list of modules for pipe. - * This list contains modules from source to sink - */ - ret = skl_create_pipeline(skl, mconfig->pipe); - if (ret < 0) - return ret; - - /* Init all pipe modules from source to sink */ - ret = skl_tplg_init_pipe_modules(skl, s_pipe); - if (ret < 0) - return ret; - - /* Bind modules from source to sink */ - list_for_each_entry(w_module, &s_pipe->w_list, node) { - dst_module = w_module->w->priv; - - if (src_module == NULL) { - src_module = dst_module; - continue; - } - - ret = skl_bind_modules(skl, src_module, dst_module); - if (ret < 0) - return ret; - - src_module = dst_module; - } - - /* - * When the destination module is initialized, check for these modules - * in deferred bind list. If found, bind them. - */ - list_for_each_entry(w_module, &s_pipe->w_list, node) { - if (list_empty(&skl->bind_list)) - break; - - list_for_each_entry(modules, &skl->bind_list, node) { - module = w_module->w->priv; - if (modules->dst == module) - skl_bind_modules(skl, modules->src, - modules->dst); - } - } - - return 0; -} - -static int skl_fill_sink_instance_id(struct skl_dev *skl, u32 *params, - int size, struct skl_module_cfg *mcfg) -{ - int i, pvt_id; - - if (mcfg->m_type == SKL_MODULE_TYPE_KPB) { - struct skl_kpb_params *kpb_params = - (struct skl_kpb_params *)params; - struct skl_mod_inst_map *inst = kpb_params->u.map; - - for (i = 0; i < kpb_params->num_modules; i++) { - pvt_id = skl_get_pvt_instance_id_map(skl, inst->mod_id, - inst->inst_id); - if (pvt_id < 0) - return -EINVAL; - - inst->inst_id = pvt_id; - inst++; - } - } - - return 0; -} -/* - * Some modules require params to be set after the module is bound to - * all pins connected. - * - * The module provider initializes set_param flag for such modules and we - * send params after binding - */ -static int skl_tplg_set_module_bind_params(struct snd_soc_dapm_widget *w, - struct skl_module_cfg *mcfg, struct skl_dev *skl) -{ - int i, ret; - struct skl_module_cfg *mconfig = w->priv; - const struct snd_kcontrol_new *k; - struct soc_bytes_ext *sb; - struct skl_algo_data *bc; - struct skl_specific_cfg *sp_cfg; - u32 *params; - - /* - * check all out/in pins are in bind state. - * if so set the module param - */ - for (i = 0; i < mcfg->module->max_output_pins; i++) { - if (mcfg->m_out_pin[i].pin_state != SKL_PIN_BIND_DONE) - return 0; - } - - for (i = 0; i < mcfg->module->max_input_pins; i++) { - if (mcfg->m_in_pin[i].pin_state != SKL_PIN_BIND_DONE) - return 0; - } - - if (mconfig->formats_config[SKL_PARAM_BIND].caps_size > 0 && - mconfig->formats_config[SKL_PARAM_BIND].set_params == - SKL_PARAM_BIND) { - sp_cfg = &mconfig->formats_config[SKL_PARAM_BIND]; - ret = skl_set_module_params(skl, sp_cfg->caps, - sp_cfg->caps_size, - sp_cfg->param_id, mconfig); - if (ret < 0) - return ret; - } - - for (i = 0; i < w->num_kcontrols; i++) { - k = &w->kcontrol_news[i]; - if (k->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) { - sb = (void *) k->private_value; - bc = (struct skl_algo_data *)sb->dobj.private; - - if (bc->set_params == SKL_PARAM_BIND) { - params = kmemdup(bc->params, bc->max, GFP_KERNEL); - if (!params) - return -ENOMEM; - - skl_fill_sink_instance_id(skl, params, bc->max, - mconfig); - - ret = skl_set_module_params(skl, params, - bc->max, bc->param_id, mconfig); - kfree(params); - - if (ret < 0) - return ret; - } - } - } - - return 0; -} - -static int skl_get_module_id(struct skl_dev *skl, guid_t *uuid) -{ - struct uuid_module *module; - - list_for_each_entry(module, &skl->uuid_list, list) { - if (guid_equal(uuid, &module->uuid)) - return module->id; - } - - return -EINVAL; -} - -static int skl_tplg_find_moduleid_from_uuid(struct skl_dev *skl, - const struct snd_kcontrol_new *k) -{ - struct soc_bytes_ext *sb = (void *) k->private_value; - struct skl_algo_data *bc = (struct skl_algo_data *)sb->dobj.private; - struct skl_kpb_params *uuid_params, *params; - struct hdac_bus *bus = skl_to_bus(skl); - int i, size, module_id; - - if (bc->set_params == SKL_PARAM_BIND && bc->max) { - uuid_params = (struct skl_kpb_params *)bc->params; - size = struct_size(params, u.map, uuid_params->num_modules); - - params = devm_kzalloc(bus->dev, size, GFP_KERNEL); - if (!params) - return -ENOMEM; - - params->num_modules = uuid_params->num_modules; - - for (i = 0; i < uuid_params->num_modules; i++) { - module_id = skl_get_module_id(skl, - &uuid_params->u.map_uuid[i].mod_uuid); - if (module_id < 0) { - devm_kfree(bus->dev, params); - return -EINVAL; - } - - params->u.map[i].mod_id = module_id; - params->u.map[i].inst_id = - uuid_params->u.map_uuid[i].inst_id; - } - - devm_kfree(bus->dev, bc->params); - bc->params = (char *)params; - bc->max = size; - } - - return 0; -} - -/* - * Retrieve the module id from UUID mentioned in the - * post bind params - */ -void skl_tplg_add_moduleid_in_bind_params(struct skl_dev *skl, - struct snd_soc_dapm_widget *w) -{ - struct skl_module_cfg *mconfig = w->priv; - int i; - - /* - * Post bind params are used for only for KPB - * to set copier instances to drain the data - * in fast mode - */ - if (mconfig->m_type != SKL_MODULE_TYPE_KPB) - return; - - for (i = 0; i < w->num_kcontrols; i++) - if ((w->kcontrol_news[i].access & - SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) && - (skl_tplg_find_moduleid_from_uuid(skl, - &w->kcontrol_news[i]) < 0)) - dev_err(skl->dev, - "%s: invalid kpb post bind params\n", - __func__); -} - -static int skl_tplg_module_add_deferred_bind(struct skl_dev *skl, - struct skl_module_cfg *src, struct skl_module_cfg *dst) -{ - struct skl_module_deferred_bind *m_list, *modules; - int i; - - /* only supported for module with static pin connection */ - for (i = 0; i < dst->module->max_input_pins; i++) { - struct skl_module_pin *pin = &dst->m_in_pin[i]; - - if (pin->is_dynamic) - continue; - - if ((pin->id.module_id == src->id.module_id) && - (pin->id.instance_id == src->id.instance_id)) { - - if (!list_empty(&skl->bind_list)) { - list_for_each_entry(modules, &skl->bind_list, node) { - if (modules->src == src && modules->dst == dst) - return 0; - } - } - - m_list = kzalloc(sizeof(*m_list), GFP_KERNEL); - if (!m_list) - return -ENOMEM; - - m_list->src = src; - m_list->dst = dst; - - list_add(&m_list->node, &skl->bind_list); - } - } - - return 0; -} - -static int skl_tplg_bind_sinks(struct snd_soc_dapm_widget *w, - struct skl_dev *skl, - struct snd_soc_dapm_widget *src_w, - struct skl_module_cfg *src_mconfig) -{ - struct snd_soc_dapm_path *p; - struct snd_soc_dapm_widget *sink = NULL, *next_sink = NULL; - struct skl_module_cfg *sink_mconfig; - int ret; - - snd_soc_dapm_widget_for_each_sink_path(w, p) { - if (!p->connect) - continue; - - dev_dbg(skl->dev, - "%s: src widget=%s\n", __func__, w->name); - dev_dbg(skl->dev, - "%s: sink widget=%s\n", __func__, p->sink->name); - - next_sink = p->sink; - - if (!is_skl_dsp_widget_type(p->sink, skl->dev)) - return skl_tplg_bind_sinks(p->sink, skl, src_w, src_mconfig); - - /* - * here we will check widgets in sink pipelines, so that - * can be any widgets type and we are only interested if - * they are ones used for SKL so check that first - */ - if ((p->sink->priv != NULL) && - is_skl_dsp_widget_type(p->sink, skl->dev)) { - - sink = p->sink; - sink_mconfig = sink->priv; - - /* - * Modules other than PGA leaf can be connected - * directly or via switch to a module in another - * pipeline. EX: reference path - * when the path is enabled, the dst module that needs - * to be bound may not be initialized. if the module is - * not initialized, add these modules in the deferred - * bind list and when the dst module is initialised, - * bind this module to the dst_module in deferred list. - */ - if (((src_mconfig->m_state == SKL_MODULE_INIT_DONE) - && (sink_mconfig->m_state == SKL_MODULE_UNINIT))) { - - ret = skl_tplg_module_add_deferred_bind(skl, - src_mconfig, sink_mconfig); - - if (ret < 0) - return ret; - - } - - - if (src_mconfig->m_state == SKL_MODULE_UNINIT || - sink_mconfig->m_state == SKL_MODULE_UNINIT) - continue; - - /* Bind source to sink, mixin is always source */ - ret = skl_bind_modules(skl, src_mconfig, sink_mconfig); - if (ret) - return ret; - - /* set module params after bind */ - skl_tplg_set_module_bind_params(src_w, - src_mconfig, skl); - skl_tplg_set_module_bind_params(sink, - sink_mconfig, skl); - - /* Start sinks pipe first */ - if (sink_mconfig->pipe->state != SKL_PIPE_STARTED) { - if (sink_mconfig->pipe->conn_type != - SKL_PIPE_CONN_TYPE_FE) - ret = skl_run_pipe(skl, - sink_mconfig->pipe); - if (ret) - return ret; - } - } - } - - if (!sink && next_sink) - return skl_tplg_bind_sinks(next_sink, skl, src_w, src_mconfig); - - return 0; -} - -/* - * A PGA represents a module in a pipeline. So in the Pre-PMU event of PGA - * we need to do following: - * - Bind to sink pipeline - * Since the sink pipes can be running and we don't get mixer event on - * connect for already running mixer, we need to find the sink pipes - * here and bind to them. This way dynamic connect works. - * - Start sink pipeline, if not running - * - Then run current pipe - */ -static int skl_tplg_pga_dapm_pre_pmu_event(struct snd_soc_dapm_widget *w, - struct skl_dev *skl) -{ - struct skl_module_cfg *src_mconfig; - int ret = 0; - - src_mconfig = w->priv; - - /* - * find which sink it is connected to, bind with the sink, - * if sink is not started, start sink pipe first, then start - * this pipe - */ - ret = skl_tplg_bind_sinks(w, skl, w, src_mconfig); - if (ret) - return ret; - - /* Start source pipe last after starting all sinks */ - if (src_mconfig->pipe->conn_type != SKL_PIPE_CONN_TYPE_FE) - return skl_run_pipe(skl, src_mconfig->pipe); - - return 0; -} - -static struct snd_soc_dapm_widget *skl_get_src_dsp_widget( - struct snd_soc_dapm_widget *w, struct skl_dev *skl) -{ - struct snd_soc_dapm_path *p; - struct snd_soc_dapm_widget *src_w = NULL; - - snd_soc_dapm_widget_for_each_source_path(w, p) { - src_w = p->source; - if (!p->connect) - continue; - - dev_dbg(skl->dev, "sink widget=%s\n", w->name); - dev_dbg(skl->dev, "src widget=%s\n", p->source->name); - - /* - * here we will check widgets in sink pipelines, so that can - * be any widgets type and we are only interested if they are - * ones used for SKL so check that first - */ - if ((p->source->priv != NULL) && - is_skl_dsp_widget_type(p->source, skl->dev)) { - return p->source; - } - } - - if (src_w != NULL) - return skl_get_src_dsp_widget(src_w, skl); - - return NULL; -} - -/* - * in the Post-PMU event of mixer we need to do following: - * - Check if this pipe is running - * - if not, then - * - bind this pipeline to its source pipeline - * if source pipe is already running, this means it is a dynamic - * connection and we need to bind only to that pipe - * - start this pipeline - */ -static int skl_tplg_mixer_dapm_post_pmu_event(struct snd_soc_dapm_widget *w, - struct skl_dev *skl) -{ - int ret = 0; - struct snd_soc_dapm_widget *source, *sink; - struct skl_module_cfg *src_mconfig, *sink_mconfig; - int src_pipe_started = 0; - - sink = w; - sink_mconfig = sink->priv; - - /* - * If source pipe is already started, that means source is driving - * one more sink before this sink got connected, Since source is - * started, bind this sink to source and start this pipe. - */ - source = skl_get_src_dsp_widget(w, skl); - if (source != NULL) { - src_mconfig = source->priv; - sink_mconfig = sink->priv; - src_pipe_started = 1; - - /* - * check pipe state, then no need to bind or start the - * pipe - */ - if (src_mconfig->pipe->state != SKL_PIPE_STARTED) - src_pipe_started = 0; - } - - if (src_pipe_started) { - ret = skl_bind_modules(skl, src_mconfig, sink_mconfig); - if (ret) - return ret; - - /* set module params after bind */ - skl_tplg_set_module_bind_params(source, src_mconfig, skl); - skl_tplg_set_module_bind_params(sink, sink_mconfig, skl); - - if (sink_mconfig->pipe->conn_type != SKL_PIPE_CONN_TYPE_FE) - ret = skl_run_pipe(skl, sink_mconfig->pipe); - } - - return ret; -} - -/* - * in the Pre-PMD event of mixer we need to do following: - * - Stop the pipe - * - find the source connections and remove that from dapm_path_list - * - unbind with source pipelines if still connected - */ -static int skl_tplg_mixer_dapm_pre_pmd_event(struct snd_soc_dapm_widget *w, - struct skl_dev *skl) -{ - struct skl_module_cfg *src_mconfig, *sink_mconfig; - int ret = 0, i; - - sink_mconfig = w->priv; - - /* Stop the pipe */ - ret = skl_stop_pipe(skl, sink_mconfig->pipe); - if (ret) - return ret; - - for (i = 0; i < sink_mconfig->module->max_input_pins; i++) { - if (sink_mconfig->m_in_pin[i].pin_state == SKL_PIN_BIND_DONE) { - src_mconfig = sink_mconfig->m_in_pin[i].tgt_mcfg; - if (!src_mconfig) - continue; - - ret = skl_unbind_modules(skl, - src_mconfig, sink_mconfig); - } - } - - return ret; -} - -/* - * in the Post-PMD event of mixer we need to do following: - * - Unbind the modules within the pipeline - * - Delete the pipeline (modules are not required to be explicitly - * deleted, pipeline delete is enough here - */ -static int skl_tplg_mixer_dapm_post_pmd_event(struct snd_soc_dapm_widget *w, - struct skl_dev *skl) -{ - struct skl_module_cfg *mconfig = w->priv; - struct skl_pipe_module *w_module; - struct skl_module_cfg *src_module = NULL, *dst_module; - struct skl_pipe *s_pipe = mconfig->pipe; - struct skl_module_deferred_bind *modules, *tmp; - - if (s_pipe->state == SKL_PIPE_INVALID) - return -EINVAL; - - list_for_each_entry(w_module, &s_pipe->w_list, node) { - if (list_empty(&skl->bind_list)) - break; - - src_module = w_module->w->priv; - - list_for_each_entry_safe(modules, tmp, &skl->bind_list, node) { - /* - * When the destination module is deleted, Unbind the - * modules from deferred bind list. - */ - if (modules->dst == src_module) { - skl_unbind_modules(skl, modules->src, - modules->dst); - } - - /* - * When the source module is deleted, remove this entry - * from the deferred bind list. - */ - if (modules->src == src_module) { - list_del(&modules->node); - modules->src = NULL; - modules->dst = NULL; - kfree(modules); - } - } - } - - list_for_each_entry(w_module, &s_pipe->w_list, node) { - dst_module = w_module->w->priv; - - if (src_module == NULL) { - src_module = dst_module; - continue; - } - - skl_unbind_modules(skl, src_module, dst_module); - src_module = dst_module; - } - - skl_delete_pipe(skl, mconfig->pipe); - - list_for_each_entry(w_module, &s_pipe->w_list, node) { - src_module = w_module->w->priv; - src_module->m_state = SKL_MODULE_UNINIT; - } - - return skl_tplg_unload_pipe_modules(skl, s_pipe); -} - -/* - * in the Post-PMD event of PGA we need to do following: - * - Stop the pipeline - * - In source pipe is connected, unbind with source pipelines - */ -static int skl_tplg_pga_dapm_post_pmd_event(struct snd_soc_dapm_widget *w, - struct skl_dev *skl) -{ - struct skl_module_cfg *src_mconfig, *sink_mconfig; - int ret = 0, i; - - src_mconfig = w->priv; - - /* Stop the pipe since this is a mixin module */ - ret = skl_stop_pipe(skl, src_mconfig->pipe); - if (ret) - return ret; - - for (i = 0; i < src_mconfig->module->max_output_pins; i++) { - if (src_mconfig->m_out_pin[i].pin_state == SKL_PIN_BIND_DONE) { - sink_mconfig = src_mconfig->m_out_pin[i].tgt_mcfg; - if (!sink_mconfig) - continue; - /* - * This is a connecter and if path is found that means - * unbind between source and sink has not happened yet - */ - ret = skl_unbind_modules(skl, src_mconfig, - sink_mconfig); - } - } - - return ret; -} - -/* - * In modelling, we assume there will be ONLY one mixer in a pipeline. If a - * second one is required that is created as another pipe entity. - * The mixer is responsible for pipe management and represent a pipeline - * instance - */ -static int skl_tplg_mixer_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *k, int event) -{ - struct snd_soc_dapm_context *dapm = w->dapm; - struct skl_dev *skl = get_skl_ctx(dapm->dev); - - switch (event) { - case SND_SOC_DAPM_PRE_PMU: - return skl_tplg_mixer_dapm_pre_pmu_event(w, skl); - - case SND_SOC_DAPM_POST_PMU: - return skl_tplg_mixer_dapm_post_pmu_event(w, skl); - - case SND_SOC_DAPM_PRE_PMD: - return skl_tplg_mixer_dapm_pre_pmd_event(w, skl); - - case SND_SOC_DAPM_POST_PMD: - return skl_tplg_mixer_dapm_post_pmd_event(w, skl); - } - - return 0; -} - -/* - * In modelling, we assumed rest of the modules in pipeline are PGA. But we - * are interested in last PGA (leaf PGA) in a pipeline to disconnect with - * the sink when it is running (two FE to one BE or one FE to two BE) - * scenarios - */ -static int skl_tplg_pga_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *k, int event) - -{ - struct snd_soc_dapm_context *dapm = w->dapm; - struct skl_dev *skl = get_skl_ctx(dapm->dev); - - switch (event) { - case SND_SOC_DAPM_PRE_PMU: - return skl_tplg_pga_dapm_pre_pmu_event(w, skl); - - case SND_SOC_DAPM_POST_PMD: - return skl_tplg_pga_dapm_post_pmd_event(w, skl); - } - - return 0; -} - -static int skl_tplg_multi_config_set_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol, - bool is_set) -{ - struct snd_soc_component *component = - snd_soc_kcontrol_component(kcontrol); - struct hdac_bus *bus = snd_soc_component_get_drvdata(component); - struct skl_dev *skl = bus_to_skl(bus); - struct skl_pipeline *ppl; - struct skl_pipe *pipe = NULL; - struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value; - u32 *pipe_id; - - if (!ec) - return -EINVAL; - - if (is_set && ucontrol->value.enumerated.item[0] > ec->items) - return -EINVAL; - - pipe_id = ec->dobj.private; - - list_for_each_entry(ppl, &skl->ppl_list, node) { - if (ppl->pipe->ppl_id == *pipe_id) { - pipe = ppl->pipe; - break; - } - } - if (!pipe) - return -EIO; - - if (is_set) - skl_tplg_set_pipe_config_idx(pipe, ucontrol->value.enumerated.item[0]); - else - ucontrol->value.enumerated.item[0] = pipe->cur_config_idx; - - return 0; -} - -static int skl_tplg_multi_config_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - return skl_tplg_multi_config_set_get(kcontrol, ucontrol, false); -} - -static int skl_tplg_multi_config_set(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - return skl_tplg_multi_config_set_get(kcontrol, ucontrol, true); -} - -static int skl_tplg_multi_config_get_dmic(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - return skl_tplg_multi_config_set_get(kcontrol, ucontrol, false); -} - -static int skl_tplg_multi_config_set_dmic(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - return skl_tplg_multi_config_set_get(kcontrol, ucontrol, true); -} - -static int skl_tplg_tlv_control_get(struct snd_kcontrol *kcontrol, - unsigned int __user *data, unsigned int size) -{ - struct soc_bytes_ext *sb = - (struct soc_bytes_ext *)kcontrol->private_value; - struct skl_algo_data *bc = (struct skl_algo_data *)sb->dobj.private; - struct snd_soc_dapm_widget *w = snd_soc_dapm_kcontrol_widget(kcontrol); - struct skl_module_cfg *mconfig = w->priv; - struct skl_dev *skl = get_skl_ctx(w->dapm->dev); - - if (w->power) - skl_get_module_params(skl, (u32 *)bc->params, - bc->size, bc->param_id, mconfig); - - /* decrement size for TLV header */ - size -= 2 * sizeof(u32); - - /* check size as we don't want to send kernel data */ - if (size > bc->max) - size = bc->max; - - if (bc->params) { - if (copy_to_user(data, &bc->param_id, sizeof(u32))) - return -EFAULT; - if (copy_to_user(data + 1, &size, sizeof(u32))) - return -EFAULT; - if (copy_to_user(data + 2, bc->params, size)) - return -EFAULT; - } - - return 0; -} - -#define SKL_PARAM_VENDOR_ID 0xff - -static int skl_tplg_tlv_control_set(struct snd_kcontrol *kcontrol, - const unsigned int __user *data, unsigned int size) -{ - struct snd_soc_dapm_widget *w = snd_soc_dapm_kcontrol_widget(kcontrol); - struct skl_module_cfg *mconfig = w->priv; - struct soc_bytes_ext *sb = - (struct soc_bytes_ext *)kcontrol->private_value; - struct skl_algo_data *ac = (struct skl_algo_data *)sb->dobj.private; - struct skl_dev *skl = get_skl_ctx(w->dapm->dev); - - if (ac->params) { - if (size > ac->max) - return -EINVAL; - ac->size = size; - - if (copy_from_user(ac->params, data, size)) - return -EFAULT; - - if (w->power) - return skl_set_module_params(skl, - (u32 *)ac->params, ac->size, - ac->param_id, mconfig); - } - - return 0; -} - -static int skl_tplg_mic_control_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_dapm_widget *w = snd_soc_dapm_kcontrol_widget(kcontrol); - struct skl_module_cfg *mconfig = w->priv; - struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value; - u32 ch_type = *((u32 *)ec->dobj.private); - - if (mconfig->dmic_ch_type == ch_type) - ucontrol->value.enumerated.item[0] = - mconfig->dmic_ch_combo_index; - else - ucontrol->value.enumerated.item[0] = 0; - - return 0; -} - -static int skl_fill_mic_sel_params(struct skl_module_cfg *mconfig, - struct skl_mic_sel_config *mic_cfg, struct device *dev) -{ - struct skl_specific_cfg *sp_cfg = - &mconfig->formats_config[SKL_PARAM_INIT]; - - sp_cfg->caps_size = sizeof(struct skl_mic_sel_config); - sp_cfg->set_params = SKL_PARAM_SET; - sp_cfg->param_id = 0x00; - if (!sp_cfg->caps) { - sp_cfg->caps = devm_kzalloc(dev, sp_cfg->caps_size, GFP_KERNEL); - if (!sp_cfg->caps) - return -ENOMEM; - } - - mic_cfg->mic_switch = SKL_MIC_SEL_SWITCH; - mic_cfg->flags = 0; - memcpy(sp_cfg->caps, mic_cfg, sp_cfg->caps_size); - - return 0; -} - -static int skl_tplg_mic_control_set(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_dapm_widget *w = snd_soc_dapm_kcontrol_widget(kcontrol); - struct skl_module_cfg *mconfig = w->priv; - struct skl_mic_sel_config mic_cfg = {0}; - struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value; - u32 ch_type = *((u32 *)ec->dobj.private); - const int *list; - u8 in_ch, out_ch, index; - - mconfig->dmic_ch_type = ch_type; - mconfig->dmic_ch_combo_index = ucontrol->value.enumerated.item[0]; - - /* enum control index 0 is INVALID, so no channels to be set */ - if (mconfig->dmic_ch_combo_index == 0) - return 0; - - /* No valid channel selection map for index 0, so offset by 1 */ - index = mconfig->dmic_ch_combo_index - 1; - - switch (ch_type) { - case SKL_CH_MONO: - if (mconfig->dmic_ch_combo_index > ARRAY_SIZE(mic_mono_list)) - return -EINVAL; - - list = &mic_mono_list[index]; - break; - - case SKL_CH_STEREO: - if (mconfig->dmic_ch_combo_index > ARRAY_SIZE(mic_stereo_list)) - return -EINVAL; - - list = mic_stereo_list[index]; - break; - - case SKL_CH_TRIO: - if (mconfig->dmic_ch_combo_index > ARRAY_SIZE(mic_trio_list)) - return -EINVAL; - - list = mic_trio_list[index]; - break; - - case SKL_CH_QUATRO: - if (mconfig->dmic_ch_combo_index > ARRAY_SIZE(mic_quatro_list)) - return -EINVAL; - - list = mic_quatro_list[index]; - break; - - default: - dev_err(w->dapm->dev, - "Invalid channel %d for mic_select module\n", - ch_type); - return -EINVAL; - - } - - /* channel type enum map to number of chanels for that type */ - for (out_ch = 0; out_ch < ch_type; out_ch++) { - in_ch = list[out_ch]; - mic_cfg.blob[out_ch][in_ch] = SKL_DEFAULT_MIC_SEL_GAIN; - } - - return skl_fill_mic_sel_params(mconfig, &mic_cfg, w->dapm->dev); -} - -/* - * Fill the dma id for host and link. In case of passthrough - * pipeline, this will both host and link in the same - * pipeline, so need to copy the link and host based on dev_type - */ -static void skl_tplg_fill_dma_id(struct skl_module_cfg *mcfg, - struct skl_pipe_params *params) -{ - struct skl_pipe *pipe = mcfg->pipe; - - if (pipe->passthru) { - switch (mcfg->dev_type) { - case SKL_DEVICE_HDALINK: - pipe->p_params->link_dma_id = params->link_dma_id; - pipe->p_params->link_index = params->link_index; - pipe->p_params->link_bps = params->link_bps; - break; - - case SKL_DEVICE_HDAHOST: - pipe->p_params->host_dma_id = params->host_dma_id; - pipe->p_params->host_bps = params->host_bps; - break; - - default: - break; - } - pipe->p_params->s_fmt = params->s_fmt; - pipe->p_params->ch = params->ch; - pipe->p_params->s_freq = params->s_freq; - pipe->p_params->stream = params->stream; - pipe->p_params->format = params->format; - - } else { - memcpy(pipe->p_params, params, sizeof(*params)); - } -} - -/* - * The FE params are passed by hw_params of the DAI. - * On hw_params, the params are stored in Gateway module of the FE and we - * need to calculate the format in DSP module configuration, that - * conversion is done here - */ -int skl_tplg_update_pipe_params(struct device *dev, - struct skl_module_cfg *mconfig, - struct skl_pipe_params *params) -{ - struct skl_module_res *res; - struct skl_dev *skl = get_skl_ctx(dev); - struct skl_module_fmt *format = NULL; - u8 cfg_idx = mconfig->pipe->cur_config_idx; - - res = &mconfig->module->resources[mconfig->res_idx]; - skl_tplg_fill_dma_id(mconfig, params); - mconfig->fmt_idx = mconfig->mod_cfg[cfg_idx].fmt_idx; - mconfig->res_idx = mconfig->mod_cfg[cfg_idx].res_idx; - - if (skl->nr_modules) - return 0; - - if (params->stream == SNDRV_PCM_STREAM_PLAYBACK) - format = &mconfig->module->formats[mconfig->fmt_idx].inputs[0].fmt; - else - format = &mconfig->module->formats[mconfig->fmt_idx].outputs[0].fmt; - - /* set the hw_params */ - format->s_freq = params->s_freq; - format->channels = params->ch; - format->valid_bit_depth = skl_get_bit_depth(params->s_fmt); - - /* - * 16 bit is 16 bit container whereas 24 bit is in 32 bit - * container so update bit depth accordingly - */ - switch (format->valid_bit_depth) { - case SKL_DEPTH_16BIT: - format->bit_depth = format->valid_bit_depth; - break; - - case SKL_DEPTH_24BIT: - case SKL_DEPTH_32BIT: - format->bit_depth = SKL_DEPTH_32BIT; - break; - - default: - dev_err(dev, "Invalid bit depth %x for pipe\n", - format->valid_bit_depth); - return -EINVAL; - } - - if (params->stream == SNDRV_PCM_STREAM_PLAYBACK) { - res->ibs = (format->s_freq / 1000) * - (format->channels) * - (format->bit_depth >> 3); - } else { - res->obs = (format->s_freq / 1000) * - (format->channels) * - (format->bit_depth >> 3); - } - - return 0; -} - -/* - * Query the module config for the FE DAI - * This is used to find the hw_params set for that DAI and apply to FE - * pipeline - */ -struct skl_module_cfg * -skl_tplg_fe_get_cpr_module(struct snd_soc_dai *dai, int stream) -{ - struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(dai, stream); - struct snd_soc_dapm_path *p = NULL; - - if (stream == SNDRV_PCM_STREAM_PLAYBACK) { - snd_soc_dapm_widget_for_each_sink_path(w, p) { - if (p->connect && p->sink->power && - !is_skl_dsp_widget_type(p->sink, dai->dev)) - continue; - - if (p->sink->priv) { - dev_dbg(dai->dev, "set params for %s\n", - p->sink->name); - return p->sink->priv; - } - } - } else { - snd_soc_dapm_widget_for_each_source_path(w, p) { - if (p->connect && p->source->power && - !is_skl_dsp_widget_type(p->source, dai->dev)) - continue; - - if (p->source->priv) { - dev_dbg(dai->dev, "set params for %s\n", - p->source->name); - return p->source->priv; - } - } - } - - return NULL; -} - -static struct skl_module_cfg *skl_get_mconfig_pb_cpr( - struct snd_soc_dai *dai, struct snd_soc_dapm_widget *w) -{ - struct snd_soc_dapm_path *p; - struct skl_module_cfg *mconfig = NULL; - - snd_soc_dapm_widget_for_each_source_path(w, p) { - if (w->endpoints[SND_SOC_DAPM_DIR_OUT] > 0) { - if (p->connect && - (p->sink->id == snd_soc_dapm_aif_out) && - p->source->priv) { - mconfig = p->source->priv; - return mconfig; - } - mconfig = skl_get_mconfig_pb_cpr(dai, p->source); - if (mconfig) - return mconfig; - } - } - return mconfig; -} - -static struct skl_module_cfg *skl_get_mconfig_cap_cpr( - struct snd_soc_dai *dai, struct snd_soc_dapm_widget *w) -{ - struct snd_soc_dapm_path *p; - struct skl_module_cfg *mconfig = NULL; - - snd_soc_dapm_widget_for_each_sink_path(w, p) { - if (w->endpoints[SND_SOC_DAPM_DIR_IN] > 0) { - if (p->connect && - (p->source->id == snd_soc_dapm_aif_in) && - p->sink->priv) { - mconfig = p->sink->priv; - return mconfig; - } - mconfig = skl_get_mconfig_cap_cpr(dai, p->sink); - if (mconfig) - return mconfig; - } - } - return mconfig; -} - -struct skl_module_cfg * -skl_tplg_be_get_cpr_module(struct snd_soc_dai *dai, int stream) -{ - struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(dai, stream); - struct skl_module_cfg *mconfig; - - if (stream == SNDRV_PCM_STREAM_PLAYBACK) { - mconfig = skl_get_mconfig_pb_cpr(dai, w); - } else { - mconfig = skl_get_mconfig_cap_cpr(dai, w); - } - return mconfig; -} - -static u8 skl_tplg_be_link_type(int dev_type) -{ - int ret; - - switch (dev_type) { - case SKL_DEVICE_BT: - ret = NHLT_LINK_SSP; - break; - - case SKL_DEVICE_DMIC: - ret = NHLT_LINK_DMIC; - break; - - case SKL_DEVICE_I2S: - ret = NHLT_LINK_SSP; - break; - - case SKL_DEVICE_HDALINK: - ret = NHLT_LINK_HDA; - break; - - default: - ret = NHLT_LINK_INVALID; - break; - } - - return ret; -} - -/* - * Fill the BE gateway parameters - * The BE gateway expects a blob of parameters which are kept in the ACPI - * NHLT blob, so query the blob for interface type (i2s/pdm) and instance. - * The port can have multiple settings so pick based on the pipeline - * parameters - */ -static int skl_tplg_be_fill_pipe_params(struct snd_soc_dai *dai, - struct skl_module_cfg *mconfig, - struct skl_pipe_params *params) -{ - struct nhlt_specific_cfg *cfg; - struct skl_pipe *pipe = mconfig->pipe; - struct skl_pipe_params save = *pipe->p_params; - struct skl_pipe_fmt *pipe_fmt; - struct skl_dev *skl = get_skl_ctx(dai->dev); - int link_type = skl_tplg_be_link_type(mconfig->dev_type); - u8 dev_type = skl_tplg_be_dev_type(mconfig->dev_type); - int ret; - - skl_tplg_fill_dma_id(mconfig, params); - - if (link_type == NHLT_LINK_HDA) - return 0; - - *pipe->p_params = *params; - ret = skl_tplg_get_pipe_config(skl, mconfig); - if (ret) - goto err; - - dev_dbg(skl->dev, "%s using pipe config: %d\n", __func__, pipe->cur_config_idx); - if (pipe->direction == SNDRV_PCM_STREAM_PLAYBACK) - pipe_fmt = &pipe->configs[pipe->cur_config_idx].out_fmt; - else - pipe_fmt = &pipe->configs[pipe->cur_config_idx].in_fmt; - - /* update the blob based on virtual bus_id*/ - cfg = intel_nhlt_get_endpoint_blob(dai->dev, skl->nhlt, - mconfig->vbus_id, link_type, - pipe_fmt->bps, params->s_cont, - pipe_fmt->channels, pipe_fmt->freq, - pipe->direction, dev_type); - if (cfg) { - mconfig->formats_config[SKL_PARAM_INIT].caps_size = cfg->size; - mconfig->formats_config[SKL_PARAM_INIT].caps = (u32 *)&cfg->caps; - } else { - dev_err(dai->dev, "Blob NULL for id:%d type:%d dirn:%d ch:%d, freq:%d, fmt:%d\n", - mconfig->vbus_id, link_type, params->stream, - params->ch, params->s_freq, params->s_fmt); - ret = -EINVAL; - goto err; - } - - return 0; - -err: - *pipe->p_params = save; - return ret; -} - -static int skl_tplg_be_set_src_pipe_params(struct snd_soc_dai *dai, - struct snd_soc_dapm_widget *w, - struct skl_pipe_params *params) -{ - struct snd_soc_dapm_path *p; - int ret = -EIO; - - snd_soc_dapm_widget_for_each_source_path(w, p) { - if (p->connect && is_skl_dsp_widget_type(p->source, dai->dev) && - p->source->priv) { - - ret = skl_tplg_be_fill_pipe_params(dai, - p->source->priv, params); - if (ret < 0) - return ret; - } else { - ret = skl_tplg_be_set_src_pipe_params(dai, - p->source, params); - if (ret < 0) - return ret; - } - } - - return ret; -} - -static int skl_tplg_be_set_sink_pipe_params(struct snd_soc_dai *dai, - struct snd_soc_dapm_widget *w, struct skl_pipe_params *params) -{ - struct snd_soc_dapm_path *p; - int ret = -EIO; - - snd_soc_dapm_widget_for_each_sink_path(w, p) { - if (p->connect && is_skl_dsp_widget_type(p->sink, dai->dev) && - p->sink->priv) { - - ret = skl_tplg_be_fill_pipe_params(dai, - p->sink->priv, params); - if (ret < 0) - return ret; - } else { - ret = skl_tplg_be_set_sink_pipe_params( - dai, p->sink, params); - if (ret < 0) - return ret; - } - } - - return ret; -} - -/* - * BE hw_params can be a source parameters (capture) or sink parameters - * (playback). Based on sink and source we need to either find the source - * list or the sink list and set the pipeline parameters - */ -int skl_tplg_be_update_params(struct snd_soc_dai *dai, - struct skl_pipe_params *params) -{ - struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(dai, params->stream); - - if (params->stream == SNDRV_PCM_STREAM_PLAYBACK) { - return skl_tplg_be_set_src_pipe_params(dai, w, params); - } else { - return skl_tplg_be_set_sink_pipe_params(dai, w, params); - } -} - -static const struct snd_soc_tplg_widget_events skl_tplg_widget_ops[] = { - {SKL_MIXER_EVENT, skl_tplg_mixer_event}, - {SKL_VMIXER_EVENT, skl_tplg_mixer_event}, - {SKL_PGA_EVENT, skl_tplg_pga_event}, -}; - -static const struct snd_soc_tplg_bytes_ext_ops skl_tlv_ops[] = { - {SKL_CONTROL_TYPE_BYTE_TLV, skl_tplg_tlv_control_get, - skl_tplg_tlv_control_set}, -}; - -static const struct snd_soc_tplg_kcontrol_ops skl_tplg_kcontrol_ops[] = { - { - .id = SKL_CONTROL_TYPE_MIC_SELECT, - .get = skl_tplg_mic_control_get, - .put = skl_tplg_mic_control_set, - }, - { - .id = SKL_CONTROL_TYPE_MULTI_IO_SELECT, - .get = skl_tplg_multi_config_get, - .put = skl_tplg_multi_config_set, - }, - { - .id = SKL_CONTROL_TYPE_MULTI_IO_SELECT_DMIC, - .get = skl_tplg_multi_config_get_dmic, - .put = skl_tplg_multi_config_set_dmic, - } -}; - -static int skl_tplg_fill_pipe_cfg(struct device *dev, - struct skl_pipe *pipe, u32 tkn, - u32 tkn_val, int conf_idx, int dir) -{ - struct skl_pipe_fmt *fmt; - struct skl_path_config *config; - - switch (dir) { - case SKL_DIR_IN: - fmt = &pipe->configs[conf_idx].in_fmt; - break; - - case SKL_DIR_OUT: - fmt = &pipe->configs[conf_idx].out_fmt; - break; - - default: - dev_err(dev, "Invalid direction: %d\n", dir); - return -EINVAL; - } - - config = &pipe->configs[conf_idx]; - - switch (tkn) { - case SKL_TKN_U32_CFG_FREQ: - fmt->freq = tkn_val; - break; - - case SKL_TKN_U8_CFG_CHAN: - fmt->channels = tkn_val; - break; - - case SKL_TKN_U8_CFG_BPS: - fmt->bps = tkn_val; - break; - - case SKL_TKN_U32_PATH_MEM_PGS: - config->mem_pages = tkn_val; - break; - - default: - dev_err(dev, "Invalid token config: %d\n", tkn); - return -EINVAL; - } - - return 0; -} - -static int skl_tplg_fill_pipe_tkn(struct device *dev, - struct skl_pipe *pipe, u32 tkn, - u32 tkn_val) -{ - - switch (tkn) { - case SKL_TKN_U32_PIPE_CONN_TYPE: - pipe->conn_type = tkn_val; - break; - - case SKL_TKN_U32_PIPE_PRIORITY: - pipe->pipe_priority = tkn_val; - break; - - case SKL_TKN_U32_PIPE_MEM_PGS: - pipe->memory_pages = tkn_val; - break; - - case SKL_TKN_U32_PMODE: - pipe->lp_mode = tkn_val; - break; - - case SKL_TKN_U32_PIPE_DIRECTION: - pipe->direction = tkn_val; - break; - - case SKL_TKN_U32_NUM_CONFIGS: - pipe->nr_cfgs = tkn_val; - break; - - default: - dev_err(dev, "Token not handled %d\n", tkn); - return -EINVAL; - } - - return 0; -} - -/* - * Add pipeline by parsing the relevant tokens - * Return an existing pipe if the pipe already exists. - */ -static int skl_tplg_add_pipe(struct device *dev, - struct skl_module_cfg *mconfig, struct skl_dev *skl, - struct snd_soc_tplg_vendor_value_elem *tkn_elem) -{ - struct skl_pipeline *ppl; - struct skl_pipe *pipe; - struct skl_pipe_params *params; - - list_for_each_entry(ppl, &skl->ppl_list, node) { - if (ppl->pipe->ppl_id == tkn_elem->value) { - mconfig->pipe = ppl->pipe; - return -EEXIST; - } - } - - ppl = devm_kzalloc(dev, sizeof(*ppl), GFP_KERNEL); - if (!ppl) - return -ENOMEM; - - pipe = devm_kzalloc(dev, sizeof(*pipe), GFP_KERNEL); - if (!pipe) - return -ENOMEM; - - params = devm_kzalloc(dev, sizeof(*params), GFP_KERNEL); - if (!params) - return -ENOMEM; - - pipe->p_params = params; - pipe->ppl_id = tkn_elem->value; - INIT_LIST_HEAD(&pipe->w_list); - - ppl->pipe = pipe; - list_add(&ppl->node, &skl->ppl_list); - - mconfig->pipe = pipe; - mconfig->pipe->state = SKL_PIPE_INVALID; - - return 0; -} - -static int skl_tplg_get_uuid(struct device *dev, guid_t *guid, - struct snd_soc_tplg_vendor_uuid_elem *uuid_tkn) -{ - if (uuid_tkn->token == SKL_TKN_UUID) { - import_guid(guid, uuid_tkn->uuid); - return 0; - } - - dev_err(dev, "Not an UUID token %d\n", uuid_tkn->token); - - return -EINVAL; -} - -static int skl_tplg_fill_pin(struct device *dev, - struct snd_soc_tplg_vendor_value_elem *tkn_elem, - struct skl_module_pin *m_pin, - int pin_index) -{ - int ret; - - switch (tkn_elem->token) { - case SKL_TKN_U32_PIN_MOD_ID: - m_pin[pin_index].id.module_id = tkn_elem->value; - break; - - case SKL_TKN_U32_PIN_INST_ID: - m_pin[pin_index].id.instance_id = tkn_elem->value; - break; - - case SKL_TKN_UUID: - ret = skl_tplg_get_uuid(dev, &m_pin[pin_index].id.mod_uuid, - (struct snd_soc_tplg_vendor_uuid_elem *)tkn_elem); - if (ret < 0) - return ret; - - break; - - default: - dev_err(dev, "%d Not a pin token\n", tkn_elem->token); - return -EINVAL; - } - - return 0; -} - -/* - * Parse for pin config specific tokens to fill up the - * module private data - */ -static int skl_tplg_fill_pins_info(struct device *dev, - struct skl_module_cfg *mconfig, - struct snd_soc_tplg_vendor_value_elem *tkn_elem, - int dir, int pin_count) -{ - int ret; - struct skl_module_pin *m_pin; - - switch (dir) { - case SKL_DIR_IN: - m_pin = mconfig->m_in_pin; - break; - - case SKL_DIR_OUT: - m_pin = mconfig->m_out_pin; - break; - - default: - dev_err(dev, "Invalid direction value\n"); - return -EINVAL; - } - - ret = skl_tplg_fill_pin(dev, tkn_elem, m_pin, pin_count); - if (ret < 0) - return ret; - - m_pin[pin_count].in_use = false; - m_pin[pin_count].pin_state = SKL_PIN_UNBIND; - - return 0; -} - -/* - * Fill up input/output module config format based - * on the direction - */ -static int skl_tplg_fill_fmt(struct device *dev, - struct skl_module_fmt *dst_fmt, - u32 tkn, u32 value) -{ - switch (tkn) { - case SKL_TKN_U32_FMT_CH: - dst_fmt->channels = value; - break; - - case SKL_TKN_U32_FMT_FREQ: - dst_fmt->s_freq = value; - break; - - case SKL_TKN_U32_FMT_BIT_DEPTH: - dst_fmt->bit_depth = value; - break; - - case SKL_TKN_U32_FMT_SAMPLE_SIZE: - dst_fmt->valid_bit_depth = value; - break; - - case SKL_TKN_U32_FMT_CH_CONFIG: - dst_fmt->ch_cfg = value; - break; - - case SKL_TKN_U32_FMT_INTERLEAVE: - dst_fmt->interleaving_style = value; - break; - - case SKL_TKN_U32_FMT_SAMPLE_TYPE: - dst_fmt->sample_type = value; - break; - - case SKL_TKN_U32_FMT_CH_MAP: - dst_fmt->ch_map = value; - break; - - default: - dev_err(dev, "Invalid token %d\n", tkn); - return -EINVAL; - } - - return 0; -} - -static int skl_tplg_widget_fill_fmt(struct device *dev, - struct skl_module_iface *fmt, - u32 tkn, u32 val, u32 dir, int fmt_idx) -{ - struct skl_module_fmt *dst_fmt; - - if (!fmt) - return -EINVAL; - - switch (dir) { - case SKL_DIR_IN: - dst_fmt = &fmt->inputs[fmt_idx].fmt; - break; - - case SKL_DIR_OUT: - dst_fmt = &fmt->outputs[fmt_idx].fmt; - break; - - default: - dev_err(dev, "Invalid direction: %d\n", dir); - return -EINVAL; - } - - return skl_tplg_fill_fmt(dev, dst_fmt, tkn, val); -} - -static void skl_tplg_fill_pin_dynamic_val( - struct skl_module_pin *mpin, u32 pin_count, u32 value) -{ - int i; - - for (i = 0; i < pin_count; i++) - mpin[i].is_dynamic = value; -} - -/* - * Resource table in the manifest has pin specific resources - * like pin and pin buffer size - */ -static int skl_tplg_manifest_pin_res_tkn(struct device *dev, - struct snd_soc_tplg_vendor_value_elem *tkn_elem, - struct skl_module_res *res, int pin_idx, int dir) -{ - struct skl_module_pin_resources *m_pin; - - switch (dir) { - case SKL_DIR_IN: - m_pin = &res->input[pin_idx]; - break; - - case SKL_DIR_OUT: - m_pin = &res->output[pin_idx]; - break; - - default: - dev_err(dev, "Invalid pin direction: %d\n", dir); - return -EINVAL; - } - - switch (tkn_elem->token) { - case SKL_TKN_MM_U32_RES_PIN_ID: - m_pin->pin_index = tkn_elem->value; - break; - - case SKL_TKN_MM_U32_PIN_BUF: - m_pin->buf_size = tkn_elem->value; - break; - - default: - dev_err(dev, "Invalid token: %d\n", tkn_elem->token); - return -EINVAL; - } - - return 0; -} - -/* - * Fill module specific resources from the manifest's resource - * table like CPS, DMA size, mem_pages. - */ -static int skl_tplg_fill_res_tkn(struct device *dev, - struct snd_soc_tplg_vendor_value_elem *tkn_elem, - struct skl_module_res *res, - int pin_idx, int dir) -{ - int ret, tkn_count = 0; - - if (!res) - return -EINVAL; - - switch (tkn_elem->token) { - case SKL_TKN_MM_U32_DMA_SIZE: - res->dma_buffer_size = tkn_elem->value; - break; - - case SKL_TKN_MM_U32_CPC: - res->cpc = tkn_elem->value; - break; - - case SKL_TKN_U32_MEM_PAGES: - res->is_pages = tkn_elem->value; - break; - - case SKL_TKN_U32_OBS: - res->obs = tkn_elem->value; - break; - - case SKL_TKN_U32_IBS: - res->ibs = tkn_elem->value; - break; - - case SKL_TKN_MM_U32_RES_PIN_ID: - case SKL_TKN_MM_U32_PIN_BUF: - ret = skl_tplg_manifest_pin_res_tkn(dev, tkn_elem, res, - pin_idx, dir); - if (ret < 0) - return ret; - break; - - case SKL_TKN_MM_U32_CPS: - case SKL_TKN_U32_MAX_MCPS: - /* ignore unused tokens */ - break; - - default: - dev_err(dev, "Not a res type token: %d", tkn_elem->token); - return -EINVAL; - - } - tkn_count++; - - return tkn_count; -} - -/* - * Parse tokens to fill up the module private data - */ -static int skl_tplg_get_token(struct device *dev, - struct snd_soc_tplg_vendor_value_elem *tkn_elem, - struct skl_dev *skl, struct skl_module_cfg *mconfig) -{ - int tkn_count = 0; - int ret; - static int is_pipe_exists; - static int pin_index, dir, conf_idx; - struct skl_module_iface *iface = NULL; - struct skl_module_res *res = NULL; - int res_idx = mconfig->res_idx; - int fmt_idx = mconfig->fmt_idx; - - /* - * If the manifest structure contains no modules, fill all - * the module data to 0th index. - * res_idx and fmt_idx are default set to 0. - */ - if (skl->nr_modules == 0) { - res = &mconfig->module->resources[res_idx]; - iface = &mconfig->module->formats[fmt_idx]; - } - - if (tkn_elem->token > SKL_TKN_MAX) - return -EINVAL; - - switch (tkn_elem->token) { - case SKL_TKN_U8_IN_QUEUE_COUNT: - mconfig->module->max_input_pins = tkn_elem->value; - break; - - case SKL_TKN_U8_OUT_QUEUE_COUNT: - mconfig->module->max_output_pins = tkn_elem->value; - break; - - case SKL_TKN_U8_DYN_IN_PIN: - if (!mconfig->m_in_pin) - mconfig->m_in_pin = - devm_kcalloc(dev, MAX_IN_QUEUE, - sizeof(*mconfig->m_in_pin), - GFP_KERNEL); - if (!mconfig->m_in_pin) - return -ENOMEM; - - skl_tplg_fill_pin_dynamic_val(mconfig->m_in_pin, MAX_IN_QUEUE, - tkn_elem->value); - break; - - case SKL_TKN_U8_DYN_OUT_PIN: - if (!mconfig->m_out_pin) - mconfig->m_out_pin = - devm_kcalloc(dev, MAX_IN_QUEUE, - sizeof(*mconfig->m_in_pin), - GFP_KERNEL); - if (!mconfig->m_out_pin) - return -ENOMEM; - - skl_tplg_fill_pin_dynamic_val(mconfig->m_out_pin, MAX_OUT_QUEUE, - tkn_elem->value); - break; - - case SKL_TKN_U8_TIME_SLOT: - mconfig->time_slot = tkn_elem->value; - break; - - case SKL_TKN_U8_CORE_ID: - mconfig->core_id = tkn_elem->value; - break; - - case SKL_TKN_U8_MOD_TYPE: - mconfig->m_type = tkn_elem->value; - break; - - case SKL_TKN_U8_DEV_TYPE: - mconfig->dev_type = tkn_elem->value; - break; - - case SKL_TKN_U8_HW_CONN_TYPE: - mconfig->hw_conn_type = tkn_elem->value; - break; - - case SKL_TKN_U16_MOD_INST_ID: - mconfig->id.instance_id = - tkn_elem->value; - break; - - case SKL_TKN_U32_MEM_PAGES: - case SKL_TKN_U32_MAX_MCPS: - case SKL_TKN_U32_OBS: - case SKL_TKN_U32_IBS: - ret = skl_tplg_fill_res_tkn(dev, tkn_elem, res, pin_index, dir); - if (ret < 0) - return ret; - - break; - - case SKL_TKN_U32_VBUS_ID: - mconfig->vbus_id = tkn_elem->value; - break; - - case SKL_TKN_U32_PARAMS_FIXUP: - mconfig->params_fixup = tkn_elem->value; - break; - - case SKL_TKN_U32_CONVERTER: - mconfig->converter = tkn_elem->value; - break; - - case SKL_TKN_U32_D0I3_CAPS: - mconfig->d0i3_caps = tkn_elem->value; - break; - - case SKL_TKN_U32_PIPE_ID: - ret = skl_tplg_add_pipe(dev, - mconfig, skl, tkn_elem); - - if (ret < 0) { - if (ret == -EEXIST) { - is_pipe_exists = 1; - break; - } - return is_pipe_exists; - } - - break; - - case SKL_TKN_U32_PIPE_CONFIG_ID: - conf_idx = tkn_elem->value; - break; - - case SKL_TKN_U32_PIPE_CONN_TYPE: - case SKL_TKN_U32_PIPE_PRIORITY: - case SKL_TKN_U32_PIPE_MEM_PGS: - case SKL_TKN_U32_PMODE: - case SKL_TKN_U32_PIPE_DIRECTION: - case SKL_TKN_U32_NUM_CONFIGS: - if (is_pipe_exists) { - ret = skl_tplg_fill_pipe_tkn(dev, mconfig->pipe, - tkn_elem->token, tkn_elem->value); - if (ret < 0) - return ret; - } - - break; - - case SKL_TKN_U32_PATH_MEM_PGS: - case SKL_TKN_U32_CFG_FREQ: - case SKL_TKN_U8_CFG_CHAN: - case SKL_TKN_U8_CFG_BPS: - if (mconfig->pipe->nr_cfgs) { - ret = skl_tplg_fill_pipe_cfg(dev, mconfig->pipe, - tkn_elem->token, tkn_elem->value, - conf_idx, dir); - if (ret < 0) - return ret; - } - break; - - case SKL_TKN_CFG_MOD_RES_ID: - mconfig->mod_cfg[conf_idx].res_idx = tkn_elem->value; - break; - - case SKL_TKN_CFG_MOD_FMT_ID: - mconfig->mod_cfg[conf_idx].fmt_idx = tkn_elem->value; - break; - - /* - * SKL_TKN_U32_DIR_PIN_COUNT token has the value for both - * direction and the pin count. The first four bits represent - * direction and next four the pin count. - */ - case SKL_TKN_U32_DIR_PIN_COUNT: - dir = tkn_elem->value & SKL_IN_DIR_BIT_MASK; - pin_index = (tkn_elem->value & - SKL_PIN_COUNT_MASK) >> 4; - - break; - - case SKL_TKN_U32_FMT_CH: - case SKL_TKN_U32_FMT_FREQ: - case SKL_TKN_U32_FMT_BIT_DEPTH: - case SKL_TKN_U32_FMT_SAMPLE_SIZE: - case SKL_TKN_U32_FMT_CH_CONFIG: - case SKL_TKN_U32_FMT_INTERLEAVE: - case SKL_TKN_U32_FMT_SAMPLE_TYPE: - case SKL_TKN_U32_FMT_CH_MAP: - ret = skl_tplg_widget_fill_fmt(dev, iface, tkn_elem->token, - tkn_elem->value, dir, pin_index); - - if (ret < 0) - return ret; - - break; - - case SKL_TKN_U32_PIN_MOD_ID: - case SKL_TKN_U32_PIN_INST_ID: - case SKL_TKN_UUID: - ret = skl_tplg_fill_pins_info(dev, - mconfig, tkn_elem, dir, - pin_index); - if (ret < 0) - return ret; - - break; - - case SKL_TKN_U32_FMT_CFG_IDX: - if (tkn_elem->value > SKL_MAX_PARAMS_TYPES) - return -EINVAL; - - mconfig->fmt_cfg_idx = tkn_elem->value; - break; - - case SKL_TKN_U32_CAPS_SIZE: - mconfig->formats_config[mconfig->fmt_cfg_idx].caps_size = - tkn_elem->value; - - break; - - case SKL_TKN_U32_CAPS_SET_PARAMS: - mconfig->formats_config[mconfig->fmt_cfg_idx].set_params = - tkn_elem->value; - break; - - case SKL_TKN_U32_CAPS_PARAMS_ID: - mconfig->formats_config[mconfig->fmt_cfg_idx].param_id = - tkn_elem->value; - break; - - case SKL_TKN_U32_PROC_DOMAIN: - mconfig->domain = - tkn_elem->value; - - break; - - case SKL_TKN_U32_DMA_BUF_SIZE: - mconfig->dma_buffer_size = tkn_elem->value; - break; - - case SKL_TKN_U8_IN_PIN_TYPE: - case SKL_TKN_U8_OUT_PIN_TYPE: - case SKL_TKN_U8_CONN_TYPE: - break; - - default: - dev_err(dev, "Token %d not handled\n", - tkn_elem->token); - return -EINVAL; - } - - tkn_count++; - - return tkn_count; -} - -/* - * Parse the vendor array for specific tokens to construct - * module private data - */ -static int skl_tplg_get_tokens(struct device *dev, - char *pvt_data, struct skl_dev *skl, - struct skl_module_cfg *mconfig, int block_size) -{ - struct snd_soc_tplg_vendor_array *array; - struct snd_soc_tplg_vendor_value_elem *tkn_elem; - int tkn_count = 0, ret; - int off = 0, tuple_size = 0; - bool is_module_guid = true; - - if (block_size <= 0) - return -EINVAL; - - while (tuple_size < block_size) { - array = (struct snd_soc_tplg_vendor_array *)(pvt_data + off); - - off += array->size; - - switch (array->type) { - case SND_SOC_TPLG_TUPLE_TYPE_STRING: - dev_warn(dev, "no string tokens expected for skl tplg\n"); - continue; - - case SND_SOC_TPLG_TUPLE_TYPE_UUID: - if (is_module_guid) { - ret = skl_tplg_get_uuid(dev, (guid_t *)mconfig->guid, - array->uuid); - is_module_guid = false; - } else { - ret = skl_tplg_get_token(dev, array->value, skl, - mconfig); - } - - if (ret < 0) - return ret; - - tuple_size += sizeof(*array->uuid); - - continue; - - default: - tkn_elem = array->value; - tkn_count = 0; - break; - } - - while (tkn_count <= (array->num_elems - 1)) { - ret = skl_tplg_get_token(dev, tkn_elem, - skl, mconfig); - - if (ret < 0) - return ret; - - tkn_count = tkn_count + ret; - tkn_elem++; - } - - tuple_size += tkn_count * sizeof(*tkn_elem); - } - - return off; -} - -/* - * Every data block is preceded by a descriptor to read the number - * of data blocks, they type of the block and it's size - */ -static int skl_tplg_get_desc_blocks(struct device *dev, - struct snd_soc_tplg_vendor_array *array) -{ - struct snd_soc_tplg_vendor_value_elem *tkn_elem; - - tkn_elem = array->value; - - switch (tkn_elem->token) { - case SKL_TKN_U8_NUM_BLOCKS: - case SKL_TKN_U8_BLOCK_TYPE: - case SKL_TKN_U16_BLOCK_SIZE: - return tkn_elem->value; - - default: - dev_err(dev, "Invalid descriptor token %d\n", tkn_elem->token); - break; - } - - return -EINVAL; -} - -static int skl_tplg_get_caps_data(struct device *dev, char *data, - struct skl_module_cfg *mconfig) -{ - int idx = mconfig->fmt_cfg_idx; - - if (mconfig->formats_config[idx].caps_size > 0) { - mconfig->formats_config[idx].caps = - devm_kzalloc(dev, mconfig->formats_config[idx].caps_size, - GFP_KERNEL); - if (!mconfig->formats_config[idx].caps) - return -ENOMEM; - memcpy(mconfig->formats_config[idx].caps, data, - mconfig->formats_config[idx].caps_size); - } - - return mconfig->formats_config[idx].caps_size; -} - -/* - * Parse the private data for the token and corresponding value. - * The private data can have multiple data blocks. So, a data block - * is preceded by a descriptor for number of blocks and a descriptor - * for the type and size of the suceeding data block. - */ -static int skl_tplg_get_pvt_data(struct snd_soc_tplg_dapm_widget *tplg_w, - struct skl_dev *skl, struct device *dev, - struct skl_module_cfg *mconfig) -{ - struct snd_soc_tplg_vendor_array *array; - int num_blocks, block_size, block_type, off = 0; - char *data; - int ret; - - /* Read the NUM_DATA_BLOCKS descriptor */ - array = (struct snd_soc_tplg_vendor_array *)tplg_w->priv.data; - ret = skl_tplg_get_desc_blocks(dev, array); - if (ret < 0) - return ret; - num_blocks = ret; - - off += array->size; - /* Read the BLOCK_TYPE and BLOCK_SIZE descriptor */ - while (num_blocks > 0) { - array = (struct snd_soc_tplg_vendor_array *) - (tplg_w->priv.data + off); - - ret = skl_tplg_get_desc_blocks(dev, array); - - if (ret < 0) - return ret; - block_type = ret; - off += array->size; - - array = (struct snd_soc_tplg_vendor_array *) - (tplg_w->priv.data + off); - - ret = skl_tplg_get_desc_blocks(dev, array); - - if (ret < 0) - return ret; - block_size = ret; - off += array->size; - - data = (tplg_w->priv.data + off); - - if (block_type == SKL_TYPE_TUPLE) { - ret = skl_tplg_get_tokens(dev, data, - skl, mconfig, block_size); - } else { - ret = skl_tplg_get_caps_data(dev, data, mconfig); - } - - if (ret < 0) - return ret; - - --num_blocks; - off += ret; - } - - return 0; -} - -static void skl_clear_pin_config(struct snd_soc_component *component, - struct snd_soc_dapm_widget *w) -{ - int i; - struct skl_module_cfg *mconfig; - struct skl_pipe *pipe; - - if (!strncmp(w->dapm->component->name, component->name, - strlen(component->name))) { - mconfig = w->priv; - pipe = mconfig->pipe; - for (i = 0; i < mconfig->module->max_input_pins; i++) { - mconfig->m_in_pin[i].in_use = false; - mconfig->m_in_pin[i].pin_state = SKL_PIN_UNBIND; - } - for (i = 0; i < mconfig->module->max_output_pins; i++) { - mconfig->m_out_pin[i].in_use = false; - mconfig->m_out_pin[i].pin_state = SKL_PIN_UNBIND; - } - pipe->state = SKL_PIPE_INVALID; - mconfig->m_state = SKL_MODULE_UNINIT; - } -} - -void skl_cleanup_resources(struct skl_dev *skl) -{ - struct snd_soc_component *soc_component = skl->component; - struct snd_soc_dapm_widget *w; - struct snd_soc_card *card; - - if (soc_component == NULL) - return; - - card = soc_component->card; - if (!snd_soc_card_is_instantiated(card)) - return; - - list_for_each_entry(w, &card->widgets, list) { - if (is_skl_dsp_widget_type(w, skl->dev) && w->priv != NULL) - skl_clear_pin_config(soc_component, w); - } - - skl_clear_module_cnt(skl->dsp); -} - -/* - * Topology core widget load callback - * - * This is used to save the private data for each widget which gives - * information to the driver about module and pipeline parameters which DSP - * FW expects like ids, resource values, formats etc - */ -static int skl_tplg_widget_load(struct snd_soc_component *cmpnt, int index, - struct snd_soc_dapm_widget *w, - struct snd_soc_tplg_dapm_widget *tplg_w) -{ - int ret; - struct hdac_bus *bus = snd_soc_component_get_drvdata(cmpnt); - struct skl_dev *skl = bus_to_skl(bus); - struct skl_module_cfg *mconfig; - - if (!tplg_w->priv.size) - goto bind_event; - - mconfig = devm_kzalloc(bus->dev, sizeof(*mconfig), GFP_KERNEL); - - if (!mconfig) - return -ENOMEM; - - if (skl->nr_modules == 0) { - mconfig->module = devm_kzalloc(bus->dev, - sizeof(*mconfig->module), GFP_KERNEL); - if (!mconfig->module) - return -ENOMEM; - } - - w->priv = mconfig; - - /* - * module binary can be loaded later, so set it to query when - * module is load for a use case - */ - mconfig->id.module_id = -1; - - /* To provide backward compatibility, set default as SKL_PARAM_INIT */ - mconfig->fmt_cfg_idx = SKL_PARAM_INIT; - - /* Parse private data for tuples */ - ret = skl_tplg_get_pvt_data(tplg_w, skl, bus->dev, mconfig); - if (ret < 0) - return ret; - - skl_debug_init_module(skl->debugfs, w, mconfig); - -bind_event: - if (tplg_w->event_type == 0) { - dev_dbg(bus->dev, "ASoC: No event handler required\n"); - return 0; - } - - ret = snd_soc_tplg_widget_bind_event(w, skl_tplg_widget_ops, - ARRAY_SIZE(skl_tplg_widget_ops), - tplg_w->event_type); - - if (ret) { - dev_err(bus->dev, "%s: No matching event handlers found for %d\n", - __func__, tplg_w->event_type); - return -EINVAL; - } - - return 0; -} - -static int skl_init_algo_data(struct device *dev, struct soc_bytes_ext *be, - struct snd_soc_tplg_bytes_control *bc) -{ - struct skl_algo_data *ac; - struct skl_dfw_algo_data *dfw_ac = - (struct skl_dfw_algo_data *)bc->priv.data; - - ac = devm_kzalloc(dev, sizeof(*ac), GFP_KERNEL); - if (!ac) - return -ENOMEM; - - /* Fill private data */ - ac->max = dfw_ac->max; - ac->param_id = dfw_ac->param_id; - ac->set_params = dfw_ac->set_params; - ac->size = dfw_ac->max; - - if (ac->max) { - ac->params = devm_kzalloc(dev, ac->max, GFP_KERNEL); - if (!ac->params) - return -ENOMEM; - - memcpy(ac->params, dfw_ac->params, ac->max); - } - - be->dobj.private = ac; - return 0; -} - -static int skl_init_enum_data(struct device *dev, struct soc_enum *se, - struct snd_soc_tplg_enum_control *ec) -{ - - void *data; - - if (ec->priv.size) { - data = devm_kzalloc(dev, sizeof(ec->priv.size), GFP_KERNEL); - if (!data) - return -ENOMEM; - memcpy(data, ec->priv.data, ec->priv.size); - se->dobj.private = data; - } - - return 0; - -} - -static int skl_tplg_control_load(struct snd_soc_component *cmpnt, - int index, - struct snd_kcontrol_new *kctl, - struct snd_soc_tplg_ctl_hdr *hdr) -{ - struct soc_bytes_ext *sb; - struct snd_soc_tplg_bytes_control *tplg_bc; - struct snd_soc_tplg_enum_control *tplg_ec; - struct hdac_bus *bus = snd_soc_component_get_drvdata(cmpnt); - struct soc_enum *se; - - switch (hdr->ops.info) { - case SND_SOC_TPLG_CTL_BYTES: - tplg_bc = container_of(hdr, - struct snd_soc_tplg_bytes_control, hdr); - if (kctl->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) { - sb = (struct soc_bytes_ext *)kctl->private_value; - if (tplg_bc->priv.size) - return skl_init_algo_data( - bus->dev, sb, tplg_bc); - } - break; - - case SND_SOC_TPLG_CTL_ENUM: - tplg_ec = container_of(hdr, - struct snd_soc_tplg_enum_control, hdr); - if (kctl->access & SNDRV_CTL_ELEM_ACCESS_READ) { - se = (struct soc_enum *)kctl->private_value; - if (tplg_ec->priv.size) - skl_init_enum_data(bus->dev, se, tplg_ec); - } - - /* - * now that the control initializations are done, remove - * write permission for the DMIC configuration enums to - * avoid conflicts between NHLT settings and user interaction - */ - - if (hdr->ops.get == SKL_CONTROL_TYPE_MULTI_IO_SELECT_DMIC) - kctl->access = SNDRV_CTL_ELEM_ACCESS_READ; - - break; - - default: - dev_dbg(bus->dev, "Control load not supported %d:%d:%d\n", - hdr->ops.get, hdr->ops.put, hdr->ops.info); - break; - } - - return 0; -} - -static int skl_tplg_fill_str_mfest_tkn(struct device *dev, - struct snd_soc_tplg_vendor_string_elem *str_elem, - struct skl_dev *skl) -{ - int tkn_count = 0; - static int ref_count; - - switch (str_elem->token) { - case SKL_TKN_STR_LIB_NAME: - if (ref_count > skl->lib_count - 1) { - ref_count = 0; - return -EINVAL; - } - - strncpy(skl->lib_info[ref_count].name, - str_elem->string, - ARRAY_SIZE(skl->lib_info[ref_count].name)); - ref_count++; - break; - - default: - dev_err(dev, "Not a string token %d\n", str_elem->token); - break; - } - tkn_count++; - - return tkn_count; -} - -static int skl_tplg_get_str_tkn(struct device *dev, - struct snd_soc_tplg_vendor_array *array, - struct skl_dev *skl) -{ - int tkn_count = 0, ret; - struct snd_soc_tplg_vendor_string_elem *str_elem; - - str_elem = (struct snd_soc_tplg_vendor_string_elem *)array->value; - while (tkn_count < array->num_elems) { - ret = skl_tplg_fill_str_mfest_tkn(dev, str_elem, skl); - str_elem++; - - if (ret < 0) - return ret; - - tkn_count = tkn_count + ret; - } - - return tkn_count; -} - -static int skl_tplg_manifest_fill_fmt(struct device *dev, - struct skl_module_iface *fmt, - struct snd_soc_tplg_vendor_value_elem *tkn_elem, - u32 dir, int fmt_idx) -{ - struct skl_module_pin_fmt *dst_fmt; - struct skl_module_fmt *mod_fmt; - int ret; - - if (!fmt) - return -EINVAL; - - switch (dir) { - case SKL_DIR_IN: - dst_fmt = &fmt->inputs[fmt_idx]; - break; - - case SKL_DIR_OUT: - dst_fmt = &fmt->outputs[fmt_idx]; - break; - - default: - dev_err(dev, "Invalid direction: %d\n", dir); - return -EINVAL; - } - - mod_fmt = &dst_fmt->fmt; - - switch (tkn_elem->token) { - case SKL_TKN_MM_U32_INTF_PIN_ID: - dst_fmt->id = tkn_elem->value; - break; - - default: - ret = skl_tplg_fill_fmt(dev, mod_fmt, tkn_elem->token, - tkn_elem->value); - if (ret < 0) - return ret; - break; - } - - return 0; -} - -static int skl_tplg_fill_mod_info(struct device *dev, - struct snd_soc_tplg_vendor_value_elem *tkn_elem, - struct skl_module *mod) -{ - - if (!mod) - return -EINVAL; - - switch (tkn_elem->token) { - case SKL_TKN_U8_IN_PIN_TYPE: - mod->input_pin_type = tkn_elem->value; - break; - - case SKL_TKN_U8_OUT_PIN_TYPE: - mod->output_pin_type = tkn_elem->value; - break; - - case SKL_TKN_U8_IN_QUEUE_COUNT: - mod->max_input_pins = tkn_elem->value; - break; - - case SKL_TKN_U8_OUT_QUEUE_COUNT: - mod->max_output_pins = tkn_elem->value; - break; - - case SKL_TKN_MM_U8_NUM_RES: - mod->nr_resources = tkn_elem->value; - break; - - case SKL_TKN_MM_U8_NUM_INTF: - mod->nr_interfaces = tkn_elem->value; - break; - - default: - dev_err(dev, "Invalid mod info token %d", tkn_elem->token); - return -EINVAL; - } - - return 0; -} - - -static int skl_tplg_get_int_tkn(struct device *dev, - struct snd_soc_tplg_vendor_value_elem *tkn_elem, - struct skl_dev *skl) -{ - int tkn_count = 0, ret; - static int mod_idx, res_val_idx, intf_val_idx, dir, pin_idx; - struct skl_module_res *res = NULL; - struct skl_module_iface *fmt = NULL; - struct skl_module *mod = NULL; - static struct skl_astate_param *astate_table; - static int astate_cfg_idx, count; - int i; - size_t size; - - if (skl->modules) { - mod = skl->modules[mod_idx]; - res = &mod->resources[res_val_idx]; - fmt = &mod->formats[intf_val_idx]; - } - - switch (tkn_elem->token) { - case SKL_TKN_U32_LIB_COUNT: - skl->lib_count = tkn_elem->value; - break; - - case SKL_TKN_U8_NUM_MOD: - skl->nr_modules = tkn_elem->value; - skl->modules = devm_kcalloc(dev, skl->nr_modules, - sizeof(*skl->modules), GFP_KERNEL); - if (!skl->modules) - return -ENOMEM; - - for (i = 0; i < skl->nr_modules; i++) { - skl->modules[i] = devm_kzalloc(dev, - sizeof(struct skl_module), GFP_KERNEL); - if (!skl->modules[i]) - return -ENOMEM; - } - break; - - case SKL_TKN_MM_U8_MOD_IDX: - mod_idx = tkn_elem->value; - break; - - case SKL_TKN_U32_ASTATE_COUNT: - if (astate_table != NULL) { - dev_err(dev, "More than one entry for A-State count"); - return -EINVAL; - } - - if (tkn_elem->value > SKL_MAX_ASTATE_CFG) { - dev_err(dev, "Invalid A-State count %d\n", - tkn_elem->value); - return -EINVAL; - } - - size = struct_size(skl->cfg.astate_cfg, astate_table, - tkn_elem->value); - skl->cfg.astate_cfg = devm_kzalloc(dev, size, GFP_KERNEL); - if (!skl->cfg.astate_cfg) - return -ENOMEM; - - astate_table = skl->cfg.astate_cfg->astate_table; - count = skl->cfg.astate_cfg->count = tkn_elem->value; - break; - - case SKL_TKN_U32_ASTATE_IDX: - if (tkn_elem->value >= count) { - dev_err(dev, "Invalid A-State index %d\n", - tkn_elem->value); - return -EINVAL; - } - - astate_cfg_idx = tkn_elem->value; - break; - - case SKL_TKN_U32_ASTATE_KCPS: - astate_table[astate_cfg_idx].kcps = tkn_elem->value; - break; - - case SKL_TKN_U32_ASTATE_CLK_SRC: - astate_table[astate_cfg_idx].clk_src = tkn_elem->value; - break; - - case SKL_TKN_U8_IN_PIN_TYPE: - case SKL_TKN_U8_OUT_PIN_TYPE: - case SKL_TKN_U8_IN_QUEUE_COUNT: - case SKL_TKN_U8_OUT_QUEUE_COUNT: - case SKL_TKN_MM_U8_NUM_RES: - case SKL_TKN_MM_U8_NUM_INTF: - ret = skl_tplg_fill_mod_info(dev, tkn_elem, mod); - if (ret < 0) - return ret; - break; - - case SKL_TKN_U32_DIR_PIN_COUNT: - dir = tkn_elem->value & SKL_IN_DIR_BIT_MASK; - pin_idx = (tkn_elem->value & SKL_PIN_COUNT_MASK) >> 4; - break; - - case SKL_TKN_MM_U32_RES_ID: - if (!res) - return -EINVAL; - - res->id = tkn_elem->value; - res_val_idx = tkn_elem->value; - break; - - case SKL_TKN_MM_U32_FMT_ID: - if (!fmt) - return -EINVAL; - - fmt->fmt_idx = tkn_elem->value; - intf_val_idx = tkn_elem->value; - break; - - case SKL_TKN_MM_U32_CPS: - case SKL_TKN_MM_U32_DMA_SIZE: - case SKL_TKN_MM_U32_CPC: - case SKL_TKN_U32_MEM_PAGES: - case SKL_TKN_U32_OBS: - case SKL_TKN_U32_IBS: - case SKL_TKN_MM_U32_RES_PIN_ID: - case SKL_TKN_MM_U32_PIN_BUF: - ret = skl_tplg_fill_res_tkn(dev, tkn_elem, res, pin_idx, dir); - if (ret < 0) - return ret; - - break; - - case SKL_TKN_MM_U32_NUM_IN_FMT: - if (!fmt) - return -EINVAL; - - res->nr_input_pins = tkn_elem->value; - break; - - case SKL_TKN_MM_U32_NUM_OUT_FMT: - if (!fmt) - return -EINVAL; - - res->nr_output_pins = tkn_elem->value; - break; - - case SKL_TKN_U32_FMT_CH: - case SKL_TKN_U32_FMT_FREQ: - case SKL_TKN_U32_FMT_BIT_DEPTH: - case SKL_TKN_U32_FMT_SAMPLE_SIZE: - case SKL_TKN_U32_FMT_CH_CONFIG: - case SKL_TKN_U32_FMT_INTERLEAVE: - case SKL_TKN_U32_FMT_SAMPLE_TYPE: - case SKL_TKN_U32_FMT_CH_MAP: - case SKL_TKN_MM_U32_INTF_PIN_ID: - ret = skl_tplg_manifest_fill_fmt(dev, fmt, tkn_elem, - dir, pin_idx); - if (ret < 0) - return ret; - break; - - default: - dev_err(dev, "Not a manifest token %d\n", tkn_elem->token); - return -EINVAL; - } - tkn_count++; - - return tkn_count; -} - -/* - * Fill the manifest structure by parsing the tokens based on the - * type. - */ -static int skl_tplg_get_manifest_tkn(struct device *dev, - char *pvt_data, struct skl_dev *skl, - int block_size) -{ - int tkn_count = 0, ret; - int off = 0, tuple_size = 0; - u8 uuid_index = 0; - struct snd_soc_tplg_vendor_array *array; - struct snd_soc_tplg_vendor_value_elem *tkn_elem; - - if (block_size <= 0) - return -EINVAL; - - while (tuple_size < block_size) { - array = (struct snd_soc_tplg_vendor_array *)(pvt_data + off); - off += array->size; - switch (array->type) { - case SND_SOC_TPLG_TUPLE_TYPE_STRING: - ret = skl_tplg_get_str_tkn(dev, array, skl); - - if (ret < 0) - return ret; - tkn_count = ret; - - tuple_size += tkn_count * - sizeof(struct snd_soc_tplg_vendor_string_elem); - continue; - - case SND_SOC_TPLG_TUPLE_TYPE_UUID: - if (array->uuid->token != SKL_TKN_UUID) { - dev_err(dev, "Not an UUID token: %d\n", - array->uuid->token); - return -EINVAL; - } - if (uuid_index >= skl->nr_modules) { - dev_err(dev, "Too many UUID tokens\n"); - return -EINVAL; - } - import_guid(&skl->modules[uuid_index++]->uuid, - array->uuid->uuid); - - tuple_size += sizeof(*array->uuid); - continue; - - default: - tkn_elem = array->value; - tkn_count = 0; - break; - } - - while (tkn_count <= array->num_elems - 1) { - ret = skl_tplg_get_int_tkn(dev, - tkn_elem, skl); - if (ret < 0) - return ret; - - tkn_count = tkn_count + ret; - tkn_elem++; - } - tuple_size += (tkn_count * sizeof(*tkn_elem)); - tkn_count = 0; - } - - return off; -} - -/* - * Parse manifest private data for tokens. The private data block is - * preceded by descriptors for type and size of data block. - */ -static int skl_tplg_get_manifest_data(struct snd_soc_tplg_manifest *manifest, - struct device *dev, struct skl_dev *skl) -{ - struct snd_soc_tplg_vendor_array *array; - int num_blocks, block_size = 0, block_type, off = 0; - char *data; - int ret; - - /* Read the NUM_DATA_BLOCKS descriptor */ - array = (struct snd_soc_tplg_vendor_array *)manifest->priv.data; - ret = skl_tplg_get_desc_blocks(dev, array); - if (ret < 0) - return ret; - num_blocks = ret; - - off += array->size; - /* Read the BLOCK_TYPE and BLOCK_SIZE descriptor */ - while (num_blocks > 0) { - array = (struct snd_soc_tplg_vendor_array *) - (manifest->priv.data + off); - ret = skl_tplg_get_desc_blocks(dev, array); - - if (ret < 0) - return ret; - block_type = ret; - off += array->size; - - array = (struct snd_soc_tplg_vendor_array *) - (manifest->priv.data + off); - - ret = skl_tplg_get_desc_blocks(dev, array); - - if (ret < 0) - return ret; - block_size = ret; - off += array->size; - - data = (manifest->priv.data + off); - - if (block_type == SKL_TYPE_TUPLE) { - ret = skl_tplg_get_manifest_tkn(dev, data, skl, - block_size); - - if (ret < 0) - return ret; - - --num_blocks; - } else { - return -EINVAL; - } - off += ret; - } - - return 0; -} - -static int skl_manifest_load(struct snd_soc_component *cmpnt, int index, - struct snd_soc_tplg_manifest *manifest) -{ - struct hdac_bus *bus = snd_soc_component_get_drvdata(cmpnt); - struct skl_dev *skl = bus_to_skl(bus); - - /* proceed only if we have private data defined */ - if (manifest->priv.size == 0) - return 0; - - skl_tplg_get_manifest_data(manifest, bus->dev, skl); - - if (skl->lib_count > SKL_MAX_LIB) { - dev_err(bus->dev, "Exceeding max Library count. Got:%d\n", - skl->lib_count); - return -EINVAL; - } - - return 0; -} - -static int skl_tplg_complete(struct snd_soc_component *component) -{ - struct snd_soc_dobj *dobj; - struct snd_soc_acpi_mach *mach; - struct snd_ctl_elem_value *val; - int i; - - val = kmalloc(sizeof(*val), GFP_KERNEL); - if (!val) - return -ENOMEM; - - mach = dev_get_platdata(component->card->dev); - list_for_each_entry(dobj, &component->dobj_list, list) { - struct snd_kcontrol *kcontrol = dobj->control.kcontrol; - struct soc_enum *se; - char **texts; - char chan_text[4]; - - if (dobj->type != SND_SOC_DOBJ_ENUM || !kcontrol || - kcontrol->put != skl_tplg_multi_config_set_dmic) - continue; - - se = (struct soc_enum *)kcontrol->private_value; - texts = dobj->control.dtexts; - sprintf(chan_text, "c%d", mach->mach_params.dmic_num); - - for (i = 0; i < se->items; i++) { - if (strstr(texts[i], chan_text)) { - memset(val, 0, sizeof(*val)); - val->value.enumerated.item[0] = i; - kcontrol->put(kcontrol, val); - } - } - } - - kfree(val); - return 0; -} - -static const struct snd_soc_tplg_ops skl_tplg_ops = { - .widget_load = skl_tplg_widget_load, - .control_load = skl_tplg_control_load, - .bytes_ext_ops = skl_tlv_ops, - .bytes_ext_ops_count = ARRAY_SIZE(skl_tlv_ops), - .io_ops = skl_tplg_kcontrol_ops, - .io_ops_count = ARRAY_SIZE(skl_tplg_kcontrol_ops), - .manifest = skl_manifest_load, - .dai_load = skl_dai_load, - .complete = skl_tplg_complete, -}; - -/* - * A pipe can have multiple modules, each of them will be a DAPM widget as - * well. While managing a pipeline we need to get the list of all the - * widgets in a pipelines, so this helper - skl_tplg_create_pipe_widget_list() - * helps to get the SKL type widgets in that pipeline - */ -static int skl_tplg_create_pipe_widget_list(struct snd_soc_component *component) -{ - struct snd_soc_dapm_widget *w; - struct skl_module_cfg *mcfg = NULL; - struct skl_pipe_module *p_module = NULL; - struct skl_pipe *pipe; - - list_for_each_entry(w, &component->card->widgets, list) { - if (is_skl_dsp_widget_type(w, component->dev) && w->priv) { - mcfg = w->priv; - pipe = mcfg->pipe; - - p_module = devm_kzalloc(component->dev, - sizeof(*p_module), GFP_KERNEL); - if (!p_module) - return -ENOMEM; - - p_module->w = w; - list_add_tail(&p_module->node, &pipe->w_list); - } - } - - return 0; -} - -static void skl_tplg_set_pipe_type(struct skl_dev *skl, struct skl_pipe *pipe) -{ - struct skl_pipe_module *w_module; - struct snd_soc_dapm_widget *w; - struct skl_module_cfg *mconfig; - bool host_found = false, link_found = false; - - list_for_each_entry(w_module, &pipe->w_list, node) { - w = w_module->w; - mconfig = w->priv; - - if (mconfig->dev_type == SKL_DEVICE_HDAHOST) - host_found = true; - else if (mconfig->dev_type != SKL_DEVICE_NONE) - link_found = true; - } - - if (host_found && link_found) - pipe->passthru = true; - else - pipe->passthru = false; -} - -/* - * SKL topology init routine - */ -int skl_tplg_init(struct snd_soc_component *component, struct hdac_bus *bus) -{ - int ret; - const struct firmware *fw; - struct skl_dev *skl = bus_to_skl(bus); - struct skl_pipeline *ppl; - - ret = request_firmware(&fw, skl->tplg_name, bus->dev); - if (ret < 0) { - char alt_tplg_name[64]; - - snprintf(alt_tplg_name, sizeof(alt_tplg_name), "%s-tplg.bin", - skl->mach->drv_name); - dev_info(bus->dev, "tplg fw %s load failed with %d, trying alternative tplg name %s", - skl->tplg_name, ret, alt_tplg_name); - - ret = request_firmware(&fw, alt_tplg_name, bus->dev); - if (!ret) - goto component_load; - - dev_info(bus->dev, "tplg %s failed with %d, falling back to dfw_sst.bin", - alt_tplg_name, ret); - - ret = request_firmware(&fw, "dfw_sst.bin", bus->dev); - if (ret < 0) { - dev_err(bus->dev, "Fallback tplg fw %s load failed with %d\n", - "dfw_sst.bin", ret); - return ret; - } - } - -component_load: - ret = snd_soc_tplg_component_load(component, &skl_tplg_ops, fw); - if (ret < 0) { - dev_err(bus->dev, "tplg component load failed%d\n", ret); - goto err; - } - - ret = skl_tplg_create_pipe_widget_list(component); - if (ret < 0) { - dev_err(bus->dev, "tplg create pipe widget list failed%d\n", - ret); - goto err; - } - - list_for_each_entry(ppl, &skl->ppl_list, node) - skl_tplg_set_pipe_type(skl, ppl->pipe); - -err: - release_firmware(fw); - return ret; -} - -void skl_tplg_exit(struct snd_soc_component *component, struct hdac_bus *bus) -{ - struct skl_dev *skl = bus_to_skl(bus); - struct skl_pipeline *ppl, *tmp; - - list_for_each_entry_safe(ppl, tmp, &skl->ppl_list, node) - list_del(&ppl->node); - - /* clean up topology */ - snd_soc_tplg_component_remove(component); -} diff --git a/sound/soc/intel/skylake/skl-topology.h b/sound/soc/intel/skylake/skl-topology.h deleted file mode 100644 index 30a0977af94375..00000000000000 --- a/sound/soc/intel/skylake/skl-topology.h +++ /dev/null @@ -1,524 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * skl_topology.h - Intel HDA Platform topology header file - * - * Copyright (C) 2014-15 Intel Corp - * Author: Jeeja KP - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ - -#ifndef __SKL_TOPOLOGY_H__ -#define __SKL_TOPOLOGY_H__ - -#include - -#include -#include -#include -#include "skl.h" - -#define BITS_PER_BYTE 8 -#define MAX_TS_GROUPS 8 -#define MAX_DMIC_TS_GROUPS 4 -#define MAX_FIXED_DMIC_PARAMS_SIZE 727 - -/* Maximum number of coefficients up down mixer module */ -#define UP_DOWN_MIXER_MAX_COEFF 8 - -#define MODULE_MAX_IN_PINS 8 -#define MODULE_MAX_OUT_PINS 8 - -#define SKL_MIC_CH_SUPPORT 4 -#define SKL_MIC_MAX_CH_SUPPORT 8 -#define SKL_DEFAULT_MIC_SEL_GAIN 0x3FF -#define SKL_MIC_SEL_SWITCH 0x3 - -#define SKL_OUTPUT_PIN 0 -#define SKL_INPUT_PIN 1 -#define SKL_MAX_PATH_CONFIGS 8 -#define SKL_MAX_MODULES_IN_PIPE 8 -#define SKL_MAX_MODULE_FORMATS 32 -#define SKL_MAX_MODULE_RESOURCES 32 - -enum skl_channel_index { - SKL_CHANNEL_LEFT = 0, - SKL_CHANNEL_RIGHT = 1, - SKL_CHANNEL_CENTER = 2, - SKL_CHANNEL_LEFT_SURROUND = 3, - SKL_CHANNEL_CENTER_SURROUND = 3, - SKL_CHANNEL_RIGHT_SURROUND = 4, - SKL_CHANNEL_LFE = 7, - SKL_CHANNEL_INVALID = 0xF, -}; - -enum skl_bitdepth { - SKL_DEPTH_8BIT = 8, - SKL_DEPTH_16BIT = 16, - SKL_DEPTH_24BIT = 24, - SKL_DEPTH_32BIT = 32, - SKL_DEPTH_INVALID -}; - - -enum skl_s_freq { - SKL_FS_8000 = 8000, - SKL_FS_11025 = 11025, - SKL_FS_12000 = 12000, - SKL_FS_16000 = 16000, - SKL_FS_22050 = 22050, - SKL_FS_24000 = 24000, - SKL_FS_32000 = 32000, - SKL_FS_44100 = 44100, - SKL_FS_48000 = 48000, - SKL_FS_64000 = 64000, - SKL_FS_88200 = 88200, - SKL_FS_96000 = 96000, - SKL_FS_128000 = 128000, - SKL_FS_176400 = 176400, - SKL_FS_192000 = 192000, - SKL_FS_INVALID -}; - -#define SKL_MAX_PARAMS_TYPES 4 - -enum skl_widget_type { - SKL_WIDGET_VMIXER = 1, - SKL_WIDGET_MIXER = 2, - SKL_WIDGET_PGA = 3, - SKL_WIDGET_MUX = 4 -}; - -struct skl_audio_data_format { - enum skl_s_freq s_freq; - enum skl_bitdepth bit_depth; - u32 channel_map; - enum skl_ch_cfg ch_cfg; - enum skl_interleaving interleaving; - u8 number_of_channels; - u8 valid_bit_depth; - u8 sample_type; - u8 reserved; -} __packed; - -struct skl_base_cfg { - u32 cpc; - u32 ibs; - u32 obs; - u32 is_pages; - struct skl_audio_data_format audio_fmt; -}; - -struct skl_cpr_gtw_cfg { - u32 node_id; - u32 dma_buffer_size; - u32 config_length; - /* not mandatory; required only for DMIC/I2S */ - struct { - u32 gtw_attrs; - u32 data[]; - } config_data; -} __packed; - -struct skl_dma_control { - u32 node_id; - u32 config_length; - u32 config_data[]; -} __packed; - -struct skl_cpr_cfg { - struct skl_base_cfg base_cfg; - struct skl_audio_data_format out_fmt; - u32 cpr_feature_mask; - struct skl_cpr_gtw_cfg gtw_cfg; -} __packed; - -struct skl_cpr_pin_fmt { - u32 sink_id; - struct skl_audio_data_format src_fmt; - struct skl_audio_data_format dst_fmt; -} __packed; - -struct skl_src_module_cfg { - struct skl_base_cfg base_cfg; - enum skl_s_freq src_cfg; -} __packed; - -struct skl_up_down_mixer_cfg { - struct skl_base_cfg base_cfg; - enum skl_ch_cfg out_ch_cfg; - /* This should be set to 1 if user coefficients are required */ - u32 coeff_sel; - /* Pass the user coeff in this array */ - s32 coeff[UP_DOWN_MIXER_MAX_COEFF]; - u32 ch_map; -} __packed; - -struct skl_pin_format { - u32 pin_idx; - u32 buf_size; - struct skl_audio_data_format audio_fmt; -} __packed; - -struct skl_base_cfg_ext { - u16 nr_input_pins; - u16 nr_output_pins; - u8 reserved[8]; - u32 priv_param_length; - /* Input pin formats followed by output ones. */ - struct skl_pin_format pins_fmt[]; -} __packed; - -struct skl_algo_cfg { - struct skl_base_cfg base_cfg; - char params[]; -} __packed; - -struct skl_base_outfmt_cfg { - struct skl_base_cfg base_cfg; - struct skl_audio_data_format out_fmt; -} __packed; - -enum skl_dma_type { - SKL_DMA_HDA_HOST_OUTPUT_CLASS = 0, - SKL_DMA_HDA_HOST_INPUT_CLASS = 1, - SKL_DMA_HDA_HOST_INOUT_CLASS = 2, - SKL_DMA_HDA_LINK_OUTPUT_CLASS = 8, - SKL_DMA_HDA_LINK_INPUT_CLASS = 9, - SKL_DMA_HDA_LINK_INOUT_CLASS = 0xA, - SKL_DMA_DMIC_LINK_INPUT_CLASS = 0xB, - SKL_DMA_I2S_LINK_OUTPUT_CLASS = 0xC, - SKL_DMA_I2S_LINK_INPUT_CLASS = 0xD, -}; - -union skl_ssp_dma_node { - u8 val; - struct { - u8 time_slot_index:4; - u8 i2s_instance:4; - } dma_node; -}; - -union skl_connector_node_id { - u32 val; - struct { - u32 vindex:8; - u32 dma_type:4; - u32 rsvd:20; - } node; -}; - -struct skl_module_fmt { - u32 channels; - u32 s_freq; - u32 bit_depth; - u32 valid_bit_depth; - u32 ch_cfg; - u32 interleaving_style; - u32 sample_type; - u32 ch_map; -}; - -struct skl_module_cfg; - -struct skl_mod_inst_map { - u16 mod_id; - u16 inst_id; -}; - -struct skl_uuid_inst_map { - u16 inst_id; - u16 reserved; - guid_t mod_uuid; -} __packed; - -struct skl_kpb_params { - u32 num_modules; - union { - DECLARE_FLEX_ARRAY(struct skl_mod_inst_map, map); - DECLARE_FLEX_ARRAY(struct skl_uuid_inst_map, map_uuid); - } u; -}; - -struct skl_module_inst_id { - guid_t mod_uuid; - int module_id; - u32 instance_id; - int pvt_id; -}; - -enum skl_module_pin_state { - SKL_PIN_UNBIND = 0, - SKL_PIN_BIND_DONE = 1, -}; - -struct skl_module_pin { - struct skl_module_inst_id id; - bool is_dynamic; - bool in_use; - enum skl_module_pin_state pin_state; - struct skl_module_cfg *tgt_mcfg; -}; - -struct skl_specific_cfg { - u32 set_params; - u32 param_id; - u32 caps_size; - u32 *caps; -}; - -enum skl_pipe_state { - SKL_PIPE_INVALID = 0, - SKL_PIPE_CREATED = 1, - SKL_PIPE_PAUSED = 2, - SKL_PIPE_STARTED = 3, - SKL_PIPE_RESET = 4 -}; - -struct skl_pipe_module { - struct snd_soc_dapm_widget *w; - struct list_head node; -}; - -struct skl_pipe_params { - u8 host_dma_id; - u8 link_dma_id; - u32 ch; - u32 s_freq; - u32 s_fmt; - u32 s_cont; - u8 linktype; - snd_pcm_format_t format; - int link_index; - int stream; - unsigned int host_bps; - unsigned int link_bps; -}; - -struct skl_pipe_fmt { - u32 freq; - u8 channels; - u8 bps; -}; - -struct skl_pipe_mcfg { - u8 res_idx; - u8 fmt_idx; -}; - -struct skl_path_config { - u8 mem_pages; - struct skl_pipe_fmt in_fmt; - struct skl_pipe_fmt out_fmt; -}; - -struct skl_pipe { - u8 ppl_id; - u8 pipe_priority; - u16 conn_type; - u32 memory_pages; - u8 lp_mode; - struct skl_pipe_params *p_params; - enum skl_pipe_state state; - u8 direction; - u8 cur_config_idx; - u8 nr_cfgs; - struct skl_path_config configs[SKL_MAX_PATH_CONFIGS]; - struct list_head w_list; - bool passthru; -}; - -enum skl_module_state { - SKL_MODULE_UNINIT = 0, - SKL_MODULE_INIT_DONE = 1, - SKL_MODULE_BIND_DONE = 2, -}; - -enum d0i3_capability { - SKL_D0I3_NONE = 0, - SKL_D0I3_STREAMING = 1, - SKL_D0I3_NON_STREAMING = 2, -}; - -struct skl_module_pin_fmt { - u8 id; - struct skl_module_fmt fmt; -}; - -struct skl_module_iface { - u8 fmt_idx; - u8 nr_in_fmt; - u8 nr_out_fmt; - struct skl_module_pin_fmt inputs[MAX_IN_QUEUE]; - struct skl_module_pin_fmt outputs[MAX_OUT_QUEUE]; -}; - -struct skl_module_pin_resources { - u8 pin_index; - u32 buf_size; -}; - -struct skl_module_res { - u8 id; - u32 is_pages; - u32 ibs; - u32 obs; - u32 dma_buffer_size; - u32 cpc; - u8 nr_input_pins; - u8 nr_output_pins; - struct skl_module_pin_resources input[MAX_IN_QUEUE]; - struct skl_module_pin_resources output[MAX_OUT_QUEUE]; -}; - -struct skl_module { - guid_t uuid; - u8 loadable; - u8 input_pin_type; - u8 output_pin_type; - u8 max_input_pins; - u8 max_output_pins; - u8 nr_resources; - u8 nr_interfaces; - struct skl_module_res resources[SKL_MAX_MODULE_RESOURCES]; - struct skl_module_iface formats[SKL_MAX_MODULE_FORMATS]; -}; - -struct skl_module_cfg { - u8 guid[16]; - struct skl_module_inst_id id; - struct skl_module *module; - int res_idx; - int fmt_idx; - int fmt_cfg_idx; - u8 domain; - bool homogenous_inputs; - bool homogenous_outputs; - struct skl_module_fmt in_fmt[MODULE_MAX_IN_PINS]; - struct skl_module_fmt out_fmt[MODULE_MAX_OUT_PINS]; - u8 max_in_queue; - u8 max_out_queue; - u8 in_queue_mask; - u8 out_queue_mask; - u8 in_queue; - u8 out_queue; - u8 is_loadable; - u8 core_id; - u8 dev_type; - u8 dma_id; - u8 time_slot; - u8 dmic_ch_combo_index; - u32 dmic_ch_type; - u32 params_fixup; - u32 converter; - u32 vbus_id; - u32 mem_pages; - enum d0i3_capability d0i3_caps; - u32 dma_buffer_size; /* in milli seconds */ - struct skl_module_pin *m_in_pin; - struct skl_module_pin *m_out_pin; - enum skl_module_type m_type; - enum skl_hw_conn_type hw_conn_type; - enum skl_module_state m_state; - struct skl_pipe *pipe; - struct skl_specific_cfg formats_config[SKL_MAX_PARAMS_TYPES]; - struct skl_pipe_mcfg mod_cfg[SKL_MAX_MODULES_IN_PIPE]; -}; - -struct skl_algo_data { - u32 param_id; - u32 set_params; - u32 max; - u32 size; - char *params; -}; - -struct skl_pipeline { - struct skl_pipe *pipe; - struct list_head node; -}; - -struct skl_module_deferred_bind { - struct skl_module_cfg *src; - struct skl_module_cfg *dst; - struct list_head node; -}; - -struct skl_mic_sel_config { - u16 mic_switch; - u16 flags; - u16 blob[SKL_MIC_MAX_CH_SUPPORT][SKL_MIC_MAX_CH_SUPPORT]; -} __packed; - -enum skl_channel { - SKL_CH_MONO = 1, - SKL_CH_STEREO = 2, - SKL_CH_TRIO = 3, - SKL_CH_QUATRO = 4, -}; - -static inline struct skl_dev *get_skl_ctx(struct device *dev) -{ - struct hdac_bus *bus = dev_get_drvdata(dev); - - return bus_to_skl(bus); -} - -int skl_tplg_be_update_params(struct snd_soc_dai *dai, - struct skl_pipe_params *params); -int skl_dsp_set_dma_control(struct skl_dev *skl, u32 *caps, - u32 caps_size, u32 node_id); -void skl_tplg_set_be_dmic_config(struct snd_soc_dai *dai, - struct skl_pipe_params *params, int stream); -int skl_tplg_init(struct snd_soc_component *component, - struct hdac_bus *bus); -void skl_tplg_exit(struct snd_soc_component *component, - struct hdac_bus *bus); -struct skl_module_cfg *skl_tplg_fe_get_cpr_module( - struct snd_soc_dai *dai, int stream); -int skl_tplg_update_pipe_params(struct device *dev, - struct skl_module_cfg *mconfig, struct skl_pipe_params *params); - -void skl_tplg_d0i3_get(struct skl_dev *skl, enum d0i3_capability caps); -void skl_tplg_d0i3_put(struct skl_dev *skl, enum d0i3_capability caps); - -int skl_create_pipeline(struct skl_dev *skl, struct skl_pipe *pipe); - -int skl_run_pipe(struct skl_dev *skl, struct skl_pipe *pipe); - -int skl_pause_pipe(struct skl_dev *skl, struct skl_pipe *pipe); - -int skl_delete_pipe(struct skl_dev *skl, struct skl_pipe *pipe); - -int skl_stop_pipe(struct skl_dev *skl, struct skl_pipe *pipe); - -int skl_reset_pipe(struct skl_dev *skl, struct skl_pipe *pipe); - -int skl_init_module(struct skl_dev *skl, struct skl_module_cfg *mconfig); - -int skl_bind_modules(struct skl_dev *skl, struct skl_module_cfg - *src_mcfg, struct skl_module_cfg *dst_mcfg); - -int skl_unbind_modules(struct skl_dev *skl, struct skl_module_cfg - *src_mcfg, struct skl_module_cfg *dst_mcfg); - -int skl_set_module_params(struct skl_dev *skl, u32 *params, int size, - u32 param_id, struct skl_module_cfg *mcfg); -int skl_get_module_params(struct skl_dev *skl, u32 *params, int size, - u32 param_id, struct skl_module_cfg *mcfg); - -struct skl_module_cfg *skl_tplg_be_get_cpr_module(struct snd_soc_dai *dai, - int stream); -enum skl_bitdepth skl_get_bit_depth(int params); -int skl_pcm_host_dma_prepare(struct device *dev, - struct skl_pipe_params *params); -int skl_pcm_link_dma_prepare(struct device *dev, - struct skl_pipe_params *params); - -int skl_dai_load(struct snd_soc_component *cmp, int index, - struct snd_soc_dai_driver *dai_drv, - struct snd_soc_tplg_pcm *pcm, struct snd_soc_dai *dai); -void skl_tplg_add_moduleid_in_bind_params(struct skl_dev *skl, - struct snd_soc_dapm_widget *w); -#endif diff --git a/sound/soc/intel/skylake/skl.c b/sound/soc/intel/skylake/skl.c deleted file mode 100644 index 96c71c9a2681fb..00000000000000 --- a/sound/soc/intel/skylake/skl.c +++ /dev/null @@ -1,1159 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * skl.c - Implementation of ASoC Intel SKL HD Audio driver - * - * Copyright (C) 2014-2015 Intel Corp - * Author: Jeeja KP - * - * Derived mostly from Intel HDA driver with following copyrights: - * Copyright (c) 2004 Takashi Iwai - * PeiSen Hou - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "skl.h" -#include "skl-sst-dsp.h" -#include "skl-sst-ipc.h" - -#if IS_ENABLED(CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC) -#include "../../../soc/codecs/hdac_hda.h" -#endif -static int skl_pci_binding; -module_param_named(pci_binding, skl_pci_binding, int, 0444); -MODULE_PARM_DESC(pci_binding, "PCI binding (0=auto, 1=only legacy, 2=only asoc"); - -/* - * initialize the PCI registers - */ -static void skl_update_pci_byte(struct pci_dev *pci, unsigned int reg, - unsigned char mask, unsigned char val) -{ - unsigned char data; - - pci_read_config_byte(pci, reg, &data); - data &= ~mask; - data |= (val & mask); - pci_write_config_byte(pci, reg, data); -} - -static void skl_init_pci(struct skl_dev *skl) -{ - struct hdac_bus *bus = skl_to_bus(skl); - - /* - * Clear bits 0-2 of PCI register TCSEL (at offset 0x44) - * TCSEL == Traffic Class Select Register, which sets PCI express QOS - * Ensuring these bits are 0 clears playback static on some HD Audio - * codecs. - * The PCI register TCSEL is defined in the Intel manuals. - */ - dev_dbg(bus->dev, "Clearing TCSEL\n"); - skl_update_pci_byte(skl->pci, AZX_PCIREG_TCSEL, 0x07, 0); -} - -static void update_pci_dword(struct pci_dev *pci, - unsigned int reg, u32 mask, u32 val) -{ - u32 data = 0; - - pci_read_config_dword(pci, reg, &data); - data &= ~mask; - data |= (val & mask); - pci_write_config_dword(pci, reg, data); -} - -/* - * skl_enable_miscbdcge - enable/dsiable CGCTL.MISCBDCGE bits - * - * @dev: device pointer - * @enable: enable/disable flag - */ -static void skl_enable_miscbdcge(struct device *dev, bool enable) -{ - struct pci_dev *pci = to_pci_dev(dev); - u32 val; - - val = enable ? AZX_CGCTL_MISCBDCGE_MASK : 0; - - update_pci_dword(pci, AZX_PCIREG_CGCTL, AZX_CGCTL_MISCBDCGE_MASK, val); -} - -/** - * skl_clock_power_gating: Enable/Disable clock and power gating - * - * @dev: Device pointer - * @enable: Enable/Disable flag - */ -static void skl_clock_power_gating(struct device *dev, bool enable) -{ - struct pci_dev *pci = to_pci_dev(dev); - struct hdac_bus *bus = pci_get_drvdata(pci); - u32 val; - - /* Update PDCGE bit of CGCTL register */ - val = enable ? AZX_CGCTL_ADSPDCGE : 0; - update_pci_dword(pci, AZX_PCIREG_CGCTL, AZX_CGCTL_ADSPDCGE, val); - - /* Update L1SEN bit of EM2 register */ - val = enable ? AZX_REG_VS_EM2_L1SEN : 0; - snd_hdac_chip_updatel(bus, VS_EM2, AZX_REG_VS_EM2_L1SEN, val); - - /* Update ADSPPGD bit of PGCTL register */ - val = enable ? 0 : AZX_PGCTL_ADSPPGD; - update_pci_dword(pci, AZX_PCIREG_PGCTL, AZX_PGCTL_ADSPPGD, val); -} - -/* - * While performing reset, controller may not come back properly causing - * issues, so recommendation is to set CGCTL.MISCBDCGE to 0 then do reset - * (init chip) and then again set CGCTL.MISCBDCGE to 1 - */ -static int skl_init_chip(struct hdac_bus *bus, bool full_reset) -{ - struct hdac_ext_link *hlink; - int ret; - - snd_hdac_set_codec_wakeup(bus, true); - skl_enable_miscbdcge(bus->dev, false); - ret = snd_hdac_bus_init_chip(bus, full_reset); - - /* Reset stream-to-link mapping */ - list_for_each_entry(hlink, &bus->hlink_list, list) - writel(0, hlink->ml_addr + AZX_REG_ML_LOSIDV); - - skl_enable_miscbdcge(bus->dev, true); - snd_hdac_set_codec_wakeup(bus, false); - - return ret; -} - -void skl_update_d0i3c(struct device *dev, bool enable) -{ - struct pci_dev *pci = to_pci_dev(dev); - struct hdac_bus *bus = pci_get_drvdata(pci); - u8 reg; - int timeout = 50; - - reg = snd_hdac_chip_readb(bus, VS_D0I3C); - /* Do not write to D0I3C until command in progress bit is cleared */ - while ((reg & AZX_REG_VS_D0I3C_CIP) && --timeout) { - udelay(10); - reg = snd_hdac_chip_readb(bus, VS_D0I3C); - } - - /* Highly unlikely. But if it happens, flag error explicitly */ - if (!timeout) { - dev_err(bus->dev, "Before D0I3C update: D0I3C CIP timeout\n"); - return; - } - - if (enable) - reg = reg | AZX_REG_VS_D0I3C_I3; - else - reg = reg & (~AZX_REG_VS_D0I3C_I3); - - snd_hdac_chip_writeb(bus, VS_D0I3C, reg); - - timeout = 50; - /* Wait for cmd in progress to be cleared before exiting the function */ - reg = snd_hdac_chip_readb(bus, VS_D0I3C); - while ((reg & AZX_REG_VS_D0I3C_CIP) && --timeout) { - udelay(10); - reg = snd_hdac_chip_readb(bus, VS_D0I3C); - } - - /* Highly unlikely. But if it happens, flag error explicitly */ - if (!timeout) { - dev_err(bus->dev, "After D0I3C update: D0I3C CIP timeout\n"); - return; - } - - dev_dbg(bus->dev, "D0I3C register = 0x%x\n", - snd_hdac_chip_readb(bus, VS_D0I3C)); -} - -/** - * skl_dum_set - set DUM bit in EM2 register - * @bus: HD-audio core bus - * - * Addresses incorrect position reporting for capture streams. - * Used on device power up. - */ -static void skl_dum_set(struct hdac_bus *bus) -{ - /* For the DUM bit to be set, CRST needs to be out of reset state */ - if (!(snd_hdac_chip_readb(bus, GCTL) & AZX_GCTL_RESET)) { - skl_enable_miscbdcge(bus->dev, false); - snd_hdac_bus_exit_link_reset(bus); - skl_enable_miscbdcge(bus->dev, true); - } - - snd_hdac_chip_updatel(bus, VS_EM2, AZX_VS_EM2_DUM, AZX_VS_EM2_DUM); -} - -/* called from IRQ */ -static void skl_stream_update(struct hdac_bus *bus, struct hdac_stream *hstr) -{ - snd_pcm_period_elapsed(hstr->substream); -} - -static irqreturn_t skl_interrupt(int irq, void *dev_id) -{ - struct hdac_bus *bus = dev_id; - u32 status; - - if (!pm_runtime_active(bus->dev)) - return IRQ_NONE; - - spin_lock(&bus->reg_lock); - - status = snd_hdac_chip_readl(bus, INTSTS); - if (status == 0 || status == 0xffffffff) { - spin_unlock(&bus->reg_lock); - return IRQ_NONE; - } - - /* clear rirb int */ - status = snd_hdac_chip_readb(bus, RIRBSTS); - if (status & RIRB_INT_MASK) { - if (status & RIRB_INT_RESPONSE) - snd_hdac_bus_update_rirb(bus); - snd_hdac_chip_writeb(bus, RIRBSTS, RIRB_INT_MASK); - } - - spin_unlock(&bus->reg_lock); - - return snd_hdac_chip_readl(bus, INTSTS) ? IRQ_WAKE_THREAD : IRQ_HANDLED; -} - -static irqreturn_t skl_threaded_handler(int irq, void *dev_id) -{ - struct hdac_bus *bus = dev_id; - u32 status; - - status = snd_hdac_chip_readl(bus, INTSTS); - - snd_hdac_bus_handle_stream_irq(bus, status, skl_stream_update); - - return IRQ_HANDLED; -} - -static int skl_acquire_irq(struct hdac_bus *bus, int do_disconnect) -{ - struct skl_dev *skl = bus_to_skl(bus); - int ret; - - ret = request_threaded_irq(skl->pci->irq, skl_interrupt, - skl_threaded_handler, - IRQF_SHARED, - KBUILD_MODNAME, bus); - if (ret) { - dev_err(bus->dev, - "unable to grab IRQ %d, disabling device\n", - skl->pci->irq); - return ret; - } - - bus->irq = skl->pci->irq; - pci_intx(skl->pci, 1); - - return 0; -} - -static int skl_suspend_late(struct device *dev) -{ - struct pci_dev *pci = to_pci_dev(dev); - struct hdac_bus *bus = pci_get_drvdata(pci); - struct skl_dev *skl = bus_to_skl(bus); - - return skl_suspend_late_dsp(skl); -} - -#ifdef CONFIG_PM -static int _skl_suspend(struct hdac_bus *bus) -{ - struct skl_dev *skl = bus_to_skl(bus); - struct pci_dev *pci = to_pci_dev(bus->dev); - int ret; - - snd_hdac_ext_bus_link_power_down_all(bus); - - ret = skl_suspend_dsp(skl); - if (ret < 0) - return ret; - - snd_hdac_bus_stop_chip(bus); - update_pci_dword(pci, AZX_PCIREG_PGCTL, - AZX_PGCTL_LSRMD_MASK, AZX_PGCTL_LSRMD_MASK); - skl_enable_miscbdcge(bus->dev, false); - snd_hdac_bus_enter_link_reset(bus); - skl_enable_miscbdcge(bus->dev, true); - skl_cleanup_resources(skl); - - return 0; -} - -static int _skl_resume(struct hdac_bus *bus) -{ - struct skl_dev *skl = bus_to_skl(bus); - - skl_init_pci(skl); - skl_dum_set(bus); - skl_init_chip(bus, true); - - return skl_resume_dsp(skl); -} -#endif - -#ifdef CONFIG_PM_SLEEP -/* - * power management - */ -static int skl_suspend(struct device *dev) -{ - struct pci_dev *pci = to_pci_dev(dev); - struct hdac_bus *bus = pci_get_drvdata(pci); - struct skl_dev *skl = bus_to_skl(bus); - int ret; - - /* - * Do not suspend if streams which are marked ignore suspend are - * running, we need to save the state for these and continue - */ - if (skl->supend_active) { - /* turn off the links and stop the CORB/RIRB DMA if it is On */ - snd_hdac_ext_bus_link_power_down_all(bus); - - if (bus->cmd_dma_state) - snd_hdac_bus_stop_cmd_io(bus); - - enable_irq_wake(bus->irq); - pci_save_state(pci); - } else { - ret = _skl_suspend(bus); - if (ret < 0) - return ret; - skl->fw_loaded = false; - } - - return 0; -} - -static int skl_resume(struct device *dev) -{ - struct pci_dev *pci = to_pci_dev(dev); - struct hdac_bus *bus = pci_get_drvdata(pci); - struct skl_dev *skl = bus_to_skl(bus); - struct hdac_ext_link *hlink; - int ret; - - /* - * resume only when we are not in suspend active, otherwise need to - * restore the device - */ - if (skl->supend_active) { - pci_restore_state(pci); - snd_hdac_ext_bus_link_power_up_all(bus); - disable_irq_wake(bus->irq); - /* - * turn On the links which are On before active suspend - * and start the CORB/RIRB DMA if On before - * active suspend. - */ - list_for_each_entry(hlink, &bus->hlink_list, list) { - if (hlink->ref_count) - snd_hdac_ext_bus_link_power_up(hlink); - } - - ret = 0; - if (bus->cmd_dma_state) - snd_hdac_bus_init_cmd_io(bus); - } else { - ret = _skl_resume(bus); - } - - return ret; -} -#endif /* CONFIG_PM_SLEEP */ - -#ifdef CONFIG_PM -static int skl_runtime_suspend(struct device *dev) -{ - struct pci_dev *pci = to_pci_dev(dev); - struct hdac_bus *bus = pci_get_drvdata(pci); - - dev_dbg(bus->dev, "in %s\n", __func__); - - return _skl_suspend(bus); -} - -static int skl_runtime_resume(struct device *dev) -{ - struct pci_dev *pci = to_pci_dev(dev); - struct hdac_bus *bus = pci_get_drvdata(pci); - - dev_dbg(bus->dev, "in %s\n", __func__); - - return _skl_resume(bus); -} -#endif /* CONFIG_PM */ - -static const struct dev_pm_ops skl_pm = { - SET_SYSTEM_SLEEP_PM_OPS(skl_suspend, skl_resume) - SET_RUNTIME_PM_OPS(skl_runtime_suspend, skl_runtime_resume, NULL) - .suspend_late = skl_suspend_late, -}; - -/* - * destructor - */ -static int skl_free(struct hdac_bus *bus) -{ - struct skl_dev *skl = bus_to_skl(bus); - - skl->init_done = 0; /* to be sure */ - - snd_hdac_stop_streams_and_chip(bus); - - if (bus->irq >= 0) - free_irq(bus->irq, (void *)bus); - snd_hdac_bus_free_stream_pages(bus); - snd_hdac_ext_stream_free_all(bus); - snd_hdac_ext_link_free_all(bus); - - if (bus->remap_addr) - iounmap(bus->remap_addr); - - pci_release_regions(skl->pci); - pci_disable_device(skl->pci); - - snd_hdac_ext_bus_exit(bus); - - if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) { - snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, false); - snd_hdac_i915_exit(bus); - } - - return 0; -} - -/* - * For each ssp there are 3 clocks (mclk/sclk/sclkfs). - * e.g. for ssp0, clocks will be named as - * "ssp0_mclk", "ssp0_sclk", "ssp0_sclkfs" - * So for skl+, there are 6 ssps, so 18 clocks will be created. - */ -static struct skl_ssp_clk skl_ssp_clks[] = { - {.name = "ssp0_mclk"}, {.name = "ssp1_mclk"}, {.name = "ssp2_mclk"}, - {.name = "ssp3_mclk"}, {.name = "ssp4_mclk"}, {.name = "ssp5_mclk"}, - {.name = "ssp0_sclk"}, {.name = "ssp1_sclk"}, {.name = "ssp2_sclk"}, - {.name = "ssp3_sclk"}, {.name = "ssp4_sclk"}, {.name = "ssp5_sclk"}, - {.name = "ssp0_sclkfs"}, {.name = "ssp1_sclkfs"}, - {.name = "ssp2_sclkfs"}, - {.name = "ssp3_sclkfs"}, {.name = "ssp4_sclkfs"}, - {.name = "ssp5_sclkfs"}, -}; - -static int skl_find_machine(struct skl_dev *skl, void *driver_data) -{ - struct hdac_bus *bus = skl_to_bus(skl); - struct snd_soc_acpi_mach *mach = driver_data; - struct skl_machine_pdata *pdata; - - mach = snd_soc_acpi_find_machine(mach); - if (!mach) { - dev_err(bus->dev, "No matching I2S machine driver found\n"); - return -ENODEV; - } - - skl->mach = mach; - skl->fw_name = mach->fw_filename; - pdata = mach->pdata; - - if (pdata) { - skl->use_tplg_pcm = pdata->use_tplg_pcm; - mach->mach_params.dmic_num = - intel_nhlt_get_dmic_geo(&skl->pci->dev, - skl->nhlt); - } - - return 0; -} - -static int skl_machine_device_register(struct skl_dev *skl) -{ - struct snd_soc_acpi_mach *mach = skl->mach; - struct hdac_bus *bus = skl_to_bus(skl); - struct platform_device *pdev; - int ret; - - pdev = platform_device_alloc(mach->drv_name, -1); - if (pdev == NULL) { - dev_err(bus->dev, "platform device alloc failed\n"); - return -EIO; - } - - mach->mach_params.platform = dev_name(bus->dev); - mach->mach_params.codec_mask = bus->codec_mask; - - ret = platform_device_add_data(pdev, (const void *)mach, sizeof(*mach)); - if (ret) { - dev_err(bus->dev, "failed to add machine device platform data\n"); - platform_device_put(pdev); - return ret; - } - - ret = platform_device_add(pdev); - if (ret) { - dev_err(bus->dev, "failed to add machine device\n"); - platform_device_put(pdev); - return -EIO; - } - - - skl->i2s_dev = pdev; - - return 0; -} - -static void skl_machine_device_unregister(struct skl_dev *skl) -{ - if (skl->i2s_dev) - platform_device_unregister(skl->i2s_dev); -} - -static int skl_dmic_device_register(struct skl_dev *skl) -{ - struct hdac_bus *bus = skl_to_bus(skl); - struct platform_device *pdev; - int ret; - - /* SKL has one dmic port, so allocate dmic device for this */ - pdev = platform_device_alloc("dmic-codec", -1); - if (!pdev) { - dev_err(bus->dev, "failed to allocate dmic device\n"); - return -ENOMEM; - } - - ret = platform_device_add(pdev); - if (ret) { - dev_err(bus->dev, "failed to add dmic device: %d\n", ret); - platform_device_put(pdev); - return ret; - } - skl->dmic_dev = pdev; - - return 0; -} - -static void skl_dmic_device_unregister(struct skl_dev *skl) -{ - if (skl->dmic_dev) - platform_device_unregister(skl->dmic_dev); -} - -static struct skl_clk_parent_src skl_clk_src[] = { - { .clk_id = SKL_XTAL, .name = "xtal" }, - { .clk_id = SKL_CARDINAL, .name = "cardinal", .rate = 24576000 }, - { .clk_id = SKL_PLL, .name = "pll", .rate = 96000000 }, -}; - -struct skl_clk_parent_src *skl_get_parent_clk(u8 clk_id) -{ - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(skl_clk_src); i++) { - if (skl_clk_src[i].clk_id == clk_id) - return &skl_clk_src[i]; - } - - return NULL; -} - -static void init_skl_xtal_rate(int pci_id) -{ - switch (pci_id) { - case PCI_DEVICE_ID_INTEL_HDA_SKL_LP: - case PCI_DEVICE_ID_INTEL_HDA_KBL_LP: - skl_clk_src[0].rate = 24000000; - return; - - default: - skl_clk_src[0].rate = 19200000; - return; - } -} - -static int skl_clock_device_register(struct skl_dev *skl) -{ - struct platform_device_info pdevinfo = {NULL}; - struct skl_clk_pdata *clk_pdata; - - if (!skl->nhlt) - return 0; - - clk_pdata = devm_kzalloc(&skl->pci->dev, sizeof(*clk_pdata), - GFP_KERNEL); - if (!clk_pdata) - return -ENOMEM; - - init_skl_xtal_rate(skl->pci->device); - - clk_pdata->parent_clks = skl_clk_src; - clk_pdata->ssp_clks = skl_ssp_clks; - clk_pdata->num_clks = ARRAY_SIZE(skl_ssp_clks); - - /* Query NHLT to fill the rates and parent */ - skl_get_clks(skl, clk_pdata->ssp_clks); - clk_pdata->pvt_data = skl; - - /* Register Platform device */ - pdevinfo.parent = &skl->pci->dev; - pdevinfo.id = -1; - pdevinfo.name = "skl-ssp-clk"; - pdevinfo.data = clk_pdata; - pdevinfo.size_data = sizeof(*clk_pdata); - skl->clk_dev = platform_device_register_full(&pdevinfo); - return PTR_ERR_OR_ZERO(skl->clk_dev); -} - -static void skl_clock_device_unregister(struct skl_dev *skl) -{ - if (skl->clk_dev) - platform_device_unregister(skl->clk_dev); -} - -#if IS_ENABLED(CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC) - -#define IDISP_INTEL_VENDOR_ID 0x80860000 - -/* - * load the legacy codec driver - */ -static void load_codec_module(struct hda_codec *codec) -{ -#ifdef MODULE - char modalias[MODULE_NAME_LEN]; - const char *mod = NULL; - - snd_hdac_codec_modalias(&codec->core, modalias, sizeof(modalias)); - mod = modalias; - dev_dbg(&codec->core.dev, "loading %s codec module\n", mod); - request_module(mod); -#endif -} - -#endif /* CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC */ - -static struct hda_codec *skl_codec_device_init(struct hdac_bus *bus, int addr) -{ - struct hda_codec *codec; - int ret; - - codec = snd_hda_codec_device_init(to_hda_bus(bus), addr, "ehdaudio%dD%d", bus->idx, addr); - if (IS_ERR(codec)) { - dev_err(bus->dev, "device init failed for hdac device\n"); - return codec; - } - - codec->core.type = HDA_DEV_ASOC; - - ret = snd_hdac_device_register(&codec->core); - if (ret) { - dev_err(bus->dev, "failed to register hdac device\n"); - put_device(&codec->core.dev); - return ERR_PTR(ret); - } - - return codec; -} - -/* - * Probe the given codec address - */ -static int probe_codec(struct hdac_bus *bus, int addr) -{ - unsigned int cmd = (addr << 28) | (AC_NODE_ROOT << 20) | - (AC_VERB_PARAMETERS << 8) | AC_PAR_VENDOR_ID; - unsigned int res = -1; -#if IS_ENABLED(CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC) - struct skl_dev *skl = bus_to_skl(bus); - struct hdac_hda_priv *hda_codec; -#endif - struct hda_codec *codec; - - mutex_lock(&bus->cmd_mutex); - snd_hdac_bus_send_cmd(bus, cmd); - snd_hdac_bus_get_response(bus, addr, &res); - mutex_unlock(&bus->cmd_mutex); - if (res == -1) - return -EIO; - dev_dbg(bus->dev, "codec #%d probed OK: %x\n", addr, res); - -#if IS_ENABLED(CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC) - hda_codec = devm_kzalloc(&skl->pci->dev, sizeof(*hda_codec), - GFP_KERNEL); - if (!hda_codec) - return -ENOMEM; - - codec = skl_codec_device_init(bus, addr); - if (IS_ERR(codec)) - return PTR_ERR(codec); - - hda_codec->codec = codec; - hda_codec->dev_index = addr; - dev_set_drvdata(&codec->core.dev, hda_codec); - - /* use legacy bus only for HDA codecs, idisp uses ext bus */ - if ((res & 0xFFFF0000) != IDISP_INTEL_VENDOR_ID) { - codec->core.type = HDA_DEV_LEGACY; - load_codec_module(hda_codec->codec); - } - return 0; -#else - codec = skl_codec_device_init(bus, addr); - return PTR_ERR_OR_ZERO(codec); -#endif /* CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC */ -} - -/* Codec initialization */ -static void skl_codec_create(struct hdac_bus *bus) -{ - int c, max_slots; - - max_slots = HDA_MAX_CODECS; - - /* First try to probe all given codec slots */ - for (c = 0; c < max_slots; c++) { - if ((bus->codec_mask & (1 << c))) { - if (probe_codec(bus, c) < 0) { - /* - * Some BIOSen give you wrong codec addresses - * that don't exist - */ - dev_warn(bus->dev, - "Codec #%d probe error; disabling it...\n", c); - bus->codec_mask &= ~(1 << c); - /* - * More badly, accessing to a non-existing - * codec often screws up the controller bus, - * and disturbs the further communications. - * Thus if an error occurs during probing, - * better to reset the controller bus to get - * back to the sanity state. - */ - snd_hdac_bus_stop_chip(bus); - skl_init_chip(bus, true); - } - } - } -} - -static void skl_probe_work(struct work_struct *work) -{ - struct skl_dev *skl = container_of(work, struct skl_dev, probe_work); - struct hdac_bus *bus = skl_to_bus(skl); - struct hdac_ext_link *hlink; - int err; - - if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) - snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, true); - - skl_init_pci(skl); - skl_dum_set(bus); - - err = skl_init_chip(bus, true); - if (err < 0) { - dev_err(bus->dev, "Init chip failed with err: %d\n", err); - goto out_err; - } - - /* codec detection */ - if (!bus->codec_mask) - dev_info(bus->dev, "no hda codecs found!\n"); - - /* create codec instances */ - skl_codec_create(bus); - - /* register platform dai and controls */ - err = skl_platform_register(bus->dev); - if (err < 0) { - dev_err(bus->dev, "platform register failed: %d\n", err); - goto out_err; - } - - err = skl_machine_device_register(skl); - if (err < 0) { - dev_err(bus->dev, "machine register failed: %d\n", err); - goto out_err; - } - - /* - * we are done probing so decrement link counts - */ - list_for_each_entry(hlink, &bus->hlink_list, list) - snd_hdac_ext_bus_link_put(bus, hlink); - - if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) - snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, false); - - /* configure PM */ - pm_runtime_put_noidle(bus->dev); - pm_runtime_allow(bus->dev); - skl->init_done = 1; - - return; - -out_err: - if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) - snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, false); -} - -/* - * constructor - */ -static int skl_create(struct pci_dev *pci, - struct skl_dev **rskl) -{ - struct hdac_ext_bus_ops *ext_ops = NULL; - struct skl_dev *skl; - struct hdac_bus *bus; - struct hda_bus *hbus; - int err; - - *rskl = NULL; - - err = pci_enable_device(pci); - if (err < 0) - return err; - - skl = devm_kzalloc(&pci->dev, sizeof(*skl), GFP_KERNEL); - if (!skl) { - pci_disable_device(pci); - return -ENOMEM; - } - - hbus = skl_to_hbus(skl); - bus = skl_to_bus(skl); - - INIT_LIST_HEAD(&skl->ppl_list); - INIT_LIST_HEAD(&skl->bind_list); - -#if IS_ENABLED(CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC) - ext_ops = snd_soc_hdac_hda_get_ops(); -#endif - snd_hdac_ext_bus_init(bus, &pci->dev, NULL, ext_ops); - bus->use_posbuf = 1; - skl->pci = pci; - INIT_WORK(&skl->probe_work, skl_probe_work); - bus->bdl_pos_adj = 0; - - mutex_init(&hbus->prepare_mutex); - hbus->pci = pci; - hbus->mixer_assigned = -1; - hbus->modelname = "sklbus"; - - *rskl = skl; - - return 0; -} - -static int skl_first_init(struct hdac_bus *bus) -{ - struct skl_dev *skl = bus_to_skl(bus); - struct pci_dev *pci = skl->pci; - int err; - unsigned short gcap; - int cp_streams, pb_streams, start_idx; - - err = pci_request_regions(pci, "Skylake HD audio"); - if (err < 0) - return err; - - bus->addr = pci_resource_start(pci, 0); - bus->remap_addr = pci_ioremap_bar(pci, 0); - if (bus->remap_addr == NULL) { - dev_err(bus->dev, "ioremap error\n"); - return -ENXIO; - } - - snd_hdac_bus_parse_capabilities(bus); - - /* check if PPCAP exists */ - if (!bus->ppcap) { - dev_err(bus->dev, "bus ppcap not set, HDAudio or DSP not present?\n"); - return -ENODEV; - } - - if (skl_acquire_irq(bus, 0) < 0) - return -EBUSY; - - pci_set_master(pci); - synchronize_irq(bus->irq); - - gcap = snd_hdac_chip_readw(bus, GCAP); - dev_dbg(bus->dev, "chipset global capabilities = 0x%x\n", gcap); - - /* read number of streams from GCAP register */ - cp_streams = (gcap >> 8) & 0x0f; - pb_streams = (gcap >> 12) & 0x0f; - - if (!pb_streams && !cp_streams) { - dev_err(bus->dev, "no streams found in GCAP definitions?\n"); - return -EIO; - } - - bus->num_streams = cp_streams + pb_streams; - - /* allow 64bit DMA address if supported by H/W */ - if (dma_set_mask_and_coherent(bus->dev, DMA_BIT_MASK(64))) - dma_set_mask_and_coherent(bus->dev, DMA_BIT_MASK(32)); - dma_set_max_seg_size(bus->dev, UINT_MAX); - - /* initialize streams */ - snd_hdac_ext_stream_init_all - (bus, 0, cp_streams, SNDRV_PCM_STREAM_CAPTURE); - start_idx = cp_streams; - snd_hdac_ext_stream_init_all - (bus, start_idx, pb_streams, SNDRV_PCM_STREAM_PLAYBACK); - - err = snd_hdac_bus_alloc_stream_pages(bus); - if (err < 0) - return err; - - return 0; -} - -static int skl_probe(struct pci_dev *pci, - const struct pci_device_id *pci_id) -{ - struct skl_dev *skl; - struct hdac_bus *bus = NULL; - int err; - - switch (skl_pci_binding) { - case SND_SKL_PCI_BIND_AUTO: - err = snd_intel_dsp_driver_probe(pci); - if (err != SND_INTEL_DSP_DRIVER_ANY && - err != SND_INTEL_DSP_DRIVER_SST) - return -ENODEV; - break; - case SND_SKL_PCI_BIND_LEGACY: - dev_info(&pci->dev, "Module parameter forced binding with HDAudio legacy, aborting probe\n"); - return -ENODEV; - case SND_SKL_PCI_BIND_ASOC: - dev_info(&pci->dev, "Module parameter forced binding with SKL driver, bypassed detection logic\n"); - break; - default: - dev_err(&pci->dev, "invalid value for skl_pci_binding module parameter, ignored\n"); - break; - } - - /* we use ext core ops, so provide NULL for ops here */ - err = skl_create(pci, &skl); - if (err < 0) - return err; - - bus = skl_to_bus(skl); - - err = skl_first_init(bus); - if (err < 0) { - dev_err(bus->dev, "skl_first_init failed with err: %d\n", err); - goto out_free; - } - - skl->pci_id = pci->device; - - device_disable_async_suspend(bus->dev); - - skl->nhlt = intel_nhlt_init(bus->dev); - - if (skl->nhlt == NULL) { -#if !IS_ENABLED(CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC) - dev_err(bus->dev, "no nhlt info found\n"); - err = -ENODEV; - goto out_free; -#else - dev_warn(bus->dev, "no nhlt info found, continuing to try to enable HDAudio codec\n"); -#endif - } else { - - err = skl_nhlt_create_sysfs(skl); - if (err < 0) { - dev_err(bus->dev, "skl_nhlt_create_sysfs failed with err: %d\n", err); - goto out_nhlt_free; - } - - skl_nhlt_update_topology_bin(skl); - - /* create device for dsp clk */ - err = skl_clock_device_register(skl); - if (err < 0) { - dev_err(bus->dev, "skl_clock_device_register failed with err: %d\n", err); - goto out_clk_free; - } - } - - pci_set_drvdata(skl->pci, bus); - - - err = skl_find_machine(skl, (void *)pci_id->driver_data); - if (err < 0) { - dev_err(bus->dev, "skl_find_machine failed with err: %d\n", err); - goto out_nhlt_free; - } - - err = skl_init_dsp(skl); - if (err < 0) { - dev_dbg(bus->dev, "error failed to register dsp\n"); - goto out_nhlt_free; - } - skl->enable_miscbdcge = skl_enable_miscbdcge; - skl->clock_power_gating = skl_clock_power_gating; - - if (bus->mlcap) - snd_hdac_ext_bus_get_ml_capabilities(bus); - - /* create device for soc dmic */ - err = skl_dmic_device_register(skl); - if (err < 0) { - dev_err(bus->dev, "skl_dmic_device_register failed with err: %d\n", err); - goto out_dsp_free; - } - - if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) { - err = snd_hdac_i915_init(bus); - if (err < 0) - goto out_dmic_unregister; - } - schedule_work(&skl->probe_work); - - return 0; - -out_dmic_unregister: - skl_dmic_device_unregister(skl); -out_dsp_free: - skl_free_dsp(skl); -out_clk_free: - skl_clock_device_unregister(skl); -out_nhlt_free: - if (skl->nhlt) - intel_nhlt_free(skl->nhlt); -out_free: - skl_free(bus); - - return err; -} - -static void skl_shutdown(struct pci_dev *pci) -{ - struct hdac_bus *bus = pci_get_drvdata(pci); - struct hdac_stream *s; - struct hdac_ext_stream *stream; - struct skl_dev *skl; - - if (!bus) - return; - - skl = bus_to_skl(bus); - - if (!skl->init_done) - return; - - snd_hdac_stop_streams(bus); - snd_hdac_ext_bus_link_power_down_all(bus); - skl_dsp_sleep(skl->dsp); - - list_for_each_entry(s, &bus->stream_list, list) { - stream = stream_to_hdac_ext_stream(s); - snd_hdac_ext_stream_decouple(bus, stream, false); - } - - snd_hdac_bus_stop_chip(bus); -} - -static void skl_remove(struct pci_dev *pci) -{ - struct hdac_bus *bus = pci_get_drvdata(pci); - struct skl_dev *skl = bus_to_skl(bus); - - cancel_work_sync(&skl->probe_work); - - pm_runtime_get_noresume(&pci->dev); - - /* codec removal, invoke bus_device_remove */ - snd_hdac_ext_bus_device_remove(bus); - - skl_platform_unregister(&pci->dev); - skl_free_dsp(skl); - skl_machine_device_unregister(skl); - skl_dmic_device_unregister(skl); - skl_clock_device_unregister(skl); - skl_nhlt_remove_sysfs(skl); - if (skl->nhlt) - intel_nhlt_free(skl->nhlt); - skl_free(bus); -} - -/* PCI IDs */ -static const struct pci_device_id skl_ids[] = { -#if IS_ENABLED(CONFIG_SND_SOC_INTEL_SKL) - { PCI_DEVICE_DATA(INTEL, HDA_SKL_LP, &snd_soc_acpi_intel_skl_machines) }, -#endif -#if IS_ENABLED(CONFIG_SND_SOC_INTEL_APL) - { PCI_DEVICE_DATA(INTEL, HDA_APL, &snd_soc_acpi_intel_bxt_machines) }, -#endif -#if IS_ENABLED(CONFIG_SND_SOC_INTEL_KBL) - { PCI_DEVICE_DATA(INTEL, HDA_KBL_LP, &snd_soc_acpi_intel_kbl_machines) }, -#endif -#if IS_ENABLED(CONFIG_SND_SOC_INTEL_GLK) - { PCI_DEVICE_DATA(INTEL, HDA_GML, &snd_soc_acpi_intel_glk_machines) }, -#endif -#if IS_ENABLED(CONFIG_SND_SOC_INTEL_CNL) - { PCI_DEVICE_DATA(INTEL, HDA_CNL_LP, &snd_soc_acpi_intel_cnl_machines) }, -#endif -#if IS_ENABLED(CONFIG_SND_SOC_INTEL_CFL) - { PCI_DEVICE_DATA(INTEL, HDA_CNL_H, &snd_soc_acpi_intel_cnl_machines) }, -#endif -#if IS_ENABLED(CONFIG_SND_SOC_INTEL_CML_LP) - { PCI_DEVICE_DATA(INTEL, HDA_CML_LP, &snd_soc_acpi_intel_cnl_machines) }, -#endif -#if IS_ENABLED(CONFIG_SND_SOC_INTEL_CML_H) - { PCI_DEVICE_DATA(INTEL, HDA_CML_H, &snd_soc_acpi_intel_cnl_machines) }, -#endif - { 0, } -}; -MODULE_DEVICE_TABLE(pci, skl_ids); - -/* pci_driver definition */ -static struct pci_driver skl_driver = { - .name = KBUILD_MODNAME, - .id_table = skl_ids, - .probe = skl_probe, - .remove = skl_remove, - .shutdown = skl_shutdown, - .driver = { - .pm = &skl_pm, - }, -}; -module_pci_driver(skl_driver); - -MODULE_LICENSE("GPL v2"); -MODULE_DESCRIPTION("Intel Skylake ASoC HDA driver"); diff --git a/sound/soc/intel/skylake/skl.h b/sound/soc/intel/skylake/skl.h deleted file mode 100644 index f55f8b3dbdc32f..00000000000000 --- a/sound/soc/intel/skylake/skl.h +++ /dev/null @@ -1,207 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * skl.h - HD Audio skylake definitions. - * - * Copyright (C) 2015 Intel Corp - * Author: Jeeja KP - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ - -#ifndef __SOUND_SOC_SKL_H -#define __SOUND_SOC_SKL_H - -#include -#include -#include -#include -#include "skl-ssp-clk.h" -#include "skl-sst-ipc.h" - -#define SKL_SUSPEND_DELAY 2000 - -#define SKL_MAX_ASTATE_CFG 3 - -#define AZX_PCIREG_PGCTL 0x44 -#define AZX_PGCTL_LSRMD_MASK (1 << 4) -#define AZX_PGCTL_ADSPPGD BIT(2) -#define AZX_PCIREG_CGCTL 0x48 -#define AZX_CGCTL_MISCBDCGE_MASK (1 << 6) -#define AZX_CGCTL_ADSPDCGE BIT(1) -/* D0I3C Register fields */ -#define AZX_REG_VS_D0I3C_CIP 0x1 /* Command in progress */ -#define AZX_REG_VS_D0I3C_I3 0x4 /* D0i3 enable */ -#define SKL_MAX_DMACTRL_CFG 18 -#define DMA_CLK_CONTROLS 1 -#define DMA_TRANSMITION_START 2 -#define DMA_TRANSMITION_STOP 3 - -#define AZX_VS_EM2_DUM BIT(23) -#define AZX_REG_VS_EM2_L1SEN BIT(13) - -struct skl_debug; - -struct skl_astate_param { - u32 kcps; - u32 clk_src; -}; - -struct skl_astate_config { - u32 count; - struct skl_astate_param astate_table[]; -}; - -struct skl_fw_config { - struct skl_astate_config *astate_cfg; -}; - -struct skl_dev { - struct hda_bus hbus; - struct pci_dev *pci; - - unsigned int init_done:1; /* delayed init status */ - struct platform_device *dmic_dev; - struct platform_device *i2s_dev; - struct platform_device *clk_dev; - struct snd_soc_component *component; - struct snd_soc_dai_driver *dais; - - struct nhlt_acpi_table *nhlt; /* nhlt ptr */ - - struct list_head ppl_list; - struct list_head bind_list; - - const char *fw_name; - char tplg_name[64]; - unsigned short pci_id; - - int supend_active; - - struct work_struct probe_work; - - struct skl_debug *debugfs; - u8 nr_modules; - struct skl_module **modules; - bool use_tplg_pcm; - struct skl_fw_config cfg; - struct snd_soc_acpi_mach *mach; - - struct device *dev; - struct sst_dsp *dsp; - - /* boot */ - wait_queue_head_t boot_wait; - bool boot_complete; - - /* module load */ - wait_queue_head_t mod_load_wait; - bool mod_load_complete; - bool mod_load_status; - - /* IPC messaging */ - struct sst_generic_ipc ipc; - - /* callback for miscbdge */ - void (*enable_miscbdcge)(struct device *dev, bool enable); - /* Is CGCTL.MISCBDCGE disabled */ - bool miscbdcg_disabled; - - /* Populate module information */ - struct list_head uuid_list; - - /* Is firmware loaded */ - bool fw_loaded; - - /* first boot ? */ - bool is_first_boot; - - /* multi-core */ - struct skl_dsp_cores cores; - - /* library info */ - struct skl_lib_info lib_info[SKL_MAX_LIB]; - int lib_count; - - /* Callback to update D0i3C register */ - void (*update_d0i3c)(struct device *dev, bool enable); - - struct skl_d0i3_data d0i3; - - const struct skl_dsp_ops *dsp_ops; - - /* Callback to update dynamic clock and power gating registers */ - void (*clock_power_gating)(struct device *dev, bool enable); -}; - -#define skl_to_bus(s) (&(s)->hbus.core) -#define bus_to_skl(bus) container_of(bus, struct skl_dev, hbus.core) - -#define skl_to_hbus(s) (&(s)->hbus) -#define hbus_to_skl(hbus) container_of((hbus), struct skl_dev, (hbus)) - -/* to pass dai dma data */ -struct skl_dma_params { - u32 format; - u8 stream_tag; -}; - -struct skl_machine_pdata { - bool use_tplg_pcm; /* use dais and dai links from topology */ -}; - -struct skl_dsp_ops { - int id; - unsigned int num_cores; - struct skl_dsp_loader_ops (*loader_ops)(void); - int (*init)(struct device *dev, void __iomem *mmio_base, - int irq, const char *fw_name, - struct skl_dsp_loader_ops loader_ops, - struct skl_dev **skl_sst); - int (*init_fw)(struct device *dev, struct skl_dev *skl); - void (*cleanup)(struct device *dev, struct skl_dev *skl); -}; - -int skl_platform_unregister(struct device *dev); -int skl_platform_register(struct device *dev); - -int skl_nhlt_update_topology_bin(struct skl_dev *skl); -int skl_init_dsp(struct skl_dev *skl); -int skl_free_dsp(struct skl_dev *skl); -int skl_suspend_late_dsp(struct skl_dev *skl); -int skl_suspend_dsp(struct skl_dev *skl); -int skl_resume_dsp(struct skl_dev *skl); -void skl_cleanup_resources(struct skl_dev *skl); -const struct skl_dsp_ops *skl_get_dsp_ops(int pci_id); -void skl_update_d0i3c(struct device *dev, bool enable); -int skl_nhlt_create_sysfs(struct skl_dev *skl); -void skl_nhlt_remove_sysfs(struct skl_dev *skl); -void skl_get_clks(struct skl_dev *skl, struct skl_ssp_clk *ssp_clks); -struct skl_clk_parent_src *skl_get_parent_clk(u8 clk_id); -int skl_dsp_set_dma_control(struct skl_dev *skl, u32 *caps, - u32 caps_size, u32 node_id); - -struct skl_module_cfg; - -#ifdef CONFIG_DEBUG_FS -struct skl_debug *skl_debugfs_init(struct skl_dev *skl); -void skl_debugfs_exit(struct skl_dev *skl); -void skl_debug_init_module(struct skl_debug *d, - struct snd_soc_dapm_widget *w, - struct skl_module_cfg *mconfig); -#else -static inline struct skl_debug *skl_debugfs_init(struct skl_dev *skl) -{ - return NULL; -} - -static inline void skl_debugfs_exit(struct skl_dev *skl) -{} - -static inline void skl_debug_init_module(struct skl_debug *d, - struct snd_soc_dapm_widget *w, - struct skl_module_cfg *mconfig) -{} -#endif - -#endif /* __SOUND_SOC_SKL_H */ diff --git a/sound/soc/loongson/loongson_dma.c b/sound/soc/loongson/loongson_dma.c index 4fcc2868160bb9..0238f88bc674b6 100644 --- a/sound/soc/loongson/loongson_dma.c +++ b/sound/soc/loongson/loongson_dma.c @@ -95,7 +95,6 @@ static int loongson_pcm_trigger(struct snd_soc_component *component, struct device *dev = substream->pcm->card->dev; void __iomem *order_reg = prtd->dma_data->order_addr; u64 val; - int ret = 0; switch (cmd) { case SNDRV_PCM_TRIGGER_START: @@ -129,7 +128,7 @@ static int loongson_pcm_trigger(struct snd_soc_component *component, return -EINVAL; } - return ret; + return 0; } static int loongson_pcm_hw_params(struct snd_soc_component *component, @@ -230,7 +229,6 @@ static int loongson_pcm_open(struct snd_soc_component *component, struct snd_card *card = substream->pcm->card; struct loongson_runtime_data *prtd; struct loongson_dma_data *dma_data; - int ret; /* * For mysterious reasons (and despite what the manual says) @@ -252,20 +250,17 @@ static int loongson_pcm_open(struct snd_soc_component *component, prtd->dma_desc_arr = dma_alloc_coherent(card->dev, PAGE_SIZE, &prtd->dma_desc_arr_phy, GFP_KERNEL); - if (!prtd->dma_desc_arr) { - ret = -ENOMEM; + if (!prtd->dma_desc_arr) goto desc_err; - } + prtd->dma_desc_arr_size = PAGE_SIZE / sizeof(*prtd->dma_desc_arr); prtd->dma_pos_desc = dma_alloc_coherent(card->dev, sizeof(*prtd->dma_pos_desc), &prtd->dma_pos_desc_phy, GFP_KERNEL); - if (!prtd->dma_pos_desc) { - ret = -ENOMEM; + if (!prtd->dma_pos_desc) goto pos_err; - } dma_data = snd_soc_dai_get_dma_data(snd_soc_rtd_to_cpu(rtd, 0), substream); prtd->dma_data = dma_data; @@ -279,7 +274,7 @@ static int loongson_pcm_open(struct snd_soc_component *component, desc_err: kfree(prtd); - return ret; + return -ENOMEM; } static int loongson_pcm_close(struct snd_soc_component *component, diff --git a/sound/soc/mediatek/mt8188/mt8188-afe-pcm.c b/sound/soc/mediatek/mt8188/mt8188-afe-pcm.c index ccb6c1f3adc7d9..73e5c63aeec878 100644 --- a/sound/soc/mediatek/mt8188/mt8188-afe-pcm.c +++ b/sound/soc/mediatek/mt8188/mt8188-afe-pcm.c @@ -2748,6 +2748,7 @@ static bool mt8188_is_volatile_reg(struct device *dev, unsigned int reg) case AFE_ASRC12_NEW_CON9: case AFE_LRCK_CNT: case AFE_DAC_MON0: + case AFE_DAC_CON0: case AFE_DL2_CUR: case AFE_DL3_CUR: case AFE_DL6_CUR: diff --git a/sound/soc/meson/axg-fifo.c b/sound/soc/meson/axg-fifo.c index 7e6090af720b9a..75909196b7698a 100644 --- a/sound/soc/meson/axg-fifo.c +++ b/sound/soc/meson/axg-fifo.c @@ -207,25 +207,18 @@ static irqreturn_t axg_fifo_pcm_irq_block(int irq, void *dev_id) status = FIELD_GET(STATUS1_INT_STS, status); axg_fifo_ack_irq(fifo, status); - /* Use the thread to call period elapsed on nonatomic links */ - if (status & FIFO_INT_COUNT_REPEAT) - return IRQ_WAKE_THREAD; + if (status & ~FIFO_INT_COUNT_REPEAT) + dev_dbg(axg_fifo_dev(ss), "unexpected irq - STS 0x%02x\n", + status); - dev_dbg(axg_fifo_dev(ss), "unexpected irq - STS 0x%02x\n", - status); + if (status & FIFO_INT_COUNT_REPEAT) { + snd_pcm_period_elapsed(ss); + return IRQ_HANDLED; + } return IRQ_NONE; } -static irqreturn_t axg_fifo_pcm_irq_block_thread(int irq, void *dev_id) -{ - struct snd_pcm_substream *ss = dev_id; - - snd_pcm_period_elapsed(ss); - - return IRQ_HANDLED; -} - int axg_fifo_pcm_open(struct snd_soc_component *component, struct snd_pcm_substream *ss) { @@ -251,8 +244,9 @@ int axg_fifo_pcm_open(struct snd_soc_component *component, if (ret) return ret; - ret = request_threaded_irq(fifo->irq, axg_fifo_pcm_irq_block, - axg_fifo_pcm_irq_block_thread, + /* Use the threaded irq handler only with non-atomic links */ + ret = request_threaded_irq(fifo->irq, NULL, + axg_fifo_pcm_irq_block, IRQF_ONESHOT, dev_name(dev), ss); if (ret) return ret; diff --git a/sound/soc/soc-card-test.c b/sound/soc/soc-card-test.c index e4a4b101d7438d..47dfd8b1babc2a 100644 --- a/sound/soc/soc-card-test.c +++ b/sound/soc/soc-card-test.c @@ -67,62 +67,6 @@ static void test_snd_soc_card_get_kcontrol(struct kunit *test) KUNIT_EXPECT_NULL(test, kc); } -static void test_snd_soc_card_get_kcontrol_locked(struct kunit *test) -{ - struct soc_card_test_priv *priv = test->priv; - struct snd_soc_card *card = priv->card; - struct snd_kcontrol *kc, *kcw; - struct soc_mixer_control *mc; - int i, ret; - - ret = snd_soc_add_card_controls(card, test_card_controls, ARRAY_SIZE(test_card_controls)); - KUNIT_ASSERT_EQ(test, ret, 0); - - /* Look up every control */ - for (i = 0; i < ARRAY_SIZE(test_card_controls); ++i) { - down_read(&card->snd_card->controls_rwsem); - kc = snd_soc_card_get_kcontrol_locked(card, test_card_controls[i].name); - up_read(&card->snd_card->controls_rwsem); - KUNIT_EXPECT_NOT_ERR_OR_NULL_MSG(test, kc, "Failed to find '%s'\n", - test_card_controls[i].name); - if (!kc) - continue; - - /* Test that it is the correct control */ - mc = (struct soc_mixer_control *)kc->private_value; - KUNIT_EXPECT_EQ_MSG(test, mc->shift, i, "For '%s'\n", test_card_controls[i].name); - - down_write(&card->snd_card->controls_rwsem); - kcw = snd_soc_card_get_kcontrol_locked(card, test_card_controls[i].name); - up_write(&card->snd_card->controls_rwsem); - KUNIT_EXPECT_NOT_ERR_OR_NULL_MSG(test, kcw, "Failed to find '%s'\n", - test_card_controls[i].name); - - KUNIT_EXPECT_PTR_EQ(test, kc, kcw); - } - - /* Test some names that should not be found */ - down_read(&card->snd_card->controls_rwsem); - kc = snd_soc_card_get_kcontrol_locked(card, "None"); - up_read(&card->snd_card->controls_rwsem); - KUNIT_EXPECT_NULL(test, kc); - - down_read(&card->snd_card->controls_rwsem); - kc = snd_soc_card_get_kcontrol_locked(card, "Left None"); - up_read(&card->snd_card->controls_rwsem); - KUNIT_EXPECT_NULL(test, kc); - - down_read(&card->snd_card->controls_rwsem); - kc = snd_soc_card_get_kcontrol_locked(card, "Left"); - up_read(&card->snd_card->controls_rwsem); - KUNIT_EXPECT_NULL(test, kc); - - down_read(&card->snd_card->controls_rwsem); - kc = snd_soc_card_get_kcontrol_locked(card, NULL); - up_read(&card->snd_card->controls_rwsem); - KUNIT_EXPECT_NULL(test, kc); -} - static int soc_card_test_case_init(struct kunit *test) { struct soc_card_test_priv *priv; @@ -169,7 +113,6 @@ static void soc_card_test_case_exit(struct kunit *test) static struct kunit_case soc_card_test_cases[] = { KUNIT_CASE(test_snd_soc_card_get_kcontrol), - KUNIT_CASE(test_snd_soc_card_get_kcontrol_locked), {} }; diff --git a/sound/soc/soc-card.c b/sound/soc/soc-card.c index 0a3104d4ad2356..8e9546fe742812 100644 --- a/sound/soc/soc-card.c +++ b/sound/soc/soc-card.c @@ -29,16 +29,6 @@ static inline int _soc_card_ret(struct snd_soc_card *card, return ret; } -struct snd_kcontrol *snd_soc_card_get_kcontrol_locked(struct snd_soc_card *soc_card, - const char *name) -{ - if (unlikely(!name)) - return NULL; - - return snd_ctl_find_id_mixer_locked(soc_card->snd_card, name); -} -EXPORT_SYMBOL_GPL(snd_soc_card_get_kcontrol_locked); - struct snd_kcontrol *snd_soc_card_get_kcontrol(struct snd_soc_card *soc_card, const char *name) { diff --git a/sound/soc/soc-component.c b/sound/soc/soc-component.c index 42f48132191979..b3d7bb91e29497 100644 --- a/sound/soc/soc-component.c +++ b/sound/soc/soc-component.c @@ -257,18 +257,6 @@ struct snd_kcontrol *snd_soc_component_get_kcontrol(struct snd_soc_component *co } EXPORT_SYMBOL_GPL(snd_soc_component_get_kcontrol); -struct snd_kcontrol * -snd_soc_component_get_kcontrol_locked(struct snd_soc_component *component, - const char * const ctl) -{ - char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; - - soc_get_kcontrol_name(component, name, ARRAY_SIZE(name), ctl); - - return snd_soc_card_get_kcontrol_locked(component->card, name); -} -EXPORT_SYMBOL_GPL(snd_soc_component_get_kcontrol_locked); - int snd_soc_component_notify_control(struct snd_soc_component *component, const char * const ctl) { diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index 9e47053419c16e..302ca753a1f355 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -685,26 +685,6 @@ int snd_soc_pcm_dai_trigger(struct snd_pcm_substream *substream, return ret; } -int snd_soc_pcm_dai_bespoke_trigger(struct snd_pcm_substream *substream, - int cmd) -{ - struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); - struct snd_soc_dai *dai; - int i, ret; - - for_each_rtd_dais(rtd, i, dai) { - if (dai->driver->ops && - dai->driver->ops->bespoke_trigger) { - ret = dai->driver->ops->bespoke_trigger(substream, - cmd, dai); - if (ret < 0) - return soc_dai_ret(dai, ret); - } - } - - return 0; -} - void snd_soc_pcm_dai_delay(struct snd_pcm_substream *substream, snd_pcm_sframes_t *cpu_delay, snd_pcm_sframes_t *codec_delay) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 5520944ac9ddc7..baf8b81e71103d 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -49,24 +49,6 @@ static inline int _soc_pcm_ret(struct snd_soc_pcm_runtime *rtd, return ret; } -static inline void snd_soc_dpcm_stream_lock_irq(struct snd_soc_pcm_runtime *rtd, - int stream) -{ - snd_pcm_stream_lock_irq(snd_soc_dpcm_get_substream(rtd, stream)); -} - -#define snd_soc_dpcm_stream_lock_irqsave_nested(rtd, stream, flags) \ - snd_pcm_stream_lock_irqsave_nested(snd_soc_dpcm_get_substream(rtd, stream), flags) - -static inline void snd_soc_dpcm_stream_unlock_irq(struct snd_soc_pcm_runtime *rtd, - int stream) -{ - snd_pcm_stream_unlock_irq(snd_soc_dpcm_get_substream(rtd, stream)); -} - -#define snd_soc_dpcm_stream_unlock_irqrestore(rtd, stream, flags) \ - snd_pcm_stream_unlock_irqrestore(snd_soc_dpcm_get_substream(rtd, stream), flags) - #define DPCM_MAX_BE_USERS 8 static inline const char *soc_cpu_dai_name(struct snd_soc_pcm_runtime *rtd) @@ -260,14 +242,14 @@ static void dpcm_set_fe_update_state(struct snd_soc_pcm_runtime *fe, struct snd_pcm_substream *substream = snd_soc_dpcm_get_substream(fe, stream); - snd_soc_dpcm_stream_lock_irq(fe, stream); + snd_pcm_stream_lock_irq(substream); if (state == SND_SOC_DPCM_UPDATE_NO && fe->dpcm[stream].trigger_pending) { dpcm_fe_dai_do_trigger(substream, fe->dpcm[stream].trigger_pending - 1); fe->dpcm[stream].trigger_pending = 0; } fe->dpcm[stream].runtime_update = state; - snd_soc_dpcm_stream_unlock_irq(fe, stream); + snd_pcm_stream_unlock_irq(substream); } static void dpcm_set_be_update_state(struct snd_soc_pcm_runtime *be, @@ -1272,10 +1254,10 @@ static int dpcm_be_connect(struct snd_soc_pcm_runtime *fe, dpcm->be = be; dpcm->fe = fe; dpcm->state = SND_SOC_DPCM_LINK_STATE_NEW; - snd_soc_dpcm_stream_lock_irq(fe, stream); + snd_pcm_stream_lock_irq(fe_substream); list_add(&dpcm->list_be, &fe->dpcm[stream].be_clients); list_add(&dpcm->list_fe, &be->dpcm[stream].fe_clients); - snd_soc_dpcm_stream_unlock_irq(fe, stream); + snd_pcm_stream_unlock_irq(fe_substream); dev_dbg(fe->dev, "connected new DPCM %s path %s %s %s\n", snd_pcm_direction_name(stream), fe->dai_link->name, @@ -1320,11 +1302,12 @@ static void dpcm_be_reparent(struct snd_soc_pcm_runtime *fe, void dpcm_be_disconnect(struct snd_soc_pcm_runtime *fe, int stream) { struct snd_soc_dpcm *dpcm, *d; + struct snd_pcm_substream *substream = snd_soc_dpcm_get_substream(fe, stream); LIST_HEAD(deleted_dpcms); snd_soc_dpcm_mutex_assert_held(fe); - snd_soc_dpcm_stream_lock_irq(fe, stream); + snd_pcm_stream_lock_irq(substream); for_each_dpcm_be_safe(fe, stream, dpcm, d) { dev_dbg(fe->dev, "ASoC: BE %s disconnect check for %s\n", snd_pcm_direction_name(stream), @@ -1343,7 +1326,7 @@ void dpcm_be_disconnect(struct snd_soc_pcm_runtime *fe, int stream) list_del(&dpcm->list_be); list_move(&dpcm->list_fe, &deleted_dpcms); } - snd_soc_dpcm_stream_unlock_irq(fe, stream); + snd_pcm_stream_unlock_irq(substream); while (!list_empty(&deleted_dpcms)) { dpcm = list_first_entry(&deleted_dpcms, struct snd_soc_dpcm, @@ -2155,7 +2138,7 @@ int dpcm_be_dai_trigger(struct snd_soc_pcm_runtime *fe, int stream, be = dpcm->be; be_substream = snd_soc_dpcm_get_substream(be, stream); - snd_soc_dpcm_stream_lock_irqsave_nested(be, stream, flags); + snd_pcm_stream_lock_irqsave_nested(be_substream, flags); /* is this op for this BE ? */ if (!snd_soc_dpcm_be_can_update(fe, be, stream)) @@ -2302,7 +2285,7 @@ int dpcm_be_dai_trigger(struct snd_soc_pcm_runtime *fe, int stream, break; } next: - snd_soc_dpcm_stream_unlock_irqrestore(be, stream, flags); + snd_pcm_stream_unlock_irqrestore(be_substream, flags); if (ret) break; } @@ -2388,14 +2371,6 @@ static int dpcm_fe_dai_do_trigger(struct snd_pcm_substream *substream, int cmd) break; } break; - case SND_SOC_DPCM_TRIGGER_BESPOKE: - /* bespoke trigger() - handles both FE and BEs */ - - dev_dbg(fe->dev, "ASoC: bespoke trigger FE %s cmd %d\n", - fe->dai_link->name, cmd); - - ret = snd_soc_pcm_dai_bespoke_trigger(substream, cmd); - break; default: dev_err(fe->dev, "ASoC: invalid trigger cmd %d for %s\n", cmd, fe->dai_link->name); @@ -2525,26 +2500,12 @@ static int dpcm_fe_dai_prepare(struct snd_pcm_substream *substream) static int dpcm_run_update_shutdown(struct snd_soc_pcm_runtime *fe, int stream) { - struct snd_pcm_substream *substream = - snd_soc_dpcm_get_substream(fe, stream); - enum snd_soc_dpcm_trigger trigger = fe->dai_link->trigger[stream]; int err; dev_dbg(fe->dev, "ASoC: runtime %s close on FE %s\n", snd_pcm_direction_name(stream), fe->dai_link->name); - if (trigger == SND_SOC_DPCM_TRIGGER_BESPOKE) { - /* call bespoke trigger - FE takes care of all BE triggers */ - dev_dbg(fe->dev, "ASoC: bespoke trigger FE %s cmd stop\n", - fe->dai_link->name); - - err = snd_soc_pcm_dai_bespoke_trigger(substream, SNDRV_PCM_TRIGGER_STOP); - } else { - dev_dbg(fe->dev, "ASoC: trigger FE %s cmd stop\n", - fe->dai_link->name); - - err = dpcm_be_dai_trigger(fe, stream, SNDRV_PCM_TRIGGER_STOP); - } + err = dpcm_be_dai_trigger(fe, stream, SNDRV_PCM_TRIGGER_STOP); dpcm_be_dai_hw_free(fe, stream); @@ -2558,10 +2519,7 @@ static int dpcm_run_update_shutdown(struct snd_soc_pcm_runtime *fe, int stream) static int dpcm_run_update_startup(struct snd_soc_pcm_runtime *fe, int stream) { - struct snd_pcm_substream *substream = - snd_soc_dpcm_get_substream(fe, stream); struct snd_soc_dpcm *dpcm; - enum snd_soc_dpcm_trigger trigger = fe->dai_link->trigger[stream]; int ret = 0; dev_dbg(fe->dev, "ASoC: runtime %s open on FE %s\n", @@ -2605,23 +2563,9 @@ static int dpcm_run_update_startup(struct snd_soc_pcm_runtime *fe, int stream) fe->dpcm[stream].state == SND_SOC_DPCM_STATE_STOP) return 0; - if (trigger == SND_SOC_DPCM_TRIGGER_BESPOKE) { - /* call trigger on the frontend - FE takes care of all BE triggers */ - dev_dbg(fe->dev, "ASoC: bespoke trigger FE %s cmd start\n", - fe->dai_link->name); - - ret = snd_soc_pcm_dai_bespoke_trigger(substream, SNDRV_PCM_TRIGGER_START); - if (ret < 0) - goto hw_free; - } else { - dev_dbg(fe->dev, "ASoC: trigger FE %s cmd start\n", - fe->dai_link->name); - - ret = dpcm_be_dai_trigger(fe, stream, - SNDRV_PCM_TRIGGER_START); - if (ret < 0) - goto hw_free; - } + ret = dpcm_be_dai_trigger(fe, stream, SNDRV_PCM_TRIGGER_START); + if (ret < 0) + goto hw_free; return 0; diff --git a/sound/soc/sof/amd/acp.c b/sound/soc/sof/amd/acp.c index e508ce1a3576da..d579c3849392c1 100644 --- a/sound/soc/sof/amd/acp.c +++ b/sound/soc/sof/amd/acp.c @@ -437,6 +437,7 @@ static irqreturn_t acp_irq_handler(int irq, void *dev_id) if (val & ACP_ERROR_IRQ_MASK) { snd_sof_dsp_write(sdev, ACP_DSP_BAR, desc->ext_intr_stat, ACP_ERROR_IRQ_MASK); snd_sof_dsp_write(sdev, ACP_DSP_BAR, desc->acp_sw0_i2s_err_reason, 0); + /* ACP_SW1_I2S_ERROR_REASON is newly added register from rmb platform onwards */ if (adata->pci_rev >= ACP_RMB_PCI_ID) snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP_SW1_I2S_ERROR_REASON, 0); snd_sof_dsp_write(sdev, ACP_DSP_BAR, desc->acp_error_stat, 0); diff --git a/sound/soc/sof/mediatek/mt8195/mt8195.c b/sound/soc/sof/mediatek/mt8195/mt8195.c index 1c6e035fd313f7..82d221f53a461c 100644 --- a/sound/soc/sof/mediatek/mt8195/mt8195.c +++ b/sound/soc/sof/mediatek/mt8195/mt8195.c @@ -574,6 +574,9 @@ static struct snd_sof_of_mach sof_mt8195_machs[] = { { .compatible = "google,tomato", .sof_tplg_filename = "sof-mt8195-mt6359-rt1019-rt5682.tplg" + }, { + .compatible = "google,dojo", + .sof_tplg_filename = "sof-mt8195-mt6359-max98390-rt5682.tplg" }, { .compatible = "mediatek,mt8195", .sof_tplg_filename = "sof-mt8195.tplg" diff --git a/sound/soc/sof/sof-audio.h b/sound/soc/sof/sof-audio.h index b9b8b64768b979..01b819dd849841 100644 --- a/sound/soc/sof/sof-audio.h +++ b/sound/soc/sof/sof-audio.h @@ -347,12 +347,14 @@ struct snd_sof_pcm_stream { /* ALSA SOF PCM device */ struct snd_sof_pcm { struct snd_soc_component *scomp; - struct snd_soc_tplg_pcm pcm; struct snd_sof_pcm_stream stream[2]; struct list_head list; /* list in sdev pcm list */ struct snd_pcm_hw_params params[2]; bool prepared[2]; /* PCM_PARAMS set successfully */ bool pending_stop[2]; /* only used if (!pcm_ops->platform_stop_during_hw_free) */ + + /* Must be last - ends in a flex-array member. */ + struct snd_soc_tplg_pcm pcm; }; struct snd_sof_led_control { diff --git a/sound/sparc/amd7930.c b/sound/sparc/amd7930.c index 0fea04acc3eaa5..9bdf3db51d6293 100644 --- a/sound/sparc/amd7930.c +++ b/sound/sparc/amd7930.c @@ -935,8 +935,8 @@ static int snd_amd7930_create(struct snd_card *card, amd->regs = of_ioremap(&op->resource[0], 0, resource_size(&op->resource[0]), "amd7930"); if (!amd->regs) { - snd_printk(KERN_ERR - "amd7930-%d: Unable to map chip registers.\n", dev); + dev_err(card->dev, + "amd7930-%d: Unable to map chip registers.\n", dev); kfree(amd); return -EIO; } @@ -945,8 +945,8 @@ static int snd_amd7930_create(struct snd_card *card, if (request_irq(irq, snd_amd7930_interrupt, IRQF_SHARED, "amd7930", amd)) { - snd_printk(KERN_ERR "amd7930-%d: Unable to grab IRQ %d\n", - dev, irq); + dev_err(card->dev, "amd7930-%d: Unable to grab IRQ %d\n", + dev, irq); snd_amd7930_free(amd); return -EBUSY; } diff --git a/sound/sparc/cs4231.c b/sound/sparc/cs4231.c index c2ad3fa2f25a9d..a1339f9ef12a6a 100644 --- a/sound/sparc/cs4231.c +++ b/sound/sparc/cs4231.c @@ -292,9 +292,9 @@ static void snd_cs4231_dout(struct snd_cs4231 *chip, unsigned char reg, snd_cs4231_ready(chip); #ifdef CONFIG_SND_DEBUG if (__cs4231_readb(chip, CS4231U(chip, REGSEL)) & CS4231_INIT) - snd_printdd("out: auto calibration time out - reg = 0x%x, " - "value = 0x%x\n", - reg, value); + dev_dbg(chip->card->dev, + "out: auto calibration time out - reg = 0x%x, value = 0x%x\n", + reg, value); #endif __cs4231_writeb(chip, chip->mce_bit | reg, CS4231U(chip, REGSEL)); wmb(); @@ -325,8 +325,9 @@ static unsigned char snd_cs4231_in(struct snd_cs4231 *chip, unsigned char reg) snd_cs4231_ready(chip); #ifdef CONFIG_SND_DEBUG if (__cs4231_readb(chip, CS4231U(chip, REGSEL)) & CS4231_INIT) - snd_printdd("in: auto calibration time out - reg = 0x%x\n", - reg); + dev_dbg(chip->card->dev, + "in: auto calibration time out - reg = 0x%x\n", + reg); #endif __cs4231_writeb(chip, chip->mce_bit | reg, CS4231U(chip, REGSEL)); mb(); @@ -363,14 +364,15 @@ static void snd_cs4231_mce_up(struct snd_cs4231 *chip) snd_cs4231_ready(chip); #ifdef CONFIG_SND_DEBUG if (__cs4231_readb(chip, CS4231U(chip, REGSEL)) & CS4231_INIT) - snd_printdd("mce_up - auto calibration time out (0)\n"); + dev_dbg(chip->card->dev, + "mce_up - auto calibration time out (0)\n"); #endif chip->mce_bit |= CS4231_MCE; timeout = __cs4231_readb(chip, CS4231U(chip, REGSEL)); if (timeout == 0x80) - snd_printdd("mce_up [%p]: serious init problem - " - "codec still busy\n", - chip->port); + dev_dbg(chip->card->dev, + "mce_up [%p]: serious init problem - codec still busy\n", + chip->port); if (!(timeout & CS4231_MCE)) __cs4231_writeb(chip, chip->mce_bit | (timeout & 0x1f), CS4231U(chip, REGSEL)); @@ -386,16 +388,18 @@ static void snd_cs4231_mce_down(struct snd_cs4231 *chip) spin_lock_irqsave(&chip->lock, flags); #ifdef CONFIG_SND_DEBUG if (__cs4231_readb(chip, CS4231U(chip, REGSEL)) & CS4231_INIT) - snd_printdd("mce_down [%p] - auto calibration time out (0)\n", - CS4231U(chip, REGSEL)); + dev_dbg(chip->card->dev, + "mce_down [%p] - auto calibration time out (0)\n", + CS4231U(chip, REGSEL)); #endif chip->mce_bit &= ~CS4231_MCE; reg = __cs4231_readb(chip, CS4231U(chip, REGSEL)); __cs4231_writeb(chip, chip->mce_bit | (reg & 0x1f), CS4231U(chip, REGSEL)); if (reg == 0x80) - snd_printdd("mce_down [%p]: serious init problem " - "- codec still busy\n", chip->port); + dev_dbg(chip->card->dev, + "mce_down [%p]: serious init problem - codec still busy\n", + chip->port); if ((reg & CS4231_MCE) == 0) { spin_unlock_irqrestore(&chip->lock, flags); return; @@ -415,8 +419,8 @@ static void snd_cs4231_mce_down(struct snd_cs4231 *chip) spin_unlock_irqrestore(&chip->lock, flags); if (reg) - snd_printk(KERN_ERR - "mce_down - auto calibration time out (2)\n"); + dev_err(chip->card->dev, + "mce_down - auto calibration time out (2)\n"); } static void snd_cs4231_advance_dma(struct cs4231_dma_control *dma_cont, @@ -710,7 +714,7 @@ static void snd_cs4231_init(struct snd_cs4231 *chip) snd_cs4231_mce_down(chip); #ifdef SNDRV_DEBUG_MCE - snd_printdd("init: (1)\n"); + pr_debug("init: (1)\n"); #endif snd_cs4231_mce_up(chip); spin_lock_irqsave(&chip->lock, flags); @@ -725,7 +729,7 @@ static void snd_cs4231_init(struct snd_cs4231 *chip) snd_cs4231_mce_down(chip); #ifdef SNDRV_DEBUG_MCE - snd_printdd("init: (2)\n"); + pr_debug("init: (2)\n"); #endif snd_cs4231_mce_up(chip); @@ -736,8 +740,8 @@ static void snd_cs4231_init(struct snd_cs4231 *chip) snd_cs4231_mce_down(chip); #ifdef SNDRV_DEBUG_MCE - snd_printdd("init: (3) - afei = 0x%x\n", - chip->image[CS4231_ALT_FEATURE_1]); + pr_debug("init: (3) - afei = 0x%x\n", + chip->image[CS4231_ALT_FEATURE_1]); #endif spin_lock_irqsave(&chip->lock, flags); @@ -753,7 +757,7 @@ static void snd_cs4231_init(struct snd_cs4231 *chip) snd_cs4231_mce_down(chip); #ifdef SNDRV_DEBUG_MCE - snd_printdd("init: (4)\n"); + pr_debug("init: (4)\n"); #endif snd_cs4231_mce_up(chip); @@ -763,7 +767,7 @@ static void snd_cs4231_init(struct snd_cs4231 *chip) snd_cs4231_mce_down(chip); #ifdef SNDRV_DEBUG_MCE - snd_printdd("init: (5)\n"); + pr_debug("init: (5)\n"); #endif } @@ -1038,7 +1042,8 @@ static int snd_cs4231_probe(struct snd_cs4231 *chip) break; /* this is valid value */ } } - snd_printdd("cs4231: port = %p, id = 0x%x\n", chip->port, id); + dev_dbg(chip->card->dev, + "cs4231: port = %p, id = 0x%x\n", chip->port, id); if (id != 0x0a) return -ENODEV; /* no valid device found */ @@ -1794,7 +1799,8 @@ static int snd_cs4231_sbus_create(struct snd_card *card, chip->port = of_ioremap(&op->resource[0], 0, chip->regs_size, "cs4231"); if (!chip->port) { - snd_printdd("cs4231-%d: Unable to map chip registers.\n", dev); + dev_dbg(chip->card->dev, + "cs4231-%d: Unable to map chip registers.\n", dev); return -EIO; } @@ -1815,8 +1821,9 @@ static int snd_cs4231_sbus_create(struct snd_card *card, if (request_irq(op->archdata.irqs[0], snd_cs4231_sbus_interrupt, IRQF_SHARED, "cs4231", chip)) { - snd_printdd("cs4231-%d: Unable to grab SBUS IRQ %d\n", - dev, op->archdata.irqs[0]); + dev_dbg(chip->card->dev, + "cs4231-%d: Unable to grab SBUS IRQ %d\n", + dev, op->archdata.irqs[0]); snd_cs4231_sbus_free(chip); return -EBUSY; } @@ -1986,32 +1993,37 @@ static int snd_cs4231_ebus_create(struct snd_card *card, if (!chip->port || !chip->p_dma.ebus_info.regs || !chip->c_dma.ebus_info.regs) { snd_cs4231_ebus_free(chip); - snd_printdd("cs4231-%d: Unable to map chip registers.\n", dev); + dev_dbg(chip->card->dev, + "cs4231-%d: Unable to map chip registers.\n", dev); return -EIO; } if (ebus_dma_register(&chip->c_dma.ebus_info)) { snd_cs4231_ebus_free(chip); - snd_printdd("cs4231-%d: Unable to register EBUS capture DMA\n", - dev); + dev_dbg(chip->card->dev, + "cs4231-%d: Unable to register EBUS capture DMA\n", + dev); return -EBUSY; } if (ebus_dma_irq_enable(&chip->c_dma.ebus_info, 1)) { snd_cs4231_ebus_free(chip); - snd_printdd("cs4231-%d: Unable to enable EBUS capture IRQ\n", - dev); + dev_dbg(chip->card->dev, + "cs4231-%d: Unable to enable EBUS capture IRQ\n", + dev); return -EBUSY; } if (ebus_dma_register(&chip->p_dma.ebus_info)) { snd_cs4231_ebus_free(chip); - snd_printdd("cs4231-%d: Unable to register EBUS play DMA\n", - dev); + dev_dbg(chip->card->dev, + "cs4231-%d: Unable to register EBUS play DMA\n", + dev); return -EBUSY; } if (ebus_dma_irq_enable(&chip->p_dma.ebus_info, 1)) { snd_cs4231_ebus_free(chip); - snd_printdd("cs4231-%d: Unable to enable EBUS play IRQ\n", dev); + dev_dbg(chip->card->dev, + "cs4231-%d: Unable to enable EBUS play IRQ\n", dev); return -EBUSY; } diff --git a/sound/synth/emux/emux_hwdep.c b/sound/synth/emux/emux_hwdep.c index fd8f978cde1c6c..9e98c4c73fd1e2 100644 --- a/sound/synth/emux/emux_hwdep.c +++ b/sound/synth/emux/emux_hwdep.c @@ -26,12 +26,14 @@ snd_emux_hwdep_load_patch(struct snd_emux *emu, void __user *arg) return -EFAULT; if (patch.key == GUS_PATCH) - return snd_soundfont_load_guspatch(emu->sflist, arg, + return snd_soundfont_load_guspatch(emu->card, emu->sflist, arg, patch.len + sizeof(patch)); if (patch.type >= SNDRV_SFNT_LOAD_INFO && patch.type <= SNDRV_SFNT_PROBE_DATA) { - err = snd_soundfont_load(emu->sflist, arg, patch.len + sizeof(patch), TMP_CLIENT_ID); + err = snd_soundfont_load(emu->card, emu->sflist, arg, + patch.len + sizeof(patch), + TMP_CLIENT_ID); if (err < 0) return err; } else { diff --git a/sound/synth/emux/emux_oss.c b/sound/synth/emux/emux_oss.c index 04df46b269d375..5f98d5201ba25d 100644 --- a/sound/synth/emux/emux_oss.c +++ b/sound/synth/emux/emux_oss.c @@ -115,7 +115,7 @@ snd_emux_open_seq_oss(struct snd_seq_oss_arg *arg, void *closure) p = snd_emux_create_port(emu, tmpname, 32, 1, &callback); if (p == NULL) { - snd_printk(KERN_ERR "can't create port\n"); + dev_err(emu->card->dev, "can't create port\n"); snd_emux_dec_count(emu); return -ENOMEM; } @@ -205,7 +205,7 @@ snd_emux_load_patch_seq_oss(struct snd_seq_oss_arg *arg, int format, return -ENXIO; if (format == GUS_PATCH) - rc = snd_soundfont_load_guspatch(emu->sflist, buf, count); + rc = snd_soundfont_load_guspatch(emu->card, emu->sflist, buf, count); else if (format == SNDRV_OSS_SOUNDFONT_PATCH) { struct soundfont_patch_info patch; if (count < (int)sizeof(patch)) @@ -214,10 +214,13 @@ snd_emux_load_patch_seq_oss(struct snd_seq_oss_arg *arg, int format, return -EFAULT; if (patch.type >= SNDRV_SFNT_LOAD_INFO && patch.type <= SNDRV_SFNT_PROBE_DATA) - rc = snd_soundfont_load(emu->sflist, buf, count, SF_CLIENT_NO(p->chset.port)); + rc = snd_soundfont_load(emu->card, emu->sflist, buf, + count, + SF_CLIENT_NO(p->chset.port)); else { if (emu->ops.load_fx) - rc = emu->ops.load_fx(emu, patch.type, patch.optarg, buf, count); + rc = emu->ops.load_fx(emu, patch.type, + patch.optarg, buf, count); else rc = -EINVAL; } diff --git a/sound/synth/emux/emux_seq.c b/sound/synth/emux/emux_seq.c index 1adaa75df2f6a4..9daced0e6c59d9 100644 --- a/sound/synth/emux/emux_seq.c +++ b/sound/synth/emux/emux_seq.c @@ -61,16 +61,17 @@ snd_emux_init_seq(struct snd_emux *emu, struct snd_card *card, int index) emu->client = snd_seq_create_kernel_client(card, index, "%s WaveTable", emu->name); if (emu->client < 0) { - snd_printk(KERN_ERR "can't create client\n"); + dev_err(card->dev, "can't create client\n"); return -ENODEV; } if (emu->num_ports <= 0) { - snd_printk(KERN_WARNING "seqports must be greater than zero\n"); + dev_warn(card->dev, "seqports must be greater than zero\n"); emu->num_ports = 1; } else if (emu->num_ports > SNDRV_EMUX_MAX_PORTS) { - snd_printk(KERN_WARNING "too many ports. " - "limited max. ports %d\n", SNDRV_EMUX_MAX_PORTS); + dev_warn(card->dev, + "too many ports. limited max. ports %d\n", + SNDRV_EMUX_MAX_PORTS); emu->num_ports = SNDRV_EMUX_MAX_PORTS; } @@ -87,7 +88,7 @@ snd_emux_init_seq(struct snd_emux *emu, struct snd_card *card, int index) p = snd_emux_create_port(emu, tmpname, MIDI_CHANNELS, 0, &pinfo); if (!p) { - snd_printk(KERN_ERR "can't create port\n"); + dev_err(card->dev, "can't create port\n"); return -ENOMEM; } @@ -376,12 +377,10 @@ int snd_emux_init_virmidi(struct snd_emux *emu, struct snd_card *card) goto __error; } emu->vmidi[i] = rmidi; - /* snd_printk(KERN_DEBUG "virmidi %d ok\n", i); */ } return 0; __error: - /* snd_printk(KERN_DEBUG "error init..\n"); */ snd_emux_delete_virmidi(emu); return -ENOMEM; } diff --git a/sound/synth/emux/emux_synth.c b/sound/synth/emux/emux_synth.c index 075358a533a0ea..02e2c69d7f18e3 100644 --- a/sound/synth/emux/emux_synth.c +++ b/sound/synth/emux/emux_synth.c @@ -942,9 +942,9 @@ void snd_emux_lock_voice(struct snd_emux *emu, int voice) if (emu->voices[voice].state == SNDRV_EMUX_ST_OFF) emu->voices[voice].state = SNDRV_EMUX_ST_LOCKED; else - snd_printk(KERN_WARNING - "invalid voice for lock %d (state = %x)\n", - voice, emu->voices[voice].state); + dev_warn(emu->card->dev, + "invalid voice for lock %d (state = %x)\n", + voice, emu->voices[voice].state); spin_unlock_irqrestore(&emu->voice_lock, flags); } @@ -960,9 +960,9 @@ void snd_emux_unlock_voice(struct snd_emux *emu, int voice) if (emu->voices[voice].state == SNDRV_EMUX_ST_LOCKED) emu->voices[voice].state = SNDRV_EMUX_ST_OFF; else - snd_printk(KERN_WARNING - "invalid voice for unlock %d (state = %x)\n", - voice, emu->voices[voice].state); + dev_warn(emu->card->dev, + "invalid voice for unlock %d (state = %x)\n", + voice, emu->voices[voice].state); spin_unlock_irqrestore(&emu->voice_lock, flags); } diff --git a/sound/synth/emux/soundfont.c b/sound/synth/emux/soundfont.c index 2373ed580bf8ce..b38a4e231790fe 100644 --- a/sound/synth/emux/soundfont.c +++ b/sound/synth/emux/soundfont.c @@ -38,7 +38,8 @@ static struct snd_sf_sample *sf_sample_new(struct snd_sf_list *sflist, static void sf_sample_delete(struct snd_sf_list *sflist, struct snd_soundfont *sf, struct snd_sf_sample *sp); static int load_map(struct snd_sf_list *sflist, const void __user *data, int count); -static int load_info(struct snd_sf_list *sflist, const void __user *data, long count); +static int load_info(struct snd_card *card, struct snd_sf_list *sflist, + const void __user *data, long count); static int remove_info(struct snd_sf_list *sflist, struct snd_soundfont *sf, int bank, int instr); static void init_voice_info(struct soundfont_voice_info *avp); @@ -113,7 +114,8 @@ snd_soundfont_close_check(struct snd_sf_list *sflist, int client) * it wants to do with it. */ int -snd_soundfont_load(struct snd_sf_list *sflist, const void __user *data, +snd_soundfont_load(struct snd_card *card, + struct snd_sf_list *sflist, const void __user *data, long count, int client) { struct soundfont_patch_info patch; @@ -121,7 +123,7 @@ snd_soundfont_load(struct snd_sf_list *sflist, const void __user *data, int rc; if (count < (long)sizeof(patch)) { - snd_printk(KERN_ERR "patch record too small %ld\n", count); + dev_err(card->dev, "patch record too small %ld\n", count); return -EINVAL; } if (copy_from_user(&patch, data, sizeof(patch))) @@ -131,16 +133,16 @@ snd_soundfont_load(struct snd_sf_list *sflist, const void __user *data, data += sizeof(patch); if (patch.key != SNDRV_OSS_SOUNDFONT_PATCH) { - snd_printk(KERN_ERR "The wrong kind of patch %x\n", patch.key); + dev_err(card->dev, "The wrong kind of patch %x\n", patch.key); return -EINVAL; } if (count < patch.len) { - snd_printk(KERN_ERR "Patch too short %ld, need %d\n", - count, patch.len); + dev_err(card->dev, "Patch too short %ld, need %d\n", + count, patch.len); return -EINVAL; } if (patch.len < 0) { - snd_printk(KERN_ERR "poor length %d\n", patch.len); + dev_err(card->dev, "poor length %d\n", patch.len); return -EINVAL; } @@ -164,7 +166,7 @@ snd_soundfont_load(struct snd_sf_list *sflist, const void __user *data, rc = -EINVAL; switch (patch.type) { case SNDRV_SFNT_LOAD_INFO: - rc = load_info(sflist, data, count); + rc = load_info(card, sflist, data, count); break; case SNDRV_SFNT_LOAD_DATA: rc = load_data(sflist, data, count); @@ -184,8 +186,8 @@ snd_soundfont_load(struct snd_sf_list *sflist, const void __user *data, case SNDRV_SFNT_REMOVE_INFO: /* patch must be opened */ if (!sflist->currsf) { - snd_printk(KERN_ERR "soundfont: remove_info: " - "patch not opened\n"); + dev_err(card->dev, + "soundfont: remove_info: patch not opened\n"); rc = -EINVAL; } else { int bank, instr; @@ -509,7 +511,8 @@ remove_info(struct snd_sf_list *sflist, struct snd_soundfont *sf, * open soundfont. */ static int -load_info(struct snd_sf_list *sflist, const void __user *data, long count) +load_info(struct snd_card *card, + struct snd_sf_list *sflist, const void __user *data, long count) { struct snd_soundfont *sf; struct snd_sf_zone *zone; @@ -525,7 +528,7 @@ load_info(struct snd_sf_list *sflist, const void __user *data, long count) return -EINVAL; if (count < (long)sizeof(hdr)) { - printk(KERN_ERR "Soundfont error: invalid patch zone length\n"); + dev_err(card->dev, "Soundfont error: invalid patch zone length\n"); return -EINVAL; } if (copy_from_user((char*)&hdr, data, sizeof(hdr))) @@ -535,15 +538,15 @@ load_info(struct snd_sf_list *sflist, const void __user *data, long count) count -= sizeof(hdr); if (hdr.nvoices <= 0 || hdr.nvoices >= 100) { - printk(KERN_ERR "Soundfont error: Illegal voice number %d\n", - hdr.nvoices); + dev_err(card->dev, "Soundfont error: Illegal voice number %d\n", + hdr.nvoices); return -EINVAL; } if (count < (long)sizeof(struct soundfont_voice_info) * hdr.nvoices) { - printk(KERN_ERR "Soundfont Error: " - "patch length(%ld) is smaller than nvoices(%d)\n", - count, hdr.nvoices); + dev_err(card->dev, + "Soundfont Error: patch length(%ld) is smaller than nvoices(%d)\n", + count, hdr.nvoices); return -EINVAL; } @@ -974,7 +977,8 @@ int snd_sf_vol_table[128] = { /* load GUS patch */ static int -load_guspatch(struct snd_sf_list *sflist, const char __user *data, long count) +load_guspatch(struct snd_card *card, + struct snd_sf_list *sflist, const char __user *data, long count) { struct patch_info patch; struct snd_soundfont *sf; @@ -984,7 +988,7 @@ load_guspatch(struct snd_sf_list *sflist, const char __user *data, long count) int rc; if (count < (long)sizeof(patch)) { - snd_printk(KERN_ERR "patch record too small %ld\n", count); + dev_err(card->dev, "patch record too small %ld\n", count); return -EINVAL; } if (copy_from_user(&patch, data, sizeof(patch))) @@ -1076,10 +1080,10 @@ load_guspatch(struct snd_sf_list *sflist, const char __user *data, long count) /* panning position; -128 - 127 => 0-127 */ zone->v.pan = (patch.panning + 128) / 2; #if 0 - snd_printk(KERN_DEBUG - "gus: basefrq=%d (ofs=%d) root=%d,tune=%d, range:%d-%d\n", - (int)patch.base_freq, zone->v.rate_offset, - zone->v.root, zone->v.tune, zone->v.low, zone->v.high); + pr_debug( + "gus: basefrq=%d (ofs=%d) root=%d,tune=%d, range:%d-%d\n", + (int)patch.base_freq, zone->v.rate_offset, + zone->v.root, zone->v.tune, zone->v.low, zone->v.high); #endif /* detuning is ignored */ @@ -1111,12 +1115,12 @@ load_guspatch(struct snd_sf_list *sflist, const char __user *data, long count) zone->v.parm.volrelease = 0x8000 | snd_sf_calc_parm_decay(release); zone->v.attenuation = calc_gus_attenuation(patch.env_offset[0]); #if 0 - snd_printk(KERN_DEBUG - "gus: atkhld=%x, dcysus=%x, volrel=%x, att=%d\n", - zone->v.parm.volatkhld, - zone->v.parm.voldcysus, - zone->v.parm.volrelease, - zone->v.attenuation); + dev_dbg(card->dev, + "gus: atkhld=%x, dcysus=%x, volrel=%x, att=%d\n", + zone->v.parm.volatkhld, + zone->v.parm.voldcysus, + zone->v.parm.volrelease, + zone->v.attenuation); #endif } @@ -1160,12 +1164,13 @@ load_guspatch(struct snd_sf_list *sflist, const char __user *data, long count) /* load GUS patch */ int -snd_soundfont_load_guspatch(struct snd_sf_list *sflist, const char __user *data, +snd_soundfont_load_guspatch(struct snd_card *card, + struct snd_sf_list *sflist, const char __user *data, long count) { int rc; lock_preset(sflist); - rc = load_guspatch(sflist, data, count); + rc = load_guspatch(card, sflist, data, count); unlock_preset(sflist); return rc; } diff --git a/sound/usb/caiaq/audio.c b/sound/usb/caiaq/audio.c index 4981753652a7fe..772c0ecb707738 100644 --- a/sound/usb/caiaq/audio.c +++ b/sound/usb/caiaq/audio.c @@ -174,17 +174,9 @@ static int snd_usb_caiaq_pcm_hw_free(struct snd_pcm_substream *sub) return 0; } -/* this should probably go upstream */ -#if SNDRV_PCM_RATE_5512 != 1 << 0 || SNDRV_PCM_RATE_192000 != 1 << 12 -#error "Change this table" -#endif - -static const unsigned int rates[] = { 5512, 8000, 11025, 16000, 22050, 32000, 44100, - 48000, 64000, 88200, 96000, 176400, 192000 }; - static int snd_usb_caiaq_pcm_prepare(struct snd_pcm_substream *substream) { - int bytes_per_sample, bpp, ret, i; + int bytes_per_sample, bpp, ret; int index = substream->number; struct snd_usb_caiaqdev *cdev = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; @@ -233,10 +225,7 @@ static int snd_usb_caiaq_pcm_prepare(struct snd_pcm_substream *substream) /* the first client that opens a stream defines the sample rate * setting for all subsequent calls, until the last client closed. */ - for (i=0; i < ARRAY_SIZE(rates); i++) - if (runtime->rate == rates[i]) - cdev->pcm_info.rates = 1 << i; - + cdev->pcm_info.rates = snd_pcm_rate_to_rate_bit(runtime->rate); snd_pcm_limit_hw_rates(runtime); bytes_per_sample = BYTES_PER_SAMPLE; diff --git a/sound/usb/card.c b/sound/usb/card.c index bdb04fa37a71df..778de9244f1e76 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c @@ -206,6 +206,8 @@ static int snd_usb_create_stream(struct snd_usb_audio *chip, int ctrlif, int int return -EINVAL; } + snd_usb_add_ctrl_interface_link(chip, interface, ctrlif); + if (! snd_usb_parse_audio_interface(chip, interface)) { usb_set_interface(dev, interface, 0); /* reset the current interface */ return usb_driver_claim_interface(&usb_audio_driver, iface, diff --git a/sound/usb/clock.c b/sound/usb/clock.c index 60fcb872a80b6c..8f85200292f3ff 100644 --- a/sound/usb/clock.c +++ b/sound/usb/clock.c @@ -76,11 +76,14 @@ static bool validate_clock_multiplier(void *p, int id, int proto) } #define DEFINE_FIND_HELPER(name, obj, validator, type2, type3) \ -static obj *name(struct snd_usb_audio *chip, int id, int proto) \ +static obj *name(struct snd_usb_audio *chip, int id, \ + const struct audioformat *fmt) \ { \ - return find_uac_clock_desc(chip->ctrl_intf, id, validator, \ - proto == UAC_VERSION_3 ? (type3) : (type2), \ - proto); \ + struct usb_host_interface *ctrl_intf = \ + snd_usb_find_ctrl_interface(chip, fmt->iface); \ + return find_uac_clock_desc(ctrl_intf, id, validator, \ + fmt->protocol == UAC_VERSION_3 ? (type3) : (type2), \ + fmt->protocol); \ } DEFINE_FIND_HELPER(snd_usb_find_clock_source, @@ -93,16 +96,19 @@ DEFINE_FIND_HELPER(snd_usb_find_clock_multiplier, union uac23_clock_multiplier_desc, validate_clock_multiplier, UAC2_CLOCK_MULTIPLIER, UAC3_CLOCK_MULTIPLIER); -static int uac_clock_selector_get_val(struct snd_usb_audio *chip, int selector_id) +static int uac_clock_selector_get_val(struct snd_usb_audio *chip, + int selector_id, int iface_no) { + struct usb_host_interface *ctrl_intf; unsigned char buf; int ret; + ctrl_intf = snd_usb_find_ctrl_interface(chip, iface_no); ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), UAC2_CS_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, UAC2_CX_CLOCK_SELECTOR << 8, - snd_usb_ctrl_intf(chip) | (selector_id << 8), + snd_usb_ctrl_intf(ctrl_intf) | (selector_id << 8), &buf, sizeof(buf)); if (ret < 0) @@ -111,16 +117,18 @@ static int uac_clock_selector_get_val(struct snd_usb_audio *chip, int selector_i return buf; } -static int uac_clock_selector_set_val(struct snd_usb_audio *chip, int selector_id, - unsigned char pin) +static int uac_clock_selector_set_val(struct snd_usb_audio *chip, + int selector_id, unsigned char pin, int iface_no) { + struct usb_host_interface *ctrl_intf; int ret; + ctrl_intf = snd_usb_find_ctrl_interface(chip, iface_no); ret = snd_usb_ctl_msg(chip->dev, usb_sndctrlpipe(chip->dev, 0), UAC2_CS_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, UAC2_CX_CLOCK_SELECTOR << 8, - snd_usb_ctrl_intf(chip) | (selector_id << 8), + snd_usb_ctrl_intf(ctrl_intf) | (selector_id << 8), &pin, sizeof(pin)); if (ret < 0) return ret; @@ -132,7 +140,7 @@ static int uac_clock_selector_set_val(struct snd_usb_audio *chip, int selector_i return -EINVAL; } - ret = uac_clock_selector_get_val(chip, selector_id); + ret = uac_clock_selector_get_val(chip, selector_id, iface_no); if (ret < 0) return ret; @@ -155,8 +163,10 @@ static bool uac_clock_source_is_valid_quirk(struct snd_usb_audio *chip, unsigned char data; struct usb_device *dev = chip->dev; union uac23_clock_source_desc *cs_desc; + struct usb_host_interface *ctrl_intf; - cs_desc = snd_usb_find_clock_source(chip, source_id, fmt->protocol); + ctrl_intf = snd_usb_find_ctrl_interface(chip, fmt->iface); + cs_desc = snd_usb_find_clock_source(chip, source_id, fmt); if (!cs_desc) return false; @@ -191,7 +201,7 @@ static bool uac_clock_source_is_valid_quirk(struct snd_usb_audio *chip, err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_CUR, USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN, UAC2_CS_CONTROL_CLOCK_VALID << 8, - snd_usb_ctrl_intf(chip) | (source_id << 8), + snd_usb_ctrl_intf(ctrl_intf) | (source_id << 8), &data, sizeof(data)); if (err < 0) { dev_warn(&dev->dev, @@ -217,8 +227,10 @@ static bool uac_clock_source_is_valid(struct snd_usb_audio *chip, struct usb_device *dev = chip->dev; u32 bmControls; union uac23_clock_source_desc *cs_desc; + struct usb_host_interface *ctrl_intf; - cs_desc = snd_usb_find_clock_source(chip, source_id, fmt->protocol); + ctrl_intf = snd_usb_find_ctrl_interface(chip, fmt->iface); + cs_desc = snd_usb_find_clock_source(chip, source_id, fmt); if (!cs_desc) return false; @@ -235,7 +247,7 @@ static bool uac_clock_source_is_valid(struct snd_usb_audio *chip, err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_CUR, USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN, UAC2_CS_CONTROL_CLOCK_VALID << 8, - snd_usb_ctrl_intf(chip) | (source_id << 8), + snd_usb_ctrl_intf(ctrl_intf) | (source_id << 8), &data, sizeof(data)); if (err < 0) { @@ -274,7 +286,7 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip, } /* first, see if the ID we're looking at is a clock source already */ - source = snd_usb_find_clock_source(chip, entity_id, proto); + source = snd_usb_find_clock_source(chip, entity_id, fmt); if (source) { entity_id = GET_VAL(source, proto, bClockID); if (validate && !uac_clock_source_is_valid(chip, fmt, @@ -287,7 +299,7 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip, return entity_id; } - selector = snd_usb_find_clock_selector(chip, entity_id, proto); + selector = snd_usb_find_clock_selector(chip, entity_id, fmt); if (selector) { pins = GET_VAL(selector, proto, bNrInPins); clock_id = GET_VAL(selector, proto, bClockID); @@ -317,7 +329,7 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip, /* the entity ID we are looking at is a selector. * find out what it currently selects */ - ret = uac_clock_selector_get_val(chip, clock_id); + ret = uac_clock_selector_get_val(chip, clock_id, fmt->iface); if (ret < 0) { if (!chip->autoclock) return ret; @@ -346,7 +358,7 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip, if (chip->quirk_flags & QUIRK_FLAG_SKIP_CLOCK_SELECTOR || !writeable) return ret; - err = uac_clock_selector_set_val(chip, entity_id, cur); + err = uac_clock_selector_set_val(chip, entity_id, cur, fmt->iface); if (err < 0) { if (pins == 1) { usb_audio_dbg(chip, @@ -377,7 +389,7 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip, if (ret < 0) continue; - err = uac_clock_selector_set_val(chip, entity_id, i); + err = uac_clock_selector_set_val(chip, entity_id, i, fmt->iface); if (err < 0) continue; @@ -391,7 +403,7 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip, } /* FIXME: multipliers only act as pass-thru element for now */ - multiplier = snd_usb_find_clock_multiplier(chip, entity_id, proto); + multiplier = snd_usb_find_clock_multiplier(chip, entity_id, fmt); if (multiplier) return __uac_clock_find_source(chip, fmt, GET_VAL(multiplier, proto, bCSourceID), @@ -491,11 +503,13 @@ static int get_sample_rate_v2v3(struct snd_usb_audio *chip, int iface, struct usb_device *dev = chip->dev; __le32 data; int err; + struct usb_host_interface *ctrl_intf; + ctrl_intf = snd_usb_find_ctrl_interface(chip, iface); err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_CUR, USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN, UAC2_CS_CONTROL_SAM_FREQ << 8, - snd_usb_ctrl_intf(chip) | (clock << 8), + snd_usb_ctrl_intf(ctrl_intf) | (clock << 8), &data, sizeof(data)); if (err < 0) { dev_warn(&dev->dev, "%d:%d: cannot get freq (v2/v3): err %d\n", @@ -524,8 +538,10 @@ int snd_usb_set_sample_rate_v2v3(struct snd_usb_audio *chip, __le32 data; int err; union uac23_clock_source_desc *cs_desc; + struct usb_host_interface *ctrl_intf; - cs_desc = snd_usb_find_clock_source(chip, clock, fmt->protocol); + ctrl_intf = snd_usb_find_ctrl_interface(chip, fmt->iface); + cs_desc = snd_usb_find_clock_source(chip, clock, fmt); if (!cs_desc) return 0; @@ -544,7 +560,7 @@ int snd_usb_set_sample_rate_v2v3(struct snd_usb_audio *chip, err = snd_usb_ctl_msg(chip->dev, usb_sndctrlpipe(chip->dev, 0), UAC2_CS_CUR, USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT, UAC2_CS_CONTROL_SAM_FREQ << 8, - snd_usb_ctrl_intf(chip) | (clock << 8), + snd_usb_ctrl_intf(ctrl_intf) | (clock << 8), &data, sizeof(data)); if (err < 0) return err; diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index 8f65349a06d369..568099467dbbcc 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c @@ -921,6 +921,9 @@ static int endpoint_set_interface(struct snd_usb_audio *chip, if (ep->iface_ref->altset == altset) return 0; + /* already disconnected? */ + if (unlikely(atomic_read(&chip->shutdown))) + return -ENODEV; usb_audio_dbg(chip, "Setting usb interface %d:%d for EP 0x%x\n", ep->iface, altset, ep->ep_num); diff --git a/sound/usb/format.c b/sound/usb/format.c index 1bb6a455a1b461..0cbf1d4fbe6edd 100644 --- a/sound/usb/format.c +++ b/sound/usb/format.c @@ -545,7 +545,9 @@ static int parse_audio_format_rates_v2v3(struct snd_usb_audio *chip, unsigned char tmp[2], *data; int nr_triplets, data_size, ret = 0, ret_l6; int clock = snd_usb_clock_find_source(chip, fp, false); + struct usb_host_interface *ctrl_intf; + ctrl_intf = snd_usb_find_ctrl_interface(chip, fp->iface); if (clock < 0) { dev_err(&dev->dev, "%s(): unable to find clock source (clock %d)\n", @@ -557,7 +559,7 @@ static int parse_audio_format_rates_v2v3(struct snd_usb_audio *chip, ret = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_RANGE, USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN, UAC2_CS_CONTROL_SAM_FREQ << 8, - snd_usb_ctrl_intf(chip) | (clock << 8), + snd_usb_ctrl_intf(ctrl_intf) | (clock << 8), tmp, sizeof(tmp)); if (ret < 0) { @@ -592,7 +594,7 @@ static int parse_audio_format_rates_v2v3(struct snd_usb_audio *chip, ret = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_RANGE, USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN, UAC2_CS_CONTROL_SAM_FREQ << 8, - snd_usb_ctrl_intf(chip) | (clock << 8), + snd_usb_ctrl_intf(ctrl_intf) | (clock << 8), data, data_size); if (ret < 0) { diff --git a/sound/usb/helper.c b/sound/usb/helper.c index bf80e55d013a87..72b671fb2c84ca 100644 --- a/sound/usb/helper.c +++ b/sound/usb/helper.c @@ -130,3 +130,37 @@ snd_usb_get_host_interface(struct snd_usb_audio *chip, int ifnum, int altsetting return NULL; return usb_altnum_to_altsetting(iface, altsetting); } + +int snd_usb_add_ctrl_interface_link(struct snd_usb_audio *chip, int ifnum, + int ctrlif) +{ + struct usb_device *dev = chip->dev; + struct usb_host_interface *host_iface; + + if (chip->num_intf_to_ctrl >= MAX_CARD_INTERFACES) { + dev_info(&dev->dev, "Too many interfaces assigned to the single USB-audio card\n"); + return -EINVAL; + } + + /* find audiocontrol interface */ + host_iface = &usb_ifnum_to_if(dev, ctrlif)->altsetting[0]; + + chip->intf_to_ctrl[chip->num_intf_to_ctrl].interface = ifnum; + chip->intf_to_ctrl[chip->num_intf_to_ctrl].ctrl_intf = host_iface; + chip->num_intf_to_ctrl++; + + return 0; +} + +struct usb_host_interface *snd_usb_find_ctrl_interface(struct snd_usb_audio *chip, + int ifnum) +{ + int i; + + for (i = 0; i < chip->num_intf_to_ctrl; ++i) + if (chip->intf_to_ctrl[i].interface == ifnum) + return chip->intf_to_ctrl[i].ctrl_intf; + + /* Fallback to first audiocontrol interface */ + return chip->ctrl_intf; +} diff --git a/sound/usb/helper.h b/sound/usb/helper.h index e2b51ec96ec62a..0372e050b3dc47 100644 --- a/sound/usb/helper.h +++ b/sound/usb/helper.h @@ -17,6 +17,12 @@ unsigned char snd_usb_parse_datainterval(struct snd_usb_audio *chip, struct usb_host_interface * snd_usb_get_host_interface(struct snd_usb_audio *chip, int ifnum, int altsetting); +int snd_usb_add_ctrl_interface_link(struct snd_usb_audio *chip, int ifnum, + int ctrlif); + +struct usb_host_interface *snd_usb_find_ctrl_interface(struct snd_usb_audio *chip, + int ifnum); + /* * retrieve usb_interface descriptor from the host interface * (conditional for compatibility with the older API) @@ -28,9 +34,9 @@ snd_usb_get_host_interface(struct snd_usb_audio *chip, int ifnum, int altsetting #define snd_usb_get_speed(dev) ((dev)->speed) -static inline int snd_usb_ctrl_intf(struct snd_usb_audio *chip) +static inline int snd_usb_ctrl_intf(struct usb_host_interface *ctrl_intf) { - return get_iface_desc(chip->ctrl_intf)->bInterfaceNumber; + return get_iface_desc(ctrl_intf)->bInterfaceNumber; } /* in validate.c */ diff --git a/sound/usb/line6/driver.c b/sound/usb/line6/driver.c index f4437015d43a75..9df49a880b750d 100644 --- a/sound/usb/line6/driver.c +++ b/sound/usb/line6/driver.c @@ -286,12 +286,14 @@ static void line6_data_received(struct urb *urb) { struct usb_line6 *line6 = (struct usb_line6 *)urb->context; struct midi_buffer *mb = &line6->line6midi->midibuf_in; + unsigned long flags; int done; if (urb->status == -ESHUTDOWN) return; if (line6->properties->capabilities & LINE6_CAP_CONTROL_MIDI) { + spin_lock_irqsave(&line6->line6midi->lock, flags); done = line6_midibuf_write(mb, urb->transfer_buffer, urb->actual_length); @@ -300,12 +302,15 @@ static void line6_data_received(struct urb *urb) dev_dbg(line6->ifcdev, "%d %d buffer overflow - message skipped\n", done, urb->actual_length); } + spin_unlock_irqrestore(&line6->line6midi->lock, flags); for (;;) { + spin_lock_irqsave(&line6->line6midi->lock, flags); done = line6_midibuf_read(mb, line6->buffer_message, LINE6_MIDI_MESSAGE_MAXLEN, LINE6_MIDIBUF_READ_RX); + spin_unlock_irqrestore(&line6->line6midi->lock, flags); if (done <= 0) break; diff --git a/sound/usb/midi.c b/sound/usb/midi.c index c1f2e5a03de969..737dd00e97b142 100644 --- a/sound/usb/midi.c +++ b/sound/usb/midi.c @@ -224,10 +224,10 @@ static void snd_usbmidi_input_data(struct snd_usb_midi_in_endpoint *ep, #ifdef DUMP_PACKETS static void dump_urb(const char *type, const u8 *data, int length) { - snd_printk(KERN_DEBUG "%s packet: [", type); + pr_debug("%s packet: [", type); for (; length > 0; ++data, --length) - printk(KERN_CONT " %02x", *data); - printk(KERN_CONT " ]\n"); + pr_cont(" %02x", *data); + pr_cont(" ]\n"); } #else #define dump_urb(type, data, length) /* nothing */ diff --git a/sound/usb/midi2.c b/sound/usb/midi2.c index 820d3e4b672ab6..692dfc3c182f0e 100644 --- a/sound/usb/midi2.c +++ b/sound/usb/midi2.c @@ -607,12 +607,8 @@ static int parse_group_terminal_block(struct snd_usb_midi2_ump *rmidi, return 0; } - if (ump->info.protocol && ump->info.protocol != protocol) - usb_audio_info(rmidi->umidi->chip, - "Overriding preferred MIDI protocol in GTB %d: %x -> %x\n", - rmidi->usb_block_id, ump->info.protocol, - protocol); - ump->info.protocol = protocol; + if (!ump->info.protocol) + ump->info.protocol = protocol; protocol_caps = protocol; switch (desc->bMIDIProtocol) { @@ -624,13 +620,7 @@ static int parse_group_terminal_block(struct snd_usb_midi2_ump *rmidi, break; } - if (ump->info.protocol_caps && ump->info.protocol_caps != protocol_caps) - usb_audio_info(rmidi->umidi->chip, - "Overriding MIDI protocol caps in GTB %d: %x -> %x\n", - rmidi->usb_block_id, ump->info.protocol_caps, - protocol_caps); - ump->info.protocol_caps = protocol_caps; - + ump->info.protocol_caps |= protocol_caps; return 0; } @@ -873,9 +863,25 @@ static int create_gtb_block(struct snd_usb_midi2_ump *rmidi, int dir, int blk) fb->info.flags |= SNDRV_UMP_BLOCK_IS_MIDI1 | SNDRV_UMP_BLOCK_IS_LOWSPEED; + /* if MIDI 2.0 protocol is supported and yet the GTB shows MIDI 1.0, + * treat it as a MIDI 1.0-specific block + */ + if (rmidi->ump->info.protocol_caps & SNDRV_UMP_EP_INFO_PROTO_MIDI2) { + switch (desc->bMIDIProtocol) { + case USB_MS_MIDI_PROTO_1_0_64: + case USB_MS_MIDI_PROTO_1_0_64_JRTS: + case USB_MS_MIDI_PROTO_1_0_128: + case USB_MS_MIDI_PROTO_1_0_128_JRTS: + fb->info.flags |= SNDRV_UMP_BLOCK_IS_MIDI1; + break; + } + } + + snd_ump_update_group_attrs(rmidi->ump); + usb_audio_dbg(umidi->chip, - "Created a UMP block %d from GTB, name=%s\n", - blk, fb->info.name); + "Created a UMP block %d from GTB, name=%s, flags=0x%x\n", + blk, fb->info.name, fb->info.flags); return 0; } diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index f7ce8e8c3c3eaa..9945ae55b0d08b 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -728,7 +728,7 @@ static int get_cluster_channels_v3(struct mixer_build *state, unsigned int clust UAC3_CS_REQ_HIGH_CAPABILITY_DESCRIPTOR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, cluster_id, - snd_usb_ctrl_intf(state->chip), + snd_usb_ctrl_intf(state->mixer->hostif), &c_header, sizeof(c_header)); if (err < 0) goto error; @@ -1377,6 +1377,19 @@ static int get_min_max_with_quirks(struct usb_mixer_elem_info *cval, #define get_min_max(cval, def) get_min_max_with_quirks(cval, def, NULL) +/* get the max value advertised via control API */ +static int get_max_exposed(struct usb_mixer_elem_info *cval) +{ + if (!cval->max_exposed) { + if (cval->res) + cval->max_exposed = + DIV_ROUND_UP(cval->max - cval->min, cval->res); + else + cval->max_exposed = cval->max - cval->min; + } + return cval->max_exposed; +} + /* get a feature/mixer unit info */ static int mixer_ctl_feature_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) @@ -1389,11 +1402,8 @@ static int mixer_ctl_feature_info(struct snd_kcontrol *kcontrol, else uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; uinfo->count = cval->channels; - if (cval->val_type == USB_MIXER_BOOLEAN || - cval->val_type == USB_MIXER_INV_BOOLEAN) { - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 1; - } else { + if (cval->val_type != USB_MIXER_BOOLEAN && + cval->val_type != USB_MIXER_INV_BOOLEAN) { if (!cval->initialized) { get_min_max_with_quirks(cval, 0, kcontrol); if (cval->initialized && cval->dBmin >= cval->dBmax) { @@ -1405,10 +1415,10 @@ static int mixer_ctl_feature_info(struct snd_kcontrol *kcontrol, &kcontrol->id); } } - uinfo->value.integer.min = 0; - uinfo->value.integer.max = - DIV_ROUND_UP(cval->max - cval->min, cval->res); } + + uinfo->value.integer.min = 0; + uinfo->value.integer.max = get_max_exposed(cval); return 0; } @@ -1449,6 +1459,7 @@ static int mixer_ctl_feature_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct usb_mixer_elem_info *cval = kcontrol->private_data; + int max_val = get_max_exposed(cval); int c, cnt, val, oval, err; int changed = 0; @@ -1461,6 +1472,8 @@ static int mixer_ctl_feature_put(struct snd_kcontrol *kcontrol, if (err < 0) return filter_error(cval, err); val = ucontrol->value.integer.value[cnt]; + if (val < 0 || val > max_val) + return -EINVAL; val = get_abs_value(cval, val); if (oval != val) { snd_usb_set_cur_mix_value(cval, c + 1, cnt, val); @@ -1474,6 +1487,8 @@ static int mixer_ctl_feature_put(struct snd_kcontrol *kcontrol, if (err < 0) return filter_error(cval, err); val = ucontrol->value.integer.value[0]; + if (val < 0 || val > max_val) + return -EINVAL; val = get_abs_value(cval, val); if (val != oval) { snd_usb_set_cur_mix_value(cval, 0, 0, val); @@ -2337,6 +2352,8 @@ static int mixer_ctl_procunit_put(struct snd_kcontrol *kcontrol, if (err < 0) return filter_error(cval, err); val = ucontrol->value.integer.value[0]; + if (val < 0 || val > get_max_exposed(cval)) + return -EINVAL; val = get_abs_value(cval, val); if (val != oval) { set_cur_ctl_value(cval, cval->control << 8, val); @@ -2699,6 +2716,8 @@ static int mixer_ctl_selector_put(struct snd_kcontrol *kcontrol, if (err < 0) return filter_error(cval, err); val = ucontrol->value.enumerated.item[0]; + if (val < 0 || val >= cval->max) /* here cval->max = # elements */ + return -EINVAL; val = get_abs_value(cval, val); if (val != oval) { set_cur_ctl_value(cval, cval->control << 8, val); diff --git a/sound/usb/mixer.h b/sound/usb/mixer.h index d43895c1ae5c6c..167fbfcf01ace9 100644 --- a/sound/usb/mixer.h +++ b/sound/usb/mixer.h @@ -88,6 +88,7 @@ struct usb_mixer_elem_info { int channels; int val_type; int min, max, res; + int max_exposed; /* control API exposes the value in 0..max_exposed */ int dBmin, dBmax; int cached; int cache_val[MAX_CHANNELS]; diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c index 2bc344cf54a831..5d6792f51f4cb2 100644 --- a/sound/usb/mixer_quirks.c +++ b/sound/usb/mixer_quirks.c @@ -1043,7 +1043,7 @@ static int snd_ftu_eff_switch_init(struct usb_mixer_interface *mixer, err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC_GET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, pval & 0xff00, - snd_usb_ctrl_intf(mixer->chip) | ((pval & 0xff) << 8), + snd_usb_ctrl_intf(mixer->hostif) | ((pval & 0xff) << 8), value, 2); if (err < 0) return err; @@ -1077,7 +1077,7 @@ static int snd_ftu_eff_switch_update(struct usb_mixer_elem_list *list) UAC_SET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, pval & 0xff00, - snd_usb_ctrl_intf(chip) | ((pval & 0xff) << 8), + snd_usb_ctrl_intf(list->mixer->hostif) | ((pval & 0xff) << 8), value, 2); snd_usb_unlock_shutdown(chip); return err; @@ -2115,24 +2115,25 @@ static int dell_dock_mixer_create(struct usb_mixer_interface *mixer) return 0; } -static void dell_dock_init_vol(struct snd_usb_audio *chip, int ch, int id) +static void dell_dock_init_vol(struct usb_mixer_interface *mixer, int ch, int id) { + struct snd_usb_audio *chip = mixer->chip; u16 buf = 0; snd_usb_ctl_msg(chip->dev, usb_sndctrlpipe(chip->dev, 0), UAC_SET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, (UAC_FU_VOLUME << 8) | ch, - snd_usb_ctrl_intf(chip) | (id << 8), + snd_usb_ctrl_intf(mixer->hostif) | (id << 8), &buf, 2); } static int dell_dock_mixer_init(struct usb_mixer_interface *mixer) { /* fix to 0dB playback volumes */ - dell_dock_init_vol(mixer->chip, 1, 16); - dell_dock_init_vol(mixer->chip, 2, 16); - dell_dock_init_vol(mixer->chip, 1, 19); - dell_dock_init_vol(mixer->chip, 2, 19); + dell_dock_init_vol(mixer, 1, 16); + dell_dock_init_vol(mixer, 2, 16); + dell_dock_init_vol(mixer, 1, 19); + dell_dock_init_vol(mixer, 2, 19); return 0; } @@ -2541,14 +2542,23 @@ enum { #define SND_BBFPRO_CTL_REG2_PAD_AN1 4 #define SND_BBFPRO_CTL_REG2_PAD_AN2 5 -#define SND_BBFPRO_MIXER_IDX_MASK 0x1ff +#define SND_BBFPRO_MIXER_MAIN_OUT_CH_OFFSET 992 +#define SND_BBFPRO_MIXER_IDX_MASK 0x3ff #define SND_BBFPRO_MIXER_VAL_MASK 0x3ffff #define SND_BBFPRO_MIXER_VAL_SHIFT 9 #define SND_BBFPRO_MIXER_VAL_MIN 0 // -inf #define SND_BBFPRO_MIXER_VAL_MAX 65536 // +6dB +#define SND_BBFPRO_GAIN_CHANNEL_MASK 0x03 +#define SND_BBFPRO_GAIN_CHANNEL_SHIFT 7 +#define SND_BBFPRO_GAIN_VAL_MASK 0x7f +#define SND_BBFPRO_GAIN_VAL_MIN 0 +#define SND_BBFPRO_GAIN_VAL_MIC_MAX 65 +#define SND_BBFPRO_GAIN_VAL_LINE_MAX 18 // 9db in 0.5db incraments + #define SND_BBFPRO_USBREQ_CTL_REG1 0x10 #define SND_BBFPRO_USBREQ_CTL_REG2 0x17 +#define SND_BBFPRO_USBREQ_GAIN 0x1a #define SND_BBFPRO_USBREQ_MIXER 0x12 static int snd_bbfpro_ctl_update(struct usb_mixer_interface *mixer, u8 reg, @@ -2695,6 +2705,114 @@ static int snd_bbfpro_ctl_resume(struct usb_mixer_elem_list *list) return snd_bbfpro_ctl_update(list->mixer, reg, idx, value); } +static int snd_bbfpro_gain_update(struct usb_mixer_interface *mixer, + u8 channel, u8 gain) +{ + int err; + struct snd_usb_audio *chip = mixer->chip; + + if (channel < 2) { + // XLR preamp: 3-bit fine, 5-bit coarse; special case >60 + if (gain < 60) + gain = ((gain % 3) << 5) | (gain / 3); + else + gain = ((gain % 6) << 5) | (60 / 3); + } + + err = snd_usb_lock_shutdown(chip); + if (err < 0) + return err; + + err = snd_usb_ctl_msg(chip->dev, + usb_sndctrlpipe(chip->dev, 0), + SND_BBFPRO_USBREQ_GAIN, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + gain, channel, NULL, 0); + + snd_usb_unlock_shutdown(chip); + return err; +} + +static int snd_bbfpro_gain_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int value = kcontrol->private_value & SND_BBFPRO_GAIN_VAL_MASK; + + ucontrol->value.integer.value[0] = value; + return 0; +} + +static int snd_bbfpro_gain_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + int pv, channel; + + pv = kcontrol->private_value; + channel = (pv >> SND_BBFPRO_GAIN_CHANNEL_SHIFT) & + SND_BBFPRO_GAIN_CHANNEL_MASK; + + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = 1; + uinfo->value.integer.min = SND_BBFPRO_GAIN_VAL_MIN; + + if (channel < 2) + uinfo->value.integer.max = SND_BBFPRO_GAIN_VAL_MIC_MAX; + else + uinfo->value.integer.max = SND_BBFPRO_GAIN_VAL_LINE_MAX; + + return 0; +} + +static int snd_bbfpro_gain_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int pv, channel, old_value, value, err; + + struct usb_mixer_elem_list *list = snd_kcontrol_chip(kcontrol); + struct usb_mixer_interface *mixer = list->mixer; + + pv = kcontrol->private_value; + channel = (pv >> SND_BBFPRO_GAIN_CHANNEL_SHIFT) & + SND_BBFPRO_GAIN_CHANNEL_MASK; + old_value = pv & SND_BBFPRO_GAIN_VAL_MASK; + value = ucontrol->value.integer.value[0]; + + if (value < SND_BBFPRO_GAIN_VAL_MIN) + return -EINVAL; + + if (channel < 2) { + if (value > SND_BBFPRO_GAIN_VAL_MIC_MAX) + return -EINVAL; + } else { + if (value > SND_BBFPRO_GAIN_VAL_LINE_MAX) + return -EINVAL; + } + + if (value == old_value) + return 0; + + err = snd_bbfpro_gain_update(mixer, channel, value); + if (err < 0) + return err; + + kcontrol->private_value = + (channel << SND_BBFPRO_GAIN_CHANNEL_SHIFT) | value; + return 1; +} + +static int snd_bbfpro_gain_resume(struct usb_mixer_elem_list *list) +{ + int pv, channel, value; + struct snd_kcontrol *kctl = list->kctl; + + pv = kctl->private_value; + channel = (pv >> SND_BBFPRO_GAIN_CHANNEL_SHIFT) & + SND_BBFPRO_GAIN_CHANNEL_MASK; + value = pv & SND_BBFPRO_GAIN_VAL_MASK; + + return snd_bbfpro_gain_update(list->mixer, channel, value); +} + static int snd_bbfpro_vol_update(struct usb_mixer_interface *mixer, u16 index, u32 value) { @@ -2790,6 +2908,15 @@ static const struct snd_kcontrol_new snd_bbfpro_ctl_control = { .put = snd_bbfpro_ctl_put }; +static const struct snd_kcontrol_new snd_bbfpro_gain_control = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .index = 0, + .info = snd_bbfpro_gain_info, + .get = snd_bbfpro_gain_get, + .put = snd_bbfpro_gain_put +}; + static const struct snd_kcontrol_new snd_bbfpro_vol_control = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, @@ -2813,6 +2940,18 @@ static int snd_bbfpro_ctl_add(struct usb_mixer_interface *mixer, u8 reg, &knew, NULL); } +static int snd_bbfpro_gain_add(struct usb_mixer_interface *mixer, u8 channel, + char *name) +{ + struct snd_kcontrol_new knew = snd_bbfpro_gain_control; + + knew.name = name; + knew.private_value = channel << SND_BBFPRO_GAIN_CHANNEL_SHIFT; + + return add_single_ctl_with_resume(mixer, 0, snd_bbfpro_gain_resume, + &knew, NULL); +} + static int snd_bbfpro_vol_add(struct usb_mixer_interface *mixer, u16 index, char *name) { @@ -2860,6 +2999,29 @@ static int snd_bbfpro_controls_create(struct usb_mixer_interface *mixer) } } + // Main out volume + for (i = 0 ; i < 12 ; ++i) { + snprintf(name, sizeof(name), "Main-Out %s", output[i]); + // Main outs are offset to 992 + err = snd_bbfpro_vol_add(mixer, + i + SND_BBFPRO_MIXER_MAIN_OUT_CH_OFFSET, + name); + if (err < 0) + return err; + } + + // Input gain + for (i = 0 ; i < 4 ; ++i) { + if (i < 2) + snprintf(name, sizeof(name), "Mic-%s Gain", input[i]); + else + snprintf(name, sizeof(name), "Line-%s Gain", input[i]); + + err = snd_bbfpro_gain_add(mixer, i, name); + if (err < 0) + return err; + } + // Control Reg 1 err = snd_bbfpro_ctl_add(mixer, SND_BBFPRO_CTL_REG1, SND_BBFPRO_CTL_REG1_CLK_OPTICAL, diff --git a/sound/usb/mixer_scarlett.c b/sound/usb/mixer_scarlett.c index 0d6e4f15bf77ca..ff548041679bbe 100644 --- a/sound/usb/mixer_scarlett.c +++ b/sound/usb/mixer_scarlett.c @@ -460,7 +460,7 @@ static int scarlett_ctl_meter_get(struct snd_kcontrol *kctl, struct snd_usb_audio *chip = elem->head.mixer->chip; unsigned char buf[2 * MAX_CHANNELS] = {0, }; int wValue = (elem->control << 8) | elem->idx_off; - int idx = snd_usb_ctrl_intf(chip) | (elem->head.id << 8); + int idx = snd_usb_ctrl_intf(elem->head.mixer->hostif) | (elem->head.id << 8); int err; err = snd_usb_ctl_msg(chip->dev, @@ -1002,7 +1002,7 @@ int snd_scarlett_controls_create(struct usb_mixer_interface *mixer) err = snd_usb_ctl_msg(mixer->chip->dev, usb_sndctrlpipe(mixer->chip->dev, 0), UAC2_CS_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | - USB_DIR_OUT, 0x0100, snd_usb_ctrl_intf(mixer->chip) | + USB_DIR_OUT, 0x0100, snd_usb_ctrl_intf(mixer->hostif) | (0x29 << 8), sample_rate_buffer, 4); if (err < 0) return err; diff --git a/sound/usb/power.c b/sound/usb/power.c index 606a2cb23eab61..66bd4daa68fd50 100644 --- a/sound/usb/power.c +++ b/sound/usb/power.c @@ -40,6 +40,7 @@ snd_usb_find_power_domain(struct usb_host_interface *ctrl_iface, le16_to_cpu(pd_desc->waRecoveryTime1); pd->pd_d2d0_rec = le16_to_cpu(pd_desc->waRecoveryTime2); + pd->ctrl_iface = ctrl_iface; return pd; } } @@ -57,7 +58,7 @@ int snd_usb_power_domain_set(struct snd_usb_audio *chip, unsigned char current_state; int err, idx; - idx = snd_usb_ctrl_intf(chip) | (pd->pd_id << 8); + idx = snd_usb_ctrl_intf(pd->ctrl_iface) | (pd->pd_id << 8); err = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), UAC2_CS_CUR, diff --git a/sound/usb/power.h b/sound/usb/power.h index 396e3e51440a7f..1fa92ad0ca9251 100644 --- a/sound/usb/power.h +++ b/sound/usb/power.h @@ -6,6 +6,7 @@ struct snd_usb_power_domain { int pd_id; /* UAC3 Power Domain ID */ int pd_d1d0_rec; /* D1 to D0 recovery time */ int pd_d2d0_rec; /* D2 to D0 recovery time */ + struct usb_host_interface *ctrl_iface; /* Control interface */ }; enum { diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h index 73abc38a540068..8d22de8bc2a96f 100644 --- a/sound/usb/quirks-table.h +++ b/sound/usb/quirks-table.h @@ -35,10 +35,87 @@ .bInterfaceClass = USB_CLASS_AUDIO, \ .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL +/* Quirk .driver_info, followed by the definition of the quirk entry; + * put like QUIRK_DRIVER_INFO { ... } in each entry of the quirk table + */ +#define QUIRK_DRIVER_INFO \ + .driver_info = (unsigned long)&(const struct snd_usb_audio_quirk) + +/* + * Macros for quirk data entries + */ + +/* Quirk data entry for ignoring the interface */ +#define QUIRK_DATA_IGNORE(_ifno) \ + .ifnum = (_ifno), .type = QUIRK_IGNORE_INTERFACE +/* Quirk data entry for a standard audio interface */ +#define QUIRK_DATA_STANDARD_AUDIO(_ifno) \ + .ifnum = (_ifno), .type = QUIRK_AUDIO_STANDARD_INTERFACE +/* Quirk data entry for a standard MIDI interface */ +#define QUIRK_DATA_STANDARD_MIDI(_ifno) \ + .ifnum = (_ifno), .type = QUIRK_MIDI_STANDARD_INTERFACE +/* Quirk data entry for a standard mixer interface */ +#define QUIRK_DATA_STANDARD_MIXER(_ifno) \ + .ifnum = (_ifno), .type = QUIRK_AUDIO_STANDARD_MIXER + +/* Quirk data entry for Yamaha MIDI */ +#define QUIRK_DATA_MIDI_YAMAHA(_ifno) \ + .ifnum = (_ifno), .type = QUIRK_MIDI_YAMAHA +/* Quirk data entry for Edirol UAxx */ +#define QUIRK_DATA_EDIROL_UAXX(_ifno) \ + .ifnum = (_ifno), .type = QUIRK_AUDIO_EDIROL_UAXX +/* Quirk data entry for raw bytes interface */ +#define QUIRK_DATA_RAW_BYTES(_ifno) \ + .ifnum = (_ifno), .type = QUIRK_MIDI_RAW_BYTES + +/* Quirk composite array terminator */ +#define QUIRK_COMPOSITE_END { .ifnum = -1 } + +/* Quirk data entry for composite quirks; + * followed by the quirk array that is terminated with QUIRK_COMPOSITE_END + * e.g. QUIRK_DATA_COMPOSITE { { quirk1 }, { quirk2 },..., QUIRK_COMPOSITE_END } + */ +#define QUIRK_DATA_COMPOSITE \ + .ifnum = QUIRK_ANY_INTERFACE, \ + .type = QUIRK_COMPOSITE, \ + .data = &(const struct snd_usb_audio_quirk[]) + +/* Quirk data entry for a fixed audio endpoint; + * followed by audioformat definition + * e.g. QUIRK_DATA_AUDIOFORMAT(n) { .formats = xxx, ... } + */ +#define QUIRK_DATA_AUDIOFORMAT(_ifno) \ + .ifnum = (_ifno), \ + .type = QUIRK_AUDIO_FIXED_ENDPOINT, \ + .data = &(const struct audioformat) + +/* Quirk data entry for a fixed MIDI endpoint; + * followed by snd_usb_midi_endpoint_info definition + * e.g. QUIRK_DATA_MIDI_FIXED_ENDPOINT(n) { .out_cables = x, .in_cables = y } + */ +#define QUIRK_DATA_MIDI_FIXED_ENDPOINT(_ifno) \ + .ifnum = (_ifno), \ + .type = QUIRK_MIDI_FIXED_ENDPOINT, \ + .data = &(const struct snd_usb_midi_endpoint_info) +/* Quirk data entry for a MIDIMAN MIDI endpoint */ +#define QUIRK_DATA_MIDI_MIDIMAN(_ifno) \ + .ifnum = (_ifno), \ + .type = QUIRK_MIDI_MIDIMAN, \ + .data = &(const struct snd_usb_midi_endpoint_info) +/* Quirk data entry for a EMAGIC MIDI endpoint */ +#define QUIRK_DATA_MIDI_EMAGIC(_ifno) \ + .ifnum = (_ifno), \ + .type = QUIRK_MIDI_EMAGIC, \ + .data = &(const struct snd_usb_midi_endpoint_info) + +/* + * Here we go... the quirk table definition begins: + */ + /* FTDI devices */ { USB_DEVICE(0x0403, 0xb8d8), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { /* .vendor_name = "STARR LABS", */ /* .product_name = "Starr Labs MIDI USB device", */ .ifnum = 0, @@ -49,10 +126,8 @@ { /* Creative BT-D1 */ USB_DEVICE(0x041e, 0x0005), - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { - .ifnum = 1, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DRIVER_INFO { + QUIRK_DATA_AUDIOFORMAT(1) { .formats = SNDRV_PCM_FMTBIT_S16_LE, .channels = 2, .iface = 1, @@ -87,18 +162,11 @@ */ { USB_AUDIO_DEVICE(0x041e, 0x4095), - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = &(const struct snd_usb_audio_quirk[]) { + QUIRK_DRIVER_INFO { + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_STANDARD_MIXER(2) }, { - .ifnum = 2, - .type = QUIRK_AUDIO_STANDARD_MIXER, - }, - { - .ifnum = 3, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(3) { .formats = SNDRV_PCM_FMTBIT_S16_LE, .channels = 2, .fmt_bits = 16, @@ -114,9 +182,7 @@ .rate_table = (unsigned int[]) { 48000 }, }, }, - { - .ifnum = -1 - }, + QUIRK_COMPOSITE_END }, }, }, @@ -128,31 +194,18 @@ */ { USB_DEVICE(0x0424, 0xb832), - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Standard Microsystems Corp.", .product_name = "HP Wireless Audio", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { + QUIRK_DATA_COMPOSITE { /* Mixer */ - { - .ifnum = 0, - .type = QUIRK_IGNORE_INTERFACE, - }, + { QUIRK_DATA_IGNORE(0) }, /* Playback */ - { - .ifnum = 1, - .type = QUIRK_IGNORE_INTERFACE, - }, + { QUIRK_DATA_IGNORE(1) }, /* Capture */ - { - .ifnum = 2, - .type = QUIRK_IGNORE_INTERFACE, - }, + { QUIRK_DATA_IGNORE(2) }, /* HID Device, .ifnum = 3 */ - { - .ifnum = -1, - } + QUIRK_COMPOSITE_END } } }, @@ -175,20 +228,18 @@ #define YAMAHA_DEVICE(id, name) { \ USB_DEVICE(0x0499, id), \ - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { \ + QUIRK_DRIVER_INFO { \ .vendor_name = "Yamaha", \ .product_name = name, \ - .ifnum = QUIRK_ANY_INTERFACE, \ - .type = QUIRK_MIDI_YAMAHA \ + QUIRK_DATA_MIDI_YAMAHA(QUIRK_ANY_INTERFACE) \ } \ } #define YAMAHA_INTERFACE(id, intf, name) { \ USB_DEVICE_VENDOR_SPEC(0x0499, id), \ - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { \ + QUIRK_DRIVER_INFO { \ .vendor_name = "Yamaha", \ .product_name = name, \ - .ifnum = intf, \ - .type = QUIRK_MIDI_YAMAHA \ + QUIRK_DATA_MIDI_YAMAHA(intf) \ } \ } YAMAHA_DEVICE(0x1000, "UX256"), @@ -273,137 +324,70 @@ YAMAHA_DEVICE(0x105a, NULL), YAMAHA_DEVICE(0x105b, NULL), YAMAHA_DEVICE(0x105c, NULL), YAMAHA_DEVICE(0x105d, NULL), +YAMAHA_DEVICE(0x1718, "P-125"), { USB_DEVICE(0x0499, 0x1503), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { /* .vendor_name = "Yamaha", */ /* .product_name = "MOX6/MOX8", */ - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 1, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 2, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 3, - .type = QUIRK_MIDI_YAMAHA - }, - { - .ifnum = -1 - } + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_STANDARD_AUDIO(1) }, + { QUIRK_DATA_STANDARD_AUDIO(2) }, + { QUIRK_DATA_MIDI_YAMAHA(3) }, + QUIRK_COMPOSITE_END } } }, { USB_DEVICE(0x0499, 0x1507), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { /* .vendor_name = "Yamaha", */ /* .product_name = "THR10", */ - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 1, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 2, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 3, - .type = QUIRK_MIDI_YAMAHA - }, - { - .ifnum = -1 - } + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_STANDARD_AUDIO(1) }, + { QUIRK_DATA_STANDARD_AUDIO(2) }, + { QUIRK_DATA_MIDI_YAMAHA(3) }, + QUIRK_COMPOSITE_END } } }, { USB_DEVICE(0x0499, 0x1509), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { /* .vendor_name = "Yamaha", */ /* .product_name = "Steinberg UR22", */ - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 1, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 2, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 3, - .type = QUIRK_MIDI_YAMAHA - }, - { - .ifnum = 4, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = -1 - } + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_STANDARD_AUDIO(1) }, + { QUIRK_DATA_STANDARD_AUDIO(2) }, + { QUIRK_DATA_MIDI_YAMAHA(3) }, + { QUIRK_DATA_IGNORE(4) }, + QUIRK_COMPOSITE_END } } }, { USB_DEVICE(0x0499, 0x150a), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { /* .vendor_name = "Yamaha", */ /* .product_name = "THR5A", */ - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 1, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 2, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 3, - .type = QUIRK_MIDI_YAMAHA - }, - { - .ifnum = -1 - } + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_STANDARD_AUDIO(1) }, + { QUIRK_DATA_STANDARD_AUDIO(2) }, + { QUIRK_DATA_MIDI_YAMAHA(3) }, + QUIRK_COMPOSITE_END } } }, { USB_DEVICE(0x0499, 0x150c), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { /* .vendor_name = "Yamaha", */ /* .product_name = "THR10C", */ - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 1, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 2, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 3, - .type = QUIRK_MIDI_YAMAHA - }, - { - .ifnum = -1 - } + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_STANDARD_AUDIO(1) }, + { QUIRK_DATA_STANDARD_AUDIO(2) }, + { QUIRK_DATA_MIDI_YAMAHA(3) }, + QUIRK_COMPOSITE_END } } }, @@ -437,7 +421,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), USB_DEVICE_ID_MATCH_INT_CLASS, .idVendor = 0x0499, .bInterfaceClass = USB_CLASS_VENDOR_SPEC, - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .ifnum = QUIRK_ANY_INTERFACE, .type = QUIRK_AUTODETECT } @@ -448,16 +432,12 @@ YAMAHA_DEVICE(0x7010, "UB99"), */ { USB_DEVICE(0x0582, 0x0000), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Roland", .product_name = "UA-100", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { + QUIRK_DATA_COMPOSITE { { - .ifnum = 0, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = & (const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(0) { .formats = SNDRV_PCM_FMTBIT_S16_LE, .channels = 4, .iface = 0, @@ -472,9 +452,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, { - .ifnum = 1, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = & (const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(1) { .formats = SNDRV_PCM_FMTBIT_S16_LE, .channels = 2, .iface = 1, @@ -489,106 +467,66 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, { - .ifnum = 2, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(2) { .out_cables = 0x0007, .in_cables = 0x0007 } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, { USB_DEVICE(0x0582, 0x0002), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "EDIROL", .product_name = "UM-4", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_IGNORE(0) }, + { QUIRK_DATA_IGNORE(1) }, { - .ifnum = 0, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = 1, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = 2, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(2) { .out_cables = 0x000f, .in_cables = 0x000f } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, { USB_DEVICE(0x0582, 0x0003), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Roland", .product_name = "SC-8850", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 0, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = 1, - .type = QUIRK_IGNORE_INTERFACE - }, + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_IGNORE(0) }, + { QUIRK_DATA_IGNORE(1) }, { - .ifnum = 2, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(2) { .out_cables = 0x003f, .in_cables = 0x003f } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, { USB_DEVICE(0x0582, 0x0004), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Roland", .product_name = "U-8", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 0, - .type = QUIRK_IGNORE_INTERFACE - }, + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_IGNORE(0) }, + { QUIRK_DATA_IGNORE(1) }, { - .ifnum = 1, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = 2, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(2) { .out_cables = 0x0005, .in_cables = 0x0005 } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, @@ -596,152 +534,92 @@ YAMAHA_DEVICE(0x7010, "UB99"), /* Has ID 0x0099 when not in "Advanced Driver" mode. * The UM-2EX has only one input, but we cannot detect this. */ USB_DEVICE(0x0582, 0x0005), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "EDIROL", .product_name = "UM-2", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_IGNORE(0) }, + { QUIRK_DATA_IGNORE(1) }, { - .ifnum = 0, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = 1, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = 2, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(2) { .out_cables = 0x0003, .in_cables = 0x0003 } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, { USB_DEVICE(0x0582, 0x0007), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Roland", .product_name = "SC-8820", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 0, - .type = QUIRK_IGNORE_INTERFACE - }, + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_IGNORE(0) }, + { QUIRK_DATA_IGNORE(1) }, { - .ifnum = 1, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = 2, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(2) { .out_cables = 0x0013, .in_cables = 0x0013 } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, { USB_DEVICE(0x0582, 0x0008), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Roland", .product_name = "PC-300", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_IGNORE(0) }, + { QUIRK_DATA_IGNORE(1) }, { - .ifnum = 0, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = 1, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = 2, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(2) { .out_cables = 0x0001, .in_cables = 0x0001 } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, { /* has ID 0x009d when not in "Advanced Driver" mode */ USB_DEVICE(0x0582, 0x0009), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "EDIROL", .product_name = "UM-1", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 0, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = 1, - .type = QUIRK_IGNORE_INTERFACE - }, + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_IGNORE(0) }, + { QUIRK_DATA_IGNORE(1) }, { - .ifnum = 2, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(2) { .out_cables = 0x0001, .in_cables = 0x0001 } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, { USB_DEVICE(0x0582, 0x000b), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Roland", .product_name = "SK-500", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 0, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = 1, - .type = QUIRK_IGNORE_INTERFACE - }, + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_IGNORE(0) }, + { QUIRK_DATA_IGNORE(1) }, { - .ifnum = 2, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(2) { .out_cables = 0x0013, .in_cables = 0x0013 } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, @@ -749,31 +627,19 @@ YAMAHA_DEVICE(0x7010, "UB99"), /* thanks to Emiliano Grilli * for helping researching this data */ USB_DEVICE(0x0582, 0x000c), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Roland", .product_name = "SC-D70", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 0, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 1, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_STANDARD_AUDIO(0) }, + { QUIRK_DATA_STANDARD_AUDIO(1) }, { - .ifnum = 2, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(2) { .out_cables = 0x0007, .in_cables = 0x0007 } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, @@ -787,35 +653,23 @@ YAMAHA_DEVICE(0x7010, "UB99"), * the 96kHz sample rate. */ USB_DEVICE(0x0582, 0x0010), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "EDIROL", .product_name = "UA-5", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 1, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 2, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = -1 - } + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_STANDARD_AUDIO(1) }, + { QUIRK_DATA_STANDARD_AUDIO(2) }, + QUIRK_COMPOSITE_END } } }, { /* has ID 0x0013 when not in "Advanced Driver" mode */ USB_DEVICE(0x0582, 0x0012), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Roland", .product_name = "XV-5050", - .ifnum = 0, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(0) { .out_cables = 0x0001, .in_cables = 0x0001 } @@ -824,12 +678,10 @@ YAMAHA_DEVICE(0x7010, "UB99"), { /* has ID 0x0015 when not in "Advanced Driver" mode */ USB_DEVICE(0x0582, 0x0014), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "EDIROL", .product_name = "UM-880", - .ifnum = 0, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(0) { .out_cables = 0x01ff, .in_cables = 0x01ff } @@ -838,74 +690,48 @@ YAMAHA_DEVICE(0x7010, "UB99"), { /* has ID 0x0017 when not in "Advanced Driver" mode */ USB_DEVICE(0x0582, 0x0016), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "EDIROL", .product_name = "SD-90", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_STANDARD_AUDIO(0) }, + { QUIRK_DATA_STANDARD_AUDIO(1) }, { - .ifnum = 0, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 1, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 2, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(2) { .out_cables = 0x000f, .in_cables = 0x000f } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, { /* has ID 0x001c when not in "Advanced Driver" mode */ USB_DEVICE(0x0582, 0x001b), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Roland", .product_name = "MMP-2", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_IGNORE(0) }, + { QUIRK_DATA_IGNORE(1) }, { - .ifnum = 0, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = 1, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = 2, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(2) { .out_cables = 0x0001, .in_cables = 0x0001 } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, { /* has ID 0x001e when not in "Advanced Driver" mode */ USB_DEVICE(0x0582, 0x001d), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Roland", .product_name = "V-SYNTH", - .ifnum = 0, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(0) { .out_cables = 0x0001, .in_cables = 0x0001 } @@ -914,12 +740,10 @@ YAMAHA_DEVICE(0x7010, "UB99"), { /* has ID 0x0024 when not in "Advanced Driver" mode */ USB_DEVICE(0x0582, 0x0023), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "EDIROL", .product_name = "UM-550", - .ifnum = 0, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(0) { .out_cables = 0x003f, .in_cables = 0x003f } @@ -932,20 +756,13 @@ YAMAHA_DEVICE(0x7010, "UB99"), * and no MIDI. */ USB_DEVICE(0x0582, 0x0025), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "EDIROL", .product_name = "UA-20", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 0, - .type = QUIRK_IGNORE_INTERFACE - }, + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_IGNORE(0) }, { - .ifnum = 1, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = & (const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(1) { .formats = SNDRV_PCM_FMTBIT_S24_3LE, .channels = 2, .iface = 1, @@ -960,9 +777,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, { - .ifnum = 2, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = & (const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(2) { .formats = SNDRV_PCM_FMTBIT_S24_3LE, .channels = 2, .iface = 2, @@ -977,28 +792,22 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, { - .ifnum = 3, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(3) { .out_cables = 0x0001, .in_cables = 0x0001 } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, { /* has ID 0x0028 when not in "Advanced Driver" mode */ USB_DEVICE(0x0582, 0x0027), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "EDIROL", .product_name = "SD-20", - .ifnum = 0, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(0) { .out_cables = 0x0003, .in_cables = 0x0007 } @@ -1007,12 +816,10 @@ YAMAHA_DEVICE(0x7010, "UB99"), { /* has ID 0x002a when not in "Advanced Driver" mode */ USB_DEVICE(0x0582, 0x0029), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "EDIROL", .product_name = "SD-80", - .ifnum = 0, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(0) { .out_cables = 0x000f, .in_cables = 0x000f } @@ -1025,39 +832,24 @@ YAMAHA_DEVICE(0x7010, "UB99"), * but offers only 16-bit PCM and no MIDI. */ USB_DEVICE_VENDOR_SPEC(0x0582, 0x002b), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "EDIROL", .product_name = "UA-700", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 1, - .type = QUIRK_AUDIO_EDIROL_UAXX - }, - { - .ifnum = 2, - .type = QUIRK_AUDIO_EDIROL_UAXX - }, - { - .ifnum = 3, - .type = QUIRK_AUDIO_EDIROL_UAXX - }, - { - .ifnum = -1 - } + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_EDIROL_UAXX(1) }, + { QUIRK_DATA_EDIROL_UAXX(2) }, + { QUIRK_DATA_EDIROL_UAXX(3) }, + QUIRK_COMPOSITE_END } } }, { /* has ID 0x002e when not in "Advanced Driver" mode */ USB_DEVICE(0x0582, 0x002d), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Roland", .product_name = "XV-2020", - .ifnum = 0, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(0) { .out_cables = 0x0001, .in_cables = 0x0001 } @@ -1066,12 +858,10 @@ YAMAHA_DEVICE(0x7010, "UB99"), { /* has ID 0x0030 when not in "Advanced Driver" mode */ USB_DEVICE(0x0582, 0x002f), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Roland", .product_name = "VariOS", - .ifnum = 0, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(0) { .out_cables = 0x0007, .in_cables = 0x0007 } @@ -1080,12 +870,10 @@ YAMAHA_DEVICE(0x7010, "UB99"), { /* has ID 0x0034 when not in "Advanced Driver" mode */ USB_DEVICE(0x0582, 0x0033), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "EDIROL", .product_name = "PCR", - .ifnum = 0, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(0) { .out_cables = 0x0003, .in_cables = 0x0007 } @@ -1097,12 +885,10 @@ YAMAHA_DEVICE(0x7010, "UB99"), * later revisions use IDs 0x0054 and 0x00a2. */ USB_DEVICE(0x0582, 0x0037), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Roland", .product_name = "Digital Piano", - .ifnum = 0, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(0) { .out_cables = 0x0001, .in_cables = 0x0001 } @@ -1115,39 +901,24 @@ YAMAHA_DEVICE(0x7010, "UB99"), * and no MIDI. */ USB_DEVICE_VENDOR_SPEC(0x0582, 0x003b), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "BOSS", .product_name = "GS-10", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = & (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 1, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 2, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 3, - .type = QUIRK_MIDI_STANDARD_INTERFACE - }, - { - .ifnum = -1 - } + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_STANDARD_AUDIO(1) }, + { QUIRK_DATA_STANDARD_AUDIO(2) }, + { QUIRK_DATA_STANDARD_MIDI(3) }, + QUIRK_COMPOSITE_END } } }, { /* has ID 0x0041 when not in "Advanced Driver" mode */ USB_DEVICE(0x0582, 0x0040), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Roland", .product_name = "GI-20", - .ifnum = 0, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(0) { .out_cables = 0x0001, .in_cables = 0x0001 } @@ -1156,12 +927,10 @@ YAMAHA_DEVICE(0x7010, "UB99"), { /* has ID 0x0043 when not in "Advanced Driver" mode */ USB_DEVICE(0x0582, 0x0042), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Roland", .product_name = "RS-70", - .ifnum = 0, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(0) { .out_cables = 0x0001, .in_cables = 0x0001 } @@ -1170,36 +939,24 @@ YAMAHA_DEVICE(0x7010, "UB99"), { /* has ID 0x0049 when not in "Advanced Driver" mode */ USB_DEVICE(0x0582, 0x0047), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { /* .vendor_name = "EDIROL", */ /* .product_name = "UR-80", */ - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { + QUIRK_DATA_COMPOSITE { /* in the 96 kHz modes, only interface 1 is there */ - { - .ifnum = 1, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 2, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = -1 - } + { QUIRK_DATA_STANDARD_AUDIO(1) }, + { QUIRK_DATA_STANDARD_AUDIO(2) }, + QUIRK_COMPOSITE_END } } }, { /* has ID 0x004a when not in "Advanced Driver" mode */ USB_DEVICE(0x0582, 0x0048), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { /* .vendor_name = "EDIROL", */ /* .product_name = "UR-80", */ - .ifnum = 0, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(0) { .out_cables = 0x0003, .in_cables = 0x0007 } @@ -1208,35 +965,23 @@ YAMAHA_DEVICE(0x7010, "UB99"), { /* has ID 0x004e when not in "Advanced Driver" mode */ USB_DEVICE(0x0582, 0x004c), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "EDIROL", .product_name = "PCR-A", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 1, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 2, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = -1 - } + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_STANDARD_AUDIO(1) }, + { QUIRK_DATA_STANDARD_AUDIO(2) }, + QUIRK_COMPOSITE_END } } }, { /* has ID 0x004f when not in "Advanced Driver" mode */ USB_DEVICE(0x0582, 0x004d), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "EDIROL", .product_name = "PCR-A", - .ifnum = 0, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(0) { .out_cables = 0x0003, .in_cables = 0x0007 } @@ -1248,76 +993,52 @@ YAMAHA_DEVICE(0x7010, "UB99"), * is standard compliant, but has only 16-bit PCM. */ USB_DEVICE(0x0582, 0x0050), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "EDIROL", .product_name = "UA-3FX", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 1, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 2, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = -1 - } + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_STANDARD_AUDIO(1) }, + { QUIRK_DATA_STANDARD_AUDIO(2) }, + QUIRK_COMPOSITE_END } } }, { USB_DEVICE(0x0582, 0x0052), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "EDIROL", .product_name = "UM-1SX", - .ifnum = 0, - .type = QUIRK_MIDI_STANDARD_INTERFACE + QUIRK_DATA_STANDARD_MIDI(0) } }, { USB_DEVICE(0x0582, 0x0060), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Roland", .product_name = "EXR Series", - .ifnum = 0, - .type = QUIRK_MIDI_STANDARD_INTERFACE + QUIRK_DATA_STANDARD_MIDI(0) } }, { /* has ID 0x0066 when not in "Advanced Driver" mode */ USB_DEVICE(0x0582, 0x0064), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { /* .vendor_name = "EDIROL", */ /* .product_name = "PCR-1", */ - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 1, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 2, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = -1 - } + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_STANDARD_AUDIO(1) }, + { QUIRK_DATA_STANDARD_AUDIO(2) }, + QUIRK_COMPOSITE_END } } }, { /* has ID 0x0067 when not in "Advanced Driver" mode */ USB_DEVICE(0x0582, 0x0065), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { /* .vendor_name = "EDIROL", */ /* .product_name = "PCR-1", */ - .ifnum = 0, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(0) { .out_cables = 0x0001, .in_cables = 0x0003 } @@ -1326,12 +1047,10 @@ YAMAHA_DEVICE(0x7010, "UB99"), { /* has ID 0x006e when not in "Advanced Driver" mode */ USB_DEVICE(0x0582, 0x006d), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Roland", .product_name = "FANTOM-X", - .ifnum = 0, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(0) { .out_cables = 0x0001, .in_cables = 0x0001 } @@ -1344,39 +1063,24 @@ YAMAHA_DEVICE(0x7010, "UB99"), * offers only 16-bit PCM at 44.1 kHz and no MIDI. */ USB_DEVICE_VENDOR_SPEC(0x0582, 0x0074), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "EDIROL", .product_name = "UA-25", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 0, - .type = QUIRK_AUDIO_EDIROL_UAXX - }, - { - .ifnum = 1, - .type = QUIRK_AUDIO_EDIROL_UAXX - }, - { - .ifnum = 2, - .type = QUIRK_AUDIO_EDIROL_UAXX - }, - { - .ifnum = -1 - } + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_EDIROL_UAXX(0) }, + { QUIRK_DATA_EDIROL_UAXX(1) }, + { QUIRK_DATA_EDIROL_UAXX(2) }, + QUIRK_COMPOSITE_END } } }, { /* has ID 0x0076 when not in "Advanced Driver" mode */ USB_DEVICE(0x0582, 0x0075), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "BOSS", .product_name = "DR-880", - .ifnum = 0, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(0) { .out_cables = 0x0001, .in_cables = 0x0001 } @@ -1385,12 +1089,10 @@ YAMAHA_DEVICE(0x7010, "UB99"), { /* has ID 0x007b when not in "Advanced Driver" mode */ USB_DEVICE_VENDOR_SPEC(0x0582, 0x007a), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Roland", /* "RD" or "RD-700SX"? */ - .ifnum = 0, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(0) { .out_cables = 0x0003, .in_cables = 0x0003 } @@ -1399,12 +1101,10 @@ YAMAHA_DEVICE(0x7010, "UB99"), { /* has ID 0x0081 when not in "Advanced Driver" mode */ USB_DEVICE(0x0582, 0x0080), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Roland", .product_name = "G-70", - .ifnum = 0, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(0) { .out_cables = 0x0001, .in_cables = 0x0001 } @@ -1413,12 +1113,10 @@ YAMAHA_DEVICE(0x7010, "UB99"), { /* has ID 0x008c when not in "Advanced Driver" mode */ USB_DEVICE(0x0582, 0x008b), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "EDIROL", .product_name = "PC-50", - .ifnum = 0, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(0) { .out_cables = 0x0001, .in_cables = 0x0001 } @@ -1430,56 +1128,31 @@ YAMAHA_DEVICE(0x7010, "UB99"), * is standard compliant, but has only 16-bit PCM and no MIDI. */ USB_DEVICE(0x0582, 0x00a3), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "EDIROL", .product_name = "UA-4FX", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 0, - .type = QUIRK_AUDIO_EDIROL_UAXX - }, - { - .ifnum = 1, - .type = QUIRK_AUDIO_EDIROL_UAXX - }, - { - .ifnum = 2, - .type = QUIRK_AUDIO_EDIROL_UAXX - }, - { - .ifnum = -1 - } + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_EDIROL_UAXX(0) }, + { QUIRK_DATA_EDIROL_UAXX(1) }, + { QUIRK_DATA_EDIROL_UAXX(2) }, + QUIRK_COMPOSITE_END } } }, { /* Edirol M-16DX */ USB_DEVICE(0x0582, 0x00c4), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { + QUIRK_DRIVER_INFO { + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_STANDARD_AUDIO(0) }, + { QUIRK_DATA_STANDARD_AUDIO(1) }, { - .ifnum = 0, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 1, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 2, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(2) { .out_cables = 0x0001, .in_cables = 0x0001 } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, @@ -1489,37 +1162,22 @@ YAMAHA_DEVICE(0x7010, "UB99"), * offers only 16-bit PCM at 44.1 kHz and no MIDI. */ USB_DEVICE_VENDOR_SPEC(0x0582, 0x00e6), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "EDIROL", .product_name = "UA-25EX", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 0, - .type = QUIRK_AUDIO_EDIROL_UAXX - }, - { - .ifnum = 1, - .type = QUIRK_AUDIO_EDIROL_UAXX - }, - { - .ifnum = 2, - .type = QUIRK_AUDIO_EDIROL_UAXX - }, - { - .ifnum = -1 - } + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_EDIROL_UAXX(0) }, + { QUIRK_DATA_EDIROL_UAXX(1) }, + { QUIRK_DATA_EDIROL_UAXX(2) }, + QUIRK_COMPOSITE_END } } }, { /* Edirol UM-3G */ USB_DEVICE_VENDOR_SPEC(0x0582, 0x0108), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .ifnum = 0, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DRIVER_INFO { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(0) { .out_cables = 0x0007, .in_cables = 0x0007 } @@ -1528,45 +1186,29 @@ YAMAHA_DEVICE(0x7010, "UB99"), { /* BOSS ME-25 */ USB_DEVICE(0x0582, 0x0113), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 0, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, + QUIRK_DRIVER_INFO { + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_STANDARD_AUDIO(0) }, + { QUIRK_DATA_STANDARD_AUDIO(1) }, { - .ifnum = 1, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 2, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(2) { .out_cables = 0x0001, .in_cables = 0x0001 } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, { /* only 44.1 kHz works at the moment */ USB_DEVICE(0x0582, 0x0120), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { /* .vendor_name = "Roland", */ /* .product_name = "OCTO-CAPTURE", */ - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { + QUIRK_DATA_COMPOSITE { { - .ifnum = 0, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = & (const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(0) { .formats = SNDRV_PCM_FMTBIT_S32_LE, .channels = 10, .iface = 0, @@ -1582,9 +1224,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, { - .ifnum = 1, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = & (const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(1) { .formats = SNDRV_PCM_FMTBIT_S32_LE, .channels = 12, .iface = 1, @@ -1600,40 +1240,26 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, { - .ifnum = 2, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(2) { .out_cables = 0x0001, .in_cables = 0x0001 } }, - { - .ifnum = 3, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = 4, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = -1 - } + { QUIRK_DATA_IGNORE(3) }, + { QUIRK_DATA_IGNORE(4) }, + QUIRK_COMPOSITE_END } } }, { /* only 44.1 kHz works at the moment */ USB_DEVICE(0x0582, 0x012f), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { /* .vendor_name = "Roland", */ /* .product_name = "QUAD-CAPTURE", */ - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { + QUIRK_DATA_COMPOSITE { { - .ifnum = 0, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = & (const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(0) { .formats = SNDRV_PCM_FMTBIT_S32_LE, .channels = 4, .iface = 0, @@ -1649,9 +1275,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, { - .ifnum = 1, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = & (const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(1) { .formats = SNDRV_PCM_FMTBIT_S32_LE, .channels = 6, .iface = 1, @@ -1667,54 +1291,32 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, { - .ifnum = 2, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(2) { .out_cables = 0x0001, .in_cables = 0x0001 } }, - { - .ifnum = 3, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = 4, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = -1 - } + { QUIRK_DATA_IGNORE(3) }, + { QUIRK_DATA_IGNORE(4) }, + QUIRK_COMPOSITE_END } } }, -{ - USB_DEVICE(0x0582, 0x0159), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - /* .vendor_name = "Roland", */ - /* .product_name = "UA-22", */ - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 0, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 1, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, +{ + USB_DEVICE(0x0582, 0x0159), + QUIRK_DRIVER_INFO { + /* .vendor_name = "Roland", */ + /* .product_name = "UA-22", */ + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_STANDARD_AUDIO(0) }, + { QUIRK_DATA_STANDARD_AUDIO(1) }, { - .ifnum = 2, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(2) { .out_cables = 0x0001, .in_cables = 0x0001 } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, @@ -1722,19 +1324,19 @@ YAMAHA_DEVICE(0x7010, "UB99"), /* UA101 and co are supported by another driver */ { USB_DEVICE(0x0582, 0x0044), /* UA-1000 high speed */ - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .ifnum = QUIRK_NODEV_INTERFACE }, }, { USB_DEVICE(0x0582, 0x007d), /* UA-101 high speed */ - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .ifnum = QUIRK_NODEV_INTERFACE }, }, { USB_DEVICE(0x0582, 0x008d), /* UA-101 full speed */ - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .ifnum = QUIRK_NODEV_INTERFACE }, }, @@ -1745,7 +1347,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), USB_DEVICE_ID_MATCH_INT_CLASS, .idVendor = 0x0582, .bInterfaceClass = USB_CLASS_VENDOR_SPEC, - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .ifnum = QUIRK_ANY_INTERFACE, .type = QUIRK_AUTODETECT } @@ -1760,12 +1362,10 @@ YAMAHA_DEVICE(0x7010, "UB99"), * compliant USB MIDI ports for external MIDI and controls. */ USB_DEVICE_VENDOR_SPEC(0x06f8, 0xb000), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Hercules", .product_name = "DJ Console (WE)", - .ifnum = 4, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(4) { .out_cables = 0x0001, .in_cables = 0x0001 } @@ -1775,12 +1375,10 @@ YAMAHA_DEVICE(0x7010, "UB99"), /* Midiman/M-Audio devices */ { USB_DEVICE_VENDOR_SPEC(0x0763, 0x1002), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "M-Audio", .product_name = "MidiSport 2x2", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_MIDI_MIDIMAN, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_MIDIMAN(QUIRK_ANY_INTERFACE) { .out_cables = 0x0003, .in_cables = 0x0003 } @@ -1788,12 +1386,10 @@ YAMAHA_DEVICE(0x7010, "UB99"), }, { USB_DEVICE_VENDOR_SPEC(0x0763, 0x1011), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "M-Audio", .product_name = "MidiSport 1x1", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_MIDI_MIDIMAN, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_MIDIMAN(QUIRK_ANY_INTERFACE) { .out_cables = 0x0001, .in_cables = 0x0001 } @@ -1801,12 +1397,10 @@ YAMAHA_DEVICE(0x7010, "UB99"), }, { USB_DEVICE_VENDOR_SPEC(0x0763, 0x1015), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "M-Audio", .product_name = "Keystation", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_MIDI_MIDIMAN, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_MIDIMAN(QUIRK_ANY_INTERFACE) { .out_cables = 0x0001, .in_cables = 0x0001 } @@ -1814,12 +1408,10 @@ YAMAHA_DEVICE(0x7010, "UB99"), }, { USB_DEVICE_VENDOR_SPEC(0x0763, 0x1021), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "M-Audio", .product_name = "MidiSport 4x4", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_MIDI_MIDIMAN, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_MIDIMAN(QUIRK_ANY_INTERFACE) { .out_cables = 0x000f, .in_cables = 0x000f } @@ -1832,12 +1424,10 @@ YAMAHA_DEVICE(0x7010, "UB99"), * Thanks to Olaf Giesbrecht */ USB_DEVICE_VER(0x0763, 0x1031, 0x0100, 0x0109), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "M-Audio", .product_name = "MidiSport 8x8", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_MIDI_MIDIMAN, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_MIDIMAN(QUIRK_ANY_INTERFACE) { .out_cables = 0x01ff, .in_cables = 0x01ff } @@ -1845,12 +1435,10 @@ YAMAHA_DEVICE(0x7010, "UB99"), }, { USB_DEVICE_VENDOR_SPEC(0x0763, 0x1033), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "M-Audio", .product_name = "MidiSport 8x8", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_MIDI_MIDIMAN, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_MIDIMAN(QUIRK_ANY_INTERFACE) { .out_cables = 0x01ff, .in_cables = 0x01ff } @@ -1858,12 +1446,10 @@ YAMAHA_DEVICE(0x7010, "UB99"), }, { USB_DEVICE_VENDOR_SPEC(0x0763, 0x1041), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "M-Audio", .product_name = "MidiSport 2x4", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_MIDI_MIDIMAN, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_MIDIMAN(QUIRK_ANY_INTERFACE) { .out_cables = 0x000f, .in_cables = 0x0003 } @@ -1871,76 +1457,41 @@ YAMAHA_DEVICE(0x7010, "UB99"), }, { USB_DEVICE_VENDOR_SPEC(0x0763, 0x2001), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "M-Audio", .product_name = "Quattro", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = & (const struct snd_usb_audio_quirk[]) { + QUIRK_DATA_COMPOSITE { /* * Interfaces 0-2 are "Windows-compatible", 16-bit only, * and share endpoints with the other interfaces. * Ignore them. The other interfaces can do 24 bits, * but captured samples are big-endian (see usbaudio.c). */ - { - .ifnum = 0, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = 1, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = 2, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = 3, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = 4, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 5, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 6, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = 7, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 8, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 9, - .type = QUIRK_MIDI_MIDIMAN, - .data = & (const struct snd_usb_midi_endpoint_info) { + { QUIRK_DATA_IGNORE(0) }, + { QUIRK_DATA_IGNORE(1) }, + { QUIRK_DATA_IGNORE(2) }, + { QUIRK_DATA_IGNORE(3) }, + { QUIRK_DATA_STANDARD_AUDIO(4) }, + { QUIRK_DATA_STANDARD_AUDIO(5) }, + { QUIRK_DATA_IGNORE(6) }, + { QUIRK_DATA_STANDARD_AUDIO(7) }, + { QUIRK_DATA_STANDARD_AUDIO(8) }, + { + QUIRK_DATA_MIDI_MIDIMAN(9) { .out_cables = 0x0001, .in_cables = 0x0001 } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, { USB_DEVICE_VENDOR_SPEC(0x0763, 0x2003), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "M-Audio", .product_name = "AudioPhile", - .ifnum = 6, - .type = QUIRK_MIDI_MIDIMAN, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_MIDIMAN(6) { .out_cables = 0x0001, .in_cables = 0x0001 } @@ -1948,12 +1499,10 @@ YAMAHA_DEVICE(0x7010, "UB99"), }, { USB_DEVICE_VENDOR_SPEC(0x0763, 0x2008), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "M-Audio", .product_name = "Ozone", - .ifnum = 3, - .type = QUIRK_MIDI_MIDIMAN, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_MIDIMAN(3) { .out_cables = 0x0001, .in_cables = 0x0001 } @@ -1961,93 +1510,45 @@ YAMAHA_DEVICE(0x7010, "UB99"), }, { USB_DEVICE_VENDOR_SPEC(0x0763, 0x200d), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "M-Audio", .product_name = "OmniStudio", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = & (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 0, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = 1, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = 2, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = 3, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = 4, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 5, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 6, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = 7, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 8, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 9, - .type = QUIRK_MIDI_MIDIMAN, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_IGNORE(0) }, + { QUIRK_DATA_IGNORE(1) }, + { QUIRK_DATA_IGNORE(2) }, + { QUIRK_DATA_IGNORE(3) }, + { QUIRK_DATA_STANDARD_AUDIO(4) }, + { QUIRK_DATA_STANDARD_AUDIO(5) }, + { QUIRK_DATA_IGNORE(6) }, + { QUIRK_DATA_STANDARD_AUDIO(7) }, + { QUIRK_DATA_STANDARD_AUDIO(8) }, + { + QUIRK_DATA_MIDI_MIDIMAN(9) { .out_cables = 0x0001, .in_cables = 0x0001 } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, { USB_DEVICE(0x0763, 0x2019), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { /* .vendor_name = "M-Audio", */ /* .product_name = "Ozone Academic", */ - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = & (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 0, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 1, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 2, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_STANDARD_AUDIO(0) }, + { QUIRK_DATA_STANDARD_AUDIO(1) }, + { QUIRK_DATA_STANDARD_AUDIO(2) }, { - .ifnum = 3, - .type = QUIRK_MIDI_MIDIMAN, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_MIDIMAN(3) { .out_cables = 0x0001, .in_cables = 0x0001 } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, @@ -2057,21 +1558,14 @@ YAMAHA_DEVICE(0x7010, "UB99"), }, { USB_DEVICE_VENDOR_SPEC(0x0763, 0x2030), - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { /* .vendor_name = "M-Audio", */ /* .product_name = "Fast Track C400", */ - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = &(const struct snd_usb_audio_quirk[]) { - { - .ifnum = 1, - .type = QUIRK_AUDIO_STANDARD_MIXER, - }, + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_STANDARD_MIXER(1) }, /* Playback */ { - .ifnum = 2, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(2) { .formats = SNDRV_PCM_FMTBIT_S24_3LE, .channels = 6, .iface = 2, @@ -2095,9 +1589,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), }, /* Capture */ { - .ifnum = 3, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(3) { .formats = SNDRV_PCM_FMTBIT_S24_3LE, .channels = 4, .iface = 3, @@ -2119,30 +1611,21 @@ YAMAHA_DEVICE(0x7010, "UB99"), .clock = 0x80, } }, - /* MIDI */ - { - .ifnum = -1 /* Interface = 4 */ - } + /* MIDI: Interface = 4*/ + QUIRK_COMPOSITE_END } } }, { USB_DEVICE_VENDOR_SPEC(0x0763, 0x2031), - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { /* .vendor_name = "M-Audio", */ /* .product_name = "Fast Track C600", */ - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = &(const struct snd_usb_audio_quirk[]) { - { - .ifnum = 1, - .type = QUIRK_AUDIO_STANDARD_MIXER, - }, + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_STANDARD_MIXER(1) }, /* Playback */ { - .ifnum = 2, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(2) { .formats = SNDRV_PCM_FMTBIT_S24_3LE, .channels = 8, .iface = 2, @@ -2166,9 +1649,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), }, /* Capture */ { - .ifnum = 3, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(3) { .formats = SNDRV_PCM_FMTBIT_S24_3LE, .channels = 6, .iface = 3, @@ -2190,29 +1671,20 @@ YAMAHA_DEVICE(0x7010, "UB99"), .clock = 0x80, } }, - /* MIDI */ - { - .ifnum = -1 /* Interface = 4 */ - } + /* MIDI: Interface = 4 */ + QUIRK_COMPOSITE_END } } }, { USB_DEVICE_VENDOR_SPEC(0x0763, 0x2080), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { /* .vendor_name = "M-Audio", */ /* .product_name = "Fast Track Ultra", */ - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = & (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 0, - .type = QUIRK_AUDIO_STANDARD_MIXER, - }, + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_STANDARD_MIXER(0) }, { - .ifnum = 1, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = & (const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(1) { .formats = SNDRV_PCM_FMTBIT_S24_3LE, .channels = 8, .iface = 1, @@ -2234,9 +1706,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, { - .ifnum = 2, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = & (const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(2) { .formats = SNDRV_PCM_FMTBIT_S24_3LE, .channels = 8, .iface = 2, @@ -2258,28 +1728,19 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, /* interface 3 (MIDI) is standard compliant */ - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, { USB_DEVICE_VENDOR_SPEC(0x0763, 0x2081), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { /* .vendor_name = "M-Audio", */ /* .product_name = "Fast Track Ultra 8R", */ - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = & (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 0, - .type = QUIRK_AUDIO_STANDARD_MIXER, - }, + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_STANDARD_MIXER(0) }, { - .ifnum = 1, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = & (const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(1) { .formats = SNDRV_PCM_FMTBIT_S24_3LE, .channels = 8, .iface = 1, @@ -2301,9 +1762,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, { - .ifnum = 2, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = & (const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(2) { .formats = SNDRV_PCM_FMTBIT_S24_3LE, .channels = 8, .iface = 2, @@ -2325,9 +1784,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, /* interface 3 (MIDI) is standard compliant */ - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, @@ -2335,21 +1792,19 @@ YAMAHA_DEVICE(0x7010, "UB99"), /* Casio devices */ { USB_DEVICE(0x07cf, 0x6801), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Casio", .product_name = "PL-40R", - .ifnum = 0, - .type = QUIRK_MIDI_YAMAHA + QUIRK_DATA_MIDI_YAMAHA(0) } }, { /* this ID is used by several devices without a product ID */ USB_DEVICE(0x07cf, 0x6802), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Casio", .product_name = "Keyboard", - .ifnum = 0, - .type = QUIRK_MIDI_YAMAHA + QUIRK_DATA_MIDI_YAMAHA(0) } }, @@ -2362,23 +1817,13 @@ YAMAHA_DEVICE(0x7010, "UB99"), .idVendor = 0x07fd, .idProduct = 0x0001, .bDeviceSubClass = 2, - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "MOTU", .product_name = "Fastlane", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = & (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 0, - .type = QUIRK_MIDI_RAW_BYTES - }, - { - .ifnum = 1, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = -1 - } + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_RAW_BYTES(0) }, + { QUIRK_DATA_IGNORE(1) }, + QUIRK_COMPOSITE_END } } }, @@ -2386,12 +1831,10 @@ YAMAHA_DEVICE(0x7010, "UB99"), /* Emagic devices */ { USB_DEVICE(0x086a, 0x0001), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Emagic", .product_name = "Unitor8", - .ifnum = 2, - .type = QUIRK_MIDI_EMAGIC, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_EMAGIC(2) { .out_cables = 0x80ff, .in_cables = 0x80ff } @@ -2399,12 +1842,10 @@ YAMAHA_DEVICE(0x7010, "UB99"), }, { USB_DEVICE(0x086a, 0x0002), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Emagic", /* .product_name = "AMT8", */ - .ifnum = 2, - .type = QUIRK_MIDI_EMAGIC, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_EMAGIC(2) { .out_cables = 0x80ff, .in_cables = 0x80ff } @@ -2412,12 +1853,10 @@ YAMAHA_DEVICE(0x7010, "UB99"), }, { USB_DEVICE(0x086a, 0x0003), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Emagic", /* .product_name = "MT4", */ - .ifnum = 2, - .type = QUIRK_MIDI_EMAGIC, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_EMAGIC(2) { .out_cables = 0x800f, .in_cables = 0x8003 } @@ -2427,38 +1866,35 @@ YAMAHA_DEVICE(0x7010, "UB99"), /* KORG devices */ { USB_DEVICE_VENDOR_SPEC(0x0944, 0x0200), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "KORG, Inc.", /* .product_name = "PANDORA PX5D", */ - .ifnum = 3, - .type = QUIRK_MIDI_STANDARD_INTERFACE, + QUIRK_DATA_STANDARD_MIDI(3) } }, { USB_DEVICE_VENDOR_SPEC(0x0944, 0x0201), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "KORG, Inc.", /* .product_name = "ToneLab ST", */ - .ifnum = 3, - .type = QUIRK_MIDI_STANDARD_INTERFACE, + QUIRK_DATA_STANDARD_MIDI(3) } }, { USB_DEVICE_VENDOR_SPEC(0x0944, 0x0204), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "KORG, Inc.", /* .product_name = "ToneLab EX", */ - .ifnum = 3, - .type = QUIRK_MIDI_STANDARD_INTERFACE, + QUIRK_DATA_STANDARD_MIDI(3) } }, /* AKAI devices */ { USB_DEVICE(0x09e8, 0x0062), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "AKAI", .product_name = "MPD16", .ifnum = 0, @@ -2469,21 +1905,11 @@ YAMAHA_DEVICE(0x7010, "UB99"), { /* Akai MPC Element */ USB_DEVICE(0x09e8, 0x0021), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = & (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 0, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = 1, - .type = QUIRK_MIDI_STANDARD_INTERFACE - }, - { - .ifnum = -1 - } + QUIRK_DRIVER_INFO { + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_IGNORE(0) }, + { QUIRK_DATA_STANDARD_MIDI(1) }, + QUIRK_COMPOSITE_END } } }, @@ -2492,66 +1918,36 @@ YAMAHA_DEVICE(0x7010, "UB99"), { /* Steinberg MI2 */ USB_DEVICE_VENDOR_SPEC(0x0a4e, 0x2040), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = & (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 0, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 1, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 2, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, + QUIRK_DRIVER_INFO { + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_STANDARD_AUDIO(0) }, + { QUIRK_DATA_STANDARD_AUDIO(1) }, + { QUIRK_DATA_STANDARD_AUDIO(2) }, { - .ifnum = 3, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = &(const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(3) { .out_cables = 0x0001, .in_cables = 0x0001 } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, { /* Steinberg MI4 */ USB_DEVICE_VENDOR_SPEC(0x0a4e, 0x4040), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = & (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 0, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 1, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 2, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, + QUIRK_DRIVER_INFO { + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_STANDARD_AUDIO(0) }, + { QUIRK_DATA_STANDARD_AUDIO(1) }, + { QUIRK_DATA_STANDARD_AUDIO(2) }, { - .ifnum = 3, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = &(const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(3) { .out_cables = 0x0001, .in_cables = 0x0001 } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, @@ -2559,34 +1955,31 @@ YAMAHA_DEVICE(0x7010, "UB99"), /* TerraTec devices */ { USB_DEVICE_VENDOR_SPEC(0x0ccd, 0x0012), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "TerraTec", .product_name = "PHASE 26", - .ifnum = 3, - .type = QUIRK_MIDI_STANDARD_INTERFACE + QUIRK_DATA_STANDARD_MIDI(3) } }, { USB_DEVICE_VENDOR_SPEC(0x0ccd, 0x0013), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "TerraTec", .product_name = "PHASE 26", - .ifnum = 3, - .type = QUIRK_MIDI_STANDARD_INTERFACE + QUIRK_DATA_STANDARD_MIDI(3) } }, { USB_DEVICE_VENDOR_SPEC(0x0ccd, 0x0014), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "TerraTec", .product_name = "PHASE 26", - .ifnum = 3, - .type = QUIRK_MIDI_STANDARD_INTERFACE + QUIRK_DATA_STANDARD_MIDI(3) } }, { USB_DEVICE(0x0ccd, 0x0035), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Miditech", .product_name = "Play'n Roll", .ifnum = 0, @@ -2594,10 +1987,14 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, +/* Stanton ScratchAmp */ +{ USB_DEVICE(0x103d, 0x0100) }, +{ USB_DEVICE(0x103d, 0x0101) }, + /* Novation EMS devices */ { USB_DEVICE_VENDOR_SPEC(0x1235, 0x0001), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Novation", .product_name = "ReMOTE Audio/XStation", .ifnum = 4, @@ -2606,7 +2003,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), }, { USB_DEVICE_VENDOR_SPEC(0x1235, 0x0002), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Novation", .product_name = "Speedio", .ifnum = 3, @@ -2615,38 +2012,29 @@ YAMAHA_DEVICE(0x7010, "UB99"), }, { USB_DEVICE(0x1235, 0x000a), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { /* .vendor_name = "Novation", */ /* .product_name = "Nocturn", */ - .ifnum = 0, - .type = QUIRK_MIDI_RAW_BYTES + QUIRK_DATA_RAW_BYTES(0) } }, { USB_DEVICE(0x1235, 0x000e), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { /* .vendor_name = "Novation", */ /* .product_name = "Launchpad", */ - .ifnum = 0, - .type = QUIRK_MIDI_RAW_BYTES + QUIRK_DATA_RAW_BYTES(0) } }, { USB_DEVICE(0x1235, 0x0010), - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Focusrite", .product_name = "Saffire 6 USB", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_STANDARD_MIXER(0) }, { - .ifnum = 0, - .type = QUIRK_AUDIO_STANDARD_MIXER, - }, - { - .ifnum = 0, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(0) { .formats = SNDRV_PCM_FMTBIT_S24_3LE, .channels = 4, .iface = 0, @@ -2673,9 +2061,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, { - .ifnum = 0, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(0) { .formats = SNDRV_PCM_FMTBIT_S24_3LE, .channels = 2, .iface = 0, @@ -2697,28 +2083,19 @@ YAMAHA_DEVICE(0x7010, "UB99"), } } }, - { - .ifnum = 1, - .type = QUIRK_MIDI_RAW_BYTES - }, - { - .ifnum = -1 - } + { QUIRK_DATA_RAW_BYTES(1) }, + QUIRK_COMPOSITE_END } } }, { USB_DEVICE(0x1235, 0x0018), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Novation", .product_name = "Twitch", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { + QUIRK_DATA_COMPOSITE { { - .ifnum = 0, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = & (const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(0) { .formats = SNDRV_PCM_FMTBIT_S24_3LE, .channels = 4, .iface = 0, @@ -2737,19 +2114,14 @@ YAMAHA_DEVICE(0x7010, "UB99"), } } }, - { - .ifnum = 1, - .type = QUIRK_MIDI_RAW_BYTES - }, - { - .ifnum = -1 - } + { QUIRK_DATA_RAW_BYTES(1) }, + QUIRK_COMPOSITE_END } } }, { USB_DEVICE_VENDOR_SPEC(0x1235, 0x4661), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Novation", .product_name = "ReMOTE25", .ifnum = 0, @@ -2761,25 +2133,16 @@ YAMAHA_DEVICE(0x7010, "UB99"), { /* VirusTI Desktop */ USB_DEVICE_VENDOR_SPEC(0x133e, 0x0815), - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = &(const struct snd_usb_audio_quirk[]) { + QUIRK_DRIVER_INFO { + QUIRK_DATA_COMPOSITE { { - .ifnum = 3, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = &(const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(3) { .out_cables = 0x0003, .in_cables = 0x0003 } }, - { - .ifnum = 4, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = -1 - } + { QUIRK_DATA_IGNORE(4) }, + QUIRK_COMPOSITE_END } } }, @@ -2807,7 +2170,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), /* QinHeng devices */ { USB_DEVICE(0x1a86, 0x752d), - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "QinHeng", .product_name = "CH345", .ifnum = 1, @@ -2821,7 +2184,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), /* Miditech devices */ { USB_DEVICE(0x4752, 0x0011), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Miditech", .product_name = "Midistart-2", .ifnum = 0, @@ -2833,7 +2196,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), { /* this ID used by both Miditech MidiStudio-2 and CME UF-x */ USB_DEVICE(0x7104, 0x2202), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .ifnum = 0, .type = QUIRK_MIDI_CME } @@ -2843,20 +2206,13 @@ YAMAHA_DEVICE(0x7010, "UB99"), { /* Thanks to Clemens Ladisch */ USB_DEVICE(0x0dba, 0x1000), - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Digidesign", .product_name = "MBox", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]){ - { - .ifnum = 0, - .type = QUIRK_AUDIO_STANDARD_MIXER, - }, + QUIRK_DATA_COMPOSITE{ + { QUIRK_DATA_STANDARD_MIXER(0) }, { - .ifnum = 1, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(1) { .formats = SNDRV_PCM_FMTBIT_S24_3BE, .channels = 2, .iface = 1, @@ -2877,9 +2233,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, { - .ifnum = 1, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(1) { .formats = SNDRV_PCM_FMTBIT_S24_3BE, .channels = 2, .iface = 1, @@ -2900,9 +2254,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), } } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, @@ -2910,24 +2262,14 @@ YAMAHA_DEVICE(0x7010, "UB99"), /* DIGIDESIGN MBOX 2 */ { USB_DEVICE(0x0dba, 0x3000), - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Digidesign", .product_name = "Mbox 2", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 0, - .type = QUIRK_IGNORE_INTERFACE - }, + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_IGNORE(0) }, + { QUIRK_DATA_IGNORE(1) }, { - .ifnum = 1, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = 2, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(2) { .formats = SNDRV_PCM_FMTBIT_S24_3BE, .channels = 2, .iface = 2, @@ -2945,15 +2287,10 @@ YAMAHA_DEVICE(0x7010, "UB99"), } } }, + { QUIRK_DATA_IGNORE(3) }, { - .ifnum = 3, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = 4, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { - .formats = SNDRV_PCM_FMTBIT_S24_3BE, + QUIRK_DATA_AUDIOFORMAT(4) { + .formats = SNDRV_PCM_FMTBIT_S24_3BE, .channels = 2, .iface = 4, .altsetting = 2, @@ -2970,14 +2307,9 @@ YAMAHA_DEVICE(0x7010, "UB99"), } } }, + { QUIRK_DATA_IGNORE(5) }, { - .ifnum = 5, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = 6, - .type = QUIRK_MIDI_MIDIMAN, - .data = &(const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_MIDIMAN(6) { .out_ep = 0x02, .out_cables = 0x0001, .in_ep = 0x81, @@ -2985,33 +2317,21 @@ YAMAHA_DEVICE(0x7010, "UB99"), .in_cables = 0x0001 } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, /* DIGIDESIGN MBOX 3 */ { USB_DEVICE(0x0dba, 0x5000), - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Digidesign", .product_name = "Mbox 3", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 0, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = 1, - .type = QUIRK_IGNORE_INTERFACE - }, + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_IGNORE(0) }, + { QUIRK_DATA_IGNORE(1) }, { - .ifnum = 2, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(2) { .formats = SNDRV_PCM_FMTBIT_S24_3LE, .fmt_bits = 24, .channels = 4, @@ -3038,9 +2358,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, { - .ifnum = 3, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(3) { .formats = SNDRV_PCM_FMTBIT_S24_3LE, .fmt_bits = 24, .channels = 4, @@ -3064,36 +2382,25 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, { - .ifnum = 4, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = &(const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(4) { .out_cables = 0x0001, .in_cables = 0x0001 } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, { /* Tascam US122 MKII - playback-only support */ USB_DEVICE_VENDOR_SPEC(0x0644, 0x8021), - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "TASCAM", .product_name = "US122 MKII", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 0, - .type = QUIRK_IGNORE_INTERFACE - }, + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_IGNORE(0) }, { - .ifnum = 1, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(1) { .formats = SNDRV_PCM_FMTBIT_S24_3LE, .channels = 2, .iface = 1, @@ -3114,9 +2421,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), } } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, @@ -3124,20 +2429,13 @@ YAMAHA_DEVICE(0x7010, "UB99"), /* Denon DN-X1600 */ { USB_AUDIO_DEVICE(0x154e, 0x500e), - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Denon", .product_name = "DN-X1600", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]){ - { - .ifnum = 0, - .type = QUIRK_IGNORE_INTERFACE, - }, + QUIRK_DATA_COMPOSITE{ + { QUIRK_DATA_IGNORE(0) }, { - .ifnum = 1, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(1) { .formats = SNDRV_PCM_FMTBIT_S24_3LE, .channels = 8, .iface = 1, @@ -3158,9 +2456,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, { - .ifnum = 2, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(2) { .formats = SNDRV_PCM_FMTBIT_S24_3LE, .channels = 8, .iface = 2, @@ -3180,13 +2476,8 @@ YAMAHA_DEVICE(0x7010, "UB99"), } } }, - { - .ifnum = 4, - .type = QUIRK_MIDI_STANDARD_INTERFACE, - }, - { - .ifnum = -1 - } + { QUIRK_DATA_STANDARD_MIDI(4) }, + QUIRK_COMPOSITE_END } } }, @@ -3195,17 +2486,13 @@ YAMAHA_DEVICE(0x7010, "UB99"), { USB_DEVICE(0x045e, 0x0283), .bInterfaceClass = USB_CLASS_PER_INTERFACE, - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Microsoft", .product_name = "XboxLive Headset/Xbox Communicator", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = &(const struct snd_usb_audio_quirk[]) { + QUIRK_DATA_COMPOSITE { { /* playback */ - .ifnum = 0, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(0) { .formats = SNDRV_PCM_FMTBIT_S16_LE, .channels = 1, .iface = 0, @@ -3221,9 +2508,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), }, { /* capture */ - .ifnum = 1, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(1) { .formats = SNDRV_PCM_FMTBIT_S16_LE, .channels = 1, .iface = 1, @@ -3237,9 +2522,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), .rate_max = 16000 } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, @@ -3248,18 +2531,11 @@ YAMAHA_DEVICE(0x7010, "UB99"), { USB_DEVICE(0x200c, 0x100b), .bInterfaceClass = USB_CLASS_PER_INTERFACE, - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = &(const struct snd_usb_audio_quirk[]) { - { - .ifnum = 0, - .type = QUIRK_AUDIO_STANDARD_MIXER, - }, + QUIRK_DRIVER_INFO { + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_STANDARD_MIXER(0) }, { - .ifnum = 1, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(1) { .formats = SNDRV_PCM_FMTBIT_S24_3LE, .channels = 4, .iface = 1, @@ -3278,9 +2554,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), } } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, @@ -3293,28 +2567,12 @@ YAMAHA_DEVICE(0x7010, "UB99"), * enabled in create_standard_audio_quirk(). */ USB_DEVICE(0x1686, 0x00dd), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { - { - /* Playback */ - .ifnum = 1, - .type = QUIRK_AUDIO_STANDARD_INTERFACE, - }, - { - /* Capture */ - .ifnum = 2, - .type = QUIRK_AUDIO_STANDARD_INTERFACE, - }, - { - /* Midi */ - .ifnum = 3, - .type = QUIRK_MIDI_STANDARD_INTERFACE - }, - { - .ifnum = -1 - }, + QUIRK_DRIVER_INFO { + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_STANDARD_AUDIO(1) }, /* Playback */ + { QUIRK_DATA_STANDARD_AUDIO(2) }, /* Capture */ + { QUIRK_DATA_STANDARD_MIDI(3) }, /* Midi */ + QUIRK_COMPOSITE_END } } }, @@ -3328,18 +2586,16 @@ YAMAHA_DEVICE(0x7010, "UB99"), USB_DEVICE_ID_MATCH_INT_SUBCLASS, .bInterfaceClass = USB_CLASS_AUDIO, .bInterfaceSubClass = USB_SUBCLASS_MIDISTREAMING, - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_MIDI_STANDARD_INTERFACE + QUIRK_DRIVER_INFO { + QUIRK_DATA_STANDARD_MIDI(QUIRK_ANY_INTERFACE) } }, /* Rane SL-1 */ { USB_DEVICE(0x13e5, 0x0001), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_AUDIO_STANDARD_INTERFACE + QUIRK_DRIVER_INFO { + QUIRK_DATA_STANDARD_AUDIO(QUIRK_ANY_INTERFACE) } }, @@ -3355,24 +2611,13 @@ YAMAHA_DEVICE(0x7010, "UB99"), * and only the 48 kHz sample rate works for the playback interface. */ USB_DEVICE(0x0a12, 0x1243), - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 0, - .type = QUIRK_AUDIO_STANDARD_MIXER, - }, - /* Capture */ - { - .ifnum = 1, - .type = QUIRK_IGNORE_INTERFACE, - }, + QUIRK_DRIVER_INFO { + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_STANDARD_MIXER(0) }, + { QUIRK_DATA_IGNORE(1) }, /* Capture */ /* Playback */ { - .ifnum = 2, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(2) { .formats = SNDRV_PCM_FMTBIT_S16_LE, .channels = 2, .iface = 2, @@ -3391,9 +2636,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), } } }, - { - .ifnum = -1 - }, + QUIRK_COMPOSITE_END } } }, @@ -3406,19 +2649,12 @@ YAMAHA_DEVICE(0x7010, "UB99"), * even on windows. */ USB_DEVICE(0x19b5, 0x0021), - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 0, - .type = QUIRK_AUDIO_STANDARD_MIXER, - }, + QUIRK_DRIVER_INFO { + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_STANDARD_MIXER(0) }, /* Playback */ { - .ifnum = 1, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(1) { .formats = SNDRV_PCM_FMTBIT_S16_LE, .channels = 2, .iface = 1, @@ -3437,29 +2673,20 @@ YAMAHA_DEVICE(0x7010, "UB99"), } } }, - { - .ifnum = -1 - }, + QUIRK_COMPOSITE_END } } }, /* MOTU Microbook II */ { USB_DEVICE_VENDOR_SPEC(0x07fd, 0x0004), - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "MOTU", .product_name = "MicroBookII", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 0, - .type = QUIRK_AUDIO_STANDARD_MIXER, - }, + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_STANDARD_MIXER(0) }, { - .ifnum = 0, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(0) { .formats = SNDRV_PCM_FMTBIT_S24_3BE, .channels = 6, .iface = 0, @@ -3480,9 +2707,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, { - .ifnum = 0, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(0) { .formats = SNDRV_PCM_FMTBIT_S24_3BE, .channels = 8, .iface = 0, @@ -3503,9 +2728,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), } } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, @@ -3517,14 +2740,10 @@ YAMAHA_DEVICE(0x7010, "UB99"), * The feedback for the output is the input. */ USB_DEVICE_VENDOR_SPEC(0x2b73, 0x0023), - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { + QUIRK_DRIVER_INFO { + QUIRK_DATA_COMPOSITE { { - .ifnum = 0, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(0) { .formats = SNDRV_PCM_FMTBIT_S32_LE, .channels = 12, .iface = 0, @@ -3541,9 +2760,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, { - .ifnum = 0, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(0) { .formats = SNDRV_PCM_FMTBIT_S32_LE, .channels = 10, .iface = 0, @@ -3561,9 +2778,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), .rate_table = (unsigned int[]) { 44100 } } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, @@ -3606,14 +2821,10 @@ YAMAHA_DEVICE(0x7010, "UB99"), * but not for DVS (Digital Vinyl Systems) like in Mixxx. */ USB_DEVICE_VENDOR_SPEC(0x2b73, 0x0017), - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { + QUIRK_DRIVER_INFO { + QUIRK_DATA_COMPOSITE { { - .ifnum = 0, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(0) { .formats = SNDRV_PCM_FMTBIT_S24_3LE, .channels = 8, // outputs .iface = 0, @@ -3630,9 +2841,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, { - .ifnum = 0, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(0) { .formats = SNDRV_PCM_FMTBIT_S24_3LE, .channels = 8, // inputs .iface = 0, @@ -3650,9 +2859,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), .rate_table = (unsigned int[]) { 48000 } } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, @@ -3663,14 +2870,10 @@ YAMAHA_DEVICE(0x7010, "UB99"), * The feedback for the output is the dummy input. */ USB_DEVICE_VENDOR_SPEC(0x2b73, 0x000e), - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { + QUIRK_DRIVER_INFO { + QUIRK_DATA_COMPOSITE { { - .ifnum = 0, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(0) { .formats = SNDRV_PCM_FMTBIT_S24_3LE, .channels = 4, .iface = 0, @@ -3687,9 +2890,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, { - .ifnum = 0, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(0) { .formats = SNDRV_PCM_FMTBIT_S24_3LE, .channels = 2, .iface = 0, @@ -3707,9 +2908,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), .rate_table = (unsigned int[]) { 44100 } } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, @@ -3720,14 +2919,10 @@ YAMAHA_DEVICE(0x7010, "UB99"), * PCM is 6 channels out & 4 channels in @ 44.1 fixed */ USB_DEVICE_VENDOR_SPEC(0x2b73, 0x000d), - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { + QUIRK_DRIVER_INFO { + QUIRK_DATA_COMPOSITE { { - .ifnum = 0, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(0) { .formats = SNDRV_PCM_FMTBIT_S24_3LE, .channels = 6, //Master, Headphones & Booth .iface = 0, @@ -3744,9 +2939,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, { - .ifnum = 0, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(0) { .formats = SNDRV_PCM_FMTBIT_S24_3LE, .channels = 4, //2x RCA inputs (CH1 & CH2) .iface = 0, @@ -3764,9 +2957,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), .rate_table = (unsigned int[]) { 44100 } } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, @@ -3778,14 +2969,10 @@ YAMAHA_DEVICE(0x7010, "UB99"), * The Feedback for the output is the input */ USB_DEVICE_VENDOR_SPEC(0x2b73, 0x001e), - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { + QUIRK_DRIVER_INFO { + QUIRK_DATA_COMPOSITE { { - .ifnum = 0, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(0) { .formats = SNDRV_PCM_FMTBIT_S24_3LE, .channels = 4, .iface = 0, @@ -3802,9 +2989,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, { - .ifnum = 0, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(0) { .formats = SNDRV_PCM_FMTBIT_S24_3LE, .channels = 6, .iface = 0, @@ -3822,9 +3007,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), .rate_table = (unsigned int[]) { 44100 } } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, @@ -3835,14 +3018,10 @@ YAMAHA_DEVICE(0x7010, "UB99"), * 10 channels playback & 12 channels capture @ 44.1/48/96kHz S24LE */ USB_DEVICE_VENDOR_SPEC(0x2b73, 0x000a), - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { + QUIRK_DRIVER_INFO { + QUIRK_DATA_COMPOSITE { { - .ifnum = 0, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(0) { .formats = SNDRV_PCM_FMTBIT_S24_3LE, .channels = 10, .iface = 0, @@ -3863,9 +3042,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, { - .ifnum = 0, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(0) { .formats = SNDRV_PCM_FMTBIT_S24_3LE, .channels = 12, .iface = 0, @@ -3887,9 +3064,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), } } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, @@ -3901,14 +3076,10 @@ YAMAHA_DEVICE(0x7010, "UB99"), * The Feedback for the output is the input */ USB_DEVICE_VENDOR_SPEC(0x2b73, 0x0029), - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { + QUIRK_DRIVER_INFO { + QUIRK_DATA_COMPOSITE { { - .ifnum = 0, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(0) { .formats = SNDRV_PCM_FMTBIT_S24_3LE, .channels = 6, .iface = 0, @@ -3925,9 +3096,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, { - .ifnum = 0, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(0) { .formats = SNDRV_PCM_FMTBIT_S24_3LE, .channels = 6, .iface = 0, @@ -3945,9 +3114,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), .rate_table = (unsigned int[]) { 44100 } } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, @@ -3965,20 +3132,13 @@ YAMAHA_DEVICE(0x7010, "UB99"), */ { USB_AUDIO_DEVICE(0x534d, 0x0021), - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "MacroSilicon", .product_name = "MS210x", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = &(const struct snd_usb_audio_quirk[]) { - { - .ifnum = 2, - .type = QUIRK_AUDIO_STANDARD_MIXER, - }, + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_STANDARD_MIXER(2) }, { - .ifnum = 3, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(3) { .formats = SNDRV_PCM_FMTBIT_S16_LE, .channels = 2, .iface = 3, @@ -3993,9 +3153,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), .rate_max = 48000, } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, @@ -4013,20 +3171,13 @@ YAMAHA_DEVICE(0x7010, "UB99"), */ { USB_AUDIO_DEVICE(0x534d, 0x2109), - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "MacroSilicon", .product_name = "MS2109", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = &(const struct snd_usb_audio_quirk[]) { - { - .ifnum = 2, - .type = QUIRK_AUDIO_STANDARD_MIXER, - }, + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_STANDARD_MIXER(2) }, { - .ifnum = 3, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(3) { .formats = SNDRV_PCM_FMTBIT_S16_LE, .channels = 2, .iface = 3, @@ -4041,9 +3192,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), .rate_max = 48000, } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, @@ -4053,14 +3202,10 @@ YAMAHA_DEVICE(0x7010, "UB99"), * 8 channels playback & 8 channels capture @ 44.1/48/96kHz S24LE */ USB_DEVICE_VENDOR_SPEC(0x08e4, 0x017f), - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { + QUIRK_DRIVER_INFO { + QUIRK_DATA_COMPOSITE { { - .ifnum = 0, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(0) { .formats = SNDRV_PCM_FMTBIT_S24_3LE, .channels = 8, .iface = 0, @@ -4079,9 +3224,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, { - .ifnum = 0, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(0) { .formats = SNDRV_PCM_FMTBIT_S24_3LE, .channels = 8, .iface = 0, @@ -4101,9 +3244,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), .rate_table = (unsigned int[]) { 44100, 48000, 96000 } } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, @@ -4113,14 +3254,10 @@ YAMAHA_DEVICE(0x7010, "UB99"), * 10 channels playback & 12 channels capture @ 48kHz S24LE */ USB_DEVICE_VENDOR_SPEC(0x2b73, 0x001b), - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { + QUIRK_DRIVER_INFO { + QUIRK_DATA_COMPOSITE { { - .ifnum = 0, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(0) { .formats = SNDRV_PCM_FMTBIT_S24_3LE, .channels = 10, .iface = 0, @@ -4139,9 +3276,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, { - .ifnum = 0, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(0) { .formats = SNDRV_PCM_FMTBIT_S24_3LE, .channels = 12, .iface = 0, @@ -4159,9 +3294,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), .rate_table = (unsigned int[]) { 48000 } } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, @@ -4173,14 +3306,10 @@ YAMAHA_DEVICE(0x7010, "UB99"), * Capture on EP 0x86 */ USB_DEVICE_VENDOR_SPEC(0x08e4, 0x0163), - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { + QUIRK_DRIVER_INFO { + QUIRK_DATA_COMPOSITE { { - .ifnum = 0, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(0) { .formats = SNDRV_PCM_FMTBIT_S24_3LE, .channels = 8, .iface = 0, @@ -4200,9 +3329,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, { - .ifnum = 0, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(0) { .formats = SNDRV_PCM_FMTBIT_S24_3LE, .channels = 8, .iface = 0, @@ -4222,9 +3349,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), .rate_table = (unsigned int[]) { 44100, 48000, 96000 } } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, @@ -4235,14 +3360,10 @@ YAMAHA_DEVICE(0x7010, "UB99"), * and 8 channels in @ 48 fixed (endpoint 0x82). */ USB_DEVICE_VENDOR_SPEC(0x2b73, 0x0013), - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { + QUIRK_DRIVER_INFO { + QUIRK_DATA_COMPOSITE { { - .ifnum = 0, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(0) { .formats = SNDRV_PCM_FMTBIT_S24_3LE, .channels = 8, // outputs .iface = 0, @@ -4259,9 +3380,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, { - .ifnum = 0, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(0) { .formats = SNDRV_PCM_FMTBIT_S24_3LE, .channels = 8, // inputs .iface = 0, @@ -4279,9 +3398,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), .rate_table = (unsigned int[]) { 48000 } } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, @@ -4292,28 +3409,15 @@ YAMAHA_DEVICE(0x7010, "UB99"), */ USB_DEVICE(0x1395, 0x0300), .bInterfaceClass = USB_CLASS_PER_INTERFACE, - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = &(const struct snd_usb_audio_quirk[]) { + QUIRK_DRIVER_INFO { + QUIRK_DATA_COMPOSITE { // Communication - { - .ifnum = 3, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, + { QUIRK_DATA_STANDARD_AUDIO(3) }, // Recording - { - .ifnum = 4, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, + { QUIRK_DATA_STANDARD_AUDIO(4) }, // Main - { - .ifnum = 1, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = -1 - } + { QUIRK_DATA_STANDARD_AUDIO(1) }, + QUIRK_COMPOSITE_END } } }, @@ -4322,21 +3426,14 @@ YAMAHA_DEVICE(0x7010, "UB99"), * Fiero SC-01 (firmware v1.0.0 @ 48 kHz) */ USB_DEVICE(0x2b53, 0x0023), - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Fiero", .product_name = "SC-01", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = &(const struct snd_usb_audio_quirk[]) { - { - .ifnum = 0, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_STANDARD_AUDIO(0) }, /* Playback */ { - .ifnum = 1, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(1) { .formats = SNDRV_PCM_FMTBIT_S32_LE, .channels = 2, .fmt_bits = 24, @@ -4356,9 +3453,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), }, /* Capture */ { - .ifnum = 2, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(2) { .formats = SNDRV_PCM_FMTBIT_S32_LE, .channels = 2, .fmt_bits = 24, @@ -4377,9 +3472,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), .clock = 0x29 } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, @@ -4388,21 +3481,14 @@ YAMAHA_DEVICE(0x7010, "UB99"), * Fiero SC-01 (firmware v1.0.0 @ 96 kHz) */ USB_DEVICE(0x2b53, 0x0024), - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Fiero", .product_name = "SC-01", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = &(const struct snd_usb_audio_quirk[]) { - { - .ifnum = 0, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_STANDARD_AUDIO(0) }, /* Playback */ { - .ifnum = 1, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(1) { .formats = SNDRV_PCM_FMTBIT_S32_LE, .channels = 2, .fmt_bits = 24, @@ -4422,9 +3508,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), }, /* Capture */ { - .ifnum = 2, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(2) { .formats = SNDRV_PCM_FMTBIT_S32_LE, .channels = 2, .fmt_bits = 24, @@ -4443,9 +3527,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), .clock = 0x29 } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, @@ -4454,21 +3536,14 @@ YAMAHA_DEVICE(0x7010, "UB99"), * Fiero SC-01 (firmware v1.1.0) */ USB_DEVICE(0x2b53, 0x0031), - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Fiero", .product_name = "SC-01", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = &(const struct snd_usb_audio_quirk[]) { - { - .ifnum = 0, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_STANDARD_AUDIO(0) }, /* Playback */ { - .ifnum = 1, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(1) { .formats = SNDRV_PCM_FMTBIT_S32_LE, .channels = 2, .fmt_bits = 24, @@ -4489,9 +3564,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), }, /* Capture */ { - .ifnum = 2, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(2) { .formats = SNDRV_PCM_FMTBIT_S32_LE, .channels = 2, .fmt_bits = 24, @@ -4511,9 +3584,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), .clock = 0x29 } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, @@ -4522,27 +3593,14 @@ YAMAHA_DEVICE(0x7010, "UB99"), * For the standard mode, Mythware XA001AU has ID ffad:a001 */ USB_DEVICE_VENDOR_SPEC(0xffad, 0xa001), - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Mythware", .product_name = "XA001AU", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 0, - .type = QUIRK_IGNORE_INTERFACE, - }, - { - .ifnum = 1, - .type = QUIRK_AUDIO_STANDARD_INTERFACE, - }, - { - .ifnum = 2, - .type = QUIRK_AUDIO_STANDARD_INTERFACE, - }, - { - .ifnum = -1 - } + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_IGNORE(0) }, + { QUIRK_DATA_STANDARD_AUDIO(1) }, + { QUIRK_DATA_STANDARD_AUDIO(2) }, + QUIRK_COMPOSITE_END } } }, diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index ea063a14cdd8fe..e7b68c67852e92 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -2221,6 +2221,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = { QUIRK_FLAG_GENERIC_IMPLICIT_FB), DEVICE_FLG(0x2b53, 0x0031, /* Fiero SC-01 (firmware v1.1.0) */ QUIRK_FLAG_GENERIC_IMPLICIT_FB), + DEVICE_FLG(0x2d95, 0x8021, /* VIVO USB-C-XE710 HEADSET */ + QUIRK_FLAG_CTL_MSG_DELAY_1M), DEVICE_FLG(0x30be, 0x0101, /* Schiit Hel */ QUIRK_FLAG_IGNORE_CTL_ERROR), DEVICE_FLG(0x413c, 0xa506, /* Dell AE515 sound bar */ diff --git a/sound/usb/stream.c b/sound/usb/stream.c index d5409f38794559..d70c140813d688 100644 --- a/sound/usb/stream.c +++ b/sound/usb/stream.c @@ -244,8 +244,8 @@ static struct snd_pcm_chmap_elem *convert_chmap(int channels, unsigned int bits, SNDRV_CHMAP_FR, /* right front */ SNDRV_CHMAP_FC, /* center front */ SNDRV_CHMAP_LFE, /* LFE */ - SNDRV_CHMAP_SL, /* left surround */ - SNDRV_CHMAP_SR, /* right surround */ + SNDRV_CHMAP_RL, /* left surround */ + SNDRV_CHMAP_RR, /* right surround */ SNDRV_CHMAP_FLC, /* left of center */ SNDRV_CHMAP_FRC, /* right of center */ SNDRV_CHMAP_RC, /* surround */ @@ -713,10 +713,13 @@ snd_usb_get_audioformat_uac12(struct snd_usb_audio *chip, struct usb_device *dev = chip->dev; struct uac_format_type_i_continuous_descriptor *fmt; unsigned int num_channels = 0, chconfig = 0; + struct usb_host_interface *ctrl_intf; struct audioformat *fp; int clock = 0; u64 format; + ctrl_intf = snd_usb_find_ctrl_interface(chip, iface_no); + /* get audio formats */ if (protocol == UAC_VERSION_1) { struct uac1_as_header_descriptor *as = @@ -740,7 +743,7 @@ snd_usb_get_audioformat_uac12(struct snd_usb_audio *chip, format = le16_to_cpu(as->wFormatTag); /* remember the format value */ - iterm = snd_usb_find_input_terminal_descriptor(chip->ctrl_intf, + iterm = snd_usb_find_input_terminal_descriptor(ctrl_intf, as->bTerminalLink, protocol); if (iterm) { @@ -776,7 +779,7 @@ snd_usb_get_audioformat_uac12(struct snd_usb_audio *chip, * lookup the terminal associated to this interface * to extract the clock */ - input_term = snd_usb_find_input_terminal_descriptor(chip->ctrl_intf, + input_term = snd_usb_find_input_terminal_descriptor(ctrl_intf, as->bTerminalLink, protocol); if (input_term) { @@ -786,7 +789,7 @@ snd_usb_get_audioformat_uac12(struct snd_usb_audio *chip, goto found_clock; } - output_term = snd_usb_find_output_terminal_descriptor(chip->ctrl_intf, + output_term = snd_usb_find_output_terminal_descriptor(ctrl_intf, as->bTerminalLink, protocol); if (output_term) { @@ -870,6 +873,7 @@ snd_usb_get_audioformat_uac3(struct snd_usb_audio *chip, struct uac3_cluster_header_descriptor *cluster; struct uac3_as_header_descriptor *as = NULL; struct uac3_hc_descriptor_header hc_header; + struct usb_host_interface *ctrl_intf; struct snd_pcm_chmap_elem *chmap; struct snd_usb_power_domain *pd; unsigned char badd_profile; @@ -881,6 +885,7 @@ snd_usb_get_audioformat_uac3(struct snd_usb_audio *chip, int err; badd_profile = chip->badd_profile; + ctrl_intf = snd_usb_find_ctrl_interface(chip, iface_no); if (badd_profile >= UAC3_FUNCTION_SUBCLASS_GENERIC_IO) { unsigned int maxpacksize = @@ -966,7 +971,7 @@ snd_usb_get_audioformat_uac3(struct snd_usb_audio *chip, UAC3_CS_REQ_HIGH_CAPABILITY_DESCRIPTOR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, cluster_id, - snd_usb_ctrl_intf(chip), + snd_usb_ctrl_intf(ctrl_intf), &hc_header, sizeof(hc_header)); if (err < 0) return ERR_PTR(err); @@ -990,7 +995,7 @@ snd_usb_get_audioformat_uac3(struct snd_usb_audio *chip, UAC3_CS_REQ_HIGH_CAPABILITY_DESCRIPTOR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, cluster_id, - snd_usb_ctrl_intf(chip), + snd_usb_ctrl_intf(ctrl_intf), cluster, wLength); if (err < 0) { kfree(cluster); @@ -1011,7 +1016,7 @@ snd_usb_get_audioformat_uac3(struct snd_usb_audio *chip, * lookup the terminal associated to this interface * to extract the clock */ - input_term = snd_usb_find_input_terminal_descriptor(chip->ctrl_intf, + input_term = snd_usb_find_input_terminal_descriptor(ctrl_intf, as->bTerminalLink, UAC_VERSION_3); if (input_term) { @@ -1019,7 +1024,7 @@ snd_usb_get_audioformat_uac3(struct snd_usb_audio *chip, goto found_clock; } - output_term = snd_usb_find_output_terminal_descriptor(chip->ctrl_intf, + output_term = snd_usb_find_output_terminal_descriptor(ctrl_intf, as->bTerminalLink, UAC_VERSION_3); if (output_term) { @@ -1068,7 +1073,7 @@ snd_usb_get_audioformat_uac3(struct snd_usb_audio *chip, UAC_VERSION_3, iface_no); - pd = snd_usb_find_power_domain(chip->ctrl_intf, + pd = snd_usb_find_power_domain(ctrl_intf, as->bTerminalLink); /* ok, let's parse further... */ diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h index 43d4029edab463..b0f042c996087e 100644 --- a/sound/usb/usbaudio.h +++ b/sound/usb/usbaudio.h @@ -21,6 +21,15 @@ struct media_intf_devnode; #define MAX_CARD_INTERFACES 16 +/* + * Structure holding assosiation between Audio Control Interface + * and given Streaming or Midi Interface. + */ +struct snd_intf_to_ctrl { + u8 interface; + struct usb_host_interface *ctrl_intf; +}; + struct snd_usb_audio { int index; struct usb_device *dev; @@ -63,6 +72,9 @@ struct snd_usb_audio { struct usb_host_interface *ctrl_intf; /* the audio control interface */ struct media_device *media_dev; struct media_intf_devnode *ctl_intf_media_devnode; + + unsigned int num_intf_to_ctrl; + struct snd_intf_to_ctrl intf_to_ctrl[MAX_CARD_INTERFACES]; }; #define USB_AUDIO_IFACE_UNUSED ((void *)-1L) diff --git a/sound/usb/usx2y/us122l.c b/sound/usb/usx2y/us122l.c index 709ccad972e2ff..1be0e980feb958 100644 --- a/sound/usb/usx2y/us122l.c +++ b/sound/usb/usx2y/us122l.c @@ -84,12 +84,9 @@ static int us144_create_usbmidi(struct snd_card *card) static void pt_info_set(struct usb_device *dev, u8 v) { - int ret; - - ret = usb_control_msg_send(dev, 0, 'I', - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - v, 0, NULL, 0, 1000, GFP_NOIO); - snd_printdd(KERN_DEBUG "%i\n", ret); + usb_control_msg_send(dev, 0, 'I', + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + v, 0, NULL, 0, 1000, GFP_NOIO); } static void usb_stream_hwdep_vm_open(struct vm_area_struct *area) @@ -97,7 +94,6 @@ static void usb_stream_hwdep_vm_open(struct vm_area_struct *area) struct us122l *us122l = area->vm_private_data; atomic_inc(&us122l->mmap_count); - snd_printdd(KERN_DEBUG "%i\n", atomic_read(&us122l->mmap_count)); } static vm_fault_t usb_stream_hwdep_vm_fault(struct vm_fault *vmf) @@ -141,7 +137,6 @@ static void usb_stream_hwdep_vm_close(struct vm_area_struct *area) struct us122l *us122l = area->vm_private_data; atomic_dec(&us122l->mmap_count); - snd_printdd(KERN_DEBUG "%i\n", atomic_read(&us122l->mmap_count)); } static const struct vm_operations_struct usb_stream_hwdep_vm_ops = { @@ -155,7 +150,6 @@ static int usb_stream_hwdep_open(struct snd_hwdep *hw, struct file *file) struct us122l *us122l = hw->private_data; struct usb_interface *iface; - snd_printdd(KERN_DEBUG "%p %p\n", hw, file); if (hw->used >= 2) return -EBUSY; @@ -176,8 +170,6 @@ static int usb_stream_hwdep_release(struct snd_hwdep *hw, struct file *file) struct us122l *us122l = hw->private_data; struct usb_interface *iface; - snd_printdd(KERN_DEBUG "%p %p\n", hw, file); - if (us122l->is_us144) { iface = usb_ifnum_to_if(us122l->dev, 0); usb_autopm_put_interface(iface); @@ -213,12 +205,10 @@ static int usb_stream_hwdep_mmap(struct snd_hwdep *hw, err = -EPERM; goto out; } - snd_printdd(KERN_DEBUG "%lu %u\n", size, - read ? s->read_size : s->write_size); /* if userspace tries to mmap beyond end of our buffer, fail */ if (size > PAGE_ALIGN(read ? s->read_size : s->write_size)) { - snd_printk(KERN_WARNING "%lu > %u\n", size, - read ? s->read_size : s->write_size); + dev_warn(hw->card->dev, "%s: size %lu > %u\n", __func__, + size, read ? s->read_size : s->write_size); err = -EINVAL; goto out; } @@ -289,8 +279,8 @@ static int us122l_set_sample_rate(struct usb_device *dev, int rate) UAC_EP_CS_ATTR_SAMPLE_RATE << 8, ep, data, 3, 1000, GFP_NOIO); if (err) - snd_printk(KERN_ERR "%d: cannot set freq %d to ep 0x%x\n", - dev->devnum, rate, ep); + dev_err(&dev->dev, "%d: cannot set freq %d to ep 0x%x\n", + dev->devnum, rate, ep); return err; } @@ -326,13 +316,13 @@ static bool us122l_start(struct us122l *us122l, err = us122l_set_sample_rate(us122l->dev, rate); if (err < 0) { us122l_stop(us122l); - snd_printk(KERN_ERR "us122l_set_sample_rate error\n"); + dev_err(&us122l->dev->dev, "us122l_set_sample_rate error\n"); goto out; } err = usb_stream_start(&us122l->sk); if (err < 0) { us122l_stop(us122l); - snd_printk(KERN_ERR "%s error %i\n", __func__, err); + dev_err(&us122l->dev->dev, "%s error %i\n", __func__, err); goto out; } list_for_each(p, &us122l->midi_list) @@ -445,13 +435,13 @@ static bool us122l_create_card(struct snd_card *card) if (us122l->is_us144) { err = usb_set_interface(us122l->dev, 0, 1); if (err) { - snd_printk(KERN_ERR "usb_set_interface error\n"); + dev_err(card->dev, "usb_set_interface error\n"); return false; } } err = usb_set_interface(us122l->dev, 1, 1); if (err) { - snd_printk(KERN_ERR "usb_set_interface error\n"); + dev_err(card->dev, "usb_set_interface error\n"); return false; } @@ -466,7 +456,7 @@ static bool us122l_create_card(struct snd_card *card) else err = us122l_create_usbmidi(card); if (err < 0) { - snd_printk(KERN_ERR "us122l_create_usbmidi error %i\n", err); + dev_err(card->dev, "us122l_create_usbmidi error %i\n", err); goto stop; } err = usb_stream_hwdep_new(card); @@ -517,6 +507,7 @@ static int usx2y_create_card(struct usb_device *device, card->private_free = snd_us122l_free; US122L(card)->dev = device; mutex_init(&US122L(card)->mutex); + US122L(card)->sk.dev = device; init_waitqueue_head(&US122L(card)->sk.sleep); US122L(card)->is_us144 = flags & US122L_FLAG_US144; INIT_LIST_HEAD(&US122L(card)->midi_list); @@ -572,12 +563,10 @@ static int snd_us122l_probe(struct usb_interface *intf, if (id->driver_info & US122L_FLAG_US144 && device->speed == USB_SPEED_HIGH) { - snd_printk(KERN_ERR "disable ehci-hcd to run US-144\n"); + dev_err(&device->dev, "disable ehci-hcd to run US-144\n"); return -ENODEV; } - snd_printdd(KERN_DEBUG"%p:%i\n", - intf, intf->cur_altsetting->desc.bInterfaceNumber); if (intf->cur_altsetting->desc.bInterfaceNumber != 1) return 0; @@ -668,13 +657,13 @@ static int snd_us122l_resume(struct usb_interface *intf) if (us122l->is_us144) { err = usb_set_interface(us122l->dev, 0, 1); if (err) { - snd_printk(KERN_ERR "usb_set_interface error\n"); + dev_err(&us122l->dev->dev, "usb_set_interface error\n"); goto unlock; } } err = usb_set_interface(us122l->dev, 1, 1); if (err) { - snd_printk(KERN_ERR "usb_set_interface error\n"); + dev_err(&us122l->dev->dev, "usb_set_interface error\n"); goto unlock; } @@ -684,7 +673,7 @@ static int snd_us122l_resume(struct usb_interface *intf) err = us122l_set_sample_rate(us122l->dev, us122l->sk.s->cfg.sample_rate); if (err < 0) { - snd_printk(KERN_ERR "us122l_set_sample_rate error\n"); + dev_err(&us122l->dev->dev, "us122l_set_sample_rate error\n"); goto unlock; } err = usb_stream_start(&us122l->sk); diff --git a/sound/usb/usx2y/usX2Yhwdep.c b/sound/usb/usx2y/usX2Yhwdep.c index 4937ede0b5d70b..9fd6a86cc08e06 100644 --- a/sound/usb/usx2y/usX2Yhwdep.c +++ b/sound/usb/usx2y/usX2Yhwdep.c @@ -24,19 +24,12 @@ static vm_fault_t snd_us428ctls_vm_fault(struct vm_fault *vmf) struct page *page; void *vaddr; - snd_printdd("ENTER, start %lXh, pgoff %ld\n", - vmf->vma->vm_start, - vmf->pgoff); - offset = vmf->pgoff << PAGE_SHIFT; vaddr = (char *)((struct usx2ydev *)vmf->vma->vm_private_data)->us428ctls_sharedmem + offset; page = virt_to_page(vaddr); get_page(page); vmf->page = page; - snd_printdd("vaddr=%p made us428ctls_vm_fault() page %p\n", - vaddr, page); - return 0; } @@ -56,7 +49,8 @@ static int snd_us428ctls_mmap(struct snd_hwdep *hw, struct file *filp, struct vm /* if userspace tries to mmap beyond end of our buffer, fail */ if (size > US428_SHAREDMEM_PAGES) { - snd_printd("%lu > %lu\n", size, (unsigned long)US428_SHAREDMEM_PAGES); + dev_dbg(hw->card->dev, "%s: mmap size %lu > %lu\n", __func__, + size, (unsigned long)US428_SHAREDMEM_PAGES); return -EINVAL; } @@ -150,7 +144,6 @@ static int usx2y_create_usbmidi(struct snd_card *card) le16_to_cpu(dev->descriptor.idProduct) == USB_ID_US428 ? &quirk_2 : &quirk_1; - snd_printdd("%s\n", __func__); return snd_usbmidi_create(card, iface, &usx2y(card)->midi_list, quirk); } @@ -160,7 +153,8 @@ static int usx2y_create_alsa_devices(struct snd_card *card) err = usx2y_create_usbmidi(card); if (err < 0) { - snd_printk(KERN_ERR "%s: usx2y_create_usbmidi error %i\n", __func__, err); + dev_err(card->dev, "%s: usx2y_create_usbmidi error %i\n", + __func__, err); return err; } err = usx2y_audio_create(card); @@ -183,15 +177,13 @@ static int snd_usx2y_hwdep_dsp_load(struct snd_hwdep *hw, int lret, err; char *buf; - snd_printdd("dsp_load %s\n", dsp->name); - buf = memdup_user(dsp->image, dsp->length); if (IS_ERR(buf)) return PTR_ERR(buf); err = usb_set_interface(dev, 0, 1); if (err) - snd_printk(KERN_ERR "usb_set_interface error\n"); + dev_err(&dev->dev, "usb_set_interface error\n"); else err = usb_bulk_msg(dev, usb_sndbulkpipe(dev, 2), buf, dsp->length, &lret, 6000); kfree(buf); @@ -201,21 +193,20 @@ static int snd_usx2y_hwdep_dsp_load(struct snd_hwdep *hw, msleep(250); // give the device some time err = usx2y_async_seq04_init(priv); if (err) { - snd_printk(KERN_ERR "usx2y_async_seq04_init error\n"); + dev_err(&dev->dev, "usx2y_async_seq04_init error\n"); return err; } err = usx2y_in04_init(priv); if (err) { - snd_printk(KERN_ERR "usx2y_in04_init error\n"); + dev_err(&dev->dev, "usx2y_in04_init error\n"); return err; } err = usx2y_create_alsa_devices(hw->card); if (err) { - snd_printk(KERN_ERR "usx2y_create_alsa_devices error %i\n", err); + dev_err(&dev->dev, "usx2y_create_alsa_devices error %i\n", err); return err; } priv->chip_status |= USX2Y_STAT_CHIP_INIT; - snd_printdd("%s: alsa all started\n", hw->name); } return err; } diff --git a/sound/usb/usx2y/usb_stream.c b/sound/usb/usx2y/usb_stream.c index a4d32e8a1d3663..3122cf653273df 100644 --- a/sound/usb/usx2y/usb_stream.c +++ b/sound/usb/usx2y/usb_stream.c @@ -34,14 +34,11 @@ static void playback_prep_freqn(struct usb_stream_kernel *sk, struct urb *urb) urb->iso_frame_desc[pack].length = l; lb += l; } - snd_printdd(KERN_DEBUG "%i\n", lb); check: urb->number_of_packets = pack; urb->transfer_buffer_length = lb; s->idle_outsize += lb - s->period_size; - snd_printdd(KERN_DEBUG "idle=%i ul=%i ps=%i\n", s->idle_outsize, - lb, s->period_size); } static int init_pipe_urbs(struct usb_stream_kernel *sk, @@ -191,14 +188,14 @@ struct usb_stream *usb_stream_new(struct usb_stream_kernel *sk, write_size = max_packsize * packets * USB_STREAM_URBDEPTH; if (read_size >= 256*PAGE_SIZE || write_size >= 256*PAGE_SIZE) { - snd_printk(KERN_WARNING "a size exceeds 128*PAGE_SIZE\n"); + dev_warn(&dev->dev, "%s: a size exceeds 128*PAGE_SIZE\n", __func__); goto out; } sk->s = alloc_pages_exact(read_size, GFP_KERNEL | __GFP_ZERO | __GFP_NOWARN); if (!sk->s) { - pr_warn("us122l: couldn't allocate read buffer\n"); + dev_warn(&dev->dev, "us122l: couldn't allocate read buffer\n"); goto out; } sk->s->cfg.version = USB_STREAM_INTERFACE_VERSION; @@ -217,7 +214,7 @@ struct usb_stream *usb_stream_new(struct usb_stream_kernel *sk, sk->write_page = alloc_pages_exact(write_size, GFP_KERNEL | __GFP_ZERO | __GFP_NOWARN); if (!sk->write_page) { - pr_warn("us122l: couldn't allocate write buffer\n"); + dev_warn(&dev->dev, "us122l: couldn't allocate write buffer\n"); usb_stream_free(sk); return NULL; } @@ -246,7 +243,8 @@ static bool balance_check(struct usb_stream_kernel *sk, struct urb *urb) if (unlikely(urb->status)) { if (urb->status != -ESHUTDOWN && urb->status != -ENOENT) - snd_printk(KERN_WARNING "status=%i\n", urb->status); + dev_warn(&sk->dev->dev, "%s: status=%i\n", __func__, + urb->status); sk->iso_frame_balance = 0x7FFFFFFF; return false; } @@ -318,17 +316,18 @@ static int usb_stream_prepare_playback(struct usb_stream_kernel *sk, check_ok: s->sync_packet -= inurb->number_of_packets; if (unlikely(s->sync_packet < -2 || s->sync_packet > 0)) { - snd_printk(KERN_WARNING "invalid sync_packet = %i;" - " p=%i nop=%i %i %x %x %x > %x\n", - s->sync_packet, p, inurb->number_of_packets, - s->idle_outsize + lb + l, - s->idle_outsize, lb, l, - s->period_size); + dev_warn(&sk->dev->dev, + "%s: invalid sync_packet = %i; p=%i nop=%i %i %x %x %x > %x\n", + __func__, + s->sync_packet, p, inurb->number_of_packets, + s->idle_outsize + lb + l, + s->idle_outsize, lb, l, + s->period_size); return -1; } if (unlikely(lb % s->cfg.frame_size)) { - snd_printk(KERN_WARNING"invalid outsize = %i\n", - lb); + dev_warn(&sk->dev->dev, "%s: invalid outsize = %i\n", + __func__, lb); return -1; } s->idle_outsize += lb - s->period_size; @@ -337,7 +336,7 @@ static int usb_stream_prepare_playback(struct usb_stream_kernel *sk, if (s->idle_outsize <= 0) return 0; - snd_printk(KERN_WARNING "idle=%i\n", s->idle_outsize); + dev_warn(&sk->dev->dev, "%s: idle=%i\n", __func__, s->idle_outsize); return -1; } @@ -377,7 +376,7 @@ static int submit_urbs(struct usb_stream_kernel *sk, return 0; report_failure: - snd_printk(KERN_ERR "%i\n", err); + dev_err(&sk->dev->dev, "%s error: %i\n", __func__, err); return err; } @@ -424,8 +423,8 @@ static void loop_back(struct usb_stream *s) } if (iu == sk->completed_inurb) { if (l != s->period_size) - printk(KERN_DEBUG"%s:%i %i\n", __func__, __LINE__, - l/(int)s->cfg.frame_size); + dev_dbg(&sk->dev->dev, "%s:%i %i\n", __func__, __LINE__, + l/(int)s->cfg.frame_size); return; } @@ -460,8 +459,8 @@ static void stream_idle(struct usb_stream_kernel *sk, l = id[p].actual_length; if (unlikely(l == 0 || id[p].status)) { - snd_printk(KERN_WARNING "underrun, status=%u\n", - id[p].status); + dev_warn(&sk->dev->dev, "%s: underrun, status=%u\n", + __func__, id[p].status); goto err_out; } s->inpacket_head++; @@ -482,8 +481,8 @@ static void stream_idle(struct usb_stream_kernel *sk, } s->idle_insize += urb_size - s->period_size; if (s->idle_insize < 0) { - snd_printk(KERN_WARNING "%i\n", - (s->idle_insize)/(int)s->cfg.frame_size); + dev_warn(&sk->dev->dev, "%s error: %i\n", __func__, + (s->idle_insize)/(int)s->cfg.frame_size); goto err_out; } s->insize_done += urb_size; @@ -558,19 +557,15 @@ static void stream_start(struct usb_stream_kernel *sk, min_frames += frames_per_packet; diff = urb_size - (min_frames >> 8) * s->cfg.frame_size; - if (diff < max_diff) { - snd_printdd(KERN_DEBUG "%i %i %i %i\n", - s->insize_done, - urb_size / (int)s->cfg.frame_size, - inurb->number_of_packets, diff); + if (diff < max_diff) max_diff = diff; - } } s->idle_insize -= max_diff - max_diff_0; s->idle_insize += urb_size - s->period_size; if (s->idle_insize < 0) { - snd_printk(KERN_WARNING "%i %i %i\n", - s->idle_insize, urb_size, s->period_size); + dev_warn(&sk->dev->dev, "%s idle_insize: %i %i %i\n", + __func__, + s->idle_insize, urb_size, s->period_size); return; } else if (s->idle_insize == 0) { s->next_inpacket_split = @@ -620,7 +615,7 @@ static void i_capture_start(struct urb *urb) int empty = 0; if (urb->status) { - snd_printk(KERN_WARNING "status=%i\n", urb->status); + dev_warn(&sk->dev->dev, "%s: status=%i\n", __func__, urb->status); return; } @@ -630,7 +625,7 @@ static void i_capture_start(struct urb *urb) if (l < s->cfg.frame_size) { ++empty; if (s->state >= usb_stream_sync0) { - snd_printk(KERN_WARNING "%i\n", l); + dev_warn(&sk->dev->dev, "%s: length %i\n", __func__, l); return; } } @@ -642,8 +637,8 @@ static void i_capture_start(struct urb *urb) } #ifdef SHOW_EMPTY if (empty) { - printk(KERN_DEBUG"%s:%i: %i", __func__, __LINE__, - urb->iso_frame_desc[0].actual_length); + dev_dbg(&sk->dev->dev, "%s:%i: %i", __func__, __LINE__, + urb->iso_frame_desc[0].actual_length); for (pack = 1; pack < urb->number_of_packets; ++pack) { int l = urb->iso_frame_desc[pack].actual_length; @@ -670,7 +665,7 @@ static void i_playback_start(struct urb *urb) int usb_stream_start(struct usb_stream_kernel *sk) { struct usb_stream *s = sk->s; - int frame = 0, iters = 0; + int frame = 0; int u, err; int try = 0; @@ -705,43 +700,42 @@ int usb_stream_start(struct usb_stream_kernel *sk) frame = usb_get_current_frame_number(dev); do { now = usb_get_current_frame_number(dev); - ++iters; } while (now > -1 && now == frame); } err = usb_submit_urb(inurb, GFP_ATOMIC); if (err < 0) { - snd_printk(KERN_ERR - "usb_submit_urb(sk->inurb[%i]) returned %i\n", - u, err); + dev_err(&sk->dev->dev, + "%s: usb_submit_urb(sk->inurb[%i]) returned %i\n", + __func__, u, err); return err; } err = usb_submit_urb(outurb, GFP_ATOMIC); if (err < 0) { - snd_printk(KERN_ERR - "usb_submit_urb(sk->outurb[%i]) returned %i\n", - u, err); + dev_err(&sk->dev->dev, + "%s: usb_submit_urb(sk->outurb[%i]) returned %i\n", + __func__, u, err); return err; } if (inurb->start_frame != outurb->start_frame) { - snd_printd(KERN_DEBUG - "u[%i] start_frames differ in:%u out:%u\n", - u, inurb->start_frame, outurb->start_frame); + dev_dbg(&sk->dev->dev, + "%s: u[%i] start_frames differ in:%u out:%u\n", + __func__, u, inurb->start_frame, outurb->start_frame); goto check_retry; } } - snd_printdd(KERN_DEBUG "%i %i\n", frame, iters); try = 0; check_retry: if (try) { usb_stream_stop(sk); if (try < 5) { msleep(1500); - snd_printd(KERN_DEBUG "goto dotry;\n"); + dev_dbg(&sk->dev->dev, "goto dotry;\n"); goto dotry; } - snd_printk(KERN_WARNING - "couldn't start all urbs on the same start_frame.\n"); + dev_warn(&sk->dev->dev, + "%s: couldn't start all urbs on the same start_frame.\n", + __func__); return -EFAULT; } @@ -755,7 +749,6 @@ int usb_stream_start(struct usb_stream_kernel *sk) int wait_ms = 3000; while (s->state != usb_stream_ready && wait_ms > 0) { - snd_printdd(KERN_DEBUG "%i\n", s->state); msleep(200); wait_ms -= 200; } diff --git a/sound/usb/usx2y/usb_stream.h b/sound/usb/usx2y/usb_stream.h index 73e57b341adc86..2ed10add49f1a0 100644 --- a/sound/usb/usx2y/usb_stream.h +++ b/sound/usb/usx2y/usb_stream.h @@ -9,6 +9,7 @@ struct usb_stream_kernel { struct usb_stream *s; + struct usb_device *dev; void *write_page; diff --git a/sound/usb/usx2y/usbusx2y.c b/sound/usb/usx2y/usbusx2y.c index 52f4e6652407d5..2f9cede242b3a9 100644 --- a/sound/usb/usx2y/usbusx2y.c +++ b/sound/usb/usx2y/usbusx2y.c @@ -163,7 +163,7 @@ static void i_usx2y_out04_int(struct urb *urb) for (i = 0; i < 10 && usx2y->as04.urb[i] != urb; i++) ; - snd_printdd("%s urb %i status=%i\n", __func__, i, urb->status); + dev_dbg(&urb->dev->dev, "%s urb %i status=%i\n", __func__, i, urb->status); } #endif } @@ -179,11 +179,10 @@ static void i_usx2y_in04_int(struct urb *urb) usx2y->in04_int_calls++; if (urb->status) { - snd_printdd("Interrupt Pipe 4 came back with status=%i\n", urb->status); + dev_dbg(&urb->dev->dev, "Interrupt Pipe 4 came back with status=%i\n", urb->status); return; } - // printk("%i:0x%02X ", 8, (int)((unsigned char*)usx2y->in04_buf)[8]); Master volume shows 0 here if fader is at max during boot ?!? if (us428ctls) { diff = -1; if (us428ctls->ctl_snapshot_last == -2) { @@ -239,7 +238,7 @@ static void i_usx2y_in04_int(struct urb *urb) } if (err) - snd_printk(KERN_ERR "in04_int() usb_submit_urb err=%i\n", err); + dev_err(&urb->dev->dev, "in04_int() usb_submit_urb err=%i\n", err); urb->dev = usx2y->dev; usb_submit_urb(urb, GFP_ATOMIC); diff --git a/sound/usb/usx2y/usbusx2yaudio.c b/sound/usb/usx2y/usbusx2yaudio.c index ca7888495a9f40..f540f46a0b143b 100644 --- a/sound/usb/usx2y/usbusx2yaudio.c +++ b/sound/usb/usx2y/usbusx2yaudio.c @@ -67,14 +67,15 @@ static int usx2y_urb_capt_retire(struct snd_usx2y_substream *subs) for (i = 0; i < nr_of_packs(); i++) { cp = (unsigned char *)urb->transfer_buffer + urb->iso_frame_desc[i].offset; if (urb->iso_frame_desc[i].status) { /* active? hmm, skip this */ - snd_printk(KERN_ERR - "active frame status %i. Most probably some hardware problem.\n", - urb->iso_frame_desc[i].status); + dev_err(&usx2y->dev->dev, + "%s: active frame status %i. Most probably some hardware problem.\n", + __func__, + urb->iso_frame_desc[i].status); return urb->iso_frame_desc[i].status; } len = urb->iso_frame_desc[i].actual_length / usx2y->stride; if (!len) { - snd_printd("0 == len ERROR!\n"); + dev_dbg(&usx2y->dev->dev, "%s: 0 == len ERROR!\n", __func__); continue; } @@ -128,7 +129,8 @@ static int usx2y_urb_play_prepare(struct snd_usx2y_substream *subs, counts = cap_urb->iso_frame_desc[pack].actual_length / usx2y->stride; count += counts; if (counts < 43 || counts > 50) { - snd_printk(KERN_ERR "should not be here with counts=%i\n", counts); + dev_err(&usx2y->dev->dev, "%s: should not be here with counts=%i\n", + __func__, counts); return -EPIPE; } /* set up descriptor */ @@ -196,7 +198,8 @@ static int usx2y_urb_submit(struct snd_usx2y_substream *subs, struct urb *urb, i urb->dev = subs->usx2y->dev; /* we need to set this at each time */ err = usb_submit_urb(urb, GFP_ATOMIC); if (err < 0) { - snd_printk(KERN_ERR "usb_submit_urb() returned %i\n", err); + dev_err(&urb->dev->dev, "%s: usb_submit_urb() returned %i\n", + __func__, err); return err; } return 0; @@ -264,7 +267,8 @@ static void usx2y_clients_stop(struct usx2ydev *usx2y) for (s = 0; s < 4; s++) { subs = usx2y->subs[s]; if (subs) { - snd_printdd("%i %p state=%i\n", s, subs, atomic_read(&subs->state)); + dev_dbg(&usx2y->dev->dev, "%s: %i %p state=%i\n", + __func__, s, subs, atomic_read(&subs->state)); atomic_set(&subs->state, STATE_STOPPED); } } @@ -276,8 +280,9 @@ static void usx2y_clients_stop(struct usx2ydev *usx2y) for (u = 0; u < NRURBS; u++) { urb = subs->urb[u]; if (urb) - snd_printdd("%i status=%i start_frame=%i\n", - u, urb->status, urb->start_frame); + dev_dbg(&usx2y->dev->dev, + "%s: %i status=%i start_frame=%i\n", + __func__, u, urb->status, urb->start_frame); } } } @@ -288,7 +293,8 @@ static void usx2y_clients_stop(struct usx2ydev *usx2y) static void usx2y_error_urb_status(struct usx2ydev *usx2y, struct snd_usx2y_substream *subs, struct urb *urb) { - snd_printk(KERN_ERR "ep=%i stalled with status=%i\n", subs->endpoint, urb->status); + dev_err(&usx2y->dev->dev, "%s: ep=%i stalled with status=%i\n", + __func__, subs->endpoint, urb->status); urb->status = 0; usx2y_clients_stop(usx2y); } @@ -300,10 +306,12 @@ static void i_usx2y_urb_complete(struct urb *urb) struct snd_usx2y_substream *capsubs, *playbacksubs; if (unlikely(atomic_read(&subs->state) < STATE_PREPARED)) { - snd_printdd("hcd_frame=%i ep=%i%s status=%i start_frame=%i\n", - usb_get_current_frame_number(usx2y->dev), - subs->endpoint, usb_pipein(urb->pipe) ? "in" : "out", - urb->status, urb->start_frame); + dev_dbg(&usx2y->dev->dev, + "%s: hcd_frame=%i ep=%i%s status=%i start_frame=%i\n", + __func__, + usb_get_current_frame_number(usx2y->dev), + subs->endpoint, usb_pipein(urb->pipe) ? "in" : "out", + urb->status, urb->start_frame); return; } if (unlikely(urb->status)) { @@ -323,7 +331,6 @@ static void i_usx2y_urb_complete(struct urb *urb) if (!usx2y_usbframe_complete(capsubs, playbacksubs, urb->start_frame)) { usx2y->wait_iso_frame += nr_of_packs(); } else { - snd_printdd("\n"); usx2y_clients_stop(usx2y); } } @@ -373,8 +380,9 @@ static void i_usx2y_subs_startup(struct urb *urb) static void usx2y_subs_prepare(struct snd_usx2y_substream *subs) { - snd_printdd("usx2y_substream_prepare(%p) ep=%i urb0=%p urb1=%p\n", - subs, subs->endpoint, subs->urb[0], subs->urb[1]); + dev_dbg(&subs->usx2y->dev->dev, + "%s(%p) ep=%i urb0=%p urb1=%p\n", + __func__, subs, subs->endpoint, subs->urb[0], subs->urb[1]); /* reset the pointer */ subs->hwptr = 0; subs->hwptr_done = 0; @@ -399,7 +407,7 @@ static void usx2y_urbs_release(struct snd_usx2y_substream *subs) { int i; - snd_printdd("%s %i\n", __func__, subs->endpoint); + dev_dbg(&subs->usx2y->dev->dev, "%s %i\n", __func__, subs->endpoint); for (i = 0; i < NRURBS; i++) usx2y_urb_release(subs->urb + i, subs != subs->usx2y->subs[SNDRV_PCM_STREAM_PLAYBACK]); @@ -505,7 +513,8 @@ static int usx2y_urbs_start(struct snd_usx2y_substream *subs) urb->transfer_buffer_length = subs->maxpacksize * nr_of_packs(); err = usb_submit_urb(urb, GFP_ATOMIC); if (err < 0) { - snd_printk(KERN_ERR "cannot submit datapipe for urb %d, err = %d\n", i, err); + dev_err(&urb->dev->dev, "%s: cannot submit datapipe for urb %d, err = %d\n", + __func__, i, err); err = -EPIPE; goto cleanup; } else { @@ -550,17 +559,16 @@ static int snd_usx2y_pcm_trigger(struct snd_pcm_substream *substream, int cmd) switch (cmd) { case SNDRV_PCM_TRIGGER_START: - snd_printdd("%s(START)\n", __func__); + dev_dbg(&subs->usx2y->dev->dev, "%s(START)\n", __func__); if (atomic_read(&subs->state) == STATE_PREPARED && atomic_read(&subs->usx2y->subs[SNDRV_PCM_STREAM_CAPTURE]->state) >= STATE_PREPARED) { atomic_set(&subs->state, STATE_PRERUNNING); } else { - snd_printdd("\n"); return -EPIPE; } break; case SNDRV_PCM_TRIGGER_STOP: - snd_printdd("%s(STOP)\n", __func__); + dev_dbg(&subs->usx2y->dev->dev, "%s(STOP)\n", __func__); if (atomic_read(&subs->state) >= STATE_PRERUNNING) atomic_set(&subs->state, STATE_PREPARED); break; @@ -661,7 +669,8 @@ static void i_usx2y_04int(struct urb *urb) struct usx2ydev *usx2y = urb->context; if (urb->status) - snd_printk(KERN_ERR "snd_usx2y_04int() urb->status=%i\n", urb->status); + dev_err(&urb->dev->dev, "%s() urb->status=%i\n", + __func__, urb->status); if (!--usx2y->us04->len) wake_up(&usx2y->in04_wait_queue); } @@ -751,7 +760,8 @@ static int usx2y_format_set(struct usx2ydev *usx2y, snd_pcm_format_t format) usb_kill_urb(usx2y->in04_urb); err = usb_set_interface(usx2y->dev, 0, alternate); if (err) { - snd_printk(KERN_ERR "usb_set_interface error\n"); + dev_err(&usx2y->dev->dev, "%s: usb_set_interface error\n", + __func__); return err; } usx2y->in04_urb->dev = usx2y->dev; @@ -778,7 +788,7 @@ static int snd_usx2y_pcm_hw_params(struct snd_pcm_substream *substream, int i; mutex_lock(&usx2y(card)->pcm_mutex); - snd_printdd("snd_usx2y_hw_params(%p, %p)\n", substream, hw_params); + dev_dbg(&dev->dev->dev, "%s(%p, %p)\n", __func__, substream, hw_params); /* all pcm substreams off one usx2y have to operate at the same * rate & format */ @@ -814,7 +824,7 @@ static int snd_usx2y_pcm_hw_free(struct snd_pcm_substream *substream) struct snd_usx2y_substream *cap_subs, *playback_subs; mutex_lock(&subs->usx2y->pcm_mutex); - snd_printdd("snd_usx2y_hw_free(%p)\n", substream); + dev_dbg(&subs->usx2y->dev->dev, "%s(%p)\n", __func__, substream); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { cap_subs = subs->usx2y->subs[SNDRV_PCM_STREAM_CAPTURE]; @@ -850,7 +860,7 @@ static int snd_usx2y_pcm_prepare(struct snd_pcm_substream *substream) struct snd_usx2y_substream *capsubs = subs->usx2y->subs[SNDRV_PCM_STREAM_CAPTURE]; int err = 0; - snd_printdd("%s(%p)\n", __func__, substream); + dev_dbg(&usx2y->dev->dev, "%s(%p)\n", __func__, substream); mutex_lock(&usx2y->pcm_mutex); usx2y_subs_prepare(subs); @@ -867,7 +877,8 @@ static int snd_usx2y_pcm_prepare(struct snd_pcm_substream *substream) if (err < 0) goto up_prepare_mutex; } - snd_printdd("starting capture pipe for %s\n", subs == capsubs ? "self" : "playpipe"); + dev_dbg(&usx2y->dev->dev, "%s: starting capture pipe for %s\n", + __func__, subs == capsubs ? "self" : "playpipe"); err = usx2y_urbs_start(capsubs); if (err < 0) goto up_prepare_mutex; diff --git a/sound/usb/usx2y/usx2yhwdeppcm.c b/sound/usb/usx2y/usx2yhwdeppcm.c index 36f2e31168fb0f..1b1496adb47eb2 100644 --- a/sound/usb/usx2y/usx2yhwdeppcm.c +++ b/sound/usb/usx2y/usx2yhwdeppcm.c @@ -59,13 +59,13 @@ static int usx2y_usbpcm_urb_capt_retire(struct snd_usx2y_substream *subs) if (head >= ARRAY_SIZE(usx2y->hwdep_pcm_shm->captured_iso)) head = 0; usx2y->hwdep_pcm_shm->capture_iso_start = head; - snd_printdd("cap start %i\n", head); + dev_dbg(&usx2y->dev->dev, "cap start %i\n", head); } for (i = 0; i < nr_of_packs(); i++) { if (urb->iso_frame_desc[i].status) { /* active? hmm, skip this */ - snd_printk(KERN_ERR - "active frame status %i. Most probably some hardware problem.\n", - urb->iso_frame_desc[i].status); + dev_err(&usx2y->dev->dev, + "active frame status %i. Most probably some hardware problem.\n", + urb->iso_frame_desc[i].status); return urb->iso_frame_desc[i].status; } lens += urb->iso_frame_desc[i].actual_length / usx2y->stride; @@ -120,7 +120,7 @@ static int usx2y_hwdep_urb_play_prepare(struct snd_usx2y_substream *subs, /* calculate the size of a packet */ counts = shm->captured_iso[shm->playback_iso_head].length / usx2y->stride; if (counts < 43 || counts > 50) { - snd_printk(KERN_ERR "should not be here with counts=%i\n", counts); + dev_err(&usx2y->dev->dev, "should not be here with counts=%i\n", counts); return -EPIPE; } /* set up descriptor */ @@ -234,10 +234,11 @@ static void i_usx2y_usbpcm_urb_complete(struct urb *urb) struct snd_usx2y_substream *capsubs, *capsubs2, *playbacksubs; if (unlikely(atomic_read(&subs->state) < STATE_PREPARED)) { - snd_printdd("hcd_frame=%i ep=%i%s status=%i start_frame=%i\n", - usb_get_current_frame_number(usx2y->dev), - subs->endpoint, usb_pipein(urb->pipe) ? "in" : "out", - urb->status, urb->start_frame); + dev_dbg(&usx2y->dev->dev, + "hcd_frame=%i ep=%i%s status=%i start_frame=%i\n", + usb_get_current_frame_number(usx2y->dev), + subs->endpoint, usb_pipein(urb->pipe) ? "in" : "out", + urb->status, urb->start_frame); return; } if (unlikely(urb->status)) { @@ -255,7 +256,6 @@ static void i_usx2y_usbpcm_urb_complete(struct urb *urb) if (!usx2y_usbpcm_usbframe_complete(capsubs, capsubs2, playbacksubs, urb->start_frame)) { usx2y->wait_iso_frame += nr_of_packs(); } else { - snd_printdd("\n"); usx2y_clients_stop(usx2y); } } @@ -275,7 +275,8 @@ static void usx2y_usbpcm_urbs_release(struct snd_usx2y_substream *subs) { int i; - snd_printdd("snd_usx2y_urbs_release() %i\n", subs->endpoint); + dev_dbg(&subs->usx2y->dev->dev, + "snd_usx2y_urbs_release() %i\n", subs->endpoint); for (i = 0; i < NRURBS; i++) usx2y_hwdep_urb_release(subs->urb + i); } @@ -365,7 +366,7 @@ static int snd_usx2y_usbpcm_hw_free(struct snd_pcm_substream *substream) struct snd_usx2y_substream *cap_subs2; mutex_lock(&subs->usx2y->pcm_mutex); - snd_printdd("%s(%p)\n", __func__, substream); + dev_dbg(&subs->usx2y->dev->dev, "%s(%p)\n", __func__, substream); cap_subs2 = subs->usx2y->subs[SNDRV_PCM_STREAM_CAPTURE + 2]; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { @@ -456,11 +457,12 @@ static int usx2y_usbpcm_urbs_start(struct snd_usx2y_substream *subs) urb->transfer_buffer_length = subs->maxpacksize * nr_of_packs(); err = usb_submit_urb(urb, GFP_KERNEL); if (err < 0) { - snd_printk(KERN_ERR "cannot usb_submit_urb() for urb %d, err = %d\n", u, err); + dev_err(&urb->dev->dev, + "cannot usb_submit_urb() for urb %d, err = %d\n", + u, err); err = -EPIPE; goto cleanup; } else { - snd_printdd("%i\n", urb->start_frame); if (!u) usx2y->wait_iso_frame = urb->start_frame; } @@ -500,7 +502,7 @@ static int snd_usx2y_usbpcm_prepare(struct snd_pcm_substream *substream) struct snd_usx2y_substream *capsubs = subs->usx2y->subs[SNDRV_PCM_STREAM_CAPTURE]; int err = 0; - snd_printdd("snd_usx2y_pcm_prepare(%p)\n", substream); + dev_dbg(&usx2y->dev->dev, "snd_usx2y_pcm_prepare(%p)\n", substream); mutex_lock(&usx2y->pcm_mutex); @@ -528,8 +530,9 @@ static int snd_usx2y_usbpcm_prepare(struct snd_pcm_substream *substream) if (err < 0) goto up_prepare_mutex; } - snd_printdd("starting capture pipe for %s\n", subs == capsubs ? - "self" : "playpipe"); + dev_dbg(&usx2y->dev->dev, + "starting capture pipe for %s\n", subs == capsubs ? + "self" : "playpipe"); err = usx2y_usbpcm_urbs_start(capsubs); if (err < 0) goto up_prepare_mutex; @@ -540,9 +543,10 @@ static int snd_usx2y_usbpcm_prepare(struct snd_pcm_substream *substream) if (atomic_read(&subs->state) < STATE_PREPARED) { while (usx2y_iso_frames_per_buffer(runtime, usx2y) > usx2y->hwdep_pcm_shm->captured_iso_frames) { - snd_printdd("Wait: iso_frames_per_buffer=%i,captured_iso_frames=%i\n", - usx2y_iso_frames_per_buffer(runtime, usx2y), - usx2y->hwdep_pcm_shm->captured_iso_frames); + dev_dbg(&usx2y->dev->dev, + "Wait: iso_frames_per_buffer=%i,captured_iso_frames=%i\n", + usx2y_iso_frames_per_buffer(runtime, usx2y), + usx2y->hwdep_pcm_shm->captured_iso_frames); if (msleep_interruptible(10)) { err = -ERESTARTSYS; goto up_prepare_mutex; @@ -552,9 +556,10 @@ static int snd_usx2y_usbpcm_prepare(struct snd_pcm_substream *substream) if (err < 0) goto up_prepare_mutex; } - snd_printdd("Ready: iso_frames_per_buffer=%i,captured_iso_frames=%i\n", - usx2y_iso_frames_per_buffer(runtime, usx2y), - usx2y->hwdep_pcm_shm->captured_iso_frames); + dev_dbg(&usx2y->dev->dev, + "Ready: iso_frames_per_buffer=%i,captured_iso_frames=%i\n", + usx2y_iso_frames_per_buffer(runtime, usx2y), + usx2y->hwdep_pcm_shm->captured_iso_frames); } else { usx2y->hwdep_pcm_shm->capture_iso_start = -1; } @@ -698,7 +703,8 @@ static int snd_usx2y_hwdep_pcm_mmap(struct snd_hwdep *hw, struct file *filp, str /* if userspace tries to mmap beyond end of our buffer, fail */ if (size > USX2Y_HWDEP_PCM_PAGES) { - snd_printd("%lu > %lu\n", size, (unsigned long)USX2Y_HWDEP_PCM_PAGES); + dev_dbg(hw->card->dev, "%s: %lu > %lu\n", __func__, + size, (unsigned long)USX2Y_HWDEP_PCM_PAGES); return -EINVAL; } diff --git a/tools/arch/arm64/include/asm/cputype.h b/tools/arch/arm64/include/asm/cputype.h index 7b32b99023a21d..5fd7caea441936 100644 --- a/tools/arch/arm64/include/asm/cputype.h +++ b/tools/arch/arm64/include/asm/cputype.h @@ -86,9 +86,14 @@ #define ARM_CPU_PART_CORTEX_X2 0xD48 #define ARM_CPU_PART_NEOVERSE_N2 0xD49 #define ARM_CPU_PART_CORTEX_A78C 0xD4B +#define ARM_CPU_PART_CORTEX_X1C 0xD4C +#define ARM_CPU_PART_CORTEX_X3 0xD4E #define ARM_CPU_PART_NEOVERSE_V2 0xD4F +#define ARM_CPU_PART_CORTEX_A720 0xD81 #define ARM_CPU_PART_CORTEX_X4 0xD82 #define ARM_CPU_PART_NEOVERSE_V3 0xD84 +#define ARM_CPU_PART_CORTEX_X925 0xD85 +#define ARM_CPU_PART_CORTEX_A725 0xD87 #define APM_CPU_PART_XGENE 0x000 #define APM_CPU_VAR_POTENZA 0x00 @@ -162,9 +167,14 @@ #define MIDR_CORTEX_X2 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X2) #define MIDR_NEOVERSE_N2 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_N2) #define MIDR_CORTEX_A78C MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A78C) +#define MIDR_CORTEX_X1C MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X1C) +#define MIDR_CORTEX_X3 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X3) #define MIDR_NEOVERSE_V2 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_V2) +#define MIDR_CORTEX_A720 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A720) #define MIDR_CORTEX_X4 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X4) #define MIDR_NEOVERSE_V3 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_V3) +#define MIDR_CORTEX_X925 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X925) +#define MIDR_CORTEX_A725 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A725) #define MIDR_THUNDERX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX) #define MIDR_THUNDERX_81XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_81XX) #define MIDR_THUNDERX_83XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_83XX) diff --git a/tools/arch/powerpc/include/uapi/asm/kvm.h b/tools/arch/powerpc/include/uapi/asm/kvm.h index 1691297a766a9c..eaeda001784ebb 100644 --- a/tools/arch/powerpc/include/uapi/asm/kvm.h +++ b/tools/arch/powerpc/include/uapi/asm/kvm.h @@ -645,6 +645,9 @@ struct kvm_ppc_cpu_char { #define KVM_REG_PPC_SIER3 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xc3) #define KVM_REG_PPC_DAWR1 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xc4) #define KVM_REG_PPC_DAWRX1 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xc5) +#define KVM_REG_PPC_DEXCR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xc6) +#define KVM_REG_PPC_HASHKEYR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xc7) +#define KVM_REG_PPC_HASHPKEYR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xc8) /* Transactional Memory checkpointed state: * This is all GPRs, all VSX regs and a subset of SPRs diff --git a/tools/arch/x86/include/asm/cpufeatures.h b/tools/arch/x86/include/asm/cpufeatures.h index 3c7434329661c6..dd4682857c1208 100644 --- a/tools/arch/x86/include/asm/cpufeatures.h +++ b/tools/arch/x86/include/asm/cpufeatures.h @@ -18,170 +18,170 @@ /* * Note: If the comment begins with a quoted string, that string is used - * in /proc/cpuinfo instead of the macro name. If the string is "", - * this feature bit is not displayed in /proc/cpuinfo at all. + * in /proc/cpuinfo instead of the macro name. Otherwise, this feature + * bit is not displayed in /proc/cpuinfo at all. * * When adding new features here that depend on other features, * please update the table in kernel/cpu/cpuid-deps.c as well. */ /* Intel-defined CPU features, CPUID level 0x00000001 (EDX), word 0 */ -#define X86_FEATURE_FPU ( 0*32+ 0) /* Onboard FPU */ -#define X86_FEATURE_VME ( 0*32+ 1) /* Virtual Mode Extensions */ -#define X86_FEATURE_DE ( 0*32+ 2) /* Debugging Extensions */ -#define X86_FEATURE_PSE ( 0*32+ 3) /* Page Size Extensions */ -#define X86_FEATURE_TSC ( 0*32+ 4) /* Time Stamp Counter */ -#define X86_FEATURE_MSR ( 0*32+ 5) /* Model-Specific Registers */ -#define X86_FEATURE_PAE ( 0*32+ 6) /* Physical Address Extensions */ -#define X86_FEATURE_MCE ( 0*32+ 7) /* Machine Check Exception */ -#define X86_FEATURE_CX8 ( 0*32+ 8) /* CMPXCHG8 instruction */ -#define X86_FEATURE_APIC ( 0*32+ 9) /* Onboard APIC */ -#define X86_FEATURE_SEP ( 0*32+11) /* SYSENTER/SYSEXIT */ -#define X86_FEATURE_MTRR ( 0*32+12) /* Memory Type Range Registers */ -#define X86_FEATURE_PGE ( 0*32+13) /* Page Global Enable */ -#define X86_FEATURE_MCA ( 0*32+14) /* Machine Check Architecture */ -#define X86_FEATURE_CMOV ( 0*32+15) /* CMOV instructions (plus FCMOVcc, FCOMI with FPU) */ -#define X86_FEATURE_PAT ( 0*32+16) /* Page Attribute Table */ -#define X86_FEATURE_PSE36 ( 0*32+17) /* 36-bit PSEs */ -#define X86_FEATURE_PN ( 0*32+18) /* Processor serial number */ -#define X86_FEATURE_CLFLUSH ( 0*32+19) /* CLFLUSH instruction */ +#define X86_FEATURE_FPU ( 0*32+ 0) /* "fpu" Onboard FPU */ +#define X86_FEATURE_VME ( 0*32+ 1) /* "vme" Virtual Mode Extensions */ +#define X86_FEATURE_DE ( 0*32+ 2) /* "de" Debugging Extensions */ +#define X86_FEATURE_PSE ( 0*32+ 3) /* "pse" Page Size Extensions */ +#define X86_FEATURE_TSC ( 0*32+ 4) /* "tsc" Time Stamp Counter */ +#define X86_FEATURE_MSR ( 0*32+ 5) /* "msr" Model-Specific Registers */ +#define X86_FEATURE_PAE ( 0*32+ 6) /* "pae" Physical Address Extensions */ +#define X86_FEATURE_MCE ( 0*32+ 7) /* "mce" Machine Check Exception */ +#define X86_FEATURE_CX8 ( 0*32+ 8) /* "cx8" CMPXCHG8 instruction */ +#define X86_FEATURE_APIC ( 0*32+ 9) /* "apic" Onboard APIC */ +#define X86_FEATURE_SEP ( 0*32+11) /* "sep" SYSENTER/SYSEXIT */ +#define X86_FEATURE_MTRR ( 0*32+12) /* "mtrr" Memory Type Range Registers */ +#define X86_FEATURE_PGE ( 0*32+13) /* "pge" Page Global Enable */ +#define X86_FEATURE_MCA ( 0*32+14) /* "mca" Machine Check Architecture */ +#define X86_FEATURE_CMOV ( 0*32+15) /* "cmov" CMOV instructions (plus FCMOVcc, FCOMI with FPU) */ +#define X86_FEATURE_PAT ( 0*32+16) /* "pat" Page Attribute Table */ +#define X86_FEATURE_PSE36 ( 0*32+17) /* "pse36" 36-bit PSEs */ +#define X86_FEATURE_PN ( 0*32+18) /* "pn" Processor serial number */ +#define X86_FEATURE_CLFLUSH ( 0*32+19) /* "clflush" CLFLUSH instruction */ #define X86_FEATURE_DS ( 0*32+21) /* "dts" Debug Store */ -#define X86_FEATURE_ACPI ( 0*32+22) /* ACPI via MSR */ -#define X86_FEATURE_MMX ( 0*32+23) /* Multimedia Extensions */ -#define X86_FEATURE_FXSR ( 0*32+24) /* FXSAVE/FXRSTOR, CR4.OSFXSR */ +#define X86_FEATURE_ACPI ( 0*32+22) /* "acpi" ACPI via MSR */ +#define X86_FEATURE_MMX ( 0*32+23) /* "mmx" Multimedia Extensions */ +#define X86_FEATURE_FXSR ( 0*32+24) /* "fxsr" FXSAVE/FXRSTOR, CR4.OSFXSR */ #define X86_FEATURE_XMM ( 0*32+25) /* "sse" */ #define X86_FEATURE_XMM2 ( 0*32+26) /* "sse2" */ #define X86_FEATURE_SELFSNOOP ( 0*32+27) /* "ss" CPU self snoop */ -#define X86_FEATURE_HT ( 0*32+28) /* Hyper-Threading */ +#define X86_FEATURE_HT ( 0*32+28) /* "ht" Hyper-Threading */ #define X86_FEATURE_ACC ( 0*32+29) /* "tm" Automatic clock control */ -#define X86_FEATURE_IA64 ( 0*32+30) /* IA-64 processor */ -#define X86_FEATURE_PBE ( 0*32+31) /* Pending Break Enable */ +#define X86_FEATURE_IA64 ( 0*32+30) /* "ia64" IA-64 processor */ +#define X86_FEATURE_PBE ( 0*32+31) /* "pbe" Pending Break Enable */ /* AMD-defined CPU features, CPUID level 0x80000001, word 1 */ /* Don't duplicate feature flags which are redundant with Intel! */ -#define X86_FEATURE_SYSCALL ( 1*32+11) /* SYSCALL/SYSRET */ -#define X86_FEATURE_MP ( 1*32+19) /* MP Capable */ -#define X86_FEATURE_NX ( 1*32+20) /* Execute Disable */ -#define X86_FEATURE_MMXEXT ( 1*32+22) /* AMD MMX extensions */ -#define X86_FEATURE_FXSR_OPT ( 1*32+25) /* FXSAVE/FXRSTOR optimizations */ +#define X86_FEATURE_SYSCALL ( 1*32+11) /* "syscall" SYSCALL/SYSRET */ +#define X86_FEATURE_MP ( 1*32+19) /* "mp" MP Capable */ +#define X86_FEATURE_NX ( 1*32+20) /* "nx" Execute Disable */ +#define X86_FEATURE_MMXEXT ( 1*32+22) /* "mmxext" AMD MMX extensions */ +#define X86_FEATURE_FXSR_OPT ( 1*32+25) /* "fxsr_opt" FXSAVE/FXRSTOR optimizations */ #define X86_FEATURE_GBPAGES ( 1*32+26) /* "pdpe1gb" GB pages */ -#define X86_FEATURE_RDTSCP ( 1*32+27) /* RDTSCP */ -#define X86_FEATURE_LM ( 1*32+29) /* Long Mode (x86-64, 64-bit support) */ -#define X86_FEATURE_3DNOWEXT ( 1*32+30) /* AMD 3DNow extensions */ -#define X86_FEATURE_3DNOW ( 1*32+31) /* 3DNow */ +#define X86_FEATURE_RDTSCP ( 1*32+27) /* "rdtscp" RDTSCP */ +#define X86_FEATURE_LM ( 1*32+29) /* "lm" Long Mode (x86-64, 64-bit support) */ +#define X86_FEATURE_3DNOWEXT ( 1*32+30) /* "3dnowext" AMD 3DNow extensions */ +#define X86_FEATURE_3DNOW ( 1*32+31) /* "3dnow" 3DNow */ /* Transmeta-defined CPU features, CPUID level 0x80860001, word 2 */ -#define X86_FEATURE_RECOVERY ( 2*32+ 0) /* CPU in recovery mode */ -#define X86_FEATURE_LONGRUN ( 2*32+ 1) /* Longrun power control */ -#define X86_FEATURE_LRTI ( 2*32+ 3) /* LongRun table interface */ +#define X86_FEATURE_RECOVERY ( 2*32+ 0) /* "recovery" CPU in recovery mode */ +#define X86_FEATURE_LONGRUN ( 2*32+ 1) /* "longrun" Longrun power control */ +#define X86_FEATURE_LRTI ( 2*32+ 3) /* "lrti" LongRun table interface */ /* Other features, Linux-defined mapping, word 3 */ /* This range is used for feature bits which conflict or are synthesized */ -#define X86_FEATURE_CXMMX ( 3*32+ 0) /* Cyrix MMX extensions */ -#define X86_FEATURE_K6_MTRR ( 3*32+ 1) /* AMD K6 nonstandard MTRRs */ -#define X86_FEATURE_CYRIX_ARR ( 3*32+ 2) /* Cyrix ARRs (= MTRRs) */ -#define X86_FEATURE_CENTAUR_MCR ( 3*32+ 3) /* Centaur MCRs (= MTRRs) */ -#define X86_FEATURE_K8 ( 3*32+ 4) /* "" Opteron, Athlon64 */ -#define X86_FEATURE_ZEN5 ( 3*32+ 5) /* "" CPU based on Zen5 microarchitecture */ -#define X86_FEATURE_P3 ( 3*32+ 6) /* "" P3 */ -#define X86_FEATURE_P4 ( 3*32+ 7) /* "" P4 */ -#define X86_FEATURE_CONSTANT_TSC ( 3*32+ 8) /* TSC ticks at a constant rate */ -#define X86_FEATURE_UP ( 3*32+ 9) /* SMP kernel running on UP */ -#define X86_FEATURE_ART ( 3*32+10) /* Always running timer (ART) */ -#define X86_FEATURE_ARCH_PERFMON ( 3*32+11) /* Intel Architectural PerfMon */ -#define X86_FEATURE_PEBS ( 3*32+12) /* Precise-Event Based Sampling */ -#define X86_FEATURE_BTS ( 3*32+13) /* Branch Trace Store */ -#define X86_FEATURE_SYSCALL32 ( 3*32+14) /* "" syscall in IA32 userspace */ -#define X86_FEATURE_SYSENTER32 ( 3*32+15) /* "" sysenter in IA32 userspace */ -#define X86_FEATURE_REP_GOOD ( 3*32+16) /* REP microcode works well */ -#define X86_FEATURE_AMD_LBR_V2 ( 3*32+17) /* AMD Last Branch Record Extension Version 2 */ -#define X86_FEATURE_CLEAR_CPU_BUF ( 3*32+18) /* "" Clear CPU buffers using VERW */ -#define X86_FEATURE_ACC_POWER ( 3*32+19) /* AMD Accumulated Power Mechanism */ -#define X86_FEATURE_NOPL ( 3*32+20) /* The NOPL (0F 1F) instructions */ -#define X86_FEATURE_ALWAYS ( 3*32+21) /* "" Always-present feature */ -#define X86_FEATURE_XTOPOLOGY ( 3*32+22) /* CPU topology enum extensions */ -#define X86_FEATURE_TSC_RELIABLE ( 3*32+23) /* TSC is known to be reliable */ -#define X86_FEATURE_NONSTOP_TSC ( 3*32+24) /* TSC does not stop in C states */ -#define X86_FEATURE_CPUID ( 3*32+25) /* CPU has CPUID instruction itself */ -#define X86_FEATURE_EXTD_APICID ( 3*32+26) /* Extended APICID (8 bits) */ -#define X86_FEATURE_AMD_DCM ( 3*32+27) /* AMD multi-node processor */ -#define X86_FEATURE_APERFMPERF ( 3*32+28) /* P-State hardware coordination feedback capability (APERF/MPERF MSRs) */ -#define X86_FEATURE_RAPL ( 3*32+29) /* AMD/Hygon RAPL interface */ -#define X86_FEATURE_NONSTOP_TSC_S3 ( 3*32+30) /* TSC doesn't stop in S3 state */ -#define X86_FEATURE_TSC_KNOWN_FREQ ( 3*32+31) /* TSC has known frequency */ +#define X86_FEATURE_CXMMX ( 3*32+ 0) /* "cxmmx" Cyrix MMX extensions */ +#define X86_FEATURE_K6_MTRR ( 3*32+ 1) /* "k6_mtrr" AMD K6 nonstandard MTRRs */ +#define X86_FEATURE_CYRIX_ARR ( 3*32+ 2) /* "cyrix_arr" Cyrix ARRs (= MTRRs) */ +#define X86_FEATURE_CENTAUR_MCR ( 3*32+ 3) /* "centaur_mcr" Centaur MCRs (= MTRRs) */ +#define X86_FEATURE_K8 ( 3*32+ 4) /* Opteron, Athlon64 */ +#define X86_FEATURE_ZEN5 ( 3*32+ 5) /* CPU based on Zen5 microarchitecture */ +#define X86_FEATURE_P3 ( 3*32+ 6) /* P3 */ +#define X86_FEATURE_P4 ( 3*32+ 7) /* P4 */ +#define X86_FEATURE_CONSTANT_TSC ( 3*32+ 8) /* "constant_tsc" TSC ticks at a constant rate */ +#define X86_FEATURE_UP ( 3*32+ 9) /* "up" SMP kernel running on UP */ +#define X86_FEATURE_ART ( 3*32+10) /* "art" Always running timer (ART) */ +#define X86_FEATURE_ARCH_PERFMON ( 3*32+11) /* "arch_perfmon" Intel Architectural PerfMon */ +#define X86_FEATURE_PEBS ( 3*32+12) /* "pebs" Precise-Event Based Sampling */ +#define X86_FEATURE_BTS ( 3*32+13) /* "bts" Branch Trace Store */ +#define X86_FEATURE_SYSCALL32 ( 3*32+14) /* syscall in IA32 userspace */ +#define X86_FEATURE_SYSENTER32 ( 3*32+15) /* sysenter in IA32 userspace */ +#define X86_FEATURE_REP_GOOD ( 3*32+16) /* "rep_good" REP microcode works well */ +#define X86_FEATURE_AMD_LBR_V2 ( 3*32+17) /* "amd_lbr_v2" AMD Last Branch Record Extension Version 2 */ +#define X86_FEATURE_CLEAR_CPU_BUF ( 3*32+18) /* Clear CPU buffers using VERW */ +#define X86_FEATURE_ACC_POWER ( 3*32+19) /* "acc_power" AMD Accumulated Power Mechanism */ +#define X86_FEATURE_NOPL ( 3*32+20) /* "nopl" The NOPL (0F 1F) instructions */ +#define X86_FEATURE_ALWAYS ( 3*32+21) /* Always-present feature */ +#define X86_FEATURE_XTOPOLOGY ( 3*32+22) /* "xtopology" CPU topology enum extensions */ +#define X86_FEATURE_TSC_RELIABLE ( 3*32+23) /* "tsc_reliable" TSC is known to be reliable */ +#define X86_FEATURE_NONSTOP_TSC ( 3*32+24) /* "nonstop_tsc" TSC does not stop in C states */ +#define X86_FEATURE_CPUID ( 3*32+25) /* "cpuid" CPU has CPUID instruction itself */ +#define X86_FEATURE_EXTD_APICID ( 3*32+26) /* "extd_apicid" Extended APICID (8 bits) */ +#define X86_FEATURE_AMD_DCM ( 3*32+27) /* "amd_dcm" AMD multi-node processor */ +#define X86_FEATURE_APERFMPERF ( 3*32+28) /* "aperfmperf" P-State hardware coordination feedback capability (APERF/MPERF MSRs) */ +#define X86_FEATURE_RAPL ( 3*32+29) /* "rapl" AMD/Hygon RAPL interface */ +#define X86_FEATURE_NONSTOP_TSC_S3 ( 3*32+30) /* "nonstop_tsc_s3" TSC doesn't stop in S3 state */ +#define X86_FEATURE_TSC_KNOWN_FREQ ( 3*32+31) /* "tsc_known_freq" TSC has known frequency */ /* Intel-defined CPU features, CPUID level 0x00000001 (ECX), word 4 */ #define X86_FEATURE_XMM3 ( 4*32+ 0) /* "pni" SSE-3 */ -#define X86_FEATURE_PCLMULQDQ ( 4*32+ 1) /* PCLMULQDQ instruction */ -#define X86_FEATURE_DTES64 ( 4*32+ 2) /* 64-bit Debug Store */ +#define X86_FEATURE_PCLMULQDQ ( 4*32+ 1) /* "pclmulqdq" PCLMULQDQ instruction */ +#define X86_FEATURE_DTES64 ( 4*32+ 2) /* "dtes64" 64-bit Debug Store */ #define X86_FEATURE_MWAIT ( 4*32+ 3) /* "monitor" MONITOR/MWAIT support */ #define X86_FEATURE_DSCPL ( 4*32+ 4) /* "ds_cpl" CPL-qualified (filtered) Debug Store */ -#define X86_FEATURE_VMX ( 4*32+ 5) /* Hardware virtualization */ -#define X86_FEATURE_SMX ( 4*32+ 6) /* Safer Mode eXtensions */ -#define X86_FEATURE_EST ( 4*32+ 7) /* Enhanced SpeedStep */ -#define X86_FEATURE_TM2 ( 4*32+ 8) /* Thermal Monitor 2 */ -#define X86_FEATURE_SSSE3 ( 4*32+ 9) /* Supplemental SSE-3 */ -#define X86_FEATURE_CID ( 4*32+10) /* Context ID */ -#define X86_FEATURE_SDBG ( 4*32+11) /* Silicon Debug */ -#define X86_FEATURE_FMA ( 4*32+12) /* Fused multiply-add */ -#define X86_FEATURE_CX16 ( 4*32+13) /* CMPXCHG16B instruction */ -#define X86_FEATURE_XTPR ( 4*32+14) /* Send Task Priority Messages */ -#define X86_FEATURE_PDCM ( 4*32+15) /* Perf/Debug Capabilities MSR */ -#define X86_FEATURE_PCID ( 4*32+17) /* Process Context Identifiers */ -#define X86_FEATURE_DCA ( 4*32+18) /* Direct Cache Access */ +#define X86_FEATURE_VMX ( 4*32+ 5) /* "vmx" Hardware virtualization */ +#define X86_FEATURE_SMX ( 4*32+ 6) /* "smx" Safer Mode eXtensions */ +#define X86_FEATURE_EST ( 4*32+ 7) /* "est" Enhanced SpeedStep */ +#define X86_FEATURE_TM2 ( 4*32+ 8) /* "tm2" Thermal Monitor 2 */ +#define X86_FEATURE_SSSE3 ( 4*32+ 9) /* "ssse3" Supplemental SSE-3 */ +#define X86_FEATURE_CID ( 4*32+10) /* "cid" Context ID */ +#define X86_FEATURE_SDBG ( 4*32+11) /* "sdbg" Silicon Debug */ +#define X86_FEATURE_FMA ( 4*32+12) /* "fma" Fused multiply-add */ +#define X86_FEATURE_CX16 ( 4*32+13) /* "cx16" CMPXCHG16B instruction */ +#define X86_FEATURE_XTPR ( 4*32+14) /* "xtpr" Send Task Priority Messages */ +#define X86_FEATURE_PDCM ( 4*32+15) /* "pdcm" Perf/Debug Capabilities MSR */ +#define X86_FEATURE_PCID ( 4*32+17) /* "pcid" Process Context Identifiers */ +#define X86_FEATURE_DCA ( 4*32+18) /* "dca" Direct Cache Access */ #define X86_FEATURE_XMM4_1 ( 4*32+19) /* "sse4_1" SSE-4.1 */ #define X86_FEATURE_XMM4_2 ( 4*32+20) /* "sse4_2" SSE-4.2 */ -#define X86_FEATURE_X2APIC ( 4*32+21) /* X2APIC */ -#define X86_FEATURE_MOVBE ( 4*32+22) /* MOVBE instruction */ -#define X86_FEATURE_POPCNT ( 4*32+23) /* POPCNT instruction */ -#define X86_FEATURE_TSC_DEADLINE_TIMER ( 4*32+24) /* TSC deadline timer */ -#define X86_FEATURE_AES ( 4*32+25) /* AES instructions */ -#define X86_FEATURE_XSAVE ( 4*32+26) /* XSAVE/XRSTOR/XSETBV/XGETBV instructions */ -#define X86_FEATURE_OSXSAVE ( 4*32+27) /* "" XSAVE instruction enabled in the OS */ -#define X86_FEATURE_AVX ( 4*32+28) /* Advanced Vector Extensions */ -#define X86_FEATURE_F16C ( 4*32+29) /* 16-bit FP conversions */ -#define X86_FEATURE_RDRAND ( 4*32+30) /* RDRAND instruction */ -#define X86_FEATURE_HYPERVISOR ( 4*32+31) /* Running on a hypervisor */ +#define X86_FEATURE_X2APIC ( 4*32+21) /* "x2apic" X2APIC */ +#define X86_FEATURE_MOVBE ( 4*32+22) /* "movbe" MOVBE instruction */ +#define X86_FEATURE_POPCNT ( 4*32+23) /* "popcnt" POPCNT instruction */ +#define X86_FEATURE_TSC_DEADLINE_TIMER ( 4*32+24) /* "tsc_deadline_timer" TSC deadline timer */ +#define X86_FEATURE_AES ( 4*32+25) /* "aes" AES instructions */ +#define X86_FEATURE_XSAVE ( 4*32+26) /* "xsave" XSAVE/XRSTOR/XSETBV/XGETBV instructions */ +#define X86_FEATURE_OSXSAVE ( 4*32+27) /* XSAVE instruction enabled in the OS */ +#define X86_FEATURE_AVX ( 4*32+28) /* "avx" Advanced Vector Extensions */ +#define X86_FEATURE_F16C ( 4*32+29) /* "f16c" 16-bit FP conversions */ +#define X86_FEATURE_RDRAND ( 4*32+30) /* "rdrand" RDRAND instruction */ +#define X86_FEATURE_HYPERVISOR ( 4*32+31) /* "hypervisor" Running on a hypervisor */ /* VIA/Cyrix/Centaur-defined CPU features, CPUID level 0xC0000001, word 5 */ #define X86_FEATURE_XSTORE ( 5*32+ 2) /* "rng" RNG present (xstore) */ #define X86_FEATURE_XSTORE_EN ( 5*32+ 3) /* "rng_en" RNG enabled */ #define X86_FEATURE_XCRYPT ( 5*32+ 6) /* "ace" on-CPU crypto (xcrypt) */ #define X86_FEATURE_XCRYPT_EN ( 5*32+ 7) /* "ace_en" on-CPU crypto enabled */ -#define X86_FEATURE_ACE2 ( 5*32+ 8) /* Advanced Cryptography Engine v2 */ -#define X86_FEATURE_ACE2_EN ( 5*32+ 9) /* ACE v2 enabled */ -#define X86_FEATURE_PHE ( 5*32+10) /* PadLock Hash Engine */ -#define X86_FEATURE_PHE_EN ( 5*32+11) /* PHE enabled */ -#define X86_FEATURE_PMM ( 5*32+12) /* PadLock Montgomery Multiplier */ -#define X86_FEATURE_PMM_EN ( 5*32+13) /* PMM enabled */ +#define X86_FEATURE_ACE2 ( 5*32+ 8) /* "ace2" Advanced Cryptography Engine v2 */ +#define X86_FEATURE_ACE2_EN ( 5*32+ 9) /* "ace2_en" ACE v2 enabled */ +#define X86_FEATURE_PHE ( 5*32+10) /* "phe" PadLock Hash Engine */ +#define X86_FEATURE_PHE_EN ( 5*32+11) /* "phe_en" PHE enabled */ +#define X86_FEATURE_PMM ( 5*32+12) /* "pmm" PadLock Montgomery Multiplier */ +#define X86_FEATURE_PMM_EN ( 5*32+13) /* "pmm_en" PMM enabled */ /* More extended AMD flags: CPUID level 0x80000001, ECX, word 6 */ -#define X86_FEATURE_LAHF_LM ( 6*32+ 0) /* LAHF/SAHF in long mode */ -#define X86_FEATURE_CMP_LEGACY ( 6*32+ 1) /* If yes HyperThreading not valid */ -#define X86_FEATURE_SVM ( 6*32+ 2) /* Secure Virtual Machine */ -#define X86_FEATURE_EXTAPIC ( 6*32+ 3) /* Extended APIC space */ -#define X86_FEATURE_CR8_LEGACY ( 6*32+ 4) /* CR8 in 32-bit mode */ -#define X86_FEATURE_ABM ( 6*32+ 5) /* Advanced bit manipulation */ -#define X86_FEATURE_SSE4A ( 6*32+ 6) /* SSE-4A */ -#define X86_FEATURE_MISALIGNSSE ( 6*32+ 7) /* Misaligned SSE mode */ -#define X86_FEATURE_3DNOWPREFETCH ( 6*32+ 8) /* 3DNow prefetch instructions */ -#define X86_FEATURE_OSVW ( 6*32+ 9) /* OS Visible Workaround */ -#define X86_FEATURE_IBS ( 6*32+10) /* Instruction Based Sampling */ -#define X86_FEATURE_XOP ( 6*32+11) /* extended AVX instructions */ -#define X86_FEATURE_SKINIT ( 6*32+12) /* SKINIT/STGI instructions */ -#define X86_FEATURE_WDT ( 6*32+13) /* Watchdog timer */ -#define X86_FEATURE_LWP ( 6*32+15) /* Light Weight Profiling */ -#define X86_FEATURE_FMA4 ( 6*32+16) /* 4 operands MAC instructions */ -#define X86_FEATURE_TCE ( 6*32+17) /* Translation Cache Extension */ -#define X86_FEATURE_NODEID_MSR ( 6*32+19) /* NodeId MSR */ -#define X86_FEATURE_TBM ( 6*32+21) /* Trailing Bit Manipulations */ -#define X86_FEATURE_TOPOEXT ( 6*32+22) /* Topology extensions CPUID leafs */ -#define X86_FEATURE_PERFCTR_CORE ( 6*32+23) /* Core performance counter extensions */ -#define X86_FEATURE_PERFCTR_NB ( 6*32+24) /* NB performance counter extensions */ -#define X86_FEATURE_BPEXT ( 6*32+26) /* Data breakpoint extension */ -#define X86_FEATURE_PTSC ( 6*32+27) /* Performance time-stamp counter */ -#define X86_FEATURE_PERFCTR_LLC ( 6*32+28) /* Last Level Cache performance counter extensions */ -#define X86_FEATURE_MWAITX ( 6*32+29) /* MWAIT extension (MONITORX/MWAITX instructions) */ +#define X86_FEATURE_LAHF_LM ( 6*32+ 0) /* "lahf_lm" LAHF/SAHF in long mode */ +#define X86_FEATURE_CMP_LEGACY ( 6*32+ 1) /* "cmp_legacy" If yes HyperThreading not valid */ +#define X86_FEATURE_SVM ( 6*32+ 2) /* "svm" Secure Virtual Machine */ +#define X86_FEATURE_EXTAPIC ( 6*32+ 3) /* "extapic" Extended APIC space */ +#define X86_FEATURE_CR8_LEGACY ( 6*32+ 4) /* "cr8_legacy" CR8 in 32-bit mode */ +#define X86_FEATURE_ABM ( 6*32+ 5) /* "abm" Advanced bit manipulation */ +#define X86_FEATURE_SSE4A ( 6*32+ 6) /* "sse4a" SSE-4A */ +#define X86_FEATURE_MISALIGNSSE ( 6*32+ 7) /* "misalignsse" Misaligned SSE mode */ +#define X86_FEATURE_3DNOWPREFETCH ( 6*32+ 8) /* "3dnowprefetch" 3DNow prefetch instructions */ +#define X86_FEATURE_OSVW ( 6*32+ 9) /* "osvw" OS Visible Workaround */ +#define X86_FEATURE_IBS ( 6*32+10) /* "ibs" Instruction Based Sampling */ +#define X86_FEATURE_XOP ( 6*32+11) /* "xop" Extended AVX instructions */ +#define X86_FEATURE_SKINIT ( 6*32+12) /* "skinit" SKINIT/STGI instructions */ +#define X86_FEATURE_WDT ( 6*32+13) /* "wdt" Watchdog timer */ +#define X86_FEATURE_LWP ( 6*32+15) /* "lwp" Light Weight Profiling */ +#define X86_FEATURE_FMA4 ( 6*32+16) /* "fma4" 4 operands MAC instructions */ +#define X86_FEATURE_TCE ( 6*32+17) /* "tce" Translation Cache Extension */ +#define X86_FEATURE_NODEID_MSR ( 6*32+19) /* "nodeid_msr" NodeId MSR */ +#define X86_FEATURE_TBM ( 6*32+21) /* "tbm" Trailing Bit Manipulations */ +#define X86_FEATURE_TOPOEXT ( 6*32+22) /* "topoext" Topology extensions CPUID leafs */ +#define X86_FEATURE_PERFCTR_CORE ( 6*32+23) /* "perfctr_core" Core performance counter extensions */ +#define X86_FEATURE_PERFCTR_NB ( 6*32+24) /* "perfctr_nb" NB performance counter extensions */ +#define X86_FEATURE_BPEXT ( 6*32+26) /* "bpext" Data breakpoint extension */ +#define X86_FEATURE_PTSC ( 6*32+27) /* "ptsc" Performance time-stamp counter */ +#define X86_FEATURE_PERFCTR_LLC ( 6*32+28) /* "perfctr_llc" Last Level Cache performance counter extensions */ +#define X86_FEATURE_MWAITX ( 6*32+29) /* "mwaitx" MWAIT extension (MONITORX/MWAITX instructions) */ /* * Auxiliary flags: Linux defined - For features scattered in various @@ -189,93 +189,93 @@ * * Reuse free bits when adding new feature flags! */ -#define X86_FEATURE_RING3MWAIT ( 7*32+ 0) /* Ring 3 MONITOR/MWAIT instructions */ -#define X86_FEATURE_CPUID_FAULT ( 7*32+ 1) /* Intel CPUID faulting */ -#define X86_FEATURE_CPB ( 7*32+ 2) /* AMD Core Performance Boost */ -#define X86_FEATURE_EPB ( 7*32+ 3) /* IA32_ENERGY_PERF_BIAS support */ -#define X86_FEATURE_CAT_L3 ( 7*32+ 4) /* Cache Allocation Technology L3 */ -#define X86_FEATURE_CAT_L2 ( 7*32+ 5) /* Cache Allocation Technology L2 */ -#define X86_FEATURE_CDP_L3 ( 7*32+ 6) /* Code and Data Prioritization L3 */ -#define X86_FEATURE_TDX_HOST_PLATFORM ( 7*32+ 7) /* Platform supports being a TDX host */ -#define X86_FEATURE_HW_PSTATE ( 7*32+ 8) /* AMD HW-PState */ -#define X86_FEATURE_PROC_FEEDBACK ( 7*32+ 9) /* AMD ProcFeedbackInterface */ -#define X86_FEATURE_XCOMPACTED ( 7*32+10) /* "" Use compacted XSTATE (XSAVES or XSAVEC) */ -#define X86_FEATURE_PTI ( 7*32+11) /* Kernel Page Table Isolation enabled */ -#define X86_FEATURE_KERNEL_IBRS ( 7*32+12) /* "" Set/clear IBRS on kernel entry/exit */ -#define X86_FEATURE_RSB_VMEXIT ( 7*32+13) /* "" Fill RSB on VM-Exit */ -#define X86_FEATURE_INTEL_PPIN ( 7*32+14) /* Intel Processor Inventory Number */ -#define X86_FEATURE_CDP_L2 ( 7*32+15) /* Code and Data Prioritization L2 */ -#define X86_FEATURE_MSR_SPEC_CTRL ( 7*32+16) /* "" MSR SPEC_CTRL is implemented */ -#define X86_FEATURE_SSBD ( 7*32+17) /* Speculative Store Bypass Disable */ -#define X86_FEATURE_MBA ( 7*32+18) /* Memory Bandwidth Allocation */ -#define X86_FEATURE_RSB_CTXSW ( 7*32+19) /* "" Fill RSB on context switches */ -#define X86_FEATURE_PERFMON_V2 ( 7*32+20) /* AMD Performance Monitoring Version 2 */ -#define X86_FEATURE_USE_IBPB ( 7*32+21) /* "" Indirect Branch Prediction Barrier enabled */ -#define X86_FEATURE_USE_IBRS_FW ( 7*32+22) /* "" Use IBRS during runtime firmware calls */ -#define X86_FEATURE_SPEC_STORE_BYPASS_DISABLE ( 7*32+23) /* "" Disable Speculative Store Bypass. */ -#define X86_FEATURE_LS_CFG_SSBD ( 7*32+24) /* "" AMD SSBD implementation via LS_CFG MSR */ -#define X86_FEATURE_IBRS ( 7*32+25) /* Indirect Branch Restricted Speculation */ -#define X86_FEATURE_IBPB ( 7*32+26) /* Indirect Branch Prediction Barrier */ -#define X86_FEATURE_STIBP ( 7*32+27) /* Single Thread Indirect Branch Predictors */ -#define X86_FEATURE_ZEN ( 7*32+28) /* "" Generic flag for all Zen and newer */ -#define X86_FEATURE_L1TF_PTEINV ( 7*32+29) /* "" L1TF workaround PTE inversion */ -#define X86_FEATURE_IBRS_ENHANCED ( 7*32+30) /* Enhanced IBRS */ -#define X86_FEATURE_MSR_IA32_FEAT_CTL ( 7*32+31) /* "" MSR IA32_FEAT_CTL configured */ +#define X86_FEATURE_RING3MWAIT ( 7*32+ 0) /* "ring3mwait" Ring 3 MONITOR/MWAIT instructions */ +#define X86_FEATURE_CPUID_FAULT ( 7*32+ 1) /* "cpuid_fault" Intel CPUID faulting */ +#define X86_FEATURE_CPB ( 7*32+ 2) /* "cpb" AMD Core Performance Boost */ +#define X86_FEATURE_EPB ( 7*32+ 3) /* "epb" IA32_ENERGY_PERF_BIAS support */ +#define X86_FEATURE_CAT_L3 ( 7*32+ 4) /* "cat_l3" Cache Allocation Technology L3 */ +#define X86_FEATURE_CAT_L2 ( 7*32+ 5) /* "cat_l2" Cache Allocation Technology L2 */ +#define X86_FEATURE_CDP_L3 ( 7*32+ 6) /* "cdp_l3" Code and Data Prioritization L3 */ +#define X86_FEATURE_TDX_HOST_PLATFORM ( 7*32+ 7) /* "tdx_host_platform" Platform supports being a TDX host */ +#define X86_FEATURE_HW_PSTATE ( 7*32+ 8) /* "hw_pstate" AMD HW-PState */ +#define X86_FEATURE_PROC_FEEDBACK ( 7*32+ 9) /* "proc_feedback" AMD ProcFeedbackInterface */ +#define X86_FEATURE_XCOMPACTED ( 7*32+10) /* Use compacted XSTATE (XSAVES or XSAVEC) */ +#define X86_FEATURE_PTI ( 7*32+11) /* "pti" Kernel Page Table Isolation enabled */ +#define X86_FEATURE_KERNEL_IBRS ( 7*32+12) /* Set/clear IBRS on kernel entry/exit */ +#define X86_FEATURE_RSB_VMEXIT ( 7*32+13) /* Fill RSB on VM-Exit */ +#define X86_FEATURE_INTEL_PPIN ( 7*32+14) /* "intel_ppin" Intel Processor Inventory Number */ +#define X86_FEATURE_CDP_L2 ( 7*32+15) /* "cdp_l2" Code and Data Prioritization L2 */ +#define X86_FEATURE_MSR_SPEC_CTRL ( 7*32+16) /* MSR SPEC_CTRL is implemented */ +#define X86_FEATURE_SSBD ( 7*32+17) /* "ssbd" Speculative Store Bypass Disable */ +#define X86_FEATURE_MBA ( 7*32+18) /* "mba" Memory Bandwidth Allocation */ +#define X86_FEATURE_RSB_CTXSW ( 7*32+19) /* Fill RSB on context switches */ +#define X86_FEATURE_PERFMON_V2 ( 7*32+20) /* "perfmon_v2" AMD Performance Monitoring Version 2 */ +#define X86_FEATURE_USE_IBPB ( 7*32+21) /* Indirect Branch Prediction Barrier enabled */ +#define X86_FEATURE_USE_IBRS_FW ( 7*32+22) /* Use IBRS during runtime firmware calls */ +#define X86_FEATURE_SPEC_STORE_BYPASS_DISABLE ( 7*32+23) /* Disable Speculative Store Bypass. */ +#define X86_FEATURE_LS_CFG_SSBD ( 7*32+24) /* AMD SSBD implementation via LS_CFG MSR */ +#define X86_FEATURE_IBRS ( 7*32+25) /* "ibrs" Indirect Branch Restricted Speculation */ +#define X86_FEATURE_IBPB ( 7*32+26) /* "ibpb" Indirect Branch Prediction Barrier */ +#define X86_FEATURE_STIBP ( 7*32+27) /* "stibp" Single Thread Indirect Branch Predictors */ +#define X86_FEATURE_ZEN ( 7*32+28) /* Generic flag for all Zen and newer */ +#define X86_FEATURE_L1TF_PTEINV ( 7*32+29) /* L1TF workaround PTE inversion */ +#define X86_FEATURE_IBRS_ENHANCED ( 7*32+30) /* "ibrs_enhanced" Enhanced IBRS */ +#define X86_FEATURE_MSR_IA32_FEAT_CTL ( 7*32+31) /* MSR IA32_FEAT_CTL configured */ /* Virtualization flags: Linux defined, word 8 */ -#define X86_FEATURE_TPR_SHADOW ( 8*32+ 0) /* Intel TPR Shadow */ -#define X86_FEATURE_FLEXPRIORITY ( 8*32+ 1) /* Intel FlexPriority */ -#define X86_FEATURE_EPT ( 8*32+ 2) /* Intel Extended Page Table */ -#define X86_FEATURE_VPID ( 8*32+ 3) /* Intel Virtual Processor ID */ +#define X86_FEATURE_TPR_SHADOW ( 8*32+ 0) /* "tpr_shadow" Intel TPR Shadow */ +#define X86_FEATURE_FLEXPRIORITY ( 8*32+ 1) /* "flexpriority" Intel FlexPriority */ +#define X86_FEATURE_EPT ( 8*32+ 2) /* "ept" Intel Extended Page Table */ +#define X86_FEATURE_VPID ( 8*32+ 3) /* "vpid" Intel Virtual Processor ID */ -#define X86_FEATURE_VMMCALL ( 8*32+15) /* Prefer VMMCALL to VMCALL */ -#define X86_FEATURE_XENPV ( 8*32+16) /* "" Xen paravirtual guest */ -#define X86_FEATURE_EPT_AD ( 8*32+17) /* Intel Extended Page Table access-dirty bit */ -#define X86_FEATURE_VMCALL ( 8*32+18) /* "" Hypervisor supports the VMCALL instruction */ -#define X86_FEATURE_VMW_VMMCALL ( 8*32+19) /* "" VMware prefers VMMCALL hypercall instruction */ -#define X86_FEATURE_PVUNLOCK ( 8*32+20) /* "" PV unlock function */ -#define X86_FEATURE_VCPUPREEMPT ( 8*32+21) /* "" PV vcpu_is_preempted function */ -#define X86_FEATURE_TDX_GUEST ( 8*32+22) /* Intel Trust Domain Extensions Guest */ +#define X86_FEATURE_VMMCALL ( 8*32+15) /* "vmmcall" Prefer VMMCALL to VMCALL */ +#define X86_FEATURE_XENPV ( 8*32+16) /* Xen paravirtual guest */ +#define X86_FEATURE_EPT_AD ( 8*32+17) /* "ept_ad" Intel Extended Page Table access-dirty bit */ +#define X86_FEATURE_VMCALL ( 8*32+18) /* Hypervisor supports the VMCALL instruction */ +#define X86_FEATURE_VMW_VMMCALL ( 8*32+19) /* VMware prefers VMMCALL hypercall instruction */ +#define X86_FEATURE_PVUNLOCK ( 8*32+20) /* PV unlock function */ +#define X86_FEATURE_VCPUPREEMPT ( 8*32+21) /* PV vcpu_is_preempted function */ +#define X86_FEATURE_TDX_GUEST ( 8*32+22) /* "tdx_guest" Intel Trust Domain Extensions Guest */ /* Intel-defined CPU features, CPUID level 0x00000007:0 (EBX), word 9 */ -#define X86_FEATURE_FSGSBASE ( 9*32+ 0) /* RDFSBASE, WRFSBASE, RDGSBASE, WRGSBASE instructions*/ -#define X86_FEATURE_TSC_ADJUST ( 9*32+ 1) /* TSC adjustment MSR 0x3B */ -#define X86_FEATURE_SGX ( 9*32+ 2) /* Software Guard Extensions */ -#define X86_FEATURE_BMI1 ( 9*32+ 3) /* 1st group bit manipulation extensions */ -#define X86_FEATURE_HLE ( 9*32+ 4) /* Hardware Lock Elision */ -#define X86_FEATURE_AVX2 ( 9*32+ 5) /* AVX2 instructions */ -#define X86_FEATURE_FDP_EXCPTN_ONLY ( 9*32+ 6) /* "" FPU data pointer updated only on x87 exceptions */ -#define X86_FEATURE_SMEP ( 9*32+ 7) /* Supervisor Mode Execution Protection */ -#define X86_FEATURE_BMI2 ( 9*32+ 8) /* 2nd group bit manipulation extensions */ -#define X86_FEATURE_ERMS ( 9*32+ 9) /* Enhanced REP MOVSB/STOSB instructions */ -#define X86_FEATURE_INVPCID ( 9*32+10) /* Invalidate Processor Context ID */ -#define X86_FEATURE_RTM ( 9*32+11) /* Restricted Transactional Memory */ -#define X86_FEATURE_CQM ( 9*32+12) /* Cache QoS Monitoring */ -#define X86_FEATURE_ZERO_FCS_FDS ( 9*32+13) /* "" Zero out FPU CS and FPU DS */ -#define X86_FEATURE_MPX ( 9*32+14) /* Memory Protection Extension */ -#define X86_FEATURE_RDT_A ( 9*32+15) /* Resource Director Technology Allocation */ -#define X86_FEATURE_AVX512F ( 9*32+16) /* AVX-512 Foundation */ -#define X86_FEATURE_AVX512DQ ( 9*32+17) /* AVX-512 DQ (Double/Quad granular) Instructions */ -#define X86_FEATURE_RDSEED ( 9*32+18) /* RDSEED instruction */ -#define X86_FEATURE_ADX ( 9*32+19) /* ADCX and ADOX instructions */ -#define X86_FEATURE_SMAP ( 9*32+20) /* Supervisor Mode Access Prevention */ -#define X86_FEATURE_AVX512IFMA ( 9*32+21) /* AVX-512 Integer Fused Multiply-Add instructions */ -#define X86_FEATURE_CLFLUSHOPT ( 9*32+23) /* CLFLUSHOPT instruction */ -#define X86_FEATURE_CLWB ( 9*32+24) /* CLWB instruction */ -#define X86_FEATURE_INTEL_PT ( 9*32+25) /* Intel Processor Trace */ -#define X86_FEATURE_AVX512PF ( 9*32+26) /* AVX-512 Prefetch */ -#define X86_FEATURE_AVX512ER ( 9*32+27) /* AVX-512 Exponential and Reciprocal */ -#define X86_FEATURE_AVX512CD ( 9*32+28) /* AVX-512 Conflict Detection */ -#define X86_FEATURE_SHA_NI ( 9*32+29) /* SHA1/SHA256 Instruction Extensions */ -#define X86_FEATURE_AVX512BW ( 9*32+30) /* AVX-512 BW (Byte/Word granular) Instructions */ -#define X86_FEATURE_AVX512VL ( 9*32+31) /* AVX-512 VL (128/256 Vector Length) Extensions */ +#define X86_FEATURE_FSGSBASE ( 9*32+ 0) /* "fsgsbase" RDFSBASE, WRFSBASE, RDGSBASE, WRGSBASE instructions*/ +#define X86_FEATURE_TSC_ADJUST ( 9*32+ 1) /* "tsc_adjust" TSC adjustment MSR 0x3B */ +#define X86_FEATURE_SGX ( 9*32+ 2) /* "sgx" Software Guard Extensions */ +#define X86_FEATURE_BMI1 ( 9*32+ 3) /* "bmi1" 1st group bit manipulation extensions */ +#define X86_FEATURE_HLE ( 9*32+ 4) /* "hle" Hardware Lock Elision */ +#define X86_FEATURE_AVX2 ( 9*32+ 5) /* "avx2" AVX2 instructions */ +#define X86_FEATURE_FDP_EXCPTN_ONLY ( 9*32+ 6) /* FPU data pointer updated only on x87 exceptions */ +#define X86_FEATURE_SMEP ( 9*32+ 7) /* "smep" Supervisor Mode Execution Protection */ +#define X86_FEATURE_BMI2 ( 9*32+ 8) /* "bmi2" 2nd group bit manipulation extensions */ +#define X86_FEATURE_ERMS ( 9*32+ 9) /* "erms" Enhanced REP MOVSB/STOSB instructions */ +#define X86_FEATURE_INVPCID ( 9*32+10) /* "invpcid" Invalidate Processor Context ID */ +#define X86_FEATURE_RTM ( 9*32+11) /* "rtm" Restricted Transactional Memory */ +#define X86_FEATURE_CQM ( 9*32+12) /* "cqm" Cache QoS Monitoring */ +#define X86_FEATURE_ZERO_FCS_FDS ( 9*32+13) /* Zero out FPU CS and FPU DS */ +#define X86_FEATURE_MPX ( 9*32+14) /* "mpx" Memory Protection Extension */ +#define X86_FEATURE_RDT_A ( 9*32+15) /* "rdt_a" Resource Director Technology Allocation */ +#define X86_FEATURE_AVX512F ( 9*32+16) /* "avx512f" AVX-512 Foundation */ +#define X86_FEATURE_AVX512DQ ( 9*32+17) /* "avx512dq" AVX-512 DQ (Double/Quad granular) Instructions */ +#define X86_FEATURE_RDSEED ( 9*32+18) /* "rdseed" RDSEED instruction */ +#define X86_FEATURE_ADX ( 9*32+19) /* "adx" ADCX and ADOX instructions */ +#define X86_FEATURE_SMAP ( 9*32+20) /* "smap" Supervisor Mode Access Prevention */ +#define X86_FEATURE_AVX512IFMA ( 9*32+21) /* "avx512ifma" AVX-512 Integer Fused Multiply-Add instructions */ +#define X86_FEATURE_CLFLUSHOPT ( 9*32+23) /* "clflushopt" CLFLUSHOPT instruction */ +#define X86_FEATURE_CLWB ( 9*32+24) /* "clwb" CLWB instruction */ +#define X86_FEATURE_INTEL_PT ( 9*32+25) /* "intel_pt" Intel Processor Trace */ +#define X86_FEATURE_AVX512PF ( 9*32+26) /* "avx512pf" AVX-512 Prefetch */ +#define X86_FEATURE_AVX512ER ( 9*32+27) /* "avx512er" AVX-512 Exponential and Reciprocal */ +#define X86_FEATURE_AVX512CD ( 9*32+28) /* "avx512cd" AVX-512 Conflict Detection */ +#define X86_FEATURE_SHA_NI ( 9*32+29) /* "sha_ni" SHA1/SHA256 Instruction Extensions */ +#define X86_FEATURE_AVX512BW ( 9*32+30) /* "avx512bw" AVX-512 BW (Byte/Word granular) Instructions */ +#define X86_FEATURE_AVX512VL ( 9*32+31) /* "avx512vl" AVX-512 VL (128/256 Vector Length) Extensions */ /* Extended state features, CPUID level 0x0000000d:1 (EAX), word 10 */ -#define X86_FEATURE_XSAVEOPT (10*32+ 0) /* XSAVEOPT instruction */ -#define X86_FEATURE_XSAVEC (10*32+ 1) /* XSAVEC instruction */ -#define X86_FEATURE_XGETBV1 (10*32+ 2) /* XGETBV with ECX = 1 instruction */ -#define X86_FEATURE_XSAVES (10*32+ 3) /* XSAVES/XRSTORS instructions */ -#define X86_FEATURE_XFD (10*32+ 4) /* "" eXtended Feature Disabling */ +#define X86_FEATURE_XSAVEOPT (10*32+ 0) /* "xsaveopt" XSAVEOPT instruction */ +#define X86_FEATURE_XSAVEC (10*32+ 1) /* "xsavec" XSAVEC instruction */ +#define X86_FEATURE_XGETBV1 (10*32+ 2) /* "xgetbv1" XGETBV with ECX = 1 instruction */ +#define X86_FEATURE_XSAVES (10*32+ 3) /* "xsaves" XSAVES/XRSTORS instructions */ +#define X86_FEATURE_XFD (10*32+ 4) /* eXtended Feature Disabling */ /* * Extended auxiliary flags: Linux defined - for features scattered in various @@ -283,181 +283,183 @@ * * Reuse free bits when adding new feature flags! */ -#define X86_FEATURE_CQM_LLC (11*32+ 0) /* LLC QoS if 1 */ -#define X86_FEATURE_CQM_OCCUP_LLC (11*32+ 1) /* LLC occupancy monitoring */ -#define X86_FEATURE_CQM_MBM_TOTAL (11*32+ 2) /* LLC Total MBM monitoring */ -#define X86_FEATURE_CQM_MBM_LOCAL (11*32+ 3) /* LLC Local MBM monitoring */ -#define X86_FEATURE_FENCE_SWAPGS_USER (11*32+ 4) /* "" LFENCE in user entry SWAPGS path */ -#define X86_FEATURE_FENCE_SWAPGS_KERNEL (11*32+ 5) /* "" LFENCE in kernel entry SWAPGS path */ -#define X86_FEATURE_SPLIT_LOCK_DETECT (11*32+ 6) /* #AC for split lock */ -#define X86_FEATURE_PER_THREAD_MBA (11*32+ 7) /* "" Per-thread Memory Bandwidth Allocation */ -#define X86_FEATURE_SGX1 (11*32+ 8) /* "" Basic SGX */ -#define X86_FEATURE_SGX2 (11*32+ 9) /* "" SGX Enclave Dynamic Memory Management (EDMM) */ -#define X86_FEATURE_ENTRY_IBPB (11*32+10) /* "" Issue an IBPB on kernel entry */ -#define X86_FEATURE_RRSBA_CTRL (11*32+11) /* "" RET prediction control */ -#define X86_FEATURE_RETPOLINE (11*32+12) /* "" Generic Retpoline mitigation for Spectre variant 2 */ -#define X86_FEATURE_RETPOLINE_LFENCE (11*32+13) /* "" Use LFENCE for Spectre variant 2 */ -#define X86_FEATURE_RETHUNK (11*32+14) /* "" Use REturn THUNK */ -#define X86_FEATURE_UNRET (11*32+15) /* "" AMD BTB untrain return */ -#define X86_FEATURE_USE_IBPB_FW (11*32+16) /* "" Use IBPB during runtime firmware calls */ -#define X86_FEATURE_RSB_VMEXIT_LITE (11*32+17) /* "" Fill RSB on VM exit when EIBRS is enabled */ -#define X86_FEATURE_SGX_EDECCSSA (11*32+18) /* "" SGX EDECCSSA user leaf function */ -#define X86_FEATURE_CALL_DEPTH (11*32+19) /* "" Call depth tracking for RSB stuffing */ -#define X86_FEATURE_MSR_TSX_CTRL (11*32+20) /* "" MSR IA32_TSX_CTRL (Intel) implemented */ -#define X86_FEATURE_SMBA (11*32+21) /* "" Slow Memory Bandwidth Allocation */ -#define X86_FEATURE_BMEC (11*32+22) /* "" Bandwidth Monitoring Event Configuration */ -#define X86_FEATURE_USER_SHSTK (11*32+23) /* Shadow stack support for user mode applications */ -#define X86_FEATURE_SRSO (11*32+24) /* "" AMD BTB untrain RETs */ -#define X86_FEATURE_SRSO_ALIAS (11*32+25) /* "" AMD BTB untrain RETs through aliasing */ -#define X86_FEATURE_IBPB_ON_VMEXIT (11*32+26) /* "" Issue an IBPB only on VMEXIT */ -#define X86_FEATURE_APIC_MSRS_FENCE (11*32+27) /* "" IA32_TSC_DEADLINE and X2APIC MSRs need fencing */ -#define X86_FEATURE_ZEN2 (11*32+28) /* "" CPU based on Zen2 microarchitecture */ -#define X86_FEATURE_ZEN3 (11*32+29) /* "" CPU based on Zen3 microarchitecture */ -#define X86_FEATURE_ZEN4 (11*32+30) /* "" CPU based on Zen4 microarchitecture */ -#define X86_FEATURE_ZEN1 (11*32+31) /* "" CPU based on Zen1 microarchitecture */ +#define X86_FEATURE_CQM_LLC (11*32+ 0) /* "cqm_llc" LLC QoS if 1 */ +#define X86_FEATURE_CQM_OCCUP_LLC (11*32+ 1) /* "cqm_occup_llc" LLC occupancy monitoring */ +#define X86_FEATURE_CQM_MBM_TOTAL (11*32+ 2) /* "cqm_mbm_total" LLC Total MBM monitoring */ +#define X86_FEATURE_CQM_MBM_LOCAL (11*32+ 3) /* "cqm_mbm_local" LLC Local MBM monitoring */ +#define X86_FEATURE_FENCE_SWAPGS_USER (11*32+ 4) /* LFENCE in user entry SWAPGS path */ +#define X86_FEATURE_FENCE_SWAPGS_KERNEL (11*32+ 5) /* LFENCE in kernel entry SWAPGS path */ +#define X86_FEATURE_SPLIT_LOCK_DETECT (11*32+ 6) /* "split_lock_detect" #AC for split lock */ +#define X86_FEATURE_PER_THREAD_MBA (11*32+ 7) /* Per-thread Memory Bandwidth Allocation */ +#define X86_FEATURE_SGX1 (11*32+ 8) /* Basic SGX */ +#define X86_FEATURE_SGX2 (11*32+ 9) /* SGX Enclave Dynamic Memory Management (EDMM) */ +#define X86_FEATURE_ENTRY_IBPB (11*32+10) /* Issue an IBPB on kernel entry */ +#define X86_FEATURE_RRSBA_CTRL (11*32+11) /* RET prediction control */ +#define X86_FEATURE_RETPOLINE (11*32+12) /* Generic Retpoline mitigation for Spectre variant 2 */ +#define X86_FEATURE_RETPOLINE_LFENCE (11*32+13) /* Use LFENCE for Spectre variant 2 */ +#define X86_FEATURE_RETHUNK (11*32+14) /* Use REturn THUNK */ +#define X86_FEATURE_UNRET (11*32+15) /* AMD BTB untrain return */ +#define X86_FEATURE_USE_IBPB_FW (11*32+16) /* Use IBPB during runtime firmware calls */ +#define X86_FEATURE_RSB_VMEXIT_LITE (11*32+17) /* Fill RSB on VM exit when EIBRS is enabled */ +#define X86_FEATURE_SGX_EDECCSSA (11*32+18) /* SGX EDECCSSA user leaf function */ +#define X86_FEATURE_CALL_DEPTH (11*32+19) /* Call depth tracking for RSB stuffing */ +#define X86_FEATURE_MSR_TSX_CTRL (11*32+20) /* MSR IA32_TSX_CTRL (Intel) implemented */ +#define X86_FEATURE_SMBA (11*32+21) /* Slow Memory Bandwidth Allocation */ +#define X86_FEATURE_BMEC (11*32+22) /* Bandwidth Monitoring Event Configuration */ +#define X86_FEATURE_USER_SHSTK (11*32+23) /* "user_shstk" Shadow stack support for user mode applications */ +#define X86_FEATURE_SRSO (11*32+24) /* AMD BTB untrain RETs */ +#define X86_FEATURE_SRSO_ALIAS (11*32+25) /* AMD BTB untrain RETs through aliasing */ +#define X86_FEATURE_IBPB_ON_VMEXIT (11*32+26) /* Issue an IBPB only on VMEXIT */ +#define X86_FEATURE_APIC_MSRS_FENCE (11*32+27) /* IA32_TSC_DEADLINE and X2APIC MSRs need fencing */ +#define X86_FEATURE_ZEN2 (11*32+28) /* CPU based on Zen2 microarchitecture */ +#define X86_FEATURE_ZEN3 (11*32+29) /* CPU based on Zen3 microarchitecture */ +#define X86_FEATURE_ZEN4 (11*32+30) /* CPU based on Zen4 microarchitecture */ +#define X86_FEATURE_ZEN1 (11*32+31) /* CPU based on Zen1 microarchitecture */ /* Intel-defined CPU features, CPUID level 0x00000007:1 (EAX), word 12 */ -#define X86_FEATURE_AVX_VNNI (12*32+ 4) /* AVX VNNI instructions */ -#define X86_FEATURE_AVX512_BF16 (12*32+ 5) /* AVX512 BFLOAT16 instructions */ -#define X86_FEATURE_CMPCCXADD (12*32+ 7) /* "" CMPccXADD instructions */ -#define X86_FEATURE_ARCH_PERFMON_EXT (12*32+ 8) /* "" Intel Architectural PerfMon Extension */ -#define X86_FEATURE_FZRM (12*32+10) /* "" Fast zero-length REP MOVSB */ -#define X86_FEATURE_FSRS (12*32+11) /* "" Fast short REP STOSB */ -#define X86_FEATURE_FSRC (12*32+12) /* "" Fast short REP {CMPSB,SCASB} */ -#define X86_FEATURE_FRED (12*32+17) /* Flexible Return and Event Delivery */ -#define X86_FEATURE_LKGS (12*32+18) /* "" Load "kernel" (userspace) GS */ -#define X86_FEATURE_WRMSRNS (12*32+19) /* "" Non-serializing WRMSR */ -#define X86_FEATURE_AMX_FP16 (12*32+21) /* "" AMX fp16 Support */ -#define X86_FEATURE_AVX_IFMA (12*32+23) /* "" Support for VPMADD52[H,L]UQ */ -#define X86_FEATURE_LAM (12*32+26) /* Linear Address Masking */ +#define X86_FEATURE_AVX_VNNI (12*32+ 4) /* "avx_vnni" AVX VNNI instructions */ +#define X86_FEATURE_AVX512_BF16 (12*32+ 5) /* "avx512_bf16" AVX512 BFLOAT16 instructions */ +#define X86_FEATURE_CMPCCXADD (12*32+ 7) /* CMPccXADD instructions */ +#define X86_FEATURE_ARCH_PERFMON_EXT (12*32+ 8) /* Intel Architectural PerfMon Extension */ +#define X86_FEATURE_FZRM (12*32+10) /* Fast zero-length REP MOVSB */ +#define X86_FEATURE_FSRS (12*32+11) /* Fast short REP STOSB */ +#define X86_FEATURE_FSRC (12*32+12) /* Fast short REP {CMPSB,SCASB} */ +#define X86_FEATURE_FRED (12*32+17) /* "fred" Flexible Return and Event Delivery */ +#define X86_FEATURE_LKGS (12*32+18) /* Load "kernel" (userspace) GS */ +#define X86_FEATURE_WRMSRNS (12*32+19) /* Non-serializing WRMSR */ +#define X86_FEATURE_AMX_FP16 (12*32+21) /* AMX fp16 Support */ +#define X86_FEATURE_AVX_IFMA (12*32+23) /* Support for VPMADD52[H,L]UQ */ +#define X86_FEATURE_LAM (12*32+26) /* "lam" Linear Address Masking */ /* AMD-defined CPU features, CPUID level 0x80000008 (EBX), word 13 */ -#define X86_FEATURE_CLZERO (13*32+ 0) /* CLZERO instruction */ -#define X86_FEATURE_IRPERF (13*32+ 1) /* Instructions Retired Count */ -#define X86_FEATURE_XSAVEERPTR (13*32+ 2) /* Always save/restore FP error pointers */ -#define X86_FEATURE_RDPRU (13*32+ 4) /* Read processor register at user level */ -#define X86_FEATURE_WBNOINVD (13*32+ 9) /* WBNOINVD instruction */ -#define X86_FEATURE_AMD_IBPB (13*32+12) /* "" Indirect Branch Prediction Barrier */ -#define X86_FEATURE_AMD_IBRS (13*32+14) /* "" Indirect Branch Restricted Speculation */ -#define X86_FEATURE_AMD_STIBP (13*32+15) /* "" Single Thread Indirect Branch Predictors */ -#define X86_FEATURE_AMD_STIBP_ALWAYS_ON (13*32+17) /* "" Single Thread Indirect Branch Predictors always-on preferred */ -#define X86_FEATURE_AMD_PPIN (13*32+23) /* Protected Processor Inventory Number */ -#define X86_FEATURE_AMD_SSBD (13*32+24) /* "" Speculative Store Bypass Disable */ -#define X86_FEATURE_VIRT_SSBD (13*32+25) /* Virtualized Speculative Store Bypass Disable */ -#define X86_FEATURE_AMD_SSB_NO (13*32+26) /* "" Speculative Store Bypass is fixed in hardware. */ -#define X86_FEATURE_CPPC (13*32+27) /* Collaborative Processor Performance Control */ -#define X86_FEATURE_AMD_PSFD (13*32+28) /* "" Predictive Store Forwarding Disable */ -#define X86_FEATURE_BTC_NO (13*32+29) /* "" Not vulnerable to Branch Type Confusion */ -#define X86_FEATURE_BRS (13*32+31) /* Branch Sampling available */ +#define X86_FEATURE_CLZERO (13*32+ 0) /* "clzero" CLZERO instruction */ +#define X86_FEATURE_IRPERF (13*32+ 1) /* "irperf" Instructions Retired Count */ +#define X86_FEATURE_XSAVEERPTR (13*32+ 2) /* "xsaveerptr" Always save/restore FP error pointers */ +#define X86_FEATURE_RDPRU (13*32+ 4) /* "rdpru" Read processor register at user level */ +#define X86_FEATURE_WBNOINVD (13*32+ 9) /* "wbnoinvd" WBNOINVD instruction */ +#define X86_FEATURE_AMD_IBPB (13*32+12) /* Indirect Branch Prediction Barrier */ +#define X86_FEATURE_AMD_IBRS (13*32+14) /* Indirect Branch Restricted Speculation */ +#define X86_FEATURE_AMD_STIBP (13*32+15) /* Single Thread Indirect Branch Predictors */ +#define X86_FEATURE_AMD_STIBP_ALWAYS_ON (13*32+17) /* Single Thread Indirect Branch Predictors always-on preferred */ +#define X86_FEATURE_AMD_PPIN (13*32+23) /* "amd_ppin" Protected Processor Inventory Number */ +#define X86_FEATURE_AMD_SSBD (13*32+24) /* Speculative Store Bypass Disable */ +#define X86_FEATURE_VIRT_SSBD (13*32+25) /* "virt_ssbd" Virtualized Speculative Store Bypass Disable */ +#define X86_FEATURE_AMD_SSB_NO (13*32+26) /* Speculative Store Bypass is fixed in hardware. */ +#define X86_FEATURE_CPPC (13*32+27) /* "cppc" Collaborative Processor Performance Control */ +#define X86_FEATURE_AMD_PSFD (13*32+28) /* Predictive Store Forwarding Disable */ +#define X86_FEATURE_BTC_NO (13*32+29) /* Not vulnerable to Branch Type Confusion */ +#define X86_FEATURE_BRS (13*32+31) /* "brs" Branch Sampling available */ /* Thermal and Power Management Leaf, CPUID level 0x00000006 (EAX), word 14 */ -#define X86_FEATURE_DTHERM (14*32+ 0) /* Digital Thermal Sensor */ -#define X86_FEATURE_IDA (14*32+ 1) /* Intel Dynamic Acceleration */ -#define X86_FEATURE_ARAT (14*32+ 2) /* Always Running APIC Timer */ -#define X86_FEATURE_PLN (14*32+ 4) /* Intel Power Limit Notification */ -#define X86_FEATURE_PTS (14*32+ 6) /* Intel Package Thermal Status */ -#define X86_FEATURE_HWP (14*32+ 7) /* Intel Hardware P-states */ -#define X86_FEATURE_HWP_NOTIFY (14*32+ 8) /* HWP Notification */ -#define X86_FEATURE_HWP_ACT_WINDOW (14*32+ 9) /* HWP Activity Window */ -#define X86_FEATURE_HWP_EPP (14*32+10) /* HWP Energy Perf. Preference */ -#define X86_FEATURE_HWP_PKG_REQ (14*32+11) /* HWP Package Level Request */ -#define X86_FEATURE_HFI (14*32+19) /* Hardware Feedback Interface */ +#define X86_FEATURE_DTHERM (14*32+ 0) /* "dtherm" Digital Thermal Sensor */ +#define X86_FEATURE_IDA (14*32+ 1) /* "ida" Intel Dynamic Acceleration */ +#define X86_FEATURE_ARAT (14*32+ 2) /* "arat" Always Running APIC Timer */ +#define X86_FEATURE_PLN (14*32+ 4) /* "pln" Intel Power Limit Notification */ +#define X86_FEATURE_PTS (14*32+ 6) /* "pts" Intel Package Thermal Status */ +#define X86_FEATURE_HWP (14*32+ 7) /* "hwp" Intel Hardware P-states */ +#define X86_FEATURE_HWP_NOTIFY (14*32+ 8) /* "hwp_notify" HWP Notification */ +#define X86_FEATURE_HWP_ACT_WINDOW (14*32+ 9) /* "hwp_act_window" HWP Activity Window */ +#define X86_FEATURE_HWP_EPP (14*32+10) /* "hwp_epp" HWP Energy Perf. Preference */ +#define X86_FEATURE_HWP_PKG_REQ (14*32+11) /* "hwp_pkg_req" HWP Package Level Request */ +#define X86_FEATURE_HWP_HIGHEST_PERF_CHANGE (14*32+15) /* HWP Highest perf change */ +#define X86_FEATURE_HFI (14*32+19) /* "hfi" Hardware Feedback Interface */ /* AMD SVM Feature Identification, CPUID level 0x8000000a (EDX), word 15 */ -#define X86_FEATURE_NPT (15*32+ 0) /* Nested Page Table support */ -#define X86_FEATURE_LBRV (15*32+ 1) /* LBR Virtualization support */ +#define X86_FEATURE_NPT (15*32+ 0) /* "npt" Nested Page Table support */ +#define X86_FEATURE_LBRV (15*32+ 1) /* "lbrv" LBR Virtualization support */ #define X86_FEATURE_SVML (15*32+ 2) /* "svm_lock" SVM locking MSR */ #define X86_FEATURE_NRIPS (15*32+ 3) /* "nrip_save" SVM next_rip save */ #define X86_FEATURE_TSCRATEMSR (15*32+ 4) /* "tsc_scale" TSC scaling support */ #define X86_FEATURE_VMCBCLEAN (15*32+ 5) /* "vmcb_clean" VMCB clean bits support */ -#define X86_FEATURE_FLUSHBYASID (15*32+ 6) /* flush-by-ASID support */ -#define X86_FEATURE_DECODEASSISTS (15*32+ 7) /* Decode Assists support */ -#define X86_FEATURE_PAUSEFILTER (15*32+10) /* filtered pause intercept */ -#define X86_FEATURE_PFTHRESHOLD (15*32+12) /* pause filter threshold */ -#define X86_FEATURE_AVIC (15*32+13) /* Virtual Interrupt Controller */ -#define X86_FEATURE_V_VMSAVE_VMLOAD (15*32+15) /* Virtual VMSAVE VMLOAD */ -#define X86_FEATURE_VGIF (15*32+16) /* Virtual GIF */ -#define X86_FEATURE_X2AVIC (15*32+18) /* Virtual x2apic */ -#define X86_FEATURE_V_SPEC_CTRL (15*32+20) /* Virtual SPEC_CTRL */ -#define X86_FEATURE_VNMI (15*32+25) /* Virtual NMI */ -#define X86_FEATURE_SVME_ADDR_CHK (15*32+28) /* "" SVME addr check */ +#define X86_FEATURE_FLUSHBYASID (15*32+ 6) /* "flushbyasid" Flush-by-ASID support */ +#define X86_FEATURE_DECODEASSISTS (15*32+ 7) /* "decodeassists" Decode Assists support */ +#define X86_FEATURE_PAUSEFILTER (15*32+10) /* "pausefilter" Filtered pause intercept */ +#define X86_FEATURE_PFTHRESHOLD (15*32+12) /* "pfthreshold" Pause filter threshold */ +#define X86_FEATURE_AVIC (15*32+13) /* "avic" Virtual Interrupt Controller */ +#define X86_FEATURE_V_VMSAVE_VMLOAD (15*32+15) /* "v_vmsave_vmload" Virtual VMSAVE VMLOAD */ +#define X86_FEATURE_VGIF (15*32+16) /* "vgif" Virtual GIF */ +#define X86_FEATURE_X2AVIC (15*32+18) /* "x2avic" Virtual x2apic */ +#define X86_FEATURE_V_SPEC_CTRL (15*32+20) /* "v_spec_ctrl" Virtual SPEC_CTRL */ +#define X86_FEATURE_VNMI (15*32+25) /* "vnmi" Virtual NMI */ +#define X86_FEATURE_SVME_ADDR_CHK (15*32+28) /* SVME addr check */ /* Intel-defined CPU features, CPUID level 0x00000007:0 (ECX), word 16 */ -#define X86_FEATURE_AVX512VBMI (16*32+ 1) /* AVX512 Vector Bit Manipulation instructions*/ -#define X86_FEATURE_UMIP (16*32+ 2) /* User Mode Instruction Protection */ -#define X86_FEATURE_PKU (16*32+ 3) /* Protection Keys for Userspace */ -#define X86_FEATURE_OSPKE (16*32+ 4) /* OS Protection Keys Enable */ -#define X86_FEATURE_WAITPKG (16*32+ 5) /* UMONITOR/UMWAIT/TPAUSE Instructions */ -#define X86_FEATURE_AVX512_VBMI2 (16*32+ 6) /* Additional AVX512 Vector Bit Manipulation Instructions */ -#define X86_FEATURE_SHSTK (16*32+ 7) /* "" Shadow stack */ -#define X86_FEATURE_GFNI (16*32+ 8) /* Galois Field New Instructions */ -#define X86_FEATURE_VAES (16*32+ 9) /* Vector AES */ -#define X86_FEATURE_VPCLMULQDQ (16*32+10) /* Carry-Less Multiplication Double Quadword */ -#define X86_FEATURE_AVX512_VNNI (16*32+11) /* Vector Neural Network Instructions */ -#define X86_FEATURE_AVX512_BITALG (16*32+12) /* Support for VPOPCNT[B,W] and VPSHUF-BITQMB instructions */ -#define X86_FEATURE_TME (16*32+13) /* Intel Total Memory Encryption */ -#define X86_FEATURE_AVX512_VPOPCNTDQ (16*32+14) /* POPCNT for vectors of DW/QW */ -#define X86_FEATURE_LA57 (16*32+16) /* 5-level page tables */ -#define X86_FEATURE_RDPID (16*32+22) /* RDPID instruction */ -#define X86_FEATURE_BUS_LOCK_DETECT (16*32+24) /* Bus Lock detect */ -#define X86_FEATURE_CLDEMOTE (16*32+25) /* CLDEMOTE instruction */ -#define X86_FEATURE_MOVDIRI (16*32+27) /* MOVDIRI instruction */ -#define X86_FEATURE_MOVDIR64B (16*32+28) /* MOVDIR64B instruction */ -#define X86_FEATURE_ENQCMD (16*32+29) /* ENQCMD and ENQCMDS instructions */ -#define X86_FEATURE_SGX_LC (16*32+30) /* Software Guard Extensions Launch Control */ +#define X86_FEATURE_AVX512VBMI (16*32+ 1) /* "avx512vbmi" AVX512 Vector Bit Manipulation instructions*/ +#define X86_FEATURE_UMIP (16*32+ 2) /* "umip" User Mode Instruction Protection */ +#define X86_FEATURE_PKU (16*32+ 3) /* "pku" Protection Keys for Userspace */ +#define X86_FEATURE_OSPKE (16*32+ 4) /* "ospke" OS Protection Keys Enable */ +#define X86_FEATURE_WAITPKG (16*32+ 5) /* "waitpkg" UMONITOR/UMWAIT/TPAUSE Instructions */ +#define X86_FEATURE_AVX512_VBMI2 (16*32+ 6) /* "avx512_vbmi2" Additional AVX512 Vector Bit Manipulation Instructions */ +#define X86_FEATURE_SHSTK (16*32+ 7) /* Shadow stack */ +#define X86_FEATURE_GFNI (16*32+ 8) /* "gfni" Galois Field New Instructions */ +#define X86_FEATURE_VAES (16*32+ 9) /* "vaes" Vector AES */ +#define X86_FEATURE_VPCLMULQDQ (16*32+10) /* "vpclmulqdq" Carry-Less Multiplication Double Quadword */ +#define X86_FEATURE_AVX512_VNNI (16*32+11) /* "avx512_vnni" Vector Neural Network Instructions */ +#define X86_FEATURE_AVX512_BITALG (16*32+12) /* "avx512_bitalg" Support for VPOPCNT[B,W] and VPSHUF-BITQMB instructions */ +#define X86_FEATURE_TME (16*32+13) /* "tme" Intel Total Memory Encryption */ +#define X86_FEATURE_AVX512_VPOPCNTDQ (16*32+14) /* "avx512_vpopcntdq" POPCNT for vectors of DW/QW */ +#define X86_FEATURE_LA57 (16*32+16) /* "la57" 5-level page tables */ +#define X86_FEATURE_RDPID (16*32+22) /* "rdpid" RDPID instruction */ +#define X86_FEATURE_BUS_LOCK_DETECT (16*32+24) /* "bus_lock_detect" Bus Lock detect */ +#define X86_FEATURE_CLDEMOTE (16*32+25) /* "cldemote" CLDEMOTE instruction */ +#define X86_FEATURE_MOVDIRI (16*32+27) /* "movdiri" MOVDIRI instruction */ +#define X86_FEATURE_MOVDIR64B (16*32+28) /* "movdir64b" MOVDIR64B instruction */ +#define X86_FEATURE_ENQCMD (16*32+29) /* "enqcmd" ENQCMD and ENQCMDS instructions */ +#define X86_FEATURE_SGX_LC (16*32+30) /* "sgx_lc" Software Guard Extensions Launch Control */ /* AMD-defined CPU features, CPUID level 0x80000007 (EBX), word 17 */ -#define X86_FEATURE_OVERFLOW_RECOV (17*32+ 0) /* MCA overflow recovery support */ -#define X86_FEATURE_SUCCOR (17*32+ 1) /* Uncorrectable error containment and recovery */ -#define X86_FEATURE_SMCA (17*32+ 3) /* Scalable MCA */ +#define X86_FEATURE_OVERFLOW_RECOV (17*32+ 0) /* "overflow_recov" MCA overflow recovery support */ +#define X86_FEATURE_SUCCOR (17*32+ 1) /* "succor" Uncorrectable error containment and recovery */ +#define X86_FEATURE_SMCA (17*32+ 3) /* "smca" Scalable MCA */ /* Intel-defined CPU features, CPUID level 0x00000007:0 (EDX), word 18 */ -#define X86_FEATURE_AVX512_4VNNIW (18*32+ 2) /* AVX-512 Neural Network Instructions */ -#define X86_FEATURE_AVX512_4FMAPS (18*32+ 3) /* AVX-512 Multiply Accumulation Single precision */ -#define X86_FEATURE_FSRM (18*32+ 4) /* Fast Short Rep Mov */ -#define X86_FEATURE_AVX512_VP2INTERSECT (18*32+ 8) /* AVX-512 Intersect for D/Q */ -#define X86_FEATURE_SRBDS_CTRL (18*32+ 9) /* "" SRBDS mitigation MSR available */ -#define X86_FEATURE_MD_CLEAR (18*32+10) /* VERW clears CPU buffers */ -#define X86_FEATURE_RTM_ALWAYS_ABORT (18*32+11) /* "" RTM transaction always aborts */ -#define X86_FEATURE_TSX_FORCE_ABORT (18*32+13) /* "" TSX_FORCE_ABORT */ -#define X86_FEATURE_SERIALIZE (18*32+14) /* SERIALIZE instruction */ -#define X86_FEATURE_HYBRID_CPU (18*32+15) /* "" This part has CPUs of more than one type */ -#define X86_FEATURE_TSXLDTRK (18*32+16) /* TSX Suspend Load Address Tracking */ -#define X86_FEATURE_PCONFIG (18*32+18) /* Intel PCONFIG */ -#define X86_FEATURE_ARCH_LBR (18*32+19) /* Intel ARCH LBR */ -#define X86_FEATURE_IBT (18*32+20) /* Indirect Branch Tracking */ -#define X86_FEATURE_AMX_BF16 (18*32+22) /* AMX bf16 Support */ -#define X86_FEATURE_AVX512_FP16 (18*32+23) /* AVX512 FP16 */ -#define X86_FEATURE_AMX_TILE (18*32+24) /* AMX tile Support */ -#define X86_FEATURE_AMX_INT8 (18*32+25) /* AMX int8 Support */ -#define X86_FEATURE_SPEC_CTRL (18*32+26) /* "" Speculation Control (IBRS + IBPB) */ -#define X86_FEATURE_INTEL_STIBP (18*32+27) /* "" Single Thread Indirect Branch Predictors */ -#define X86_FEATURE_FLUSH_L1D (18*32+28) /* Flush L1D cache */ -#define X86_FEATURE_ARCH_CAPABILITIES (18*32+29) /* IA32_ARCH_CAPABILITIES MSR (Intel) */ -#define X86_FEATURE_CORE_CAPABILITIES (18*32+30) /* "" IA32_CORE_CAPABILITIES MSR */ -#define X86_FEATURE_SPEC_CTRL_SSBD (18*32+31) /* "" Speculative Store Bypass Disable */ +#define X86_FEATURE_AVX512_4VNNIW (18*32+ 2) /* "avx512_4vnniw" AVX-512 Neural Network Instructions */ +#define X86_FEATURE_AVX512_4FMAPS (18*32+ 3) /* "avx512_4fmaps" AVX-512 Multiply Accumulation Single precision */ +#define X86_FEATURE_FSRM (18*32+ 4) /* "fsrm" Fast Short Rep Mov */ +#define X86_FEATURE_AVX512_VP2INTERSECT (18*32+ 8) /* "avx512_vp2intersect" AVX-512 Intersect for D/Q */ +#define X86_FEATURE_SRBDS_CTRL (18*32+ 9) /* SRBDS mitigation MSR available */ +#define X86_FEATURE_MD_CLEAR (18*32+10) /* "md_clear" VERW clears CPU buffers */ +#define X86_FEATURE_RTM_ALWAYS_ABORT (18*32+11) /* RTM transaction always aborts */ +#define X86_FEATURE_TSX_FORCE_ABORT (18*32+13) /* TSX_FORCE_ABORT */ +#define X86_FEATURE_SERIALIZE (18*32+14) /* "serialize" SERIALIZE instruction */ +#define X86_FEATURE_HYBRID_CPU (18*32+15) /* This part has CPUs of more than one type */ +#define X86_FEATURE_TSXLDTRK (18*32+16) /* "tsxldtrk" TSX Suspend Load Address Tracking */ +#define X86_FEATURE_PCONFIG (18*32+18) /* "pconfig" Intel PCONFIG */ +#define X86_FEATURE_ARCH_LBR (18*32+19) /* "arch_lbr" Intel ARCH LBR */ +#define X86_FEATURE_IBT (18*32+20) /* "ibt" Indirect Branch Tracking */ +#define X86_FEATURE_AMX_BF16 (18*32+22) /* "amx_bf16" AMX bf16 Support */ +#define X86_FEATURE_AVX512_FP16 (18*32+23) /* "avx512_fp16" AVX512 FP16 */ +#define X86_FEATURE_AMX_TILE (18*32+24) /* "amx_tile" AMX tile Support */ +#define X86_FEATURE_AMX_INT8 (18*32+25) /* "amx_int8" AMX int8 Support */ +#define X86_FEATURE_SPEC_CTRL (18*32+26) /* Speculation Control (IBRS + IBPB) */ +#define X86_FEATURE_INTEL_STIBP (18*32+27) /* Single Thread Indirect Branch Predictors */ +#define X86_FEATURE_FLUSH_L1D (18*32+28) /* "flush_l1d" Flush L1D cache */ +#define X86_FEATURE_ARCH_CAPABILITIES (18*32+29) /* "arch_capabilities" IA32_ARCH_CAPABILITIES MSR (Intel) */ +#define X86_FEATURE_CORE_CAPABILITIES (18*32+30) /* IA32_CORE_CAPABILITIES MSR */ +#define X86_FEATURE_SPEC_CTRL_SSBD (18*32+31) /* Speculative Store Bypass Disable */ /* AMD-defined memory encryption features, CPUID level 0x8000001f (EAX), word 19 */ -#define X86_FEATURE_SME (19*32+ 0) /* AMD Secure Memory Encryption */ -#define X86_FEATURE_SEV (19*32+ 1) /* AMD Secure Encrypted Virtualization */ -#define X86_FEATURE_VM_PAGE_FLUSH (19*32+ 2) /* "" VM Page Flush MSR is supported */ -#define X86_FEATURE_SEV_ES (19*32+ 3) /* AMD Secure Encrypted Virtualization - Encrypted State */ -#define X86_FEATURE_SEV_SNP (19*32+ 4) /* AMD Secure Encrypted Virtualization - Secure Nested Paging */ -#define X86_FEATURE_V_TSC_AUX (19*32+ 9) /* "" Virtual TSC_AUX */ -#define X86_FEATURE_SME_COHERENT (19*32+10) /* "" AMD hardware-enforced cache coherency */ -#define X86_FEATURE_DEBUG_SWAP (19*32+14) /* AMD SEV-ES full debug state swap support */ +#define X86_FEATURE_SME (19*32+ 0) /* "sme" AMD Secure Memory Encryption */ +#define X86_FEATURE_SEV (19*32+ 1) /* "sev" AMD Secure Encrypted Virtualization */ +#define X86_FEATURE_VM_PAGE_FLUSH (19*32+ 2) /* VM Page Flush MSR is supported */ +#define X86_FEATURE_SEV_ES (19*32+ 3) /* "sev_es" AMD Secure Encrypted Virtualization - Encrypted State */ +#define X86_FEATURE_SEV_SNP (19*32+ 4) /* "sev_snp" AMD Secure Encrypted Virtualization - Secure Nested Paging */ +#define X86_FEATURE_V_TSC_AUX (19*32+ 9) /* Virtual TSC_AUX */ +#define X86_FEATURE_SME_COHERENT (19*32+10) /* AMD hardware-enforced cache coherency */ +#define X86_FEATURE_DEBUG_SWAP (19*32+14) /* "debug_swap" AMD SEV-ES full debug state swap support */ +#define X86_FEATURE_SVSM (19*32+28) /* "svsm" SVSM present */ /* AMD-defined Extended Feature 2 EAX, CPUID level 0x80000021 (EAX), word 20 */ -#define X86_FEATURE_NO_NESTED_DATA_BP (20*32+ 0) /* "" No Nested Data Breakpoints */ -#define X86_FEATURE_WRMSR_XX_BASE_NS (20*32+ 1) /* "" WRMSR to {FS,GS,KERNEL_GS}_BASE is non-serializing */ -#define X86_FEATURE_LFENCE_RDTSC (20*32+ 2) /* "" LFENCE always serializing / synchronizes RDTSC */ -#define X86_FEATURE_NULL_SEL_CLR_BASE (20*32+ 6) /* "" Null Selector Clears Base */ -#define X86_FEATURE_AUTOIBRS (20*32+ 8) /* "" Automatic IBRS */ -#define X86_FEATURE_NO_SMM_CTL_MSR (20*32+ 9) /* "" SMM_CTL MSR is not present */ +#define X86_FEATURE_NO_NESTED_DATA_BP (20*32+ 0) /* No Nested Data Breakpoints */ +#define X86_FEATURE_WRMSR_XX_BASE_NS (20*32+ 1) /* WRMSR to {FS,GS,KERNEL_GS}_BASE is non-serializing */ +#define X86_FEATURE_LFENCE_RDTSC (20*32+ 2) /* LFENCE always serializing / synchronizes RDTSC */ +#define X86_FEATURE_NULL_SEL_CLR_BASE (20*32+ 6) /* Null Selector Clears Base */ +#define X86_FEATURE_AUTOIBRS (20*32+ 8) /* Automatic IBRS */ +#define X86_FEATURE_NO_SMM_CTL_MSR (20*32+ 9) /* SMM_CTL MSR is not present */ -#define X86_FEATURE_SBPB (20*32+27) /* "" Selective Branch Prediction Barrier */ -#define X86_FEATURE_IBPB_BRTYPE (20*32+28) /* "" MSR_PRED_CMD[IBPB] flushes all branch type predictions */ -#define X86_FEATURE_SRSO_NO (20*32+29) /* "" CPU is not affected by SRSO */ +#define X86_FEATURE_SBPB (20*32+27) /* Selective Branch Prediction Barrier */ +#define X86_FEATURE_IBPB_BRTYPE (20*32+28) /* MSR_PRED_CMD[IBPB] flushes all branch type predictions */ +#define X86_FEATURE_SRSO_NO (20*32+29) /* CPU is not affected by SRSO */ /* * Extended auxiliary flags: Linux defined - for features scattered in various @@ -465,59 +467,60 @@ * * Reuse free bits when adding new feature flags! */ -#define X86_FEATURE_AMD_LBR_PMC_FREEZE (21*32+ 0) /* AMD LBR and PMC Freeze */ -#define X86_FEATURE_CLEAR_BHB_LOOP (21*32+ 1) /* "" Clear branch history at syscall entry using SW loop */ -#define X86_FEATURE_BHI_CTRL (21*32+ 2) /* "" BHI_DIS_S HW control available */ -#define X86_FEATURE_CLEAR_BHB_HW (21*32+ 3) /* "" BHI_DIS_S HW control enabled */ -#define X86_FEATURE_CLEAR_BHB_LOOP_ON_VMEXIT (21*32+ 4) /* "" Clear branch history at vmexit using SW loop */ +#define X86_FEATURE_AMD_LBR_PMC_FREEZE (21*32+ 0) /* "amd_lbr_pmc_freeze" AMD LBR and PMC Freeze */ +#define X86_FEATURE_CLEAR_BHB_LOOP (21*32+ 1) /* Clear branch history at syscall entry using SW loop */ +#define X86_FEATURE_BHI_CTRL (21*32+ 2) /* BHI_DIS_S HW control available */ +#define X86_FEATURE_CLEAR_BHB_HW (21*32+ 3) /* BHI_DIS_S HW control enabled */ +#define X86_FEATURE_CLEAR_BHB_LOOP_ON_VMEXIT (21*32+ 4) /* Clear branch history at vmexit using SW loop */ +#define X86_FEATURE_FAST_CPPC (21*32 + 5) /* AMD Fast CPPC */ /* * BUG word(s) */ #define X86_BUG(x) (NCAPINTS*32 + (x)) -#define X86_BUG_F00F X86_BUG(0) /* Intel F00F */ -#define X86_BUG_FDIV X86_BUG(1) /* FPU FDIV */ -#define X86_BUG_COMA X86_BUG(2) /* Cyrix 6x86 coma */ +#define X86_BUG_F00F X86_BUG(0) /* "f00f" Intel F00F */ +#define X86_BUG_FDIV X86_BUG(1) /* "fdiv" FPU FDIV */ +#define X86_BUG_COMA X86_BUG(2) /* "coma" Cyrix 6x86 coma */ #define X86_BUG_AMD_TLB_MMATCH X86_BUG(3) /* "tlb_mmatch" AMD Erratum 383 */ #define X86_BUG_AMD_APIC_C1E X86_BUG(4) /* "apic_c1e" AMD Erratum 400 */ -#define X86_BUG_11AP X86_BUG(5) /* Bad local APIC aka 11AP */ -#define X86_BUG_FXSAVE_LEAK X86_BUG(6) /* FXSAVE leaks FOP/FIP/FOP */ -#define X86_BUG_CLFLUSH_MONITOR X86_BUG(7) /* AAI65, CLFLUSH required before MONITOR */ -#define X86_BUG_SYSRET_SS_ATTRS X86_BUG(8) /* SYSRET doesn't fix up SS attrs */ +#define X86_BUG_11AP X86_BUG(5) /* "11ap" Bad local APIC aka 11AP */ +#define X86_BUG_FXSAVE_LEAK X86_BUG(6) /* "fxsave_leak" FXSAVE leaks FOP/FIP/FOP */ +#define X86_BUG_CLFLUSH_MONITOR X86_BUG(7) /* "clflush_monitor" AAI65, CLFLUSH required before MONITOR */ +#define X86_BUG_SYSRET_SS_ATTRS X86_BUG(8) /* "sysret_ss_attrs" SYSRET doesn't fix up SS attrs */ #ifdef CONFIG_X86_32 /* * 64-bit kernels don't use X86_BUG_ESPFIX. Make the define conditional * to avoid confusion. */ -#define X86_BUG_ESPFIX X86_BUG(9) /* "" IRET to 16-bit SS corrupts ESP/RSP high bits */ +#define X86_BUG_ESPFIX X86_BUG(9) /* IRET to 16-bit SS corrupts ESP/RSP high bits */ #endif -#define X86_BUG_NULL_SEG X86_BUG(10) /* Nulling a selector preserves the base */ -#define X86_BUG_SWAPGS_FENCE X86_BUG(11) /* SWAPGS without input dep on GS */ -#define X86_BUG_MONITOR X86_BUG(12) /* IPI required to wake up remote CPU */ -#define X86_BUG_AMD_E400 X86_BUG(13) /* CPU is among the affected by Erratum 400 */ -#define X86_BUG_CPU_MELTDOWN X86_BUG(14) /* CPU is affected by meltdown attack and needs kernel page table isolation */ -#define X86_BUG_SPECTRE_V1 X86_BUG(15) /* CPU is affected by Spectre variant 1 attack with conditional branches */ -#define X86_BUG_SPECTRE_V2 X86_BUG(16) /* CPU is affected by Spectre variant 2 attack with indirect branches */ -#define X86_BUG_SPEC_STORE_BYPASS X86_BUG(17) /* CPU is affected by speculative store bypass attack */ -#define X86_BUG_L1TF X86_BUG(18) /* CPU is affected by L1 Terminal Fault */ -#define X86_BUG_MDS X86_BUG(19) /* CPU is affected by Microarchitectural data sampling */ -#define X86_BUG_MSBDS_ONLY X86_BUG(20) /* CPU is only affected by the MSDBS variant of BUG_MDS */ -#define X86_BUG_SWAPGS X86_BUG(21) /* CPU is affected by speculation through SWAPGS */ -#define X86_BUG_TAA X86_BUG(22) /* CPU is affected by TSX Async Abort(TAA) */ -#define X86_BUG_ITLB_MULTIHIT X86_BUG(23) /* CPU may incur MCE during certain page attribute changes */ -#define X86_BUG_SRBDS X86_BUG(24) /* CPU may leak RNG bits if not mitigated */ -#define X86_BUG_MMIO_STALE_DATA X86_BUG(25) /* CPU is affected by Processor MMIO Stale Data vulnerabilities */ -#define X86_BUG_MMIO_UNKNOWN X86_BUG(26) /* CPU is too old and its MMIO Stale Data status is unknown */ -#define X86_BUG_RETBLEED X86_BUG(27) /* CPU is affected by RETBleed */ -#define X86_BUG_EIBRS_PBRSB X86_BUG(28) /* EIBRS is vulnerable to Post Barrier RSB Predictions */ -#define X86_BUG_SMT_RSB X86_BUG(29) /* CPU is vulnerable to Cross-Thread Return Address Predictions */ -#define X86_BUG_GDS X86_BUG(30) /* CPU is affected by Gather Data Sampling */ -#define X86_BUG_TDX_PW_MCE X86_BUG(31) /* CPU may incur #MC if non-TD software does partial write to TDX private memory */ +#define X86_BUG_NULL_SEG X86_BUG(10) /* "null_seg" Nulling a selector preserves the base */ +#define X86_BUG_SWAPGS_FENCE X86_BUG(11) /* "swapgs_fence" SWAPGS without input dep on GS */ +#define X86_BUG_MONITOR X86_BUG(12) /* "monitor" IPI required to wake up remote CPU */ +#define X86_BUG_AMD_E400 X86_BUG(13) /* "amd_e400" CPU is among the affected by Erratum 400 */ +#define X86_BUG_CPU_MELTDOWN X86_BUG(14) /* "cpu_meltdown" CPU is affected by meltdown attack and needs kernel page table isolation */ +#define X86_BUG_SPECTRE_V1 X86_BUG(15) /* "spectre_v1" CPU is affected by Spectre variant 1 attack with conditional branches */ +#define X86_BUG_SPECTRE_V2 X86_BUG(16) /* "spectre_v2" CPU is affected by Spectre variant 2 attack with indirect branches */ +#define X86_BUG_SPEC_STORE_BYPASS X86_BUG(17) /* "spec_store_bypass" CPU is affected by speculative store bypass attack */ +#define X86_BUG_L1TF X86_BUG(18) /* "l1tf" CPU is affected by L1 Terminal Fault */ +#define X86_BUG_MDS X86_BUG(19) /* "mds" CPU is affected by Microarchitectural data sampling */ +#define X86_BUG_MSBDS_ONLY X86_BUG(20) /* "msbds_only" CPU is only affected by the MSDBS variant of BUG_MDS */ +#define X86_BUG_SWAPGS X86_BUG(21) /* "swapgs" CPU is affected by speculation through SWAPGS */ +#define X86_BUG_TAA X86_BUG(22) /* "taa" CPU is affected by TSX Async Abort(TAA) */ +#define X86_BUG_ITLB_MULTIHIT X86_BUG(23) /* "itlb_multihit" CPU may incur MCE during certain page attribute changes */ +#define X86_BUG_SRBDS X86_BUG(24) /* "srbds" CPU may leak RNG bits if not mitigated */ +#define X86_BUG_MMIO_STALE_DATA X86_BUG(25) /* "mmio_stale_data" CPU is affected by Processor MMIO Stale Data vulnerabilities */ +#define X86_BUG_MMIO_UNKNOWN X86_BUG(26) /* "mmio_unknown" CPU is too old and its MMIO Stale Data status is unknown */ +#define X86_BUG_RETBLEED X86_BUG(27) /* "retbleed" CPU is affected by RETBleed */ +#define X86_BUG_EIBRS_PBRSB X86_BUG(28) /* "eibrs_pbrsb" EIBRS is vulnerable to Post Barrier RSB Predictions */ +#define X86_BUG_SMT_RSB X86_BUG(29) /* "smt_rsb" CPU is vulnerable to Cross-Thread Return Address Predictions */ +#define X86_BUG_GDS X86_BUG(30) /* "gds" CPU is affected by Gather Data Sampling */ +#define X86_BUG_TDX_PW_MCE X86_BUG(31) /* "tdx_pw_mce" CPU may incur #MC if non-TD software does partial write to TDX private memory */ /* BUG word 2 */ -#define X86_BUG_SRSO X86_BUG(1*32 + 0) /* AMD SRSO bug */ -#define X86_BUG_DIV0 X86_BUG(1*32 + 1) /* AMD DIV0 speculation bug */ -#define X86_BUG_RFDS X86_BUG(1*32 + 2) /* CPU is vulnerable to Register File Data Sampling */ -#define X86_BUG_BHI X86_BUG(1*32 + 3) /* CPU is affected by Branch History Injection */ +#define X86_BUG_SRSO X86_BUG(1*32 + 0) /* "srso" AMD SRSO bug */ +#define X86_BUG_DIV0 X86_BUG(1*32 + 1) /* "div0" AMD DIV0 speculation bug */ +#define X86_BUG_RFDS X86_BUG(1*32 + 2) /* "rfds" CPU is vulnerable to Register File Data Sampling */ +#define X86_BUG_BHI X86_BUG(1*32 + 3) /* "bhi" CPU is affected by Branch History Injection */ #endif /* _ASM_X86_CPUFEATURES_H */ diff --git a/tools/arch/x86/include/asm/msr-index.h b/tools/arch/x86/include/asm/msr-index.h index e022e6eb766c64..82c6a4d350e09e 100644 --- a/tools/arch/x86/include/asm/msr-index.h +++ b/tools/arch/x86/include/asm/msr-index.h @@ -566,6 +566,12 @@ #define MSR_RELOAD_PMC0 0x000014c1 #define MSR_RELOAD_FIXED_CTR0 0x00001309 +/* V6 PMON MSR range */ +#define MSR_IA32_PMC_V6_GP0_CTR 0x1900 +#define MSR_IA32_PMC_V6_GP0_CFG_A 0x1901 +#define MSR_IA32_PMC_V6_FX0_CTR 0x1980 +#define MSR_IA32_PMC_V6_STEP 4 + /* KeyID partitioning between MKTME and TDX */ #define MSR_IA32_MKTME_KEYID_PARTITIONING 0x00000087 @@ -660,6 +666,8 @@ #define MSR_AMD64_RMP_BASE 0xc0010132 #define MSR_AMD64_RMP_END 0xc0010133 +#define MSR_SVSM_CAA 0xc001f000 + /* AMD Collaborative Processor Performance Control MSRs */ #define MSR_AMD_CPPC_CAP1 0xc00102b0 #define MSR_AMD_CPPC_ENABLE 0xc00102b1 @@ -781,6 +789,8 @@ #define MSR_K7_HWCR_IRPERF_EN BIT_ULL(MSR_K7_HWCR_IRPERF_EN_BIT) #define MSR_K7_FID_VID_CTL 0xc0010041 #define MSR_K7_FID_VID_STATUS 0xc0010042 +#define MSR_K7_HWCR_CPB_DIS_BIT 25 +#define MSR_K7_HWCR_CPB_DIS BIT_ULL(MSR_K7_HWCR_CPB_DIS_BIT) /* K6 MSRs */ #define MSR_K6_WHCR 0xc0000082 @@ -1164,6 +1174,7 @@ #define MSR_IA32_QM_CTR 0xc8e #define MSR_IA32_PQR_ASSOC 0xc8f #define MSR_IA32_L3_CBM_BASE 0xc90 +#define MSR_RMID_SNC_CONFIG 0xca0 #define MSR_IA32_L2_CBM_BASE 0xd10 #define MSR_IA32_MBA_THRTL_BASE 0xd50 diff --git a/tools/arch/x86/include/uapi/asm/kvm.h b/tools/arch/x86/include/uapi/asm/kvm.h index 9fae1b73b529ca..bf57a824f72281 100644 --- a/tools/arch/x86/include/uapi/asm/kvm.h +++ b/tools/arch/x86/include/uapi/asm/kvm.h @@ -106,6 +106,7 @@ struct kvm_ioapic_state { #define KVM_RUN_X86_SMM (1 << 0) #define KVM_RUN_X86_BUS_LOCK (1 << 1) +#define KVM_RUN_X86_GUEST_MODE (1 << 2) /* for KVM_GET_REGS and KVM_SET_REGS */ struct kvm_regs { @@ -697,6 +698,11 @@ enum sev_cmd_id { /* Second time is the charm; improved versions of the above ioctls. */ KVM_SEV_INIT2, + /* SNP-specific commands */ + KVM_SEV_SNP_LAUNCH_START = 100, + KVM_SEV_SNP_LAUNCH_UPDATE, + KVM_SEV_SNP_LAUNCH_FINISH, + KVM_SEV_NR_MAX, }; @@ -824,6 +830,48 @@ struct kvm_sev_receive_update_data { __u32 pad2; }; +struct kvm_sev_snp_launch_start { + __u64 policy; + __u8 gosvw[16]; + __u16 flags; + __u8 pad0[6]; + __u64 pad1[4]; +}; + +/* Kept in sync with firmware values for simplicity. */ +#define KVM_SEV_SNP_PAGE_TYPE_NORMAL 0x1 +#define KVM_SEV_SNP_PAGE_TYPE_ZERO 0x3 +#define KVM_SEV_SNP_PAGE_TYPE_UNMEASURED 0x4 +#define KVM_SEV_SNP_PAGE_TYPE_SECRETS 0x5 +#define KVM_SEV_SNP_PAGE_TYPE_CPUID 0x6 + +struct kvm_sev_snp_launch_update { + __u64 gfn_start; + __u64 uaddr; + __u64 len; + __u8 type; + __u8 pad0; + __u16 flags; + __u32 pad1; + __u64 pad2[4]; +}; + +#define KVM_SEV_SNP_ID_BLOCK_SIZE 96 +#define KVM_SEV_SNP_ID_AUTH_SIZE 4096 +#define KVM_SEV_SNP_FINISH_DATA_SIZE 32 + +struct kvm_sev_snp_launch_finish { + __u64 id_block_uaddr; + __u64 id_auth_uaddr; + __u8 id_block_en; + __u8 auth_key_en; + __u8 vcek_disabled; + __u8 host_data[KVM_SEV_SNP_FINISH_DATA_SIZE]; + __u8 pad0[3]; + __u16 flags; + __u64 pad1[4]; +}; + #define KVM_X2APIC_API_USE_32BIT_IDS (1ULL << 0) #define KVM_X2APIC_API_DISABLE_BROADCAST_QUIRK (1ULL << 1) @@ -874,5 +922,6 @@ struct kvm_hyperv_eventfd { #define KVM_X86_SW_PROTECTED_VM 1 #define KVM_X86_SEV_VM 2 #define KVM_X86_SEV_ES_VM 3 +#define KVM_X86_SNP_VM 4 #endif /* _ASM_X86_KVM_H */ diff --git a/tools/arch/x86/include/uapi/asm/svm.h b/tools/arch/x86/include/uapi/asm/svm.h index 80e1df482337df..1814b413fd5783 100644 --- a/tools/arch/x86/include/uapi/asm/svm.h +++ b/tools/arch/x86/include/uapi/asm/svm.h @@ -115,6 +115,7 @@ #define SVM_VMGEXIT_AP_CREATE_ON_INIT 0 #define SVM_VMGEXIT_AP_CREATE 1 #define SVM_VMGEXIT_AP_DESTROY 2 +#define SVM_VMGEXIT_SNP_RUN_VMPL 0x80000018 #define SVM_VMGEXIT_HV_FEATURES 0x8000fffd #define SVM_VMGEXIT_TERM_REQUEST 0x8000fffe #define SVM_VMGEXIT_TERM_REASON(reason_set, reason_code) \ diff --git a/tools/build/feature/Makefile b/tools/build/feature/Makefile index 489cbed7e82a7d..12796808f07a8c 100644 --- a/tools/build/feature/Makefile +++ b/tools/build/feature/Makefile @@ -82,7 +82,30 @@ FILES= \ FILES := $(addprefix $(OUTPUT),$(FILES)) -PKG_CONFIG ?= $(CROSS_COMPILE)pkg-config +# Some distros provide the command $(CROSS_COMPILE)pkg-config for +# searching packges installed with Multiarch. Use it for cross +# compilation if it is existed. +ifneq (, $(shell which $(CROSS_COMPILE)pkg-config)) + PKG_CONFIG ?= $(CROSS_COMPILE)pkg-config +else + PKG_CONFIG ?= pkg-config + + # PKG_CONFIG_PATH or PKG_CONFIG_LIBDIR, alongside PKG_CONFIG_SYSROOT_DIR + # for modified system root, are required for the cross compilation. + # If these PKG_CONFIG environment variables are not set, Multiarch library + # paths are used instead. + ifdef CROSS_COMPILE + ifeq ($(PKG_CONFIG_LIBDIR)$(PKG_CONFIG_PATH)$(PKG_CONFIG_SYSROOT_DIR),) + CROSS_ARCH = $(shell $(CC) -dumpmachine) + PKG_CONFIG_LIBDIR := /usr/local/$(CROSS_ARCH)/lib/pkgconfig/ + PKG_CONFIG_LIBDIR := $(PKG_CONFIG_LIBDIR):/usr/local/lib/$(CROSS_ARCH)/pkgconfig/ + PKG_CONFIG_LIBDIR := $(PKG_CONFIG_LIBDIR):/usr/lib/$(CROSS_ARCH)/pkgconfig/ + PKG_CONFIG_LIBDIR := $(PKG_CONFIG_LIBDIR):/usr/local/share/pkgconfig/ + PKG_CONFIG_LIBDIR := $(PKG_CONFIG_LIBDIR):/usr/share/pkgconfig/ + export PKG_CONFIG_LIBDIR + endif + endif +endif all: $(FILES) @@ -147,7 +170,17 @@ $(OUTPUT)test-libopencsd.bin: DWARFLIBS := -ldw ifeq ($(findstring -static,${LDFLAGS}),-static) -DWARFLIBS += -lelf -lebl -lz -llzma -lbz2 + DWARFLIBS += -lelf -lz -llzma -lbz2 -lzstd + + LIBDW_VERSION := $(shell $(PKG_CONFIG) --modversion libdw) + LIBDW_VERSION_1 := $(word 1, $(subst ., ,$(LIBDW_VERSION))) + LIBDW_VERSION_2 := $(word 2, $(subst ., ,$(LIBDW_VERSION))) + + # Elfutils merged libebl.a into libdw.a starting from version 0.177, + # Link libebl.a only if libdw is older than this version. + ifeq ($(shell test $(LIBDW_VERSION_2) -lt 177; echo $$?),0) + DWARFLIBS += -lebl + endif endif $(OUTPUT)test-dwarf.bin: @@ -178,27 +211,27 @@ $(OUTPUT)test-numa_num_possible_cpus.bin: $(BUILD) -lnuma $(OUTPUT)test-libunwind.bin: - $(BUILD) -lelf + $(BUILD) -lelf -llzma $(OUTPUT)test-libunwind-debug-frame.bin: - $(BUILD) -lelf + $(BUILD) -lelf -llzma $(OUTPUT)test-libunwind-x86.bin: - $(BUILD) -lelf -lunwind-x86 + $(BUILD) -lelf -llzma -lunwind-x86 $(OUTPUT)test-libunwind-x86_64.bin: - $(BUILD) -lelf -lunwind-x86_64 + $(BUILD) -lelf -llzma -lunwind-x86_64 $(OUTPUT)test-libunwind-arm.bin: - $(BUILD) -lelf -lunwind-arm + $(BUILD) -lelf -llzma -lunwind-arm $(OUTPUT)test-libunwind-aarch64.bin: - $(BUILD) -lelf -lunwind-aarch64 + $(BUILD) -lelf -llzma -lunwind-aarch64 $(OUTPUT)test-libunwind-debug-frame-arm.bin: - $(BUILD) -lelf -lunwind-arm + $(BUILD) -lelf -llzma -lunwind-arm $(OUTPUT)test-libunwind-debug-frame-aarch64.bin: - $(BUILD) -lelf -lunwind-aarch64 + $(BUILD) -lelf -llzma -lunwind-aarch64 $(OUTPUT)test-libaudit.bin: $(BUILD) -laudit diff --git a/tools/include/uapi/README b/tools/include/uapi/README new file mode 100644 index 00000000000000..7147b1b2cb2850 --- /dev/null +++ b/tools/include/uapi/README @@ -0,0 +1,73 @@ +Why we want a copy of kernel headers in tools? +============================================== + +There used to be no copies, with tools/ code using kernel headers +directly. From time to time tools/perf/ broke due to legitimate kernel +hacking. At some point Linus complained about such direct usage. Then we +adopted the current model. + +The way these headers are used in perf are not restricted to just +including them to compile something. + +There are sometimes used in scripts that convert defines into string +tables, etc, so some change may break one of these scripts, or new MSRs +may use some different #define pattern, etc. + +E.g.: + + $ ls -1 tools/perf/trace/beauty/*.sh | head -5 + tools/perf/trace/beauty/arch_errno_names.sh + tools/perf/trace/beauty/drm_ioctl.sh + tools/perf/trace/beauty/fadvise.sh + tools/perf/trace/beauty/fsconfig.sh + tools/perf/trace/beauty/fsmount.sh + $ + $ tools/perf/trace/beauty/fadvise.sh + static const char *fadvise_advices[] = { + [0] = "NORMAL", + [1] = "RANDOM", + [2] = "SEQUENTIAL", + [3] = "WILLNEED", + [4] = "DONTNEED", + [5] = "NOREUSE", + }; + $ + +The tools/perf/check-headers.sh script, part of the tools/ build +process, points out changes in the original files. + +So its important not to touch the copies in tools/ when doing changes in +the original kernel headers, that will be done later, when +check-headers.sh inform about the change to the perf tools hackers. + +Another explanation from Ingo Molnar: +It's better than all the alternatives we tried so far: + + - Symbolic links and direct #includes: this was the original approach but + was pushed back on from the kernel side, when tooling modified the + headers and broke them accidentally for kernel builds. + + - Duplicate self-defined ABI headers like glibc: double the maintenance + burden, double the chance for mistakes, plus there's no tech-driven + notification mechanism to look at new kernel side changes. + +What we are doing now is a third option: + + - A software-enforced copy-on-write mechanism of kernel headers to + tooling, driven by non-fatal warnings on the tooling side build when + kernel headers get modified: + + Warning: Kernel ABI header differences: + diff -u tools/include/uapi/drm/i915_drm.h include/uapi/drm/i915_drm.h + diff -u tools/include/uapi/linux/fs.h include/uapi/linux/fs.h + diff -u tools/include/uapi/linux/kvm.h include/uapi/linux/kvm.h + ... + + The tooling policy is to always pick up the kernel side headers as-is, + and integate them into the tooling build. The warnings above serve as a + notification to tooling maintainers that there's changes on the kernel + side. + +We've been using this for many years now, and it might seem hacky, but +works surprisingly well. + diff --git a/tools/include/uapi/asm-generic/unistd.h b/tools/include/uapi/asm-generic/unistd.h index a00d53d027235a..5bf6148cac2b93 100644 --- a/tools/include/uapi/asm-generic/unistd.h +++ b/tools/include/uapi/asm-generic/unistd.h @@ -737,7 +737,7 @@ __SC_COMP(__NR_pselect6_time64, sys_pselect6, compat_sys_pselect6_time64) #define __NR_ppoll_time64 414 __SC_COMP(__NR_ppoll_time64, sys_ppoll, compat_sys_ppoll_time64) #define __NR_io_pgetevents_time64 416 -__SYSCALL(__NR_io_pgetevents_time64, sys_io_pgetevents) +__SC_COMP(__NR_io_pgetevents_time64, sys_io_pgetevents, compat_sys_io_pgetevents_time64) #define __NR_recvmmsg_time64 417 __SC_COMP(__NR_recvmmsg_time64, sys_recvmmsg, compat_sys_recvmmsg_time64) #define __NR_mq_timedsend_time64 418 diff --git a/tools/include/uapi/drm/i915_drm.h b/tools/include/uapi/drm/i915_drm.h index d4d86e566e0777..535cb68fdb5c4b 100644 --- a/tools/include/uapi/drm/i915_drm.h +++ b/tools/include/uapi/drm/i915_drm.h @@ -2163,6 +2163,15 @@ struct drm_i915_gem_context_param { * supports this per context flag. */ #define I915_CONTEXT_PARAM_LOW_LATENCY 0xe + +/* + * I915_CONTEXT_PARAM_CONTEXT_IMAGE: + * + * Allows userspace to provide own context images. + * + * Note that this is a debug API not available on production kernel builds. + */ +#define I915_CONTEXT_PARAM_CONTEXT_IMAGE 0xf /* Must be kept compact -- no holes and well documented */ /** @value: Context parameter value to be set or queried */ @@ -2564,6 +2573,24 @@ struct i915_context_param_engines { struct i915_engine_class_instance engines[N__]; \ } __attribute__((packed)) name__ +struct i915_gem_context_param_context_image { + /** @engine: Engine class & instance to be configured. */ + struct i915_engine_class_instance engine; + + /** @flags: One of the supported flags or zero. */ + __u32 flags; +#define I915_CONTEXT_IMAGE_FLAG_ENGINE_INDEX (1u << 0) + + /** @size: Size of the image blob pointed to by @image. */ + __u32 size; + + /** @mbz: Must be zero. */ + __u32 mbz; + + /** @image: Userspace memory containing the context image. */ + __u64 image; +} __attribute__((packed)); + /** * struct drm_i915_gem_context_create_ext_setparam - Context parameter * to set or query during context creation. diff --git a/tools/include/uapi/linux/in.h b/tools/include/uapi/linux/in.h index e682ab628dfa66..d358add1611cd1 100644 --- a/tools/include/uapi/linux/in.h +++ b/tools/include/uapi/linux/in.h @@ -81,6 +81,8 @@ enum { #define IPPROTO_ETHERNET IPPROTO_ETHERNET IPPROTO_RAW = 255, /* Raw IP packets */ #define IPPROTO_RAW IPPROTO_RAW + IPPROTO_SMC = 256, /* Shared Memory Communications */ +#define IPPROTO_SMC IPPROTO_SMC IPPROTO_MPTCP = 262, /* Multipath TCP connection */ #define IPPROTO_MPTCP IPPROTO_MPTCP IPPROTO_MAX diff --git a/tools/include/uapi/linux/kvm.h b/tools/include/uapi/linux/kvm.h index e5af8c692dc063..637efc05514534 100644 --- a/tools/include/uapi/linux/kvm.h +++ b/tools/include/uapi/linux/kvm.h @@ -192,11 +192,24 @@ struct kvm_xen_exit { /* Flags that describe what fields in emulation_failure hold valid data. */ #define KVM_INTERNAL_ERROR_EMULATION_FLAG_INSTRUCTION_BYTES (1ULL << 0) +/* + * struct kvm_run can be modified by userspace at any time, so KVM must be + * careful to avoid TOCTOU bugs. In order to protect KVM, HINT_UNSAFE_IN_KVM() + * renames fields in struct kvm_run from to __unsafe when + * compiled into the kernel, ensuring that any use within KVM is obvious and + * gets extra scrutiny. + */ +#ifdef __KERNEL__ +#define HINT_UNSAFE_IN_KVM(_symbol) _symbol##__unsafe +#else +#define HINT_UNSAFE_IN_KVM(_symbol) _symbol +#endif + /* for KVM_RUN, returned by mmap(vcpu_fd, offset=0) */ struct kvm_run { /* in */ __u8 request_interrupt_window; - __u8 immediate_exit; + __u8 HINT_UNSAFE_IN_KVM(immediate_exit); __u8 padding1[6]; /* out */ @@ -918,6 +931,8 @@ struct kvm_enable_cap { #define KVM_CAP_GUEST_MEMFD 234 #define KVM_CAP_VM_TYPES 235 #define KVM_CAP_PRE_FAULT_MEMORY 236 +#define KVM_CAP_X86_APIC_BUS_CYCLES_NS 237 +#define KVM_CAP_X86_GUEST_MODE 238 struct kvm_irq_routing_irqchip { __u32 irqchip; diff --git a/tools/include/uapi/linux/perf_event.h b/tools/include/uapi/linux/perf_event.h index 3a64499b0f5d63..4842c36fdf8019 100644 --- a/tools/include/uapi/linux/perf_event.h +++ b/tools/include/uapi/linux/perf_event.h @@ -1349,12 +1349,14 @@ union perf_mem_data_src { #define PERF_MEM_LVLNUM_L2 0x02 /* L2 */ #define PERF_MEM_LVLNUM_L3 0x03 /* L3 */ #define PERF_MEM_LVLNUM_L4 0x04 /* L4 */ -/* 5-0x7 available */ +#define PERF_MEM_LVLNUM_L2_MHB 0x05 /* L2 Miss Handling Buffer */ +#define PERF_MEM_LVLNUM_MSC 0x06 /* Memory-side Cache */ +/* 0x7 available */ #define PERF_MEM_LVLNUM_UNC 0x08 /* Uncached */ #define PERF_MEM_LVLNUM_CXL 0x09 /* CXL */ #define PERF_MEM_LVLNUM_IO 0x0a /* I/O */ #define PERF_MEM_LVLNUM_ANY_CACHE 0x0b /* Any cache */ -#define PERF_MEM_LVLNUM_LFB 0x0c /* LFB */ +#define PERF_MEM_LVLNUM_LFB 0x0c /* LFB / L1 Miss Handling Buffer */ #define PERF_MEM_LVLNUM_RAM 0x0d /* RAM */ #define PERF_MEM_LVLNUM_PMEM 0x0e /* PMEM */ #define PERF_MEM_LVLNUM_NA 0x0f /* N/A */ diff --git a/tools/include/uapi/linux/stat.h b/tools/include/uapi/linux/stat.h index 67626d53531664..887a2528644168 100644 --- a/tools/include/uapi/linux/stat.h +++ b/tools/include/uapi/linux/stat.h @@ -126,9 +126,15 @@ struct statx { __u64 stx_mnt_id; __u32 stx_dio_mem_align; /* Memory buffer alignment for direct I/O */ __u32 stx_dio_offset_align; /* File offset alignment for direct I/O */ - __u64 stx_subvol; /* Subvolume identifier */ /* 0xa0 */ - __u64 __spare3[11]; /* Spare space for future expansion */ + __u64 stx_subvol; /* Subvolume identifier */ + __u32 stx_atomic_write_unit_min; /* Min atomic write unit in bytes */ + __u32 stx_atomic_write_unit_max; /* Max atomic write unit in bytes */ + /* 0xb0 */ + __u32 stx_atomic_write_segments_max; /* Max atomic write segment count */ + __u32 __spare1[1]; + /* 0xb8 */ + __u64 __spare3[9]; /* Spare space for future expansion */ /* 0x100 */ }; @@ -157,6 +163,7 @@ struct statx { #define STATX_DIOALIGN 0x00002000U /* Want/got direct I/O alignment info */ #define STATX_MNT_ID_UNIQUE 0x00004000U /* Want/got extended stx_mount_id */ #define STATX_SUBVOL 0x00008000U /* Want/got stx_subvol */ +#define STATX_WRITE_ATOMIC 0x00010000U /* Want/got atomic_write_* fields */ #define STATX__RESERVED 0x80000000U /* Reserved for future struct statx expansion */ @@ -192,6 +199,7 @@ struct statx { #define STATX_ATTR_MOUNT_ROOT 0x00002000 /* Root of a mount */ #define STATX_ATTR_VERITY 0x00100000 /* [I] Verity protected file */ #define STATX_ATTR_DAX 0x00200000 /* File is currently in DAX state */ +#define STATX_ATTR_WRITE_ATOMIC 0x00400000 /* File supports atomic write operations */ #endif /* _UAPI_LINUX_STAT_H */ diff --git a/tools/perf/Documentation/Build.txt b/tools/perf/Documentation/Build.txt index 3766886c4bca3d..83dc87c662b63e 100644 --- a/tools/perf/Documentation/Build.txt +++ b/tools/perf/Documentation/Build.txt @@ -71,3 +71,31 @@ supported by GCC. UBSan detects undefined behaviors of programs at runtime. $ UBSAN_OPTIONS=print_stacktrace=1 ./perf record -a If UBSan detects any problem at runtime, it outputs a “runtime error:” message. + +4) Cross compilation +==================== +As Multiarch is commonly supported in Linux distributions, we can install +libraries for multiple architectures on the same system and then cross-compile +Linux perf. For example, Aarch64 libraries and toolchains can be installed on +an x86_64 machine, allowing us to compile perf for an Aarch64 target. + +Below is the command for building the perf with dynamic linking. + + $ cd /path/to/Linux + $ make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- -C tools/perf + +For static linking, the option `LDFLAGS="-static"` is required. + + $ make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- \ + LDFLAGS="-static" -C tools/perf + +In the embedded system world, a use case is to explicitly specify the package +configuration paths for cross building: + + $ PKG_CONFIG_SYSROOT_DIR="/path/to/cross/build/sysroot" \ + PKG_CONFIG_LIBDIR="/usr/lib/:/usr/local/lib" \ + make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- -C tools/perf + +In this case, the variable PKG_CONFIG_SYSROOT_DIR can be used alongside the +variable PKG_CONFIG_LIBDIR or PKG_CONFIG_PATH to prepend the sysroot path to +the library paths for cross compilation. diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config index c896babf7a740e..fa679db61f6226 100644 --- a/tools/perf/Makefile.config +++ b/tools/perf/Makefile.config @@ -152,7 +152,17 @@ ifdef LIBDW_DIR endif DWARFLIBS := -ldw ifeq ($(findstring -static,${LDFLAGS}),-static) - DWARFLIBS += -lelf -lebl -ldl -lz -llzma -lbz2 + DWARFLIBS += -lelf -ldl -lz -llzma -lbz2 -lzstd + + LIBDW_VERSION := $(shell $(PKG_CONFIG) --modversion libdw) + LIBDW_VERSION_1 := $(word 1, $(subst ., ,$(LIBDW_VERSION))) + LIBDW_VERSION_2 := $(word 2, $(subst ., ,$(LIBDW_VERSION))) + + # Elfutils merged libebl.a into libdw.a starting from version 0.177, + # Link libebl.a only if libdw is older than this version. + ifeq ($(shell test $(LIBDW_VERSION_2) -lt 177; echo $$?),0) + DWARFLIBS += -lebl + endif endif FEATURE_CHECK_CFLAGS-libdw-dwarf-unwind := $(LIBDW_CFLAGS) FEATURE_CHECK_LDFLAGS-libdw-dwarf-unwind := $(LIBDW_LDFLAGS) $(DWARFLIBS) @@ -296,6 +306,11 @@ endif ifdef PYTHON_CONFIG PYTHON_EMBED_LDOPTS := $(shell $(PYTHON_CONFIG_SQ) $(PYTHON_CONFIG_LDFLAGS) 2>/dev/null) + # Update the python flags for cross compilation + ifdef CROSS_COMPILE + PYTHON_NATIVE := $(shell echo $(PYTHON_EMBED_LDOPTS) | sed 's/\(-L.*\/\)\(.*-linux-gnu\).*/\2/') + PYTHON_EMBED_LDOPTS := $(subst $(PYTHON_NATIVE),$(shell $(CC) -dumpmachine),$(PYTHON_EMBED_LDOPTS)) + endif PYTHON_EMBED_LDFLAGS := $(call strip-libs,$(PYTHON_EMBED_LDOPTS)) PYTHON_EMBED_LIBADD := $(call grep-libs,$(PYTHON_EMBED_LDOPTS)) -lutil PYTHON_EMBED_CCOPTS := $(shell $(PYTHON_CONFIG_SQ) --includes 2>/dev/null) @@ -897,6 +912,9 @@ else PYTHON_SETUPTOOLS_INSTALLED := $(shell $(PYTHON) -c 'import setuptools;' 2> /dev/null && echo "yes" || echo "no") ifeq ($(PYTHON_SETUPTOOLS_INSTALLED), yes) PYTHON_EXTENSION_SUFFIX := $(shell $(PYTHON) -c 'from importlib import machinery; print(machinery.EXTENSION_SUFFIXES[0])') + ifdef CROSS_COMPILE + PYTHON_EXTENSION_SUFFIX := $(subst $(PYTHON_NATIVE),$(shell $(CC) -dumpmachine),$(PYTHON_EXTENSION_SUFFIX)) + endif LANG_BINDINGS += $(obj-perf)python/perf$(PYTHON_EXTENSION_SUFFIX) else $(warning Missing python setuptools, the python binding won't be built, please install python3-setuptools or equivalent) diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf index 175e4c7898f0ed..f8148db5fc389b 100644 --- a/tools/perf/Makefile.perf +++ b/tools/perf/Makefile.perf @@ -193,7 +193,32 @@ HOSTLD ?= ld HOSTAR ?= ar CLANG ?= clang -PKG_CONFIG = $(CROSS_COMPILE)pkg-config +# Some distros provide the command $(CROSS_COMPILE)pkg-config for +# searching packges installed with Multiarch. Use it for cross +# compilation if it is existed. +ifneq (, $(shell which $(CROSS_COMPILE)pkg-config)) + PKG_CONFIG ?= $(CROSS_COMPILE)pkg-config +else + PKG_CONFIG ?= pkg-config + + # PKG_CONFIG_PATH or PKG_CONFIG_LIBDIR, alongside PKG_CONFIG_SYSROOT_DIR + # for modified system root, is required for the cross compilation. + # If these PKG_CONFIG environment variables are not set, Multiarch library + # paths are used instead. + ifdef CROSS_COMPILE + ifeq ($(PKG_CONFIG_LIBDIR)$(PKG_CONFIG_PATH)$(PKG_CONFIG_SYSROOT_DIR),) + CROSS_ARCH = $(shell $(CC) -dumpmachine) + PKG_CONFIG_LIBDIR := /usr/local/$(CROSS_ARCH)/lib/pkgconfig/ + PKG_CONFIG_LIBDIR := $(PKG_CONFIG_LIBDIR):/usr/local/lib/$(CROSS_ARCH)/pkgconfig/ + PKG_CONFIG_LIBDIR := $(PKG_CONFIG_LIBDIR):/usr/lib/$(CROSS_ARCH)/pkgconfig/ + PKG_CONFIG_LIBDIR := $(PKG_CONFIG_LIBDIR):/usr/local/share/pkgconfig/ + PKG_CONFIG_LIBDIR := $(PKG_CONFIG_LIBDIR):/usr/share/pkgconfig/ + export PKG_CONFIG_LIBDIR + $(warning Missing PKG_CONFIG_LIBDIR, PKG_CONFIG_PATH and PKG_CONFIG_SYSROOT_DIR for cross compilation,) + $(warning set PKG_CONFIG_LIBDIR for using Multiarch libs.) + endif + endif +endif RM = rm -f LN = ln -f diff --git a/tools/perf/arch/powerpc/entry/syscalls/syscall.tbl b/tools/perf/arch/powerpc/entry/syscalls/syscall.tbl index 3656f1ca7a21c6..ebae8415dfbbab 100644 --- a/tools/perf/arch/powerpc/entry/syscalls/syscall.tbl +++ b/tools/perf/arch/powerpc/entry/syscalls/syscall.tbl @@ -230,8 +230,10 @@ 178 nospu rt_sigsuspend sys_rt_sigsuspend compat_sys_rt_sigsuspend 179 32 pread64 sys_ppc_pread64 compat_sys_ppc_pread64 179 64 pread64 sys_pread64 +179 spu pread64 sys_pread64 180 32 pwrite64 sys_ppc_pwrite64 compat_sys_ppc_pwrite64 180 64 pwrite64 sys_pwrite64 +180 spu pwrite64 sys_pwrite64 181 common chown sys_chown 182 common getcwd sys_getcwd 183 common capget sys_capget @@ -246,6 +248,7 @@ 190 common ugetrlimit sys_getrlimit compat_sys_getrlimit 191 32 readahead sys_ppc_readahead compat_sys_ppc_readahead 191 64 readahead sys_readahead +191 spu readahead sys_readahead 192 32 mmap2 sys_mmap2 compat_sys_mmap2 193 32 truncate64 sys_ppc_truncate64 compat_sys_ppc_truncate64 194 32 ftruncate64 sys_ppc_ftruncate64 compat_sys_ppc_ftruncate64 @@ -293,6 +296,7 @@ 232 nospu set_tid_address sys_set_tid_address 233 32 fadvise64 sys_ppc32_fadvise64 compat_sys_ppc32_fadvise64 233 64 fadvise64 sys_fadvise64 +233 spu fadvise64 sys_fadvise64 234 nospu exit_group sys_exit_group 235 nospu lookup_dcookie sys_ni_syscall 236 common epoll_create sys_epoll_create @@ -502,7 +506,7 @@ 412 32 utimensat_time64 sys_utimensat sys_utimensat 413 32 pselect6_time64 sys_pselect6 compat_sys_pselect6_time64 414 32 ppoll_time64 sys_ppoll compat_sys_ppoll_time64 -416 32 io_pgetevents_time64 sys_io_pgetevents sys_io_pgetevents +416 32 io_pgetevents_time64 sys_io_pgetevents compat_sys_io_pgetevents_time64 417 32 recvmmsg_time64 sys_recvmmsg compat_sys_recvmmsg_time64 418 32 mq_timedsend_time64 sys_mq_timedsend sys_mq_timedsend 419 32 mq_timedreceive_time64 sys_mq_timedreceive sys_mq_timedreceive diff --git a/tools/perf/arch/s390/entry/syscalls/syscall.tbl b/tools/perf/arch/s390/entry/syscalls/syscall.tbl index bd0fee24ad10a3..01071182763e96 100644 --- a/tools/perf/arch/s390/entry/syscalls/syscall.tbl +++ b/tools/perf/arch/s390/entry/syscalls/syscall.tbl @@ -418,7 +418,7 @@ 412 32 utimensat_time64 - sys_utimensat 413 32 pselect6_time64 - compat_sys_pselect6_time64 414 32 ppoll_time64 - compat_sys_ppoll_time64 -416 32 io_pgetevents_time64 - sys_io_pgetevents +416 32 io_pgetevents_time64 - compat_sys_io_pgetevents_time64 417 32 recvmmsg_time64 - compat_sys_recvmmsg_time64 418 32 mq_timedsend_time64 - sys_mq_timedsend 419 32 mq_timedreceive_time64 - sys_mq_timedreceive diff --git a/tools/perf/arch/x86/entry/syscalls/syscall_64.tbl b/tools/perf/arch/x86/entry/syscalls/syscall_64.tbl index a396f6e6ab5bf9..7093ee21c0d1c0 100644 --- a/tools/perf/arch/x86/entry/syscalls/syscall_64.tbl +++ b/tools/perf/arch/x86/entry/syscalls/syscall_64.tbl @@ -1,8 +1,9 @@ +# SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note # # 64-bit system call numbers and entry vectors # # The format is: -# +# [ [noreturn]] # # The __x64_sys_*() stubs are created on-the-fly for sys_*() system calls # @@ -68,7 +69,7 @@ 57 common fork sys_fork 58 common vfork sys_vfork 59 64 execve sys_execve -60 common exit sys_exit +60 common exit sys_exit - noreturn 61 common wait4 sys_wait4 62 common kill sys_kill 63 common uname sys_newuname @@ -239,7 +240,7 @@ 228 common clock_gettime sys_clock_gettime 229 common clock_getres sys_clock_getres 230 common clock_nanosleep sys_clock_nanosleep -231 common exit_group sys_exit_group +231 common exit_group sys_exit_group - noreturn 232 common epoll_wait sys_epoll_wait 233 common epoll_ctl sys_epoll_ctl 234 common tgkill sys_tgkill @@ -343,6 +344,7 @@ 332 common statx sys_statx 333 common io_pgetevents sys_io_pgetevents 334 common rseq sys_rseq +335 common uretprobe sys_uretprobe # don't use numbers 387 through 423, add new calls after the last # 'common' entry 424 common pidfd_send_signal sys_pidfd_send_signal diff --git a/tools/perf/builtin-daemon.c b/tools/perf/builtin-daemon.c index de76bbc50bfbcb..5c9335fff2d396 100644 --- a/tools/perf/builtin-daemon.c +++ b/tools/perf/builtin-daemon.c @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 #include +#include #include #include #include @@ -688,7 +689,7 @@ static int cmd_session_list(struct daemon *daemon, union cmd *cmd, FILE *out) /* lock */ csv_sep, daemon->base, "lock"); - fprintf(out, "%c%lu", + fprintf(out, "%c%" PRIu64, /* session up time */ csv_sep, (curr - daemon->start) / 60); @@ -700,7 +701,7 @@ static int cmd_session_list(struct daemon *daemon, union cmd *cmd, FILE *out) daemon->base, SESSION_OUTPUT); fprintf(out, " lock: %s/lock\n", daemon->base); - fprintf(out, " up: %lu minutes\n", + fprintf(out, " up: %" PRIu64 " minutes\n", (curr - daemon->start) / 60); } } @@ -727,7 +728,7 @@ static int cmd_session_list(struct daemon *daemon, union cmd *cmd, FILE *out) /* session ack */ csv_sep, session->base, SESSION_ACK); - fprintf(out, "%c%lu", + fprintf(out, "%c%" PRIu64, /* session up time */ csv_sep, (curr - session->start) / 60); @@ -745,7 +746,7 @@ static int cmd_session_list(struct daemon *daemon, union cmd *cmd, FILE *out) session->base, SESSION_CONTROL); fprintf(out, " ack: %s/%s\n", session->base, SESSION_ACK); - fprintf(out, " up: %lu minutes\n", + fprintf(out, " up: %" PRIu64 " minutes\n", (curr - session->start) / 60); } } diff --git a/tools/perf/pmu-events/arch/riscv/andes/ax45/firmware.json b/tools/perf/pmu-events/arch/riscv/andes/ax45/firmware.json index 9b4a032186a7b1..7149caec4f80e5 100644 --- a/tools/perf/pmu-events/arch/riscv/andes/ax45/firmware.json +++ b/tools/perf/pmu-events/arch/riscv/andes/ax45/firmware.json @@ -36,7 +36,7 @@ "ArchStdEvent": "FW_SFENCE_VMA_RECEIVED" }, { - "ArchStdEvent": "FW_SFENCE_VMA_RECEIVED" + "ArchStdEvent": "FW_SFENCE_VMA_ASID_SENT" }, { "ArchStdEvent": "FW_SFENCE_VMA_ASID_RECEIVED" diff --git a/tools/perf/pmu-events/arch/riscv/riscv-sbi-firmware.json b/tools/perf/pmu-events/arch/riscv/riscv-sbi-firmware.json index a9939823b14b5a..0c9b9a2d2958a4 100644 --- a/tools/perf/pmu-events/arch/riscv/riscv-sbi-firmware.json +++ b/tools/perf/pmu-events/arch/riscv/riscv-sbi-firmware.json @@ -74,7 +74,7 @@ { "PublicDescription": "Sent SFENCE.VMA with ASID request to other HART event", "ConfigCode": "0x800000000000000c", - "EventName": "FW_SFENCE_VMA_RECEIVED", + "EventName": "FW_SFENCE_VMA_ASID_SENT", "BriefDescription": "Sent SFENCE.VMA with ASID request to other HART event" }, { diff --git a/tools/perf/pmu-events/arch/riscv/sifive/u74/firmware.json b/tools/perf/pmu-events/arch/riscv/sifive/u74/firmware.json index 9b4a032186a7b1..7149caec4f80e5 100644 --- a/tools/perf/pmu-events/arch/riscv/sifive/u74/firmware.json +++ b/tools/perf/pmu-events/arch/riscv/sifive/u74/firmware.json @@ -36,7 +36,7 @@ "ArchStdEvent": "FW_SFENCE_VMA_RECEIVED" }, { - "ArchStdEvent": "FW_SFENCE_VMA_RECEIVED" + "ArchStdEvent": "FW_SFENCE_VMA_ASID_SENT" }, { "ArchStdEvent": "FW_SFENCE_VMA_ASID_RECEIVED" diff --git a/tools/perf/pmu-events/arch/riscv/starfive/dubhe-80/firmware.json b/tools/perf/pmu-events/arch/riscv/starfive/dubhe-80/firmware.json index 9b4a032186a7b1..7149caec4f80e5 100644 --- a/tools/perf/pmu-events/arch/riscv/starfive/dubhe-80/firmware.json +++ b/tools/perf/pmu-events/arch/riscv/starfive/dubhe-80/firmware.json @@ -36,7 +36,7 @@ "ArchStdEvent": "FW_SFENCE_VMA_RECEIVED" }, { - "ArchStdEvent": "FW_SFENCE_VMA_RECEIVED" + "ArchStdEvent": "FW_SFENCE_VMA_ASID_SENT" }, { "ArchStdEvent": "FW_SFENCE_VMA_ASID_RECEIVED" diff --git a/tools/perf/pmu-events/arch/riscv/thead/c900-legacy/firmware.json b/tools/perf/pmu-events/arch/riscv/thead/c900-legacy/firmware.json index 9b4a032186a7b1..7149caec4f80e5 100644 --- a/tools/perf/pmu-events/arch/riscv/thead/c900-legacy/firmware.json +++ b/tools/perf/pmu-events/arch/riscv/thead/c900-legacy/firmware.json @@ -36,7 +36,7 @@ "ArchStdEvent": "FW_SFENCE_VMA_RECEIVED" }, { - "ArchStdEvent": "FW_SFENCE_VMA_RECEIVED" + "ArchStdEvent": "FW_SFENCE_VMA_ASID_SENT" }, { "ArchStdEvent": "FW_SFENCE_VMA_ASID_RECEIVED" diff --git a/tools/perf/trace/beauty/include/linux/socket.h b/tools/perf/trace/beauty/include/linux/socket.h index 89d16b90370bd4..df9cdb8bbfb884 100644 --- a/tools/perf/trace/beauty/include/linux/socket.h +++ b/tools/perf/trace/beauty/include/linux/socket.h @@ -76,7 +76,7 @@ struct msghdr { __kernel_size_t msg_controllen; /* ancillary data buffer length */ struct kiocb *msg_iocb; /* ptr to iocb for async requests */ struct ubuf_info *msg_ubuf; - int (*sg_from_iter)(struct sock *sk, struct sk_buff *skb, + int (*sg_from_iter)(struct sk_buff *skb, struct iov_iter *from, size_t length); }; @@ -442,11 +442,14 @@ extern int __sys_accept4(int fd, struct sockaddr __user *upeer_sockaddr, extern int __sys_socket(int family, int type, int protocol); extern struct file *__sys_socket_file(int family, int type, int protocol); extern int __sys_bind(int fd, struct sockaddr __user *umyaddr, int addrlen); +extern int __sys_bind_socket(struct socket *sock, struct sockaddr_storage *address, + int addrlen); extern int __sys_connect_file(struct file *file, struct sockaddr_storage *addr, int addrlen, int file_flags); extern int __sys_connect(int fd, struct sockaddr __user *uservaddr, int addrlen); extern int __sys_listen(int fd, int backlog); +extern int __sys_listen_socket(struct socket *sock, int backlog); extern int __sys_getsockname(int fd, struct sockaddr __user *usockaddr, int __user *usockaddr_len); extern int __sys_getpeername(int fd, struct sockaddr __user *usockaddr, diff --git a/tools/perf/trace/beauty/include/uapi/linux/fs.h b/tools/perf/trace/beauty/include/uapi/linux/fs.h index 45e4e64fd6643c..7539717707337a 100644 --- a/tools/perf/trace/beauty/include/uapi/linux/fs.h +++ b/tools/perf/trace/beauty/include/uapi/linux/fs.h @@ -329,12 +329,17 @@ typedef int __bitwise __kernel_rwf_t; /* per-IO negation of O_APPEND */ #define RWF_NOAPPEND ((__force __kernel_rwf_t)0x00000020) +/* Atomic Write */ +#define RWF_ATOMIC ((__force __kernel_rwf_t)0x00000040) + /* mask of flags supported by the kernel */ #define RWF_SUPPORTED (RWF_HIPRI | RWF_DSYNC | RWF_SYNC | RWF_NOWAIT |\ - RWF_APPEND | RWF_NOAPPEND) + RWF_APPEND | RWF_NOAPPEND | RWF_ATOMIC) + +#define PROCFS_IOCTL_MAGIC 'f' /* Pagemap ioctl */ -#define PAGEMAP_SCAN _IOWR('f', 16, struct pm_scan_arg) +#define PAGEMAP_SCAN _IOWR(PROCFS_IOCTL_MAGIC, 16, struct pm_scan_arg) /* Bitmasks provided in pm_scan_args masks and reported in page_region.categories. */ #define PAGE_IS_WPALLOWED (1 << 0) @@ -393,4 +398,158 @@ struct pm_scan_arg { __u64 return_mask; }; +/* /proc//maps ioctl */ +#define PROCMAP_QUERY _IOWR(PROCFS_IOCTL_MAGIC, 17, struct procmap_query) + +enum procmap_query_flags { + /* + * VMA permission flags. + * + * Can be used as part of procmap_query.query_flags field to look up + * only VMAs satisfying specified subset of permissions. E.g., specifying + * PROCMAP_QUERY_VMA_READABLE only will return both readable and read/write VMAs, + * while having PROCMAP_QUERY_VMA_READABLE | PROCMAP_QUERY_VMA_WRITABLE will only + * return read/write VMAs, though both executable/non-executable and + * private/shared will be ignored. + * + * PROCMAP_QUERY_VMA_* flags are also returned in procmap_query.vma_flags + * field to specify actual VMA permissions. + */ + PROCMAP_QUERY_VMA_READABLE = 0x01, + PROCMAP_QUERY_VMA_WRITABLE = 0x02, + PROCMAP_QUERY_VMA_EXECUTABLE = 0x04, + PROCMAP_QUERY_VMA_SHARED = 0x08, + /* + * Query modifier flags. + * + * By default VMA that covers provided address is returned, or -ENOENT + * is returned. With PROCMAP_QUERY_COVERING_OR_NEXT_VMA flag set, closest + * VMA with vma_start > addr will be returned if no covering VMA is + * found. + * + * PROCMAP_QUERY_FILE_BACKED_VMA instructs query to consider only VMAs that + * have file backing. Can be combined with PROCMAP_QUERY_COVERING_OR_NEXT_VMA + * to iterate all VMAs with file backing. + */ + PROCMAP_QUERY_COVERING_OR_NEXT_VMA = 0x10, + PROCMAP_QUERY_FILE_BACKED_VMA = 0x20, +}; + +/* + * Input/output argument structured passed into ioctl() call. It can be used + * to query a set of VMAs (Virtual Memory Areas) of a process. + * + * Each field can be one of three kinds, marked in a short comment to the + * right of the field: + * - "in", input argument, user has to provide this value, kernel doesn't modify it; + * - "out", output argument, kernel sets this field with VMA data; + * - "in/out", input and output argument; user provides initial value (used + * to specify maximum allowable buffer size), and kernel sets it to actual + * amount of data written (or zero, if there is no data). + * + * If matching VMA is found (according to criterias specified by + * query_addr/query_flags, all the out fields are filled out, and ioctl() + * returns 0. If there is no matching VMA, -ENOENT will be returned. + * In case of any other error, negative error code other than -ENOENT is + * returned. + * + * Most of the data is similar to the one returned as text in /proc//maps + * file, but procmap_query provides more querying flexibility. There are no + * consistency guarantees between subsequent ioctl() calls, but data returned + * for matched VMA is self-consistent. + */ +struct procmap_query { + /* Query struct size, for backwards/forward compatibility */ + __u64 size; + /* + * Query flags, a combination of enum procmap_query_flags values. + * Defines query filtering and behavior, see enum procmap_query_flags. + * + * Input argument, provided by user. Kernel doesn't modify it. + */ + __u64 query_flags; /* in */ + /* + * Query address. By default, VMA that covers this address will + * be looked up. PROCMAP_QUERY_* flags above modify this default + * behavior further. + * + * Input argument, provided by user. Kernel doesn't modify it. + */ + __u64 query_addr; /* in */ + /* VMA starting (inclusive) and ending (exclusive) address, if VMA is found. */ + __u64 vma_start; /* out */ + __u64 vma_end; /* out */ + /* VMA permissions flags. A combination of PROCMAP_QUERY_VMA_* flags. */ + __u64 vma_flags; /* out */ + /* VMA backing page size granularity. */ + __u64 vma_page_size; /* out */ + /* + * VMA file offset. If VMA has file backing, this specifies offset + * within the file that VMA's start address corresponds to. + * Is set to zero if VMA has no backing file. + */ + __u64 vma_offset; /* out */ + /* Backing file's inode number, or zero, if VMA has no backing file. */ + __u64 inode; /* out */ + /* Backing file's device major/minor number, or zero, if VMA has no backing file. */ + __u32 dev_major; /* out */ + __u32 dev_minor; /* out */ + /* + * If set to non-zero value, signals the request to return VMA name + * (i.e., VMA's backing file's absolute path, with " (deleted)" suffix + * appended, if file was unlinked from FS) for matched VMA. VMA name + * can also be some special name (e.g., "[heap]", "[stack]") or could + * be even user-supplied with prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME). + * + * Kernel will set this field to zero, if VMA has no associated name. + * Otherwise kernel will return actual amount of bytes filled in + * user-supplied buffer (see vma_name_addr field below), including the + * terminating zero. + * + * If VMA name is longer that user-supplied maximum buffer size, + * -E2BIG error is returned. + * + * If this field is set to non-zero value, vma_name_addr should point + * to valid user space memory buffer of at least vma_name_size bytes. + * If set to zero, vma_name_addr should be set to zero as well + */ + __u32 vma_name_size; /* in/out */ + /* + * If set to non-zero value, signals the request to extract and return + * VMA's backing file's build ID, if the backing file is an ELF file + * and it contains embedded build ID. + * + * Kernel will set this field to zero, if VMA has no backing file, + * backing file is not an ELF file, or ELF file has no build ID + * embedded. + * + * Build ID is a binary value (not a string). Kernel will set + * build_id_size field to exact number of bytes used for build ID. + * If build ID is requested and present, but needs more bytes than + * user-supplied maximum buffer size (see build_id_addr field below), + * -E2BIG error will be returned. + * + * If this field is set to non-zero value, build_id_addr should point + * to valid user space memory buffer of at least build_id_size bytes. + * If set to zero, build_id_addr should be set to zero as well + */ + __u32 build_id_size; /* in/out */ + /* + * User-supplied address of a buffer of at least vma_name_size bytes + * for kernel to fill with matched VMA's name (see vma_name_size field + * description above for details). + * + * Should be set to zero if VMA name should not be returned. + */ + __u64 vma_name_addr; /* in */ + /* + * User-supplied address of a buffer of at least build_id_size bytes + * for kernel to fill with matched VMA's ELF build ID, if available + * (see build_id_size field description above for details). + * + * Should be set to zero if build ID should not be returned. + */ + __u64 build_id_addr; /* in */ +}; + #endif /* _UAPI_LINUX_FS_H */ diff --git a/tools/perf/trace/beauty/include/uapi/linux/mount.h b/tools/perf/trace/beauty/include/uapi/linux/mount.h index ad5478dbad0073..225bc366ffcbf0 100644 --- a/tools/perf/trace/beauty/include/uapi/linux/mount.h +++ b/tools/perf/trace/beauty/include/uapi/linux/mount.h @@ -154,7 +154,7 @@ struct mount_attr { */ struct statmount { __u32 size; /* Total size, including strings */ - __u32 __spare1; + __u32 mnt_opts; /* [str] Mount options of the mount */ __u64 mask; /* What results were written */ __u32 sb_dev_major; /* Device ID */ __u32 sb_dev_minor; @@ -172,7 +172,8 @@ struct statmount { __u64 propagate_from; /* Propagation from in current namespace */ __u32 mnt_root; /* [str] Root of mount relative to root of fs */ __u32 mnt_point; /* [str] Mountpoint relative to current root */ - __u64 __spare2[50]; + __u64 mnt_ns_id; /* ID of the mount namespace */ + __u64 __spare2[49]; char str[]; /* Variable size part containing strings */ }; @@ -188,10 +189,12 @@ struct mnt_id_req { __u32 spare; __u64 mnt_id; __u64 param; + __u64 mnt_ns_id; }; /* List of all mnt_id_req versions. */ #define MNT_ID_REQ_SIZE_VER0 24 /* sizeof first published struct */ +#define MNT_ID_REQ_SIZE_VER1 32 /* sizeof second published struct */ /* * @mask bits for statmount(2) @@ -202,10 +205,13 @@ struct mnt_id_req { #define STATMOUNT_MNT_ROOT 0x00000008U /* Want/got mnt_root */ #define STATMOUNT_MNT_POINT 0x00000010U /* Want/got mnt_point */ #define STATMOUNT_FS_TYPE 0x00000020U /* Want/got fs_type */ +#define STATMOUNT_MNT_NS_ID 0x00000040U /* Want/got mnt_ns_id */ +#define STATMOUNT_MNT_OPTS 0x00000080U /* Want/got mnt_opts */ /* * Special @mnt_id values that can be passed to listmount */ #define LSMT_ROOT 0xffffffffffffffff /* root mount */ +#define LISTMOUNT_REVERSE (1 << 0) /* List later mounts first */ #endif /* _UAPI_LINUX_MOUNT_H */ diff --git a/tools/perf/trace/beauty/include/uapi/linux/stat.h b/tools/perf/trace/beauty/include/uapi/linux/stat.h index 67626d53531664..887a2528644168 100644 --- a/tools/perf/trace/beauty/include/uapi/linux/stat.h +++ b/tools/perf/trace/beauty/include/uapi/linux/stat.h @@ -126,9 +126,15 @@ struct statx { __u64 stx_mnt_id; __u32 stx_dio_mem_align; /* Memory buffer alignment for direct I/O */ __u32 stx_dio_offset_align; /* File offset alignment for direct I/O */ - __u64 stx_subvol; /* Subvolume identifier */ /* 0xa0 */ - __u64 __spare3[11]; /* Spare space for future expansion */ + __u64 stx_subvol; /* Subvolume identifier */ + __u32 stx_atomic_write_unit_min; /* Min atomic write unit in bytes */ + __u32 stx_atomic_write_unit_max; /* Max atomic write unit in bytes */ + /* 0xb0 */ + __u32 stx_atomic_write_segments_max; /* Max atomic write segment count */ + __u32 __spare1[1]; + /* 0xb8 */ + __u64 __spare3[9]; /* Spare space for future expansion */ /* 0x100 */ }; @@ -157,6 +163,7 @@ struct statx { #define STATX_DIOALIGN 0x00002000U /* Want/got direct I/O alignment info */ #define STATX_MNT_ID_UNIQUE 0x00004000U /* Want/got extended stx_mount_id */ #define STATX_SUBVOL 0x00008000U /* Want/got stx_subvol */ +#define STATX_WRITE_ATOMIC 0x00010000U /* Want/got atomic_write_* fields */ #define STATX__RESERVED 0x80000000U /* Reserved for future struct statx expansion */ @@ -192,6 +199,7 @@ struct statx { #define STATX_ATTR_MOUNT_ROOT 0x00002000 /* Root of a mount */ #define STATX_ATTR_VERITY 0x00100000 /* [I] Verity protected file */ #define STATX_ATTR_DAX 0x00200000 /* File is currently in DAX state */ +#define STATX_ATTR_WRITE_ATOMIC 0x00400000 /* File supports atomic write operations */ #endif /* _UAPI_LINUX_STAT_H */ diff --git a/tools/perf/trace/beauty/include/uapi/sound/asound.h b/tools/perf/trace/beauty/include/uapi/sound/asound.h index 628d46a0da92eb..8bf7e8a0eb6f03 100644 --- a/tools/perf/trace/beauty/include/uapi/sound/asound.h +++ b/tools/perf/trace/beauty/include/uapi/sound/asound.h @@ -142,7 +142,7 @@ struct snd_hwdep_dsp_image { * * *****************************************************************************/ -#define SNDRV_PCM_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 17) +#define SNDRV_PCM_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 18) typedef unsigned long snd_pcm_uframes_t; typedef signed long snd_pcm_sframes_t; @@ -334,7 +334,7 @@ union snd_pcm_sync_id { unsigned char id[16]; unsigned short id16[8]; unsigned int id32[4]; -}; +} __attribute__((deprecated)); struct snd_pcm_info { unsigned int device; /* RO/WR (control): device number */ @@ -348,7 +348,7 @@ struct snd_pcm_info { int dev_subclass; /* SNDRV_PCM_SUBCLASS_* */ unsigned int subdevices_count; unsigned int subdevices_avail; - union snd_pcm_sync_id sync; /* hardware synchronization ID */ + unsigned char pad1[16]; /* was: hardware synchronization ID */ unsigned char reserved[64]; /* reserved for future... */ }; @@ -420,7 +420,8 @@ struct snd_pcm_hw_params { unsigned int rate_num; /* R: rate numerator */ unsigned int rate_den; /* R: rate denominator */ snd_pcm_uframes_t fifo_size; /* R: chip FIFO size in frames */ - unsigned char reserved[64]; /* reserved for future */ + unsigned char sync[16]; /* R: synchronization ID (perfect sync - one clock source) */ + unsigned char reserved[48]; /* reserved for future */ }; enum { diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c index 1730b852a94740..6d075648d2ccf4 100644 --- a/tools/perf/util/callchain.c +++ b/tools/perf/util/callchain.c @@ -1141,7 +1141,7 @@ int hist_entry__append_callchain(struct hist_entry *he, struct perf_sample *samp int fill_callchain_info(struct addr_location *al, struct callchain_cursor_node *node, bool hide_unresolved) { - struct machine *machine = maps__machine(node->ms.maps); + struct machine *machine = node->ms.maps ? maps__machine(node->ms.maps) : NULL; maps__put(al->maps); al->maps = maps__get(node->ms.maps); diff --git a/tools/testing/selftests/alsa/Makefile b/tools/testing/selftests/alsa/Makefile index c1ce39874e2b54..25be6802529083 100644 --- a/tools/testing/selftests/alsa/Makefile +++ b/tools/testing/selftests/alsa/Makefile @@ -12,9 +12,9 @@ LDLIBS+=-lpthread OVERRIDE_TARGETS = 1 -TEST_GEN_PROGS := mixer-test pcm-test test-pcmtest-driver +TEST_GEN_PROGS := mixer-test pcm-test test-pcmtest-driver utimer-test -TEST_GEN_PROGS_EXTENDED := libatest.so +TEST_GEN_PROGS_EXTENDED := libatest.so global-timer TEST_FILES := conf.d pcm-test.conf diff --git a/tools/testing/selftests/alsa/global-timer.c b/tools/testing/selftests/alsa/global-timer.c new file mode 100644 index 00000000000000..c15ec0ba851acf --- /dev/null +++ b/tools/testing/selftests/alsa/global-timer.c @@ -0,0 +1,87 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * This tool is used by the utimer test, and it allows us to + * count the ticks of a global timer in a certain time frame + * (which is set by `timeout` parameter). + * + * Author: Ivan Orlov + */ +#include +#include +#include +#include + +static int ticked; +static void async_callback(snd_async_handler_t *ahandler) +{ + ticked++; +} + +static char timer_name[64]; +static void bind_to_timer(int device, int subdevice, int timeout) +{ + snd_timer_t *handle; + snd_timer_params_t *params; + snd_async_handler_t *ahandler; + + time_t end; + + sprintf(timer_name, "hw:CLASS=%d,SCLASS=%d,DEV=%d,SUBDEV=%d", + SND_TIMER_CLASS_GLOBAL, SND_TIMER_SCLASS_NONE, + device, subdevice); + + snd_timer_params_alloca(¶ms); + + if (snd_timer_open(&handle, timer_name, SND_TIMER_OPEN_NONBLOCK) < 0) { + perror("Can't open the timer"); + exit(EXIT_FAILURE); + } + + snd_timer_params_set_auto_start(params, 1); + snd_timer_params_set_ticks(params, 1); + if (snd_timer_params(handle, params) < 0) { + perror("Can't set timer params"); + exit(EXIT_FAILURE); + } + + if (snd_async_add_timer_handler(&ahandler, handle, async_callback, NULL) < 0) { + perror("Can't create a handler"); + exit(EXIT_FAILURE); + } + end = time(NULL) + timeout; + if (snd_timer_start(handle) < 0) { + perror("Failed to start the timer"); + exit(EXIT_FAILURE); + } + printf("Timer has started\n"); + while (time(NULL) <= end) { + /* + * Waiting for the timeout to elapse. Can't use sleep here, as it gets + * constantly interrupted by the signal from the timer (SIGIO) + */ + } + snd_timer_stop(handle); + snd_timer_close(handle); +} + +int main(int argc, char *argv[]) +{ + int device, subdevice, timeout; + + if (argc < 4) { + perror("Usage: %s "); + return EXIT_FAILURE; + } + + setlinebuf(stdout); + + device = atoi(argv[1]); + subdevice = atoi(argv[2]); + timeout = atoi(argv[3]); + + bind_to_timer(device, subdevice, timeout); + + printf("Total ticks count: %d\n", ticked); + + return EXIT_SUCCESS; +} diff --git a/tools/testing/selftests/alsa/utimer-test.c b/tools/testing/selftests/alsa/utimer-test.c new file mode 100644 index 00000000000000..32ee3ce577216b --- /dev/null +++ b/tools/testing/selftests/alsa/utimer-test.c @@ -0,0 +1,164 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * This test covers the functionality of userspace-driven ALSA timers. Such timers + * are purely virtual (so they don't directly depend on the hardware), and they could be + * created and triggered by userspace applications. + * + * Author: Ivan Orlov + */ +#include "../kselftest_harness.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#define FRAME_RATE 8000 +#define PERIOD_SIZE 4410 +#define UTIMER_DEFAULT_ID -1 +#define UTIMER_DEFAULT_FD -1 +#define NANO 1000000000ULL +#define TICKS_COUNT 10 +#define TICKS_RECORDING_DELTA 5 +#define TIMER_OUTPUT_BUF_LEN 1024 +#define TIMER_FREQ_SEC 1 +#define RESULT_PREFIX_LEN strlen("Total ticks count: ") + +enum timer_app_event { + TIMER_APP_STARTED, + TIMER_APP_RESULT, + TIMER_NO_EVENT, +}; + +FIXTURE(timer_f) { + struct snd_timer_uinfo *utimer_info; +}; + +FIXTURE_SETUP(timer_f) { + int timer_dev_fd; + + if (geteuid()) + SKIP(return, "This test needs root to run!"); + + self->utimer_info = calloc(1, sizeof(*self->utimer_info)); + ASSERT_NE(NULL, self->utimer_info); + + /* Resolution is the time the period of frames takes in nanoseconds */ + self->utimer_info->resolution = (NANO / FRAME_RATE * PERIOD_SIZE); + + timer_dev_fd = open("/dev/snd/timer", O_RDONLY); + ASSERT_GE(timer_dev_fd, 0); + + ASSERT_EQ(ioctl(timer_dev_fd, SNDRV_TIMER_IOCTL_CREATE, self->utimer_info), 0); + ASSERT_GE(self->utimer_info->fd, 0); + + close(timer_dev_fd); +} + +FIXTURE_TEARDOWN(timer_f) { + close(self->utimer_info->fd); + free(self->utimer_info); +} + +static void *ticking_func(void *data) +{ + int i; + int *fd = (int *)data; + + for (i = 0; i < TICKS_COUNT; i++) { + /* Well, trigger the timer! */ + ioctl(*fd, SNDRV_TIMER_IOCTL_TRIGGER, NULL); + sleep(TIMER_FREQ_SEC); + } + + return NULL; +} + +static enum timer_app_event parse_timer_output(const char *s) +{ + if (strstr(s, "Timer has started")) + return TIMER_APP_STARTED; + if (strstr(s, "Total ticks count")) + return TIMER_APP_RESULT; + + return TIMER_NO_EVENT; +} + +static int parse_timer_result(const char *s) +{ + char *end; + long d; + + d = strtol(s + RESULT_PREFIX_LEN, &end, 10); + if (end == s + RESULT_PREFIX_LEN) + return -1; + + return d; +} + +/* + * This test triggers the timer and counts ticks at the same time. The amount + * of the timer trigger calls should be equal to the amount of ticks received. + */ +TEST_F(timer_f, utimer) { + char command[64]; + pthread_t ticking_thread; + int total_ticks = 0; + FILE *rfp; + char *buf = malloc(TIMER_OUTPUT_BUF_LEN); + + ASSERT_NE(buf, NULL); + + /* The timeout should be the ticks interval * count of ticks + some delta */ + sprintf(command, "./global-timer %d %d %d", SNDRV_TIMER_GLOBAL_UDRIVEN, + self->utimer_info->id, TICKS_COUNT * TIMER_FREQ_SEC + TICKS_RECORDING_DELTA); + + rfp = popen(command, "r"); + while (fgets(buf, TIMER_OUTPUT_BUF_LEN, rfp)) { + buf[TIMER_OUTPUT_BUF_LEN - 1] = 0; + switch (parse_timer_output(buf)) { + case TIMER_APP_STARTED: + /* global-timer waits for timer to trigger, so start the ticking thread */ + pthread_create(&ticking_thread, NULL, ticking_func, + &self->utimer_info->fd); + break; + case TIMER_APP_RESULT: + total_ticks = parse_timer_result(buf); + break; + case TIMER_NO_EVENT: + break; + } + } + pthread_join(ticking_thread, NULL); + ASSERT_EQ(total_ticks, TICKS_COUNT); + pclose(rfp); +} + +TEST(wrong_timers_test) { + int timer_dev_fd; + int utimer_fd; + size_t i; + struct snd_timer_uinfo wrong_timer = { + .resolution = 0, + .id = UTIMER_DEFAULT_ID, + .fd = UTIMER_DEFAULT_FD, + }; + + timer_dev_fd = open("/dev/snd/timer", O_RDONLY); + ASSERT_GE(timer_dev_fd, 0); + + utimer_fd = ioctl(timer_dev_fd, SNDRV_TIMER_IOCTL_CREATE, &wrong_timer); + ASSERT_LT(utimer_fd, 0); + /* Check that id was not updated */ + ASSERT_EQ(wrong_timer.id, UTIMER_DEFAULT_ID); + + /* Test the NULL as an argument is processed correctly */ + ASSERT_LT(ioctl(timer_dev_fd, SNDRV_TIMER_IOCTL_CREATE, NULL), 0); + + close(timer_dev_fd); +} + +TEST_HARNESS_MAIN diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile index dd49c1d23a604c..81d4757ecd4c65 100644 --- a/tools/testing/selftests/bpf/Makefile +++ b/tools/testing/selftests/bpf/Makefile @@ -713,7 +713,7 @@ $(OUTPUT)/xdp_features: xdp_features.c $(OUTPUT)/network_helpers.o $(OUTPUT)/xdp # Make sure we are able to include and link libbpf against c++. $(OUTPUT)/test_cpp: test_cpp.cpp $(OUTPUT)/test_core_extern.skel.h $(BPFOBJ) $(call msg,CXX,,$@) - $(Q)$(CXX) $(CFLAGS) $(filter %.a %.o %.cpp,$^) $(LDLIBS) -o $@ + $(Q)$(CXX) $(subst -D_GNU_SOURCE=,,$(CFLAGS)) $(filter %.a %.o %.cpp,$^) $(LDLIBS) -o $@ # Benchmark runner $(OUTPUT)/bench_%.o: benchs/bench_%.c bench.h $(BPFOBJ) diff --git a/tools/testing/selftests/bpf/prog_tests/uprobe_syscall.c b/tools/testing/selftests/bpf/prog_tests/uprobe_syscall.c index bd8c75b620c29d..c397336fe1ed1c 100644 --- a/tools/testing/selftests/bpf/prog_tests/uprobe_syscall.c +++ b/tools/testing/selftests/bpf/prog_tests/uprobe_syscall.c @@ -216,7 +216,7 @@ static void test_uretprobe_regs_change(void) } #ifndef __NR_uretprobe -#define __NR_uretprobe 467 +#define __NR_uretprobe 335 #endif __naked unsigned long uretprobe_syscall_call_1(void) @@ -253,7 +253,7 @@ static void test_uretprobe_syscall_call(void) struct uprobe_syscall_executed *skel; int pid, status, err, go[2], c; - if (ASSERT_OK(pipe(go), "pipe")) + if (!ASSERT_OK(pipe(go), "pipe")) return; skel = uprobe_syscall_executed__open_and_load(); diff --git a/tools/testing/selftests/bpf/progs/iters.c b/tools/testing/selftests/bpf/progs/iters.c index 16bdc3e255913c..ef70b88bccb252 100644 --- a/tools/testing/selftests/bpf/progs/iters.c +++ b/tools/testing/selftests/bpf/progs/iters.c @@ -1432,4 +1432,58 @@ int iter_arr_with_actual_elem_count(const void *ctx) return sum; } +__u32 upper, select_n, result; +__u64 global; + +static __noinline bool nest_2(char *str) +{ + /* some insns (including branch insns) to ensure stacksafe() is triggered + * in nest_2(). This way, stacksafe() can compare frame associated with nest_1(). + */ + if (str[0] == 't') + return true; + if (str[1] == 'e') + return true; + if (str[2] == 's') + return true; + if (str[3] == 't') + return true; + return false; +} + +static __noinline bool nest_1(int n) +{ + /* case 0: allocate stack, case 1: no allocate stack */ + switch (n) { + case 0: { + char comm[16]; + + if (bpf_get_current_comm(comm, 16)) + return false; + return nest_2(comm); + } + case 1: + return nest_2((char *)&global); + default: + return false; + } +} + +SEC("raw_tp") +__success +int iter_subprog_check_stacksafe(const void *ctx) +{ + long i; + + bpf_for(i, 0, upper) { + if (!nest_1(select_n)) { + result = 1; + return 0; + } + } + + result = 2; + return 0; +} + char _license[] SEC("license") = "GPL"; diff --git a/tools/testing/selftests/core/close_range_test.c b/tools/testing/selftests/core/close_range_test.c index 991c473e385938..12b4eb9d04347f 100644 --- a/tools/testing/selftests/core/close_range_test.c +++ b/tools/testing/selftests/core/close_range_test.c @@ -589,4 +589,39 @@ TEST(close_range_cloexec_unshare_syzbot) EXPECT_EQ(close(fd3), 0); } +TEST(close_range_bitmap_corruption) +{ + pid_t pid; + int status; + struct __clone_args args = { + .flags = CLONE_FILES, + .exit_signal = SIGCHLD, + }; + + /* get the first 128 descriptors open */ + for (int i = 2; i < 128; i++) + EXPECT_GE(dup2(0, i), 0); + + /* get descriptor table shared */ + pid = sys_clone3(&args, sizeof(args)); + ASSERT_GE(pid, 0); + + if (pid == 0) { + /* unshare and truncate descriptor table down to 64 */ + if (sys_close_range(64, ~0U, CLOSE_RANGE_UNSHARE)) + exit(EXIT_FAILURE); + + ASSERT_EQ(fcntl(64, F_GETFD), -1); + /* ... and verify that the range 64..127 is not + stuck "fully used" according to secondary bitmap */ + EXPECT_EQ(dup(0), 64) + exit(EXIT_FAILURE); + exit(EXIT_SUCCESS); + } + + EXPECT_EQ(waitpid(pid, &status, 0), pid); + EXPECT_EQ(true, WIFEXITED(status)); + EXPECT_EQ(0, WEXITSTATUS(status)); +} + TEST_HARNESS_MAIN diff --git a/tools/testing/selftests/dmabuf-heaps/dmabuf-heap.c b/tools/testing/selftests/dmabuf-heaps/dmabuf-heap.c index 5f541522364fbd..5d0a809dc2df93 100644 --- a/tools/testing/selftests/dmabuf-heaps/dmabuf-heap.c +++ b/tools/testing/selftests/dmabuf-heaps/dmabuf-heap.c @@ -29,9 +29,11 @@ static int check_vgem(int fd) version.name = name; ret = ioctl(fd, DRM_IOCTL_VERSION, &version); - if (ret) + if (ret || version.name_len != 4) return 0; + name[4] = '\0'; + return !strcmp(name, "vgem"); } diff --git a/tools/testing/selftests/drivers/net/hw/rss_ctx.py b/tools/testing/selftests/drivers/net/hw/rss_ctx.py index 931dbc36ca43d6..011508ca604b08 100755 --- a/tools/testing/selftests/drivers/net/hw/rss_ctx.py +++ b/tools/testing/selftests/drivers/net/hw/rss_ctx.py @@ -19,6 +19,15 @@ def _rss_key_rand(length): return [random.randint(0, 255) for _ in range(length)] +def _rss_key_check(cfg, data=None, context=0): + if data is None: + data = get_rss(cfg, context=context) + if 'rss-hash-key' not in data: + return + non_zero = [x for x in data['rss-hash-key'] if x != 0] + ksft_eq(bool(non_zero), True, comment=f"RSS key is all zero {data['rss-hash-key']}") + + def get_rss(cfg, context=0): return ethtool(f"-x {cfg.ifname} context {context}", json=True)[0] @@ -90,8 +99,9 @@ def _send_traffic_check(cfg, port, name, params): def test_rss_key_indir(cfg): """Test basics like updating the main RSS key and indirection table.""" - if len(_get_rx_cnts(cfg)) < 2: - KsftSkipEx("Device has only one queue (or doesn't support queue stats)") + qcnt = len(_get_rx_cnts(cfg)) + if qcnt < 3: + KsftSkipEx("Device has fewer than 3 queues (or doesn't support queue stats)") data = get_rss(cfg) want_keys = ['rss-hash-key', 'rss-hash-function', 'rss-indirection-table'] @@ -101,6 +111,7 @@ def test_rss_key_indir(cfg): if not data[k]: raise KsftFailEx(f"ethtool results empty for '{k}': {data[k]}") + _rss_key_check(cfg, data=data) key_len = len(data['rss-hash-key']) # Set the key @@ -110,9 +121,26 @@ def test_rss_key_indir(cfg): data = get_rss(cfg) ksft_eq(key, data['rss-hash-key']) + # Set the indirection table and the key together + key = _rss_key_rand(key_len) + ethtool(f"-X {cfg.ifname} equal 3 hkey " + _rss_key_str(key)) + reset_indir = defer(ethtool, f"-X {cfg.ifname} default") + + data = get_rss(cfg) + _rss_key_check(cfg, data=data) + ksft_eq(0, min(data['rss-indirection-table'])) + ksft_eq(2, max(data['rss-indirection-table'])) + + # Reset indirection table and set the key + key = _rss_key_rand(key_len) + ethtool(f"-X {cfg.ifname} default hkey " + _rss_key_str(key)) + data = get_rss(cfg) + _rss_key_check(cfg, data=data) + ksft_eq(0, min(data['rss-indirection-table'])) + ksft_eq(qcnt - 1, max(data['rss-indirection-table'])) + # Set the indirection table ethtool(f"-X {cfg.ifname} equal 2") - reset_indir = defer(ethtool, f"-X {cfg.ifname} default") data = get_rss(cfg) ksft_eq(0, min(data['rss-indirection-table'])) ksft_eq(1, max(data['rss-indirection-table'])) @@ -317,8 +345,11 @@ def test_rss_context(cfg, ctx_cnt=1, create_with_cfg=None): ctx_cnt = i break + _rss_key_check(cfg, context=ctx_id) + if not create_with_cfg: ethtool(f"-X {cfg.ifname} context {ctx_id} {want_cfg}") + _rss_key_check(cfg, context=ctx_id) # Sanity check the context we just created data = get_rss(cfg, ctx_id) diff --git a/tools/testing/selftests/hid/hid_bpf.c b/tools/testing/selftests/hid/hid_bpf.c index dc0408a831d07c..75b7b4ef6cfaa7 100644 --- a/tools/testing/selftests/hid/hid_bpf.c +++ b/tools/testing/selftests/hid/hid_bpf.c @@ -532,6 +532,7 @@ static void load_programs(const struct test_program programs[], FIXTURE_DATA(hid_bpf) * self, const FIXTURE_VARIANT(hid_bpf) * variant) { + struct bpf_map *iter_map; int err = -EINVAL; ASSERT_LE(progs_count, ARRAY_SIZE(self->hid_links)) @@ -564,6 +565,13 @@ static void load_programs(const struct test_program programs[], *ops_hid_id = self->hid_id; } + /* we disable the auto-attach feature of all maps because we + * only want the tested one to be manually attached in the next + * call to bpf_map__attach_struct_ops() + */ + bpf_object__for_each_map(iter_map, *self->skel->skeleton->obj) + bpf_map__set_autoattach(iter_map, false); + err = hid__load(self->skel); ASSERT_OK(err) TH_LOG("hid_skel_load failed: %d", err); @@ -686,6 +694,24 @@ TEST_F(hid_bpf, subprog_raw_event) ASSERT_EQ(buf[2], 52); } +/* + * Attach hid_first_event to the given uhid device, + * attempt at re-attaching it, we should not lock and + * return an invalid struct bpf_link + */ +TEST_F(hid_bpf, multiple_attach) +{ + const struct test_program progs[] = { + { .name = "hid_first_event" }, + }; + struct bpf_link *link; + + LOAD_PROGRAMS(progs); + + link = bpf_map__attach_struct_ops(self->skel->maps.first_event); + ASSERT_NULL(link) TH_LOG("unexpected return value when re-attaching the struct_ops"); +} + /* * Ensures that we can attach/detach programs */ diff --git a/tools/testing/selftests/hid/progs/hid.c b/tools/testing/selftests/hid/progs/hid.c index ee9bbbcf751b48..5ecc845ef79216 100644 --- a/tools/testing/selftests/hid/progs/hid.c +++ b/tools/testing/selftests/hid/progs/hid.c @@ -455,7 +455,7 @@ struct { __type(value, struct elem); } hmap SEC(".maps"); -static int wq_cb_sleepable(void *map, int *key, struct bpf_wq *work) +static int wq_cb_sleepable(void *map, int *key, void *work) { __u8 buf[9] = {2, 3, 4, 5, 6, 7, 8, 9, 10}; struct hid_bpf_ctx *hid_ctx; diff --git a/tools/testing/selftests/hid/progs/hid_bpf_helpers.h b/tools/testing/selftests/hid/progs/hid_bpf_helpers.h index cfe37f49190622..e5db897586bbfe 100644 --- a/tools/testing/selftests/hid/progs/hid_bpf_helpers.h +++ b/tools/testing/selftests/hid/progs/hid_bpf_helpers.h @@ -114,7 +114,7 @@ extern int hid_bpf_try_input_report(struct hid_bpf_ctx *ctx, extern int bpf_wq_init(struct bpf_wq *wq, void *p__map, unsigned int flags) __weak __ksym; extern int bpf_wq_start(struct bpf_wq *wq, unsigned int flags) __weak __ksym; extern int bpf_wq_set_callback_impl(struct bpf_wq *wq, - int (callback_fn)(void *map, int *key, struct bpf_wq *wq), + int (callback_fn)(void *map, int *key, void *wq), unsigned int flags__k, void *aux__ign) __ksym; #define bpf_wq_set_callback(timer, cb, flags) \ bpf_wq_set_callback_impl(timer, cb, flags, NULL) diff --git a/tools/testing/selftests/kselftest/ksft.py b/tools/testing/selftests/kselftest/ksft.py index cd89fb2bc10e7f..bf215790a89d73 100644 --- a/tools/testing/selftests/kselftest/ksft.py +++ b/tools/testing/selftests/kselftest/ksft.py @@ -70,7 +70,7 @@ def test_result(condition, description=""): def finished(): - if ksft_cnt["pass"] == ksft_num_tests: + if ksft_cnt["pass"] + ksft_cnt["skip"] == ksft_num_tests: exit_code = KSFT_PASS else: exit_code = KSFT_FAIL diff --git a/tools/testing/selftests/kvm/aarch64/get-reg-list.c b/tools/testing/selftests/kvm/aarch64/get-reg-list.c index 709d7d72176035..4abebde781873b 100644 --- a/tools/testing/selftests/kvm/aarch64/get-reg-list.c +++ b/tools/testing/selftests/kvm/aarch64/get-reg-list.c @@ -32,13 +32,13 @@ static struct feature_id_reg feat_id_regs[] = { { ARM64_SYS_REG(3, 0, 10, 2, 2), /* PIRE0_EL1 */ ARM64_SYS_REG(3, 0, 0, 7, 3), /* ID_AA64MMFR3_EL1 */ - 4, + 8, 1 }, { ARM64_SYS_REG(3, 0, 10, 2, 3), /* PIR_EL1 */ ARM64_SYS_REG(3, 0, 0, 7, 3), /* ID_AA64MMFR3_EL1 */ - 4, + 8, 1 } }; diff --git a/tools/testing/selftests/kvm/riscv/get-reg-list.c b/tools/testing/selftests/kvm/riscv/get-reg-list.c index f92c2fb23fcd75..8e34f7fa44e94c 100644 --- a/tools/testing/selftests/kvm/riscv/get-reg-list.c +++ b/tools/testing/selftests/kvm/riscv/get-reg-list.c @@ -961,10 +961,10 @@ KVM_ISA_EXT_SIMPLE_CONFIG(zbkb, ZBKB); KVM_ISA_EXT_SIMPLE_CONFIG(zbkc, ZBKC); KVM_ISA_EXT_SIMPLE_CONFIG(zbkx, ZBKX); KVM_ISA_EXT_SIMPLE_CONFIG(zbs, ZBS); -KVM_ISA_EXT_SIMPLE_CONFIG(zca, ZCA), -KVM_ISA_EXT_SIMPLE_CONFIG(zcb, ZCB), -KVM_ISA_EXT_SIMPLE_CONFIG(zcd, ZCD), -KVM_ISA_EXT_SIMPLE_CONFIG(zcf, ZCF), +KVM_ISA_EXT_SIMPLE_CONFIG(zca, ZCA); +KVM_ISA_EXT_SIMPLE_CONFIG(zcb, ZCB); +KVM_ISA_EXT_SIMPLE_CONFIG(zcd, ZCD); +KVM_ISA_EXT_SIMPLE_CONFIG(zcf, ZCF); KVM_ISA_EXT_SIMPLE_CONFIG(zcmop, ZCMOP); KVM_ISA_EXT_SIMPLE_CONFIG(zfa, ZFA); KVM_ISA_EXT_SIMPLE_CONFIG(zfh, ZFH); diff --git a/tools/testing/selftests/kvm/x86_64/xapic_state_test.c b/tools/testing/selftests/kvm/x86_64/xapic_state_test.c index 69849acd95b0af..618cd244239004 100644 --- a/tools/testing/selftests/kvm/x86_64/xapic_state_test.c +++ b/tools/testing/selftests/kvm/x86_64/xapic_state_test.c @@ -184,6 +184,33 @@ static void test_apic_id(void) kvm_vm_free(vm); } +static void test_x2apic_id(void) +{ + struct kvm_lapic_state lapic = {}; + struct kvm_vcpu *vcpu; + struct kvm_vm *vm; + int i; + + vm = vm_create_with_one_vcpu(&vcpu, NULL); + vcpu_set_msr(vcpu, MSR_IA32_APICBASE, MSR_IA32_APICBASE_ENABLE | X2APIC_ENABLE); + + /* + * Try stuffing a modified x2APIC ID, KVM should ignore the value and + * always return the vCPU's default/readonly x2APIC ID. + */ + for (i = 0; i <= 0xff; i++) { + *(u32 *)(lapic.regs + APIC_ID) = i << 24; + *(u32 *)(lapic.regs + APIC_SPIV) = APIC_SPIV_APIC_ENABLED; + vcpu_ioctl(vcpu, KVM_SET_LAPIC, &lapic); + + vcpu_ioctl(vcpu, KVM_GET_LAPIC, &lapic); + TEST_ASSERT(*((u32 *)&lapic.regs[APIC_ID]) == vcpu->id << 24, + "x2APIC ID should be fully readonly"); + } + + kvm_vm_free(vm); +} + int main(int argc, char *argv[]) { struct xapic_vcpu x = { @@ -211,4 +238,5 @@ int main(int argc, char *argv[]) kvm_vm_free(vm); test_apic_id(); + test_x2apic_id(); } diff --git a/tools/testing/selftests/mm/Makefile b/tools/testing/selftests/mm/Makefile index 901e0d07765b6f..cfad627e8d94de 100644 --- a/tools/testing/selftests/mm/Makefile +++ b/tools/testing/selftests/mm/Makefile @@ -53,7 +53,9 @@ TEST_GEN_FILES += madv_populate TEST_GEN_FILES += map_fixed_noreplace TEST_GEN_FILES += map_hugetlb TEST_GEN_FILES += map_populate +ifneq (,$(filter $(ARCH),arm64 riscv riscv64 x86 x86_64)) TEST_GEN_FILES += memfd_secret +endif TEST_GEN_FILES += migration TEST_GEN_FILES += mkdirty TEST_GEN_FILES += mlock-random-test @@ -110,7 +112,7 @@ endif endif -ifneq (,$(filter $(ARCH),arm64 ia64 mips64 parisc64 powerpc riscv64 s390x sparc64 x86_64)) +ifneq (,$(filter $(ARCH),arm64 ia64 mips64 parisc64 powerpc riscv64 s390x sparc64 x86_64 s390)) TEST_GEN_FILES += va_high_addr_switch TEST_GEN_FILES += virtual_address_range TEST_GEN_FILES += write_to_hugetlbfs diff --git a/tools/testing/selftests/mm/compaction_test.c b/tools/testing/selftests/mm/compaction_test.c index e140558e6f53f8..2c3a0eb6b22d31 100644 --- a/tools/testing/selftests/mm/compaction_test.c +++ b/tools/testing/selftests/mm/compaction_test.c @@ -89,9 +89,10 @@ int check_compaction(unsigned long mem_free, unsigned long hugepage_size, int fd, ret = -1; int compaction_index = 0; char nr_hugepages[20] = {0}; - char init_nr_hugepages[20] = {0}; + char init_nr_hugepages[24] = {0}; - sprintf(init_nr_hugepages, "%lu", initial_nr_hugepages); + snprintf(init_nr_hugepages, sizeof(init_nr_hugepages), + "%lu", initial_nr_hugepages); /* We want to test with 80% of available memory. Else, OOM killer comes in to play */ diff --git a/tools/testing/selftests/mm/mremap_test.c b/tools/testing/selftests/mm/mremap_test.c index 1b03bcfaefdfa2..5a3a9bcba64048 100644 --- a/tools/testing/selftests/mm/mremap_test.c +++ b/tools/testing/selftests/mm/mremap_test.c @@ -22,8 +22,10 @@ #define VALIDATION_DEFAULT_THRESHOLD 4 /* 4MB */ #define VALIDATION_NO_THRESHOLD 0 /* Verify the entire region */ +#ifndef MIN #define MIN(X, Y) ((X) < (Y) ? (X) : (Y)) #define MAX(X, Y) ((X) > (Y) ? (X) : (Y)) +#endif #define SIZE_MB(m) ((size_t)m * (1024 * 1024)) #define SIZE_KB(k) ((size_t)k * 1024) diff --git a/tools/testing/selftests/mm/run_vmtests.sh b/tools/testing/selftests/mm/run_vmtests.sh index 03ac4f2e1cce65..36045edb10dea0 100755 --- a/tools/testing/selftests/mm/run_vmtests.sh +++ b/tools/testing/selftests/mm/run_vmtests.sh @@ -374,8 +374,11 @@ CATEGORY="hmm" run_test bash ./test_hmm.sh smoke # MADV_POPULATE_READ and MADV_POPULATE_WRITE tests CATEGORY="madv_populate" run_test ./madv_populate +if [ -x ./memfd_secret ] +then (echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope 2>&1) | tap_prefix CATEGORY="memfd_secret" run_test ./memfd_secret +fi # KSM KSM_MERGE_TIME_HUGE_PAGES test with size of 100 CATEGORY="ksm" run_test ./ksm_tests -H -s 100 diff --git a/tools/testing/selftests/net/af_unix/msg_oob.c b/tools/testing/selftests/net/af_unix/msg_oob.c index 16d0c172eaebec..535eb2c3d7d1c8 100644 --- a/tools/testing/selftests/net/af_unix/msg_oob.c +++ b/tools/testing/selftests/net/af_unix/msg_oob.c @@ -209,7 +209,7 @@ static void __sendpair(struct __test_metadata *_metadata, static void __recvpair(struct __test_metadata *_metadata, FIXTURE_DATA(msg_oob) *self, - const void *expected_buf, int expected_len, + const char *expected_buf, int expected_len, int buf_len, int flags) { int i, ret[2], recv_errno[2], expected_errno = 0; diff --git a/tools/testing/selftests/net/lib.sh b/tools/testing/selftests/net/lib.sh index d0219032f77300..8ee4489238ca4b 100644 --- a/tools/testing/selftests/net/lib.sh +++ b/tools/testing/selftests/net/lib.sh @@ -146,6 +146,7 @@ cleanup_ns() for ns in "$@"; do [ -z "${ns}" ] && continue + ip netns pids "${ns}" 2> /dev/null | xargs -r kill || true ip netns delete "${ns}" &> /dev/null || true if ! busywait $BUSYWAIT_TIMEOUT ip netns list \| grep -vq "^$ns$" &> /dev/null; then echo "Warn: Failed to remove namespace $ns" diff --git a/tools/testing/selftests/net/mptcp/mptcp_connect.c b/tools/testing/selftests/net/mptcp/mptcp_connect.c index d2043ec3bf6d69..4209b95690394b 100644 --- a/tools/testing/selftests/net/mptcp/mptcp_connect.c +++ b/tools/testing/selftests/net/mptcp/mptcp_connect.c @@ -1115,11 +1115,11 @@ int main_loop_s(int listensock) return 1; } - if (--cfg_repeat > 0) { - if (cfg_input) - close(fd); + if (cfg_input) + close(fd); + + if (--cfg_repeat > 0) goto again; - } return 0; } diff --git a/tools/testing/selftests/net/mptcp/mptcp_join.sh b/tools/testing/selftests/net/mptcp/mptcp_join.sh index 108aeeb84ef10a..9ea6d698e9d382 100755 --- a/tools/testing/selftests/net/mptcp/mptcp_join.sh +++ b/tools/testing/selftests/net/mptcp/mptcp_join.sh @@ -661,7 +661,7 @@ pm_nl_check_endpoint() done if [ -z "${id}" ]; then - test_fail "bad test - missing endpoint id" + fail_test "bad test - missing endpoint id" return fi @@ -1415,18 +1415,28 @@ chk_add_nr() local add_nr=$1 local echo_nr=$2 local port_nr=${3:-0} - local syn_nr=${4:-$port_nr} - local syn_ack_nr=${5:-$port_nr} - local ack_nr=${6:-$port_nr} - local mis_syn_nr=${7:-0} - local mis_ack_nr=${8:-0} + local ns_invert=${4:-""} + local syn_nr=$port_nr + local syn_ack_nr=$port_nr + local ack_nr=$port_nr + local mis_syn_nr=0 + local mis_ack_nr=0 + local ns_tx=$ns1 + local ns_rx=$ns2 + local extra_msg="" local count local timeout - timeout=$(ip netns exec $ns1 sysctl -n net.mptcp.add_addr_timeout) + if [[ $ns_invert = "invert" ]]; then + ns_tx=$ns2 + ns_rx=$ns1 + extra_msg="invert" + fi + + timeout=$(ip netns exec ${ns_tx} sysctl -n net.mptcp.add_addr_timeout) print_check "add" - count=$(mptcp_lib_get_counter ${ns2} "MPTcpExtAddAddr") + count=$(mptcp_lib_get_counter ${ns_rx} "MPTcpExtAddAddr") if [ -z "$count" ]; then print_skip # if the test configured a short timeout tolerate greater then expected @@ -1438,7 +1448,7 @@ chk_add_nr() fi print_check "echo" - count=$(mptcp_lib_get_counter ${ns1} "MPTcpExtEchoAdd") + count=$(mptcp_lib_get_counter ${ns_tx} "MPTcpExtEchoAdd") if [ -z "$count" ]; then print_skip elif [ "$count" != "$echo_nr" ]; then @@ -1449,7 +1459,7 @@ chk_add_nr() if [ $port_nr -gt 0 ]; then print_check "pt" - count=$(mptcp_lib_get_counter ${ns2} "MPTcpExtPortAdd") + count=$(mptcp_lib_get_counter ${ns_rx} "MPTcpExtPortAdd") if [ -z "$count" ]; then print_skip elif [ "$count" != "$port_nr" ]; then @@ -1459,7 +1469,7 @@ chk_add_nr() fi print_check "syn" - count=$(mptcp_lib_get_counter ${ns1} "MPTcpExtMPJoinPortSynRx") + count=$(mptcp_lib_get_counter ${ns_tx} "MPTcpExtMPJoinPortSynRx") if [ -z "$count" ]; then print_skip elif [ "$count" != "$syn_nr" ]; then @@ -1470,7 +1480,7 @@ chk_add_nr() fi print_check "synack" - count=$(mptcp_lib_get_counter ${ns2} "MPTcpExtMPJoinPortSynAckRx") + count=$(mptcp_lib_get_counter ${ns_rx} "MPTcpExtMPJoinPortSynAckRx") if [ -z "$count" ]; then print_skip elif [ "$count" != "$syn_ack_nr" ]; then @@ -1481,7 +1491,7 @@ chk_add_nr() fi print_check "ack" - count=$(mptcp_lib_get_counter ${ns1} "MPTcpExtMPJoinPortAckRx") + count=$(mptcp_lib_get_counter ${ns_tx} "MPTcpExtMPJoinPortAckRx") if [ -z "$count" ]; then print_skip elif [ "$count" != "$ack_nr" ]; then @@ -1492,7 +1502,7 @@ chk_add_nr() fi print_check "syn" - count=$(mptcp_lib_get_counter ${ns1} "MPTcpExtMismatchPortSynRx") + count=$(mptcp_lib_get_counter ${ns_tx} "MPTcpExtMismatchPortSynRx") if [ -z "$count" ]; then print_skip elif [ "$count" != "$mis_syn_nr" ]; then @@ -1503,7 +1513,7 @@ chk_add_nr() fi print_check "ack" - count=$(mptcp_lib_get_counter ${ns1} "MPTcpExtMismatchPortAckRx") + count=$(mptcp_lib_get_counter ${ns_tx} "MPTcpExtMismatchPortAckRx") if [ -z "$count" ]; then print_skip elif [ "$count" != "$mis_ack_nr" ]; then @@ -1513,6 +1523,8 @@ chk_add_nr() print_ok fi fi + + print_info "$extra_msg" } chk_add_tx_nr() @@ -1634,6 +1646,8 @@ chk_prio_nr() { local mp_prio_nr_tx=$1 local mp_prio_nr_rx=$2 + local mpj_syn=$3 + local mpj_syn_ack=$4 local count print_check "ptx" @@ -1655,6 +1669,26 @@ chk_prio_nr() else print_ok fi + + print_check "syn backup" + count=$(mptcp_lib_get_counter ${ns1} "MPTcpExtMPJoinSynBackupRx") + if [ -z "$count" ]; then + print_skip + elif [ "$count" != "$mpj_syn" ]; then + fail_test "got $count JOIN[s] syn with Backup expected $mpj_syn" + else + print_ok + fi + + print_check "synack backup" + count=$(mptcp_lib_get_counter ${ns2} "MPTcpExtMPJoinSynAckBackupRx") + if [ -z "$count" ]; then + print_skip + elif [ "$count" != "$mpj_syn_ack" ]; then + fail_test "got $count JOIN[s] synack with Backup expected $mpj_syn_ack" + else + print_ok + fi } chk_subflow_nr() @@ -1955,6 +1989,21 @@ signal_address_tests() chk_add_nr 1 1 fi + # uncommon: subflow and signal flags on the same endpoint + # or because the user wrongly picked both, but still expects the client + # to create additional subflows + if reset "subflow and signal together"; then + pm_nl_set_limits $ns1 0 2 + pm_nl_set_limits $ns2 0 2 + pm_nl_add_endpoint $ns2 10.0.3.2 flags signal,subflow + run_tests $ns1 $ns2 10.0.1.1 + chk_join_nr 1 1 1 + chk_add_nr 1 1 0 invert # only initiated by ns2 + chk_add_nr 0 0 0 # none initiated by ns1 + chk_rst_nr 0 0 invert # no RST sent by the client + chk_rst_nr 0 0 # no RST sent by the server + fi + # accept and use add_addr with additional subflows if reset "multiple subflows and signal"; then pm_nl_set_limits $ns1 0 3 @@ -2612,11 +2661,24 @@ backup_tests() sflags=nobackup speed=slow \ run_tests $ns1 $ns2 10.0.1.1 chk_join_nr 1 1 1 - chk_prio_nr 0 1 + chk_prio_nr 0 1 1 0 fi # single address, backup if reset "single address, backup" && + continue_if mptcp_lib_kallsyms_has "subflow_rebuild_header$"; then + pm_nl_set_limits $ns1 0 1 + pm_nl_add_endpoint $ns1 10.0.2.1 flags signal,backup + pm_nl_set_limits $ns2 1 1 + sflags=nobackup speed=slow \ + run_tests $ns1 $ns2 10.0.1.1 + chk_join_nr 1 1 1 + chk_add_nr 1 1 + chk_prio_nr 1 0 0 1 + fi + + # single address, switch to backup + if reset "single address, switch to backup" && continue_if mptcp_lib_kallsyms_has "subflow_rebuild_header$"; then pm_nl_set_limits $ns1 0 1 pm_nl_add_endpoint $ns1 10.0.2.1 flags signal @@ -2625,20 +2687,20 @@ backup_tests() run_tests $ns1 $ns2 10.0.1.1 chk_join_nr 1 1 1 chk_add_nr 1 1 - chk_prio_nr 1 1 + chk_prio_nr 1 1 0 0 fi # single address with port, backup if reset "single address with port, backup" && continue_if mptcp_lib_kallsyms_has "subflow_rebuild_header$"; then pm_nl_set_limits $ns1 0 1 - pm_nl_add_endpoint $ns1 10.0.2.1 flags signal port 10100 + pm_nl_add_endpoint $ns1 10.0.2.1 flags signal,backup port 10100 pm_nl_set_limits $ns2 1 1 - sflags=backup speed=slow \ + sflags=nobackup speed=slow \ run_tests $ns1 $ns2 10.0.1.1 chk_join_nr 1 1 1 chk_add_nr 1 1 - chk_prio_nr 1 1 + chk_prio_nr 1 0 0 1 fi if reset "mpc backup" && @@ -2647,17 +2709,26 @@ backup_tests() speed=slow \ run_tests $ns1 $ns2 10.0.1.1 chk_join_nr 0 0 0 - chk_prio_nr 0 1 + chk_prio_nr 0 1 0 0 fi if reset "mpc backup both sides" && continue_if mptcp_lib_kallsyms_doesnt_have "T mptcp_subflow_send_ack$"; then - pm_nl_add_endpoint $ns1 10.0.1.1 flags subflow,backup + pm_nl_set_limits $ns1 0 2 + pm_nl_set_limits $ns2 1 2 + pm_nl_add_endpoint $ns1 10.0.1.1 flags signal,backup pm_nl_add_endpoint $ns2 10.0.1.2 flags subflow,backup + + # 10.0.2.2 (non-backup) -> 10.0.1.1 (backup) + pm_nl_add_endpoint $ns2 10.0.2.2 flags subflow + # 10.0.1.2 (backup) -> 10.0.2.1 (non-backup) + pm_nl_add_endpoint $ns1 10.0.2.1 flags signal + ip -net "$ns2" route add 10.0.2.1 via 10.0.1.1 dev ns2eth1 # force this path + speed=slow \ run_tests $ns1 $ns2 10.0.1.1 - chk_join_nr 0 0 0 - chk_prio_nr 1 1 + chk_join_nr 2 2 2 + chk_prio_nr 1 1 1 1 fi if reset "mpc switch to backup" && @@ -2666,7 +2737,7 @@ backup_tests() sflags=backup speed=slow \ run_tests $ns1 $ns2 10.0.1.1 chk_join_nr 0 0 0 - chk_prio_nr 0 1 + chk_prio_nr 0 1 0 0 fi if reset "mpc switch to backup both sides" && @@ -2676,7 +2747,7 @@ backup_tests() sflags=backup speed=slow \ run_tests $ns1 $ns2 10.0.1.1 chk_join_nr 0 0 0 - chk_prio_nr 1 1 + chk_prio_nr 1 1 0 0 fi } @@ -3053,7 +3124,7 @@ fullmesh_tests() addr_nr_ns2=1 sflags=backup,fullmesh speed=slow \ run_tests $ns1 $ns2 10.0.1.1 chk_join_nr 2 2 2 - chk_prio_nr 0 1 + chk_prio_nr 0 1 1 0 chk_rm_nr 0 1 fi @@ -3066,7 +3137,7 @@ fullmesh_tests() sflags=nobackup,nofullmesh speed=slow \ run_tests $ns1 $ns2 10.0.1.1 chk_join_nr 2 2 2 - chk_prio_nr 0 1 + chk_prio_nr 0 1 1 0 chk_rm_nr 0 1 fi } @@ -3318,7 +3389,7 @@ userspace_tests() sflags=backup speed=slow \ run_tests $ns1 $ns2 10.0.1.1 chk_join_nr 1 1 0 - chk_prio_nr 0 0 + chk_prio_nr 0 0 0 0 fi # userspace pm type prevents rm_addr @@ -3526,6 +3597,35 @@ endpoint_tests() chk_mptcp_info subflows 1 subflows 1 mptcp_lib_kill_wait $tests_pid fi + + # remove and re-add + if reset "delete re-add signal" && + mptcp_lib_kallsyms_has "subflow_rebuild_header$"; then + pm_nl_set_limits $ns1 1 1 + pm_nl_set_limits $ns2 1 1 + pm_nl_add_endpoint $ns1 10.0.2.1 id 1 flags signal + test_linkfail=4 speed=20 \ + run_tests $ns1 $ns2 10.0.1.1 & + local tests_pid=$! + + wait_mpj $ns2 + pm_nl_check_endpoint "creation" \ + $ns1 10.0.2.1 id 1 flags signal + chk_subflow_nr "before delete" 2 + chk_mptcp_info subflows 1 subflows 1 + + pm_nl_del_endpoint $ns1 1 10.0.2.1 + sleep 0.5 + chk_subflow_nr "after delete" 1 + chk_mptcp_info subflows 0 subflows 0 + + pm_nl_add_endpoint $ns1 10.0.2.1 flags signal + wait_mpj $ns2 + chk_subflow_nr "after re-add" 2 + chk_mptcp_info subflows 1 subflows 1 + mptcp_lib_kill_wait $tests_pid + fi + } # [$1: error message] diff --git a/tools/testing/selftests/net/netfilter/Makefile b/tools/testing/selftests/net/netfilter/Makefile index 47945b2b3f9258..d13fb5ea3e8942 100644 --- a/tools/testing/selftests/net/netfilter/Makefile +++ b/tools/testing/selftests/net/netfilter/Makefile @@ -7,6 +7,7 @@ MNL_CFLAGS := $(shell $(HOSTPKG_CONFIG) --cflags libmnl 2>/dev/null) MNL_LDLIBS := $(shell $(HOSTPKG_CONFIG) --libs libmnl 2>/dev/null || echo -lmnl) TEST_PROGS := br_netfilter.sh bridge_brouter.sh +TEST_PROGS += br_netfilter_queue.sh TEST_PROGS += conntrack_icmp_related.sh TEST_PROGS += conntrack_ipip_mtu.sh TEST_PROGS += conntrack_tcp_unreplied.sh diff --git a/tools/testing/selftests/net/netfilter/br_netfilter_queue.sh b/tools/testing/selftests/net/netfilter/br_netfilter_queue.sh new file mode 100755 index 00000000000000..6a764d70ab06f9 --- /dev/null +++ b/tools/testing/selftests/net/netfilter/br_netfilter_queue.sh @@ -0,0 +1,78 @@ +#!/bin/bash + +source lib.sh + +checktool "nft --version" "run test without nft tool" + +cleanup() { + cleanup_all_ns +} + +setup_ns c1 c2 c3 sender + +trap cleanup EXIT + +nf_queue_wait() +{ + grep -q "^ *$1 " "/proc/self/net/netfilter/nfnetlink_queue" +} + +port_add() { + ns="$1" + dev="$2" + a="$3" + + ip link add name "$dev" type veth peer name "$dev" netns "$ns" + + ip -net "$ns" addr add 192.168.1."$a"/24 dev "$dev" + ip -net "$ns" link set "$dev" up + + ip link set "$dev" master br0 + ip link set "$dev" up +} + +[ "${1}" != "run" ] && { unshare -n "${0}" run; exit $?; } + +ip link add br0 type bridge +ip addr add 192.168.1.254/24 dev br0 + +port_add "$c1" "c1" 1 +port_add "$c2" "c2" 2 +port_add "$c3" "c3" 3 +port_add "$sender" "sender" 253 + +ip link set br0 up + +modprobe -q br_netfilter + +sysctl net.bridge.bridge-nf-call-iptables=1 || exit 1 + +ip netns exec "$sender" ping -I sender -c1 192.168.1.1 || exit 1 +ip netns exec "$sender" ping -I sender -c1 192.168.1.2 || exit 2 +ip netns exec "$sender" ping -I sender -c1 192.168.1.3 || exit 3 + +nft -f /dev/stdin < /dev/null & + +busywait 5000 nf_queue_wait + +for i in $(seq 1 5); do conntrack -F > /dev/null 2> /dev/null; sleep 0.1 ; done & +ip netns exec "$sender" ping -I sender -f -c 50 -b 192.168.1.255 + +read t < /proc/sys/kernel/tainted +if [ "$t" -eq 0 ];then + echo PASS: kernel not tainted +else + echo ERROR: kernel is tainted + exit 1 +fi + +exit 0 diff --git a/tools/testing/selftests/net/udpgso.c b/tools/testing/selftests/net/udpgso.c index 3e74cfa1a2bfec..3f2fca02fec53f 100644 --- a/tools/testing/selftests/net/udpgso.c +++ b/tools/testing/selftests/net/udpgso.c @@ -67,6 +67,7 @@ struct testcase { int gso_len; /* mss after applying gso */ int r_num_mss; /* recv(): number of calls of full mss */ int r_len_last; /* recv(): size of last non-mss dgram, if any */ + bool v6_ext_hdr; /* send() dgrams with IPv6 extension headers */ }; const struct in6_addr addr6 = { @@ -77,6 +78,8 @@ const struct in_addr addr4 = { __constant_htonl(0x0a000001), /* 10.0.0.1 */ }; +static const char ipv6_hopopts_pad1[8] = { 0 }; + struct testcase testcases_v4[] = { { /* no GSO: send a single byte */ @@ -255,6 +258,13 @@ struct testcase testcases_v6[] = { .gso_len = 1, .r_num_mss = 2, }, + { + /* send 2 1B segments with extension headers */ + .tlen = 2, + .gso_len = 1, + .r_num_mss = 2, + .v6_ext_hdr = true, + }, { /* send 2B + 2B + 1B segments */ .tlen = 5, @@ -396,11 +406,18 @@ static void run_one(struct testcase *test, int fdt, int fdr, int i, ret, val, mss; bool sent; - fprintf(stderr, "ipv%d tx:%d gso:%d %s\n", + fprintf(stderr, "ipv%d tx:%d gso:%d %s%s\n", addr->sa_family == AF_INET ? 4 : 6, test->tlen, test->gso_len, + test->v6_ext_hdr ? "ext-hdr " : "", test->tfail ? "(fail)" : ""); + if (test->v6_ext_hdr) { + if (setsockopt(fdt, IPPROTO_IPV6, IPV6_HOPOPTS, + ipv6_hopopts_pad1, sizeof(ipv6_hopopts_pad1))) + error(1, errno, "setsockopt ipv6 hopopts"); + } + val = test->gso_len; if (cfg_do_setsockopt) { if (setsockopt(fdt, SOL_UDP, UDP_SEGMENT, &val, sizeof(val))) @@ -412,6 +429,12 @@ static void run_one(struct testcase *test, int fdt, int fdr, error(1, 0, "send succeeded while expecting failure"); if (!sent && !test->tfail) error(1, 0, "send failed while expecting success"); + + if (test->v6_ext_hdr) { + if (setsockopt(fdt, IPPROTO_IPV6, IPV6_HOPOPTS, NULL, 0)) + error(1, errno, "setsockopt ipv6 hopopts clear"); + } + if (!sent) return; diff --git a/tools/testing/selftests/seccomp/seccomp_bpf.c b/tools/testing/selftests/seccomp/seccomp_bpf.c index e3f97f90d8db0f..8c3a73461475ba 100644 --- a/tools/testing/selftests/seccomp/seccomp_bpf.c +++ b/tools/testing/selftests/seccomp/seccomp_bpf.c @@ -60,7 +60,9 @@ #define SKIP(s, ...) XFAIL(s, ##__VA_ARGS__) #endif +#ifndef MIN #define MIN(X, Y) ((X) < (Y) ? (X) : (Y)) +#endif #ifndef PR_SET_PTRACER # define PR_SET_PTRACER 0x59616d61 diff --git a/tools/tracing/rtla/src/osnoise_top.c b/tools/tracing/rtla/src/osnoise_top.c index f594a44df840e4..2f756628613dd8 100644 --- a/tools/tracing/rtla/src/osnoise_top.c +++ b/tools/tracing/rtla/src/osnoise_top.c @@ -651,8 +651,10 @@ struct osnoise_tool *osnoise_init_top(struct osnoise_top_params *params) return NULL; tool->data = osnoise_alloc_top(nr_cpus); - if (!tool->data) - goto out_err; + if (!tool->data) { + osnoise_destroy_tool(tool); + return NULL; + } tool->params = params; @@ -660,11 +662,6 @@ struct osnoise_tool *osnoise_init_top(struct osnoise_top_params *params) osnoise_top_handler, NULL); return tool; - -out_err: - osnoise_free_top(tool->data); - osnoise_destroy_tool(tool); - return NULL; } static int stop_tracing; diff --git a/virt/kvm/Kconfig b/virt/kvm/Kconfig index b14e14cdbfb9fd..fd6a3010afa833 100644 --- a/virt/kvm/Kconfig +++ b/virt/kvm/Kconfig @@ -113,10 +113,10 @@ config KVM_GENERIC_PRIVATE_MEM select KVM_PRIVATE_MEM bool -config HAVE_KVM_GMEM_PREPARE +config HAVE_KVM_ARCH_GMEM_PREPARE bool depends on KVM_PRIVATE_MEM -config HAVE_KVM_GMEM_INVALIDATE +config HAVE_KVM_ARCH_GMEM_INVALIDATE bool depends on KVM_PRIVATE_MEM diff --git a/virt/kvm/eventfd.c b/virt/kvm/eventfd.c index 229570059a1bb5..992f9beb3e7d04 100644 --- a/virt/kvm/eventfd.c +++ b/virt/kvm/eventfd.c @@ -97,18 +97,19 @@ irqfd_resampler_shutdown(struct kvm_kernel_irqfd *irqfd) mutex_lock(&kvm->irqfds.resampler_lock); list_del_rcu(&irqfd->resampler_link); - synchronize_srcu(&kvm->irq_srcu); if (list_empty(&resampler->list)) { list_del_rcu(&resampler->link); kvm_unregister_irq_ack_notifier(kvm, &resampler->notifier); /* - * synchronize_srcu(&kvm->irq_srcu) already called + * synchronize_srcu_expedited(&kvm->irq_srcu) already called * in kvm_unregister_irq_ack_notifier(). */ kvm_set_irq(kvm, KVM_IRQFD_RESAMPLE_IRQ_SOURCE_ID, resampler->notifier.gsi, 0, false); kfree(resampler); + } else { + synchronize_srcu_expedited(&kvm->irq_srcu); } mutex_unlock(&kvm->irqfds.resampler_lock); @@ -126,7 +127,7 @@ irqfd_shutdown(struct work_struct *work) u64 cnt; /* Make sure irqfd has been initialized in assign path. */ - synchronize_srcu(&kvm->irq_srcu); + synchronize_srcu_expedited(&kvm->irq_srcu); /* * Synchronize with the wait-queue and unhook ourselves to prevent @@ -384,7 +385,7 @@ kvm_irqfd_assign(struct kvm *kvm, struct kvm_irqfd *args) } list_add_rcu(&irqfd->resampler_link, &irqfd->resampler->list); - synchronize_srcu(&kvm->irq_srcu); + synchronize_srcu_expedited(&kvm->irq_srcu); mutex_unlock(&kvm->irqfds.resampler_lock); } @@ -523,7 +524,7 @@ void kvm_unregister_irq_ack_notifier(struct kvm *kvm, mutex_lock(&kvm->irq_lock); hlist_del_init_rcu(&kian->link); mutex_unlock(&kvm->irq_lock); - synchronize_srcu(&kvm->irq_srcu); + synchronize_srcu_expedited(&kvm->irq_srcu); kvm_arch_post_irq_ack_notifier_list_update(kvm); } @@ -608,7 +609,7 @@ kvm_irqfd_release(struct kvm *kvm) /* * Take note of a change in irq routing. - * Caller must invoke synchronize_srcu(&kvm->irq_srcu) afterwards. + * Caller must invoke synchronize_srcu_expedited(&kvm->irq_srcu) afterwards. */ void kvm_irq_routing_update(struct kvm *kvm) { diff --git a/virt/kvm/guest_memfd.c b/virt/kvm/guest_memfd.c index 1c509c35126146..8f079a61a56db7 100644 --- a/virt/kvm/guest_memfd.c +++ b/virt/kvm/guest_memfd.c @@ -13,84 +13,93 @@ struct kvm_gmem { struct list_head entry; }; -static int kvm_gmem_prepare_folio(struct inode *inode, pgoff_t index, struct folio *folio) +/** + * folio_file_pfn - like folio_file_page, but return a pfn. + * @folio: The folio which contains this index. + * @index: The index we want to look up. + * + * Return: The pfn for this index. + */ +static inline kvm_pfn_t folio_file_pfn(struct folio *folio, pgoff_t index) { -#ifdef CONFIG_HAVE_KVM_GMEM_PREPARE - struct list_head *gmem_list = &inode->i_mapping->i_private_list; - struct kvm_gmem *gmem; + return folio_pfn(folio) + (index & (folio_nr_pages(folio) - 1)); +} - list_for_each_entry(gmem, gmem_list, entry) { - struct kvm_memory_slot *slot; - struct kvm *kvm = gmem->kvm; - struct page *page; - kvm_pfn_t pfn; - gfn_t gfn; - int rc; - - if (!kvm_arch_gmem_prepare_needed(kvm)) - continue; - - slot = xa_load(&gmem->bindings, index); - if (!slot) - continue; - - page = folio_file_page(folio, index); - pfn = page_to_pfn(page); - gfn = slot->base_gfn + index - slot->gmem.pgoff; - rc = kvm_arch_gmem_prepare(kvm, gfn, pfn, compound_order(compound_head(page))); - if (rc) { - pr_warn_ratelimited("gmem: Failed to prepare folio for index %lx GFN %llx PFN %llx error %d.\n", - index, gfn, pfn, rc); - return rc; - } +static int __kvm_gmem_prepare_folio(struct kvm *kvm, struct kvm_memory_slot *slot, + pgoff_t index, struct folio *folio) +{ +#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_PREPARE + kvm_pfn_t pfn = folio_file_pfn(folio, index); + gfn_t gfn = slot->base_gfn + index - slot->gmem.pgoff; + int rc = kvm_arch_gmem_prepare(kvm, gfn, pfn, folio_order(folio)); + if (rc) { + pr_warn_ratelimited("gmem: Failed to prepare folio for index %lx GFN %llx PFN %llx error %d.\n", + index, gfn, pfn, rc); + return rc; } - #endif + return 0; } -static struct folio *kvm_gmem_get_folio(struct inode *inode, pgoff_t index, bool prepare) +static inline void kvm_gmem_mark_prepared(struct folio *folio) { - struct folio *folio; + folio_mark_uptodate(folio); +} - /* TODO: Support huge pages. */ - folio = filemap_grab_folio(inode->i_mapping, index); - if (IS_ERR(folio)) - return folio; +/* + * Process @folio, which contains @gfn, so that the guest can use it. + * The folio must be locked and the gfn must be contained in @slot. + * On successful return the guest sees a zero page so as to avoid + * leaking host data and the up-to-date flag is set. + */ +static int kvm_gmem_prepare_folio(struct kvm *kvm, struct kvm_memory_slot *slot, + gfn_t gfn, struct folio *folio) +{ + unsigned long nr_pages, i; + pgoff_t index; + int r; + + nr_pages = folio_nr_pages(folio); + for (i = 0; i < nr_pages; i++) + clear_highpage(folio_page(folio, i)); /* - * Use the up-to-date flag to track whether or not the memory has been - * zeroed before being handed off to the guest. There is no backing - * storage for the memory, so the folio will remain up-to-date until - * it's removed. + * Preparing huge folios should always be safe, since it should + * be possible to split them later if needed. * - * TODO: Skip clearing pages when trusted firmware will do it when - * assigning memory to the guest. + * Right now the folio order is always going to be zero, but the + * code is ready for huge folios. The only assumption is that + * the base pgoff of memslots is naturally aligned with the + * requested page order, ensuring that huge folios can also use + * huge page table entries for GPA->HPA mapping. + * + * The order will be passed when creating the guest_memfd, and + * checked when creating memslots. */ - if (!folio_test_uptodate(folio)) { - unsigned long nr_pages = folio_nr_pages(folio); - unsigned long i; - - for (i = 0; i < nr_pages; i++) - clear_highpage(folio_page(folio, i)); - - folio_mark_uptodate(folio); - } + WARN_ON(!IS_ALIGNED(slot->gmem.pgoff, 1 << folio_order(folio))); + index = gfn - slot->base_gfn + slot->gmem.pgoff; + index = ALIGN_DOWN(index, 1 << folio_order(folio)); + r = __kvm_gmem_prepare_folio(kvm, slot, index, folio); + if (!r) + kvm_gmem_mark_prepared(folio); - if (prepare) { - int r = kvm_gmem_prepare_folio(inode, index, folio); - if (r < 0) { - folio_unlock(folio); - folio_put(folio); - return ERR_PTR(r); - } - } + return r; +} - /* - * Ignore accessed, referenced, and dirty flags. The memory is - * unevictable and there is no storage to write back to. - */ - return folio; +/* + * Returns a locked folio on success. The caller is responsible for + * setting the up-to-date flag before the memory is mapped into the guest. + * There is no backing storage for the memory, so the folio will remain + * up-to-date until it's removed. + * + * Ignore accessed, referenced, and dirty flags. The memory is + * unevictable and there is no storage to write back to. + */ +static struct folio *kvm_gmem_get_folio(struct inode *inode, pgoff_t index) +{ + /* TODO: Support huge pages. */ + return filemap_grab_folio(inode->i_mapping, index); } static void kvm_gmem_invalidate_begin(struct kvm_gmem *gmem, pgoff_t start, @@ -190,7 +199,7 @@ static long kvm_gmem_allocate(struct inode *inode, loff_t offset, loff_t len) break; } - folio = kvm_gmem_get_folio(inode, index, true); + folio = kvm_gmem_get_folio(inode, index); if (IS_ERR(folio)) { r = PTR_ERR(folio); break; @@ -343,7 +352,7 @@ static int kvm_gmem_error_folio(struct address_space *mapping, struct folio *fol return MF_DELAYED; } -#ifdef CONFIG_HAVE_KVM_GMEM_INVALIDATE +#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_INVALIDATE static void kvm_gmem_free_folio(struct folio *folio) { struct page *page = folio_page(folio, 0); @@ -358,7 +367,7 @@ static const struct address_space_operations kvm_gmem_aops = { .dirty_folio = noop_dirty_folio, .migrate_folio = kvm_gmem_migrate_folio, .error_remove_folio = kvm_gmem_error_folio, -#ifdef CONFIG_HAVE_KVM_GMEM_INVALIDATE +#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_INVALIDATE .free_folio = kvm_gmem_free_folio, #endif }; @@ -541,64 +550,76 @@ void kvm_gmem_unbind(struct kvm_memory_slot *slot) fput(file); } -static int __kvm_gmem_get_pfn(struct file *file, struct kvm_memory_slot *slot, - gfn_t gfn, kvm_pfn_t *pfn, int *max_order, bool prepare) +/* Returns a locked folio on success. */ +static struct folio * +__kvm_gmem_get_pfn(struct file *file, struct kvm_memory_slot *slot, + gfn_t gfn, kvm_pfn_t *pfn, bool *is_prepared, + int *max_order) { pgoff_t index = gfn - slot->base_gfn + slot->gmem.pgoff; struct kvm_gmem *gmem = file->private_data; struct folio *folio; - struct page *page; - int r; if (file != slot->gmem.file) { WARN_ON_ONCE(slot->gmem.file); - return -EFAULT; + return ERR_PTR(-EFAULT); } gmem = file->private_data; if (xa_load(&gmem->bindings, index) != slot) { WARN_ON_ONCE(xa_load(&gmem->bindings, index)); - return -EIO; + return ERR_PTR(-EIO); } - folio = kvm_gmem_get_folio(file_inode(file), index, prepare); + folio = kvm_gmem_get_folio(file_inode(file), index); if (IS_ERR(folio)) - return PTR_ERR(folio); + return folio; if (folio_test_hwpoison(folio)) { folio_unlock(folio); folio_put(folio); - return -EHWPOISON; + return ERR_PTR(-EHWPOISON); } - page = folio_file_page(folio, index); - - *pfn = page_to_pfn(page); + *pfn = folio_file_pfn(folio, index); if (max_order) *max_order = 0; - r = 0; - - folio_unlock(folio); - - return r; + *is_prepared = folio_test_uptodate(folio); + return folio; } int kvm_gmem_get_pfn(struct kvm *kvm, struct kvm_memory_slot *slot, gfn_t gfn, kvm_pfn_t *pfn, int *max_order) { struct file *file = kvm_gmem_get_file(slot); - int r; + struct folio *folio; + bool is_prepared = false; + int r = 0; if (!file) return -EFAULT; - r = __kvm_gmem_get_pfn(file, slot, gfn, pfn, max_order, true); + folio = __kvm_gmem_get_pfn(file, slot, gfn, pfn, &is_prepared, max_order); + if (IS_ERR(folio)) { + r = PTR_ERR(folio); + goto out; + } + + if (!is_prepared) + r = kvm_gmem_prepare_folio(kvm, slot, gfn, folio); + + folio_unlock(folio); + if (r < 0) + folio_put(folio); + +out: fput(file); return r; } EXPORT_SYMBOL_GPL(kvm_gmem_get_pfn); +#ifdef CONFIG_KVM_GENERIC_PRIVATE_MEM long kvm_gmem_populate(struct kvm *kvm, gfn_t start_gfn, void __user *src, long npages, kvm_gmem_populate_cb post_populate, void *opaque) { @@ -625,7 +646,9 @@ long kvm_gmem_populate(struct kvm *kvm, gfn_t start_gfn, void __user *src, long npages = min_t(ulong, slot->npages - (start_gfn - slot->base_gfn), npages); for (i = 0; i < npages; i += (1 << max_order)) { + struct folio *folio; gfn_t gfn = start_gfn + i; + bool is_prepared = false; kvm_pfn_t pfn; if (signal_pending(current)) { @@ -633,18 +656,39 @@ long kvm_gmem_populate(struct kvm *kvm, gfn_t start_gfn, void __user *src, long break; } - ret = __kvm_gmem_get_pfn(file, slot, gfn, &pfn, &max_order, false); - if (ret) + folio = __kvm_gmem_get_pfn(file, slot, gfn, &pfn, &is_prepared, &max_order); + if (IS_ERR(folio)) { + ret = PTR_ERR(folio); break; + } - if (!IS_ALIGNED(gfn, (1 << max_order)) || - (npages - i) < (1 << max_order)) - max_order = 0; + if (is_prepared) { + folio_unlock(folio); + folio_put(folio); + ret = -EEXIST; + break; + } + + folio_unlock(folio); + WARN_ON(!IS_ALIGNED(gfn, 1 << max_order) || + (npages - i) < (1 << max_order)); + + ret = -EINVAL; + while (!kvm_range_has_memory_attributes(kvm, gfn, gfn + (1 << max_order), + KVM_MEMORY_ATTRIBUTE_PRIVATE, + KVM_MEMORY_ATTRIBUTE_PRIVATE)) { + if (!max_order) + goto put_folio_and_exit; + max_order--; + } p = src ? src + i * PAGE_SIZE : NULL; ret = post_populate(kvm, gfn, pfn, p, max_order, opaque); + if (!ret) + kvm_gmem_mark_prepared(folio); - put_page(pfn_to_page(pfn)); +put_folio_and_exit: + folio_put(folio); if (ret) break; } @@ -655,3 +699,4 @@ long kvm_gmem_populate(struct kvm *kvm, gfn_t start_gfn, void __user *src, long return ret && !i ? ret : i; } EXPORT_SYMBOL_GPL(kvm_gmem_populate); +#endif diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index d0788d0a72cc09..cb2b78e92910fb 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -1578,15 +1578,14 @@ static int check_memory_region_flags(struct kvm *kvm, if (mem->flags & KVM_MEM_GUEST_MEMFD) valid_flags &= ~KVM_MEM_LOG_DIRTY_PAGES; -#ifdef CONFIG_HAVE_KVM_READONLY_MEM /* * GUEST_MEMFD is incompatible with read-only memslots, as writes to * read-only memslots have emulated MMIO, not page fault, semantics, * and KVM doesn't allow emulated MMIO for private memory. */ - if (!(mem->flags & KVM_MEM_GUEST_MEMFD)) + if (kvm_arch_has_readonly_mem(kvm) && + !(mem->flags & KVM_MEM_GUEST_MEMFD)) valid_flags |= KVM_MEM_READONLY; -#endif if (mem->flags & ~valid_flags) return -EINVAL; @@ -2398,48 +2397,47 @@ static int kvm_vm_ioctl_clear_dirty_log(struct kvm *kvm, #endif /* CONFIG_KVM_GENERIC_DIRTYLOG_READ_PROTECT */ #ifdef CONFIG_KVM_GENERIC_MEMORY_ATTRIBUTES +static u64 kvm_supported_mem_attributes(struct kvm *kvm) +{ + if (!kvm || kvm_arch_has_private_mem(kvm)) + return KVM_MEMORY_ATTRIBUTE_PRIVATE; + + return 0; +} + /* * Returns true if _all_ gfns in the range [@start, @end) have attributes - * matching @attrs. + * such that the bits in @mask match @attrs. */ bool kvm_range_has_memory_attributes(struct kvm *kvm, gfn_t start, gfn_t end, - unsigned long attrs) + unsigned long mask, unsigned long attrs) { XA_STATE(xas, &kvm->mem_attr_array, start); unsigned long index; - bool has_attrs; void *entry; - rcu_read_lock(); + mask &= kvm_supported_mem_attributes(kvm); + if (attrs & ~mask) + return false; - if (!attrs) { - has_attrs = !xas_find(&xas, end - 1); - goto out; - } + if (end == start + 1) + return (kvm_get_memory_attributes(kvm, start) & mask) == attrs; + + guard(rcu)(); + if (!attrs) + return !xas_find(&xas, end - 1); - has_attrs = true; for (index = start; index < end; index++) { do { entry = xas_next(&xas); } while (xas_retry(&xas, entry)); - if (xas.xa_index != index || xa_to_value(entry) != attrs) { - has_attrs = false; - break; - } + if (xas.xa_index != index || + (xa_to_value(entry) & mask) != attrs) + return false; } -out: - rcu_read_unlock(); - return has_attrs; -} - -static u64 kvm_supported_mem_attributes(struct kvm *kvm) -{ - if (!kvm || kvm_arch_has_private_mem(kvm)) - return KVM_MEMORY_ATTRIBUTE_PRIVATE; - - return 0; + return true; } static __always_inline void kvm_handle_gfn_range(struct kvm *kvm, @@ -2534,7 +2532,7 @@ static int kvm_vm_set_mem_attributes(struct kvm *kvm, gfn_t start, gfn_t end, mutex_lock(&kvm->slots_lock); /* Nothing to do if the entire range as the desired attributes. */ - if (kvm_range_has_memory_attributes(kvm, start, end, attributes)) + if (kvm_range_has_memory_attributes(kvm, start, end, ~0, attributes)) goto out_unlock; /*